avatar

目录
.Net逆向(PC逆向4)

NET逆向1.0

先查壳,把软件拖进ScanId,显示结果是无,或者未知

查了无壳以后,把软件拉进dnSpy,拉进去界面就是这样。

.NET破解,其实就是看得懂代码就好了,看不懂代码也就没办法了,一些函数使用,去百度看下解释,也就差不多了。

一个一个点开,可以看见一个form1_Load的函数,因为.NET,采用MFC,所以窗体通常是form1,form2命名嘛,所以这里很可疑。

先理解一下这个函数的每句代码的意思

然后就可以知道这里很明显就是突破口,如果flag为真,就结束当前窗口,显示登陆后的窗口,那么,只要把这个判断,删掉,按照OD中,就是NOP掉他,不管怎么样都显示,不就完事了吗。

c#
1
2
3
4
5
if(flag)
{
break;
}
logon.ShowDialog();

说搞就搞,把判断删掉,然后点击右下角的Compile,但是报错,尝试处理了下,发现处理不了,那就只能从别的地方入手了

右键,这里有个编辑IL指令,点击进去看看

好了,看不懂,不过对比源码看了看,好像还是能看懂的,因为要处理的地方是判断,那个IF那里嘛,然后IF上面有个字符串比较函数Equlas,看了看这个IL指令,发现就有了,然后对stloc.3,ldloc.3都修改下,一个一个琢磨,一个一个测试

随便切换了一下,哪个ldloc.3,我改成ldloc.2,就从flag改成了text,现在阅读了一下代码

c#
1
2
3
4
5
6
7
8
9
logon logon = new logon();//窗口对象
string value = logon.readFile("reg.dat");//输入进来的注册码
string text = MD5Encrypt.MD51(new HardwareInfo().GetCpuID(), "");//机器码
bool flag = MD5Encrypt.MD51(text + "pcg7410852.", "").Equals(value);//对比
if (text != null)//如果机器码不等于空
{
break;//结束当前窗口
}
logon.ShowDialog();//显示后面的窗口

这样子也符合破解的效果。


.NET逆向2.0

刚才的程序,换一种破解思路,将那个注册码显示出来。

在这个logon_Load的函数中

c#
1
2
3
4
5
private void logon_Load(object sender, EventArgs e)
{
this.jqm.Text = MD5Encrypt.MD51(new HardwareInfo().GetCpuID(), "");//机器码
this.zcm.Text = logon.readFile("reg.dat");//读取输入进来的注册码
}

回到刚才那个form1_Load,那个Flag变量里面,就有一个比较,可以看出那个就是注册码的算法,把它复制过来

c#
1
MD5Encrypt.MD51(text + "pcg7410852.", "")

然后对这个函数进行修改,使其初始化时候输出正确的注册码

c#
1
2
3
4
5
private void logon_Load(object sender, EventArgs e)
{
this.jqm.Text = MD5Encrypt.MD51(new HardwareInfo().GetCpuID(), "");//机器码
this.zcm.Text = MD5Encrypt.MD51(this.jqm.Text + "pcg7410852.", "");//读取输入进来的注册码
}

然后保存模块,导出软件,启动.


.NET逆向3.0

这是一个转换工具,查了无壳,直接拖进dnSpy

reg一看就是注册函数,点进去,每个函数都看一下,get_reg_code按照理解就是获取注册码,Is_Reg而且是布尔类型,就是判断是否注册成功,所以这两个函数都可以是入口点

get_reg_codereturn处下断,查看返回的值

启动软件,然后运行时候,看下方,返回了四个值

machine_code:是机器码

num:是个十六进制的值

text:是个十进制的值

i:循环的次数

对代码阅读一下,就可以看出来,num就是返回的注册码,ToString()就是转为十进制,没准text就是注册码。

但是返回的是错的

在查看了一下代码,觉得没道理啊,没可能错的,除非num十六进制转回来不是这个值,拉到网站上转换一下

