首页 > 其他分享 >攻防世界Reverse三星题 zorropub

攻防世界Reverse三星题 zorropub

时间:2024-04-10 17:55:37浏览次数:25  
标签:__ 攻防 Reverse rbp char zorropub seed rsp MD5

题目


分析过程 

丢到PE里面,无壳,64bit

丢到IDA里面,查看mian函数

 1 int __fastcall main(int a1, char **a2, char **a3)
 2 {
 3   size_t s_len; // rax
 4   int drink_ID; // [rsp+1Ch] [rbp-104h] BYREF
 5   int input; // [rsp+20h] [rbp-100h] BYREF
 6   int i; // [rsp+24h] [rbp-FCh]
 7   unsigned int seed; // [rsp+28h] [rbp-F8h]
 8   unsigned int v9; // [rsp+2Ch] [rbp-F4h]
 9   char MD5__[96]; // [rsp+30h] [rbp-F0h] BYREF
10   char MD5__1[16]; // [rsp+90h] [rbp-90h] BYREF
11   char v12[32]; // [rsp+A0h] [rbp-80h] BYREF
12   char s[32]; // [rsp+C0h] [rbp-60h] BYREF
13   char s1[40]; // [rsp+E0h] [rbp-40h] BYREF
14   unsigned __int64 v15; // [rsp+108h] [rbp-18h]
15 
16   v15 = __readfsqword(0x28u);
17   seed = 0;
18   puts("Welcome to Pub Zorro!!");
19   printf("Straight to the point. How many drinks you want?");
20   __isoc99_scanf("%d", &drink_ID);
21   if ( drink_ID <= 0 )
22   {
23     printf("You are too drunk!! Get Out!!");
24     exit(-1);
25   }
26   printf("OK. I need details of all the drinks. Give me %d drink ids:", (unsigned int)drink_ID);
27   for ( i = 0; i < drink_ID; ++i )              // 输入的drink_ID决定了input的数量
28   {
29     __isoc99_scanf("%d", &input);
30     if ( input <= 16 || input > 65535 )         // 16<input<65535
31     {
32       puts("Invalid Drink Id.");                // 无效的饮料ID。
33       printf("Get Out!!");
34       exit(-1);
35     }
36     seed ^= input;                              // 与自己异或
37   }
38   i = seed;
39   v9 = 0;
40   while ( i )
41   {
42     ++v9;                                       // 循环了10次
43     i &= i - 1;
44   }
45   if ( v9 != 10 )                               // v9=10
46   {
47     puts("Looks like its a dangerous combination of drinks right there.");// 看起来这是一种危险的饮品组合。
48     puts("Get Out, you will get yourself killed");
49     exit(-1);
50   }
51   srand(seed);                                  // seed是rand()的种子,用来初始化rand()的起始值,该函数不返回任何值
52   MD5_Init(MD5__);                              // 产生一个128位(16字节)的哈希值,通常表示为一个32字符的十六进制数
53   for ( i = 0; i <= 29; ++i )
54   {
55     v9 = rand() % 1000;                         // 会自动调用srand(seed)一次来初始化它的起始值
56                                                 // 随机数的范围限制在0到999
57     sprintf(s, "%d", v9);                       // 这一行将整数值v9转换为字符串表示,并将其存储在字符数组s
58     s_len = strlen(s);
59     MD5_Update(MD5__, s, s_len);                // 执行MD5_Update函数更新md5的值
60     v12[i] = v9 ^ LOBYTE(dword_6020C0[i]);      // 低字节进行按位异或操作
61   }
62   v12[i] = 0;                                   // 加上终止符
63   MD5_Final(MD5__1, MD5__);                     // 计算MD__的哈希值放在前面
64   for ( i = 0; i <= 15; ++i )
65     sprintf(&s1[2 * i], "%02x", (unsigned __int8)MD5__1[i]);// 每个MD5哈希字节的十六进制表示占用两个字符的位置,所以这个2就是遍历吧
66                                                 // X 表示以十六进制形式输出;02 表示不足两位,前面补0输出;如果超过两位,则实际输出
67                                                 // 只取MD5__1[i]字节的低8位
68   if ( strcmp(s1, "5eba99aff105c9ff6a1a913e343fec67") )// s1=5eba99aff105c9ff6a1a913e343fec67
69   {
70     puts("Try different mix, This mix is too sloppy");// 试试不同的调料,这个调料太马虎了
71     exit(-1);
72   }
73   return printf("\nYou choose right mix and here is your reward: The flag is nullcon{%s}\n", v12);// \n您选择正确的混合,这是您的奖励:旗帜是空号{%S}\n
74 }

为了更好理解,注释中一些零碎知识点的补充:

MD5_Init(MD5__);MD5_Final(MD5__1, MD5__);MD5_Final(MD5__1, MD5__);

