学长说,做出我这到题,你就可以到网上找CrackMe做了。那就做做看吧。
引言
分析
学长给了个提示:
找到key!听说这个程序还能当计算器用??喵喵喵?
先随便输输,发现输错不会有任何提示,会让你不断重输,没什么发现,直接OD载入先。
追踪
老方法,先查找字符串,找到一些:
上下翻翻发现这些:
向下f8,可以发现,就是这个jnz让我们不断输入key:
观察后发现eax存的是我们输入的key的长度,说明key必须为20位长度。根据下面两个jnz以及printf,我猜测CALL 004010A0和CALL 00401000为两个关键CALL。见下
- CALL 004010A0的分析
这里用到IDA,f5分析得:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
| signed int __usercall sub_4010A0@<eax>(int a1@<eax>, int a2@<ebx>, unsigned int a3@<edi>) { unsigned int v3; char v4; unsigned int v5;
v3 = 0; if ( a3 ) { do { v4 = *(_BYTE *)(v3 + a2); if ( v4 == 61 ) break; if ( v4 < 43 ) return 1; if ( v4 > 122 ) return 1; v5 = byte_4020CD[v4]; if ( v5 == -1 ) return 1; switch ( v3 & 3 ) { case 0u: *(_BYTE *)a1 = 4 * v5; break; case 1u: *(_BYTE *)a1++ += (v5 >> 4) & 3; if ( v3 < a3 - 3 || *(_BYTE *)(a2 + a3 - 2) != 61 ) *(_BYTE *)a1 = 16 * v5; break; case 2u: *(_BYTE *)a1++ += (v5 >> 2) & 0xF; if ( v3 < a3 - 2 || *(_BYTE *)(a2 + a3 - 1) != 61 ) *(_BYTE *)a1 = (_BYTE)v5 << 6; break; case 3u: *(_BYTE *)a1++ += v5; +=v5 break; default: break; } ++v3; } while ( v3 < a3 ); } return 0; }
|
ps.我分析完以后才发现此处为base64解密,水平不够,哪怕发现了是3/4的转换也没想到base64,分析代码的时候并没有发现,耗了很多时间
以下为4020CD之后的一些二进制数据:
1 2 3 4 5 6 7 8 9 10 11
| 004020CD 00 00 00 00 00 00 00 FD 63 62 58 00 00 00 00 02 004020DD 00 00 00 67 00 00 00 B8 21 00 00 B8 11 00 00 50 004020ED 31 40 00 A8 31 40 00 00 00 00 00 3E FF FF FF 3F 004020FD 34 35 36 37 38 39 3A 3B 3C 3D FF FF FF FF FF FF 0040210D FF 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0040211D 0F 10 11 12 13 14 15 16 17 18 19 FF FF FF FF FF 0040212D FF 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27 28 0040213D 29 2A 2B 2C 2D 2E 2F 30 31 32 33 6B 65 79 00 73 0040214D 75 63 63 65 73 73 66 75 6C 00 00 67 69 76 65 20 0040215D 6D 65 20 25 73 3A 00 25 73 00 00 66 61 69 6C 00 0040216D 00 00 00 48 00 00 00 00 00 00 00 00 00 00 00 00
|
看完没什么思路。转向401000的分析。
IDA分析得:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| __int64 __cdecl sub_401000(const char *a1) { unsigned int v1; signed int v2; unsigned int v3; int v4; const char v5; int v6; __int64 v8;
v1 = strlen(a1); v2 = 0; v3 = v1; v8 = 0i64; if ( !v1 || (signed int)v1 > 13 ) goto LABEL_13; if ( (signed int)v1 > 0 ) { v4 = 8 * v1 + 4206760; do { v5 = a1[v2]; if ( v5 < 48 || v5 > 57 ) { if ( v5 < 65 || v5 > 90 ) goto LABEL_13; v6 = v5 - 55; } else { v6 = v5 - 48; } v8 += v6 * *(_QWORD *)v4; ++v2; v4 -= 8; } while ( v2 < (signed int)v3 ); if ( v8 < 0 ) LABEL_13: exit(1); } return v8; }
|
以下为0x4030A8后的一些二进制数据:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| 0x4030A8 0x59000000 5A000000 0x01000000 00000000 0x24000000 00000000 0x10050000 00000000 0x40B60000 00000000 0X00A11900 00000000 0X00A49A03 00000000 0x0010BF81 00000000 0x0040DE3E 12000000 0x000041D7 90020000 0x00002445 5E5C0000 0x000010B9 41FD0C00 0x00004006 3E9DD301 0x000000E1 B81CC241
|
由Little-Endian知,v4实际读取到的数据为:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| 0000005A00000059 0000000000000001 36^0 0000000000000024 36^1 0000000000000510 36^2 000000000000B640 36^3 000000000019A100 36^4 00000000039AA400 36^5 0000000081BF1000 36^6 000000123EDE4000 36^7 00000290D7410000 36^8 00005C5E45240000 36^9 000CFD41B9100000 36^10 01D39D3E06400000 36^11 41C21CB8E1000000 36^12
|
发现其实是一个36进制到16进制的转换,转换的结果为6261736532333333h,反向计算的经过004010A0加密以后的字符串应该为1HUXV29D2KFUB。
- 再转向CALL 004010A0
既然知道了加密后的字符串,通过004020CD处的数据慢慢解密(真的很慢,如果发现是base64就是几秒钟的事情了)可以得到最终的key:MUhVWFYyOUQyS0ZVQg==
我艰辛的过程大致如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| 01 |a*4| | | | | | | | | | | | | | | 77 M 02 |b |b*F| | | | | | | | | | | | | | 85 U 03 | |c |c | | | | | | | | | | | | | 104 h 04 | | |d | | | | | | | | | | | | | 86 V 05 | | | |e*4| | | | | | | | | | | | 87 W 06 | | | |f |f*F| | | | | | | | | | | 70 F 07 | | | | |g |g | | | | | | | | | | 89 Y 08 | | | | | |h | | | | | | | | | | 121 y 09 | | | | | | |i*4| | | | | | | | | 79 O 10 | | | | | | |j |j*F| | | | | | | | 85 U 11 | | | | | | | |k |k | | | | | | | 81 Q 12 | | | | | | | | |l | | | | | | | 121 y 13 | | | | | | | | | |m*4| | | | | | 83 S 14 | | | | | | | | | |n |n*F| | | | | 48 0 15 | | | | | | | | | | |o |o | | | | 90 Z 16 | | | | | | | | | | | |p | | | | 86 V 17 | | | | | | | | | | | | |q*4| | | 81 Q 18 | | | | | | | | | | | | |2 |0 | | 103 g 19 | | | | | | | | | | | | | |0 |s | = 20 | | | | | | | | | | | | | | |t | = | 49| 72| 85| 88| 86| 50| 57| 68| 50| 75| 70| 85| 66| 00| 00| 1 H U X V 2 9 D 2 K F U B
|
虽说key是解出来了,但毕竟是入门的题目,解了这么就还是太慢,反思自己,连常见加密的算法都不熟练。