首页
社区
课程
招聘
[原创]用PEBrowse对.Net程序进行动态调试
发表于: 2006-4-25 11:01 29430

[原创]用PEBrowse对.Net程序进行动态调试

2006-4-25 11:01
29430
用PEBrowse对.Net程序进行动态调试
tankaiha[NE365]@www.vxer.cn
2006.04.25

    本文主要讲了通过在.Net平台下动态调试应用程序来破解程序的一些思路和方法,研究的对象是Code Library .Net(Access),版本号13.8.2294.11793。
一、    调试工具的选择
我通常在.Net平台下使用的动态调试方法有两种:一是用ildasm将程序反汇编,然后进行必要修改(如去除强名称),再用ilasm汇编为带debug信息的,然后用Framework SDK自带的GuiDebug进行调试。但是这种方法我用的还不多,因为我机上没有1.1版本的SDK,而现在更多的程序是1.1的,所以我更喜欢用第二种:用第三方调试软件(类似win32下的Ollydbg)来直接调试,这里使用的是PEBrowse Professional Interactive。具体使用方法结合例子在后面再说。

二、    静态分析
    拿到一个程序我们首先要做的就是静态分析,看看有没有敏感信息,以便找到关键代码。用Reflector打开后,发现程序已经混淆,代码直接是看不到的。现在的.Net程序基本都做过混淆,在名称混淆方面做的比较变态的是把名称混淆为不可打印字符,这样很多反汇编程序出来的代码都会出错,即使不出错也分不清谁跟谁了!只能用ildasm直接反汇编成il代码了。之后打开CodeLib.il,发现流程也混淆了,跟踪一个函数发现两三句指令就是一个跳转,非常不爽。
    先来看看有没有什么明文的敏感信息吧,通过搜索il文件,我们发现了“User”“Keycode”两个关键字段,代表什么显而易见,就是开机要我们输入的用户名和密码。然后不管你输入对错都是弹出“感谢注册”的对话框,这种形式通常注册信息被保存在文件或者注册表中,果然,我们在文件中发现了“Software\VB and VBA Program Settings\fishCodeLib”字段,这是信息保存的位置。
    但是还有一些字符串没有搜到,比如第一个窗口中的“This is an unresigered copy”。仔细看一下,代码中有很多bytearray,比如:
ldstr      bytearray (46 D8 57 DF 55 E6 5C ED 06 F4 4C FB 53 02 FD 08
                  3B 10 45 17 F4 1D 46 25 3C 2C 3D 33 2D 3A 2C 41
                  2B 48 32 4F 30 56 1E 5D 28 64 18 6B 14 72 CD 78
                  0D 80 16 87 14 8E 1A 95 CC 9B )
ldc.i4     0x6e66d7f2
call string xed3d7768b7546353.x7846ebd83ad1c299::_bc22ed13a5229081(string, int32)
    看来字符串都被加了密。写个il程序解码,代码就用程序中的_bc22ed13a5229081(string,int32),具体代码见附件。解码后得到这段字符串正是“This is an unresigered copy”。同理我们可以将其它的相关字符串统统解码。

三、    静态流程分析
首先在il文件中静态跟一下流程,但是经过混淆的代码看起来实在是痛苦,鼠标的滚轮没少受折磨。搜一下文件中的“Keycode”,发现太多地方使用了,没有办法一下确定哪一处是关键点。(这么多关键点,看来爆破是没折了!)但至少我们发现一个关键信息:
bool CodeLib.x83a1ac2c48984168::x6ae105ff7a55905e
是判断是否注册的关键变量,根据吗,看下面的代码:

