MD5算法的识别

3/8/2017来源:ASP.NET技巧人气:2290

前言

如果程序中用到了md5算法, 又没有对抗, 用PEID.KryptoANALzer插件扫描算法时, 会指出MD5算法特征的位置. 扫描的是MD5Transform函数.

记录

扫描记录的格式: 算法名称 , RVA, VA 参考点

MD5 :: 00001393 :: 00401393 The reference is above.

MD5特征码的参考点不太准, 向上找1,2,行反汇编, 可以看到和源码中对应的特征码.

00401367 |. 8B4D 08 mov ecx, dWord ptr [ebp+8] 0040136A |. 0345 B8 add eax, dword ptr [ebp-48] 0040136D |. 8D8C01 78A46A>lea ecx, dword ptr [ecx+eax+D76AA478] 00401374 |. 8BC1 mov eax, ecx 00401376 |. C1E8 19 shr eax, 19 00401379 |. C1E1 07 shl ecx, 7 0040137C |. 0BC1 or eax, ecx 0040137E |. 03C7 add eax, edi 00401380 |. 8BC8 mov ecx, eax 00401382 |. 23D0 and edx, eax 00401384 |. F7D1 not ecx 00401386 |. 23CB and ecx, ebx 00401388 |. 0BCA or ecx, edx 0040138A |. 8B55 F8 mov edx, dword ptr [ebp-8] 0040138D |. 034D BC add ecx, dword ptr [ebp-44] 00401390 |. 8D940A 56B7C7>lea edx, dword ptr [edx+ecx+E8C7B756] static void MD5Transform (state, block) UINT4 state[4]; unsigned char block[64]; { UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16]; Decode (x, block, 64); /* Round 1 */ FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */ FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */

查找MD5Transform调用参考, 有2处, 所在函数为MD5Update

00401228 <MD5calcu.MD5Update> /$ 55 push ebp 00401229 |. 8BEC mov ebp, esp 0040122B |. 53 push ebx 0040122C |. 56 push esi 0040122D |. 8B75 08 mov esi, dword ptr [ebp+8] 00401230 |. 57 push edi 00401231 |. 8B7D 10 mov edi, dword ptr [ebp+10] 00401234 |. 8B4E 10 mov ecx, dword ptr [esi+10] 00401237 |. 8BD7 mov edx, edi 00401239 |. 8BC1 mov eax, ecx 0040123B |. C1E8 03 shr eax, 3 0040123E |. 8D0CF9 lea ecx, dword ptr [ecx+edi*8] 00401241 |. 83E0 3F and eax, 3F 00401244 |. C1E2 03 shl edx, 3 00401247 |. 3BCA cmp ecx, edx 00401249 |. 894E 10 mov dword ptr [esi+10], ecx 0040124C |. 73 03 jnb short 00401251 0040124E |. FF46 14 inc dword ptr [esi+14] 00401251 |> 6A 40 push 40 00401253 |. 8BCF mov ecx, edi 00401255 |. 5B pop ebx 00401256 |. C1E9 1D shr ecx, 1D 00401259 |. 014E 14 add dword ptr [esi+14], ecx 0040125C |. 2BD8 sub ebx, eax 0040125E |. 3BFB cmp edi, ebx 00401260 |. 72 42 jb short 004012A4 00401262 |. 53 push ebx 00401263 |. 8D4430 18 lea eax, dword ptr [eax+esi+18] 00401267 |. FF75 0C push dword ptr [ebp+C] 0040126A |. 50 push eax 0040126B |. E8 EC090000 call 00401C5C 00401270 |. 8D46 18 lea eax, dword ptr [esi+18] 00401273 |. 50 push eax 00401274 |. 56 push esi 00401275 |. E8 B0000000 call <MD5Transform> 0040127A |. 83C4 14 add esp, 14 0040127D |. 895D 08 mov dword ptr [ebp+8], ebx 00401280 |. 83C3 3F add ebx, 3F 00401283 |> 3BDF /cmp ebx, edi 00401285 |. 73 19 |jnb short 004012A0 00401287 |. 8B45 0C |mov eax, dword ptr [ebp+C] 0040128A |. 8D4418 C1 |lea eax, dword ptr [eax+ebx-3F] 0040128E |. 50 |push eax 0040128F |. 56 |push esi 00401290 |. E8 95000000 |call <MD5Transform> 00401295 |. 8345 08 40 |add dword ptr [ebp+8], 40 00401299 |. 59 |pop ecx 0040129A |. 59 |pop ecx 0040129B |. 83C3 40 |add ebx, 40 0040129E |.^ EB E3 \jmp short 00401283 004012A0 |> 33C0 xor eax, eax 004012A2 |. EB 04 jmp short 004012A8 004012A4 |> 8365 08 00 and dword ptr [ebp+8], 0 004012A8 |> 8B4D 08 mov ecx, dword ptr [ebp+8] 004012AB |. 8B55 0C mov edx, dword ptr [ebp+C] 004012AE |. 2BF9 sub edi, ecx 004012B0 |. 03CA add ecx, edx 004012B2 |. 57 push edi 004012B3 |. 8D4430 18 lea eax, dword ptr [eax+esi+18] 004012B7 |. 51 push ecx 004012B8 |. 50 push eax 004012B9 |. E8 9E090000 call 00401C5C 004012BE |. 83C4 0C add esp, 0C 004012C1 |. 5F pop edi 004012C2 |. 5E pop esi 004012C3 |. 5B pop ebx 004012C4 |. 5D pop ebp 004012C5 \. C3 retn

