---
# System prepended metadata

title: MAPNA CTF 2024
tags: [Hacking, Writeup, CTF, MapnaCTF]

---

# Writeup for MAPNA CTF 2024
Hello, I'm 9x14S and I played this CTF as part of team 0xE0F.

## Flags:
My flags:
- Welcome 
- PLC - `MAPNA{y0U_sHOuLd_4lW4yS__CaR3__PaADd1n9!!}`
- Heaverse - `MAPNA{JUS7_LIST3N_N0T_REV3RSE}`

@Lucky flags:
- Compile Me! - `MAPNA{1426__11__31582_!}`
- Tampered - `MAPNA{Tx,D51otN\eUf7qQ7>ToSYQ\;5P6jTIHH#6TL+uv}`

## Writeups

### PLC
 
 The provided archive contains a `.pcap` file, called `plc.pcap`. 

Opening it in Wireshark we get a few packets, which I just inspected manually and found that the `[ACK]` packets had parts of the flag and their order in the `trailer` section.
![image](https://hackmd.io/_uploads/B1C8dh9K6.png)


The flag can be easily reconstructed by following the order.

Flag: `MAPNA{y0U_sHOuLd_4lW4yS__CaR3__PaADd1n9!!}`

### Heaverse

The provided archive contains a binary, called `heaverse`.

Running it outputs `Runing the code...` and then beeps randomly. 

Static analysis with Ghidra here just shows some cryptic output:
```c=
  --snip--
  uStack_30 = 0xeada8d91;
  uStack_2c = 0x93215a28;
  local_28 = 0xba5a6b23;
  uStack_24 = 0x983b6343;
  uStack_20 = 0x46e74bc3;
  uStack_1c = 0x538163c2;
  i = 0;
  while( true ) {
    buffer[i] = f_xor_key ^ s_xor_key;
    if (i + 1 == 85) break;
    f_xor_key = *(byte *)((long)&first_offset + i + 1);
    s_xor_key = *(byte *)((long)&second_offset + i + 1);
    i = i + 1;
  }
  puts("Runing the code... ");
  pause_and_loop(buffer);
  if (canary == *(long *)(CANARY + 0x28)) {
    return 0;
  }
                    /* WARNING: Subroutine does not return */
  __stack_chk_fail();
}
```
The only interesting part here is that some loop decodes the many variables declared at the top of the program, using an XOR key.

In most cases like these, the best way to reverse engineer the program is to go for dynamic analysis, so I ran the binary inside `pwndbg`.
Because the binary is stripped, you can't disassemble or break at the `main` function, so you have to follow the entrypoint until `libc_call_main` calls main. Thankfully for this challenge, making a breakpoint in `puts` breaks just after decoding the string:
```c=
*R10  0x7fffffffd1b0 ◂— 0x800000
*R11  0x246
*R12  0x1
 R13  0x0
*R14  0x7ffff7ffd000 (_rtld_local) —▸ 0x7ffff7ffe2c0 —▸ 0x555555554000 ◂— 0x10102464c457f
*R15  0x555555557d40 —▸ 0x5555555553e0 ◂— endbr64 
*RBP  0x7fffffffd360 —▸ 0x7fffffffd370 ◂— '.--- ..- ... --... / .-.. .. ... - ...-- -. / -. ----- - / .-. . ...- ...-- .-. ... .'
*RSP  0x7fffffffd360 —▸ 0x7fffffffd370 ◂— '.--- ..- ... --... / .-.. .. ... - ...-- -. / -. ----- - / .-. . ...- ...-- .-. ... .'
*RIP  0x7ffff7c67108 (puts+8) ◂— push r15
────────────────────────────────────────────────────────────────────────────[ DISASM / x86-64 / set emulate on ]─────────────────────────────────────────────────────────────────────────────
 ► 0x7ffff7c67108 <puts+8>     push   r15
   0x7ffff7c6710a <puts+10>    push   r14
   0x7ffff7c6710c <puts+12>    push   r13
   0x7ffff7c6710e <puts+14>    push   r12
   0x7ffff7c67110 <puts+16>    mov    r12, rdi
   0x7ffff7c67113 <puts+19>    push   rbx
   0x7ffff7c67114 <puts+20>    sub    rsp, 0x18
   0x7ffff7c67118 <puts+24>    call   *ABS*+0xa3880@plt                <*ABS*+0xa3880@plt>
 
   0x7ffff7c6711d <puts+29>    mov    r14, qword ptr [rip + 0x15acec]
   0x7ffff7c67124 <puts+36>    mov    rbx, rax
   0x7ffff7c67127 <puts+39>    mov    r13, qword ptr [r14]
──────────────────────────────────────────────────────────────────────────────────────────[ STACK ]──────────────────────────────────────────────────────────────────────────────────────────
00:0000│ rbp rsp 0x7fffffffd360 —▸ 0x7fffffffd370 ◂— '.--- ..- ... --... / .-.. .. ... - ...-- -. / -. ----- - / .-. . ...- ...-- .-. ... .'
01:0008│+008     0x7fffffffd368 —▸ 0x555555555309 ◂— mov rdi, rbp
02:0010│+010     0x7fffffffd370 ◂— '.--- ..- ... --... / .-.. .. ... - ...-- -. / -. ----- - / .-. . ...- ...-- .-. ... .'
03:0018│+018     0x7fffffffd378 ◂— ' ... --... / .-.. .. ... - ...-- -. / -. ----- - / .-. . ...- ...-- .-. ... .'
04:0020│+020     0x7fffffffd380 ◂— '.. / .-.. .. ... - ...-- -. / -. ----- - / .-. . ...- ...-- .-. ... .'
05:0028│+028     0x7fffffffd388 ◂— '. .. ... - ...-- -. / -. ----- - / .-. . ...- ...-- .-. ... .'
06:0030│+030     0x7fffffffd390 ◂— ' - ...-- -. / -. ----- - / .-. . ...- ...-- .-. ... .'
07:0038│+038     0x7fffffffd398 ◂— ' -. / -. ----- - / .-. . ...- ...-- .-. ... .'
────────────────────────────────────────────────────────────────────────────────────────[ BACKTRACE ]────────────────────────────────────────────────────────────────────────────────────────
 ► 0   0x7ffff7c67108 puts+8
   1   0x555555555309
   2   0x7ffff7c15b8a __libc_start_call_main+122
   3   0x7ffff7c15c4b __libc_start_main_impl+139
   4   0x555555555365
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
pwndbg> 
```
And as it can be seen, the stack contains a pointer to the decoded string, which is morse code: `.--- ..- ... --... / .-.. .. ... - ...-- -. / -. ----- - / .-. . ...- ...-- .-. ... .`
I went online to decode it and got the following output: 
![image](https://hackmd.io/_uploads/rkcHS35K6.png)
([website](https://morsecode.world/international/translator.html))

Now just replace the spaces with `_` and put it inside `MAPNA{}` to get the flag.

Flag: `MAPNA{JUS7_LIST3N_N0T_REV3RSE}`

### Tampered

(Solved by @Lucky)

The archive contains a file called `flags.txt` and the task here is to get a flag which doesn't follow a pattern the others do.

From the rules page, we can get a regular expression: `MAPNA{[0-9a-zA-Z_-]+.!?|}`
But running this against the the flags has a catch: the file has Windows line separators, which means that using `grep` or any other tool in other OSes won't work. 

@Lucky solved it using a simple Python script, shown below:
```python=
import re
def main():
    for idx, line in enumerate(lines):
        if matches := re.search(r'MAPNA{[0-9a-zA-Z_-]+.!?|}', line):
            continue
        else:
            print(f"Flag: {lines[idx - 1]}", end='')
            exit(0)

with open("flags.txt") as f:
    lines = f.readlines()
    main()
```
This at first didn't work for me, as I use Linux, but found that running `dos2unix` on the `flags.txt` file makes it work.

Also, looking at the `flags.txt` file in a hex viewer (here, I used `xxd` after `dos2unix`), returns an interesting pattern: 
![image](https://hackmd.io/_uploads/H1hxPhcK6.png)

Flag: `MAPNA{Tx,D51otN\eUf7qQ7>ToSYQ\;5P6jTIHH#6TL+uv}`

### Compile Me!

(Solved by @Lucky)

The challenge page gives you the following code:
```c=
Welcome,to,MAPNA,CTF,Year_2k24;main(){for(++CTF;to=-~getchar();Welcome+=11==to,Year_2k24++)CTF=to>0xe^012>to&&'`'^to^65?!to:!CTF?++MAPNA:CTF;printf("MAPNA{%4d__%d__%d_!}\n",(to+20)^(Welcome+24)+1390,MAPNA+=(!CTF&&Year_2k24)+10,Year_2k24+31337);}
```

You're supposed to compile it as-is, and then run the binary, passing to it the source file name.

Another catch here is that the file has to contain zero newlines or carriage returns for it to work.

Running it that way, gives you the flag: 
![image](https://hackmd.io/_uploads/rJgmd2qK6.png)

Flag: `MAPNA{1427__11__31346_!}`