从一个reverse-box到python脚本化调试
文章目录
- 从一个reverse-box到python脚本化调试
- 题目分析
- 题目条件
- 分析
- 思路
- ida-python爆破
- 另外
- 动调脚本化
- ida - python
攻防世界 reverse-box 题目
原题来自 mma-ctf-2nd-2016: reverse-box
题目分析
题目条件
Description:
$ ./reverse_box ${FLAG}
95eeaf95ef94234999582f722f492f72b19a7aaf72e6e776b57aee722fe77ab5ad9aaeb156729676ae7a236d99b1df4a
题目flag格式:TWCTF{…}
分析
main函数如下:
运行程序时输入的参数,会和一个数值相加,转化成十六进制,然后打印出来,
我们简单运行下如下:
另外汇编是:
这个位置,是一个查表的过程,函数
重点在于:
后部分都是设置建立表,但是这个生成表的种子是随机的,也就是我们的表是不固定的。
思路
题目就是对输入进行查表,然后打印出来,并且给出了正确flag查表对应的值,但是这个表是随机生成的,我们需要得到正确的一个表。
方案应该是只能爆破,并且
这时候我们面对一个问题,这个怎么方便的进行爆破?
下面我们写一下关于爆破的方法,
其中wp有的直接爆破出正确的,有的直接爆破出所有的再交python得到最后工作,这都是差不多的, 我们只讨论爆破的实现。
下面是我搜到一些wp中的解法:
- gdb 脚本–githubgdb脚本-csdn
- [gdb - python 脚本](https://github.com/TeamContagion/CTF-Write-Ups/tree/master/TokyoWesterns-2016/Reverse Box))
- idc脚本
- uncorn 脚本
- python 重构这个函数然后爆破
- [ida-python脚本] (本文)
其中大部分方法都可以看到链接。一个ida python的手段是我们的重点, 也恰好是在wp没有看到的一种方案。
ida-python爆破
相关的文章是这个, 比较详细的介绍了相关的函数。
脚本:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | import idaapi import idc for i in range(1, 256): RunTo(0x080485b1) GetDebuggerEvent(WFNE_SUSP, -1) print i SetRegValue(i, "eax") RunTo(0x08048704) GetDebuggerEvent(WFNE_SUSP, -1) bool = GetRegValue("eax") RunTo(0x08048746) GetDebuggerEvent(WFNE_SUSP, -1) SetRegValue(0x080486D4, 'eip') if bool == 0x95: print i break RunTo(0x080485b1) GetDebuggerEvent(WFNE_SUSP, -1) print i SetRegValue(i, "eax") RunTo(0x08048704) GetDebuggerEvent(WFNE_SUSP, -1) stack = GetRegValue("esp") arr_addr = stack + 0x1c arr = [] for i in range(0xff): arr.append(Byte(arr_addr + i)) s = '95eeaf95ef94234999582f722f492f72b19a7aaf72e6e776b57aee722fe77ab5ad9aaeb156729676ae7a236d99b1df4a' a = [] for i in range(0,len(s), 2): a.append(arr.index(int(s[i:i+2], 16))) print ''.join(map(chr, a)) |
注意idc定义的的函数可以直接在ida-python中调用。
注意一点:关于
GetDebuggerEvent() 这个代码看起来很无用,但是不加会报错,
因为python脚本和调试器会异步执行,我们要获取寄存器的话应该要等待,直接过去是会报错,显示寄存器名错误,可以通过加入
GetDebuggerEvent(WFNE_SUSP, -1) 来解决这个问题,注意每次要读取修改数据啥的要加一个这个就可以了。
设置好debug options, 直接运行脚本,ida会自动开始动调,
然后运行脚本得到flag,
ida 内运行直接得到flag
另外
注意两点,
- 参数
一个是对于这种要求调用时要参数的程序,我们在ida debug options中设置:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AZwpjfBD-1586228644870)(image-20200405222503984.png)]
这样调试的时候,对应的参数就是"T"
这个是linux 下wine运行的ida因此为127.0.0.1
- ida-python 调试不能自己重复多次调试
我们的脚本的循环中每次都是改掉eip调整程序运行的。ida-python 不能够自动循环启动多次调试,但是对于一般题目修改eip已经足够我们的使用。
动调脚本化
在所有的wp解法中, 我认为最简洁和具有通用性的应该是ida-python的解法和gdb-python的解法,
这里简单写一下相关的使用。
gdb - python, 有一个官方文档, 然后个人觉得使用起来略显复杂,主要写下idapython
ida - python
然后在动调主要使用到的函数:
一般使用的:
- 用于程序运行, 获取相关位置,设定相关寄存器。
1 2 3 4 | RunTo(xxxx) GetDebuggerEvent(WFNE_SUSP, -1) SetRegValue(xxx, 'xxx') xxx = GetRegValue("xxx") |
- 获取栈内数据:
1 2 3 | RunTo(xxx) GetDebuggerEvent(WFNE_SUSP, -1) stack = GetRegValue("esp") |
这样,运行到某个位置,获取esp/rsp的值,为栈顶,通过偏移可以获取相对应的栈内地址,然后使用