| Level 5 |
This level is also similar with previous one but with more math logic. Still the same though. We find the pointer of 8 enc hex sequel. And brute force it by xoring with 0x1 to 0xFF and collect meaningful flags. and we will get "Victory!". I also see vICTORY/0x1 too. 0x1 is shown in my windows cmd line as smile emoji. But unpredictable and unprintable in my phone. Not sure if we can take it as valid flags or not.
So, I will leave 2 solution here. If we want to use Victory! flags, the xor key is 0xBD. 0xBD is also the end hex of second key. So second key must be any 0xFFFFBD. With the math logic to filter from cmp in assembler, here is lua code to get valid candidates for flags Victory!.
local target = 0xBD
for key1 = 0, 0xFFFF, 17 do
local key2 = (key1 ~ 0x1337) + 42
if key2 & 0xFF == target then
print(string.format(
"Key1: %d (0x%X) | Key2: %d (0x%X)",
key1, key1, key2, key2))
end
end
If we want to use flags vCTORY/0x1, the xor key would be 0x9D. Any 0xFFFFFF9D for key 2 with math logic from cmp will give us validated license and flag. So just use the above lua script but replace 0xBD with 0x9D. |
2026-07-12 18:37 |
| Level 4 |
This level is also very similar to the last one, level 3. But now with more strict gateway to make it show meaningful flags.
For the username and password part, it is easy since any password would make the job done according to its username. It use simple logic like sum of bytes of username * 0x7b is password. For example, for username Hungary, password is 90282 and it will show Success.
Now, we need to find flag. In assembler, I saw a pointer is being used in the loop. If we breakpoint there, we can follow it and see 7 hex in memory. There was also a variable that comes from Xoring between the last 2 hex of serial and 0x34. We can see this one as our xor key. The xor key is used to xor with all the values of pointer one by one in the loop. The result is then shown on output as decrypted flags.
So, what we need now is to start from meaningful flags. We will copy the hex values from pointer. Then we will try to brute force it by xoring with the xor key starting from 0x01 to 0xFF. And filter to get only meaningful printable texts. We will then see one among them showing "Solved!" with xored key being 0x67. Probably valid flags.
But we have a condition here. We can't use any username and serial to get flags Solved!. So, we need to find only valid username that can show correct flags. The xored key is 0x67. If we revert it as my third paragraph, we should xor 0x67 and 0x34 which will give us 0x53 (The last 2 hex digit of serial). So, The serial must be something like 0xFFFFFF53 but it must be also divisible by 0x7b (123 in decimal). By writing a function, it will give us multiple candidates such as 0xFA53, 0x17553.
The smallest one would be 0xFA53 (64083 in dec). 521 in decimal if it is devided by 123. any printable username that has total bytes of 521 will make the job done with serial being 64083. For example, username: zlaaa, serial: 64083 will give us Success with Solved! flags.
I like this series very much and it is my first time solving level 4 too. |
2026-07-12 16:44 |
| Level 3 |
Very Educational program. Not so hard. Not so easy. This is my very first level 3 solving problem.
The password is generated according to the input user name. So, every username will work once we find out which solution the program use to generate password and compare to what.
We have to really try to understand what is being compared to get Granted response. In the program asm, we see that it get total decimal bytes of the input username and multiply it with 1337 and xor with 0x5a5a. and the result is compared to input password. So, by writing the solution to generate password according to whatever username input, we will pass for every username. Below is my lua version to generate valid password.
local User = "liuasfuhflkwe"
local function getValidPassword(username)
local username_total_bytes = 0
for i=1, #username do
local decimal = string.byte(username, i)
username_total_bytes = username_total_bytes + decimal
end
return (username_total_bytes*1337) ~ 0x5a5a
end
local validPassword = getValidPassword(User)
print(validPassword) |
2026-07-11 20:02 |