吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 60530|回复: 149
收起左侧

[.NET逆向] 一个简单的.NET程序的脱壳以及破解

    [复制链接]
ximo 发表于 2009-1-20 16:30
前几天有朋友问.NET程序的破解,又鉴于论坛里关于.NET脱壳和破解的文章也不多,于是抽空写一个。由于本人也很少接触.NET的程序,因此文章没什么技术含量,用到的技术也是在网上很早就公开的东西。本文仅仅是本人分析.NET程序的一点基本套路而已,有什么错误还请多多指教。
本文的目标文件是一个非常简单的CrackMe.
本CrackMe的任务有4个:
1.脱壳
2.去NAG
3.去灰色按钮
4.破解
OK,一个一个来完成任务吧。
一、脱壳
查壳发现为:

1.GIF

按照经验,此程序应该是用.NET Reactor加的壳
下面来脱壳吧
根据前人经验,此壳其实只是在简单的混淆,在运行的同时,在内存中会释放原程序的镜像
根据这一特点,我们下断点:BP WriteProcessMemory,然后F9运行,中断下来
中断下来看堆栈

2.GIF

写入的地址为:17B1050
在数据窗口查看,然后拉到最顶端

3.GIF

可以发现,PE头在017B0000
于是可以dump此地址的镜像。
当然,此时dump下来的程序不行,因为还有好多内容没写入。于是,不断SHIFT+F9,直到程序运行。
这时候就可以dump了.
用LordPE,区域转存017B0000这个区段,保存为dumped.exe就OK了.

4.GIF

不过,此时dump后,程序是无法运行的。
我们还得再用CFF修正几个量
(1).选Nt Headers,再File Header,然后选Characteristics,再点旁边的Click here,在出现的对话框中,去掉“File is a DLL”就OK了。

5.GIF

(2)修正MetaData RVA和MetaData Size的值
MetaData RVA值的获得可以用2种方法
第一种:原程序中,下完BP WriteProcessMemory,F9运行,第一次中断的时候就dump这个区段,此时的MetaData RVA是正确的。
在CFF中,选.NET Directory,看MetaData RVA的值,并记录:

6.GIF

记录这个值为A400,然后在dumped.exe中同样修正这个值为A400
第二种:参考老K的文章
CFF中,选Address Converter,然后搜索字符“BSJB”

7.GIF

搜索到偏移地址为:9400
接着就换算成RVA的值:

8.GIF

换算结果同样为A400
下面接着来计算MetaData Size的值
选Optional Header,接着点Data Directories [x],然后看Import Directory RVA 的值

9.GIF

记下值为BD4C
所以,
MetaData Size=BD4C-A400=194C
故把MetaData Size的值修正为194C

10.GIF

最后,把修改完的程序保存,就OK了,程序可以正常运行了。
脱壳就到此结束了,再用PEiD查下,已经无壳了

11.GIF

另外一种抓取镜像文件的方法如下(参考老K文章):
首先运行下原程序,继续下标题为:Sample Crackme
OD载入程序,接着F9运行程序,然后ALT+M打开内存镜像,CTRL+B,在搜索UNICODE字符串“Sample Crackme”

111.GIF

大约搜索2次后,就来到下面的地方:

112.GIF

拉到最上端

113.GIF

然后就选备份,保存数据文件,扩展名改为.exe就行

114.GIF

后续的操作同上

二、去NAG
运行程序可以发现,此程序有个讨厌的NAG,并且作者也要求我们去掉

12.GIF

分析.NET程序常用的工具为:ildasm2.0,Reflector,xenocode fox
我这里就用xenocode fox这个了,因为这个工具可以查看地址
当然,默认的选项可能没显示地址,我们可以自己手动改下设置
在设置中,选DeCompiler这个选项卡,然后勾上“Show method body address”前面的勾就OK了

13.GIF

在语言(Language)选项中,我们先为了分析方便,可以选C#语言,当然你也可以选其他的

14.GIF

OK,下面就找关键地方吧,这个没什么好说的,靠自己去寻找。

15.GIF

