CTF-reverse-Reversing-x64Elf-100

题目链接

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]
  • 21
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值