攻防世界reverse-box

news/2024/5/19 21:36:15 标签: c++, gdb, ctf, re

题目下载:下载

这道题有两种方法,一个是写c来解,另一个是用ref="/tags/GDB.html" title=gdb>gdb脚本。

经查wp知道,这道题攻防世界中少给了条件:

挑战描述
$ ./reverse_box ${FLAG}
95eeaf95ef94234999582f722f492f72b19a7aaf72e6e776b57aee722fe77ab5ad9aaeb156729676ae7a236d99b1df4a
flag格式:TWCTF{}

也就是你运行这个文件的时候,输入一字符串(flag),然后会回显'95eeaf95ef94234999582f722f492f72b19a7aaf72e6e776b57aee722fe77ab5ad9aaeb156729676ae7a236d99b1df4a'

载入IDA

发现有个if语句,其中a1,a2是main函数的形参

一般来说,我们写main函数,就定义main(),它的参数部分看似没有,实际上,main函数也是有参数的,只是在我们写时省略了。

main函数的参数由三部分组成,分别是argc(int型,表示命令行参数的个数)、argv[](char数组型,指向命令行的每一个命令参数)、envp[](char数组型,指向环境变量)。

说明:argc包括程序本身,所以它大于等于1。argv以NULL结尾,且也包括程序本身,所以它的元素个数大于等于2。
—摘自https://blog.csdn.net/smell201611010513/article/details/80130941
 

所以当我们运行可执行文件不进行输入的时候,即a1==1,会输出特定的东西"./reverse_box"

 而当输入一些东西的时候就会经过sub_804858D(v4)变化,并且发现每次输出不太一样

既然题目要求是输入flag就会回显特定的字符串,那一定是经过如下操作:

即输入作为下标,在v4当中索引一个值然后输出,又因为输入一定有'TWCTF{}',所以可以推断v4[84]=0x95,v4[87]=0xee,v4[67]=0xaf,v4[84]=0x95,v4[70]=0xef,v4[123]=0x94,v4[125]=0x4a,这可以作为后面爆破的一个条件。

那进入sub_804858D(v4)看看变化:

re>int __cdecl sub_804858D(_BYTE *a1) { unsigned int v1; // eax char v2; // al char v3; // al int v4; // ecx int v5; // eax int v6; // ecx int v7; // eax int v8; // ecx int v9; // eax int v10; // ecx int result; // eax char v12; // [esp+1Ah] [ebp-Eh] unsigned __int8 v13; // [esp+1Bh] [ebp-Dh] char v14; // [esp+1Bh] [ebp-Dh] char v15; // [esp+1Bh] [ebp-Dh] int v16; // [esp+1Ch] [ebp-Ch] v1 = time(0); srand(v1); do v16 = rand(); // 如果是0的话会继续rand() while ( !v16 ); *a1 = v16; // v16一定不是0 v12 = 1; v13 = 1; do { if ( v12 >= 0 ) v2 = 0; else v2 = 27; v12 ^= (2 * v12) ^ v2; v14 = (4 * ((2 * v13) ^ v13)) ^ (2 * v13) ^ v13; v15 = (16 * v14) ^ v14; if ( v15 >= 0 ) v3 = 0; else v3 = 9; v13 = v15 ^ v3; v4 = v13; LOBYTE(v4) = __ROR1__(v13, 7); v5 = v4 ^ (v13 ^ *a1); v6 = v13; LOBYTE(v6) = __ROR1__(v13, 6); v7 = v6 ^ v5; v8 = v13; LOBYTE(v8) = __ROR1__(v13, 5); v9 = v8 ^ v7; v10 = v13; LOBYTE(v10) = __ROR1__(v13, 4); result = v10 ^ v9; a1[v12] = result; } while ( v12 != 1 ); return result; }re>

 发现有一个rand()函数(这是不是和前面同一输入但不同输出有关呢),然后在经过一系列的操作就能得到v4数组,又因为v16不同所以得到的v4数组也不同,所以就要根据前面的条件v4[84]=0x95,v4[87]=0xee,v4[67]=0xaf,v4[84]=0x95,v4[70]=0xef,v4[123]=0x94,v4[125]=0x4a爆破符合条件的v4数组。

还有一个疑问就是rand生成的数范围是多少?看一看汇编代码,

 所以应该是0-255之间,所以根据给的伪代码可以写出c,求出v4数组

re>#include <stdio.h> #include <stdlib.h> #include <string.h> int __ROR1__(unsigned __int8 value,int x){ value= (value>>x) | (value<<(8-x)); return value; } int main(){ unsigned int v1; // eax char v2; // al char v3; // al int v4; // ecx int v5; // eax int v6; // ecx int v7; // eax int v8; // ecx int v9; // eax int v10; // ecx int result; // eax char v12; // [esp+1Ah] [ebp-Eh] unsigned __int8 v13; // [esp+1Bh] [ebp-Dh] char v14; // [esp+1Bh] [ebp-Dh] char v15; // [esp+1Bh] [ebp-Dh] int v16; // [esp+1Ch] [ebp-Ch] unsigned __int8 a1[256]={0}; int i; for(i=1;i<256;i++){ memset(a1,0,sizeof(a1)); a1[0] = i; v12 = 1; v13 = 1; do { if ( v12 >= 0 ) v2 = 0; else v2 = 27; v12 ^= (2 * v12) ^ v2; v14 = (4 * ((2 * v13) ^ v13)) ^ (2 * v13) ^ v13; v15 = (16 * v14) ^ v14; if ( v15 >= 0 ) v3 = 0; else v3 = 9; v13 = v15 ^ v3; v4 = v13; v4 = __ROR1__(v13, 7); v5 = v4 ^ (v13 ^ *a1); v6 = v13; v6 = __ROR1__(v13, 6); v7 = v6 ^ v5; v8 = v13; v8 = __ROR1__(v13, 5); v9 = v8 ^ v7; v10 = v13; v10 = __ROR1__(v13, 4); result = v10 ^ v9; a1[v12] = result; }while ( v12 != 1 ); if(a1[84]==0x95 && a1[87]==0xee && a1[67]==0xaf && a1[84]==0x95 && a1[70]==0xef && a1[123]==0x94 && a1[125]==0x4a){ printf("找到了正确的数组,此时的随机值i为:%d\n",i); break; } } for(i=0;i<256;i++){ if(i%16==0) printf("\n"); printf("0x%02x ",a1[i]); } } //找到了正确的数组,此时的随机值i为:214 0xd6 0xc9 0xc2 0xce 0x47 0xde 0xda 0x70 0x85 0xb4 0xd2 0x9e 0x4b 0x62 0x1e 0xc3 0x7f 0x37 0x7c 0xc8 0x4f 0xec 0xf2 0x45 0x18 0x61 0x17 0x1a 0x29 0x11 0xc7 0x75 0x02 0x48 0x26 0x93 0x83 0x8a 0x42 0x79 0x81 0x10 0x50 0x44 0xc4 0x6d 0x84 0xa0 0xb1 0x72 0x96 0x76 0xad 0x23 0xb0 0x2f 0xb2 0xa7 0x35 0x57 0x5e 0x92 0x07 0xc0 0xbc 0x36 0x99 0xaf 0xae 0xdb 0xef 0x15 0xe7 0x8e 0x63 0x06 0x9c 0x56 0x9a 0x31 0xe6 0x64 0xb5 0x58 0x95 0x49 0x04 0xee 0xdf 0x7e 0x0b 0x8c 0xff 0xf9 0xed 0x7a 0x65 0x5a 0x1f 0x4e 0xf6 0xf8 0x86 0x30 0xf0 0x4c 0xb7 0xca 0xe5 0x89 0x2a 0x1d 0xe4 0x16 0xf5 0x3a 0x27 0x28 0x8d 0x40 0x09 0x03 0x6f 0x94 0xa5 0x4a 0x46 0x67 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00re>

最后在根据条件给的那一串字符串,找到在v4数组中的位置就可以了

re>list = [0xd6,0xc9,0xc2,0xce,0x47,0xde,0xda,0x70 ,0x85,0xb4,0xd2,0x9e,0x4b,0x62,0x1e,0xc3 ,0x7f,0x37,0x7c,0xc8,0x4f,0xec,0xf2,0x45 ,0x18,0x61,0x17,0x1a,0x29,0x11,0xc7,0x75 ,0x02,0x48,0x26,0x93,0x83,0x8a,0x42,0x79 ,0x81,0x10,0x50,0x44,0xc4,0x6d,0x84,0xa0 ,0xb1,0x72,0x96,0x76,0xad,0x23,0xb0,0x2f ,0xb2,0xa7,0x35,0x57,0x5e,0x92,0x07,0xc0 ,0xbc,0x36,0x99,0xaf,0xae,0xdb,0xef,0x15 ,0xe7,0x8e,0x63,0x06,0x9c,0x56,0x9a,0x31 ,0xe6,0x64,0xb5,0x58,0x95,0x49,0x04,0xee ,0xdf,0x7e,0x0b,0x8c,0xff,0xf9,0xed,0x7a ,0x65,0x5a,0x1f,0x4e,0xf6,0xf8,0x86,0x30 ,0xf0,0x4c,0xb7,0xca,0xe5,0x89,0x2a,0x1d ,0xe4,0x16,0xf5,0x3a,0x27,0x28,0x8d,0x40 ,0x09,0x03,0x6f,0x94,0xa5,0x4a,0x46,0x67] flag = "" s = "95eeaf95ef94234999582f722f492f72b19a7aaf72e6e776b57aee722fe77ab5ad9aaeb156729676ae7a236d99b1df4a"; for i in range(0, len(s), 2): s1 = int(s[i:i+2], 16) flag += chr(list.index(s1)) print (flag) #TWCTF{5UBS717U710N_C1PH3R_W17H_R4ND0M123D_5-B0X} re>

方法二:ref="/tags/GDB.html" title=gdb>gdb脚本https://blog.csdn.net/Onlyone_1314/article/details/120242744?ops_request_misc=&request_id=&biz_id=102&utm_term=%E6%94%BB%E9%98%B2%E4%B8%96%E7%95%8Creverse-box&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduweb~default-1-120242744.142^v74^insert_down4,201^v4^add_ask,239^v2^insert_chatgpt&spm=1018.2226.3001.4187

ref="/tags/GDB.html" title=gdb>gdb脚本第一次看,所以只能搬运别人的代码,自己来理解理解。

这里有2种方法,执行ref="/tags/GDB.html" title=gdb>gdb脚本,一:直接输入defien命令,输入指令,最后执行。二:单独写成一个脚本文件使用 source 来执行。这里用source 脚本名来写。

分析一下汇编,看一看随机数和v4数组都存在哪里

 

 所以esp+eax+1ch是数组的地址,但是当输出数组第一个值时,eax是0,所以数组初始地址是esp+1ch,所以根据这些写ref="/tags/GDB.html" title=gdb>gdb脚本命名test.sh。

re>#设置从0到255的随机值爆破 set $i=0 set $total=256 while($i<$total) #在生成随机值之后的地址下第一个断点 b *0x80485b1 #在main函数中printf输出的位置下第二个断点 b *0x8048707 #运行程序,并输入参数"TWCTF" run TWCTF #$i变量的值递加1 set $i=$i+1 #程序在第一个断点停下来的时候,把当前的随机值赋值给eax寄存器 set $eax=$i #继续运行程序 continue #程序在第二个断点停下来的时候,判断此时的输出的第一个16进制值是否是0x95 if ($eax==0x95) #如果是,则认为找到了正确的解,输出此时的随机值 print $i #查看起始地址从esp+0x1c开始的256个16进制字节的内容,这里就是存放数组的地方 x/256xb $esp+0x1c #令变量的值为256,退出循环 set $i=256 end stop end end re>

 运行:

 不断回车

 在根据给出的题目的回显值写flag即可。

TWCTF{5UBS717U710N_C1PH3R_W17H_R4ND0M123D_5-B0X}

reeSkill">

http://www.niftyadmin.cn/n/161910.html

相关文章

汽车电子的搬运工(AUTOSAR架构)

AUTOSAR开发技术手册 一、总体概述 AUTOSAR是Automotive Open System Architecture&#xff08;汽车开放系统架构&#xff09;的首字母缩写&#xff0c;是一家致力于制定汽车电子软件标准的联盟。AUTOSAR是由全球汽车制造商、部件供应商及其他电子、半导体和软件系统公司联合建…

设计模式-第18章(单例模式)

单例模式单例模式多线程下的单例模式双重检测锁静态初始化单例模式 单例模式&#xff08;Singleton&#xff09;&#xff0c;保证一个类仅有一个实例&#xff0c;并提供一个访问它的全局访问点。 通常可以让一个全局变量使得一个对象被访问&#xff0c;但它不能防止你实例化多…

XGBoost和LightGBM时间序列预测对比

XGBoost和LightGBM都是目前非常流行的基于决策树的机器学习模型&#xff0c;它们都有着高效的性能表现&#xff0c;但是在某些情况下&#xff0c;它们也有着不同的特点。 XGBoost和LightGBM简单对比 训练速度 LightGBM相较于xgboost在训练速度方面有明显的优势。这是因为Ligh…

1.0、Java泛型 - 什么是泛型类 ?

1.0、Java泛型 - 什么是泛型类 &#xff1f; 背景&#xff1a; Java推出泛型之前&#xff0c;程序猿可以构建一个元素类型为 Object 的集合&#xff0c;该集合能够存储任意的数据类型对象&#xff0c;而在使用该集合的过程中&#xff0c;需要程序猿明确知道存储每个元素的数据类…

【基础算法】数组相关题目

系列综述&#xff1a; &#x1f49e;目的&#xff1a;本系列是个人整理为了秋招算法的&#xff0c;整理期间苛求每个知识点&#xff0c;平衡理解简易度与深入程度。 &#x1f970;来源&#xff1a;材料主要源于代码随想录进行的&#xff0c;每个算法代码参考leetcode高赞回答和…

【设计模式】实战聊聊工作中使用了哪些设计模式

文章目录前言1.策略模式1.1 业务场景1.2 策略模式定义1.3 策略模式使用1.3.1 一个接口&#xff0c;两个方法1.3.2 不同策略的差异化实现1.3.3 使用策略模式2. 责任链模式2.1 业务场景2.2 责任链模式定义2.3 责任链模式使用2.3.1 一个接口或者抽象类2.3.2 每个对象差异化处理2.3…

如何学习Java开发

目录当今IT就业环境Java学习路线Java语言基础SQLJDBCJava Web基础开发框架开发框架进阶微服务提醒当今IT就业环境 疫情以来互联网甚至各行各业的就业环境就开始变差&#xff0c;直到疫情结束以来仍没有恢复。由于培训机构的教育模式和方法&#xff0c;导致国内出现了一大批初级…

进阶C语言——指针【指针笔试题练习】

文章目录笔试题1笔试题2笔试题3笔试题4笔试题5笔试题6笔试题7笔试题8笔试题1 int main() {int a[5] { 1, 2, 3, 4, 5 };int* ptr (int*)(&a 1);printf("%d,%d", *(a 1), *(ptr - 1));return 0; }运行结果&#xff1a; ptr-1向前移动一个字节指向5&#xf…