很明显了吧,这个地方就是显示NAG窗口的代码。
下面就修改这个代码吧,思路就是,在此代码段的头,直接ret,这样,就可以避免产生NAG窗口了。
为了看机器码和偏移地址,我们把语言改为中间语言IL Assembly
代码如下:
method private hidebysig instance void uuNkODx(object, [mscorlib]System.EventArgs) cil managed
{
     // Method Body Address: 0x00001524
     // Code Size: 14 byte(s)
     .maxstack 1
     .locals init (
          SampleCrackme.frmNag nag1)
     L_0000: newobj instance void SampleCrackme.frmNag::.ctor()
     L_0005: stloc.0 
     L_0006: ldloc.0 
     L_0007: callvirt instance [System.Windows.Forms]System.Windows.Forms.DialogResult [System.Windows.Forms]System.Windows.Forms.Form::ShowDialog()
     L_000c: pop 
     L_000d: ret 
}
可以发现,ret的机器码为0x 2A,而开头代码段的机器码为0x 73,偏移地址为0x00001524
接着就用16进制编辑工具打开脱壳后的程序,定位到0x00001524,把起始代码0x 73修改为0x 2A

16.GIF

修改后保存一下,就去掉NAG了

三、去灰色按纽

17.GIF

原程序这个Check按纽是灰色,而用一般的灰色按纽精灵又去不掉,因为,我们就自己手动来去吧。
同样用xenocode fox来进行分析
private void uQZDKK ()
{
     // Method Body Address: 0x00001628
     uuNkODx = new Container();
     uvUSBXHuS = new Label();
     ubGakVp2Mu = new Label();
     uJUoPB0V4HyITVABlwk = new TextBox();
     uQZDKK = new TextBox();
     uSIEDr = new Button();
     ulcmJh = new Button();
     usL7yU = new Button();
     u2lcYy2h = new ToolTip(uuNkODx);
     base.SuspendLayout();
     uvUSBXHuS.AutoSize = true;
     uvUSBXHuS.Location = new Point(9, 11);
     uvUSBXHuS.Name = "label1";
     uvUSBXHuS.Size = new Size(0x23, 13);
     uvUSBXHuS.TabIndex = 0;
     uvUSBXHuS.Text = "Name";
     ubGakVp2Mu.AutoSize = true;
     ubGakVp2Mu.Location = new Point(9, 0x28);
     ubGakVp2Mu.Name = "label2";
     ubGakVp2Mu.Size = new Size(0x21, 13);
     ubGakVp2Mu.TabIndex = 1;
     ubGakVp2Mu.Text = "Serial";
     uJUoPB0V4HyITVABlwk.Location = new Point(0x35, 9);
     uJUoPB0V4HyITVABlwk.Name = "txtName";
     uJUoPB0V4HyITVABlwk.Size = new Size(0xe3, 0x14);
     uJUoPB0V4HyITVABlwk.TabIndex = 2;
     uJUoPB0V4HyITVABlwk.TextAlign = HorizontalAlignment.Center;
     uQZDKK.Location = new Point(0x35, 0x25);
     uQZDKK.Name = "txtSerial";
     uQZDKK.Size = new Size(0xe3, 0x14);
     uQZDKK.TabIndex = 3;
     uQZDKK.TextAlign = HorizontalAlignment.Center;
     uSIEDr.Enabled = false;
     uSIEDr.FlatStyle = FlatStyle.Flat;
     uSIEDr.Location = new Point(12, 0x45);
     uSIEDr.Name = "btnCheckIt";
     uSIEDr.Size = new Size(0x3f, 0x1a);
     uSIEDr.TabIndex = 4;
     uSIEDr.Text = "&Check It!";
     u2lcYy2h.SetToolTip(uSIEDr, "2. Challenge, please enable this button");
     uSIEDr.UseVisualStyleBackColor = true;
     uSIEDr.Click += new EventHandler(this.uJUoPB0V4HyITVABlwk);
     ulcmJh.DialogResult = DialogResult.Cancel;
     ulcmJh.FlatStyle = FlatStyle.Flat;
     ulcmJh.Location = new Point(0x72, 0x45);
     ulcmJh.Name = "btnExit";
     ulcmJh.Size = new Size(0x3f, 0x1a);
     ulcmJh.TabIndex = 5;
     ulcmJh.Text = "&Exit";
     ulcmJh.UseVisualStyleBackColor = true;
     ulcmJh.Click += new EventHandler(this.uvUSBXHuS);
     usL7yU.FlatStyle = FlatStyle.Flat;
     usL7yU.Location = new Point(0xd8, 0x45);
     usL7yU.Name = "btnAbout";
     usL7yU.Size = new Size(0x3f, 0x1a);
     usL7yU.TabIndex = 6;
     usL7yU.Text = "&About";
     usL7yU.UseVisualStyleBackColor = true;
     usL7yU.Click += new EventHandler(this.ubGakVp2Mu);
     base.AcceptButton = uSIEDr;
     base.AutoScaleDimensions = new SizeF(6.00F, 13.00F);
     base.AutoScaleMode = AutoScaleMode.Font;
     base.CancelButton = ulcmJh;
     base.ClientSize = new Size(0x124, 0x65);
     base.Controls.Add(usL7yU);
     base.Controls.Add(ulcmJh);
     base.Controls.Add(uSIEDr);
     base.Controls.Add(uQZDKK);
     base.Controls.Add(uJUoPB0V4HyITVABlwk);
     base.Controls.Add(ubGakVp2Mu);
     base.Controls.Add(uvUSBXHuS);
     base.FormBorderStyle = FormBorderStyle.FixedToolWindow;
     base.Icon=
(Icon)newComponentResourceManager(typeof(Form1)).GetObject("$this.Icon");
     base.Name = "Form1";
     base.StartPosition = FormStartPosition.CenterScreen;
     Text = "Sample Crackme";
     base.Load += new EventHandler(this.uuNkODx);
     base.ResumeLayout(false);
     base.PerformLayout();
}
 
