Qualify for semi finals! Here is some writeups for the challenges

# brote (rev)

## Challenge file:

We are given a python script

Try run it in terminal:

``````python3 brote.py
Enter flag for verification: a
``````

Look at the source code:

``````import re
import hashlib

def md5_sha1(x):
a = hashlib.sha1(x).hexdigest().encode('utf-8')
return hashlib.md5(a)

def md5_md5_md5(x):
a = hashlib.md5(x).hexdigest().encode('utf-8')
a = hashlib.md5(a).hexdigest().encode('utf-8')
return hashlib.md5(a)

x = [hashlib.sha224, hashlib.sha256, hashlib.sha384, hashlib.sha512, hashlib.md5, hashlib.sha1, md5_sha1, md5_md5_md5]
]

def check_flag(flag):
flag = flag.encode()
chunks = [flag[i:i+4] for i in range(0, len(flag), 4)]
for c,(f,o) in zip(chunks, zip(x,y)):
if f(c).hexdigest() != o:
return False
return True

user_input = input("Enter flag for verification: ")

if user_input and \
len(user_input) == 32 and \
re.match(r'^[a-z0-9]+\$', user_input) and \
check_flag(user_input):
print("Congratulations!")
else:
``````

We can see our input is the flag, and the correct flag should be:

1. In length of 32
2. lowercase letter or number
3. return true for `check_flag`

Let’s see what `check_flag` function does:

``````def check_flag(flag):
flag = flag.encode()
chunks = [flag[i:i+4] for i in range(0, len(flag), 4)]
for c,(f,o) in zip(chunks, zip(x,y)):
if f(c).hexdigest() != o:
return False
return True
``````

We can see it split the `flag` in four chunks, then it pass into a for loop

The for loop is just looping for hash functions in `x` is it equal to hex values `y`

You can see the `x` and `y` array:

``````x = [hashlib.sha224, hashlib.sha256, hashlib.sha384, hashlib.sha512, hashlib.md5, hashlib.sha1, md5_sha1, md5_md5_md5]
]
``````

We know that hash functions cannot reverse but we can brute force it!

Therefore, to solve this we must brute force the flag but in 4 character at a time

So quite fast to solve this

## Solving

Write a simple python script, I use pwntools the brute force the flag:

``````flag = ''

for i in range(len(x)):
flag += pwnlib.util.iters.mbruteforce(lambda text: x[i](text.encode()).hexdigest() == y[i], string.ascii_lowercase+string.digits, length = 4)
print(flag)
# [+] MBruteforcing: Found key: "fsbr"
# [+] MBruteforcing: Found key: "34k4"
# [+] MBruteforcing: Found key: "llth"
# [+] MBruteforcing: Found key: "3s3h"
# [+] MBruteforcing: Found key: "4sh3"
# [+] MBruteforcing: Found key: "spl3"
# [+] MBruteforcing: Found key: "453c"
# [+] MBruteforcing: Found key: "yber"
# fsbr34k4llth3s3h4sh3spl3453cyber
``````

Thats it! Simple reverse challenge! Full python script

# Crypto Stream

## Challenge files

We are given a python script `encrypt.py` and a binary file `flag.enc`

Let’s see the source code:

``````import random
from secret import flag, key

def generate_key(s):
assert len(s) == 16, "The key must be 16 bytes long"

k = [0, 0]
for i in range(len(s)):
if i == 0:
k[0] = k[0] ^ s[i]
k[1] = (k[1] + s[i]) & 0xFF
else:
k[0] = (k[0] ^ (s[i] - s[i - 1])) & 0xFF
k[1] = (k[1] + s[i] ^ s[i - 1]) & 0xFF

return k

def encrypt(s, k):
n1 = k[0]
n2 = k[1]

encrypted = []
for c in s:
encrypted.append(c ^ n1)
random.seed(n1)
n1 = n2
n2 = random.randint(0, 255)

return bytes(encrypted).hex()

e = encrypt(flag, generate_key(key))

with open('flag.enc', 'w') as f:
f.write(e)
``````

As you can see, it encrypts the `flag` with a `key` that we don’t know

Then save the encrypted flag inside `flag.enc`

## First bug

Notice that the `generate_key` function return array `k` and the value must be <= 255

Because it perform AND bitwise operation, therefore the generated key must be <= 255

## Second bug

We can predict the value of `n1` and `n2` inside the `encrypt` function

Because it use `n1` as the random seed, that means if we know the correct `n1` we can predict `n2` and the entire flag!!

## Solving (Brute force)

My idea is to brute force all 256 values for `k[0]` and `k[1]`, until it decrypt the flag starts with `fs` and ends with `cyber`

