吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 6297|回复: 6
收起左侧

[原创] 160个CrackMe之89 -- PhrekTech (16位NE)的详细跟踪和追码过程

  [复制链接]
solly 发表于 2019-5-5 14:10
本帖最后由 solly 于 2019-5-6 23:22 编辑

160个CrackMe之89--PhrekTech是一个16位的NE格式的win16执行程序,这个程序只能在Win3.x和Win9x系统下运行,需要装一个Win98SE来跟踪。
我是在VMWare中装了一个Win98SE的虚拟机来跟踪这个程序的,并且是通过Win9x下经典的调试工具 TRW2000 来完成跟踪和追码。
为了在虚拟机中调试该CrackMe,需要进行以下设置或操作,不然无法调出TRW2k的调试界面,但这样设置后就无法使用鼠标了,只能通过键盘操作。

1、修改虚拟机vmx配置文件:
  vmmouse.present = "FALSE"
  svga.maxFullscreenRefreshTick = "5"
2、将TRW2000的所有文件及子目录放置到C:\盘的根目录下。如下图所示:
01.png
由于只能键盘操作,有几个快捷键要用到:
1、ALT+SpaceBar:调用出系统菜单,可以用方向键调整窗口大小,以及移动窗口位置;
2、ALT+F4:关闭窗口;
3、ALT+TAB:切换窗口;
4、TAB键:在窗口内各个控件中移动焦点。
5、CTRL + ALT:从虚拟机中切回到Window10主机;
6、TRW2000加载后,CTRL+N和CTRL+M,调出TRW2000的调试界面。

下面简单介绍在TRW中需要用到了几个调试命令:
1、s 0,FFFFFFFF ’solly‘  在内存中搜索字符串”solly"
2、bpm address 内存下断点,内存地址格式:segment:offset,如 es:0528
3、bl 查看断点
4、bd 编号  禁用某个编号的断点,如 bd 04 禁用04断点,编号可以通过上面的bl查到
5、be 编号  启用某个编号的断点,如 be 04 启用04断点,编号可以通过前面的bl查到
6、bpx 代码下断点,如 bpx cs:0208 ,在代码段中偏移0208处下断点。
7、g 运行,退出调试界面
8、按F8键是跟入,可以进入函数,F10是单步跟踪(不进入函数)
注意,有时从TRW2000退回Win98后,键盘不响应,按任何键虚拟机都是发出“嘀”声时,可以先按"CTRL+ALT"返回Window10,再点击虚拟机的桌面进去,就可以再次使用键盘了。

16位的NE程序与DOS程序一样,是分段的,所有的代码和数据的访问是通过 segment:offset 的地址格式来访问的,如 cs:0208 是访问代码,ds:0528、ss:sp、es:si、es:di 是访问数据等


该CrackMe程序是Delphi 1.x编写的,通过IDA反汇编后,可以看到其资源和内部函数,我们可以通过IDA找到内部函数,在TRW2000中就不需要进入这些内部函数跟踪了。

