RCTF2018 babyre WriteUp

Author Avatar
kabeor 5月 23, 2018

RCTF2018 babyre WriteUp

题目给了一个压缩包,里面有两个文件
mark

out文件
mark

这种题型应该就是得到算法后枚举,与正确输出的out作比较

那么首先拿IDA看一下吧

IDA分析

先搜索一下字符串吧
mark
可以看到这些有用的提示,使用交叉引用到汇编指令

用图形化看一下(最后一张有一点歪了,请原谅)

main函数 0x08048B49
比较长,挑重点

mark
mark

返回输出流程 0x804882B

mark
mark
mark

注意到那个红色的报错了吗,是的,我们现在无法F5
mark

显示sp分析失败
经过搜索学习,明白了这种问题一般都是堆栈不平衡导致的,因此我们需要手动调整栈指针

首先 菜单栏OPtions->General
mark

打上勾
然后回到汇编窗口,找到loc_80848CBB

mark

观察发现,lea和retn处的栈指针都是00,导致问题的出现,因此我们应该运用堆栈平衡原理,将其平衡

具体来说,想要修改一个位置的指针,需要将鼠标指向这个指针的上一个指针,然后 Alt+K

mark

将里面的0x9C修改为0x0,确认
mark

现在堆栈平衡,就可以F5了

当然了,还可以选择GDB动态调试,在出错这里下断点,然后步入看汇编,但因为对汇编看的还不是很熟悉,GDB也不常接触,于是只能F5了(流下没技术的泪水)

算法分析

F5看一下
mark

mark

主函数判断输入格式,v4处可以看到,是将其八位即四字节一组(int大小为2字节,8/2=4)进行分组

然后sub_804882B内是回显
mark

sub_8048A41和sub_8048980不太清楚是干嘛的,应该是初始化和转换之类的

算法位于sub_80488E0内

先记住sub_80488E0(&v6, 0xA72BE4C1, 0x1D082C23, seed, v4, v3);,后面有用

内部

mark

看到一个30次的循环,嵌套sub_804868B
进去看看

mark

现在整个算法的全貌就展示在了我们面前

逐位循环0x20F次换算成四字节一组也就是0x20F/4=0x7F
于是我们只需要从0x20到0x7F进行枚举,按照相应算法对out进行比较即可,注意80488E0一开始传入的两个字符串需要互换然后合并

解题脚本如下

#include <stdio.h>
#include <string.h>
#include <stdint.h>
uint32_t foo(uint32_t a1, uint64_t a2) // sub_804868B
{
int j;
uint64_t v5;
uint32_t in;
in = a1;
for (j = 0; j <= 527; ++j)
{
v5 = a2 >> (j & 0x1F);
if (j & 0x20)
v5 = v5 >> 32; //高低位转换
in = (in >> 1) ^ ((v5 ^ in ^ (in >> 16) ^ (0x5C743A2E >> (((in >> 1) & 1)
+ 2
* (2
* (((in >> 20) & 1)
+ 2* (2 * (in >> 31) + ((in >> 26) & 1)))
+ ((in >> 9) & 1))))) << 31);
}
return in;
}

int main()
{
uint32_t data[30] = // out
{
0xB80C91FE,0x70573EFE,
0xBEED92AE,0x7F7A8193,
0x7390C17B,0x90347C6C,
0xAA7A15DF,0xAA7A15DF,
0x526BA076,0x153F1A32,
0x545C15AD,0x7D8AA463,
0x526BA076,0xFBCB7AA0,
0x7D8AA463,0x9C513266,
0x526BA076,0x6D7DF3E1,
0xAA7A15DF,0x9C513266,
0x1EDC3864,0x9323BC07,
0x7D8AA463,0xFBCB7AA0,
0x153F1A32,0x526BA076,
0xF5650025,0xAA7A15DF,
0x1EDC3864,0xB13AD888
};
int i;
uint32_t j;
for (i = 0; i < 30; i++)
for (j = 0x20; j < 0x7F; j++) //0x20F/4=0x7F
if (foo(j, 0x1D082C23A72BE4C1) == data[i]) //互换,合并
printf("%c", j);
printf("\n");
return 0;
}

Flag

mark

解出: RCTF{Kee1o9_1s_a1ready_so1ved}

From https://kabeor.github.io/RCTF2018 babyre WriteUp/ bye

This blog is under a CC BY-NC-SA 4.0 Unported License
本文链接:https://kabeor.github.io/RCTF2018 babyre WriteUp/