我们通过交叉引用来到主函数
发现有一个函数既作为数据参与异或,又作为函数来引用
而且这个函数打不开
我们猜测异或完后,这个函数才是真正的函数
我们找到这段函数的地址402219,通过python改变这段数据
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))
再次用ida打开,函数就显示正常了
进入sub_40207B
unsigned __int64 __fastcall sub_40207B(__int64 a1)
{
char v2; // [rsp+10h] [rbp-50h]
__int64 v3; // [rsp+20h] [rbp-40h]
__int64 v4; // [rsp+30h] [rbp-30h]
__int64 v5; // [rsp+40h] [rbp-20h]
unsigned __int64 v6; // [rsp+58h] [rbp-8h]
v6 = __readfsqword(0x28u);
sub_401CF9(&unk_603120, 0x40uLL, (__int64)&v2);
sub_401CF9(&unk_603100, 0x14uLL, (__int64)&v3);
sub_401CF9(&unk_6030C0, 0x35uLL, (__int64)&v4);
sub_401CF9(dword_4025C0, 0x100uLL, (__int64)&v5);
sub_401CF9(&v2, 0x40uLL, a1);
return __readfsqword(0x28u) ^ v6;
}
其中sub_401CF9函数是md5运算
有明显的四个常量
v6 = 0x67452301;
v7 = 0xEFCDAB89;
v8 = 0x98BADCFE;
v9 = 0x10325476;
还有基本线性函数
F(X,Y,Z) = (X & Y) | ((~X) & Z);
G(X,Y,Z) = (X & Z) | (Y & (~Z));
H(X,Y,Z) = X ^ Y ^ Z;
I(X,Y,Z) = Y ^ (X | (~Z));
具体判断需要了解md5算法,建议学习
为了得到unk_603170可以动态调试
也可以写python
import hashlib
s1 = b'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
s2 = b'\x00\x00\x00\x00\x96\x30\x07\x77\x2C\x61\x0E\xEE\xBA\x51\x09\x99\x19\xC4\x6D\x07'
s3 = b'\x03\x05\x07\x0B\x0D\x11\x13\x17\x1D\x1F\x25\x29\x2B\x2F\x35\x3B\x3D\x43\x47\x49\x4F\x53\x59\x61\x65\x67\x6B\x6D\x71\x7F\x83\x89\x8B\x95\x97\x9D\xA3\xA7\xAD\xB3\xB5\xBF\xC1\xC5\xC7\xD3\xDF\xE3\xE5\xE9\xEF\xF1\xFB'
s4 = b'\x78\xA4\x6A\xD7\x56\xB7\xC7\xE8\xDB\x70\x20\x24\xEE\xCE\xBD\xC1\xAF\x0F\x7C\xF5\x2A\xC6\x87\x47\x13\x46\x30\xA8\x01\x95\x46\xFD\xD8\x98\x80\x69\xAF\xF7\x44\x8B\xB1\x5B\xFF\xFF\xBE\xD7\x5C\x89\x22\x11\x90\x6B\x93\x71\x98\xFD\x8E\x43\x79\xA6\x21\x08\xB4\x49\x62\x25\x1E\xF6\x40\xB3\x40\xC0\x51\x5A\x5E\x26\xAA\xC7\xB6\xE9\x5D\x10\x2F\xD6\x53\x14\x44\x02\x81\xE6\xA1\xD8\xC8\xFB\xD3\xE7\xE6\xCD\xE1\x21\xD6\x07\x37\xC3\x87\x0D\xD5\xF4\xED\x14\x5A\x45\x05\xE9\xE3\xA9\xF8\xA3\xEF\xFC\xD9\x02\x6F\x67\x8A\x4C\x2A\x8D\x42\x39\xFA\xFF\x81\xF6\x71\x87\x22\x61\x9D\x6D\x0C\x38\xE5\xFD\x44\xEA\xBE\xA4\xA9\xCF\xDE\x4B\x60\x4B\xBB\xF6\x70\xBC\xBF\xBE\xC6\x7E\x9B\x28\xFA\x27\xA1\xEA\x85\x30\xEF\xD4\x05\x1D\x88\x04\x39\xD0\xD4\xD9\xE5\x99\xDB\xE6\xF8\x7C\xA2\x1F\x65\x56\xAC\xC4\x44\x22\x29\xF4\x97\xFF\x2A\x43\xA7\x23\x94\xAB\x39\xA0\x93\xFC\xC3\x59\x5B\x65\x92\xCC\x0C\x8F\x7D\xF4\xEF\xFF\xD1\x5D\x84\x85\x4F\x7E\xA8\x6F\xE0\xE6\x2C\xFE\x14\x43\x01\xA3\xA1\x11\x08\x4E\x82\x7E\x53\xF7\x35\xF2\x3A\xBD\xBB\xD2\xD7\x2A\x91\xD3\x86\xEB'
s =''
a = [s1,s2,s3,s4]
for i in a:
md5 = hashlib.md5()
md5.update(i)
s += md5.hexdigest()
#以上步骤得到s,下面是我把它提取出来转化为二进制了
s = b'\x78\x45\xf7\xea\xde\x89\x33\x8a\xda\xbf\xef\x89\xbd\x6e\x9a\x5b\xe8\x4f\xed\xef\x50\x67\xcf\x85\xf5\xe4\x7f\x4f\x4b\x59\x47\xa3\xc8\x38\xba\xe0\x2e\x07\xae\x0c\x27\x6d\xfb\x2e\x53\x30\x04\xc8\x7a\xc5\xfb\xac\x91\x1f\x3b\x36\x78\x41\xf8\xdc\xec\xc9\xdb\x46'
md5 = hashlib.md5()
md5.update(s)
print(md5.hexdigest()
#得到cb8d493521b47a4cc1ae7e62229266ce
我们进入sub_402219
__int64 __fastcall sub_402219(__int64 a1)
{
unsigned int v2; // [rsp+18h] [rbp-D8h]
signed int i; // [rsp+1Ch] [rbp-D4h]
char v4; // [rsp+20h] [rbp-D0h]
unsigned __int64 v5; // [rsp+E8h] [rbp-8h]
v5 = __readfsqword(0x28u);
sub_400A71((__int64)&v4, (__int64)&unk_603170);// 密钥扩展
sub_40196E((__int64)&v4, a1);
sub_40196E((__int64)&v4, a1 + 16);
v2 = 1;
for ( i = 0; i <= 31; ++i )
{
if ( *(_BYTE *)(i + a1) != byte_6030A0[i] )
v2 = 0;
}
return v2;
}
进入sub_400A71会发现这是个AES算法的密钥扩展
sub_40196E就是通过密钥AES加密
具体识别建议学习AES
最后解密python
from Crypto.Cipher import AES
from binascii import b2a_hex, a2b_hex
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)
print(b2a_hex(cipher_text))
#得到b'666c61677b39323461396162323136336433393034313064306131663637307d'
最后在十六进制转ascii即可
了解到了
SMC自修改代码
idc脚本
Findcrypt插件
学习了
但也有一些不赞同的地方
有wp认为a1只与第10行14行代码有关
其实不然
我用*(v2+0x10)可以直接访问到v3 的数据
用*(v2+0x20)可以直接访问到v4的数据
所以在第十四行代码sub_401CF9(&v2, 0x40uLL, a1);中
传入a1的长度为0x40,实际上是传入了v2 + v3 + v4 + v5
所以a1 与 第11,12,13行都有关
这也是这些wp最后都免不了动态调试的原因了