Read the rules
Description
Please follow the rules for this CTF!
Connect here:
Read The Rules
Solution
All we have to do is view the source of the page and look for the flag.
<!-- Thank you for reading the rules! Your flag is: -->
<!-- flag{90bc54705794a62015369fd8e86e557b} -->
Zip Zip
Description
My friend sent me this zip file… He is a prankster and compressed the file a LOT of times…
I don’t know how to make this go quickly and I don’t have the time… At least he told me the password is “pass”.
Can you please help?
Solution
Here we have a recursive zip file. So lets write a script to unzip each file.
#!/usr/bin/env python3
import zipfile
def unzip(file_name):
with zipfile.ZipFile(file_name) as myzip:
file = myzip.namelist()[0]
password = b'pass'
myzip.extractall('out', pwd=password)
if '.zip' in file:
print('Unzipping', file)
unzip('out/' + file)
else:
print('No more zips found')
unzip('50.zip')
When all zip files are unzipped we get a flag.txt file.
[ blackarch ~/ctf/grimmctf/2020/warmups/Zip_Zip/out ]# ls
00.zip 06.zip 12.zip 18.zip 24.zip 30.zip 36.zip 42.zip 48.zip
01.zip 07.zip 13.zip 19.zip 25.zip 31.zip 37.zip 43.zip 49.zip
02.zip 08.zip 14.zip 20.zip 26.zip 32.zip 38.zip 44.zip flag.txt
03.zip 09.zip 15.zip 21.zip 27.zip 33.zip 39.zip 45.zip
04.zip 10.zip 16.zip 22.zip 28.zip 34.zip 40.zip 46.zip
05.zip 11.zip 17.zip 23.zip 29.zip 35.zip 41.zip 47.zip
[ blackarch ~/ctf/grimmctf/2020/warmups/Zip_Zip/out ]# cat flag.txt
flag{cf97382071cb149aac8d6ab8baeaa3ee}
Triple
Description
I was studying something called ASCII armor because I wanted to become better at encoding. I was having fun until I realized I couldn’t decode my message…
Ulc1amIyUnBibWNnWVNCdFpYTnpZV2RsSUdseklHRWdiRzkwSUc5bUlHWjFiaUIxYm5ScGJDQnBkQ0JwYzI0bmRDNGc= V20xNGFGb3pjM3BQVkd0M1RsZFJlVTFVVVRSYWFsSnRXa2RKTTFscVFYbE9WMDE1VFRKUk1rOUVVWGROUkU1cVdXNHdQUT09
Solution
Here we got two base64 encoded strings, lets decode them.
RW5jb2RpbmcgYSBtZXNzYWdlIGlzIGEgbG90IG9mIGZ1biB1bnRpbCBpdCBpc24ndC4gWm14aFozc3pPVGt3TldReU1UUTRaalJtWkdJM1lqQXlOV015TTJRMk9EUXdNRE5qWW4wPQ==
Seems like we have another base64 encoded string, lets check out the contents of this.
Encoding a message is a lot of fun until it isn't. ZmxhZ3szOTkwNWQyMTQ4ZjRmZGI3YjAyNWMyM2Q2ODQwMDNjYn0=
Ok, another one.
flag{39905d2148f4fdb7b025c23d684003cb}
Data dump
Description
Whew, this is a dumpster fire! Can you find anything interesting in here, like any cool passwords or anything? Dig through the dumpster quick, before the foxes and raccoons start eating at it!
Solution
For this challenge we got a compressed data dump. When we unpack it we get a lot of directoires. If we take a look in the home directory we can see a directory called challenge. In this directory we can find a .mozilla folder. Checking out the subfolders for firefox, we can locate a logins.json file containing a encrypted password.
{
"nextId": 2,
"logins": [
{
"id": 1,
"hostname": "http://localhost:31337",
"httpRealm": null,
"formSubmitURL": "http://localhost:31337",
"usernameField": "username",
"passwordField": "password",
"encryptedUsername": "MDIEEPgAAAAAAAAAAAAAAAAAAAEwFAYIKoZIhvcNAwcECPs50spbp6eyBAi0aCUHIntLPA==",
"encryptedPassword": "MFIEEPgAAAAAAAAAAAAAAAAAAAEwFAYIKoZIhvcNAwcECEcjS+e6bXjFBCgCQ0p/1wCqPUmdgXdZWlohMXan4C3jD0bQgzsweyVEpAjJa+P9eOU4",
"guid": "{9a363712-620c-499a-bb7d-999b8b2515dc}",
"encType": 1,
"timeCreated": 1604703907434,
"timeLastUsed": 1604703907434,
"timePasswordChanged": 1604703907434,
"timesUsed": 1
}
],
"potentiallyVulnerablePasswords": [],
"dismissedBreachAlertsByLoginGUID": {},
"version": 3
}
So we should be able to use firepwd to decrypt this password. When we run firepwd with the logins.json file we get the decrypted password.
flag{35446041dc161cf5c9c325a3d28af3e3}
Memorandum
Description
I am so forgetful I have to write everything down.
Solution
For this challenge we get a binary blob. If we extract the strings from this we can find the flag.
strings -n 10 memorandum.bin | grep flag | tee grep.log
And in the grep.log file we can find the flag.
flag{e701f9290e2cd553be981461f8ea08e5}
Sentinel
Description
Only the password will grant access to the flag.
Solution
Here we have an Android app. Lets start by extracting the resources with apktool. In the file res\values\strings.xml we can find a encoded flag.
<string name="encrypted_flag">CVtQFwJcAFRFHAlUVRUdXQUHERgMVlMVSgoPUhUdDg4DRRpfAEw=</string>
If we base64 decode this we get the following in hex.
09 5b 50 17 02 5c 00 54 45 1c 09 54 55 15 1d 5d 05 07 11 18 0c 56 53 15 4a 0a 0f 52 15 1d 0e 0e 03 45 1a 5f 00 4c
Now it’s time to decompile the app with Bytecode Viewer to find out where the encrypted flag is used. When we have decompiled it we can see that it is obfuscated, but looking around the source we can find the following code.
package b.b.a.a;
import android.os.AsyncTask;
import android.util.Base64;
import com.congon4tor.sentinel.MainActivity;
public class a extends AsyncTask {
public MainActivity a;
public a(MainActivity var1) {
this.a = var1;
}
public Object doInBackground(Object[] var1) {
String[][] var2 = (String[][])var1;
int var3 = 0;
String var5 = var2[0][0];
String var7 = var2[0][1];
if (var7.length() != 5) {
var5 = "Invalid password length";
} else {
byte[] var6 = Base64.decode(var5.getBytes(), 0);
byte[] var8 = var7.getBytes();
byte[] var4;
for(var4 = new byte[var6.length]; var3 < var6.length; ++var3) {
var4[var3] = (byte)((byte)(var6[var3] ^ var8[var3 % var8.length]));
}
var5 = new String(var4);
}
return var5;
}
public void onPostExecute(Object var1) {
String var2 = (String)var1;
super.onPostExecute(var2);
this.a.p.setText(var2);
}
}
It looks like the encrypted flag is being XOR:ed with a password with a length of five characters. Luckily for us, we know the first five characters of the plaintext. To get the password all we have to do is XOR flag{ with the first five bytes of the encrypted flag.
When we do this we get the password o71py. And using this to decrypt the complete flag we get the following.
flag{37e5efcded226aacabe3e8ceda925c07}
Axiom
Description
Things which are equal to the same thing are equal to one another.
Solution
This is another Android application. When we decompile this with Bytecode Viewer we can see that it is a React Native application. If we extract the resources with apktool we can find the JavaScript bundle in the assets directory.
Looking around in the bundle we can find an interesting function that has some strings mentioning the flag.
function C() {
var t;
(0, u.default)(this, C);
for (var n = arguments.length, l = new Array(n), s = 0; s < n; s++) l[s] = arguments[s];
return (t = w.call.apply(w, [this].concat(l))).state = {
output: 'Insert the password to get the flag',
text: ''
}, t.hash = 'c193e190062c69fb921332a8a5fc00317a3af35188c2a8f32a7c967d8a8f0d82', t.url = 'http://congon4tor.me:7777', t.token = '652W8NxdsHFTorqLXgo=', t.getFlag = function () {
return o.default.async(function (n) {
for (;;) switch (n.prev = n.next) {
case 0:
return n.prev = 0, n.next = 3, o.default.awrap(y.default.get(t.url + '/?token=' + t.token));
case 3:
response = n.sent, t.setState({
output: response.data
}), n.next = 11;
break;
case 7:
n.prev = 7, n.t0 = n.catch(0), console.log(n.t0), t.setState({
output: 'An error occurred getting the flag'
});
case 11:
case "end":
return n.stop()
}
}, null, null, [
[0, 7]
], Promise)
}, t.onChangeText = function (n) {
t.setState({
text: n
})
}, t.onPress = function () {
t.hash === (0, x.sha256)(t.state.text) ? t.getFlag() : t.setState({
output: 'Invalid password'
})
}, t
}
From this we can see that the getFlag
function calls the endpoint http://congon4tor.me:7777/?token=652W8NxdsHFTorqLXgo=
and when we call this endpoint we get the flag.
flag{c62a673e0381ee32ec46282b94b2003a}
wannabeel33t
Description
We are chasing down a hacker, wannabeel33t and we watch to catch him red-handed. He keeps a low profile online, but he has to have some bad habits…
Solution
So we got the username. Lets use sherlock to find out on which social media platforms we might find him.
[*] Checking username wannabeel33t on:
[+] 500px: https://500px.com/p/wannabeel33t
[+] Badoo: https://badoo.com/profile/wannabeel33t
[+] Pling: https://www.pling.com/u/wannabeel33t/
[+] Realmeye: https://www.realmeye.com/player/wannabeel33t
[+] Reddit: https://www.reddit.com/user/wannabeel33t
[+] Travellerspoint: https://www.travellerspoint.com/users/wannabeel33t
We got some hits, but the most interesting of those are Reddit. Lets start there.

This looks like it might be the right place and the text looks like it’s URL encoded. Lets see what it says when we decode it.
flag{66b15347c58c91d1937f0b40e973d3f6}
Syringe
Description
Doctors love their databases! Here is a library of words and semantics relating to medical words, like “syringe”, or “x-ray”, or “injection”. Find whatever you need, just by searching for it!
Solution
For this challenge we got a web page with a single input field.

When we take a look at the source of the page we can find the following comment.
<!-- if ( isset($_GET["debug"])){ echo($sql_query); } -->
Lets add that to our URL. When we do this we can see the current SQL query for our search.
SELECT * FROM semantics WHERE name LIKE "%%";
Now we have to figure out a way to get the flag by SQLi. If we do a UNION SELECT from the table flag with the following search query f" UNION SELECT * FROM flag; #
we get the flag.

fruitify
Description
Come grab a tasty freshly made juice, they are delicious
Solution
This challenge consists of a page with recipies for smoothies and juices.

Using Burp Suite we can see that there’s a request made to an endpoint called graphql when loading the page.

If we send this request to Repeater we can try to do some GraphQL introspection. If we change the request to {"operationName":"","variables":{},"query":"query {__schema{types{name,fields{name}}}}"}
we get the following response.
{
"data": {
"__schema": {
"types": [
{
"fields": [
{
"name": "id"
},
{
"name": "image"
},
{
"name": "ingredients"
},
{
"name": "method"
},
{
"name": "name"
}
],
"name": "Juice"
},
{
"fields": null,
"name": "String"
},
{
"fields": [
{
"name": "defaultValue"
},
{
"name": "description"
},
{
"name": "name"
},
{
"name": "type"
}
],
"name": "__InputValue"
},
{
"fields": null,
"name": "__TypeKind"
},
{
"fields": [
{
"name": "flag"
},
{
"name": "juice"
},
{
"name": "juices"
}
],
"name": "Query"
},
{
"fields": [
{
"name": "name"
},
{
"name": "quantity"
}
],
"name": "Ingredient"
},
{
"fields": null,
"name": "__DirectiveLocation"
},
{
"fields": [
{
"name": "deprecationReason"
},
{
"name": "description"
},
{
"name": "isDeprecated"
},
{
"name": "name"
}
],
"name": "__EnumValue"
},
{
"fields": [
{
"name": "args"
},
{
"name": "deprecationReason"
},
{
"name": "description"
},
{
"name": "isDeprecated"
},
{
"name": "name"
},
{
"name": "type"
}
],
"name": "__Field"
},
{
"fields": null,
"name": "Int"
},
{
"fields": [
{
"name": "directives"
},
{
"name": "mutationType"
},
{
"name": "queryType"
},
{
"name": "subscriptionType"
},
{
"name": "types"
}
],
"name": "__Schema"
},
{
"fields": [
{
"name": "description"
},
{
"name": "enumValues"
},
{
"name": "fields"
},
{
"name": "inputFields"
},
{
"name": "interfaces"
},
{
"name": "kind"
},
{
"name": "name"
},
{
"name": "ofType"
},
{
"name": "possibleTypes"
}
],
"name": "__Type"
},
{
"fields": null,
"name": "Boolean"
},
{
"fields": [
{
"name": "args"
},
{
"name": "description"
},
{
"name": "locations"
},
{
"name": "name"
}
],
"name": "__Directive"
}
]
}
}
}
Here we can see that there is a query called flag. Lets execute that query with this request {"operationName":"","variables":{},"query":"query flag {flag}"}
, now we get the following response.
{"data":{"flag":"flag{5e4e716b08873b04ed7ee8c2d88a5a2e}"}}
great work man.
LikeLike