攻防世界 debug
题目
分析过程
丢到PE里面
一开始,我看到下面的脱壳提示,以为是我没见过的壳,下载了相关工具脱壳——发现脱了后又出现没见过的脱壳提示,根据提示脱壳弄出来的东西怪怪的
卡题,查了资料
学到一个新知识点:这是一个.NET文件,不脱壳也是可以的,不能用IDA
关于.NET的工具,我下了几个体验了一下同时询问了群里的大佬,在这里提供两个:ILSpy和dnSpy
工具下载:爱盘里面都有 爱盘 - 最新的在线破解工具包 (52pojie.cn)
个人比较喜欢ILSpy的代码
可以看出函数名字都是乱码,总体上不影响阅读与理解
我看大佬的wp,发现佬直接拿原文件调试,将dnSpy(辅助)与ILSpy(主体)结合分析解出flag
但是,我在瞎倒腾脱壳过程中意外发现了一件事
根据PE的脱壳提示,使用de4bot,再丢进ILSpy里面,函数名字竟然出现了
这里了解到了一点:de4dot是一个很强的.Net程序脱壳,反混淆工具,可以利用de4dot解密被混淆的.NET代码
更多:[入门级]de4dot参数详解 - 『脱壳破解区』 - 吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn
乱码的函数名字应该是混淆的结果,利用工具反混淆后就恢复了
先看看main函数
1 private static void Main(string[] args) 2 { 3 string string_ = null;//初始化一个字符串string_ 4 string value = $"{DateTime.Now.Hour + 1}";//获取当前时间的小时部分加1,得到的结果转换成字符串并赋给value 5 string string_2 = "CreateByTenshine";//string_2里面放了字符串 CreateByTenshine 6 smethod_2(string_2, Convert.ToInt32(value), ref string_);//发生了函数调用,Convert.ToInt32(value)是将value字符串转换成整数 7 string text = Console.ReadLine();//获得用户的输入,储存在text 8 if (text == string_) 9 { 10 Console.WriteLine("u got it!"); 11 Console.ReadKey(intercept: true); 12 } 13 else 14 { 15 Console.Write("wrong"); 16 } 17 Console.ReadKey(intercept: true); 18 }
调用了以下函数
1 private static void smethod_2(string string_0, int int_0, ref string string_1) 2 { 3 int num = 0; 4 if (0 < string_0.Length) 5 { 6 do 7 { 8 char c = string_0[num]; 9 int num2 = 1; 10 do 11 { 12 //发生函数调用,将c的整数值和num2作为参数传递给它,然后将返回值转换为字符并赋给c 13 c = Convert.ToChar(smethod_0(Convert.ToInt32(c), num2));//注意这里,下标是从1遍历到14,不是15,不懂的可以简单写一个程序实验一下 14 num2++; 15 } while (num2 < 15); 16 string_1 += c; 17 num++; 18 } while (num < string_0.Length); 19 } 20 string_1 = smethod_1(string_1);//函数调用 21 }
调用了下面函数,以及下下一个函数
1 //string_1 = smethod_1(string_1) 2 private static string smethod_1(string string_0) 3 { 4 byte[] bytes = Encoding.ASCII.GetBytes(string_0);//将输入的字符串变为ASCII编码的字节数组,储存在bytes 5 return "flag{" + BitConverter.ToString(new MD5CryptoServiceProvider().ComputeHash(bytes)).Replace("-", "") + "}"; 6 //创建一个新的MD5CryptoServiceProvider实例 7 //调用ComputeHash方法来计算给定字节数组bytes的MD5哈希值,赋值给MD5CryptoServiceProvider 8 //BitConverter.ToString(...):将计算得到的MD5转换为一个由十六进制字符组成的字符串,每个字节用两个字符表示,并且字节之间没有分隔符 9 // .Replace("-", ""): 将生成的十六进制字符串中的所有连字符"-"替换为空字符串"" 10 }
1 //smethod_0(Convert.ToInt32(c), num2) 2 private static int smethod_0(int int_0, int int_1) 3 { 4 return (new int[30]//根据上面下标是1~14,而数组里面有30个,记得去掉不需要的 5 { 6 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 7 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 8 73, 79, 83, 89, 97, 101, 103, 107, 109, 113 9 })[int_1] ^ int_0;//将输入异或 10 }
解密脚本
在这里我犯了一个错误,真是被自己蠢笑了
给你们看看我第一次写的错误代码
1 import hashlib 2 3 str2 = "CreateByTenshine" 4 str1 = [3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47] # 1~14 5 flag = "" 6 7 for i in str2: 8 for j in str1: 9 c = chr(j ^ ord(i)) 10 flag += c 11 12 flag = hashlib.md5(flag.encode()).hexdigest() 13 print(flag) 14 15 ##d539a7cd4194bebe05e544521c9c2405
在第9行,c只会包含每次外部循环迭代中最后一个异或操作的结果,每循环一次c都会刷新
我们再看看反汇编代码:c = Convert.ToChar(smethod_0(Convert.ToInt32(c), num2))——c就是str2
是拿str2的元素作为参数进行函数调用,再赋值回去
修改后的正确代码:
1 import hashlib 2 3 str2 = "CreateByTenshine" 4 str1 = [3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47] # 1~14 5 flag = "" 6 7 for i in str2: 8 for j in str1: 9 i = chr(j ^ ord(i))##这里由c变为i 10 flag += i 11 12 flag = hashlib.md5(flag.encode()).hexdigest() 13 print(flag)
flag
flag{967dddfbcd32c1f53527c221d9e40a0}