cts's Avatar

cts

@gf256.bsky.social

Hacker and meme enjoyer

2,198 Followers  |  29 Following  |  69 Posts  |  Joined: 24.04.2023  |  2.3125

Latest posts by gf256.bsky.social on Bluesky

Ooh thanks let me fix this

24.04.2025 02:09 โ€” ๐Ÿ‘ 2    ๐Ÿ” 0    ๐Ÿ’ฌ 0    ๐Ÿ“Œ 0
Post image 13.04.2025 13:28 โ€” ๐Ÿ‘ 62    ๐Ÿ” 4    ๐Ÿ’ฌ 1    ๐Ÿ“Œ 0

Add progressive web app support and I'll switch back

08.04.2025 18:46 โ€” ๐Ÿ‘ 6    ๐Ÿ” 0    ๐Ÿ’ฌ 1    ๐Ÿ“Œ 0

Living with autism really be like

- 5 reps eye contact
- 10 reps considering othersโ€™ viewpoints and feelings
- 3x60 seconds tolerating uncomfortable sensations
- Remembering names and faces until failure

08.04.2025 18:41 โ€” ๐Ÿ‘ 63    ๐Ÿ” 7    ๐Ÿ’ฌ 5    ๐Ÿ“Œ 0
Post image

Lastly:

We're sponsoring PlaidCTF this year at Zellic. This is a lifelong dream of mine. Thank you so much to the organizers for putting on such an excellent CTF each year!

PlaidCTF will be running starting this Friday. Sign up here: plaidctf.com

Cheers!

02.04.2025 20:50 โ€” ๐Ÿ‘ 5    ๐Ÿ” 0    ๐Ÿ’ฌ 0    ๐Ÿ“Œ 0
Thatโ€™s a Lot of Fish: PlaidCTF 2020 Writeup for the Thatโ€™s a Lot of Fish challenge from PlaidCTF 2020

I really enjoyed this challenge. This thread was excerpted from the full writeup, which you can find here: blog.perfect.blue/Lot-of-Fish-...

02.04.2025 20:50 โ€” ๐Ÿ‘ 1    ๐Ÿ” 0    ๐Ÿ’ฌ 1    ๐Ÿ“Œ 0
Post image

This is a NP complete problem, but luckily we can attack this with dynamic programming. My teammate Sampriti wrote a solver and it gave the solution
[0,9,15,2,1,4,3,8,10,5,13,11,14,6,7,12,0]

And if we feed this into the challenge, we actually get our flag!

02.04.2025 20:50 โ€” ๐Ÿ‘ 0    ๐Ÿ” 0    ๐Ÿ’ฌ 1    ๐Ÿ“Œ 0

This is asking us to find a permutation of (xs, ys) that results in the Manhattan distances between consecutive points sums to 0x470.

This is essentially finding a Hamiltonian cycle of specified length!

02.04.2025 20:50 โ€” ๐Ÿ‘ 0    ๐Ÿ” 0    ๐Ÿ’ฌ 1    ๐Ÿ“Œ 0
Post image

If you translate this to pseudocode, it basically implements this check:

02.04.2025 20:50 โ€” ๐Ÿ‘ 0    ๐Ÿ” 0    ๐Ÿ’ฌ 1    ๐Ÿ“Œ 0
Post image

Now, if you disassemble the bytecode, you'll realize there's control flow... even subroutines and functions!

Here's a screenshot from the Binary Ninja plugin
@hgarrereyn.bsky.social independently wrote as part of his solve.

02.04.2025 20:50 โ€” ๐Ÿ‘ 1    ๐Ÿ” 0    ๐Ÿ’ฌ 1    ๐Ÿ“Œ 0

And the big array of binary digits we saw in the very first screenshot is actually the VMโ€™s bytecode.

02.04.2025 20:50 โ€” ๐Ÿ‘ 0    ๐Ÿ” 0    ๐Ÿ’ฌ 1    ๐Ÿ“Œ 0

It initializes a VM state using our input, then applies StepVM until the VM halts and returns a scalar. This scalar is the VMโ€™s exit code (halt state). This final state is asserted to be zero. So our flag needs to satisfy this whole circuit.

02.04.2025 20:50 โ€” ๐Ÿ‘ 0    ๐Ÿ” 0    ๐Ÿ’ฌ 1    ๐Ÿ“Œ 0

Essentially, this entire VM is used as a type constraint on our input!

Meaning, the type system, not any interpreted code, checks our input! The computation is done in this circuit, that is executed through type checking.

02.04.2025 20:50 โ€” ๐Ÿ‘ 0    ๐Ÿ” 0    ๐Ÿ’ฌ 1    ๐Ÿ“Œ 0
Post image

And here's how they actually launch the VM and check the flag with it. They pass the flag as input to the VM (the VM code is parameterized by the input; the VM is parameterized by the code)

02.04.2025 20:50 โ€” ๐Ÿ‘ 0    ๐Ÿ” 0    ๐Ÿ’ฌ 1    ๐Ÿ“Œ 0
Post image

And here's the instruction set.

02.04.2025 20:50 โ€” ๐Ÿ‘ 0    ๐Ÿ” 0    ๐Ÿ’ฌ 1    ๐Ÿ“Œ 0
Post image

