[GWCTF 2019]re3 wp
阿新 • • 發佈:2021-12-21
[GWCTF 2019]re3
關鍵點:AES MD5 動態除錯 smc自解密 gdb使用
跟進main函式 發現一個典型smc異或自解密
可以用idc指令碼 或者python patch 或者動態除錯檢視邏輯
a = [0xCC,0xD1,0x10,0x7C,0xD1,0x18,0x75,0x69,0x99,0x99,0x99,0xD1,0x10,0x24,0x81,0x66,0x66,0x66,0xFD,0xD1,0x12,0x9D,0xBC,0xB1,0x99,0x99,0x99,0xD1,0x10,0xDC,0x61,0xA8,0x59,0xD1,0x14,0x1C,0xA9,0x66,0x66,0x66,0x27,0xE9,0xA8,0xF9,0x99,0xD1,0x10,0x5E,0x71,0xBA,0x71,0x66,0x66,0xD1,0x12,0x0C,0x81,0x66,0x66,0x66,0xD1,0x14,0x1C,0xA9,0x66,0x66,0x66,0xD1,0x10,0x4F,0xD1,0x10,0x5E,0x71,0x9E,0x6E,0x66,0x66,0xD1,0x12,0x1C,0x81,0x66,0x66,0x66,0xD1,0x14,0xC9,0x89,0xD1,0x14,0x1C,0xA9,0x66,0x66,0x66,0xD1,0x10,0x4F,0xD1,0x10,0x5E,0x71,0x73,0x6F,0x66,0x66,0x5E,0x1C,0xB1,0x66,0x66,0x66,0x98,0x99,0x99,0x99,0x5E,0x1C,0xB5,0x66,0x66,0x66,0x99,0x99,0x99,0x99,0x72,0xA3,0x12,0x1C,0xB5,0x66,0x66,0x66,0xD1,0xFA,0x49,0xD1,0x12,0x1C,0x81,0x66,0x66,0x66,0xD1,0x98,0x49,0x96,0x2F,0x89,0x12,0x1C,0xB5,0x66,0x66,0x66,0xD1,0x01,0x96,0x2F,0x19,0x39,0xA9,0xF9,0x99,0xA1,0x5B,0xED,0x93,0x5E,0x1C,0xB1,0x66,0x66,0x66,0x99,0x99,0x99,0x99,0x1A,0x1C,0xB5,0x66,0x66,0x66,0x98,0x1A,0x24,0xB5,0x66,0x66,0x66,0x86,0xE7,0x24,0x12,0x1C,0xB1,0x66,0x66,0x66,0xD1,0x12,0xD4,0x61,0xFD,0xD1,0xAA,0x95,0xBC,0xB1,0x99,0x99,0x99,0xED,0x9C,0x71,0xC0,0x7A,0x66,0x66,0x50,0x5A] for i in range(len(a)): a[i] ^= 0x99 with open(r'D:\sundry\attachment (1)','rb+') as f: for i in range(0x2219): x = f.read(1) for i in range(224): y = [] y.append(a[i]) f.write(bytes(y))
idc指令碼
#include <idc.idc>
static main()
{
auto addr = 0x402219;
auto i = 0;
for(i=0;i<224;i++)
{
PatchByte(addr+i,Byte(addr+i)^0x99);
}
}
都是網上抄的(
手動patch一下 得到如圖主邏輯
findcrypto外掛查一下 跟進到sub_40207B 函式
sub_401CF9明顯的md5函式
幾個經典MD5常數
經過多次動態除錯 發現sub_40207B返回值相同 拿到該返回值 可以ida遠端聯動linux除錯
在這裡我使用gdb來除錯
斷在該函式結束後一行 0x4021e9
然後檢視unk_603170的值 來拿到第一步加密結果
gdb檢視地址內容 x指令
接著分析sub_402219函式
很明顯 後半部分for迴圈是判斷flag是否正確 我們把byte_6030A0拿走 這就是加密後結果
根據findcrypto與對稱加密特徵
能看出是ECB方式的AES加密 金鑰就是我們剛才動態拿到的unk_603170的值
AES加密資料塊分組長度必須為128位元(16位元組),金鑰長度可以是128位元(16位元組)、192位元(24位元組)、256位元(32位元組)中的任意一個(如果資料塊及金鑰長度不足時,會補齊)
所以我們直接使用指令碼解密
import re from Cryptodome.Cipher import AES from binascii import b2a_hex print("a" * 32) enc = [0xBC, 0x0A, 0xAD, 0xC0, 0x14, 0x7C, 0x5E, 0xCC, 0xE0, 0xB1, 0x40, 0xBC, 0x9C, 0x51, 0xD5, 0x2B, 0x46, 0xB2, 0xB9, 0x43, 0x4D, 0xE5, 0x32, 0x4B, 0xAD, 0x7F, 0xB4, 0xB3, 0x9C, 0xDB, 0x4B, 0x5B] print(len(enc)) md5_ = [0xcb, 0x8d, 0x49, 0x35, 0x21, 0xb4, 0x7a, 0x4c, 0xc1, 0xae, 0x7e, 0x62, 0x22, 0x92, 0x66, 0xce, ] print(len(md5_)) mode = AES.MODE_ECB key = b'\xcb\x8d\x49\x35\x21\xb4\x7a\x4c\xc1\xae\x7e\x62\x22\x92\x66\xce' text = b'\xBC\x0A\xAD\xC0\x14\x7C\x5E\xCC\xE0\xB1\x40\xBC\x9C\x51\xD5\x2B\x46\xB2\xB9\x43\x4D\xE5\x32\x4B\xAD\x7F\xB4\xB3\x9C\xDB\x4B\x5B' cryptos = AES.new(key, mode) cipher_text = cryptos.decrypt(text) t = b2a_hex(cipher_text).decode() t = re.findall(".{2}", t) for x in t: print(chr(int(x, 16)), end="")
flag{924a9ab2163d390410d0a1f670}