0x01 dice_game
- 题目来源:XCTF 4th-QCTF-2018
1 | Arch: amd64-64-little |
- 题目逻辑较为简单,题目提供了libc.so.6。
所以可以直接覆盖掉seed,然后利用ctypes库模拟生成随机数即可。
exp如下:
1 | from pwn import * |
0x02 forgot
- 题目来源: backdoorctf-2015
1 | Arch: i386-32-little |
- 先看一下主函数,注意这一块。
- v2是个32大小的数组,且用是
scanf("%s",v2)
来进行输入,没有控制输入长度。之后的v3、v4…..v12都为函数指针。这道题就考察通过将目标(get shell)地址覆盖到这几个函数指针中的任意一个来实现调用。
题目是一个和检查email格式有关的程序。首先会问你name,这个随便填即可,因为用了fgets且大小合理,不会造成溢出。
然后程序会通过
sub_80485DD函数
欢迎你,告诉你要输入个email。v3到v12都是会puts一段话语,其中v9、v10、v11的内容一样, 因此我们可以选择故意触发v3~v8或者v12其中任意一个函数。(不选v9、v10、v11是因为它们puts的内容一样,不太容易知道到底调用了哪一个,当然也可以选用这些,调试一下也能知道调用的是哪一个。)
- 我们运行一下程序,发现触发了v4所对应的
sub_8048618
函数。
- 又发现了
cat flag
函数,地址为0x80486cc。
因此覆盖思路为, 先覆盖掉32大小的v2数组,然后用4字节覆盖掉v3指针,然后用目标函数地址覆盖掉v4指针,这样来故意触发
cat flag
。exp如下:
1 | from pwn import * |
0x03 warmup
- 攻防世界上面没给题目附件…
- 根据题目来源: csaw-ctf-2016-quals,搜了一下这道题,不难,直接上exp吧:
1 | from pwn import * |
0x04 stack2
- 题目来源: XCTF 4th-QCTF-2018
1 | Arch: i386-32-little |
- 程序是一个简易计算器。
- 漏洞点在
3. change number
。
- 没有对边界进行检测,可以产生越界操作。
首次尝试
- 思路是通过越界操作将ret_addr改成目标(get shell)地址。
- 发现程序存在后面函数
hackhere
,地址为0x0804859B
。
首先我们需要知道v13这个数组距离ret_addr的偏移。
v13是EBP-0x70,但是EIP却不是EBP+4,至于为什么, 有博主说这是因为开了Canary保护,需要动态调试计算这个偏移,下面来动态调试计算这个偏移。
偏移计算
- 用gdb来调试这个程序,我们将断点下在
0x080488EE
的位置,即main函数的leave
的位置。 - 因为此时栈帧还没还原,这时候我们能读取到
ebp
(ebp在一个栈帧中是不变的,直到销毁栈帧。所以我们此刻的ebp就是main函数最开始的ebp。),并且再单步几次就能到达retn指令
,retn
相当于pop eip
,此刻栈顶存着的便是ret_addr
的位置。
- 运行以后随便个数,然后输入5来执行程序的exit,就可以来到断点位置。
- 这时候看到EBP为
0xffffcee8
,这个值以及下面会出现的ret_addr
的值不同环境可能不一样,但是偏移是一样的。
继续单步, 来到
ret
的位置,我们看到ESP为0xffffcefc
,这便是ret_addr
的位置。由于
v13 = EBP - 0x70
,ret_addr - EBP = 0x14
,所以偏移offset = ret_addr - v13 = 0x84
。
编写EXP
函数式编程确实挺香,至少对于这次exp里面的write函数是这样,start函数和exit倒无所谓。
test.py如下,注意是test,因为这个exp并不正确。
1 | from pwn import * |
- 至于为什么不正确,原因如下。
第二次尝试
第一种思路由于环境问题未打通, 这次换种思路,直接调用system函数,给它传入参数
sh
。我们在程序中找到了
sh
。
可以得到sh的地址为
0x08048987
。exp如下:
1 | from pwn import * |
- 注意offset+8,通过调试也能发现是需要+8,如果不调试而从理论上解释的话,就涉及到参数传递的知识了。这里直接引用某博主的一句解释:
调用system后esp指向offset+4的地方,此时esp指向的应该是返回地址,esp+4即offset+8的地方才是system的参数。
0x05 pwn100
0x06 Mary_Morton
- 题目来源: ASIS-CTF-Finals-2017
1 | Arch: amd64-64-little |
1 | void __fastcall __noreturn main(__int64 a1, char **a2, char **a3) |
1 | .text:00000000004008DA |
- 一道简单的pwn题, 考察通过格式化字符串漏洞泄露canary,然后再进行栈溢出ret。
首先通过手动测出来偏移为6。
由于我们的
canary
距离buf
有0x90 - 0x8 = 0x88个字节,而程序是64位的,所以每八个字节一组, 0x88字节即为17组。 所以我们canary距离我们输入的偏移为6 + 17 = 23
。所以就可以直接通过格式化字符串泄露canary了,然后就是基础的rop了。
1 | from pwn import * |