Here's the full processor state. It also implements binary heaps built in which is very very quirky.

Again, keep in mind every name here used to be the name of a fish๐Ÿซ  This is all manually renamed

02.04.2025 20:50 โ€” ๐Ÿ‘ 0    ๐Ÿ” 0    ๐Ÿ’ฌ 1    ๐Ÿ“Œ 0
Post image

Guess what! It's a virtual machine.

02.04.2025 20:50 โ€” ๐Ÿ‘ 1    ๐Ÿ” 0    ๐Ÿ’ฌ 1    ๐Ÿ“Œ 0
Post image

Yup... this is implementing computing the operand value for an instruction. Oh boy... this is probably going to be an entire RISC CPU.

RISC processors often fetch operand values during the instruction decode stage, and that's what's going on here.

02.04.2025 20:50 โ€” ๐Ÿ‘ 0    ๐Ÿ” 0    ๐Ÿ’ฌ 1    ๐Ÿ“Œ 0
Post image

I was feeling pretty good at this point. I was understanding what everything was doing.

But then my heart sank when I saw this.

Can you guess what this does?

02.04.2025 20:50 โ€” ๐Ÿ‘ 0    ๐Ÿ” 0    ๐Ÿ’ฌ 1    ๐Ÿ“Œ 0

Keep in mind, all of these identifiers and strings were just names of fish.

So I was sitting there discovering how "Tuna" is actually a ripple-carry adder.

02.04.2025 20:50 โ€” ๐Ÿ‘ 2    ๐Ÿ” 0    ๐Ÿ’ฌ 1    ๐Ÿ“Œ 0
Post image

Here is how they index into a list. They do this by recursively skipping every other element based on the bits of the index (!!!)

02.04.2025 20:50 โ€” ๐Ÿ‘ 0    ๐Ÿ” 0    ๐Ÿ’ฌ 1    ๐Ÿ“Œ 0
Post image

We can even build a multiplier!

02.04.2025 20:50 โ€” ๐Ÿ‘ 0    ๐Ÿ” 0    ๐Ÿ’ฌ 1    ๐Ÿ“Œ 0
Post image

What about bitwise arithmetic?

02.04.2025 20:50 โ€” ๐Ÿ‘ 0    ๐Ÿ” 0    ๐Ÿ’ฌ 1    ๐Ÿ“Œ 0
Post image

Now you may be wondering... that's great but how can we do arithmetic? How do we add two BinNums?

Well...using a full adder of course :-)

02.04.2025 20:50 โ€” ๐Ÿ‘ 0    ๐Ÿ” 0    ๐Ÿ’ฌ 1    ๐Ÿ“Œ 0

So this is basically building up bit-level computation. The types set up a circuit, and valid evaluations of the circuit type check.

The flag checker is implemented in this circuit, and we need to (1) reverse how logic is implemented in circuit form; then (2) reverse the logic.

02.04.2025 20:50 โ€” ๐Ÿ‘ 0    ๐Ÿ” 0    ๐Ÿ’ฌ 1    ๐Ÿ“Œ 0
Post image

Remember everything is actually a type: our functions are conditional types. Our parameters are actually type parameters. Our numbers are actually just types representing arrays of binary digits.

To make this concrete, let me give an example.

Correct computations typecheck!

02.04.2025 20:50 โ€” ๐Ÿ‘ 1    ๐Ÿ” 0    ๐Ÿ’ฌ 1    ๐Ÿ“Œ 0

Our BinNums are essentially representations of integers in binary form, with LSB at the front of the array and MSB at the end.

So this โ€œfunctionโ€ takes in two BinNums, and returns if they are equal by iterating through the bits in order and checking if they are all equal.

02.04.2025 20:50 โ€” ๐Ÿ‘ 0    ๐Ÿ” 0    ๐Ÿ’ฌ 1    ๐Ÿ“Œ 0

Thereโ€™s a lot going on here.

It creates a dict and then indexes into it. Itโ€™s kind of like a switch statement. The dict part is responsible for either recursing or returning the base case. The index does combinatorial logic for what to do based on the current recursion level.

02.04.2025 20:50 โ€” ๐Ÿ‘ 0    ๐Ÿ” 0    ๐Ÿ’ฌ 1    ๐Ÿ“Œ 0
Post image

If you thought that was crazy, wait till you see this.

Then they use Car and Cdr with tail recursion to accomplish iteration. This is how they check if two binary numbers are equal:

02.04.2025 20:50 โ€” ๐Ÿ‘ 1    ๐Ÿ” 0    ๐Ÿ’ฌ 1    ๐Ÿ“Œ 0

What they're doing is extremely clever. It's pattern matching on the args of a dummy functional type. That's how they represent a tuple. Then, Car (Cdr) peels off the first (second) arg of a "โ€ฆ" expansion. The ... is like Python *args.

That's how they destructure a tuple.

02.04.2025 20:50 โ€” ๐Ÿ‘ 0    ๐Ÿ” 0    ๐Ÿ’ฌ 1    ๐Ÿ“Œ 0

@gf256 is following 20 prominent accounts