buu-reverse-reverse1题解
题目链接:https://buuoj.cn/challenges
题路径:buu-reverse-reverse1
题解easyre的经验
因为没有单独写成博客就在此写入
【buu-reverse-easyre】 2021-01-04 曾生强
1.这个入门题的核心就是需要你基本熟悉一下反编译软件这里选择了思雨大佬在前面写的IDA软件(因为查了一下支持32/64位程序就选了这一款),基本入门了一下操作(https://www.cnblogs.com/17bdw/p/12239505.html)。
2.然后继续根据前面思雨大佬的思路打开了问题的exe文件,搜索了一下字符串(打开string栏:view-open subview-string),用ctrl+f搜索flag关键字,然后才发现flag已经赫然在第二行= =。
3.然后出于对这个软件的好奇,就去主页面IDA View-A找下具体在哪,发现其实就在main函数里面,然后也发现这个页面不能用ctrl+f很奇怪,也可以按F5反编译后看main函数部分也是能找到的(反编译后看就是C代码比汇编好多了)。
- 首先使用IDA 打开,因为无法确认是32还是64先用了32打开无果后使用64打开。
- 然后并没有发现main函数,果断用string字符工具栏打开搜索flag,然后发现了这个
this is the right flag!\n
果断点进去。
新东西
DATA XREF
在IDA打开的主界面IDA View-A(按空格切换成代码页面的地方),每一块代码的右侧都有DATA XREF
,左侧是汇编代码,经过查询,DATA XREF
的含义是外部引用代码,作用是链接另一处调用也好blabla(具体要学完汇编才知道),于是就从this is the right flag!\n
最近的上下两个DATA XREF
点进去了,发现应该链接下面那个才对,点两个都能进入,位置几乎是相同的。
sub_1400118C0
loc_140011996↑o
查看源码
依次,按F5查看源码,发现这个所在函数的代码,这应该就是类似easyre的main函数的位置,应该接下来就在这捣鼓了,但是看着很莫名奇妙就尝试着解读一下代码含义。
根据猜测和c语法解析了一下含义大概剩这样的
__int64 sub_1400118C0()
{
//str1,v5 和str2是可能的答案(因为flag是用char储存的)
char *v0; // rdi
signed __int64 i; // rcx
size_t v2; // rax
size_t v3; // rax
char v5; // [rsp+0h] [rbp-20h]
int j; // [rsp+24h] [rbp+4h]
char Str1; // [rsp+48h] [rbp+28h]
unsigned __int64 v8; // [rsp+128h] [rbp+108h]
v0 = &v5;
//看不懂
for ( i = 82i64; i; --i )
{
*(_DWORD *)v0 = -858993460;
v0 += 4;
}
//遍历str2中的每一个字符将ASCII==111的改成48
for ( j = 0; ; ++j )
{
v8 = j;
v2 = j_strlen(Str2);
if ( v8 > v2 )
break;
if ( Str2[j] == 111 )
Str2[j] = 48;
}
//输入flag保存位str1
sub_1400111D1("input the flag:");
sub_14001128F("%20s", &Str1);
//比较str1和str2,如果一样的输出 this is the right flag!\n
v3 = j_strlen(Str2);
if ( !strncmp(&Str1, Str2, v3) )
sub_1400111D1("this is the right flag!\n");
else
sub_1400111D1("wrong flag\n");
sub_14001113B(&v5, &unk_140019D00);
return 0i64;
}
那么按照逻辑str2就是答案了,于是双击看看能不能链接到答案,狂喜发现flag:flag{hello_world}
立马尝试了提交
结果竟然错了,然后回去翻看源码,蒙逼了半天,突然想起来这段
//遍历str2中的每一个字符将ASCII==111的改成48
for ( j = 0; ; ++j )
{
v8 = j;
v2 = j_strlen(Str2);
if ( v8 > v2 )
break;
if ( Str2[j] == 111 )
Str2[j] = 48;
}
//str2查出来是 flag{hello_world}
原本就很莫名其妙,然后查了一下ASCII码
ASCII | 字符 |
---|---|
111 | o |
48 | 0 |
猜想难道IDA查到的str2的值是还没遍历修改过吗?那正确答案应该就是flag{hell0_w0rld}
尝试提交
correct!
技术总结
- 从string入手
- 通过DATA XREF等可以链接的东西找到关联内容
- 关键要通过关键字,链接等找到关键函数(本题是
__int64 sub_1400118C0()
),然后通过解读代码找到flag