前言
如果程序中用到了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值)就知道了.