🌐
Medium
medium.com › @dassomnath › from-format-string-to-building-a-rop-chain-ft-musl-libc-nitectf-2025-1d3ef9838d12
From Format String to Building a ROP chain ft. musl libc — niteCTF 2025 | by Somnath Das | Medium
December 15, 2025 - beating_yellow_king_with_musl_in_ng+ is a binary exploitation challenge. From Off-by-one to read/write primitive via Format String vulnerability and from ROP chain to shell.
🌐
Barrebas
barrebas.github.io › blog › 2015 › 02 › 22 › maximum-overkill-two-from-format-string-vulnerability-to-remote-code-execution
Maximum Overkill Two - From Format String Vulnerability to Remote Code Execution - staring into /dev/null
This was a story of how a single format string vulnerability was beaten into arbitrary code execution. The exploit bypasses ASLR and NX via ROP, and finally sends over shellcode which will be executed. The CTF challenge was not designed with this in mind, but it was a fun exercise (and a potential warmup for Boston Key Party) nonetheless!
🌐
Medium
medium.com › @0xk4g3 › format-string-to-rop-ctf-write-up-dubai-police-fb14bf74a158
Format String to ROP — CTF Write-up (Dubai police) | by Libc | Medium
October 19, 2025 - HOST = "26e64bd890b082ae.chal.ctf.ae"def connect(): return remote(host=HOST, port=443, ssl=True, sni=HOST)def leak_addresses(r): r.sendlineafter(b"):", b"1") r.sendlineafter(b".\n", b"%3$p:9$lx") full_leak = r.recvline().strip().split(b":") stack_leak = int(full_leak[0], 16) libc_leak = int(full_leak[1], 16) return stack_leak, libc_leakdef calculate_addresses(stack_leak, libc_leak): libc = ELF('./libc.so.6', checksec=False) libc.address = libc_leak - 0x2a1ca ret_address = stack_leak - 56 return libc, ret_addressdef build_rop_chain(libc, ret_address): libc_rop = ROP(libc, badchars=b'') writes =
🌐
Cotonne does Craft!
cotonne.github.io › binary › 2020 › 07 › 14 › format-string.html
Exploiting Format String with PwnTools | Cotonne does Craft!
July 14, 2020 - You can then add the base address of system, the ROP gadget and the binsh string to get their real address in memory · Call FmtStr to calculate the offset. Provide addresses and values that need to be written to FmtStr. Don’t forget to provide the number of character already written as %n will use it to write the value in the memory. FmtStr automates all the boring stuff. With the format string exploit, the number of characters will be written at the provided address.
🌐
GitHub
github.com › hellman › libformatstr
GitHub - hellman/libformatstr: Simplify format string exploitation.
Small script to simplify format string exploitation. Case 1 - replace one dword: import sys from libformatstr import FormatStr addr = 0x08049580 system_addr = 0x080489a3 p = FormatStr() p[addr] = system_addr # buf is 14th argument, 4 bytes are already printed sys.stdout.write( p.payload(14, start_len=4) ) Case 2 - put ROP code somewhere: import sys from libformatstr import FormatStr addr = 0x08049580 rop = [0x080487af, 0x0804873c, 0x080488de] p = FormatStr() p[addr] = rop sys.stdout.write( p.payload(14) ) Case 3 - guess argument number and padding: import sys from libformatstr import FormatStr
Starred by 343 users
Forked by 36 users
Languages   Python 96.9% | C 2.4% | Makefile 0.7% | Python 96.9% | C 2.4% | Makefile 0.7%
🌐
CTFtime.org
ctftime.org › writeup › 21899
CTFtime.org / redpwnCTF 2020 / dead-canary / Writeup
This payload consists of the following parts - Format string `A$016llx;` to print the return address where main will return in `__libc_start_main`. This address will be later utilized to get other addresses like address of `system` - Format string `9$016llx;` to print the canary - Format string `196117d$n000` to write into the 11th argument (GOT entry of `__stack_chk_fail` that we are going to pass) the value `0x00400737` - Address of GOT entry of `__stack_chk_fail` is passed on the stack with `p64(stack_chk_fail_got)` - A padding upto the canary and sending `\x01` into the first byte of the canary since we know that the first byte is anyways `\x00` and if we smash any further then we won't be able to get the real value of the canary.
🌐
HACKINGISCOOL
hackingiscool.pl › stack-canary-rop-format-string-leak-also-how-i-learned-nullbyte-is-not-a-badchar-to-scanf-string
Stack-canary (ROP), format string leak plus how I learned that nullbyte is not a badchar to scanf("%s",buf) - while socat ignores read on STDIN - MBE LAB8A
July 29, 2019 - If we apply abuser friendly format string %p (so the whole dword of choice is printed, as hex) - just like we did here https://hackingiscool.pl/heap-overflow-with-stack-pivoting-format-string-leaking-first-stage-rop-ing-to-shellcode-after-making-it-executable-on-the-heap-on-a-statically-linked-binary-mbe-lab7a/) - considering that 512/4 = 128, we would expect our canary at 9$p.
🌐
Tum
sec.in.tum.de › i20 › publications › blind-format-string-attacks › @@download › file › formatstring.pdf pdf
Blind Format String Attacks Fatih Kilic, Thomas Kittel, and Claudia Eckert
ing format string attacks. We will describe the basic concepts of these attacks · in the next section. In the recent years, however, this topic gained less interest. Payer et al. [12], recently describes a method for applying both Return Oriented · Programming (ROP) [15] and Jump Oriented Programming (JOP) [5] to for-
🌐
Ret2rop
ret2rop.com › 2018 › 10 › format-strings-got-overwrite-remote.html
Format Strings: GOT overwrite to change Control Flow Remotely on ASLR
June 5, 2020 - Would you have to put the GOT address at the start of the payload, so it is passed to puts as an argument (on 32 bit). Or is there an easier way to determine the libc version using a format string vulnerability. ReplyDelete ... Yes you can although you need to setup more ROP chain to fill proper arguments in registers for puts.
🌐
Boogy's Place
reverser.ninja › 2015 › 22 › small-introduction-to-rop-and-format-string.html
Small introduction to ROP and format string - Boogy's Place
May 22, 2015 - As the title indicates, this is a very small introduction to return oriented programing (ROP) and format strings for people that don't yet know what this techniques are and what they are used for. This post is meant for people willing to understand what this 2 exploitation techniques are so …
Find elsewhere
🌐
Gitlab
xanhacks.gitlab.io › ctf-docs › pwn › buffer-overflow › 40-rop-x64-format-string
ROP & PIE leak (Format string) - CTF Docs
In conclusion, the ROP chain is executed, thanks to the buffer overflow, by utilizing both the ret (for stack alignment) and pop rdi gadgets. This sets the first argument of the system function with the address of /bin/sh. Subsequently, the system function is invoked. The Python script below determines the format string offset of addr_heap_buffer by looking for the value AAAABBBB in the stack.
🌐
Shells
book.jorianwoltjer.com › binary-exploitation › return-oriented-programming-rop
Return-Oriented Programming (ROP) | Practical CTF
May 28, 2025 - When searching for ROP gadgets to achieve this, you can use mov instructions that look like: If you control both registers, you can write any value into any address, as an "arbitrary write". There are many different ways to achieve this and you can be creative with it. Then just write a few addresses after each other to form a full string.
🌐
CTFtime.org
ctftime.org › writeup › 30724
CTFtime.org / TSG CTF 2021 / Coffee / Writeup
Then that `ret` would land in all them `A`'s, where instead of `A`'s we could write out a ROP chain. ... Any that have used _ret2csu_ will know exactly where to find a chain of pops to move the stack pointer down: ``` 401286: 48 83 c4 08 add rsp,0x8 40128a: 5b pop rbx 40128b: 5d pop rbp 40128c: 41 5c pop r12 40128e: 41 5d pop r13 401290: 41 5e pop r14 401292: 41 5f pop r15 401294: c3 ret ``` Each statement will move the stack pointer down stack and the `ret` will pop the top of the stack into RIP. ... 1. Use a format-string exploit to leak libc from the stack and GOT overwrite `puts` with our pop sled, and `_start` over.
Top answer
1 of 1
2