仔细分析可以发现这行代码:
uSIEDr.Enabled = false;
很明显,就这行代码把这个按钮的可用属性设置为了假,也就是变成的灰色按钮
下面,我们就把这个“假”修改为真,让这个按纽可用,把语言修改为中间语言,再分析
代码太多,稍微省略点:
// Method Body Address: 0x00001628 
L_01e5: ldarg.0 
     L_01e6: ldfld [System.Windows.Forms]System.Windows.Forms.Button SampleCrackme.Form1::uSIEDr
     L_01eb: ldc.i4.0 
     L_01ec: callvirt instance void [System.Windows.Forms]System.Windows.Forms.Control::set_Enabled(bool)
     L_01f1: ldarg.0 
     L_01f2: ldfld [System.Windows.Forms]System.Windows.Forms.Button SampleCrackme.Form1::uSIEDr
     L_01f7: ldc.i4.0 
     L_01f8: callvirt instance void [System.Windows.Forms]System.Windows.Forms.ButtonBase::set_FlatStyle([System.Windows.Forms]System.Windows.Forms.FlatStyle)
     L_01fd: ldarg.0 
     L_01fe: ldfld [System.Windows.Forms]System.Windows.Forms.Button SampleCrackme.Form1::uSIEDr
     L_0203: ldc.i4.s 12
     L_0205: ldc.i4.s 69
     L_0207: newobj instance void [System.Drawing]System.Drawing.Point::.ctor(int32, int32)
     L_020c: callvirt instance void [System.Windows.Forms]System.Windows.Forms.Control::set_Location([System.Drawing]System.Drawing.Point)
     L_0211: ldarg.0 
     L_0212: ldfld [System.Windows.Forms]System.Windows.Forms.Button SampleCrackme.Form1::uSIEDr
     L_0217: ldstr "btnCheckIt"
 
简单分析结果为:
  L_01eb: ldc.i4.0 的代码修改为相反的,也就是原来的机器码0x16修改为0x17
现在来计算下偏移地址:
0x1628+0x1eb=0x1813
同样用16进制工具修改:

18.GIF

修改完后保存,看下效果

19.GIF

哈,灰色按钮去掉了。下面就进行最后1个步骤了:破解!
四、破解
继续用那工具分析吧
private void uJUoPB0V4HyITVABlwk (object , EventArgs )
{
     // Method Body Address: 0x00001564
     new MD5CryptoServiceProvider();
     byte[] inArray = new UTF8Encoding().GetBytes(uJUoPB0V4HyITVABlwk.Text);
     string text1 = Convert.ToBase64String(inArray);
     if ((uQZDKK.Text == "") || (uJUoPB0V4HyITVABlwk.Text == ""))
     {
          MessageBox.Show("Please enter your name and serial", "Reverse Engineering Association");
     }
     else if (text1 == uQZDKK.Text)
     {
          MessageBox.Show("Congratulation! You are very good", "Reverse Engineering Association");
     }
     else
     {
          MessageBox.Show("No,no try it again", "Reverse Engineering Association");
     }
}
 
