需要用到的工具有
- https://down.52pojie.cn/Tools/PEtools/PE.Tools.v1.9.762.2018.zip
- ildasm
- https://down.52pojie.cn/Tools/NET/ILSpy_Master_2.3.1.1855_Binaries.zip
- DOBSTR 很老的一个工具.在<加密与解密 第三版>随书光盘里面才有 下载地址 https://download.csdn.net/download/gqhyz/3203429 在目录 /chap09/工具/反混淆/ 下
第一个方法: 用PEtools选择 exe 进程 右键dump full 可以得到一个新的exe文件 拖入 ILSpy后 可以看到逻辑代码
但是字符串还是处于混淆状态.
第二个方法: 用ILDSAM将被混淆的程序集反编译为IL文件,反编译时只改变编码为Unicode,其他不变,用DOBSTR打开这个IL文件,并选择保存位置,点击 “反混淆”,程序将生成反混淆后的IL文件.(注意:打开dobstr后 选择一下指定方法 选择程序集就使用dobstr同目录的decode.dll 请使用全路径) 其他不改. 注释选项选择不注释.
生成反混淆后的IL文件后.使用windows 系统下.NET目录(例如:C:\Windows\Microsoft.NET\Framework\v2.0.50727)的ilasm重新将il文件编译为dll或者exe 命令如下:
ilasm /exe /output=d:\server\iltoexe_server.exe d:\server\server1.il
这时候将 iltoexe_server.exe 拖入ILSpy, 有惊喜.
但是也不一定全部过程都成功. dobstr反混淆 和 ilasm重新编译过程中都会有可能出现错误.
之前的代码
之后的代码
一些具体细节
通过反编译 dobstr的源代码可以看到它直接从il文件中读取bytearray类型的字符串 然后导入解密函数进行解密.可能由于程序的多样性,dobstr 的解密算法已经硬编码在内部了. 遇到dobstr出错的时候,可以自己提取il里面的bytearray自己手工解密
以下是使用ILDSAM 反编译后获取的IL中间语音代码片段:
IL_0470: ldstr bytearray (17 68 32 6F 1E 76 28 7D 2A 84 F5 8A 15 92 12 99 ) // .h2o.v(}*.......
IL_0475: ldc.i4 0xff167c3
其中 ldstr是已经混淆过了的字符串
ldc.i4 是一个整数 用于参与反混淆过程
附上反混淆解密方法:
public string cc381ffa3ede662f(string e4115acdf4fbfccc, int 211566702b710682)
{
char[] array = e4115acdf4fbfccc.ToCharArray();
for (int i = 0; i < array.Length; i++)
{
array[i] = (char)((int)array[i] - 211566702b710682);
211566702b710682 += 1789;
}
return new string(array);
}
反混淆过程如下:
首先拿到ldstr 字符串 17 68 32 6F 1E 76 28 7D 2A 84 F5 8A 15 92 12 99
4位一组.两两对调.用\u进行拼接,得到新的字符串:\u6817\u6f32\u761e\u7d28\u842a\u8af5\u9215\u9912
再拿出ldc.i4 0xff167c3 进行16进制转换10进制 得到整数 267478979 再传入上面的反混淆函数.即可得到想要的字符串.
以下是我自己写的一个demo C#的解密代码
static void Main(string[] args)
{
string strOrgStr = "\u6817\u6f32\u761e\u7d28\u842a\u8af5\u9215\u9912";
char[] array = strOrgStr.ToCharArray();
int ccc = 267478979;
for (int i = 0; i < array.Length; i++){
char b = (char)((int)array[i] - ccc);
ccc += 1789;
Console.Write(b);
}
Console.Write("\r\nPress any key to continue....");
Console.Read();
}
这个是dobstr 调用自己写的程序集来解密,dobstr 程序还有一些问题.
// ConsoleApplication3.Form1
public string Decrypt(string str, int radix)
{
string result;
try
{
Assembly assembly = Assembly.LoadFrom(this.indll.Text);
Type type = assembly.GetType(this.Namespace.Text);
object[] array = new object[]
{
str,
radix
};
Type[] array2 = new Type[array.Length];
for (int i = 0; i < array.Length; i++)
{
array2[i] = array[i].GetType();
}
BindingFlags bindingFlags = 24;
MethodInfo method = type.GetMethod(this.Method.Text, bindingFlags, null, array2, null);
object obj = method.Invoke(null, array);
result = obj.ToString();
}
catch
{
this.OutPut.AppendText("错误:解密字符串失败!\r\n");
this.OutPut.AppendText("请检查调用的解密方法是否正确!\r\n");
this.OutPut.AppendText("\r\n");
this.bTest = false;
result = "";
}
return result;
}
这个是硬编码了的解密函数
// ConsoleApplication3.Form1
public string Decrypt(string strOrgStr, string strRadix)
{
string text = strOrgStr.Replace(" ", "");
text = text.Trim();
int num = text.get_Length() / 4;
int[] array = new int[num];
char[] array2 = new char[num];
for (int i = 0; i < num; i++)
{
string text2 = text.Substring(4 * i + 2, 2) + text.Substring(4 * i, 2);
array[i] = int.Parse(text2, 515);
array2[i] = (char)array[i];
}
string text3 = new string(array2);
text3.Trim();
int radix = int.Parse(strRadix, 515);
string text4 = this.Decrypt(text3, radix);
text4 = text4.Trim();
string text5 = text4;
byte[] bytes = Encoding.get_Unicode().GetBytes(text4);
text4 = Form1.HexTest.ToHexString(bytes);
text4 = text4.Trim();
string text6 = "";
for (int j = 0; j < text4.get_Length() / 2; j++)
{
string text2 = text4.Substring(j * 2, 2) + ' ';
text6 += text2;
}
text6 += ')';
if (this.BaStyle.Checked)
{
text6 = text6 + " //" + text5;
}
return text6;
}