查找MD5Update的调用参考, 就可以看到用户数据了. 有一个函数中有2个连续调用的MD5Update, 这个函数是MD5Final

void MD5Final (digest, context) unsigned char digest[16]; /* message digest */ MD5_CTX *context; /* context */ { unsigned char bits[8]; unsigned int index, padLen; /* Save number of bits */ Encode (bits, context->count, 8); /* Pad out to 56 mod 64. */ index = (unsigned int)((context->count[0] >> 3) & 0x3f); padLen = (index < 56) ? (56 - index) : (120 - index); MD5Update (context, PADDING, padLen); /* Append length (before padding) */ MD5Update (context, bits, 8); /* Store state in digest */ Encode (digest, context->state, 16); /* Zeroize sensitive information. */ MD5_memset ((POINTER)context, 0, sizeof (*context)); } 004012C6 <MD5calcu.MD5Final> /$ 55 push ebp 004012C7 |. 8BEC mov ebp, esp 004012C9 |. 51 push ecx 004012CA |. 51 push ecx 004012CB |. 56 push esi 004012CC |. 57 push edi 004012CD |. 8B7D 0C mov edi, dword ptr [ebp+C] 004012D0 |. 6A 08 push 8 004012D2 |. 8D45 F8 lea eax, dword ptr [ebp-8] 004012D5 |. 8D77 10 lea esi, dword ptr [edi+10] 004012D8 |. 56 push esi 004012D9 |. 50 push eax 004012DA |. E8 F2080000 call 00401BD1 004012DF |. 8B06 mov eax, dword ptr [esi] 004012E1 |. 83C4 0C add esp, 0C 004012E4 |. C1E8 03 shr eax, 3 004012E7 |. 6A 38 push 38 004012E9 |. 83E0 3F and eax, 3F 004012EC |. 59 pop ecx 004012ED |. 3BC1 cmp eax, ecx 004012EF |. 72 03 jb short 004012F4 004012F1 |. 6A 78 push 78 004012F3 |. 59 pop ecx 004012F4 |> 2BC8 sub ecx, eax 004012F6 |. 51 push ecx 004012F7 |. 68 30604000 push 00406030 004012FC |. 57 push edi 004012FD |. E8 26FFFFFF call <MD5Update> 00401302 |. 8D45 F8 lea eax, dword ptr [ebp-8] 00401305 |. 6A 08 push 8 00401307 |. 50 push eax 00401308 |. 57 push edi 00401309 |. E8 1AFFFFFF call <MD5Update> 0040130E |. 6A 10 push 10 00401310 |. 57 push edi 00401311 |. FF75 08 push dword ptr [ebp+8] 00401314 |. E8 B8080000 call 00401BD1 00401319 |. 6A 58 push 58 0040131B |. 6A 00 push 0 0040131D |. 57 push edi 0040131E |. E8 57090000 call 00401C7A 00401323 |. 83C4 30 add esp, 30 00401326 |. 5F pop edi 00401327 |. 5E pop esi 00401328 |. C9 leave 00401329 \. C3 retn

MD5Final之外函数中调用MD5Update, 是用户的业务函数. 如果不是经过封装的CMD5类, 可以看见MD5Init和MD5Final之间夹着MD5Update, 可能是一个循环调用MD5Update(如果做MD5的数据比较长).

0040118D |. /EB 6D jmp short 004011FC ; not input, do not md5 0040118F |> |8D45 A8 lea eax, dword ptr [ebp-58] 00401192 |. |50 push eax 00401193 |. |E8 68000000 call 00401200 ; MD5Init? 00401198 |. |8D85 E0FEFFFF lea eax, dword ptr [ebp-120] 0040119E |. |56 push esi 0040119F |. |50 push eax 004011A0 |. |8D45 A8 lea eax, dword ptr [ebp-58] 004011A3 |. |50 push eax 004011A4 |. |E8 7F000000 call <MD5Update> 004011A9 |. |8D45 A8 lea eax, dword ptr [ebp-58] 004011AC |. |50 push eax 004011AD |. |8D85 18FEFFFF lea eax, dword ptr [ebp-1E8] 004011B3 |. |50 push eax 004011B4 |. |E8 0D010000 call <MD5Final>

从调用关系上看疑似MD5Init的函数, 确认下.

00401200 <MD5calcu.MD5Init> /$ 8B4424 04 mov eax, dword ptr [esp+4] 00401204 |. 8360 14 00 and dword ptr [eax+14], 0 00401208 |. 8360 10 00 and dword ptr [eax+10], 0 0040120C |. C700 01234567 mov dword ptr [eax], 67452301 00401212 |. C740 04 89ABC>mov dword ptr [eax+4], EFCDAB89 00401219 |. C740 08 FEDCB>mov dword ptr [eax+8], 98BADCFE 00401220 |. C740 0C 76543>mov dword ptr [eax+C], 10325476 00401227 \. C3 retn void MD5Init (context) MD5_CTX *context; /* context */ { context->count[0] = context->count[1] = 0; /* Load magic initialization constants. */ context->state[0] = 0x67452301; context->state[1] = 0xefcdab89; context->state[2] = 0x98badcfe; context->state[3] = 0x10325476; }

当MD5Init, MD5Final, MD5Update函数的调用关系明确后, 程序调用MD5的输入数据和输出结果(MD5值)就知道了.