攻防世界reverse-box

题目下载:下载

这道题有两种方法,一个是写c来解,另一个是用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)看看变化:

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;
}

 发现有一个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数组

#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 0x00

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

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}

方法二: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

gdb脚本第一次看,所以只能搬运别人的代码,自己来理解理解。

这里有2种方法,执行gdb脚本,一:直接输入defien命令,输入指令,最后执行。二:单独写成一个脚本文件使用 source 来执行。这里用source 脚本名来写。

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

 

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

#设置从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

 运行:

 不断回车

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

TWCTF{5UBS717U710N_C1PH3R_W17H_R4ND0M123D_5-B0X}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.kler.cn/a/1425.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

「业务架构」TOGAF建模之业务架构:组织分解图(组织映射)

组织分解图描述了组织树中参与者、角色和位置之间的链接。组织图应该提供组织中所有者和决策者的指挥链。虽然组织分解图的目的不是将目标与组织联系起来&#xff0c;但是应该可以从组织分解图直观地将目标与涉众联系起来。这个图表还可以描述参与者的定义和他们的职责。组织是…

C#中的DataGridView中添加按钮并操作数据

背景&#xff1a;最近在项目中有需求需要在DataGridView中添加“删除”、“修改”按钮&#xff0c;用来对数据的操作以及显示。 在DataGridView中显示需要的按钮 首先在DataGridView中添加需要的列&#xff0c;此列是用来存放按钮的。 然后在代码中“画”按钮。 if (e.Column…

Three.js——learn02

Three.js——learn02Three.js——learn02通过轨道控制器查看物体OrbitControls核心代码index2.htmlindex.cssindex2.jsresult添加辅助器1.坐标轴辅助器AxesHelper核心代码完整代码2.箭头辅助器ArrowHelper核心代码完整代码3.相机视锥体辅助器CameraHelper核心代码完整代码Three…

Keil MDK6要来了,将嵌入式软件开发水平带到新高度,支持跨平台(2023-03-11)

注&#xff1a;这个是MDK6&#xff0c;不是MDK5 AC6&#xff0c;属于下一代MDK视频版&#xff1a; https://www.bilibili.com/video/BV16s4y157WF Keil MDK6要来了&#xff0c;将嵌入式软件开发水平带到新高度&#xff0c;支持跨平台一年一度的全球顶级嵌入式会展Embedded Wor…

JavaScript学习笔记(7.0)

<!--* Author: RealRoad1083425287qq.com* Date: 2023-03-13 14:50:18* LastEditors: Mei* LastEditTime: 2023-03-13 15:08:54* FilePath: \vscode\鼠标跟随.html* Description: * * Copyright (c) 2023 by ${git_name_email}, All Rights Reserved. --> <!DOCTYPE …

【Vue】Vue的安装

&#x1f3c6;今日学习目标&#xff1a;Vue3的安装 &#x1f603;创作者&#xff1a;颜颜yan_ ✨个人格言&#xff1a;生如芥子&#xff0c;心藏须弥 ⏰本期期数&#xff1a;第一期 &#x1f389;专栏系列&#xff1a;Vue3 文章目录前言Vue3安装独立版本CDN安装第一个Vue程序总…

【SCL】实现简单算法--冒泡排序

使用SCL语言实现一个冒泡排序的简单算法 文章目录 目录 文章目录 前言 二、实现排序 1.读取存储器地址&#xff08;PEEK&#xff09;指令 2.编写程序 总结 前言 本文我们来一起使用SCL来实现一个简单的算法——冒泡排序&#xff1b;它可以对少量数据进行从小到大或从大到小排序…

系统架构:经典三层架构

引言 经典三层架构是分层架构中最原始最典型的分层模式&#xff0c;其他分层架构都是其变种或扩展&#xff0c;例如阿里的四层架构模式和DDD领域驱动模型。阿里的 四层架构模型在三层基础上增加了 Manager 层&#xff0c;从而形成变种四层模型&#xff1b;DDD架构则在顶层用户…

【C++】命名空间

&#x1f3d6;️作者&#xff1a;malloc不出对象 ⛺专栏&#xff1a;C的学习之路 &#x1f466;个人简介&#xff1a;一名双非本科院校大二在读的科班编程菜鸟&#xff0c;努力编程只为赶上各位大佬的步伐&#x1f648;&#x1f648; 目录前言一、命名空间产生的背景二、命名空…

【数据结构】Java实现单链表