int MD5_Init(MD5_CTX *c)函数:
初始化 MD5 Contex, 成功返回1,失败返回0
.
int MD5_Update(MD5_CTX *c, const void *data, size_t len)函数:
循环调用此函数,可以将不同的数据加在一起计算MD5,成功返回1,失败返回
.
int MD5_Final(unsigned char *md, MD5_CTX *c)函数:
输出MD5结果数据,成功返回1,失败返回0
.
unsigned char *MD5(const unsigned char *d, size_t n, unsigned char *md)函数:
MD5_Init,MD5_Update,MD5_Final三个函数的组合,直接计算出MD5的值
.
void MD5_Transform(MD5_CTX *c, const unsigned char *b)函数:
内部函数,不需要调用

可以结合代码看:C语言 Openssl的md5使用方式_#include <openssl/md5.h>-CSDN博客


sprintf(&s1[2 * i], "%02x", (unsigned __int8)MD5__1[i])

X 表示以十六进制形式输出
02 表示不足两位,前面补0输出;如果超过两位,则实际输出

更多看:C语言中printf打印形式(%02X, %2X, %-2X, %.nf, %m.nf, %e, %m.ne, %2d, %-2d, %02d, %.2d)_printf %.2x-CSDN博客

补充结束,看看代码——

有两个输入(方便理解我改了名字):一个是drink_ID,另一个为input——>前者决定了后者的数量,两个一起决定了seed

seed满足一定条件后可以作为srand的种子:v9=10 以及 异或后得到赋值的i可以开启循环

这里涉及到伪随机数生成以及随机数种子的概念:

1.伪随机数生成器:计算机中的随机数通常是由伪随机数生成器生成的。这些生成器实际上是确定性算法,其输出看起来像是随机的序列,但实际上是基于一个称为“种子”的初始值来生成的。相同的种子将会生成相同的随机数序列。

2.srand() 和 rand() 函数:在 C 和 C++ 中,srand()用于设置随机数生成器的种子,而rand()用于生成随机数。如果你不调用srand()来设置种子,rand()将使用默认的种子(通常是系统时间),因此每次程序运行时都会生成不同的随机数序列。但是,如果你在每次运行程序时使用相同的种子,那么生成的随机数序列将始终相同。

更多看:随机函数 rand() srand() 以及seed的原理_srand函数原理-CSDN博客

v9是用特定 seed 随机数种子生成的特定的列表,后来由整数转化为字符串储存在 s 中

再把 s 更新到MD5__中,因为MD5__就只放了 s ,所以就是计算 s 的哈希值,储存在MD5__1中

MD5__1又经过遍历放在s1里面,最后s1要等于5eba99aff105c9ff6a1a913e343fec67——这就是v9经过MD5加密后得到的哈希值

v9还与dword_6020C0进行了异或操作,结果放在v12中,最后输出的flag就是v12

 

综上,只要v9满足条件:经过MD5加密后的值等于5eba99aff105c9ff6a1a913e343fec67,那么v9与dword_6020C0异或就可以得到flag


逆向脚本

不太会MD5py解密脚本,网上找到的没有运行出来的,就算拿5eba99aff105c9ff6a1a913e343fec67去MD5解密网站,也没有输出结果

搬了大佬的wp,下边就是爆破MD5等算法的爆破脚本

 1 import subprocess
 2 c=0
 3 seed=[]    #v5和v6都是用于生成seed种子,所以可以合并成一步
 4 for i in range(16,65535,1):    #源代码中是先i=seed再验证i的符合性,所以逆向的时候就要先验证i的符合性再seed=i
 5     while(i):
 6         c+=1
 7         i&=i-1
 8     if(c==10):
 9         seed.append(i)        #获取随机数种子列表,种子固定后rand生成的随机数就会固定。
10 flag=""
11 for i in seed:        #传入符合的i值,其实就是传入一定的seed值,
12     proc=subprocess.Popen(['./zorropub'],stdin=subprocess.PIPE,stdout=subprocess.PIPE);    #用subprocess的Popen方法开启proc子进程并用stdin和stdout获取子进程的输入和输出
13     out=proc.communicate(('1\n%s\n'%i).encode('utf-8'))[0]    #传入参数,第一个传入1即可,第二个传入符合的seed种子,第一个无论传入多少生成的seed都只有一个,所以传入1即可。用.encode('utf-8')属性可以传入字符串参数,不然就要传入bytes类型的参数了    
14     if "nullcon".encode('utf-8') in out:
15         print(out)    #打印符合的输出字符串
16         print(i)    #打印符合的seed值

这道题好像挺老的,我运行不出来(悲),但是学到了新的知识点:python subprocess模块 - lincappu - 博客园 (cnblogs.com)

 我还发现一个pwn大佬的脚本

 1 from pwn import*
 2 import time
 3 time1=time.time()
 4 a=[]
 5 
 6 for i in range(16,0xffff):
 7     v9=0
 8     i=i^0
 9     j=i
10     while(i):
11         v9+=1
12         i&=i-1
13     if v9 ==10:
14         a.append(j)
15 //数组已经弄好了
16 
17 for i in a:
18     p=process("./zorropub")
19     p.recv()
20     p.sendline('1')
21     p.sendline(str(i))//emmm,觉得int的也ok
22     result=p.recv()
23     if "null" in text:
24         print text
25         time2=time.time()
26         print "time %fs"%(time2-time1)
27         break
28 p.close()