ROP is for bypassing non-executable stack. There are further security measures that need to be circumvented for a successful exploit. For this exercise let's focus strictly on ROP and assume you have a simple setup without ASLR and such. In particular we assume that you have easy access to the stack pointer and function addresses.

We'd like to invoke printf("%d\n", edx). Using the normal 32 bit x86 cdecl calling convention we need those two arguments on the stack. The format string is easy, but we have to get edx into memory. Since we can't write any code we need to find existing instructions that do this for us. The C library is a good candidate. Spotting appropriate code is the hard part. Using objdump I have found the following promising snippet:

   2e535:       89 54 24 04             mov    DWORD PTR [esp+0x4],edx
   2e539:       ff 55 14                call   DWORD PTR [ebp+0x14]

This puts edx on the stack in the right place and calls a function through a function pointer. Must be my lucky day, because said pointer is addressed using ebp and it's easy to set the value of that since the standard function epilogue frequently does pop ebp; ret. I found one such pair nearby, at offset 2e6C1. Obviously the call will not return to our code, as such it will do undefined things after it has done the printing (it will most probably crash). If that bothers you, you'll have to find a more suitable code fragment. Don't forget to add the load address of the C library to the offsets you find.

Thus the required stack layout looks like this:

  • esp+00h: address of pop ebp; ret
  • esp+04h: esp+00h (address of address of printf offset by -0x14)
  • esp+08h: address of code that puts edx on stack and calls function pointer
  • esp+0Ch: esp+18h (address of format string)
  • esp+10h: placeholder for edx
  • esp+14h: address of printf
  • esp+18h: format string %d\n

