CTF-reverse-每日练题-Reversing-x64Elf-100

news/2024/5/19 22:25:55 标签: ctf, reverse, 攻防世界

题目链接

https://adworld.xctf.org.cn/challenges/list


 题目详情

Reversing-x64Elf-100


解题报告

下载得到的文件使用ida64分析,如果报错就换ida32,得到分析结果,有main函数就先看main

main函数分析

大致逻辑便理清楚了,输入的字符串s要使函数sub_4006FD返回false,这样才能进入else的逻辑判断

sub_4006FD函数分析

双击进入sub_4006FD函数进一步分析函数逻辑

这里首先定义了三个字符串 

然后设置循环,每次循环对字符串中的字符进行运算后判断是否结果!=1

但是联系前文,我们需要这个函数返回false,所以我们得让这个条件在12次循环内全为假,最终才能走到这个16行返回false

那么问题就简化成了让【*(char *)(v3[i % 3] + 2 * (i / 3)) - *(char *)(i + a1) != 1】 这个条件为假,简单变换为让【*(char *)(v3[i % 3] + 2 * (i / 3)) - *(char *)(i + a1) == 1】为真,即经过运算的字符最终结果始终等于1

对于这个算式,涉及到c语言的指针用法,下面进行详细分析:

①v3本质是一个二维数组,v[0]、v[1]、v[2]分别存放上图的三个字符串

②i%3很好理解了,这个结果只会是0,1,2,通过模运算来确保了数组v3不会越界

③对c语言数组稍微有点理解的话,就能明白v[0]、v[1]、v[2]分别代表的是三个字符串的首元素地址,也可以视作指针,对指针进行【+ 2 * (i / 3)】的加法运算,就是让指针的地址往后偏移,经过简单计算不难发现这个算式的结果在0~6之间(7就是三个字符串的长度,下标从0开始),也就确保了二维数组访问三个字符串的字符时都不会越界

例如v[0]代表的是【"Dufhbmf"】中的字符'D'地址,v[0]+1就是字符'u'的地址

如此一来,【v3[i % 3] + 2 * (i / 3)】的意思就是让指针往后偏移,去指向后面的字符

④(char*)指针强转,这步操作也挺关键的,经过第③步的操作,实际上获得到的还是字符串的地址而不是单个字符的地址,所以使用强制转换,将其转为字符指针,最后再使用*指针操作符对字符地址解引用,这下才彻底获取到对应的字符

其实,【*(char *)(v3[i % 3] + 2 * (i / 3))】就等效于【v[i % 3][2 * (i /3)]】,前者是二维数组的指针访问形式

⑤后半部分的【*(char *)(i + a1)】的话,其中a1是我们输入的字符串(函数形参,其实就是前面在main函数里面输入的字符串s),a1+i的话也是进行指针偏移,*(char *)跟上面第④步的操作就同理了,所以这边这个表达式的含义就是访问我们输入的字符串中的字符

综上所述,【*(char *)(v3[i % 3] + 2 * (i / 3))】是获取三个已定义字符串中的字符(记作str),【*(char *)(i + a1)】是获取输入字符中的字符(记作flag),最后拿str减去flag(当然是拿ASCII码来计算了),得到的结果需要为1,即【str - flag == 1】,到这一步逆向思路已经一目了然,即【flag = str - 1】,代入前面的str表达式就是【flag = *(char *)(v3[i % 3] + 2 * (i / 3)) - 1】,至此,脚本就完全会写了

EXP

#include<iostream>
using namespace std;
int main(){
	char v3[3][10] = {"Dufhbmf", "pG`imos", "ewUglpt"};
	//ida里面定义字符串的语法是错误的,c/c++字符数组只能在定义时赋值,同时要稍微给大一点,确保能存放下
	
	
    string flag;//这里flag直接用了c++里string类型,重载了+操作符实现字符拼接 
    for(int i = 0; i <= 11; i++){
    	flag += *(char *)(v3[i % 3] + 2 * (i / 3)) - 1;//按我们推理出来的逆向公式把符合要求的字符计算出来,然后拼接进flag 
	}
	cout << flag;//输出最终flag即可 
} 


