- Running the ELF prompted us to enter a flag.
- If we entered any random string it simply said
Incorrect!
- I opened up the ELF in Ghidra and asked for it to analyze it.
- I analyzed all the stripped Functions. and found the the 3 necessary functions; the rest being useless.
- I analyzed the code and renamed essentials variables for understanding (also renamed function names).
- Here is the cleaned-up code for the 3 functions:
main, flag-checker, flag-checker-2.
void main(int argc,char **argv){
int check_value;
size_t input_len;
long canary_offset;
char flag_buffer [40];
long stack_canary;
stack_canary = *(long *)(canary_offset + 0x28);
printf("Enter the flag: ");
fgets(flag_buffer,35,stdin);
input_len = strcspn(flag_buffer,"\n");
flag_buffer[input_len] = '\0';
flag_checker(flag_buffer);
if (check_value == 0) {
puts("Incorrect!");
}
else {
puts("Correct!");
}
if (stack_canary != *(long *)(canary_offset + 0x28)) {
__stack_chk_fail();
}
return;
}
void flag_checker(char *flag_input){
size_t length-of-flag;
long SF;
int i;
char buffer [40];
long SC;
SC = *(long *)(SF + 0x28);
length-of-flag = strlen(flag_input);
if (length-of-flag == 34) {
flag-checker-2(flag_input,buffer);
for (i = 0; (i < 34 && (buffer[i] == (&DAT_00102020)[i])); i = i + 1) {
}
}
if (SC == *(long *)(SF + 0x28)) {
return;
}
__stack_chk_fail();
}
void flag-checker-2(char *flag_input,char *buffer){
int i;
for (i = 0; i < 34; i = i + 1) {
buffer[i] = (flag_input[i] ^ 90U) + (char)i;
buffer[i] = buffer[i] << 3 | (byte)buffer[i] >> 5;
}
return;
}
- But even after analyzing all these things. i couldn’t get the flag because the
DAT_00102020 is not disassembled. - So i opened the file in
Radare2 and started analyzing it. Here is the analyzing breakdown/summary:
(kali@LEOPARD-PC)-[~/CTF-Events/Nullcon-CTF-2025/REV]$ r2 -A flag-checker
...
[0x00001100]> afl
...
0x00001100 1 37 entry0
0x00001318 6 173 main
0x00001090 1 11 fcn.00001090
0x00001130 4 34 fcn.00001130
0x000011e9 4 145 fcn.000011e9
0x0000127a 11 158 fcn.0000127a
...
[0x00001100]> s main
[0x00001318]> pdf
...
│ 0x0000137a 488d45d0 lea rax, [s1]
│ 0x0000137e 4889c7 mov rdi, rax ; char *arg1
│ 0x00001381 e8f4feffff call fcn.0000127a
│ 0x00001386 85c0 test eax, eax
│ ┌─< 0x00001388 7411 je 0x139b
│ │ 0x0000138a 488d05c40c.. lea rax, str.Correct_ ; 0x2055 ; "Correct!"
...
[0x00001318]> s fcn.0000127a
[0x0000127a]> pdf
...
│ ╎││ 0x000012dd 488d0d3c0d.. lea rcx, [0x00002020]
│ ╎││ 0x000012e4 0fb60408 movzx eax, byte [rax + rcx]
│ ╎││ 0x000012e8 38c2 cmp dl, al
│ ┌────< 0x000012ea 7407 je 0x12f3
│ │╎││ 0x000012ec b800000000 mov eax, 0
│ ┌─────< 0x000012f1 eb0f jmp 0x1302
│ ││╎││ ; CODE XREF from fcn.0000127a @ 0x12ea(x)
...
[0x0000127a]> px 34 @0x12f3
- offset - F3F4 F5F6 F7F8 F9FA FBFC FDFE FF 0 1 2 3456789ABCDEF012
0x000012f3 8345 cc01 837d cc21 7ed1 b801 0000 0048 .E...}.!~......H
0x00001303 8b55 f864 482b 1425 2800 0000 7405 e8aa .U.dH+.%(...t...
0x00001313 fdff ..
[0x0000127a]>
- Now we have the flag but it is in encrypted form. So quicky wrote this script to decode the flag:
def reverse_flag_checker(buffer):
flag_input = bytearray(34)
for i in range(34):
temp = buffer[i]
temp = (temp >> 3) | (temp << 5) & 0xFF
flag_input[i] = (temp - i) ^ 0x5A
return bytes(flag_input)
buffer_hex = "f8a8b8216073908380c39b80ab0959d321d3dbd8fb4999e0793c4c492c29ccd4dc42"
buffer = bytes.fromhex(buffer_hex)
original_flag = reverse_flag_checker(buffer)
print(original_flag.decode())
- Executing this python3 script gave me the flag.
FLAG: ENO{R3V3R53_3NG1N33R1NG_M45T3R!!!}
- The two files that they provided us with were:
import random
def encode_flag(flag, key):
xor_result = [ord(c) ^ key for c in flag]
chunk_size = 4
chunks = [xor_result[i:i+chunk_size] for i in range(0, len(xor_result), chunk_size)]
seed = random.randint(0, 10)
random.seed(seed)
random.shuffle(chunks)
scrambled_result = [item for chunk in chunks for item in chunk]
return scrambled_result, chunks
def main():
flag = "REDACTED"
key = REDACTED
scrambled_result, _ = encode_flag(flag, key)
print("result:", "".join([format(i, '02x') for i in scrambled_result]))
if __name__ == "__main__":
main()
result: 1e78197567121966196e757e1f69781e1e1f7e736d6d1f75196e75191b646e196f6465510b0b0b57
- I wrote a script to brute force the key and seed with the given
result. After analyzing all 2560 results found that the key was 42 and seed was 10. Here is the script code:
import random
def reverse_scramble(scrambled_result, seed, chunk_size=4):
random.seed(seed)
num_chunks = len(scrambled_result)
chunks = [scrambled_result[i:i + chunk_size] for i in range(0, len(scrambled_result), chunk_size)]
indices = list(range(num_chunks))
random.shuffle(indices)
unshuffled_chunks = [None] * num_chunks
for i, idx in enumerate(indices): unshuffled_chunks[idx] = chunks[i]
unscrambled_result = [item for chunk in unshuffled_chunks for item in chunk]
return unscrambled_result
def decode_flag(scrambled_result, key, seed):
unscrambled_result = reverse_scramble(scrambled_result, seed)
decoded_result = [chr(byte ^ key) for byte in unscrambled_result]
return ''.join(decoded_result)
scrambled_hex = "1e78197567121966196e757e1f69781e1e1f7e736d6d1f75196e75191b646e196f6465510b0b0b57"
scrambled_result = [int(scrambled_hex[i:i+2], 16) for i in range(0, len(scrambled_hex), 2)]
key = 42
seed = 10
flag = decode_flag(scrambled_result, key, seed)
print("Decoded flag:", flag)
- Executing the Script gave me the flag:
FLAG: ENO{5CR4M83L3D_3GG5_4R3_1ND33D_T45TY!!!}
- I download the
usbnet.pcapng file and directly uploaded it to CyberChef . - and Imported the
Extract Files Module from the list. CyberChef found a PNG file embed inside of a packet.
- Downloaded and Opened up the file. It was a QR Code.
- Scanning the QR Code gave me the Flag.
FLAG: ENO{USB_ETHERNET_ADAPTER_ARE_COOL_N!C3}
- Opening the link showed a simple interface, representing pages of the book.
- It showed all the pages from
2 to 10 except 1.
- The source code was just simple
PHP connecting SQL Database to the frontend. - It check if the
min is less then or equal to 1 or max is greater then 10.
<?php
ini_set("error_reporting", 0);
ini_set("display_errors",0);
if(isset($_GET['source'])) {
highlight_file(__FILE__);
}
include "flag.php";
$db = new SQLite3('/tmp/db.db');
try {
$db->exec("CREATE TABLE pages (id INTEGER PRIMARY KEY, title TEXT UNIQUE, content TEXT)");
$db->exec("INSERT INTO pages (title, content) VALUES ('Flag', '" . base64_encode($FLAG) . "')");
$db->exec("INSERT INTO pages (title, content) VALUES ('Page 1', 'This is not a flag, but just a boring page.')");
$db->exec("INSERT INTO pages (title, content) VALUES ('Page 2', 'This is not a flag, but just a boring page.')");
$db->exec("INSERT INTO pages (title, content) VALUES ('Page 3', 'This is not a flag, but just a boring page.')");
$db->exec("INSERT INTO pages (title, content) VALUES ('Page 4', 'This is not a flag, but just a boring page.')");
$db->exec("INSERT INTO pages (title, content) VALUES ('Page 5', 'This is not a flag, but just a boring page.')");
$db->exec("INSERT INTO pages (title, content) VALUES ('Page 6', 'This is not a flag, but just a boring page.')");
$db->exec("INSERT INTO pages (title, content) VALUES ('Page 7', 'This is not a flag, but just a boring page.')");
$db->exec("INSERT INTO pages (title, content) VALUES ('Page 8', 'This is not a flag, but just a boring page.')");
$db->exec("INSERT INTO pages (title, content) VALUES ('Page 9', 'This is not a flag, but just a boring page.')");
$db->exec("INSERT INTO pages (title, content) VALUES ('Page 10', 'This is not a flag, but just a boring page.')");
} catch(Exception $e) {
//var_dump($e);
}
if(isset($_GET['p']) && str_contains($_GET['p'], ",")) {
[$min, $max] = explode(",",$_GET['p']);
if(intval($min) <= 1 ) {
die("This post is not accessible...");
}
try {
$q = "SELECT * FROM pages WHERE id >= $min AND id <= $max";
$result = $db->query($q);
while ($row = $result->fetchArray(SQLITE3_ASSOC)) {
echo $row['title'] . " (ID=". $row['id'] . ") has content: \"" . $row['content'] . "\"<br>";
}
}catch(Exception $e) {
echo "Try harder!";
}
} else {
echo "Try harder!";
}
?>
<html>
<head>
<title>Paginator</title>
</head>
<body>
<h1>Paginator</h1>
<a href="/?p=2,10">Show me pages 2-10</a>
<p>To view the source code, <a href="/?source">click here.</a>
</body>
</html>
- Simply using modular arithmetic to get
1 as result revealed the base64 encoded flag.
- Decoded the flag with
CyberChef.
FLAG: ENO{SQL1_W1th_0uT_C0mm4_W0rks_SomeHow!}