首页
社区
课程
招聘
对bxm刚破的Crackme的一些探讨(逆向)
发表于: 2006-8-2 20:07 5914

对bxm刚破的Crackme的一些探讨(逆向)

2006-8-2 20:07
5914

下载地址:http://bbs.pediy.com/showthread.php?threadid=29940

使用工具:
 反编译工具:IDA,Resource Hacker
 程序开发包:MASM32

  这个程序用PEID查的结果是MASM/TASM编译的,而实际上更象是TASM:第一,代码区段的名字是CODE
而不是.text;第二,建立堆栈框架是用enter指令而不是push ebp; mov ebp, esp;第三,导入表中有
一大堆程序里并未用到的函数。

  用IDA载入程序,并且用Resource Hacker分析资源,将控件ID等常数用符号表示出来。由于这次的
反汇编内容比较长,为了不影响阅读起见,把它放在正文后面了。

  主界面是用DialogBoxParam建立的对话框,但在GetModuleHandle之后有一大段给某个WNDCLASSEX结
构体赋值的指令,让人还以为他要注册窗口类,但最后又不见调用RegisterClassEx之类的函数,这段代
码是垃圾,鉴定完毕,哈哈,不过怎么知道那是给一个WNDCLASSEX结构体赋值呢?一般来说,如果连续
出现几个mov语句,给地址是连续的几个内存单元依次赋值的话,那就很可能是在给某个结构体的各成员
赋初始值了,至于这个结构体是什么,那就看你对于一些常见的结构体是否熟悉了,比如现在给内存单
元[402138]赋的值是一个位于代码区段中的偏移量,把接着的两个双字填0以后,又接着把hInstance的
值赋给[402144],马上就应该联想到WNDCLASSEX结构体中,成员lpfnWndProc往后跳过两个成员的地方正
是成员hInstance,那就试试看这是不是个WNDCLASSEX结构体吧!lpfnWndProc成员在WNDCLASSEX中的偏
移是8,那么结构体的首地址应该在402138 - 8 = 402130的地方,让IDA把这个地址开始的一片区域分析
成一个WNDCLASSEX结构,再回到这段代码的地方一看,果然下面装载图标、装载光标所得的结果都被赋
给了正确的字段,从而证实我们的猜测。与之同样道理,下面的GetMessage中也可以把地址402118开始
的地方分析成一个MSG结构体,不过这样的话这个结构体的最后一个字段跟刚才的WNDCLASSEX结构体的第
一个字段cbsize发生重叠,不可能两方面都顾全,反正这也是段无用代码,随它去吧!

  罗嗦了那么多,现在继续跟踪流程,DialogBoxParam函数结束以后是一个jmp指令,跳到的地方(即
loc_4010C7标号处)先是进行一些出栈操作然后ret返回,难道程序是用这种方式结束并返回到操作系统
的?但为什么返回之前又要pop呢,程序开始运行的地方并没有对应的push操作呀!这难道不会引起堆栈
不平衡而导致返回地址错误吗?跟进对话框过程里可以发现,当对话框决定结束的时候,不是象通常那
样调用EndDialog,而是直接调用ExitProcess来个一了百了,也就是说,不会等到DialogBoxParam返回
的时候,整个进程就结束了;并且ExitProcess调用的时候甚至连uExitCode参数都懒得给,直接用当前
的[esp]值做这个参数,如果用调试器跟踪就会发现这个uExitCode的值是些象12FB74之类的奇怪数值,
他的逻辑就是管你什么堆栈不平衡,我退出进程的时候反正把我用的堆栈都释放掉了,你能奈我何!虽
然还不至于引起系统崩溃,但这种编程风格实在太差,在源码里我将其改成了常规的流程。

  在对话框过程的WM_INITDIALOG消息处理分支里也是直接返回TRUE,让Windows把输入焦点设置到第
一个定义了WS_VISIBLE | WS_TABSTOP的控件上,在资源脚本里这个控件是Close按钮,这似乎有点不同
于常识,若不喜欢,可以自行调整资源脚本中的控件顺序。

  验证注册码的算法是:用户名不能超过8个字符,只能由字母组成,程序中将其转为大写字母,然后
依次读取用户名的每个字符并到一个串

       szIndex = "A1LSK2DJF4HGP3QWO5EIR6UTYZ8MXN7CBV9"

中找到这个字符所在的位置,然后把串

     szTable = "SU7CSJKF09NCSDO9SDF09SDRLVK7809S4NF"

中对应位置的字符写入到szUnlockCode中(相当于换码),这样处理完整个用户名以后,szUnlockCode
中就是真正的序列号了;然后将输入的序列号与之进行比较。例如:

     用户名:PEDIY
     在szIndex中找到这五个字母,然后看szTable中对应位置的字符:
     序列号:SFK0L