目录 1. ArrayList的缺陷 2. 链表 2.1 链表的概念及结构 2.2 接口的实现 3. 动手实现单链表 3.1 重写SeqList接口方法 3.2 在当前链表头部添加节点&#xff08;头插&#xff09; 3.3 在 第index位置添加节点&#xff08;任意位置&#xff09; 3.4 在当前链表尾部添加…

【LeetCode每日一题】——165.比较版本号

文章目录一【题目类别】二【题目难度】三【题目编号】四【题目描述】五【题目示例】六【解题思路】七【题目提示】八【时间频度】九【代码实现】十【提交结果】一【题目类别】 双指针 二【题目难度】 中等 三【题目编号】 165.比较版本号 四【题目描述】 给你两个版本号…

Vector的扩容机制

到需要扩容的时候&#xff0c;Vector会根据需要的大小&#xff0c;创建一个新数组&#xff0c;然后把旧数组的元素复制进新数组。 我们可以看到&#xff0c;扩容后&#xff0c;其实是一个新数组&#xff0c;内部元素的地址已经改变了。所以扩容之后&#xff0c;原先的迭代器会…

idea中使用maven进行多模块打包部署时jar包中无依赖的问题(示例:jar包才5k,且无法正常启动)

引言 模块关系&#xff1a; A&#xff1a;代表父工程B&#xff1a;代表WEB模块&#xff0c;主加载类所在模块S&#xff1a;业务处理模块D&#xff1a;数据处理模块E&#xff1a;基础模块 依赖关系如下&#xff1a; D依赖ES依赖EB依赖D&#xff0c;B依赖S 第一次进行maven多模块…

2.机器学习笔记第二周

梯度下降&#xff1a; 就是最优选择算法的图形化表示&#xff1a;一个站在山顶的人&#xff0c;每秒走绝对小的一步&#xff0c;他朝着什么方向移动可以最快到达山脚。 接下来是梯度运算的数学解法&#xff1a; &#xff1a;是赋值的意思&#xff0c;a&#xff1a;b就是a无论…

openssh 9.0p1版本和openssl1.1.1o版本部署实操

【准备】 获取openssh 9.0p1版本软件包和openssl1.1.1o版本 如果设备可以连外网&#xff0c;直接从服务器上wget获取 wget --no-check-certificate https://www.openssl.org/source/openssl-1.1.1o.tar.gz wget http://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openss…

多重背包的单调队列优化

邮专学子周末早起迎寒风细雨所作............. 周末也别想休息&#xff01;&#xff01;&#xff01;耐心看完&#xff0c;必定有收获哦&#x1f970;&#x1f42f;多重背包与其他背包相比的最大区别点就是&#xff0c;每个物品的数量是有限的。下面我们来看看多重背包的更新特…

java项目发布到Linux

参考&#xff1a;https://betheme.net/a/2751593.html?actiononClick java项目发布到Linux环境简单流程步骤&#xff1a; 一、首先打包成jar包&#xff0c;有两种方式 1、maven打包 打开idea项目。在右侧找到maven &#xff0c;有需要打包的项目&#xff0c;确定需要发布的…

考研数二第五讲 无穷小阶数问题的求解

无穷小阶数问题的求解 在考研复习中&#xff0c;关于无穷小阶数的问题是比较多的&#xff0c;从最基本的确定无穷小阶数问题&#xff0c;到无穷小之间的阶数 比较问题&#xff0c;都是属于比较常见的类型。此外&#xff0c;还有一些其他的切入点的题目&#xff0c;值得多多注意…

10.0自定义SystemUI下拉状态栏和通知栏视图(六)之监听系统通知

1.前言 在进行rom产品定制化开发中,在10.0中针对systemui下拉状态栏和通知栏的定制UI的工作开发中,原生系统的下拉状态栏和通知栏的视图UI在产品开发中会不太满足功能, 所以根据产品需要来自定义SystemUI的下拉状态栏和通知栏功能,首选实现的就是下拉通知栏左滑删除通知的部…

你是真的“C”——结构体中鲜有人知的“秘密”

你是真的“C”——结构体中的精髓剖析【内存对齐】 【位段】 &#x1f60e;前言&#x1f64c;结构体内存对齐&#xff1a;&#x1f60a;结构体内存对齐存在的意思是什么&#xff1f;&#x1f618;内存对齐例子详细剖析&#xff1a;&#x1f618;结构体中的位段&#xff1a;&…
最新文章