``````enc = binascii.unhexlify(open("flag.enc",'rb').read())

for k1 in range(256):
for k2 in range(256):
flag = decrypt(f,[k1,k2]) # decrypt is same as encrypt
if flag.startswith(b"fs") and flag.endswith(b"cyber"):
print(k1,k2)
print(flag)
# 40 186
# b'fsKn0wnPl41NTextA77ackcyber'
``````

We can see the key is 40 and 186, and we get the decrypted flag!!

Full python script

## Solving (Decrypt)

Another method is to calculate the key using the flag format

`n1 = k[0]`, `n2 = k[1]` and it encrypt the flag using `c ^ n1`

To find `n1` and `n2`, we can XOR the character of encrypted flag and `fs`

We know the flag format starts with `fs`, therefore to find `k1` we can calculate `f XOR enc_flag[0]`, to find `k2` calculate `s XOR enc_flag[1]`

Write in Python script:

``````enc = binascii.unhexlify(open("flag.enc",'rb').read())

k = [ord('f') ^ enc[0], ord('s') ^ enc[1]]
print(k)
print(decrypt(enc,k))
# [40, 186]
# b'fsKn0wnPl41NTextA77ackcyber'
``````

As you can see, we get the same key and same flag!

Full python script

# Monalisa

## Challenge files

We are given a PCAP file (Packet capture file)

Lets open it with Wireshark

There are many packets in the file..

We can filter the content by enter `http` in the filter and enter:

Can see there are many stuff like html file, style css etc.

We can export the objects by going File > Export Objects > HTTP

After that click Save All to a folder

## Analyze

Saw a file called `client.js` seems interesting..

``````document.addEventListener("DOMContentLoaded", function() {
function x() {
return Math.floor(100 * Math.random()) + 1
}
var n = {
click: !1,
move: !1,
pos: {
x: 0,
y: 0
},
pos_prev: !1
},
e = document.getElementById("board"),
t = e.getContext("2d"),
i = window.innerWidth,
c = window.innerHeight,
r = io.connect();
e.width = i, e.height = c, e.onmousedown = function(o) {
n.click = !0
}, e.onmouseup = function(o) {
n.click = !1
}, e.onmousemove = function(e) {
n.pos.x = e.clientX / i + x(), n.pos.y = e.clientY / c + x(), n.move = !0
}, r.on("coor", function(o) {
var n = o.line,
x1 = (n[0].x - Math.floor(n[0].x)) * i,
y1 = (n[0].y - Math.floor(n[0].y)) * c,
x2 = (n[1].x - Math.floor(n[1].x)) * i,
y2 = (n[1].y - Math.floor(n[1].y)) * c;
t.beginPath(), t.moveTo(x1, y1), t.lineTo(x2, y2), t.stroke()
}),
function o() {
n.click && n.move && n.pos_prev && (r.emit("coor", {
line: [n.pos, n.pos_prev]
}), n.move = !1), n.pos_prev = {
x: n.pos.x,
y: n.pos.y
}, setTimeout(o, 25)
}()
});
``````

Seems like it is sending some x and y coordinates..

Also saw the HTML file:

``````<!DOCTYPE html>
<html>
<title>monalisa</title>
<meta charset="utf-8">
<script src="socket.io/socket.io.js"></script>
<script src="client.js"></script>
<body>
<canvas id="board"></canvas>
</body>
</html>
``````

The challenge name called Monalisa, so we can guess it is drawing the flag, and the draw coordinates was recorded in this packet capture file

Lets try to find the coordinates!

After finding in the wireshark, finally I found the coordinates in WebSocket!

We can see the whole coordinates Right Click > Follow > TCP Stream

Then it will show all coordinates sent:

Click `Save as` to save as a file

## Solving

We need to investigate how to recover the “drawing”

By searching `Javascript drawing` can see alot of tutorials like this one

``````var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
ctx.moveTo(0,0);
ctx.lineTo(200,100);
ctx.stroke();
``````

Is simple, `moveTo` is the starting point and `lineTo` is the ending point

Therefore we have to gather all coordinates in the capture file and then process it in this script!

We can use `grep` command in Bash to grab only the coordinates of the file:

``````grep -Po '\[{"x":[0-9]+\.[0-9]+,"y":[0-9]+\.[0-9]+},{"x":[0-9]+\.[0-9]+,"y":[0-9]+\.[0-9]+}\]' coordinates | while read line;do echo \$line,;done
``````

Alternatively, can use python script:

``````import re

coor = re.findall(r'\[{"x":[0-9]+\.[0-9]+,"y":[0-9]+\.[0-9]+},{"x":[0-9]+\.[0-9]+,"y":[0-9]+\.[0-9]+}\]', f)
for c in coor:
print(c,end=',\n')
``````