但是注意验证流程中的两点:

  第一,程序只把小于'A'及大于'z'的字符判为非法输入,其他判为合法,这其中就包括小于'a'但大
于'Z'的字符,譬如我输入字符'\',它的ASCII码为5Ch,不会被判非法,按照验证的逻辑应该减去20h变
成字符'<',但是在szIndex中无法找到这个字符,也就是说,这种用户名虽然合法但不可能有对应的序
列号,这也算是个Bug。在源码里我把合法输入的范围严格限定为字母了;

  第二,从szTable取字符到szUnlockCode中属于字节操作,那就应该直接用一个8位寄存器中转,而
没有必要先扩展到eax然后用eax来中转,容易引起误解。

  另外,由于输入只能是字母,szIndex中的数字就显得多余了,去掉这些数字,最好顺便把szIndex
调整成顺序字母表,当然要同时调整szTable,如下:

    szIndex = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
        szTable = "S4SKF0CN0FS770SSO9CRDN98LV"

这样一来,甚至于szIndex都没有存在的意义了,因为当用到一个字母的索引时,只需要用这个字母减去
'A'就可以了。代码就可以进一步优化。

  上传文件内容:1.asm 按上述讨论整理过的源码(含注册机条件汇编)
                  1.rc  资源脚本
                  2.rc  注册机资源脚本
                  Icon_1.ico 图标

===========================以下是代码========================
;分析资源得出
; enum Control_IDs
DLG_MAIN         = 1
ICO_MAIN         = 1
ID_CHECK         = 1
ID_CLOSE         = 2
EDT_NAME         = 3
EDT_SERIAL         = 4

                public start
start                proc near
                push        NULL                ; lpModuleName
                call        GetModuleHandleA
                mov        ds:hInstance, eax
                mov        ds:stMyclass.style, CS_VREDRAW or CS_HREDRAW or        CS_GLOBALCLASS
                mov        ds:stMyclass.lpfnWndProc, offset sub_4010AB
                mov        ds:stMyclass.cbClsExtra, 0
                mov        ds:stMyclass.cbWndExtra, 0
                mov        eax, ds:hInstance
                mov        ds:stMyclass.hInstance,        eax
                push        ICO_MAIN        ; lpIconName
                push        eax                ; hInstance
                call        LoadIconA
                mov        ds:stMyclass.hIcon, eax
                push        IDC_ARROW        ; lpCursorName
                push        NULL                ; hInstance
                call        LoadCursorA
                mov        ds:stMyclass.hCursor, eax
                push        0                ; dwInitParam
                push        offset _ProcDlgMain ; lpDialogFunc
                push        NULL                ; hWndParent
                push        DLG_MAIN        ; lpTemplateName
                push        ds:hInstance        ; hInstance
                call        DialogBoxParamA
                jmp        short loc_4010C7
start                endp

loc_401074:                                ; CODE XREF: CODE:0040109Ej
                push        0
                push        0
                push        0
                push        offset stMyMsg
                call        GetMessageA
                cmp        ax, 0
                jz        short loc_4010A0
                push        offset stMyMsg
                call        TranslateMessage
                push        offset stMyMsg
                call        DispatchMessageA
                jmp        short loc_401074

loc_4010A0:                                ; CODE XREF: CODE:00401088j
                push        dword ptr ds:unk_402120
                call        ExitProcess

; int __stdcall        sub_4010AB(HWND        hWnd,UINT Msg,WPARAM wParam,LPARAM lParam)
sub_4010AB        proc near                ; DATA XREF: start+16o

hWnd                = dword        ptr  8
Msg                = dword        ptr  0Ch
wParam                = dword        ptr  10h
lParam                = dword        ptr  14h

                enter        0, 0
                push        esi
                push        edi
                push        ebx
                jmp        short $+2
                push        [ebp+lParam]        ; lParam
                push        [ebp+wParam]        ; wParam
                push        [ebp+Msg]        ; Msg
                push        [ebp+hWnd]        ; hWnd
                call        DefWindowProcA
                jmp        short $+2

loc_4010C7:                                ; CODE XREF: start+72j
                pop        ebx
                pop        edi
                pop        esi
                leave
                retn        10h
sub_4010AB        endp

;对话框过程
; BOOL __stdcall ProcDlgMain(HWND hWnd,UINT uMsg,WPARAM        wParam,LPARAM lParam)
_ProcDlgMain        proc near                ; DATA XREF: start+5Eo

hWnd                = dword        ptr  8
uMsg                = dword        ptr  0Ch
wParam                = dword        ptr  10h
lParam                = dword        ptr  14h

                enter        0, 0
                push        ebx
                push        esi
                push        edi
                jmp        short loc_4010F4