--------------------------------------------------------------------------------

  .method private instance void  xb4fe74a3788695e0(object x897f7d97ff45d640, 
           class [mscorlib]System.EventArgs x92a51111cd18ca81) cil managed 
  { 
    // Code size       122 (0x7a) 
    .maxstack  7 
    .locals init (class CodeLib.xf9b7e3b2c792f083 V_0) 
    IL_0000:  newobj     instance void CodeLib.xf9b7e3b2c792f083::.ctor() 
    IL_0005:  stloc.0 
    IL_0006:  ldsfld     bool CodeLib.x83a1ac2c48984168::x6ae105ff7a55905e //注意这句 
    IL_000b:  brfalse.s  IL_0017  //然后这里跳转 

    IL_000d:  ldloc.0 
    IL_000e:  callvirt   instance class [System.Windows.Forms]System.Windows.Forms.Label CodeLib.xf9b7e3b2c792f083::get_x6bc866479ed84b6d() 
    IL_0013:  br.s       IL_0043 

    IL_0015:  br.s       IL_0072 

    IL_0017:  ldloc.0 
    IL_0018:  callvirt   instance class [System.Windows.Forms]System.Windows.Forms.Label CodeLib.xf9b7e3b2c792f083::get_x6bc866479ed84b6d() 
    IL_001d:  ldstr      bytearray (AF 06 CD 0D CF 14 78 1B A7 22 B7 29 B6 30 B5 37   // ......x..".).0.7 
                                    BC 3E BA 45 A8 4C B2 53 A2 5A 9E 61 58 68 )       // .>.E.L.S.Z.aXh 
    IL_0022:  ldc.i4     0x5c4c0661 
    //解码后的信息 
    //Not Registered! 
    IL_0027:  call       string xed3d7768b7546353.x7846ebd83ad1c299::_bc22ed13a5229081(string, 
                                                                                       int32) 
    IL_002c:  call       string [mscorlib]System.String::Intern(string) 
    IL_0031:  callvirt   instance void [System.Windows.Forms]System.Windows.Forms.Control::set_Text(string) 
    IL_0036:  ldloc.0 
    IL_0037:  callvirt   instance class [System.Windows.Forms]System.Windows.Forms.Label CodeLib.xf9b7e3b2c792f083::get_x6bc866479ed84b6d() 
    IL_003c:  call       valuetype [System.Drawing]System.Drawing.Color [System.Drawing]System.Drawing.Color::get_Red() 
    IL_0041:  br.s       IL_006d 

    IL_0043:  ldstr      "Licensed to " 
    IL_0048:  ldsfld     string CodeLib.x83a1ac2c48984168::xa07a59ecbea7b301 
    IL_004d:  ldstr      "Settings" 
    IL_0052:  ldstr      "User" 
    IL_0057:  ldstr      "" 
    IL_005c:  call       string [Microsoft.VisualBasic]Microsoft.VisualBasic.Interaction::GetSetting(string, 
                                                                                                     string, 
                                                                                                     string, 
                                                                                                     string) 
    IL_0061:  call       string [mscorlib]System.String::Concat(string, 
                                                                string) 
    IL_0066:  callvirt   instance void [System.Windows.Forms]System.Windows.Forms.Control::set_Text(string) 
    IL_006b:  br.s       IL_0015 
…… 


    这段代码明显是关于窗口根据判断是否注册而选择显示“Licensed to XXXX”还是未注册。

四、    动态调试
先来明确一下动态调试的原则:一是以注册表操作为突破口,Microsoft.VisualBasic.Interaction::GetSetting,当不知道输入用户名和密码后程序在哪里进行计算,下在这个上面是最好的,类似于win32的API断点。再就是,要是上面那个bool变量作为关键点判断是否是进行注册码的验证。
如果运行一下程序会发现,如果未注册,程序会弹出注册窗口,如果注册肯定不会有此窗口,因此判断程序初始会有代码进行注册码验证。为了找到这段代码,我们先在注册表的User字段和Keycode字段填上用户名和密码。
打开PEBrowse,载入CodeLib.exe,可这里Microsoft.VisualBasic.dll并没有载入(应该是第一次使用时载入),怎么办?用菜单DebugBreak on Module Initialization,在每一个载入模块初始化时中断。几次F5之后,左边的模块列表中多了microsoft.visualbasic.dll一项。如图1。
    图1
这时,我们可以在Microsoft.VisualBasic.Interaction::GetSetting这个方法上下断,方法是在左边列表的vb那项上单击右键,选择Search From,然后输入“GetSetting”,列表便会自动展开到这一项。然后在该项上下断点,如图2。
    图2 
从列表视图中可以看到刚才的断点是否已经添加,如图3,第一项就是。

图3
接下来便可以运行,等待程序中断了。PEBrowse的界面实在是不爽,调试时我通常开三个窗口:一个反汇编(asm)指令窗口,这是调试时最基本的;一个il反汇编指令窗口,便于观察当前程序的执行流程和功能;一个寄存器窗口。
取消刚才的Module初始化断点,F5运行,不一会程序就中断在了GetSetting的入口处。向下翻,然后在函数最后的ret上选择“run to selection”,因为我们对怎么从注册表取信息并不感兴趣,而是要看它取得了什么信息。寄存器窗口中都是保存各种函数信息的地址,双击可以查看(这点PEBrowse还是比较方便的)。返回后,双击eax,如图4,第一次取的是密码(我在注册表中输入的就是“1111111…”):
    图4

F10步进(也可以用F12,不过后者是一次跳好几句,要注意看il反汇编窗口,别跳过头),回到了调用该方法的程序段,标题栏显示现在是在x4859a6930f0abd9a::.ctor(注意PEBrowse的反汇编形式,上面是il指令,下面是JIT形成的本机指令)。接下来是检查注册码长度是否为0,Microsoft.VisualBasic.CompilerServices.StringType::StrCmp()。接下来在我的机器里会报错,没关键,F5继续运行。运行到
  ; IL_0EC5: ldstr "User"
  ; IL_0ECA: ldstr ""
  ; IL_0ECF: call  Microsoft.VisualBasic.Interaction::GetSetting()
时,就已经取得了用户名了,查看方法同上。接着走来到下面:
  ; IL_1A98: ldarg.0
  ; IL_1A99: ldarg.0
  ; IL_1A9A: ldfld x859f040f6b146ec7
  ; IL_1A9F: callvirt  CodeLib.x4859a6930f0abd9a::xd065633e7dc3dd02()
    查看eax,发现上面提到的“FishCodeLib”已经被编码为了“)f(i*s&h^c%o$d#l!i~b ”,注意最后还有个空格。
  ; IL_1A41: ldloc.2
  ; IL_1A42: ldarg.0
  ; IL_1A43: ldfld x859f040f6b146ec7
  ; IL_1A48: ldarg.0
  ; IL_1A49: br.s IL_1A13
  ; IL_1A4B: bne.un.s IL_1AB6
下面是把“)f(i*s&h^c%o$d#l!i~b ”和用户名“tankaiha”连接起来:
  ; IL_1A13: ldfld x9ba04a28429d23be
  ; IL_1A18: ldarg.0
  ; IL_1A19: ldfld x859f040f6b146ec7
  ; IL_1A1E: call  System.String::Concat()
再下面就是我们最关键的了:
  ; IL_1A23: ldloc.s 0x0A
  ; IL_1A25: call  CodeLib.x83a1ac2c48984168::x720d40bd855b5147()
将连接起来的字符串进行运算,得到了一串编码“D8tOZUJQ4qU7hBEt6fDaOQ==”。

  ; IL_1A2A: ldc.i4.0
  ; IL_1A2B: call  Microsoft.VisualBasic.CompilerServices.StringType::StrCmp()
  ; IL_1A30: ldc.i4.0
  ; IL_1A31: br.s IL_1A4B
和注册码进行比较。和注册码进行比较,那这段代码是不是就是真正的注册码呢?答案是YES。其实往后走几步,如果比较正常的话,会有这一句:
  ; IL_1AB9: ldc.i4.1
  ; IL_1ABA: stsfld x6ae105ff7a55905e
将我们刚才说的关键的bool变量置为真。OK,运行一下,输入tankaiha和D8tOZUJQ4qU7hBEt6fDaOQ==,果然,关于窗口已经改变,注册成功了。见图5



    本文主要结合一个具体的软件讲了PEBrowse的使用,后续的工作还可以做,比如做出注册机等。偶是没有那个精力了!.Net下的东东,我研究的很肤浅,所以有什么建议,有啥子BUG,大家尽管拍砖吧!

(decode.il中是bytearray的解码程序示例,使用了linhanshi发布的xacc.ide,呵呵,效果8错!)
点击下载decode

[课程]FART 脱壳王!加量不加价!FART作者讲授!

收藏
免费 7
支持
分享
最新回复 (37)
雪    币: 176
活跃值: (1450)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
2006-4-25 11:04
0
雪    币: 253
活跃值: (25)
能力值: ( LV9,RANK:290 )
在线值:
发帖
回帖
粉丝
3
支持一下
2006-4-25 11:29
0
雪    币: 207
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
.NET 是以后的趋势,楼主是先行者呀!!
支持一个。文中提到的PEBrowse Professional Interactive哪里有下?
2006-4-25 13:12
0
雪    币: 9583
活跃值: (1935)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
好文,学习.
2006-4-25 13:44
0
雪    币: 2506
活跃值: (1000)
能力值: (RANK:990 )
在线值:
发帖
回帖
粉丝
6
最初由 向日葵 发布
支持一个。文中提到的PEBrowse Professional Interactive哪里有下?

http://www.smidgeonsoft.com/download/PEBrowseDbg.zip
要用代理。
2006-4-25 13:57
0
雪    币: 176
活跃值: (1450)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
最初由 CCDebuger 发布
http://www.smidgeonsoft.com/download/PEBrowseDbg.zip
要用代理。


直接还是可以下载的。不过不稳定。
2006-4-25 13:59
0
雪    币: 234
活跃值: (370)
能力值: ( LV9,RANK:530 )
在线值:
发帖
回帖
粉丝
8
学习!
2006-4-25 14:15
0
雪    币: 209
活跃值: (12)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
最初由 CCDebuger 发布
http://www.smidgeonsoft.com/download/PEBrowseDbg.zip
要用代理。


为何不直接放到本站呢?
2006-4-25 15:32
0
雪    币: 313
活跃值: (440)
能力值: ( LV12,RANK:530 )
在线值:
发帖
回帖
粉丝
10
最初由 CCDebuger 发布
http://www.smidgeonsoft.com/download/PEBrowseDbg.zip
要用代理。

直接下不来,可以发个附件么?谢谢斑竹
2006-4-25 15:52
0
雪    币: 93944
活跃值: (200219)
能力值: (RANK:10 )
在线值:
发帖
回帖
粉丝
11
刚看到tankaiha的贴,深感荣幸!

I LIKE THIS GAME!
2006-4-25 15:55
0
雪    币: 229
活跃值: (70)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
12
牛~~~~~~~~~~
2006-4-25 16:00
0
雪    币: 93944
活跃值: (200219)
能力值: (RANK:10 )
在线值:
发帖
回帖
粉丝
13
这是我第一次看到PEBrowse Professional Interactive的应用.

I TRY!

我转载到EXETOOLS.
2006-4-25 16:03
0
雪    币: 10500
活跃值: (2159)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
支持  嘿嘿
2006-4-25 16:32
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
15
谢谢分享,学习一下
2006-4-25 16:38
0
雪    币: 5275
活跃值: (451)
能力值: (RANK:1170 )
在线值:
发帖
回帖
粉丝
16
sorry,停电一天,所以现在才有时间修正。图4发错了,原图是输入用户名和注册码的图,应该是内存数据dump的图。还有两个错别字。

偶是GPRS,上传图片就要了我的老命了,别说上传程序了。

btw:工具版是我常去的一个版,linhanshi发的工具我都看,但更重要的是大家要用起来,比如这个PEBrowse和编写il的xacc.ide就不错。
2006-4-25 19:52
0
雪    币: 671
活跃值: (723)
能力值: ( LV9,RANK:1060 )
在线值:
发帖
回帖
粉丝
17
学习一下
为了.net 要装 FrameWork。怕
2006-4-25 21:09
0
雪    币: 224
活跃值: (75)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
18
今天看了2篇.net 好文 一定要去试试。
2006-4-25 21:51
0
雪    币: 4833
活跃值: (2218)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
19
我用的是另外2种工具。因为你说的这个软件我也第一次见别人使用。
我自己使用的2个工具是自己琢磨出来的。
2006-4-25 22:03
0
雪    币: 370
活跃值: (15)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
20
今天两篇好文,一静一动,拿net程序开刀

很好!都收藏了

2006终于盼到好文了
2006-4-25 23:36
0
雪    币: 370
活跃值: (15)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
21
下载了(2006/04/21) Code Library .NET Professional 13.8.2302  ,好像输入你的注册码不行,可能版本的区别算法有变化,结果退出以后再怎么都运行不起来了,点击无反应。

我用你介绍的PEBROWER工具加载,出现kernel32几个异常之后就退出了,重新安装也无济于事。还怀疑是net平台(虽然作者说程序要求1.1即可),特意升级到2.0,结果还是一样。

难道.2302加入了anti?
2006-4-26 01:52
0
雪    币: 212
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
22
把文章做个WORD文档打包下载吧,直接复制的没图片
2006-4-26 09:33
0
雪    币: 5275
活跃值: (451)
能力值: (RANK:1170 )
在线值:
发帖
回帖
粉丝
23
最新的13.8.2306.33660已经改变了注册算法了,但是只改变了一点点。注册码就不发了,用上述的方法是完全可以跟出来的。



注意一点:有网络验证。所以防火墙报警时不要让CodeLib连接网络。

至于anti,我还没发现。
2006-4-26 10:46
0
雪    币: 370
活跃值: (15)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
24
最初由 tankaiha 发布
最新的13.8.2306.33660已经改变了注册算法了,但是只改变了一点点。注册码就不发了,用上述的方法是完全可以跟出来的。



注意一点:有网络验证。所以防火墙报警时不要让CodeLib连接网络。
........


我当时就禁止codelib联网了,也用你的办法试了,好像一加载就会看到那个vb什么的dll,进入其interact类选GetString函数Add Breakpoint,照你方法F5走,结果没到断点就异常了,然后退出。

我不知道是否是我系统的原因,只好重新安装codelib的10.0版了,免费,用了很久了。
2006-4-26 16:52
0
雪    币: 50
活跃值: (145)
能力值: ( LV12,RANK:290 )
在线值:
发帖
回帖
粉丝
25
学学,好东西
2006-4-26 19:44
0
游客
登录 | 注册 方可回帖
返回
//