hike to where?
In this challenge we have to find a location where the photo in attachment was taken. Unfortunately, exiftool doesn’t help us here, so we have to do some research. The name of person is easy to find – he’s one of the speakers on our ctf event! As we know the name – Carey Nachenberg – we can continue our research and google it. I focused on finding a photo on which the man is wearing the same clothes. I found one on the following website: https://www.picuki.com/profile/peaksandprofessors.ucla
(I’ve searched for “carey nachenberg ucla climbing” in google)
After scrolling down a little there was a photo with description:
And skull rock is what we’re looking for!
flag: lactf{skull_rock}
discord l34k
In this challenge we have a link to a discord server, but we can’t really see what’s inside. I assumed that the last part of the link is a server id. I’ve found a site where we can search for information about a server when we provide an id of it:
https://discord-avatar.com/en/server
We can see a button “Join now” after a search. We can click on it and that’s it!.
On the server we have our flag:
lactf{D15C0rD_W1D6375_134K_1NV1735}
string cheese
It’s a simple warmup reversing challenge. When we run our program, it asks us about his favorite flavor of string cheese. After decompilation in ghidra we can simply figure out that answer we need is “blueberry”. We can connect to the service with provided command and type in the answer, then we get the flag.
lactf{d0n7_m4k3_fun_0f_my_t4st3_1n_ch33s3}
Finals simulator
Here’s the decompiled code from program in this challenge:
Value inside mod:
We can see that we have to answer 3 mathematical questions to receive the flag.
- First question is: What is sin(x)/n. It’s obviously a mathematical joke, the answer is simply six.
- Second question is about the prettiest number.
All we have to do is to transform and evaluate expression in if condition. The answer is 13371337.
- Last question is definitely the most challenging. The answer should have something in common with logarithm of cabin, but we need to find the exact answer. I wrote following script in python to decrypt the answer:
import string
mod = 0xfd
dict = {}
for i in string.printable:
x = (ord(i)*0x11)%mod
dict[x] = i
enc = [0x0e, 0xb8, 0x9d, 0xb8,0x26,0x83,0x26,0x41,0x74,0xe9,0x26, 0xa5, 0x83, 0x94, 0x0e, 0x63, 0x37, 0x37, 0x37]
for i in enc:
print(dict[i], end='')
How does it work?
In we are comparing our input (that was changed in for loop) to enc.
Here’s what enc contains:
Thus, we have to obtain this string of bytes. In my script I’m calculating value of expression in for loop in our code for every possible printable character and I have a dictionary with this value as key and corresponding character as value. Then we can just print our last answer and get the flag.
Flag: currently server is not responding
UNIVERSAL
It was my first solved SAT challenge. I wasn’t familiar with z3 module, something wasn’t working for me, so I wrote my own script. I found out that we can always find an expression with 1 unknown variable, so we can calculate it and update the rest of the expressions.
I assumed that flag starts and ends as usual: lactf{…} so the first 6 and the last character is known from start. Here’s my code:
import string
file_name = "java_input"
dict = {}
stripped = []
table_name= "bytes" #what's the name of table in input file
#for lactf
dict[f"{table_name}[0]"] = str(ord('l'))
dict[f"{table_name}[1]"] = str(ord('a'))
dict[f"{table_name}[2]"] = str(ord('c'))
dict[f"{table_name}[3]"] = str(ord('t'))
dict[f"{table_name}[4]"] = str(ord('f'))
dict[f"{table_name}[5]"] = str(ord('{'))
dict[f"{table_name}[37]"] = str(ord('}'))
flag_len = 38
def two_assigned(l:list):
counter = 0
for i in l:
if len(i)>len(table_name) and i[:len(table_name)] ==table_name:
counter+=1
if counter == 1:
return True
return False
def update(to_replace):
for x in range(len(stripped)):
for y in range (len(stripped[x])):
if stripped[x][y] == to_replace:
stripped[x][y]= dict[to_replace]
def evaluate(l: list):
to_replace = ""
index = 0
for i in range(len(l)):
if l[i][:len(table_name)]==table_name:
to_replace = l[i]
l[i] = "{}"
index = i
break
x = "-1"
for bytes in string.printable:
put = ord(bytes)
expr = " ".join(l)
expr = expr.format(put)
if eval(expr) == 1:
x = str(put)
break
#update with x
if x == "-1":
print("No characters found")
exit(1)
l[index] = x
dict[to_replace] = x
update(to_replace)
done_counter = 0
with open(file_name) as file:
lines = [line.rstrip() for line in file]
for l in lines:
stripped.append(l.split(" "))
assumptions = len(dict.keys())
for i in dict.keys():
update(i)
while done_counter + assumptions < flag_len:
for i in range(len(lines)):
if two_assigned(stripped[i]):
evaluate(stripped[i])
done_counter+=1
for i in range(done_counter+assumptions):
print(chr(int(dict["{}[{}]".format(table_name, i)])), end='')
To make program work properly, we have to prepare our input file with expressions in right way:
Every value has to be separated from any other character by space. Here’s the example of first few lines with expressions from our challenge:
(( bytes[36] ^ bytes[2] * 7 ^ ~ bytes[4] + 13 ) & 0xFF ) == 0x67
(( bytes[34] ^ bytes[23] * 7 ^ ~ bytes[36] + 13 ) & 0xFF ) == 0xB6
(( bytes[37] ^ bytes[10] * 7 ^ ~ bytes[21] + 13 ) & 0xFF ) == 0xDF
(( bytes[24] ^ bytes[23] * 7 ^ ~ bytes[19] + 13 ) & 0xFF ) == 0xCD
(( bytes[25] ^ bytes[13] * 7 ^ ~ bytes[23] + 13 ) & 0xFF ) == 0x
…
#java_input file
Flag: lactf{1_d0nt_see_3_b1ll10n_s0lv3s_y3t}
2 thoughts on “hike to where, discord l34k and 3 more writeups”
Witam
No witam Pana Prezesa!