攻防世界 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}
posted @ 2024-04-10 12:32  C4emc1oudy  阅读(35)  评论(0编辑  收藏  举报