汗,源代码几乎都出来了,应该是很明显了吧
算法已经一目了然了吧:
RegCode=base64(RegName)
验证一下:
RegName=ximo
RegCode=eGltbw==

20.GIF

看,注册成功了吧

下面再看下爆破的,分析下中间代码:
省略点代码:
// Method Body Address: 0x00001564
  L_0069: callvirt instance string [System.Windows.Forms]System.Windows.Forms.Control::get_Text()
     L_006e: call bool string::op_Equality(string, string)
     L_0073: brfalse.s L_0086
     L_0075: ldstr "Congratulation! You are very good"
     L_007a: ldstr "Reverse Engineering Association"
     L_007f: call [System.Windows.Forms]System.Windows.Forms.DialogResult [System.Windows.Forms]System.Windows.Forms.MessageBox::Show(string, string)
     L_0084: pop 
     L_0085: ret 
     L_0086: ldstr "No,no try it again"
     L_008b: ldstr "Reverse Engineering Association"
     L_0090: call [System.Windows.Forms]System.Windows.Forms.DialogResult [System.Windows.Forms]System.Windows.Forms.MessageBox::Show(string, string)
     L_0095: pop 
     L_0096: ret 
 
也是很明显吧

L_0073: brfalse.s L_0086

把此代码的fale改为true就行了,换成机器码就是
0x2C改0x2D
偏移地址为:
0x1564+0x73=0x15D7

21.GIF

保存看效果:

22.GIF

看到没,随便输什么都正确了。
整个CM的分析到此全部结束了。
总结一下:
其实.NET程序的分析也没想象中的那么难,上手也是比较容易的。新手朋友也不要怕.NET程序,其实.NET程序有点类似VB的P-CODE的分析。不过分析也是需要很大的耐心,并掌握写常用的机器代码。附上张Squn提供的机器码对照表,方便大家:

未命名.jpg

其实我也是刚刚才接触.NET程序,文章中难免有很多错误,请大家多多包涵,并提出错误的意见,谢谢。

作者:ximo[LCG]

演示CrackMe.rar

534.18 KB, 下载次数: 525, 下载积分: 吾爱币 -1 CB

免费评分

参与人数 5威望 +8 热心值 +2 收起 理由
friendy + 1 我很赞同!
297044530 + 1 大牛威武啊~~~膜拜啊
wgz001 + 3 精品文章 支持
mycsy + 3 2威望怎么能形容超人的超!
zzage + 2 精品文章

查看全部评分

本帖被以下淘专辑推荐:

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

a2053216518 发表于 2014-11-1 12:08
大大,,这个公式我还不是很明白:数据的文件偏移 = (数据的内存RVA-数据所在节的RVA)+数据所在节的文件偏移

数据的内存RVA=虚拟地址
数据所在节的RVA=rva地址
数据所在节的文件偏移=BSJB搜索出来的偏移


这样理解对吗??
qq513701092 发表于 2009-1-20 17:01
bensonhb 发表于 2009-1-20 17:25
没啥好说的,顶就一个字了,收藏起来以后再看!!!!!
dgqb2008 发表于 2009-1-20 18:37
实在强大  佩服  佩服
zapline 发表于 2009-1-20 18:45
膜拜!
超神力收徒弟不?
mycsy 发表于 2009-1-21 19:24
必须收藏!!!

以备后用!!!

过段时间在写个CM.NET
shsww 发表于 2009-1-21 21:20
这个的确强悍!直接看不懂啊!
hbfp 发表于 2009-1-22 12:24
没动过NET程序,收藏一份.
darwen 发表于 2009-1-22 15:56

学习了 谢谢楼主 啊

看看有没有我期待的?  帮楼主顶了
wgz001 发表于 2009-1-22 17:29
超大   只有膜拜的分    :)
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

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

GMT+8, 2024-11-15 10:12

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

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