【文章标题】: 奇妙的跳转
【文章作者】: coldpine
【软件名称】: SV_KeygenMe.exe
【下载地址】: http://www.crackmes.de/users/sv_reverser/sv_keygenme/
【编写语言】: masm
【使用工具】: od & calc.exe
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
用od加载,对GetDlgItemTextA函数下断点,并输入
name:heminrui
code:1234567890123456(经过跟踪发现要16位序列号)
00401229 . 6A 28 PUSH 28 ;
0040122B . 68 68344000 PUSH SV_Keyge.00403468 ;
00401230 . 68 EB030000 PUSH 3EB ;
00401235 . FF75 08 PUSH DWORD PTR SS:[EBP+8] ;
00401238 . E8 0B010000 CALL <JMP.&user32.GetDlgItemTextA> ; 获取输入的name
0040123D . 6A 28 PUSH 28 ;
0040123F . 68 68304000 PUSH SV_Keyge.00403068 ;
00401244 . 68 EC030000 PUSH 3EC ;
00401249 . FF75 08 PUSH DWORD PTR SS:[EBP+8] ;
0040124C . E8 F7000000 CALL <JMP.&user32.GetDlgItemTextA> ; 获取输入的code
00401251 . 68 68304000 PUSH SV_Keyge.00403068 ;
00401256 . E8 53010000 CALL <JMP.&kernel32.lstrlenA> ; code代码的长度
0040125B . 83F8 10 CMP EAX, 10 ;判断是不是16位,如果不是的,就跳出
0040125E 75 64 JNZ SHORT SV_Keyge.004012C4
00401260 . E8 D3FDFFFF CALL SV_Keyge.00401038 ;关键call,计算序列号用的函数
跟进子函数
功能:取name每位字符的ascii码和code的两位数字进行异或
----------------------------------------------------------------------------------------------
00401038 /$ 8D1D 68344000 LEA EBX, DWORD PTR DS:[403468] ;用户名地址进ebx
0040103E |. 8D35 68304000 LEA ESI, DWORD PTR DS:[403068] ;序列号地址进esi
00401044 |. 8D3D 68324000 LEA EDI, DWORD PTR DS:[403268]
0040104A |. EB 2A JMP SHORT SV_Keyge.00401076
0040104C |> 6A 03 /PUSH 3 ; /n = 3
0040104E |. 56 |PUSH ESI ; |String2
0040104F |. 68 68364000 |PUSH SV_Keyge.00403668 ; |String1 = SV_Keyge.00403668
00401054 |. E8 4F030000 |CALL <JMP.&kernel32.lstrcpynA> ; \lstrcpynA
00401059 |. 68 68364000 |PUSH SV_Keyge.00403668 ;取code两位进缓冲区
0040105E |. E8 51030000 |CALL SV_Keyge.004013B4
00401063 |. 3203 |XOR AL, BYTE PTR DS:[EBX] ;取code前两位和name的第一位的ascii码值异或
00401065 |. 8807 |MOV BYTE PTR DS:[EDI], AL ;保存结果
00401067 |. 46 |INC ESI
00401068 |. 46 |INC ESI ;code后两位的地址
00401069 |. 43 |INC EBX ;取name后一位的地址
0040106A |. 803B 00 |CMP BYTE PTR DS:[EBX], 0 ;没有取完,就继续取完,取玩的话,再重新取一遍
0040106D |. 75 06 |JNZ SHORT SV_Keyge.00401075
0040106F |. 8D1D 68344000 |LEA EBX, DWORD PTR DS:[403468]
00401075 |> 47 |INC EDI
00401076 |> 803E 00 CMP BYTE PTR DS:[ESI], 0 ;比较code取完了没有
00401079 |.^ 75 D1 \JNZ SHORT SV_Keyge.0040104C
0040107B \. C3 RET
----------------------------------------------------------------------------------------------------
00401265 . 8D3D 68324000 LEA EDI, DWORD PTR DS:[403268]
0040126B FFD7 CALL EDI
0040126D . 6A 00 PUSH 0 ; /Style = MB_OK|MB_APPLMODAL
0040126F . 68 3B304000 PUSH SV_Keyge.0040303B ; |then ?
00401274 . 68 1C304000 PUSH SV_Keyge.0040301C ; |try again
00401279 . 6A 00 PUSH 0 ; |hOwner = NULL
0040127B . E8 E6000000 CALL <JMP.&user32.MessageBoxA> ; \MessageBoxA
00401280 . EB 42 JMP SHORT SV_Keyge.004012C4
00401282 . 8D3D 68324000 LEA EDI, DWORD PTR DS:[403268]
00401288 . 83C7 04 ADD EDI, 4
0040128B . 8B07 MOV EAX, DWORD PTR DS:[EDI]
0040128D 3B05 90364000 CMP EAX, DWORD PTR DS:[403690]
00401293 75 1C JNZ SHORT SV_Keyge.004012B1
00401295 . E8 60000000 CALL SV_Keyge.004012FA
0040129A . 68 E9030000 PUSH 3E9 ; /ControlID = 3E9 (1001.)
0040129F . FF75 08 PUSH DWORD PTR SS:[EBP+8] ; |hWnd
004012A2 . E8 9B000000 CALL <JMP.&user32.GetDlgItem> ; \GetDlgItem
004012A7 . 6A 00 PUSH 0 ; /Enable = FALSE
004012A9 . 50 PUSH EAX ; |hWnd
004012AA . E8 8D000000 CALL <JMP.&user32.EnableWindow> ; \EnableWindow
004012AF . EB 13 JMP SHORT SV_Keyge.004012C4
004012B1 > 6A 00 PUSH 0 ; /Style = MB_OK|MB_APPLMODAL
004012B3 . 68 3B304000 PUSH SV_Keyge.0040303B ; |then ?
004012B8 . 68 1C304000 PUSH SV_Keyge.0040301C ; |try again
004012BD . 6A 00 PUSH 0 ; |hOwner = NULL
004012BF . E8 A2000000 CALL <JMP.&user32.MessageBoxA> ; \MessageBoxA
004012C4 > FF75 EC PUSH DWORD PTR SS:[EBP-14]
004012C7 . 64:8F05 00000>POP DWORD PTR FS:[0]
004012CE . EB 0D JMP SHORT SV_Keyge.004012DD
004012D0 > 66:3D EA03 CMP AX, 3EA
004012D4 . 75 07 JNZ SHORT SV_Keyge.004012DD
004012D6 . 6A 00 PUSH 0 ; /ExitCode = 0
004012D8 . E8 8F000000 CALL <JMP.&user32.PostQuitMessage> ; \PostQuitMessage
004012DD > EB 15 JMP SHORT SV_Keyge.004012F4
004012DF > FF75 14 PUSH DWORD PTR SS:[EBP+14] ; /lParam
004012E2 . FF75 10 PUSH DWORD PTR SS:[EBP+10] ; |wParam
004012E5 . FF75 0C PUSH DWORD PTR SS:[EBP+C] ; |Message
004012E8 . FF75 08 PUSH DWORD PTR SS:[EBP+8] ; |hWnd
004012EB . E8 40000000 CALL <JMP.&user32.DefWindowProcA> ; \DefWindowProcA
004012F0 . C9 LEAVE
004012F1 . C2 1000 RET 10
004012F4 > 33C0 XOR EAX, EAX
004012F6 . C9 LEAVE
004012F7 . C2 1000 RET 10
--------------------------------------------------------------------------------
【分析总结】
这个软件我运行了之后通过调试,发现根本没有成功的对话框
即使code是16位的,仍然一运行就跳到try again对话框上去了.
但是仔细看了一下代码
00401265 . 8D3D 68324000 LEA EDI, DWORD PTR DS:[403268]
0040126B FFD7 CALL EDI
0040126D . 6A 00 PUSH 0 ; /Style = MB_OK|MB_APPLMODAL
0040126F . 68 3B304000 PUSH SV_Keyge.0040303B ; |then ?
00401274 . 68 1C304000 PUSH SV_Keyge.0040301C ; |try again
00401279 . 6A 00 PUSH 0 ; |hOwner = NULL
0040127B . E8 E6000000 CALL <JMP.&user32.MessageBoxA> ; \MessageBoxA
00401280 . EB 42 JMP SHORT SV_Keyge.004012C4
00401282 . 8D3D 68324000 LEA EDI, DWORD PTR DS:[403268]
00401288 . 83C7 04 ADD EDI, 4
0040128B . 8B07 MOV EAX, DWORD PTR DS:[EDI]
0040128D 3B05 90364000 CMP EAX, DWORD PTR DS:[403690]
00401293 75 1C JNZ SHORT SV_Keyge.004012B1
00401295 . E8 60000000 CALL SV_Keyge.004012FA
0040129A . 68 E9030000 PUSH 3E9 ; /ControlID = 3E9 (1001.)
0040129F . FF75 08 PUSH DWORD PTR SS:[EBP+8] ; |hWnd
004012A2 . E8 9B000000 CALL <JMP.&user32.GetDlgItem> ; \GetDlgItem
004012A7 . 6A 00 PUSH 0 ; /Enable = FALSE
004012A9 . 50 PUSH EAX ; |hWnd
004012AA . E8 8D000000 CALL <JMP.&user32.EnableWindow> ; \EnableWindow
004012AF . EB 13 JMP SHORT SV_Keyge.004012C4
004012B1 > 6A 00 PUSH 0 ; /Style = MB_OK|MB_APPLMODAL
004012B3 . 68 3B304000 PUSH SV_Keyge.0040303B ; |then ?
004012B8 . 68 1C304000 PUSH SV_Keyge.0040301C ; |try again
004012BD . 6A 00 PUSH 0 ; |hOwner = NULL
004012BF . E8 A2000000 CALL <JMP.&user32.MessageBoxA> ; \MessageBoxA
发现里面有一个EnableWindow函数,这几天我一直被那几个变灰的按钮搞的头晕,我猜想,是不是
注册成功就跳转到这个EnableWindow函数上呢?但是查了半天没有看见能跳到EnableWindow这个函数
上的跳转语句.但是我注意到了这个语句
00401265 . 8D3D 68324000 LEA EDI, DWORD PTR DS:[403268]
0040126B FFD7 CALL EDI
call edi 这个语句应该是调用数据段中的数据,于是我想肯定是通过异或计算出来的结果
通过call,电脑就把那些数据理解成代码,而且应该是个段间跳转吧!
于是我通过修改汇编指令:
首先转到DS:[403268]
然后修改汇编指令jmp long 401282,看见对应的hex数据变成了E915E0FFFF
然后单步执行又跳回代码段
00401282 . 8D3D 68324000 LEA EDI, DWORD PTR DS:[403268]
00401288 . 83C7 04 ADD EDI, 4
0040128B . 8B07 MOV EAX, DWORD PTR DS:[EDI]
0040128D 3B05 90364000 CMP EAX, DWORD PTR DS:[403690]
00401293 75 1C JNZ SHORT SV_Keyge.004012B1
只是后面有一个比较语句取出计算出来的数据后四个字节
和DS:[403690]这个地方进行双字(DWORD)比较,我就纳闷了,这个DS:[403690]
好像在计算序列号的时候并没有出现过,我通过向上查看,终于看见了DS:[403690]出现
00401218 . C705 90364000>MOV DWORD PTR DS:[403690], 0FFFFFF
00401222 . C605 68324000>MOV BYTE PTR DS:[403268], 0
原来DS:[403690]的内容是00ffffff
这个说明了通过name和code计算的结果后面的四个字节中应该有00ffffff
否则的话也跳出那个按钮变灰的函数.
好了,弄清楚了算法:就是将name和code两位异或,结果前面刚好能
组成一个段间跳转语句,后面的四位刚好是00ffffff
由于按照双字取出,所以实际上要的是ffffff00
所以最终name和code异或的结果必须是
E915E0FF FFFFFF00
现在就开始计算正确的序列号:由于计算过程只有一个异或的过程很简单,并且
异或运行的逆运算也是异或,所以:
h 的ascii码值是68 xor e9 = 81
e 的ascii码值是65 xor 15 = 70
m 的ascii码值是6D xor e0 = 8d
i 的ascii码值是69 xor ff = 96
n 的ascii码值是6E xor ff = 91
r 的ascii码值是72 xor ff = 8d
u 的ascii码值是75 xor ff = 8a
i 的ascii码值是69 xor 00 = 69
组在一起就是code:81708d96918d8a69 由于只是比较数字,所以不分大小写.
--------------------------------------------------------------------------------
【版权声明】: 本文原创于看雪技术论坛, 转载请注明作者并保持文章的完整, 谢谢!
2006年09月14日 12:41:33
[培训]内核驱动高级班,冲击BAT一流互联网大厂工
作,每周日13:00-18:00直播授课
上传的附件: