-
-
逆向jdxyw刚破的那个CrackMe――顺便与jdxyw商榷分析的正确性
-
发表于:
2006-7-29 23:27
5587
-
逆向jdxyw刚破的那个CrackMe――顺便与jdxyw商榷分析的正确性
下载地址:不用多说了吧
使用工具:
反编译工具:IDA,Resource Hacker
程序开发包:MASM32
既然jdxyw都说没壳,我就毫不客气地直接用IDA加载了,如同往常那样,主程序也是三步曲:
GetModuleHandle ---> DialogBoxParam ---> ExitProcess
通过DialogBoxParam中的对话框过程指针参数找到对话框过程:
==========================================================
CODE:00401029 ; Attributes: bp-based frame
CODE:00401029
CODE:00401029 ; BOOL __stdcall DialogFunc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
CODE:00401029 DialogFunc proc near ; DATA XREF: start+Eo
CODE:00401029
CODE:00401029 hWnd = dword ptr 8
CODE:00401029 uMsg = dword ptr 0Ch
CODE:00401029 wParam = dword ptr 10h
CODE:00401029 lParam = dword ptr 14h
CODE:00401029
CODE:00401029 enter 0, 0
CODE:0040102D cmp [ebp+uMsg], WM_COMMAND
CODE:00401034 jnz short loc_40103D
CODE:00401036 call sub_401056
CODE:0040103B jmp short loc_401050
CODE:0040103D
CODE:0040103D loc_40103D: ; CODE XREF: DialogFunc+Bj
CODE:0040103D cmp [ebp+uMsg], WM_DESTROY
CODE:00401041 jnz short loc_40104A
CODE:00401043 call sub_40112D
CODE:00401048 jmp short loc_401050
CODE:0040104A
CODE:0040104A loc_40104A: ; CODE XREF: DialogFunc+18j
CODE:0040104A xor eax, eax
CODE:0040104C leave
CODE:0040104D retn 10h
CODE:00401050
CODE:00401050 loc_401050: ; CODE XREF: DialogFunc+12j
CODE:00401050 ; DialogFunc+1Fj
CODE:00401050 xor eax, eax
CODE:00401052 leave
CODE:00401053 retn 10h
CODE:00401053 DialogFunc endp
CODE:00401053
CODE:00401056
CODE:00401056
CODE:00401056
CODE:00401056 sub_401056 proc near ; CODE XREF: DialogFunc+Dp
CODE:00401056 cmp dword ptr [ebp+10h], ID_CHECK
CODE:0040105A jz short loc_40106C
CODE:0040105C cmp dword ptr [ebp+10h], 2
CODE:00401060 jz sub_40112D
CODE:00401066 xor eax, eax
CODE:00401068 leave
CODE:00401069 retn 10h
CODE:0040106C
CODE:0040106C loc_40106C: ; CODE XREF: sub_401056+4j
CODE:0040106C push 25h ; nMaxCount
CODE:0040106E push offset szSerialString ; lpString
CODE:00401073 push EDT_SERIAL ; nIDDlgItem
CODE:00401075 push dword ptr [ebp+8] ; hDlg
CODE:00401078 call GetDlgItemTextA
CODE:0040107D push 0 ; nFileSystemNameSize
CODE:0040107F push NULL ; lpFileSystemNameBuffer
CODE:00401081 push offset FileSystemFlags ; lpFileSystemFlags
CODE:00401086 push offset MaximumComponentLength ; lpMaximumComponentLength
CODE:0040108B push offset VolumeSerialNumber ; lpVolumeSerialNumber
CODE:00401090 push 32h ; nVolumeNameSize
CODE:00401092 push offset szVolNamCurDsk ; lpVolumeNameBuffer
CODE:00401097 push NULL ; lpRootPathName
CODE:00401099 call GetVolumeInformationA
CODE:0040109E push offset String2 ; "4562-ABEX"
CODE:004010A3 push offset szVolNamCurDsk ; lpString1
CODE:004010A8 call lstrcatA
CODE:004010AD mov dl, 2
CODE:004010AF
CODE:004010AF loc_4010AF: ; CODE XREF: sub_401056+77j
CODE:004010AF add ds:szVolNamCurDsk, 1
CODE:004010B6 add ds:szVolNamCurDsk+1, 1
CODE:004010BD add ds:szVolNamCurDsk+2, 1
CODE:004010C4 add ds:szVolNamCurDsk+3, 1
CODE:004010CB dec dl
CODE:004010CD jnz short loc_4010AF
CODE:004010CF push offset aL2c5781 ; "L2C-5781"
CODE:004010D4 push offset String1 ; lpString1
CODE:004010D9 call lstrcatA
CODE:004010DE push offset szVolNamCurDsk ; lpString2
CODE:004010E3 push offset String1 ; lpString1
CODE:004010E8 call lstrcatA
CODE:004010ED push offset szSerialString ; lpString2
CODE:004010F2 push offset String1 ; lpString1
CODE:004010F7 call lstrcmpiA
CODE:004010FC cmp eax, 0
CODE:004010FF jz short loc_401117
CODE:00401101 push MB_OK ; uType
CODE:00401103 push offset Caption ; "Error!"
CODE:00401108 push offset Text ; "The serial you entered is not correct!"
CODE:0040110D push dword ptr [ebp+8] ; hWnd
CODE:00401110 call MessageBoxA
CODE:00401115 jmp short sub_40112D
CODE:00401117
CODE:00401117 loc_401117: ; CODE XREF: sub_401056+A9j
CODE:00401117 push MB_OK ; uType
CODE:00401119 push offset aWellDone ; "Well Done!"
CODE:0040111E push offset aYepYouEnteredA ; "Yep, you entered a correct serial!"
CODE:00401123 push dword ptr [ebp+8] ; hWnd
CODE:00401126 call MessageBoxA
CODE:0040112B jmp short $+2
CODE:0040112B sub_401056 endp
CODE:0040112B
CODE:0040112D
CODE:0040112D ; 圹圹圹圹圹圹圹?S U B R O U T I N E 圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹?
CODE:0040112D
CODE:0040112D
CODE:0040112D sub_40112D proc near ; CODE XREF: DialogFunc+1Ap
CODE:0040112D ; sub_401056+Aj ...
CODE:0040112D push 0 ; nResult
CODE:0040112F push dword ptr [ebp+8] ; hDlg
CODE:00401132 call EndDialog
CODE:00401137 leave
CODE:00401138 retn 10h
CODE:00401138 sub_40112D endp ; sp = 4
==========================================================
作者写代码的时候似乎不太规范,消息处理分支的时候用的不是jmp跳转而是call调用,造成多压
进堆栈一个双字,以致到最后返回的时候IDA还误以为堆栈不平衡(当然这对于使用堆栈框架的子
程序返回没有影响)。不过这都不是什么大问题,接下来就是分析消息处理过程……分析API的参
数……用ResHacker分析资源……符号常量定义……等等例行的手续,等这些工作做完以后,源代
码就基本成形,只等你用文本编辑器打进去了。(说明一下:分析API的时候最好自己装个MSDN
Library,这样当碰到API中用数值表示的参数时,就可以到MSDN里查看这个参数的意义,从而快
速找到与之等值的符号常量。例如:如果有
push 0
push 80h
push 3
push 0
push 1
push 80000000h
push offset szFileName
call CreateFileA
这些数值80000000h, 1, 3……代表什么意思呢?通过查MSDN我了解到CreateFile的第二个参数可
以是GENERIC_READ或者GENERIC_WRITE,那么我就在80000000h这个常量上右击选择
“Use Symbolic Constants”,在弹出的常量列表里去找以“GENERIC_”开头的符号,很快就能
找到GENERIC_READ = 80000000h;同样可以找到其他数值的等值符号,从而把上面的调用还原成
源代码的形式:
invoke CreateFile, offset szFileName, GENERIC_READ, FILE_SHARE_READ, \
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL
总之这是遵循一个原则:在规范的程序中应尽量少出现数值形式的常量)
由于程序是采用明码比较方式的,可以顺便做个注册机条件汇编,当程序中生成真注册码的
时候把它显示到文本框中,就成为一个对应的注册机了。还有一些其他话,我都写在源代码注释
里了。
关键是:注意生成真码的过程,首先取得程序所在的驱动器(GetVolumeInformation的第一
个参数为NULL时默认如此)的卷标名,然后在这个卷标名后添加常量字符串"4562-ABEX",添加
完了以后把前4个字符各加上2,再在所得的串头部加上常量字符串L2C-5781,得到真正的注册
码。如果卷标名是空字符串,那么情况就如jdxyw所说的那样,这四个2都加在了"4562"上,变成
"6784"。但如果卷标名不为空时就不是这样了,如笔者所用的机器D:盘的卷标名是"user",经过
第一步操作时变成"user4562-ABEX",这四个2是加在了"user"上面,变成了"wugt4562-ABEX",
最后生成的真码是"L2C-5781wugt4562-ABEX"。另外注意到最后比较的时候用的是lstrcmpi函数,
这个函数不管大小写,所以诸如"l2c-5781WUGT4562-abex"、"l2C-5781wUgT4562-aBeX"之类的输
入都是合法的。
上传文件内容:Noname2.asm MASM源程序(含注册机条件汇编)
1.rc 原来的程序用的资源脚本
2.rc 注册机用的资源脚本
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课