PEBrowse

引用:

  用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。 
   http://bbs.pediy.com/upload/2006/4/image/1.jpg_684.jpg 图1 
这时,我们可以在Microsoft.VisualBasic.Interaction::GetSetting这个方法上下断,方法是在左边列表的vb那项上单击右键,选择Search From,然后输入“GetSetting”,列表便会自动展开到这一项。然后在该项上下断点,如图2。 
    http://bbs.pediy.com/upload/2006/4/image/2.jpg_742.jpg图2  
从列表视图中可以看到刚才的断点是否已经添加,如图3,第一项就是。 
 
 此图已经缩小,点击察看原图。图3 
接下来便可以运行,等待程序中断了。PEBrowse的界面实在是不爽,调试时我通常开三个窗口:一个反汇编(asm)指令窗口,这是调试时最基本的;一个il反汇编指令窗口,便于观察当前程序的执行流程和功能;一个寄存器窗口。 
取消刚才的Module初始化断点,F5运行,不一会程序就中断在了GetSetting的入口处。向下翻,然后在函数最后的ret上选择“run to selection”,因为我们对怎么从注册表取信息并不感兴趣,而是要看它取得了什么信息。寄存器窗口中都是保存各种函数信息的地址,双击可以查看(这点PEBrowse还是比较方便的)。返回后,双击eax,如图4,第一次取的是密码(我在注册表中输入的就是“1111111…”): 
  http://bbs.pediy.com/upload/2006/4/image/4.jpg_752.jpg  图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 

 http://bbs.pediy.com/upload/2006/4/image/5.jpg 




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

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
PEBrowse Professional Interactive 9.3.3 老朽痴拙汉化版(专业动态调试器).这是一个专业动态调试器(绿化或是破解软件可选)该类产品大致有二个工具: PEBrowse Professional Interactive 和 PEBrowseDbg64 Interactive 分别生成 PEBrowse Professional的创建非常强大,多功能的框架和可分别自定义 Win32 和 Win64 用户模式调试器/反汇编的框架。PEBrowse Interactive 不是源代码调试器,但可在 Intel x86 的指令级别运行,因此在最低级别运行您的程序的执行位置。调试器完全支持 Microsoft.NET 托管进程和无障碍允许互操作模式调试或混合模式调试。 PEBrowseDbg64 Interactive 是一个64位的本机代码调试器,完全支持32位和64位NET程序, 包括使用预实时编译的元数据来设置断点和逐句通过.NET thunk。 PEBrowse Interactive 可以使用系统注册表映像文件执行选项键 - 用于调试ASP.NET应用程序设置为启动调试。 原版下载 http://www.smidgeonsoft.prohosting.com/pebrowse-pro-interactive-debugger.html 使用范文 http://bbs.pediy.com/showthread.php?t=24646 阅读教程 http://translate.google.com.hk/translate?hl=zh-CN&ie=UTF8&prev=_t&sl=en&tl=zh-CN&u=http://www.smidgeonsoft.prohosting.com/documentation/pebrowse-pro-interactive-debugger-tutorial-introduction.html PEBrowse Professional Interactive and PEBrowseDbg64 Interactive build upon the framework presented by PEBrowse Professional to create very powerful, versatile, and customizable Win32 and Win64 user mode debuggers/disassemblers, respectively. PEBrowse Interactive is not a source code debugger, but operates at the Intel x86 instruction level and therefore at the lowest level where your program executes. The debugger fully supports Microsoft .NET managed processes and seamlessly allows interop or mixed-mode debugging. PEBrowseDbg64 Interactive is an x64 native-code debugger that fully supports 32 and 64-bit .NET programs, includes using pre-JITted metadata to set breakpoints and steps through .NET thunks. PEBrowse Interactive can be set as the startup debugger using the system registry Image File Execution Options key - useful for debugging ASP.NET applications.

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值