loc_4010D7:                                ; CODE XREF: _ProcDlgMain+125j
                push        MB_TASKMODAL        ; uType
                push        offset szCaption ; "Duelist's Crackme #4"
                push        offset szTxtRegSucc ; "Congratulations!        Please send your keyge"...
                push        NULL                ; hWnd
                call        MessageBoxA
                mov        eax, TRUE
                jmp        short loc_401119

loc_4010F4:                                ; CODE XREF: _ProcDlgMain+7j
                cmp        [ebp+uMsg], WM_COMMAND
                jz        loc_4011FB
                cmp        [ebp+uMsg], WM_INITDIALOG
                jz        short loc_401120
                cmp        [ebp+uMsg], WM_CLOSE
                jz        loc_40120B
                mov        eax, 0

loc_401119:                                ; CODE XREF: _ProcDlgMain+24j
                                        ; _ProcDlgMain+57j ...
                pop        edi
                pop        esi
                pop        ebx
                leave
                retn        10h                ; uExitCode

loc_401120:                                ; CODE XREF: _ProcDlgMain+3Aj
                mov        eax, TRUE
                jmp        short loc_401119

loc_401127:                                ; CODE XREF: _ProcDlgMain+131j
                push        0                ; lParam
                push        0                ; wParam
                push        WM_GETTEXTLENGTH ; Msg
                push        EDT_NAME        ; nIDDlgItem
                push        [ebp+hWnd]        ; hDlg
                call        SendDlgItemMessageA
                mov        ds:uNameLen, eax
                cmp        eax, 0
                jz        badboy
                cmp        eax, 8
                jg        badboy
                mov        esi, eax
                push        0                ; lParam
                push        0                ; wParam
                push        WM_GETTEXTLENGTH ; Msg
                push        EDT_SERIAL        ; nIDDlgItem
                push        [ebp+hWnd]        ; hDlg
                call        SendDlgItemMessageA
                cmp        eax, 0
                jz        badboy
                cmp        esi, eax
                jnz        badboy
                push        offset szUserName ; lParam
                push        8                ; wParam
                push        WM_GETTEXT        ; Msg
                push        EDT_NAME        ; nIDDlgItem
                push        [ebp+hWnd]        ; hDlg
                call        SendDlgItemMessageA
                push        offset szSerial        ; lParam
                push        10h                ; wParam
                push        WM_GETTEXT        ; Msg
                push        EDT_SERIAL        ; nIDDlgItem
                push        [ebp+hWnd]        ; hDlg
                call        SendDlgItemMessageA
                mov        ecx, -1

loc_40119C:                                ; CODE XREF: _ProcDlgMain+10Bj
                inc        ecx
                movsx        eax, ds:szUserName[ecx]
                cmp        eax, 0                ; 是否已到达串尾
                jz        short loc_4011DB
                mov        esi, -1
                cmp        eax, 'A'
                jl        short badboy
                cmp        eax, 'z'
                ja        short badboy
                cmp        eax, 'Z'
                jl        short loc_4011C0
                sub        eax, 20h        ; 转大写字母

loc_4011C0:                                ; CODE XREF: _ProcDlgMain+EDj
                                        ; _ProcDlgMain+FCj
                inc        esi
                movsx        edx, byte ptr ds:szIndex[esi] ;        "A1LSK2DJF4HGP3QWO5EIR6UTYZ8MXN7CBV9"
                cmp        eax, edx
                jnz        short loc_4011C0
                movsx        eax, byte ptr ds:szTable[esi] ;        "SU7CSJKF09NCSDO9SDF09SDRLVK7809S4NF"
                mov        ds:szUnlockCode[ecx], eax
                jmp        short loc_40119C

loc_4011DB:                                ; CODE XREF: _ProcDlgMain+D9j
                push        ds:uNameLen
                push        offset szUnlockCode
                push        offset szSerial
                call        sub_401244        ; 比较上面二个字符串
                cmp        eax, 1
                jz        loc_4010D7
                jmp        short badboy

loc_4011FB:                                ; CODE XREF: _ProcDlgMain+2Dj
                cmp        [ebp+wParam], ID_CHECK
                jz        loc_401127
                cmp        [ebp+wParam], ID_CLOSE
                jnz        short loc_40123A

loc_40120B:                                ; CODE XREF: _ProcDlgMain+40j
                call        ExitProcess
                mov        eax, 1
                jmp        loc_401119

badboy:                                        ; CODE XREF: _ProcDlgMain+71j
                                        ; _ProcDlgMain+7Aj ...
                push        MB_TASKMODAL        ; uType
                push        offset szCaption ; "Duelist's Crackme #4"
                push        offset szTxtRegFail ; "Your registration info is invalid... No"...
                push        NULL                ; hWnd
                call        MessageBoxA
                mov        eax, 0
                jmp        loc_401119