还真的不是,最后面少了一个4


.NET逆向4.0

拖进查壳软件,发现有混淆,首先去混淆

成功以后,桌面上就会多一个程序,再次查看,就是无了。

打开软件看一看,右上角有个立即注册,输入注册码显示注册失败,那么思路很清晰了,和刚才的差不多

把软件拖进dnSpy,点击资源那里,有个授权,点进去,有个button的函数

代码就是下面这个👇:

c#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
using System;
using System.ComponentModel;
using System.IO;
using System.Windows.Forms;

// Token: 0x02000009 RID: 9
public partial class 授权 : Form
{
public // Token: 0x0600005F RID: 95
void button1_Click(object sender, EventArgs e)
{
if (this.textBox1.Text != this.method_1())//判断输入进来的值与method_1是否相等,那么将等于改为不等于就好 了
{
if (!Directory.Exists(Class0.string_1))//没看懂这函数啥意思,不过好像没多大关系
{
Directory.CreateDirectory(Class0.string_1);
}
File.WriteAllLines(Class0.string_3, new string[] // 也没看懂
{
this.textBox1.Text
});
MessageBox.Show("注册成功");
base.DialogResult = DialogResult.OK;
return;
}
MessageBox.Show("注册失败");
}
}

另一种思路

跟进去method_1()函数,在return下断,启动程序,随便注册码观察返回值

text的值复制出来,然后直接粘贴进去,发现注册失败,那就只能在想办法了

按照他代码,这里既然是判断是否相等,那么就可以按照之前那样子干,把输入框的值,直接等于method_1返回的值就好了

但是在此启动,发现还是不行,然后我就试了一下,把它保存下来以后,在启动,就可以了

在物理机,也试过把算法提出来,因为他是通过ToBase64String加密的,一开始思路一直围绕着这个Base64加密,后面通过FromBase64String解密出来,才发现自己思路错了,在认真看了看代码,他根本就没有解密,而是直接调用这个加密后的值

c#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
using System;
using System.ComponentModel;
using System.Drawing;
using System.IO;
using System.Management;
using System.Security.Cryptography;
using System.Text;

namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
Program sj = new Program();
string a = sj.method_1();
Console.WriteLine("a:"+a);
Console.ReadLine();
}
public string method_0()
{

string result;
try
{
ManagementObjectSearcher managementObjectSearcher = new ManagementObjectSearcher("SELECT * FROM Win32_PhysicalMedia");
string text = "";
using (ManagementObjectCollection.ManagementObjectEnumerator enumerator = managementObjectSearcher.Get().GetEnumerator())
{
if (enumerator.MoveNext())
{
ManagementObject managementObject = (ManagementObject)enumerator.Current;
text = managementObject["SerialNumber"].ToString().Trim();
}
}
result = text;

}
catch
{
result = "";
}
return result;
}
public string method_1()
{
string text = this.method_0();
Console.WriteLine(text);
int num;

for (int i = 0; i < 10; i = num + 1)
{
text = this.method_2(text);

byte[] newBytes = Convert.FromBase64String("FCHBzqD1trtYq6uxx88taw==");
Console.WriteLine("The restored byte array: ");
Console.WriteLine(text);
Console.WriteLine(" {0}\n", BitConverter.ToString(newBytes));
num = i;
}
return text;
}
public string method_2(string string_0)
{
MD5 mD = MD5.Create();
string text = "";
byte[] inArray = mD.ComputeHash(Encoding.UTF8.GetBytes(string_0));

return Convert.ToBase64String(inArray);
}

}
}

.NET 加密 DNGuard HVM 的壳,逆不了,听说市场逆这个壳就得上W了

文章作者: KeyboArd
文章链接: https://www.wrpzkb.cn/pojie4/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 KeyboArd's Blog
打赏
  • 微信
    微信
  • 支付寶
    支付寶

评论