I hope this illustrates the idea well enough so that you can come up with a solution that fits your particular setup.

🌐
Synacktiv
synacktiv.com › en › publications › exploiting-a-blind-format-string-vulnerability-in-modern-binaries-a-case-study-from
Exploiting a Blind Format String Vulnerability in Modern Binaries: A
Additionally, it was close enough to be accessed with a stack adjustment gadget, allowing us to execute our ROP chain. Using the format string specifier %*X$c, we could read a value at a specific stack offset (such as the return address) and store it in the internal "character counter".
🌐
CTFtime.org
ctftime.org › writeup › 26750
CTFtime.org / BlueHens CTF 2021 / ForMatt Zelinsky / Writeup
March 19, 2021 - # We now use the format string vulnerability to write and execute a ropchain # Overwrite EIP with whatever we want and use it to leak LIBC. # In order to leak libc we execute puts with a function's GOT entry address as an argument. # This way puts will print out, as a string, the address of ...
🌐
hackndo
en.hackndo.com › return-oriented-programming
ROP - Return Oriented Programming - hackndo
June 4, 2024 - $ ROPgadget --binary rop | grep "inc eax" [...] 0x0804812c : inc eax ; ret [...] Perfect, so far so good. Then we have to make EBX point to the string “/bin/sh”, and ECX and EDX are null pointers, because we don’t need them.
🌐
Vidbuchanan
da.vidbuchanan.co.uk › blog › WPICTF-2018-forker-writeup.html
WPICTF 2018: Forker[1-4] Writeup - Blind-ish ROP | Blog
This is annoying, because we don't ... stage ROP gadgets. Thankfully, we can bruteforce the return address in a similar way to the canary. However, there is a slight shortcut we can take, using partial overwrites! When check_password returns, it just so happens that rsi points to the second character of our input. If we partially overwrite the return address to point to one of the calls to dprintf, then we can use a format string to leak whatever ...
🌐
Codearcana
codearcana.com › posts › 2013 › 05 › 28 › introduction-to-return-oriented-programming-rop.html
Introduction to return oriented programming (ROP)
May 28, 2013 - Last, the libc library actually contains the string /bin/sh, which we can find with gdb5 use for exploits! It is fairly straightforward to plug both of these addresses into our previous exploit: $ ./a.out "$(python -c 'print "A"*0x6c + "BBBB" + "\x30\x24\x5d\x55" + "CCCC" + "\x18\x3f\x6f\x55"')" $ With ROP, it is possible to do far more powerful things than calling a single function.
🌐
ired.team
ired.team › offensive-security › code-injection-process-injection › binary-exploitation › rop-chaining-return-oriented-programming
ROP Chaining: Return Oriented Programming | Red Team Notes
October 15, 2021 - Finally, ret instruction executes, which pops the exit() address from the stack and jumps to it, completing our second ROP chain execution and gracefully closing the vulnerable program. We could have chosen to inspect the popret gadget and we would have seen a nearly identical behaviour to the one noted above, except that popret would have popped only one value from the stack before executing the ret instruction. Below is a useful python snippet that converts a given memory address, i.e 0x565561d4, to it's little-endian format, i.e \\xd4\\x61\\x55\\x56: