0x00 前言
- 题目是
TWCTF-reverse_box
,题目下载链接如下:
0x01 程序分析
- 主要由两个函数来解题。
1 | int __cdecl main(int a1, char **a2) |
1 | int __cdecl sub_804858D(_BYTE *a1) |
题目提示如果传入正确的Flag则会输出
95eeaf95ef94234999582f722f492f72b19a7aaf72e6e776b57aee722fe77ab5ad9aaeb156729676ae7a236d99b1df4
但是分析题目, 题目会取当前时间作为随机数种子,然后取一堆随机数执行一堆操作。
由于当前时间在不断变化,所以这个随机数种子是不固定的,所取的随机数也不固定,这就对解题产生了很大的困难。
但是查看这个算法函数
sub_804858D
的汇编代码,发现了惊喜!
- 所取的随机数最后会跟
0xFF
进行按位与运算,这就会使此时eax的值只能取0-255其中一个,也就是说我们的v10
只能取0-255中的一个,这就为我们执行爆破提供了可能。
0x02 写脚本前的分析
既然我们想进行爆破,但因为由于时间的变化随机数种子一直变会,
v10
也会一直变,所以我们直接控制v10
。那么该如何控制
v10
呢?我们可以通过gdb脚本来在每次给v10
赋值的时候进行暗箱操作
。
而这个赋值的时候通过IDA能够找到,就是图中
0x080485B1
的位置,因此我们需要在这个位置下个断点。该如何暗箱操作? 既然赋值是通过eax寄存器来实现的,那么我们可以通过
set $eax 计数器
的形式来改变eax的值,计数器的范围就是0~255。而且根据要求,还需要满足首先输出
0x95
(因为题中用的printf("%02x", *((unsigned __int8 *)&v4 + a2[1][i]));
,所以输出出来只有95
)。我们来看
printf
这附近的汇编代码。
- 依然是用eax寄存器来传值,又因为
printf
是在一个for循环
里面,如果第一次输出的是95
,则爆破成功,否则就让计数器
+1 再来一遍~
- 爆破成功以后我们就能得到这个
a2[1][?]
里面的内容了,从而就能逆出flag。
0x03 脚本的实现
1 |
|
- 通过
define 脚本名称
来新建一个脚本。 - 通过
脚本名称
来调用一个脚本。
- 运行脚本得到如下结果
得出flag
- 通过结果再结合题意逆出flag,脚本如下(Python)
1 | # -*- coding: UTF-8 -*- |