⏪
CTFs
TwitterGithub
  • 👋Introduction
  • 📚Write Up
    • 2024
      • 📖1337UP LIVE CTF
        • Reverse Engineering
        • Mobile
        • Forensic
        • Misc
      • 📖HKCERT CTF Quals
        • Reverse Engineering
        • Binary Exploitation
      • 📖Flare-On 11
        • Challenge #1 - frog
      • 📖Intechfest
        • Reverse Engineering
        • Forensic
        • Cryptography
        • Mobile
      • 📖Cyber Breaker Competition (1v1)
        • Reverse Engineering
        • Web Exploitation
        • Cryptography
        • Binary Exploitation
      • 📖Cyber Breaker Competition Quals
        • Reverse Engineering
        • Web Exploitation
        • Cryptography
      • 📖BlackHat MEA Quals
        • Reverse Engineering
        • Forensic
      • 📖TFC CTF
        • Reverse Engineering
        • Forensic
        • Misc
      • 📖DeadSec CTF
        • Reverse Engineering
        • Web Exploitation
      • 📖Aptos - Code Collision CTF
        • Reverse Engineering
        • Misc
      • 📖DownUnder CTF
        • Reverse Engineering
      • 📖JustCTF
        • Reverse Engineering
        • Forensic
        • Misc
      • 📖Akasec CTF
        • Reverse Engineering
        • Forensic
      • 📖Codegate CTF Preliminary
        • Reverse Engineering
      • 📖NahamCon CTF
        • Cryptography
        • Reverse Engineering
        • Malware
        • Misc
        • Mobile
        • Scripting
        • Web Exploitation
        • Forensic
      • 📖SAS CTF Quals
        • Reverse Engineering
      • 📖SwampCTF
        • Reverse Engineering
        • Misc
        • Cryptography
      • 📖UNbreakable International
        • Reverse Engineering
        • Network
        • Cryptography
      • 📖ACSC
        • Reverse Engineering
        • Hardware
        • Web Exploitation
      • 📖0xL4ugh
        • Mobile
    • 2023
      • 📖BlackHat MEA Final
        • Reverse Engineering
        • Web Exploitation
      • 📖Flare-On 10
        • Challenge #1 - X
        • Challenge #2 - ItsOnFire
        • Challenge #3 - mypassion
        • Challenge #4 - aimbot
        • Challenge #5 - where_am_i
        • Challenge #6 - FlareSay
        • Challenge #7 - flake
        • Challenge #8 - AmongRust
        • Challenge #9 - mbransom
        • Challenge #10 - kupo
        • Challenge #11 - over_the_rainbow
        • Challenge #12 - HVM
        • Challenge #13 - y0da
      • 📖LakeCTF Quals
        • Reverse Engineering
        • Cryptography
      • 📖TSG CTF
        • Reverse Engineering
        • Cryptography
      • 📖ISITDTU Quals
        • Web Exploitation
        • Misc
        • Reverse Engineering
      • 📖BlackHat MEA Quals
        • Reverse Engineering
      • 📖ASCIS Final
        • Reverse Engineering
        • Web Exploitation
        • Cryptography
      • 📖ASCIS Quals
        • Reverse Engineering
        • Forensic
        • Cryptography
      • 📖IFest
        • Reverse Engineering
        • Cryptography
        • Misc
      • 📖Cyber Jawara International
        • Reverse Engineering
        • Forensic
        • Cryptography
        • Web Exploitation
      • 📖Intechfest
        • Reverse Engineering
        • Forensic
        • Cryptography
        • Mobile
      • 📖CSAW Quals
        • Reverse Engineering
      • 📖SECCON Quals
        • Reverse Engineering
      • 📖CTFZone Quals
        • Reverse Engineering
      • 📖Securinets Quals
        • Reverse Engineering
      • 📖Compfest Final (Attack Defense)
        • Web Exploitation
        • Cryptography
      • 📖Compfest Quals
        • Reverse Engineering
        • Cryptography
        • Forensic
        • Misc
      • 📖Tenable
        • Reverse Engineering
        • Cryptography
        • Steganography
      • 📖ASCWG Quals
        • Reverse Engineering
        • Cryptography
      • 📖Gemastik Quals
        • Reverse Engineering
      • 📖BSides Indore
        • Reverse Engineering
        • Cryptography
      • 📖NahamCon CTF
        • Cryptography
      • 📖HSCTF
        • Reverse Engineering
        • Cryptography
        • Web Exploitation
        • Misc
      • 📖ACSC
        • Reverse Engineering
      • 📖HackTM Quals
        • Reverse Engineering
    • 2022
      • 📖Intechfest
        • Reverse Engineering
        • Mobile
        • Cryptography
      • 📖NCW Final
        • Reverse Engineering
      • 📖NCW Quals
        • Reverse Engineering
        • Misc
        • Cryptography
      • 📖Compfest Final
        • Reverse Engineering
        • Forensic
      • 📖Compfest Quals
        • Reverse Engineering
        • Cryptography
      • 📖IFest
        • Reverse Engineering
        • Cryptography
        • Forensic
    • 2021
      • 📖Cyber Jawara Final
        • Reverse Engineering
      • 📖Cyber Jawara Quals
        • Reverse Engineering
        • Cryptography
      • 📖DarkCon CTF
        • Reverse Engineering
      • 📖Wreck IT Quals
        • Mobile
      • 📖MDT4.0 Final
        • Reverse Engineering
        • Cryptography
        • Forensic
      • 📖MDT4.0 Quals
        • Reverse Engineering
        • Cryptography
      • 📖IFest
        • Reverse Engineering
        • Cryptography
      • 📖Compfest Final
        • Reverse Engineering
      • 📖Compfest Quals
        • Reverse Engineering
        • Cryptography
    • 2020
      • 📖Deep CTF
        • Reverse Engineering
  • 🚩Lifetime CTF
    • 📖Hack The Box
      • Reverse Engineering
        • TBU