启动TRW2000的Loader程序 trw2000.exe:
02.png
点击“Browse”找到我们要跟踪的CrackMe程序。
03.png
然后再点击“Load"加载程序,TRW加载程序后,会弹出调试界面,停留在 INITTASK 位置。
04.png
不管它,输入 g, 加回车,返回桌面:
05.png
继续运行程序,如下:
06.png
TRW2000的 Message Output 内显示加载成功,并且CrackMe也正常进入界面,如下:
07.png 08.png
按钮上面的标签显示”Not tested“,表示还没有进行过注册码验证。
输入假码,如下图:
09.png
然后按CTRL+N调出TRW2000调试界面,如果没有出来,则多按几次。
10.png
输入” S 0, ffffffff 'solly'   “,搜索刚才输入的用户名,如果搜到,则会在后面显示地址,同时,数据窗口会显示搜索到的数据,如上图所示。
搜到地址,可以下内存断点:bpm 80386d68,这样下完断点后,只要程序读取这个用户名,就会断下来。
如果没有断下来,説明这个数据在内存中有多个,如上图,我们可以重新搜索,如 S 80386d69,ffffffff 'solly' 来重新指定搜索范围,搜索刚才没有搜索过的地址空间,直到搜索到能够断下来的地址,如果搜索结果太多,一直断不下来,则可以下g关闭调试窗口,重新输入一个没有使用过的用户名再来重新搜索。如下图,我就把用户用重新改成了”username9977",再重新搜索。
11.png
下完新的断点,再g回到windows,按CrackMe的 Test 按钮。这回断了下来,如上图,TRW2000显示“Break on BP1",代码区显示,我们断在了 KERNEL.DLL中的 HMEMCPY 函数中,这是一个内存拷贝系统函数,这里 es:si指向源字符串,为系统空间,es:di为目的字符串,指向了应用程序的空间,如下图:
12.png
在指令区下 d es:di-4,就可以看到,系统正向程序传送用户名数据,如上图,已经传送了一部分,下图则是全部传送完成了,代码也返回了应用空间的状态:
13.png
目的地址为: es:5128,这是应用程序保存用户名的缓冲区。
这个时候为了我们可以下命令 bd 01,禁用刚才的内存中断,也可以下 bc * ,禁用所有的断点,并重新下一个新的断点:bpx HMEMCPY, 这样,等一下读取序列号时就可以断下来了。
一路按F10,返回多个 retf 后,我们来到了CrackMe的指令空间,如下图:
14.png
这里就是CrackMe进行序列号验证的地方。同时,我们用IDA反编译程序,按地址3907:0237在IDA找到相应代码位置,另外,段地址3907不用管,只要在IDA搜索偏移地址0237就可以,然后跟据TRW2000中显示的汇编代码就可以在IDA中找到相应的汇编代码范围。
这样,我们可以在IDA中看到Delphi的内部函数,如下所示,是上图对应的汇编代码:
[Asm] 纯文本查看 复制代码
cseg01:0237                 call    @TControl@GetText$qv ; 读取用户名:username9977
cseg01:023C                 call    @Concat$qm6Stringt1 ; 连接字符串:"g3df" + "username9977"
cseg01:0241                 lea     di, [bp+var_100]
cseg01:0245                 push    ss
cseg01:0246                 push    di              ; es:di 输出结果缓冲区
cseg01:0247                 push    0FFh
cseg01:024A                 call    @$basg$qm6Stringt14Byte ; 生成Delphi字符串:"g3dfusername9977"
cseg01:024F                 lea     di, [bp+var_300] ; es:di ===> 用户名:username9977
cseg01:0253                 push    ss
cseg01:0254                 push    di
cseg01:0255                 lea     di, [bp+var_100] ; es:di ===>连接后的字符串:"g3dfusername9977"
cseg01:0259                 push    ss
cseg01:025A                 push    di
cseg01:025B                 call    @$basg$qm6Stringt1 ; 生成字符串:"g3dfusername9977"
cseg01:0260                 mov     di, offset aH9cf8 ; "h9cf8"
cseg01:0263                 push    cs

可以看到刚才执行了Delphi 控件的 GetText 函数,取得了用户名。
一路往下跟踪执行,来到了 3907:02D9 处,执行完这条指令,就生成了一个序列号,如下图所示:
15.png
使用 d es:4F28 就会在数据区显示出来,这个地址是前面push到栈中的[sp] = 0x4F28,在TRW2000中的Stack窗口可以看到。
同时在IDA中可以看到,马上要执行一个字符比较函数: bsub(),这是一个delphi的字符串比较函数,如果相等则返回0,不相等则返回非0,按F8进入函数内部,其进行字符串比较的代码细节如下图所示:
16.png

先比较长度,再比较字符串。
执行到 0FA7:2DCD LODSB 时,可以通过 d es:si 和 d es:di 来显示进行比较的两个字符串,如下图:


17.png
到这里,真正的序列号已经出来了,其生成规则是:
1、输入的用户名不能为空;
2、在用户名"username9977"前面加上"g3df",形成字符串1:"g3dfusername9977";
3、在前面生成的字符串1的后面加上"h9cf8",形成字符串2:"g3dfusername9977h9cf8";
4、再把前面生成的两个字符串连接起来,形成序列号:"g3dfusername9977g3dfusername9977h9cf8";
这样,只要我们返回CrackMe,输入以上序列号就可以注册通过了。
先禁用断点:

18.png
禁用断点后,输入 g 返回应用。输入正确的序列号,再按“Test”:
19.png
这时,按钮上面的标签显示“YEAH,Good work!”,表示注册成功!
下面是完整的汇编代码的验证过程,我加了注释:
[Asm] 纯文本查看 复制代码
cseg01:0208 sub_208         proc far                ; DATA XREF: cseg01:010E↑o
cseg01:0208
cseg01:0208 var_500         = byte ptr -500h
cseg01:0208 var_400         = byte ptr -400h
cseg01:0208 var_300         = byte ptr -300h
cseg01:0208 var_200         = byte ptr -200h
cseg01:0208 var_100         = byte ptr -100h
cseg01:0208 arg_0           = dword ptr  6
cseg01:0208
cseg01:0208                 push    bp
cseg01:0209                 mov     bp, sp
cseg01:020B                 mov     ax, 500h
cseg01:020E                 call    @__StackCheck$q4Word               ; __StackCheck(Word)
cseg01:0213                 sub     sp, 500h
cseg01:0217                 lea     di, [bp+var_400]
cseg01:021B                 push    ss
cseg01:021C                 push    di
cseg01:021D                 mov     di, offset aG3df                   ; "g3df"
cseg01:0220                 push    cs
cseg01:0221                 push    di
cseg01:0222                 call    @$basg$qm6Stringt1                 ; 生成Delphi字符串:"g3df"
cseg01:0227                 lea     di, [bp+var_300]                   ; es:di 保存用户名的缓冲区
cseg01:022B                 push    ss
cseg01:022C                 push    di
cseg01:022D                 les     di, [bp+arg_0]
cseg01:0230                 les     di, es:[di+18Ch]
cseg01:0235                 push    es
cseg01:0236                 push    di                                 ; this
cseg01:0237                 call    @TControl@GetText$qv               ; 读取用户名:username9977
cseg01:023C                 call    @Concat$qm6Stringt1                ; 连接字符串:"g3df" + "username9977"
cseg01:0241                 lea     di, [bp+var_100]
cseg01:0245                 push    ss
cseg01:0246                 push    di                                 ; es:di 输出结果缓冲区
cseg01:0247                 push    0FFh
cseg01:024A                 call    @$basg$qm6Stringt14Byte            ; 生成Delphi字符串:"g3dfusername9977"
cseg01:024F                 lea     di, [bp+var_300]                   ; es:di ===> 用户名:username9977
cseg01:0253                 push    ss
cseg01:0254                 push    di
cseg01:0255                 lea     di, [bp+var_100]                   ; es:di ===>连接后的字符串:"g3dfusername9977"
cseg01:0259                 push    ss
cseg01:025A                 push    di
cseg01:025B                 call    @$basg$qm6Stringt1                 ; 生成字符串:"g3dfusername9977"
cseg01:0260                 mov     di, offset aH9cf8                  ; "h9cf8"
cseg01:0263                 push    cs
cseg01:0264                 push    di
cseg01:0265                 call    @Concat$qm6Stringt1                ; 连接字符串:"g3dfusername9977" + "h9cf8"
cseg01:026A                 lea     di, [bp+var_200]                   ; es:di ===> 字符串缓冲区
cseg01:026E                 push    ss
cseg01:026F                 push    di
cseg01:0270                 push    0FFh
cseg01:0273                 call    @$basg$qm6Stringt14Byte            ; 生成Delphi字符串:"g3dfusername9977h9cf8"
cseg01:0278                 lea     di, [bp+var_300]                   ; es:di ==> delphi字符串数据区
cseg01:027C                 push    ss
cseg01:027D                 push    di
cseg01:027E                 les     di, [bp+arg_0]
cseg01:0281                 les     di, es:[di+18Ch]
cseg01:0286                 push    es
cseg01:0287                 push    di                                 ; this
cseg01:0288                 call    @TControl@GetText$qv               ; 再次取用户名
cseg01:028D                 add     sp, 4
cseg01:0290                 cmp     [bp+var_300], 0                    ; 字符串长度不等于0?
cseg01:0295                 jnz     short loc_2AD
cseg01:0297                 mov     di, offset aNaahWrong              ; "Naah! Wrong!"
cseg01:029A                 push    cs
cseg01:029B                 push    di                                 ; __int32
cseg01:029C                 les     di, [bp+arg_0]
cseg01:029F                 les     di, es:[di+184h]
cseg01:02A4                 push    es                                 ; int
cseg01:02A5                 push    di                                 ; TControl *
cseg01:02A6                 call    @TControl@SetText$q8TCaption       ; TControl::SetText(TCaption)
cseg01:02AB                 jmp     short locret_30F
cseg01:02AD ; ---------------------------------------------------------------------------
cseg01:02AD
cseg01:02AD loc_2AD:                                                   ; CODE XREF: sub_208+8D↑j
cseg01:02AD                 lea     di, [bp+var_400]                   ; es:di ==> delphi字符串数据区,准备保存序列号
cseg01:02B1                 push    ss
cseg01:02B2                 push    di
cseg01:02B3                 les     di, [bp+arg_0]
cseg01:02B6                 les     di, es:[di+17Ch]
cseg01:02BB                 push    es
cseg01:02BC                 push    di                                 ; this
cseg01:02BD                 call    @TControl@GetText$qv               ; 读取序列号
cseg01:02C2                 lea     di, [bp+var_500]
cseg01:02C6                 push    ss
cseg01:02C7                 push    di
cseg01:02C8                 lea     di, [bp+var_100]                   ; es:di ===> "g3dfusername9977"
cseg01:02CC                 push    ss
cseg01:02CD                 push    di
cseg01:02CE                 call    @$basg$qm6Stringt1                 ; 生成字符串:"g3dfusername9977"
cseg01:02D3                 lea     di, [bp+var_200]                   ; es:di ===> "g3dfusername9977h9cf8"
cseg01:02D7                 push    ss
cseg01:02D8                 push    di
cseg01:02D9                 call    @Concat$qm6Stringt1                ; 连接字符:"g3dfusername9977" + "g3dfusername9977h9cf8"
cseg01:02DE                 call    @$bsub$qm6Stringt1                 ; 比较上面连接的字符串是否与输入的序列号相等,不相等返回非0,相等返回0
cseg01:02E3                 jnz     short loc_2FB
cseg01:02E5                 mov     di, offset aYeahGoodWork           ; "YEAH! Good work!"
cseg01:02E8                 push    cs
cseg01:02E9                 push    di                                 ; __int32
cseg01:02EA                 les     di, [bp+arg_0]
cseg01:02ED                 les     di, es:[di+184h]
cseg01:02F2                 push    es                                 ; int
cseg01:02F3                 push    di                                 ; TControl *
cseg01:02F4                 call    @TControl@SetText$q8TCaption       ; TControl::SetText(TCaption)
cseg01:02F9                 jmp     short locret_30F
cseg01:02FB ; ---------------------------------------------------------------------------
cseg01:02FB
cseg01:02FB loc_2FB:                                                   ; CODE XREF: sub_208+DB↑j
cseg01:02FB                 mov     di, offset aNaahWrong              ; "Naah! Wrong!"
cseg01:02FE                 push    cs
cseg01:02FF                 push    di                                 ; __int32
cseg01:0300                 les     di, [bp+arg_0]
cseg01:0303                 les     di, es:[di+184h]
cseg01:0308                 push    es                                 ; int
cseg01:0309                 push    di                                 ; TControl *
cseg01:030A                 call    @TControl@SetText$q8TCaption       ; TControl::SetText(TCaption)
cseg01:030F
cseg01:030F locret_30F:                                                ; CODE XREF: sub_208+A3↑j
cseg01:030F                                                            ; sub_208+F1↑j
cseg01:030F                 leave
cseg01:0310                 retf    8
cseg01:0310 sub_208         endp

分析完华!

免费评分

参与人数 3吾爱币 +5 热心值 +3 收起 理由
zls黑战魔 + 1 + 1 热心回复!
liphily + 3 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
xiangxiong + 1 + 1 热心回复!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

淫神 发表于 2019-5-6 13:06
学习了 共享精神伟大
92013 发表于 2019-5-7 23:09
明世嘤嘤嘤 发表于 2019-5-30 20:47
大神真的很牛,我找了好久才找到。值得转播。
明世嘤嘤嘤 发表于 2019-5-30 20:47
大神真的很牛,我找了好久才找到。值得分享。
安尼大大 发表于 2019-7-26 11:25
谢谢分享出来
cpj1203 发表于 2019-11-5 12:01
內容很詳細
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则 警告:本版块禁止灌水或回复与主题无关内容,违者重罚!

快速回复 收藏帖子 返回列表 搜索

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-3-29 01:01

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表