总结

本题涉及到的知识点其实蛮多的,攻防世界把它放在题库里reverse方向新手模式的第一题,属实有点劝退新童鞋

涉及到的关键知识点:

  • 一维数组名的含义:数组首元素地址(指针)
  • 指针加法运算含义:指针地址向后偏移
  • 二维数组指针形式访问:*(char*)(arr[i] + j)完全等效于arr[i][j]

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

相关文章

边缘计算+WEB端应用融合:AI行为识别智能监控系统搭建指南 -- 整体介绍(一)

专栏目录 边缘计算WEB端应用融合&#xff1a;AI行为识别智能监控系统搭建指南 – 整体介绍&#xff08;一&#xff09; 边缘计算WEB端应用融合&#xff1a;AI行为识别智能监控系统搭建指南 – 边缘设备图像识别及部署&#xff08;二&#xff09; 边缘计算WEB端应用融合&#xf…

蓝牙墨水屏智能标签意想不到的多场景解析

随着物联网技术的迅猛发展&#xff0c;蓝牙墨水屏电子标签作为一种新型的智能标识技术&#xff0c;正逐渐走进人们的视野&#xff0c;其独特的优势和应用场景正不断拓宽。本文将详细解析蓝牙墨水屏标签在设备资产显示标签、仓储拣货物流追踪管理、智慧办公、环境监测显示以及智…

【ES6】let与const

目录 let命令 作用域 无变量提升 不允许重复声明 暂时性死区 块级作用域 函数能否在块级作用域中声明 const命令 let命令 作用域 ES6 新增了let命令&#xff0c;用来声明变量。它的用法类似于var&#xff0c;但是作用域不同&#xff0c;let命令只在所在的代码块内…

2024全国水科技大会:【协办单位】山东文远环保科技股份有限公司

山东文远环保科技股份有限公司坐落于千年古城齐国故都--临淄。初始成立于2011年&#xff0c;是淄博市首批国有资本参股的混合改制企业。 公司着力打造环保设备制造、环保工程及服务、环保水务/固废处理/新能源项目投资及运营管理、固废循环经济产业园等四大板块。是一家集投资、…

Flutter 开发中踩坑笔记总汇

Flutter 踩坑笔记总汇 本篇主要是收集汇总开发过程中遇到的小困惑&#xff0c;都是些比较常见的问题。后续开发中遇到&#xff0c;也会持续更新在这里。 1、Flutter Packages upgrade后任务进入阻塞状态 问题&#xff1a;无法更新下载插件库。 解决&#xff1a;配置flutter官…

深度学习——微积分基础

目录 1、导数和微分 1.1 定义函数&#xff1a; 1.2 趋近过程&#xff1a; 1.3 绘图表示&#xff1a; 2、偏导数 3、梯度 4、链式法则 5、学习心得 在2500年前&#xff0c;古希腊人把一个多边形分成三角形&#xff0c;并把它们的面积相加&#xff0c;才找到计算多边形面积…

JavaWeb基础第四章(SpringBootWeb工程,HTTP协议与Web服务器-Tomcat)

文章目录 一、SpringBoot介绍二、SpringBootWeb入门三、HTTP协议四、HTTP-请求协议五、HTTP-响应协议六、HTTP-协议解析七、Web服务器-Tomcat八、Tomcat — 基本使用九、入门程序解析 在这篇文章中&#xff0c;我们将深入探讨一种广受欢迎的Java框架 - SpringBoot。可能你已经听…

【每日一题】2024年3月汇编(上)

3.1【2369】检查数组是否存在有效划分 2369. 检查数组是否存在有效划分https://leetcode.cn/problems/check-if-there-is-a-valid-partition-for-the-array/ 1.这样的判断可以用动态规划来解决&#xff0c;用一个长度为(n1) 的数组来记录 是否存在有效划分&#xff0c;dp[i]…