PwnThyBytes CTF 2019 部分 pwn 题解
TOC
还是很不错的国际赛。
源程序打包:pwnthebytesctf2019.zip 。
babyfactory
靶机环境是 glibc-2.23 。签到题。
void __fastcall Create(char a1) |
直接输入一个很大的数字进行byte2字节编辑,即可在下面的函数heap overflow
。
void __cdecl Edit() |
直接根据堆风水进行地址泄露,劫持hook即可,脚本如下。
#!/usr/bin/python2 |
由于造成该漏洞的主要原因是,下面代码没有进行置0操作。加上置0操作即可。
if ( a1 ) |
还有一个漏洞需要修复:
Edit
没有对index进行检查,加上检查即可。
void __cdecl Edit() |
Ace of Spades
靶机环境是 glibc-2.23 。
一个模拟扑克牌的游戏。
漏洞点
主要在于程序员对库函数strcpy
的错误使用。
void __cdecl Discard() |
可能设计的时候仅仅是为了让字符串向前移动一个字节,这里完全可以自己实现,但是这里却使用的是strcpy
,对于strcpy
函数来说,如果两个参数地址有重叠的部分,难免会出一些问题。
strcpy 分析
通过查看汇编可知,strcpy并不是单纯的逐个字节转移,这样太浪费CPU资源,而是利用SEX2指令进行整块转移,开始先进行地址对齐,为了避免需要取两次内存的情况而浪费IO资源,而且字符串越长,每个单位块的就越大,当然这是建立在浪费内存空间的基础上的,也就是需要大量的汇编代码实现,但是其效率是无可比拟的。
如果原地址和目标地址没有重叠的话并不会产生问题,但是这里恰好相反。
利用下面的程序来检验是否存在问题:
// gcc -m32 main.c |
通过分析上面的结果,最终得到下面的payload:
// gcc -m32 main.c |
预期结果是123456789ABCD
,得到的结果是123456889ABCD
。
原理分析:
主要问题汇编如下:
__strcpy_sse2 proc near |
当字符串长度为14时,则意味着[ecx+13]就是0,ecx为buf + 1
,由于目标地址和原地址重叠,所以在执行movlpd xmm0, qword ptr [ecx+6]
时,复制了一个重叠的字节。
思路
我们的主要目标是得到尽可能大的分数,这样index
就能超出数组长度,造成数组溢出。
void __cdecl Play() |
通过查看栈布局可得,当index
为16时,也就是保存ebp
的位置,这样我们就能泄露栈地址,又因为其地址旁还黏连了一个程序地址,这样我们又能泄露程序基地址。
-00000040 buf dd 11 dup(?) ; offset |
我们的目标是一个 1 (A),一个 14 (K),三个 100 (Ace of Spades),这样就能得到 16800 的分数,刚好可以完成上面的步骤。
- 利用 strcpy 漏洞,增加 Ace of Spades 牌的数量。
原本 Ace of Spades 牌仅有一张,但是我们可以利用漏洞让其数量增多。这样我们就能获得足以数组溢出的分数。
amount = {100:1, 1:3, 14:4} |
- 不停的增加目标牌的数量,以增加漏洞利用的概率。
for i in range(40): |
- 抽出目标牌从而引发漏洞。
while(True): |
- 泄露地址并进行ROP拿shell
sh.sendlineafter('Your choice: ', '3') # Play |
完整脚本
#!/usr/bin/python2 |
patch方法
根本原因出在strcpy
上,直接自己写一段函数进行替换即可。
mov edi, [esp+4] |
上面这段代码可以直接看成strncpy(dst, src, 52)
,这里还限制了长度,防止非预期的方式造成溢出。