Powered by GitBook
On this page
  • Sequel (499 pts)
  • Description
  • Solution
  1. Write Up
  2. 2023
  3. Cyber Jawara International

Forensic

PreviousReverse EngineeringNextCryptography

Last updated 9 months ago

Challenge
Link

Sequel (499 pts)

Sequel (499 pts)

Description

-

Solution

Given json file, when we check the data we found sql injection payload on query parameter.

Payload we found are used for time based sql injection based on the time to deliver the generated file from randomblob. So the first step we do is determining the difference between true response or false response. In this case we found that we can utilize “time” key to determine that, so if the return is randomblob(1500000000/2) the time should be greater than 3 but if the return is randomblob(1000000000/2) the time should be greater than 2 but lower than 3. After that since we know the operation, index value (substring), and the result from query we can use z3 to find the correct value. For the operation we trial error also analyzing the result to find the correct parenthesis, something like if there is modulo and multiplication which operation will be done first. Here is parser we create to get the z3 constraint format.

import json
import re

def check(url):
	for i in blacklist:
		if(url.endswith(i)):
			return True
	return False

def beautify_sql(text):
	text = text.lower()
	text = text.replace("/**/", " ")
	return text

def check_sqli(data):
	req = json.loads(data['request']['postData']['text'])
	resp = data['response']
	ts = data['time']
	query = beautify_sql(req['query'])
	if(query == 'undefined'):
		return -1
	substr_data = re.findall(r"substr\((.*?)\)", query)
	bool_val = re.findall(r"then hex\((.*?)\)", query)
	bool_val.append(re.findall(r"else hex\((.*?)\)", query)[0])
	result_val = re.findall(r"\) like \s*(.*)", query)
	operator_val = re.findall(r"\'%cj%\'\)(.*?)\(", query)
	
	# print(substr_data,ts,bool_val)
	# print(bool_val)
	# print(result_val)
	# print(operator_val)
	
	if(ts > 3000):
		true_index = bool_val.index('randomblob(1500000000/2')
	else:
		true_index = bool_val.index('randomblob(1000000000/2')

	if(true_index == 1):
		return -1
	else:
		if(len(substr_data) == 2):
			tmp1 = substr_data[0].split(",")[1]
			tmp2 = substr_data[1].split(",")[1]
			tmp_res = result_val[0].split(" ")[0]
			if("-" not in tmp1):
				tmp1 += " + 1"
			if("-" not in tmp2):
				tmp2 += " + 1"
			if("'" in tmp_res):
				fmt = f"s.add((a1[{tmp1}] {operator_val[0]} a1[{tmp2}]) == {bytes.fromhex(tmp_res[1:-1]).decode()} )"
			else:
				fmt = f"s.add((a1[{tmp1}] {operator_val[0]} a1[{tmp2}]) == {tmp_res} )"
			return fmt
		elif(len(substr_data) == 3):
			tmp1 = substr_data[0].split(",")[1]
			tmp2 = substr_data[1].split(",")[1]
			tmp3 = substr_data[2].split(",")[1]
			if("-" not in tmp1):
				tmp1 += " + 1"
			if("-" not in tmp2):
				tmp2 += " + 1"
			if("-" not in tmp3):
				tmp3 += " + 1"


			tmp_res = result_val[0].split(" ")[0]
			# print(operator_val)
			if("'" in tmp_res):
				if('%' in operator_val and '*' in operator_val):
					fmt = f"s.add((a1[{tmp1}] {operator_val[0]} a1[{tmp2}]) {operator_val[1]} a1[{tmp3}] == {bytes.fromhex(tmp_res[1:-1]).decode()} )"
				elif('%' in operator_val):
					ind = operator_val.index('%')
					# print("ind", ind, '%')
					if(ind == 0):
						fmt = f"s.add((a1[{tmp1}] {operator_val[0]} a1[{tmp2}]) {operator_val[1]} a1[{tmp3}] == {bytes.fromhex(tmp_res[1:-1]).decode()} )"
					else:
						fmt = f"s.add(a1[{tmp1}] {operator_val[0]} (a1[{tmp2}] {operator_val[1]} a1[{tmp3}]) == {bytes.fromhex(tmp_res[1:-1]).decode()} )"
				elif('*' in operator_val):
					ind = operator_val.index('*')
					# print("ind", ind, '*')
					if(ind == 0):
						fmt = f"s.add((a1[{tmp1}] {operator_val[0]} a1[{tmp2}]) {operator_val[1]} a1[{tmp3}] == {bytes.fromhex(tmp_res[1:-1]).decode()} )"
					else:
						fmt = f"s.add(a1[{tmp1}] {operator_val[0]} (a1[{tmp2}] {operator_val[1]} a1[{tmp3}]) == {bytes.fromhex(tmp_res[1:-1]).decode()} )"
				else:
					fmt = f"s.add((a1[{tmp1}] {operator_val[0]} a1[{tmp2}]) {operator_val[1]} a1[{tmp3}] == {bytes.fromhex(tmp_res[1:-1]).decode()} )"
			else:
				if('%' in operator_val and '*' in operator_val):
					fmt = f"s.add((a1[{tmp1}] {operator_val[0]} a1[{tmp2}]) {operator_val[1]} a1[{tmp3}] == {tmp_res} )"
				elif('%' in operator_val):
					ind = operator_val.index('%')
					# print("ind", ind, '%')
					if(ind == 0):
						fmt = f"s.add((a1[{tmp1}] {operator_val[0]} a1[{tmp2}]) {operator_val[1]} a1[{tmp3}] == {tmp_res} )"
					else:
						fmt = f"s.add(a1[{tmp1}] {operator_val[0]} (a1[{tmp2}] {operator_val[1]} a1[{tmp3}]) == {tmp_res} )"
				elif('*' in operator_val):
					ind = operator_val.index('*')
					# print("ind", ind, '*')
					if(ind == 0):
						fmt = f"s.add((a1[{tmp1}] {operator_val[0]} a1[{tmp2}]) {operator_val[1]} a1[{tmp3}] == {tmp_res} )"
					else:
						fmt = f"s.add(a1[{tmp1}] {operator_val[0]} (a1[{tmp2}] {operator_val[1]} a1[{tmp3}]) == {tmp_res} )"
				else:
					fmt = f"s.add((a1[{tmp1}] {operator_val[0]} a1[{tmp2}]) {operator_val[1]} a1[{tmp3}] == {tmp_res} )"
			return fmt





