首页
社区
课程
招聘
[原创]KeyGenMe的菜鸟级破文
发表于: 2007-1-17 18:52 8460

[原创]KeyGenMe的菜鸟级破文

2007-1-17 18:52
8460

【文章标题】: 菜鸟就吃个软柿子
【文章作者】: benbentaiyang
【作者邮箱】: **
【作者主页】: **
【作者QQ号】: 40597503
【软件名称】: KeyGenMe.exe
【软件大小】: 14.5
【下载地址】: 看雪crackeme专区
【加壳方式】: 无
【保护方式】: 无
【编写语言】: Win32汇编
【使用工具】: OD,WinHex,peid,reshacker,Stud_PE
【操作平台】: xp
【软件介绍】: 一个CrackeMe,使用远线程,MD5算法,但明文比较.
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
  菜鸟级破文,只求能看懂.属入门级,高手飘过!废话不说了,开始正题.
  下载这个CrackeMe,作者自己介绍无壳,无Anti,等等.
  用Peid查看,无壳,情况属实.
  然后用OD载入,无加密提示,也说明了没有加壳.F9,运行,无退出,死机,异常,检查结束,作者比较厚道,所述情况属实.
  主进程如下:
  131416D9 >/$  6A 00         push    0                                ; /pModule = NULL
  131416DB  |.  FF15 20201413 call    dword ptr [<&kernel32.GetModuleH>; \GetModuleHandleA
  131416E1  |.  A3 E1361413   mov     dword ptr [131436E1], eax
  131416E6      8BF8          mov     edi, eax
  131416E8      037F 3C       add     edi, dword ptr [edi+3C]
  131416EB  |.  83C7 04       add     edi, 4
  131416EE  |.  83C7 14       add     edi, 14
  131416F1  |.  8B47 38       mov     eax, dword ptr [edi+38]
  131416F4      A3 ED361413   mov     dword ptr [131436ED], eax
  131416F9  |.  68 05010000   push    105                              ; /BufSize = 105 (261.)
  131416FE  |.  8D05 8C321413 lea     eax, dword ptr [1314328C]        ; |
  13141704  |.  50            push    eax                              ; |PathBuffer => KeyGenMe.1314328C
  13141705  |.  6A 00         push    0                                ; |hModule = NULL
  13141707  |.  FF15 28201413 call    dword ptr [<&kernel32.GetModuleF>; \GetModuleFileNameA
  1314170D  |.  68 28010000   push    128                              ; /Length = 128 (296.)
  13141712  |.  8D05 01371413 lea     eax, dword ptr [13143701]        ; |
  13141718  |.  50            push    eax                              ; |Destination => KeyGenMe.13143701
  13141719  |.  FF15 24201413 call    dword ptr [<&kernel32.RtlZeroMem>; \RtlZeroMemory
  1314171F  |.  C705 01371413>mov     dword ptr [13143701], 128
  13141729  |.  8D05 01371413 lea     eax, dword ptr [13143701]
  1314172F  |.  50            push    eax                              ; /ProcessID => 13143701
  13141730  |.  6A 02         push    2                                ; |Flags = TH32CS_SNAPPROCESS
  13141732  |.  FF15 2C201413 call    dword ptr [<&kernel32.CreateTool>; \CreateToolhelp32Snapshot
  13141738  |.  A3 FD361413   mov     dword ptr [131436FD], eax
  1314173D  |.  8D05 01371413 lea     eax, dword ptr [13143701]
  13141743  |.  50            push    eax                              ; /pProcessentry => KeyGenMe.13143701
  13141744  |.  FF35 FD361413 push    dword ptr [131436FD]             ; |hSnapshot = NULL
  1314174A  |.  FF15 30201413 call    dword ptr [<&kernel32.Process32F>; \Process32First
  13141750  |.  EB 44         jmp     short 13141796
  13141752  |>  8D05 25371413 /lea     eax, dword ptr [13143725]
  13141758  |.  50            |push    eax                             ; /StringOrChar => ""
  13141759  |.  FF15 A8201413 |call    dword ptr [<&user32.CharLowerA>>; \CharLowerA
  1314175F  |.  8D05 25371413 |lea     eax, dword ptr [13143725]
  13141765  |.  50            |push    eax                             ; /String2 => ""
  13141766  |.  8D05 51321413 |lea     eax, dword ptr [13143251]       ; |
  1314176C  |.  50            |push    eax                             ; |String1 => "explorer.exe"
  1314176D  |.  FF15 34201413 |call    dword ptr [<&kernel32.lstrcmpA>>; \lstrcmpA
  13141773  |.  0BC0          |or      eax, eax
  13141775  |.  75 0C         |jnz     short 13141783
  13141777  |.  FF35 09371413 |push    dword ptr [13143709]
  1314177D  |.  8F05 F1361413 |pop     dword ptr [131436F1]
  13141783  |>  8D05 01371413 |lea     eax, dword ptr [13143701]
  13141789  |.  50            |push    eax                             ; /pProcessentry => KeyGenMe.13143701
  1314178A  |.  FF35 FD361413 |push    dword ptr [131436FD]            ; |hSnapshot = NULL
  13141790  |.  FF15 38201413 |call    dword ptr [<&kernel32.Process32>; \Process32Next
  13141796  |>  0BC0           or      eax, eax
  13141798  |.^ 75 B8         \jnz     short 13141752
  1314179A  |.  FF35 F1361413 push    dword ptr [131436F1]             ; /ProcessId = 0
  131417A0  |.  6A 00         push    0                                ; |Inheritable = FALSE
  131417A2  |.  6A 2A         push    2A                               ; |Access = CREATE_THREAD|VM_OPERATION|VM_WRITE
  131417A4  |.  FF15 3C201413 call    dword ptr [<&kernel32.OpenProces>; \OpenProcess
  131417AA  |.  A3 E9361413   mov     dword ptr [131436E9], eax
  131417AF  |.  68 00800000   push    8000
  131417B4  |.  6A 00         push    0
  131417B6  |.  FF35 E1361413 push    dword ptr [131436E1]
  131417BC  |.  FF35 E9361413 push    dword ptr [131436E9]
  131417C2  |.  FF15 40201413 call    dword ptr [<&kernel32.VirtualFre>;  kernel32.VirtualFreeEx
  131417C8  |.  6A 40         push    40
  131417CA  |.  68 00300000   push    3000
  131417CF  |.  FF35 ED361413 push    dword ptr [131436ED]
  131417D5  |.  FF35 E1361413 push    dword ptr [131436E1]
  131417DB  |.  FF35 E9361413 push    dword ptr [131436E9]
  131417E1  |.  FF15 44201413 call    dword ptr [<&kernel32.VirtualAll>;  kernel32.VirtualAllocEx
  131417E7  |.  A3 E5361413   mov     dword ptr [131436E5], eax
  131417EC  |.  8D05 F5361413 lea     eax, dword ptr [131436F5]
  131417F2  |.  50            push    eax                              ; /pBytesWritten => KeyGenMe.131436F5
  131417F3  |.  FF35 ED361413 push    dword ptr [131436ED]             ; |BytesToWrite = 0
  131417F9  |.  FF35 E1361413 push    dword ptr [131436E1]             ; |Buffer = NULL
  131417FF  |.  FF35 E5361413 push    dword ptr [131436E5]             ; |Address = 0
  13141805  |.  FF35 E9361413 push    dword ptr [131436E9]             ; |hProcess = NULL
  1314180B  |.  FF15 48201413 call    dword ptr [<&kernel32.WriteProce>; \WriteProcessMemory
  13141811  |.  8D05 F9361413 lea     eax, dword ptr [131436F9]
  13141817  |.  50            push    eax
  13141818  |.  6A 00         push    0
  1314181A  |.  FF35 E1361413 push    dword ptr [131436E1]
  13141820  |.  8D05 94151413 lea     eax, dword ptr [13141594]
  13141826  |.  50            push    eax
  13141827  |.  6A 00         push    0
  13141829  |.  6A 00         push    0
  1314182B  |.  FF35 E9361413 push    dword ptr [131436E9]
  13141831  |.  FF15 4C201413 call    dword ptr [<&kernel32.CreateRemo>;  kernel32.CreateRemoteThread
  13141837  |.  6A 00         push    0                                ; /ExitCode = 0
  13141839  \.  FF15 50201413 call    dword ptr [<&kernel32.ExitProces>; \ExitProcess
  
  
  看以上代码,没有什么特别地方,大体意思是先获得本句柄,然后取得当前进程列表,接着查找explorer.exe进程,打开,从里面分配一些内存,给将来的线程使用.也就是说将来的线程是注入到explorer.exe进程中,这些我们暂且不用关心.我们主要看一下这个地方:
  13141820  |.  8D05 94151413 lea     eax, dword ptr [13141594]
  13141826  |.  50            push    eax
  13141827  |.  6A 00         push    0
  13141829  |.  6A 00         push    0
  1314182B  |.  FF35 E9361413 push    dword ptr [131436E9]
  13141831  |.  FF15 4C201413 call    dword ptr [<&kernel32.CreateRemo>;  kernel32.CreateRemoteThread
  
  这个是在程序退出之前的创建的远程线程,这个函数具体参数可以查API,因为谁也不可能背过所有的API函数,^_^. 查过函数之后我们可以知道,push eax压入的这个参数是远线程的入口地址,往上看,lea     eax, dword ptr [13141594],呵呵,eax原来就是13141594.
  也就是窗口,注册什么的那些乱七八糟的代码都是从那里开始执行的,而这里只是铺垫.
  开始我也是没办法用OD调试,只能看看静态的反汇编代码了.还好,因为是win32汇编写的,反汇编后几乎跟源码没有区别,高兴!
  先找错误提示,
  1314151E   . /75 1E         jnz     short 1314153E
  13141520   . |6A 40         push    40                               ; /Style = MB_OK|MB_ICONASTERISK|MB_APPLMODAL
  13141522   . |8D05 43341413 lea     eax, dword ptr [13143443]        ; |
  13141528   . |50            push    eax                              ; |Title => "Congratulation"
  13141529   . |8D05 52341413 lea     eax, dword ptr [13143452]        ; |
  1314152F   . |50            push    eax                              ; |Text => "yes...You Got It!!"
  13141530   . |FF35 ED341413 push    dword ptr [131434ED]             ; |hOwner = NULL
  13141536   . |FF15 70201413 call    dword ptr [<&user32.MessageBoxA>>; \MessageBoxA
  1314153C   . |EB 17         jmp     short 13141555
  1314153E   > \6A 00         push    0                                ; /Style = MB_OK|MB_APPLMODAL
  13141540   .  6A 00         push    0                                ; |Title = NULL
  13141542   .  8D05 65341413 lea     eax, dword ptr [13143465]        ; |
  13141548   .  50            push    eax                              ; |Text => "hmm..maybe something worry..try again...:)"
  13141549   .  FF35 ED341413 push    dword ptr [131434ED]             ; |hOwner = NULL
  1314154F   .  FF15 70201413 call    dword ptr [<&user32.MessageBoxA>>; \MessageBoxA
  
  呵呵,经典的错误和正确并列,真理跟缪误之间就差一个选择--跳转.呵呵,改掉这个
  1314151E   . /75 1E         jnz     short 1314153E
  就可以品尝到爆破的快乐,呵呵,这也太简单了,相信你不会就此停步,因为这样也太没意思了,人家作者说了没做什么防范的,人家厚的,你也得厚道点,那我们接着往下看.
  131414B3   .  FF15 B8201413 call    dword ptr [131420B8]             ;  KeyGenMe.13141215
  131414B9   .  68 00020000   push    200                              ; /Count = 200 (512.)
  131414BE   .  8D05 69351413 lea     eax, dword ptr [13143569]        ; |
  131414C4   .  50            push    eax                              ; |Buffer => KeyGenMe.13143569
  131414C5   .  6A 03         push    3                                ; |ControlID = 3
  131414C7   .  FF75 08       push    dword ptr [ebp+8]                ; |hWnd
  131414CA   .  FF15 74201413 call    dword ptr [<&user32.GetDlgItemTe>; \GetDlgItemTextA
  131414D0   .  50            push    eax                              ; /Arg2
  131414D1   .  8D05 69351413 lea     eax, dword ptr [13143569]        ; |
  131414D7   .  50            push    eax                              ; |Arg1 => 13143569
  131414D8   .  FF15 BC201413 call    dword ptr [131420BC]             ; \KeyGenMe.13141087
  131414DE   .  50            push    eax                              ; /<%s>
  131414DF   .  68 C0341413   push    131434C0                         ; |Format = "%s",CR,LF,""
  131414E4   .  68 DD351413   push    131435DD                         ; |s = KeyGenMe.131435DD
  131414E9   .  E8 64030000   call    <jmp.&user32.wsprintfA>          ; \wsprintfA
  131414EE   .  83C4 0C       add     esp, 0C
  131414F1   .  68 00020000   push    200                              ; /Count = 200 (512.)
  131414F6   .  8D05 05351413 lea     eax, dword ptr [13143505]        ; |
  131414FC   .  50            push    eax                              ; |Buffer => KeyGenMe.13143505
  131414FD   .  6A 04         push    4                                ; |ControlID = 4
  131414FF   .  FF75 08       push    dword ptr [ebp+8]                ; |hWnd
  13141502   .  FF15 74201413 call    dword ptr [<&user32.GetDlgItemTe>; \GetDlgItemTextA
  13141508   .  8D35 DD351413 lea     esi, dword ptr [131435DD]
  1314150E   .  8D3D 05351413 lea     edi, dword ptr [13143505]
  13141514   .  B9 21000000   mov     ecx, 21
  13141519   .  FC            cld
  1314151A   .  F3:A6         repe    cmps byte ptr es:[edi], byte ptr>
  1314151C   .  0BC9          or      ecx, ecx
  
  这是在关键跳转上面的那段代码,从调用的API函数分析,先是获得一个输入的文本,然后这个文本送进一个加工厂处理了一下,接着用wprintf函数把加工后的结果格式化包装一下,放傍边先不管.在然后呢就是又获得另一个输入文本,获得之后就是这段代码了:
  13141508   .  8D35 DD351413 lea     esi, dword ptr [131435DD]
  1314150E   .  8D3D 05351413 lea     edi, dword ptr [13143505]
  13141514   .  B9 21000000   mov     ecx, 21
  13141519   .  FC            cld
  1314151A   .  F3:A6         repe    cmps byte ptr es:[edi], byte ptr>
  1314151C   .  0BC9          or      ecx, ecx
  这不难理解,就是把处理后的结果跟获得的第二个文本进行比较了,呵呵.
  因为没有调试只是在这里瞎看,瞎看也有瞎看的原则和方法对不?呵呵,我们可以知道这两个文本一个是用户名,一个是注册码,到底是哪个进了工厂处理然后跟另一个比?目前为止可以猜一下:
  A:用户名->进加工厂->加工之后的结果  cmp  输入的注册码
  B:注册码->进加工厂->加工之后的结果  cmp  输入的用户名
  从这种加密的效果上看没什么太大区别,但是仔细想想,如果你是软件作者,你当然想一个用户名对应一个注册码,而不是一个注册码去让用户改名字哦.还有从一般人的写代码的思路来看这两个流程,当然A种情况比较合理也可能性最大.
  好了,上面我们是在看完了那些代码后的想入非非,呵呵,当然不能光靠幻想和猜测了,得来点有理有据的东西来啊,呵呵,现在这个情况下我想到了两个办法?你呢?
  第一个办法当然就是调试跟踪了,看看他们取得的值各是什么,就能确定是A还是B了.
  第二个办法就是看控件的ControlID号了,怎么看呢? OD里面是 3 和 4,怎么知道3和4对应那个输入框呢?  看资源首先想到就是资源查看工具了,我用的是ResHacker,兴奋,赶快拿来试试! 用reshacker打开!!! 郁闷!!! 除了图标什么都没有.
  怎么回事呢? 看来这些窗口按钮什么的是动态加入的了.那我们还得回到程序看代码了.感觉有点不爽,因为一个想法落空了,呵呵,没关系,我们又知道了更多的信息.
  动态加入,动态加入,嘴里念道一下,呵呵,我想你一定会想到CreateWindowEx这个函数了吧,赶快找!go!!
  在OD里我们找到了:
  13141374   .  6A 00         push    0                                ; /lParam = NULL
  13141376   .  FF35 E9341413 push    dword ptr [131434E9]             ; |hInst = NULL
  1314137C   .  6A 03         push    3                                ; |hMenu = 00000003
  1314137E   .  FF75 08       push    dword ptr [ebp+8]                ; |hParent
  13141381   .  6A 0F         push    0F                               ; |Height = F (15.)
  13141383   .  68 A0000000   push    0A0                              ; |Width = A0 (160.)
  13141388   .  6A 0F         push    0F                               ; |Y = F (15.)
  1314138A   .  6A 50         push    50                               ; |X = 50 (80.)
  1314138C   .  68 80008850   push    50880080                         ; |Style = WS_CHILD|WS_VISIBLE|WS_SYSMENU|WS_BORDER|80
  13141391   .  68 DA331413   push    131433DA                         ; |WindowName = "4stone"
  13141396   .  68 D5331413   push    131433D5                         ; |Class = "Edit"
  1314139B   .  6A 00         push    0                                ; |ExtStyle = 0
  1314139D   .  FF15 68201413 call    dword ptr [<&user32.CreateWindow>; \CreateWindowExA
  131413A3   .  A3 F1341413   mov     dword ptr [131434F1], eax
  131413A8   .  FF35 F1341413 push    dword ptr [131434F1]             ; /hWnd = NULL
  131413AE   .  FF15 6C201413 call    dword ptr [<&user32.SetFocus>]   ; \SetFocus
  131413B4   .  6A 00         push    0                                ; /lParam = NULL
  131413B6   .  FF35 E9341413 push    dword ptr [131434E9]             ; |hInst = NULL
  131413BC   .  6A 04         push    4                                ; |hMenu = 00000004
  131413BE   .  FF75 08       push    dword ptr [ebp+8]                ; |hParent
  131413C1   .  6A 0F         push    0F                               ; |Height = F (15.)
  131413C3   .  68 A0000000   push    0A0                              ; |Width = A0 (160.)
  131413C8   .  6A 2D         push    2D                               ; |Y = 2D (45.)
  131413CA   .  6A 50         push    50                               ; |X = 50 (80.)
  131413CC   .  68 80008850   push    50880080                         ; |Style = WS_CHILD|WS_VISIBLE|WS_SYSMENU|WS_BORDER|80
  131413D1   .  68 E1331413   push    131433E1                         ; |WindowName = "Put your code here.."
  131413D6   .  68 D5331413   push    131433D5                         ; |Class = "Edit"
  131413DB   .  6A 00         push    0                                ; |ExtStyle = 0
  131413DD   .  FF15 68201413 call    dword ptr [<&user32.CreateWindow>; \CreateWindowExA
  
  恩,对,就是这段代码了.很明显哪个是用户名哪个是注册码,再看一下他们的hMenu,呵呵,这个不久是我们要找的ControlID吗? yeah!  一个3  一个4,正合我意.  回到前面我们的猜测,呵呵,原来真的是第一种A的猜测啊!!
  到目前,我们还没有调试这个程序!但是我们却知道了这么多,是不是很有成就感啊!!哈哈!
  还不能太高兴了,因为我们还没找到注册码.不过既然我们知道是A种情况了,那就是程序处理后的结果跟注册码比较了,也就是说程序用用户名做参数计算出来一个结果,然后跟注册码比较.这个结果???这个结果跟注册码比较???? 晕倒,这个结果不就是真正的注册码吗!!!
  呵呵,我们找到注册码了!!!
  可是我们只是这样分析,还不能给自己的名字一个注册码?怎么样才能得到它呢? 调试吧? 可是OD 一打开就结束了.你说编程读这个地址?晕,别给我说这个,我是菜鸟,不会这个.那怎么办呢?
  静下心来想想,到嘴的肥肉不能只在嘴边舔舔而吃不下. 既然是明码,也计算出来了,但是因为我不能调试却看不到.可能作者用远线程就是这个目的,让我们干着急.看来他的目的达到了.我们可不能束手就擒.再想想,恩,程序里面计算出来了,已经有了,哈哈,对,那运行的时候内存里也有这个明码了.去内存里面找去!!yeah!!
  打开我们的好助手winhex,找这个线程,不爽,没找到.不管它,那我就打开整个内存.因为真的注册码跟假的比较,那他们应该在内存中离的不远,搜索---假的注册码
  呵呵,找到了,就在它的附近它的兄弟真注册码乖乖的躺在那里:
  
     
  哈哈,我们找到了自己的注册码了!!
  文章似乎结束了,但是总感觉有点不是很痛快.作者不让我调试,MD我就很乖很听话地没调试,不爽.
  但是现在还没什么思路该怎么调试.去论坛看看吧:
  


[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

收藏
免费 7
支持
分享
最新回复 (13)
雪    币: 2319
活跃值: (565)
能力值: (RANK:300 )
在线值:
发帖
回帖
粉丝
2
Winhex 大法
2007-1-17 19:05
0
雪    币: 461
活跃值: (93)
能力值: ( LV9,RANK:1170 )
在线值:
发帖
回帖
粉丝
3
好文章,先顶再看!
2007-1-17 21:13
0
雪    币: 263
活跃值: (10)
能力值: ( LV9,RANK:250 )
在线值:
发帖
回帖
粉丝
4
好。。。。老 的方法了,但用的恰当之处就是能显出威力,顶
2007-1-17 23:29
0
雪    币: 209
活跃值: (10)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
5
哈哈,顶楼主,下来学习呢~
2007-1-18 11:10
0
雪    币: 297
活跃值: (21)
能力值: ( LV9,RANK:330 )
在线值:
发帖
回帖
粉丝
6
牛人,这叫"以其之矛,攻其之盾"!
高~~!
实在是高~~!
严重学习一下
2007-1-19 15:09
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
得到学习.严重支持,小弟是还没破壳的鸟.希望大家多多指教.
2007-1-31 20:22
0
雪    币: 214
活跃值: (15)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
8
支持并学习!
2007-1-31 22:34
0
雪    币: 207
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
慢慢看 学习中!
2007-2-5 19:40
0
雪    币: 481
活跃值: (2739)
能力值: ( LV10,RANK:170 )
在线值:
发帖
回帖
粉丝
10
最初由 benbentaiyang 发布
下载这个CrackeMe,作者自己介绍无壳,无Anti,等等.
用Peid查看,无壳,情况属实.
然后用OD载入,无加密提示,也说明了没有加壳.F9,运行,无退出,死机,异常,检查结束,作者比较厚道,所述情况属实.

好像警察叔叔审犯人..

PS:那个KeyGenMe其实是为了测试远程线程而已...故只做了MD5加密而已.其实那个程序还是可以调试的,用OD载入Notepad,F9运行;再开个OD载入我的那个KeyGenMe,修改explorer.exe为notepad.exe,这样就会创建远程线程到notepad了.然后回到notepad的OD中..慢慢调试吧.(安全无风险 )

呵呵,不过楼主的文章真的写得不错,条理很清楚..支持下~
2007-2-6 01:40
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
but where is the crack me ?
2007-2-9 16:06
0
雪    币: 221
活跃值: (161)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
12
请问这个KeyGenMe在那里下载,能否给个链接?谢谢!
2007-2-16 09:21
0
雪    币: 228
活跃值: (75)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
13
就是就是。。看了之后练习不了哦。。。本文的KeyGenMe在哪可以下载啊。。
2007-2-24 01:37
0
雪    币: 481
活跃值: (2739)
能力值: ( LV10,RANK:170 )
在线值:
发帖
回帖
粉丝
14
KeyGenMe地址:http://bbs.pediy.com/showthread.php?s=&threadid=38027
2007-2-24 22:05
0
游客
登录 | 注册 方可回帖
返回
//