loc_40123A:                                ; CODE XREF: _ProcDlgMain+13Bj
                mov        eax, 0
                jmp        loc_401119
_ProcDlgMain        endp

sub_401244        proc near                ; CODE XREF: _ProcDlgMain+11Dp

arg_0                = dword        ptr  8
arg_4                = dword        ptr  0Ch
arg_8                = dword        ptr  10h

                enter        0, 0
                mov        eax, 1
                mov        edi, [ebp+arg_0]
                mov        esi, [ebp+arg_4]
                mov        ecx, [ebp+arg_8]
                repe cmpsb
                jcxz        locret_401260
                mov        eax, 0

locret_401260:                                ; CODE XREF: sub_401244+14j
                leave
                retn        0Ch
sub_401244        endp

DATA                segment        para public 'DATA' use32
                assume cs:DATA
                ;org 402000h
                db  20h
; char szCaption[]
szCaption        db 'Duelist',27h,'s Crackme #4',0 ; DATA XREF: _ProcDlgMain+Eo
                                        ; _ProcDlgMain+151o
                db  20h
szIndex                db 'A1LSK2DJF4HGP3QWO5EIR6UTYZ8MXN7CBV9',0 ; DATA XREF: _ProcDlgMain+F3r
                db  20h
szTable                db 'SU7CSJKF09NCSDO9SDF09SDRLVK7809S4NF',0 ; DATA XREF: _ProcDlgMain+FEr
                db  20h
; char szTxtRegSucc[]
szTxtRegSucc        db 'Congratulations! Please send your keygen (working one) to du'
                                        ; DATA XREF: _ProcDlgMain+13o
                db 'elist@beer.com!',0
                db  20h
; char szTxtRegFail[]
szTxtRegFail        db 'Your registration info is invalid... Note that most of the s'
                                        ; DATA XREF: _ProcDlgMain+156o
                db 'pecial chars may raise registration problems!',0
stMyMsg                db    0                        ; DATA XREF: CODE:0040107Ao
                                        ; CODE:0040108Ao ...
                db    0
                db    0
                db    0
                db    0
                db    0
                db    0
                db    0
unk_402120        db    0                        ; DATA XREF: CODE:loc_4010A0r
                db    0
                db    0
                db    0
                db    0
                db    0
                db    0
                db    0
                db    0
                db    0
                db    0
                db    0
                db    0
                db    0
                db    0
                db    0
stMyclass        WNDCLASSEX <0>                ; DATA XREF: start+Cw start+16w ...
szUserName        db    19h dup (0)        ; DATA XREF: _ProcDlgMain+A3o

szSerial        db    1Bh dup (0)        ; DATA XREF: _ProcDlgMain+B6o
                                        ; _ProcDlgMain+118o

szUnlockCode        dd 0                        ; DATA XREF: _ProcDlgMain+105w
                                        ; _ProcDlgMain+113o
                db    0
                db    0
                db    0
                db    0
                db    0
                db    0
                db    0
                db    0
                db    0
                db    0
                db    0
                db    0
                db    0
                db    0
                db    0
                db    0
                db    0
                db    0
                db    0
; HINSTANCE hInstance
hInstance        dd 0                        ; DATA XREF: start+7w start+34r ...
uNameLen        dd 0                        ; DATA XREF: _ProcDlgMain+69w
                                        ; _ProcDlgMain:loc_4011DBr
===========================以上是代码========================


[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

上传的附件:
收藏
免费 7
支持
分享
最新回复 (4)
雪    币: 461
活跃值: (93)
能力值: ( LV9,RANK:1170 )
在线值:
发帖
回帖
粉丝
2
好文章,可惜我看得不是太懂,至今IDA也不会用.
2006-8-2 20:57
0
雪    币: 433
活跃值: (176)
能力值: ( LV13,RANK:1250 )
在线值:
发帖
回帖
粉丝
3
那个顺序字母表中还缺个字母W,现在已修正
2006-8-2 22:03
0
雪    币: 235
活跃值: (10)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
4
让IDA把这个地址开始的一片区域分析
成一个WNDCLASSEX结构


IDA刚开始接触,请问上面那一步如何操作?
感谢楼主的无私奉献!
2006-8-2 23:19
0
雪    币: 433
活跃值: (176)
能力值: ( LV13,RANK:1250 )
在线值:
发帖
回帖
粉丝
5
最初由 Vcsoft 发布
IDA刚开始接触,请问上面那一步如何操作?
感谢楼主的无私奉献!


首先要在结构体窗口中添加标准结构体WNDCLASSEX
然后反汇编窗口中选中首地址
选择菜单项Edit -> Struct var...
弹出一个窗口,里面就有WNDCLASSEX了
2006-8-3 14:08
0
游客
登录 | 注册 方可回帖
返回
//