f = open("sequel","r").read()
data = json.loads(f)

constraint = []

flag = [0 for _ in range(100)]

blacklist = ['js', 'css', 'ico']
for i in data['log']['entries'][12:]:
	if(check(i['request']['url'])):
		continue
	else:
		tmp_check = check_sqli(i)
		if(tmp_check != -1):
			constraint.append(tmp_check)
		else:
			continue

for i in constraint:
	print(i)

After that just put the constraint into z3. When the first time running the solver , it produce unsat/failed then we found that there is invalid constraint that make our solver fail (because the value is impossible since the sum of two printable charset should not be greater than 1 byte). So after commenting that constraint we got the valid flag. Here is the final solver we use

from z3 import *

a1 = [Int("x{}".format(i)) for i in range(50)]

s = Solver()
for i in range(len(a1)):
	s.add(a1[i] > 0)
	s.add(a1[i] < 128)

s.add((a1[-23] % a1[-18]) == 52 )
s.add((a1[-42] * a1[-36]) == 6888 )
s.add((a1[0x1 + 1] * a1[-35]) == 6700 )
s.add((a1[-2] % a1[-39]) - a1[-48] == -22 )
s.add((a1[-23] * a1[0x12 + 1]) - a1[0x9 + 1] == 5201 )
s.add((a1[-36] + a1[-30]) == 106 )
s.add((a1[0x2c + 1] % a1[0xb + 1]) + a1[-47] == 121 )
s.add(a1[-46] - (a1[0x23 + 1] * a1[-4]) == -4994 )
s.add((a1[0x11 + 1] * a1[0x24 + 1]) * a1[-28] == 297000 )
s.add((a1[-18] * a1[-26]) * a1[-26] == 922082 )
s.add((a1[-29] % a1[0x2c + 1]) + a1[0xd + 1] == 57 )
s.add((a1[-46] * a1[0x26 + 1]) % a1[0xb + 1] == 46 )
s.add((a1[-33] % a1[-32]) == 49 )
s.add((a1[0x17 + 1] - a1[-1]) == -28 )
s.add((a1[-2] * a1[-48]) == 6499 )
s.add((a1[0x21 + 1] - a1[0x19 + 1]) == 1 )
s.add((a1[-43] * a1[-6]) == 5151 )
s.add((a1[-8] * a1[-3]) == 5252 )
s.add((a1[0x21 + 1] % a1[0x7 + 1]) * a1[-24] == 2450 )
s.add((a1[-17] - a1[-14]) == -2 )
s.add((a1[-48] + a1[0x16 + 1]) == 122 )
s.add((a1[0x10 + 1] * a1[-12]) % a1[-14] == 18 )
s.add((a1[0x3 + 1] * a1[0x1e + 1]) - a1[-2] == 2453 )
s.add(a1[0x2b + 1] - (a1[-22] % a1[-33]) == 100 )
s.add((a1[0x4 + 1] * a1[-2]) == 4656 )
s.add((a1[0x1b + 1] * a1[0x2c + 1]) % a1[0x7 + 1] == 36 )
s.add((a1[0x30 + 1] % a1[0x29 + 1]) == 21 )
s.add((a1[-15] * a1[-5]) - a1[-14] == 5200 )
s.add((a1[0x12 + 1] - a1[0x1a + 1]) == 49 )
s.add((a1[0x11 + 1] - a1[0x20 + 1]) == 4 )
s.add((a1[-10] - a1[0x10 + 1]) + a1[0x26 + 1] == 58 )
# s.add((a1[0x7 + 1] + a1[-44]) == 943 )
s.add((a1[0x2a + 1] * a1[-41]) + a1[0x20 + 1] == 5579 )
s.add((a1[0x5 + 1] * a1[-41]) % a1[-29] == 56 )
s.add((a1[0x15 + 1] % a1[-15]) * a1[-29] == 4896 )
s.add((a1[-15] + a1[-9]) + a1[0x1f + 1] == 252 )
s.add((a1[0x11 + 1] - a1[-17]) == 4 )
s.add(a1[-5] - (a1[0x25 + 1] * a1[0x24 + 1]) == -5289 )
s.add((a1[-5] - a1[0x13 + 1]) == 51 )
s.add((a1[0x8 + 1] % a1[0x2b + 1]) * a1[-22] == 9603 )
s.add(a1[0x9 + 1] + (a1[-40] * a1[0x2 + 1]) == 3825 )
s.add((a1[-46] % a1[0x22 + 1]) == 50 )
s.add(a1[-4] - (a1[-29] * a1[-44]) == -5003 )
s.add((a1[0xf + 1] * a1[0x1b + 1]) % a1[-29] == 39 )
s.add((a1[0x12 + 1] * a1[0x20 + 1]) * a1[0x15 + 1] == 505000 )
s.add((a1[-7] + a1[-14]) + a1[0xe + 1] == 209 )
s.add(a1[0x13 + 1] + (a1[-2] * a1[0x1a + 1]) == 5094 )
s.add((a1[-32] % a1[0xd + 1]) + a1[0xc + 1] == 155 )
s.add((a1[-19] % a1[-33]) == 2 )
s.add((a1[-19] % a1[0x25 + 1]) * a1[-33] == 2499 )
s.add((a1[0x3 + 1] - a1[-16]) + a1[-26] == 97 )
s.add((a1[0x17 + 1] - a1[-15]) == 45 )
s.add((a1[0x10 + 1] * a1[0x1a + 1]) == 2548 )
s.add((a1[-29] % a1[0x1d + 1]) - a1[-41] == -91 )
s.add((a1[-1] % a1[0x2b + 1]) * a1[-16] == 1200 )
s.add(a1[0x25 + 1] + (a1[0x2f + 1] * a1[-20]) == 4754 )
s.add((a1[-21] * a1[-47]) == 4144 )
s.add(a1[0x24 + 1] + (a1[0xe + 1] * a1[0xf + 1]) == 5555 )
s.add((a1[-23] + a1[-18]) == 150 )
s.add((a1[-11] + a1[0x27 + 1]) == 107 )
s.add((a1[0x1d + 1] * a1[0x1 + 1]) == 3216 )
s.add(a1[-12] - (a1[0x15 + 1] % a1[-23]) == 50 )
s.add(a1[-29] + (a1[-10] % a1[0x2e + 1]) == 153 )
s.add((a1[0x11 + 1] % a1[-8]) == 2 )
s.add(a1[-26] + (a1[-3] % a1[-27]) == 143 )
s.add((a1[-37] - a1[-25]) - a1[0x2 + 1] == -26 )
s.add(a1[0x5 + 1] - (a1[-21] % a1[0x25 + 1]) == -6 )
s.add((a1[-40] * a1[0x16 + 1]) == 2805 )
s.add((a1[0x5 + 1] - a1[0x2a + 1]) - a1[-5] == -108 )
s.add((a1[-28] + a1[-6]) == 201 )
s.add((a1[-48] - a1[-43]) + a1[-10] == 67 )
s.add((a1[0x20 + 1] * a1[-36]) == 2800 )
s.add((a1[0x3 + 1] - a1[-47]) + a1[-1] == 101 )

print(s.check())

model = s.model()

flag = b""

for i in a1:
    flag += bytes([model[i].as_long()])
print(flag)

Flag : CJ2023{a346e8d716e2fd7a514c803b22447b83f49eeaea}

📚
📖
Here