好友
阅读权限30
听众
最后登录1970-1-1
|
例子是帖子“谁能搞定这个crackme,太难了”里的程序:crackme.rar (701.07 KB)。
运行目标后,显示本机的“机器码”,输入“认证码”,点“认证”按钮。
如果验证成功会播放一小段视频,否则跳出“提示”框:“认证码错误。”
从下面的“认证流程”分析可知,严格讲它应该是一个KeygenMe,爆破是不可能成功的。
一.认证流程
我调试机器的机器码:N24EBC46DZ9DB8HB1,输入12345678为认证码。待出“提示”框后,OD里F12停下来,从"Call stack"窗里找到验证过程。目标程序无壳无花,可读性好。
[Asm] 纯文本查看 复制代码 00418E9D |>\8B4424 34 MOV EAX, DWORD PTR [ESP+0x34] ; Case 7D8 of switch 0041897F
00418EA1 |. 8BCE MOV ECX, ESI
00418EA3 |. 50 PUSH EAX
00418EA4 |. E8 B7A50000 CALL 00423460 <- ***
00418EA9 |. E9 58070000 JMP 00419606
00423460 /$ 55 PUSH EBP
00423461 |. 8BEC MOV EBP, ESP
00423463 |. 83EC 18 SUB ESP, 0x18
...
0042349C |>\56 PUSH ESI
0042349D |. 57 PUSH EDI
0042349E |. 8B55 08 MOV EDX, [ARG.1]
004234A1 |. 8B42 0C MOV EAX, DWORD PTR [EDX+0xC]
004234A4 |. 83E8 01 SUB EAX, 0x1
004234A7 |. 8945 EC MOV [LOCAL.5], EAX
004234AA |. EB 09 JMP SHORT 004234B5
004234AC |> 8B4D EC /MOV ECX, [LOCAL.5]
004234AF |. 83E9 01 |SUB ECX, 0x1
004234B2 |. 894D EC |MOV [LOCAL.5], ECX
004234B5 |> 837D EC 00 >CMP [LOCAL.5], 0x0
004234B9 |. 7C 12 |JL SHORT 004234CD
004234BB |. 8B55 EC |MOV EDX, [LOCAL.5]
004234BE |. 8B45 08 |MOV EAX, [ARG.1]
004234C1 |. 8B4C90 10 |MOV ECX, DWORD PTR [EAX+EDX*4+0x10]
004234C5 |. 894D F0 |MOV [LOCAL.4], ECX
004234C8 |. FF75 F0 |PUSH [LOCAL.4]
004234CB |. EB DF \JMP SHORT 004234AC
004234CD |> FF55 FC CALL NEAR [LOCAL.1] Stack SS:[0012F740]=00402DC2
... Stack SS:[0012FCAC]=0040146C
00423506 |. 8BE5 MOV ESP, EBP
00423508 |. 5D POP EBP
00423509 \. C2 0400 RETN 0x4
验证过程在00402DC2里,每次点“认证”按钮都要调用这个过程;0040146C为程序初始化过程,包括机器码的生成等,只调用一次,稍后再说它。
[Asm] 纯文本查看 复制代码 00402DC2 /. 55 PUSH EBP
00402DC3 |. 8BEC MOV EBP, ESP
00402DC5 |. 81EC 44000000 SUB ESP, 0x44
00402DCB |. C745 FC 00000000 MOV [LOCAL.1], 0x0
00402DD2 |. C745 F8 00000000 MOV [LOCAL.2], 0x0
00402DD9 |. C745 F4 00000000 MOV [LOCAL.3], 0x0
00402DE0 |. 68 00000000 PUSH 0x0
00402DE5 |. BB A0614000 MOV EBX, 004061A0
00402DEA |. E8 BD300000 CALL 00405EAC "C:\\Temp\\T266235"
00402DEF |. 83C4 04 ADD ESP, 0x4
00402DF2 |. 8945 F0 MOV [LOCAL.4], EAX
00402DF5 |. 68 00000000 PUSH 0x0
00402DFA |. BB C0614000 MOV EBX, 004061C0
00402DFF |. E8 A8300000 CALL 00405EAC "crackme.exe"
00402E04 |. 83C4 04 ADD ESP, 0x4
00402E07 |. 8945 EC MOV [LOCAL.5], EAX
00402E0A |. FF75 EC PUSH [LOCAL.5]
00402E0D |. 68 C5DD4700 PUSH 0047DDC5
00402E12 |. FF75 F0 PUSH [LOCAL.4]
00402E15 |. B9 03000000 MOV ECX, 0x3
00402E1A |. E8 67E7FFFF CALL 00401586 strcat: "C:\\Temp\\T266235\\crackme.exe"
...
在文件中,用0x59A95AA9作为标记定位文件指针到0x000A9004处(Overlay):
00402FC5 |. 68 01030080 PUSH 0x80000301
00402FCA |. 6A 00 PUSH 0x0
00402FCC |. 50 PUSH EAX
00402FCD |. 68 05000080 PUSH 0x80000005
00402FD2 |. 6A 00 PUSH 0x0
00402FD4 |. 8B45 FC MOV EAX, [LOCAL.1]
00402FD7 |. 85C0 TEST EAX, EAX
00402FD9 |. 75 05 JNZ SHORT 00402FE0
00402FDB |. B8 42DD4700 MOV EAX, 0047DD42
00402FE0 |> 50 PUSH EAX
00402FE1 |. 68 02000000 PUSH 0x2
00402FE6 |. BB A06D4000 MOV EBX, 00406DA0 read file
00402FEB |. E8 BC2E0000 CALL 00405EAC 读入Overlay+4,长度000688E8
000A9000: 59A95AA9 Tag
000A9004: 91 4D 84 F2.05 40 DF 00.34 35 C4 B4.EE 4B 91 98 加密的视频数据
...
001118E4: EE 58 F1 9E.23 59 33 EF
依次取机器码和认证码:
0040300E |. 6A FF PUSH -0x1
00403010 |. 6A 08 PUSH 0x8
00403012 |. 68 07000116 PUSH 0x16010007
00403017 |. 68 03000152 PUSH 0x52010003
0040301C |. E8 9D2E0000 CALL 00405EBE 取机器码 "N24EBC46DZ9DB8HB1"
...
00403027 |. 6A FF PUSH -0x1
00403029 |. 6A 08 PUSH 0x8
0040302B |. 68 09000116 PUSH 0x16010009
00403030 |. 68 03000152 PUSH 0x52010003
00403035 |. E8 842E0000 CALL 00405EBE 取认证码 "12345678"
由机器码和认证码计算解密用的Key:
00403040 |. 8D45 EC LEA EAX, [LOCAL.5]
00403043 |. 50 PUSH EAX
00403044 |. 8D45 F0 LEA EAX, [LOCAL.4]
00403047 |. 50 PUSH EAX
00403048 |. E8 A6030000 CALL 004033F3 计算Key,返回:24EBC46E
0012F6C4 0012F700 |Arg1 = 0012F700, []=00177620 ASCII "N24EBC46DZ9DB8HB1"
0012F6C8 0012F6FC \Arg2 = 0012F6FC, []=00177098 ASCII "12345678"
...
00403070 |> 68 01030080 PUSH 0x80000301
00403075 |. 6A 00 PUSH 0x0
00403077 |. FF75 E8 PUSH [LOCAL.6]
0040307A |. 68 01000000 PUSH 0x1
0040307F |. BB C0724000 MOV EBX, 004072C0 HextoDecString
00403084 |. E8 232E0000 CALL 00405EAC 将24EBC46E转为十进制字符串:"619431022"
解密:
004030C3 |. 68 03000000 PUSH 0x3
004030C8 |. B8 01000000 MOV EAX, 0x1
004030CD |. BB 601E4500 MOV EBX, 00451E60 RC4解密
004030D2 |. E8 ED2D0000 CALL 00405EC4
0012F6A4 00000003
0012F6A8 001780C8 Overlay data
0012F6AC 00000000
0012F6B0 80000005
0012F6B4 00177640 ASCII "619431022"
0012F6B8 00000000
0012F6BC 80000004
0012F6C0 00000002
0012F6C4 00000000
0012F6C8 80000301
解压缩:
00403119 |. 68 01000000 PUSH 0x1
0040311E |. B8 01000000 MOV EAX, 0x1
00403123 |. BB 301A4500 MOV EBX, 00451A30 zlib decompression
00403128 |. E8 972D0000 CALL 00405EC4
...
004031D0 |.|E8 41FBFFFF CALL 00402D16 比较解压缩后第一字节是否为'H'(0x48)
...
00403205 |> 837D E8 00 CMP [LOCAL.6], 0x0 比较结果:0(相同),!=0(不同)
00403209 |. 0F84 3B000000 JE 0040324A 解压正确,继续
0040320F |. 68 04000080 PUSH 0x80000004 解压错误
00403214 |. 6A 00 PUSH 0x0
00403216 |. 68 CEDD4700 PUSH 0047DDCE "提示"
0040321B |. 68 01030080 PUSH 0x80000301
00403220 |. 6A 00 PUSH 0x0
00403222 |. 68 30000000 PUSH 0x30
00403227 |. 68 04000080 PUSH 0x80000004
0040322C |. 6A 00 PUSH 0x0
0040322E |. 68 D3DD4700 PUSH 0047DDD3 "认证码错误。"
00403233 |. 68 03000000 PUSH 0x3
00403238 |. BB 407F4000 MOV EBX, 00407F40 call user32.MessageBoxA
0040323D |. E8 6A2C0000 CALL 00405EAC
00403242 |. 83C4 28 ADD ESP, 0x28
00403245 |. E9 85010000 JMP 004033CF
0040324A |> 6A 00 PUSH 0x0
0040324C |. 6A 00 PUSH 0x0
0040324E |. 6A 00 PUSH 0x0
00403250 |. 68 01000000 PUSH 0x1
00403255 |. BB 10744000 MOV EBX, 00407410 创建只读、隐藏的临时文件
0040325A |. E8 4D2C0000 CALL 00405EAC "C:\\DOCUME~1\\user\\LOCALS~1\\Temp\\1114e20.tmp"
...
004033EF |> 8BE5 MOV ESP, EBP
004033F1 |. 5D POP EBP
004033F2 \. C3 RETN
数据解压缩错误就出“提示”框;正确时,创建临时文件,并写入解压的数据,最后播放此文件。
可见,视频文件的内容需要解密、解压两步。关键是解密,各种改跳的爆破手段都是徒劳。
二.RC4的密钥
要保证数据解密正确就需要得到正确的Key,而这个Key是由“机器码”和“认证码”计算出来的(00403048 CALL 004033F3):
[Asm] 纯文本查看 复制代码 004033F3 /$ 55 PUSH EBP
004033F4 |. 8BEC MOV EBP, ESP
004033F6 |. 81EC 24000000 SUB ESP, 0x24
004033FC |. C745 FC 00000000 MOV [LOCAL.1], 0x0
00403403 |. C745 F8 00000000 MOV [LOCAL.2], 0x0
0040340A |. C745 F4 00000000 MOV [LOCAL.3], 0x0
00403411 |. FF75 08 PUSH [ARG.1] pMiD, "N24EBC46DZ9DB8HB1"
00403414 |. E8 55000000 CALL 0040346E
00403419 |. 8945 FC MOV [LOCAL.1], EAX 24EBC46D
0040341C |. FF75 0C PUSH [ARG.2] pPassword, "12345678"
0040341F |. E8 2F030000 CALL 00403753 FFFFFFFF
00403424 |. 8945 F8 MOV [LOCAL.2], EAX
00403427 |. DB45 FC FILD [LOCAL.1] Stack SS:[0012F6B8]=24EBC46D (decimal 619431021.)
0040342A |. DD5D EC FSTP QWORD PTR [EBP-0x14]
0040342D |. DD45 EC FLD QWORD PTR [EBP-0x14]
00403430 |. DB45 F8 FILD [LOCAL.2] Stack SS:[0012F6B4]=FFFFFFFF (decimal -1.)
00403433 |. DD5D E4 FSTP QWORD PTR [EBP-0x1C]
00403436 |. DC65 E4 FSUB QWORD PTR [EBP-0x1C] ST=619431021.0, Stack SS:[0012F6A0]=-1.0
00403439 |. DD5D DC FSTP QWORD PTR [EBP-0x24] 619431022.0
0040343C |. DD45 DC FLD QWORD PTR [EBP-0x24]
0040343F |. E8 1BE1FFFF CALL 0040155F DoubletoHex, 24EBC46E
00403444 |. 8945 F4 MOV [LOCAL.3], EAX
00403447 |. 8B45 F4 MOV EAX, [LOCAL.3]
0040344A |. E9 00000000 JMP 0040344F
0040344F |> 8BE5 MOV ESP, EBP
00403451 |. 5D POP EBP
00403452 \. C2 0800 RETN 0x8
为节省篇幅,两个解码CALLs的代码就不帖了,很简单的事,E把它弄得很啰嗦。简述于下:
1. CALL 0040346E解码“机器码”:字符'Z'作为分隔符,只用第二部分"9DB8HB1"。它是Base20编码的,转为十进制就是619431021.(0x24EBC46D)。
2. CALL 00403753解码“认证码”:方法同1.,不过它的第二部分是Base21编码的!这里返回0xFFFFFFFF,说明我的假码格式不正确(缺少分隔符'Z')。
3. 计算Key = MiD - Password = 24EBC46D - FFFFFFFF = 24EBC46E。
用于编码/解码的字符集是ASCII "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"的子集:Base20的字符集是"0123456789ABCDEFGHIJ",Base21为"0123456789ABCDEFGHIJK"。
crackme的关键就是这个Key。
显然,如果有一个正确的示例“认证码”,那么这里Key已计算出来,本题也就没啥难度了。
现在我们得自己解决这个问题。先从已有的信息,来探讨一下求解出Key的可能性。
三.求解出Key的可能性
因为我们不知道正确的Key,只能从它可能的取值范围一个一个地试,即传说中的暴力攻击。
暴力攻击是用字典或规则范围内的Key,以穷举的方式,解密密文,再与已知的(部分)明文比较,来确定Key的过程。
这里有三个要素:1) 密文,2) (部分)明文,3) 时间复杂程度:Key的空间大小及算法。
我们已经有了作为Overlay的密文,再看看我们是否有(部分)明文。如果没有比对的参照内容,穷举也就无从谈起。
非常幸运,也许是crackme作者故意留下了破绽。在紧接着解密后面的那个解压缩调用里:
[Asm] 纯文本查看 复制代码 00451A30 . 8B4424 0C MOV EAX, DWORD PTR [ESP+0xC]
00451A34 . 53 PUSH EBX
00451A35 . 56 PUSH ESI
00451A36 . 57 PUSH EDI
00451A37 . 8B30 MOV ESI, DWORD PTR [EAX]
00451A39 . 33FF XOR EDI, EDI
00451A3B . 83C6 08 ADD ESI, 0x8 ESI指向解密后的数据块
00451A3E . 33C0 XOR EAX, EAX
00451A40 . 8B5E FC MOV EBX, DWORD PTR [ESI-0x4] 数据块大小:000688E8
00451A43 . 894424 18 MOV DWORD PTR [ESP+0x18], EAX
00451A47 . 83FB 08 CMP EBX, 0x8
00451A4A . 72 43 JB SHORT 00451A8F 数据块长应 >= 8 字节
00451A4C . 813E 0D0F3E03 CMP DWORD PTR [ESI], 0x33E0F0D 前4字节应为:0D 0F 3E 03
00451A52 . 75 3B JNZ SHORT 00451A8F
00451A54 . 8B46 04 MOV EAX, DWORD PTR [ESI+0x4] 第二个DWORD的值为数据块解压后的长度
00451A57 . D1E0 SHL EAX, 1 解压需要的空间
00451A59 . 85C0 TEST EAX, EAX 第二个DWORD不应为0
00451A5B . 894424 18 MOV DWORD PTR [ESP+0x18], EAX
00451A5F . 7E 2E JLE SHORT 00451A8F
00451A61 . 50 PUSH EAX
00451A62 . E8 30B20000 CALL 0045CC97 call ntdll.RtlAllocateHeap
...
很好,也就是说前四字节91 4D 84 F2,应解密为0D 0F 3E 03!
如果目标程序这里不用解密后的部分明文作为判断依据,而采用比较解密后数据块的哈希值(Hash),时间复杂程度会显著提高!
再来考察Key的空间大小:一个32位数,共有0x100000000个值,范围0 ~ 0xFFFFFFFF。转换为十进制字符串,范围为:"-2147483648" ~ "2147483647",注意它是有符号数。
可见,Key的取值范围是非常有限的。这是三要素中最重要的一点。
另外,RC4算法可以说是对称算法中最简单的一种,开销很小,硬件都可容易地实现。
所以可以肯定:不需要太多时间就可以解出Key。
我们只需要将标准RC4算法作简单修改,并优化代码,以便在尽可能短的时间内找出Key。
四.密钥的暴力攻击程序
攻击程序改写自我以前的一篇文章“RC4算法暴力破解的尝试(附源码)”。
那篇文章包括RC4算法的C源码及它自身的故事,代码和编译的优化。感兴趣的可看看。
其中Key的取值范围和长度都未知,只能假定它的范围,并从最短长度以一个迭代函数逐一试算。幸运的是它使用了简单密码,只用很短时间就找到了。
本例Key的长度和范围都是确定的,迭代函数可省去。
同样针对一台四核的机器,使用4个线程并行计算,各线程求Key的区间分配如下:
Hex.: T0(0x00000000~0x3FFFFFFF), T1(0x40000000~0x7FFFFFFF), T2(0x80000000~0xBFFFFFFF), T3(0xC0000000~0xFFFFFFFF)
DecStr:T0(0 ~ 1073741823), T1(1073741824 ~ 2147483647), T2(-2147483648 ~ -1073741825), T3(-1073741824 ~ -1)
附件中命令行的攻击程序运行结束后,一个示例结果(每次运行时间约有差异):
[Plain Text] 纯文本查看 复制代码 EnumRC4KeyMT.exe
253303, 1073914258, -2147272861, -1073437260 1 sec.
Found in thread #0: 94050000 569.500 sec.
255136619, 1241974127, -1934444969, -774773308 1574 sec.
392247698, 1324093248, -1832311392, -618146173 2356 sec.
623243583, 1459369189, -1665573879, -356217674 3648 sec.
744119677, 1531805528, -1575849864, -218907462 4328 sec.
952217104, 1661629274, -1422849290, -1 5476 sec.
1073741823, 1829532136, -1275980364, -1 6199 sec.
1073741823, 1928825186, -1150374888, -1 6565 sec.
1073741823, 2131975751, -1073741825, -1 7203 sec.
1073741823, 2141500835, -1073741825, -1 7231 sec.
1073741823, 2146235850, -1073741825, -1 7245 sec.
Current Keys:
1073741823
2147483647
-1073741825
-1
Start: 2014-06-21 15:56:59.453
End: 2014-06-21 17:57:49.046
Execution time: 7249.594 seconds.
程序设计了两个热键:CTRL+C用于显示当前各线程的进度;CTRL+Break终止程序。
在线程编号0中,找到一个:94050000.(0x059B16D0),用时9分多钟。各线程在找到一个匹配后,不会停止,直到枚举完各自范围的所有Key。这是为了消除可能存在的“碰撞”。
整个Key的取值范围搜索完成耗时约2小时,只找到唯一匹配:Key=059B16D0!
五.获取“认证码”
现在有了Key,就可以正确解出视频文件了!
同时,我们也可以计算出“认证码”。
先看看“机器码”的构成。
继续上面提到的0040146C那个CALL:
[Asm] 纯文本查看 复制代码 0040146C /. 55 PUSH EBP
0040146D |. 8BEC MOV EBP, ESP
0040146F |. 81EC 04000000 SUB ESP, 0x4
00401475 |. E8 68010000 CALL 004015E2 <- ***
...
0040155B |>\8BE5 MOV ESP, EBP
0040155D |. 5D POP EBP
0040155E \. C3 RETN
跟进004015E2:
[Asm] 纯文本查看 复制代码 004015E2 /$ 55 PUSH EBP
004015E3 |. 8BEC MOV EBP, ESP
004015E5 |. 81EC 2C000000 SUB ESP, 0x2C
004015EB |. C745 FC 00000000 MOV [LOCAL.1], 0x0
004015F2 |. C745 F8 00000000 MOV [LOCAL.2], 0x0
004015F9 |. C745 F4 00000000 MOV [LOCAL.3], 0x0
00401600 |. C745 F0 00000000 MOV [LOCAL.4], 0x0
00401607 |. C745 EC 00000000 MOV [LOCAL.5], 0x0
0040160E |. E8 EC010000 CALL 004017FF <- ***
00401613 |. 8945 FC MOV [LOCAL.1], EAX
00401616 |. 837D FC 00 CMP [LOCAL.1], 0x0
0040161A |. 0F85 07000000 JNZ 00401627
...
调用004017FF里将从硬盘物理信息计算MiD/HWiD:
004017FF /$ 55 PUSH EBP
00401800 |. 8BEC MOV EBP, ESP
00401802 |. 81EC 38000000 SUB ESP, 0x38
00401808 |. C745 FC 00000000 MOV [LOCAL.1], 0x0
0040180F |. C745 F8 00000000 MOV [LOCAL.2], 0x0
00401816 |. C745 F4 00000000 MOV [LOCAL.3], 0x0
0040181D |. C745 F0 00000000 MOV [LOCAL.4], 0x0
00401824 |. C745 EC 00000000 MOV [LOCAL.5], 0x0
0040182B |. C745 E8 00000000 MOV [LOCAL.6], 0x0
00401832 |. C745 E4 00000000 MOV [LOCAL.7], 0x0
00401839 |. C745 E0 00000000 MOV [LOCAL.8], 0x0
00401840 |. B8 2FDD4700 MOV EAX, 0047DD2F ; ASCII "\\\\.\\PhysicalDrive0"
...
004019D0 |. 68 00000000 PUSH 0x0
004019D5 |. 8D45 E4 LEA EAX, [LOCAL.7]
004019D8 |. 50 PUSH EAX
004019D9 |. FF75 F4 PUSH [LOCAL.3]
004019DC |. FF75 D0 PUSH [LOCAL.12]
004019DF |. 68 0C000000 PUSH 0xC
004019E4 |. FF75 D8 PUSH [LOCAL.10]
004019E7 |. 68 00142D00 PUSH 0x2D1400
004019EC |. FF75 F8 PUSH [LOCAL.2]
004019EF |. B8 02000000 MOV EAX, 0x2
004019F4 |. E8 AD440000 CALL 00405EA6 call kernel32.DeviceIoControl
stack:
0012FBE4 00000098 HANDLE hDevice
0012FBE8 002D1400 DWORD dwIoControlCode
0012FBEC 0016DDA8 LPVOID lpInBuffer
0012FBF0 0000000C DWORD nInBufferSize
0012FBF4 001712A0 LPVOID lpOutBuffer
0012FBF8 00000400 DWORD nOutBufferSize
0012FBFC 0012FC20 LPDWORD lpBytesReturned: =0, called =000000B1
0012FC00 00000000 LPOVERLAPPED lpOverlapped
...
00401A1B |. 50 PUSH EAX
00401A1C |. E8 63000000 CALL 00401A84 ret MiD/HWiD=24EBC46D
...
00401A80 |. 8BE5 MOV ESP, EBP
00401A82 |. 5D POP EBP
00401A83 \. C3 RETN
调用00401A84里计算MiD/HWiD的具体算法不用理会,好象还蛮复杂的,没仔细看。从这里返回后,继续调用004015E2的后面部分:
[Asm] 纯文本查看 复制代码 004016C7 |. 68 10000000 PUSH 0x10 16进制
004016CC |. 68 0A000000 PUSH 0xA 十进制
004016D1 |. 8D45 E8 LEA EAX, [LOCAL.6]
004016D4 |. 50 PUSH EAX
004016D5 |. E8 B7070000 CALL 00401E91 转MiD/HWiD ASCII "24EBC46D" 为 ASCII "619431021"
...
00401724 |. 68 14000000 PUSH 0x14 20进制
00401729 |. 68 0A000000 PUSH 0xA 十进制
0040172E |. 8D45 E8 LEA EAX, [LOCAL.6]
00401731 |. 50 PUSH EAX
00401732 |. E8 5A070000 CALL 00401E91 十进制619431021编码为Base20 ASCII "9DB8HB1"
...
00401762 |. FF75 F0 PUSH [LOCAL.4]
00401765 |. 68 2DDD4700 PUSH 0047DD2D
0040176A |. FF75 F4 PUSH [LOCAL.3]
0040176D |. FF75 F8 PUSH [LOCAL.2]
00401770 |. B9 04000000 MOV ECX, 0x4
00401775 |. E8 0CFEFFFF CALL 00401586 返回 ASCII "N24EBC46DZ9DB8HB1"
0012FC34 0047DD2B |Arg1 = 0047DD2B ASCII "N"
0012FC38 00171308 |Arg2 = 00171308 ASCII "24EBC46D"
0012FC3C 0047DD2D |Arg3 = 0047DD2D ASCII "Z"
0012FC40 00171368 \Arg4 = 00171368 ASCII "9DB8HB1"
...
004017FB |. 8BE5 MOV ESP, EBP
004017FD |. 5D POP EBP
004017FE \. C3 RETN
从004015E2返回后,“机器码”就出来了。如果“保存”选项已勾选,再将它保存到注册表"SOFTWARE\\jclock"。
“机器码”的格式:"N" + MiD的16进制串 + "Z" + MiD的Base20编码
上面第一节“认证流程”里说过,“认证码”的格式:"随便字符串" + "Z" + Password的Base21编码
而Password = MiD - Key,所以我调试机器的Password = 24EBC46D - 059B16D0 = 1F50AD9D = 十进制字符串"525381021"。
再将"525381021"编码为Base21就Okay了!
编码可以用计算器自己慢慢地手工进行,也可写个Keygen。取巧的方法是利用它的进制转换函数00401E91!
函数00401E91的定义可表示为:
[C] 纯文本查看 复制代码 char* fn00401E91(char *pSrc, int nSrcBase, int nTargetBase);
步骤:
1. OD载入crackme.exe,清除所有断点,在00403939设置F2断点。
2. F9运行。“认证码”输入:"whateverZ525381021",点“认证”按钮。
3. 00403939断下:
[Asm] 纯文本查看 复制代码 00403939 . 68 0A000000 PUSH 0xA
0040393E . 68 15000000 PUSH 0x15
00403943 . FF75 EC PUSH DWORD PTR [EBP-0x14]
00403946 . E8 46E5FFFF CALL 00401E91
stack:
0012F670 00A23EA8 ASCII "WHATEVERZ525381021"
很好,就是我们输入的,那个输入框会自动转为大写。F7到00403946处,fn00401E91的参数:
[Asm] 纯文本查看 复制代码 stack:
0012F664 00176FEC |Arg1 = 00176FEC, [00176FEC]=001776B0 ASCII "525381021", pSrc
0012F668 00000015 |Arg2 = 00000015, nSrcBase
0012F66C 0000000A \Arg3 = 0000000A, nTargetBase
它的本意是将“认证码”的第二部分进行Base21解码,我们现在是利用它进行编码,所以交换一下[0012F668]和[0012F66C]的值:
[Asm] 纯文本查看 复制代码 0012F664 00176FEC |Arg1 = 00176FEC
0012F668 0000000A |Arg2 = 0000000A, nSrcBase
0012F66C 00000015 \Arg3 = 00000015, nTargetBase
F8后得到:EAX=00177760 ASCII "62D9A3I"。
所以调试机器的“认证码”为:WHATEVERZ62D9A3I。因为字符'Z'的前面部分未定义,可以是“随便”:52PoJieZ62D9A3I、MistHillZ62D9A3I……,whatever!
EnumRC4KeyMT.exe.7z
(15.79 KB, 下载次数: 160)
|
免费评分
-
查看全部评分
|