还有吾爱破解大佬用动调试解出来了,我还不太会ubuntu中的VSCODE调试,插个眼以后再详细说说
这里也放上:CTF攻防世界Reverse018_zorropub逆向分析【原创】 - 『脱壳破解区』 - 吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn


flag

 

nullcon{nu11c0n_s4yz_x0r1n6_1s_4m4z1ng}

 

标签:__,攻防,Reverse,rbp,char,zorropub,seed,rsp,MD5
From: https://www.cnblogs.com/demo41/p/18126451

相关文章

  • uRPF(Unicast Reverse Path Forwarding,单播反向路径转发)
    uRPF(UnicastReversePathForwarding)概念和原理这是网络设备的一个安全特性,主要功能是用于防止基于源地址欺骗的网络攻击行为,说简单一点就是在IP数据包转发的时候不单基于目的地址查看路由表,对源地址同样进行查表,如未能查到路由(一般不是默认路由,但根据策略不同行为稍有区别),则......
  • 攻防世界 debug
    题目分析过程丢到PE里面 一开始,我看到下面的脱壳提示,以为是我没见过的壳,下载了相关工具脱壳——发现脱了后又出现没见过的脱壳提示,根据提示脱壳弄出来的东西怪怪的卡题,查了资料学到一个新知识点:这是一个.NET文件,不脱壳也是可以的,不能用IDA关于.NET的工具,我下了几个体验......
  • 【攻防实操系列+内网渗透】--第1章:内网渗透测试基础①
    内网也指局域网(LocalAreaNetwork,LAN),是指在某一区域内由多台计算机互连而成的计算机组,组网范围通常在数千米以内。在局域网中,可以实现文件管理、应用软件共享、打印机共享、工作组内的日程安排、电子邮件和传真通信服务等。内网是封闭的,可以由办公室内的两台计算机组成,也......
  • 网络攻防中黑客常用的信息收集手段以及信息泄漏途径,详细方法以及工具介绍
    网络攻防中黑客常用的信息收集手段以及信息泄漏途径,详细方法以及工具介绍。网络攻防中的信息收集是黑客攻击前的重要步骤,其目的是通过各种手段获取目标网络的详细信息,以便为后续的攻击活动提供支持。信息收集的手段多种多样,包括但不限于网络扫描、社会工程学、数据挖掘等。......
  • 中间件漏洞攻防学习总结
    前言面试常问的一些中间件,学习总结一下。以下环境分别使用vulhub和vulfocus复现。Apacheapache文件上传(CVE-2017-15715)描述:Apache(音译为阿帕奇)是世界使用排名第一的Web服务器软件。它可以运行在几乎所有广泛使用的计算机平台上,由于其跨平台和安全性被广泛使用,是最流行......
  • 【攻防实操系列+域渗透】--域内主机(win7)配置
    1.设置静态IP,将DNS指向域控DNS的作用:定位域控2.创建域用户密码③❗❗❗至此,域内用户已经创建完成。3.把用户加入域❗会让你立即重启。切换用户,输入:new.com\lyj密码③❗❗❗至此,就是域内主机(win7)的大概配置了。......
  • 【攻防实操系列+域渗透】--安装域控(Windows-Server-2008-R2-x64)教程
    1.创建windows2008R2虚拟机选完全安装。第一个是标准版功能很少。不建议选。另外两个任意选。我选的是Enterprse企业版。❗❗❗注意:需要提前了解域控的密码复杂度规则。密码一定要自己记住!!!密码①可以看到界面非常小,不方便操作。❗❗❗需要安装vm......
  • 深入理解PHP+Redis实现布隆过滤器(亿级大数据处理和黑客攻防必备)
    布隆过滤器极简概括英文名称BloomFilter,用于判断一个元素是否在一个大数据集合中,如果检测到存在则有可能存在,如果不存在则一定不存在。Redis官网对于布隆过滤器的说明:https://redis.io/docs/data-types/probabilistic/bloom-filter/使用场景防止缓存穿透:用于快速判断某个商......
  • 攻防世界 Mine- IDA静调或x64dbg动调 两种方式
    刷攻防世界的最后一道二星题,记录一下,大佬请飘过 题目分析过程我很勇,我先双击看看这是什么是一个扫雷游戏,第一下运气好没踩雷,发现无法继续输入了;如果运气不好,会输出“您踩雷啦!”丢到PE里面 无壳,64位丢到IDA里面,shif+F12查看字符串,追踪可疑字符串,发现main函数1in......
  • 红队攻防之PowerShell基础免杀(二)
    Getbusylivingorgetbusydying什么是图片免杀?答:一般情况下,某些AV对图像未执行检测处理。这种情况下,它们可以仅使用有效负载数据来生成新图像,或将有效负载嵌入到现有图像的最低有效字节中,使其看起来像实际图像。这些图像以PNG格式保存,可进行无损压缩,不影响执行有效......