I use the HTML template on W3school:

``````<!DOCTYPE html>
<html>
<body>

<canvas id="myCanvas" width="200" height="100"
style="border:1px solid #d3d3d3;">
Your browser does not support the canvas element.
</canvas>

<script>

var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
ctx.moveTo(0,0);
ctx.lineTo(200,100);
ctx.stroke();

</script>

</body>
</html>
``````

Copy the coordinates into the script:

``````<!DOCTYPE html>
<html>
<body>

<canvas id="myCanvas"
style="border:1px solid #d3d3d3;">
Your browser does not support the canvas element.
</canvas>

<script>

var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
var coor = [
[{"x":23.06351665375678,"y":74.46076794657763},{"x":23.06351665375678,"y":74.46076794657763}],
...
...
...
]
for (var i = 0; i < coor.length; i++) {
x1 = coor[i][0]["x"];
y1 = coor[i][0]["y"];
x2 = coor[i][1]["x"];
y2 = coor[i][1]["y"];
ctx.moveTo(x1,y1);
ctx.lineTo(x2,y2);
ctx.stroke();
}

</script>

</body>
</html>
``````

Open it in browser, it will show the flag (if not mistaken..)

Its not like flag or Monalisa…

Look back the `client.js`:

``````function x() {
return Math.floor(100 * Math.random()) + 1
}
...
...
e.onmousemove = function(e) {
n.pos.x = e.clientX / i + x(), n.pos.y = e.clientY / c + x(), n.move = !0
},
``````

Notice it got add some random values in the coordinates! But how we gonna guess the coordinate if we don’t know the flag??

Look carefully in how it draw the lines:

``````i = window.innerWidth,
c = window.innerHeight,
...
...
r.on("coor", function(o) {
var n = o.line,
x1 = (n[0].x - Math.floor(n[0].x)) * i,
y1 = (n[0].y - Math.floor(n[0].y)) * c,
x2 = (n[1].x - Math.floor(n[1].x)) * i,
y2 = (n[1].y - Math.floor(n[1].y)) * c;
t.beginPath(), t.moveTo(x1, y1), t.lineTo(x2, y2), t.stroke()
})
``````

It takes the coordinates minus the integer part left only decimal part (minus Math.floor) then multiply by width or height

That means we don’t even need to guess the random number, because we only need the decimal part and integer part (random number) is not important!

Added some code to minus and multiply the width and height:

``````var w = window.innerWidth;
var h = window.innerHeight;
canvas.width = w;
canvas.height = h;

for (var i = 0; i < coor.length; i++) {
x1 = (coor[i][0]["x"] - Math.floor(coor[i][0]["x"])) * w;
y1 = (coor[i][0]["y"] - Math.floor(coor[i][0]["y"])) * h;
x2 = (coor[i][1]["x"] - Math.floor(coor[i][1]["x"])) * w;
y2 = (coor[i][1]["y"] - Math.floor(coor[i][1]["y"])) * h;
ctx.moveTo(x1,y1);
ctx.lineTo(x2,y2);
ctx.stroke();
}
``````

It draw us the Monalisa!! Full HTML script

Interesting and fun forensics challenge!

# Web

## Challenge file:

We are given a HTML file, lets look at it:

``````<script>
...
...
...
</script>
``````

Looks like obfuscated.. lets beautify it (Can use online Javascript Beautifier)

I use sublime text package for Javascript Beautify

## Analyze

At the start of the script we can see it get the parameter `p` from the URL:

``````var url_string = window['location']['href'],
url = new URL(url_string),
p = url['searchParams']['get']('p');
``````

Then at the end of script it check the `p` is length of 0x18 (24) and pass to `check` function:

``````p != null && p['length'] == 0x18 && check(p);
``````

Can see I test added `p` parameter in the URL:

Looks like `p` is the password and also flag

Lets look into `check` function:

``````function check(_0x1c2dbb) {
var _0x48f7e1 = [aa, bb, cc];
for (var _0x4b521e = 0x0; _0x4b521e < _0x48f7e1['length']; _0x4b521e++) {
var _0x1fd69e = _0x48f7e1[_0x4b521e](_0x1c2dbb);
if (!_0x1fd69e) {
return;
}
}
}
``````

It looks messy! let me clean up abit to see whats going on:

``````function check(flag) {
var func = [aa, bb, cc];
for (var i = 0x0; i < func['length']; i++) {
var correct = func[i](flag);
if (!correct) {
return;
}
}
}
``````

Now we can see clearly, it just pass our password (flag) into 3 functions `aa` `bb` `cc`

Then if one of them return `false` then our flag is not correct!

## First part (Sha256)

Look into function `aa`:

``````function aa(_0x23c1f1) {
var _0xbdcdeb = ['dce7cce055566bed799f788cd0048e209a27a473c0f48b956fa1f1780e80d2c1', '635ca73d00d4f28b5f573b16eea56e9e4579d77e561c32aa68189d9769fa1753', 'a4d0ef23161b5b7c6a8d5b287543fd74e16b3bf313d71aa187c24cdd728a7b1e', 'e0b9a8799f32453a478c9122f8b83cee68e16db18f493ac81bc1d474594b5df4'],
_0x39b271 = _0x23c1f1['substring'](0x0, 0x8)['match'](/.{1,2}/g);
for (var _0x38d68b = 0x0; _0x38d68b < _0x39b271['length']; _0x38d68b++) {
var _0x5169a8 = ansdweasd(_0x39b271[_0x38d68b]);
if (_0x5169a8 != _0xbdcdeb[_0x38d68b]) return ![];
}
return !![];
}
``````

Hmm.. the long string in the variable seems like hash, lets try to crack it in crackstation

It is a hash! Is Sha256 and it cracked the flag format `fs`

After cracking all 4 hashes, we can get the part of flag `fs0bfusc`

Can use it running `['substring'](0x0, 0x8)` with our flag (1st character to 8th character) so total 8 characters

## Second part (ROT13)

We will look at function `cc` first:

``````function cc(_0x159c99) {
var _0x593622 = ebg13(_0x159c99['substring'](0x10, 0x18));
return _0x593622 == '4egplore';
}
``````

Can see it pass the last 8 characters of the flag to function `ebg13`:

``````function ebg13(_0x394e9e) {
_0xe7ba36 = 'NOPQRSTUVWXYZABCDEFGHIJKLMnopqrstuvwxyzabcdefghijklm',
_0x4e7551 = _0x228b79 => _0x178280(_0x228b79) > -0x1 ? _0xe7ba36[_0x178280(_0x228b79)] : _0x228b79;
return _0x394e9e['split']('')['map'](_0x4e7551)['join']('');
}
``````

This function looks like doing some mapping of alphabet, we can guess this is doing the famous encryption ROT13!! The function name also hint it

Therefore, we just have to decrypt `4egplore` using ROT13, it is

``````4rtcyber
``````

## Third part (XOR)

Now we look at function `bb`:

``````function bb(_0x507300) {
var _0x3360b0 = _0x507300['substring'](0x0, 0x2) + _0x507300['substring'](0x14, 0x16),
_0x5415bb = _0x507300['substring'](0x8, 0x10),
_0x244a1b = [0x52, 0x7, 0x4a, 0x6, 0x4, 0xa, 0x0, 0x12];
for (var _0x58422e = 0x0; _0x58422e < _0x5415bb['length']; ++_0x58422e) {
var _0x2e8721 = _0x3360b0[_0x58422e % _0x3360b0['length']]['charCodeAt'](0x0),
_0x40bbc5 = _0x5415bb[_0x58422e]['charCodeAt'](0x0);
if (_0x244a1b[_0x58422e] != (_0x2e8721 ^ _0x40bbc5)) return ![];
}
return !![];
}
``````

Looks messy also clean it up:

``````function bb(flag) {
var f1 = flag['substring'](0x0, 0x2) + flag['substring'](0x14, 0x16),
f2 = flag['substring'](0x8, 0x10),
verify = [0x52, 0x7, 0x4a, 0x6, 0x4, 0xa, 0x0, 0x12];
for (var i = 0x0; i < f2['length']; ++i) {
var a = f1[i % f1['length']]['charCodeAt'](0x0),
b = f2[i]['charCodeAt'](0x0);
if (verify[i] != (a ^ b)) return ![];
}
return !![];
}
``````

Ok look much better..

Can see it perform some XOR operation, we know that XOR operation can be reverse easily

Like `A XOR B = C` then, `A = C XOR B`, `B = C XOR A`

We know the first and last 8 characters of the flag, which means we know what is `f1`, can see the code `f1` is XOR with `f2`

Therefore, we can calculate middle part of flag (which is `f2`) based on `f1` and the `verify` variable!

Write a simple python script to calculate this:

``````flag = bytearray("fs0bfusc????????4rtcyber",encoding="ascii")
f1 = flag[0:2] + flag[0x14:0x16]
verify = [0x52, 0x7, 0x4a, 0x6, 0x4, 0xa, 0x0, 0x12]

for i in range(8):
flag[i+8] = verify[i] ^ f1[i%4]
print(flag)
# bytearray(b'fs0bfusc4t3dbyyp4rtcyber')
``````

We made it! We get the whole flag! Lets test it in the URL:

Thats it simple JS reversing!