---
# System prepended metadata

title: ACECTF 2025

---

# Web
## Buried Deep

In this challenge, we need to check `/robots.txt`, which provides us with various paths containing useful information. The `flag` retrieval process consists of three steps.

```
# Hey there, you're not a robot, yet I see you sniffing through this file 😡
# Now get off my lawn! 🚫

Disallow: /secret/
Disallow: /hidden/
Disallow: /cryptic/
Disallow: /forbidden/
Disallow: /pvt/
Disallow: /buried/
Disallow: /underground/
Disallow: /secret_path/
Disallow: /hidden_flag/
Disallow: /buried_flag/
Disallow: /encrypted/
```
* **part 1**

at `/buried`
```
49 115 116 32 80 97 114 116 32 111 102 32 116 104 101 32 70 108 97 103 32 105 115 32 58 32 65 67 69 67 84 70 123 49 110 102 49 108 55 114 52 55 49 110 103 95 55 104 51 95 53 121 53 55 51 109 95 32
```
 convert from `decimal` => `ascii` 
```
1st Part of the Flag is : ACECTF{1nf1l7r471ng_7h3_5y573m_ 
```

* **part 2**

at `/secret_path`
```
..--- -. -..
.--. .- .-. -
--- ..-.
- .... .
..-. .-.. .- --.
.. ...
---...
.---- ..... ..--.- ...-- ....- ..... -.-- ..--.- .-- .... ...-- -. ..--.- -.-- ----- ..- ..--.- -.- -. ----- .-- ..--.- .-- .... ...-- .-. ...-- ..--.-
```

convert from `morse code` => `ascii`
```
2ND PART OF THE FLAG IS : 15_345Y_WH3N_Y0U_KN0W_WH3R3_
```

* **part 3**

at `static/css/style.css`
```
body {
    background-color: #121212; 
    font-family: 'Arial', sans-serif;
    margin: 0;
    padding: 0;
    color: #e0e0e0; 
    display: flex;
    justify-content: center;
    align-items: center;
    height: 100vh;
    flex-direction: column;
}

h1 {
    font-size: 3em;
    color: #bb86fc; 
    margin: 20px 0;
    text-align: center;
    text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.5);
}

p {
    font-size: 1.2em;
    line-height: 1.6;
    color: #a1a1a1; 
    max-width: 600px;
    text-align: center;
    margin: 10px 0;
}

a {
    color: #03dac6; 
    text-decoration: none;
    font-weight: bold;
}

a:hover {
    color: #00b8a9; 
    text-decoration: underline;
}

button {
    padding: 10px 20px;
    background-color: #03dac6; 
    color: #121212; 
    border: none;
    border-radius: 5px;
    cursor: pointer;
    font-size: 1em;
    transition: background-color 0.3s;
}

button:hover {
    background-color: #00b8a9; 
    color: #ffffff; 
}

.container {
    text-align: center;
    padding: 20px;
    background-color: #1e1e1e; 
    border-radius: 8px;
    box-shadow: 0px 4px 8px rgba(0, 0, 0, 0.5);
    margin: 30px;
    width: 90%;
    max-width: 800px;
}

footer {
    margin-top: 30px;
    font-size: 0.9em;
    color: #757575; 
    text-align: center;
}

#flag {
    display: none;
    content: "bC5 !2CE @7 E96 u=28 :D i f9b0db4CbEd0cCb03FC`b5N"; 
}

footer p {
    color: #888;
    font-size: 0.9em;
}

@media screen and (max-width: 768px) {
    body {
        padding: 20px;
    }
    
    h1 {
        font-size: 2em;
    }

    p {
        font-size: 1em;
    }

    .container {
        padding: 10px;
        max-width: 100%;
    }
}
```

convert `content` in `flag` id by `ROT47`
```
3rd Part of the Flag is : 7h3_53cr3t5_4r3_bur13d}
```

`Flag: ACECTF{1nf1l7r471ng_7h3_5y573m_15_345y_wh3n_y0u_kn0w_wh3r3_7h3_53cr3t5_4r3_bur13d}`

## Webrypto 

There's a way to achieve this using PHP's type juggling with arrays. In PHP, when you pass an array as a parameter, and that array is used in a string context (like in the MD5 function), PHP will convert it to the string `Array`

`payload`
```
https://chal.acectf.tech/Webrypto/?tom[]=1&jerry[]=2
```

What happens:

`$_GET['tom']` becomes an `array [1]` and `$_GET['jerry']` becomes an `array [2]`
They are not equal as `arrays`, so the first condition passes
When used in `md5('ACECTF' . $_GET['tom'])`, PHP converts `$_GET['tom']` to the string `Array`
Same for jerry, so both become `md5('ACECTFArray')`
The hashes are identical, so the second condition passes
The flag will be printed

`Flag: ACECTF{70m_4nd_j3rry_4r3_4ll135}`

## Token of Trust

In this challenge, when accessing the website, we see an endpoint `/login`. Our goal is to log in, generate a token, and use it for authentication. After checking `/robots.txt`, I found an endpoint `/flag`. I modified the token from guest to admin to authenticate and retrieve the `flag`

![image](https://hackmd.io/_uploads/BJ3wM8ysyl.png)

![image](https://hackmd.io/_uploads/BkuuzIJjyl.png)

![image](https://hackmd.io/_uploads/SyoKGUyiJg.png)
    
![image](https://hackmd.io/_uploads/Hyd9z81ikl.png)

`Flag: ACECTF{jwt_cr4ck3d_4dm1n_4cce55_0bt41n3d!}`

## Flag-Fetcher

In this challenge, I checked the source code and accessed the endpoint `assets/index--6xk1ldU.js`. Then, by inspecting the response in `Burp Suite`, I found the `flag` at the end

![image](https://hackmd.io/_uploads/H1387UJiyx.png)

`Flag: ACECTF{r3d1r3ct10n}`

## Bucket List

In this challenge, I navigated back to the main domain and searched using keywords like `flag`, `secret`, `hidden`, ... I found `cry-for-me/acectf/secret.txt`, then decoded its contents using `Base64` to retrieve the `flag`

`Flag: ACECTF{7h3_4w5_15_m15c0nf16ur3d}`


# Forensics
## Broken Secrets

* Using the file command, I identified it as a compressed file and extracted it with: `binwalk -e Brokenfr`
* Then, I navigated to the `word/media` directory and found a file named `not_so_suspicious_file` 
* Opening it in `HxD` revealed that it was a `PNG` file missing the first 16 bytes.

![Screenshot 2025-02-28 211623](https://hackmd.io/_uploads/r1eMI8Jj1x.png)

"Then, I took the first `16 bytes` from any PNG file and inserted them at the beginning of `not_so_suspicious_file`. This successfully restored the image containing the `flag`

![Screenshot 2025-02-28 211801](https://hackmd.io/_uploads/r1HOUIki1l.png)

![Screenshot 2025-02-28 211838](https://hackmd.io/_uploads/S1FO8L1skg.png)

![Screenshot 2025-02-28 211849](https://hackmd.io/_uploads/SyFjULJjkg.png)


`Flag: ACECTF{h34d3r_15_k3y}`

## Hidden in the traffic

In this challenge, the key clue was in the `ICMP traffic`. I filtered it using `tshark` and converted it to `ASCII`. The `flag` was obscured by the string `ABCDEFJKL`, so after removing those characters, the `flag` was revealed

`command`
```
tshark -r Very_mysterious_file.pcapng -Y "icmp" -T fields -e data
```

![image](https://hackmd.io/_uploads/r1RJ_Ukskg.png)

![image](https://hackmd.io/_uploads/ryc8OIko1x.png)

`Flag: ACECTF{p1n6_0f_D347h}`

## Virtual Hard Disk

Open the provided file using `FTK Imager` and search for a `Flag` file and a `Key` file. Decrypt them using `Vigenère cipher` with that key to obtain the `flag`

![image](https://hackmd.io/_uploads/rkzijyMjkl.png)

`Flag: ACECTF{7h3_d1ff3r3nc3_b37w33n_y0u_4nd_m3}`

## Keyboard Echo

The challenge involves extracting data entered by users into the host. A script is used to `extract` the data, obtaining a character string, which is then formatted into the `flag`
`script`
```py=
import subprocess,sys,os
import shlex,string
usb_codes = {
    "0x04":['a','A'],"0x05":['b','B'], "0x06":['c','C'], "0x07":['d','D'], "0x08":['e','E'], "0x09":['f','F'],"0x0A":['g','G'],"0x0B":['h','H'], "0x0C":['i','I'], "0x0D":['j','J'], "0x0E":['k','K'], "0x0F":['l','L'],"0x10":['m','M'], "0x11":['n','N'], "0x12":['o','O'], "0x13":['p','P'], "0x14":['q','Q'], "0x15":['r','R'],"0x16":['s','S'], "0x17":['t','T'], "0x18":['u','U'], "0x19":['v','V'], "0x1A":['w','W'], "0x1B":['x','X'],"0x1C":['y','Y'], "0x1D":['z','Z'], "0x1E":['1','!'], "0x1F":['2','@'], "0x20":['3','#'], "0x21":['4','$'],"0x22":['5','%'], "0x23":['6','^'], "0x24":['7','&'], "0x25":['8','*'], "0x26":['9','('], "0x27":['0',')'],"0x28":['\n','\n'], "0x29":['[ESC]','[ESC]'], "0x2A":['[BACKSPACE]','[BACKSPACE]'], "0x2B":['\t','\t'],"0x2C":[' ',' '], "0x2D":['-','_'], "0x2E":['=','+'], "0x2F":['[','{'], "0x30":[']','}'], "0x31":['\',"|'],"0x32":['#','~'], "0x33":";:", "0x34":"'\"", "0x36":",<",  "0x37":".>", "0x38":"/?","0x39":['[CAPSLOCK]','[CAPSLOCK]'], "0x3A":['F1'], "0x3B":['F2'], "0x3C":['F3'], "0x3D":['F4'], "0x3E":['F5'], "0x3F":['F6'], "0x41":['F7'], "0x42":['F8'], "0x43":['F9'], "0x44":['F10'], "0x45":['F11'],"0x46":['F12'], "0x4F":[u'→',u'→'], "0x50":[u'←',u'←'], "0x51":[u'↓',u'↓'], "0x52":[u'↑',u'↑']
   }
data = "usb.capdata"
filepath = sys.argv[1]

def keystroke_decoder(filepath,data):
    out = subprocess.run(shlex.split("tshark -r  %s -Y \"%s\" -T fields -e %s"%(filepath,data,data)),capture_output=True)
    output = out.stdout.split() # Last 8 bytes of URB_INTERPRUT_IN
    message = []
    modifier =0
    count =0
    for i in range(len(output)):
        buffer = str(output[i])[2:-1]
        if (buffer)[:2] == "02" or (buffer)[:2] == "20":
            for j in range(1):
                count +=1 
                m ="0x" + buffer[4:6].upper()
                if m in usb_codes and m == "0x2A": message.pop(len(message)-1)
                elif m in usb_codes: message.append(usb_codes.get(m)[1])
                else: break
        else:
            if buffer[:2] == "01": 
                modifier +=1
                continue   
            for j in range(1):
                count +=1 
                m  = "0x" + buffer[4:6].upper()
                if m in usb_codes and m == "0x2A": message.pop(len(message)-1)
                elif m in usb_codes : message.append(usb_codes.get(m)[0])
                else: break

    if modifier != 0:
        print(f'[-] Found Modifier in {modifier} packets [-]')
    return message

if len(sys.argv) != 2 or os.path.exists(filepath) != 1:
    print("\nUsage : ")
    print("\npython Usb_Keyboard_Parser.py <filepath>")
    print("Created by \t\t\t Sabhya <sabhrajmeh05@gmail.com\n")
    print("Must Install tshark & subprocess first to use it\n")
    print("To install run \"sudo apt install tshark\"")
    print("To install run \"pip install subprocess.run\"")
    exit(1)

function_call = keystroke_decoder(filepath,data)
hid_data =''

for _ in range(len(function_call)): hid_data += function_call[_]

if(hid_data == ''):
    function_call = keystroke_decoder(filepath, "usbhid.data")
    print("\n[+] Using filter \"usbhid.data\" Retrived HID Data is : \n")
    for _ in range(len(function_call)): print(function_call[_],end='')
    print("\n")
else:
    print("\n[+] Using filter \"usb.capdata\" Retrived HID Data is : \n")
    print(hid_data)

#Use : python3 script.py file
```

![image](https://hackmd.io/_uploads/H1AHayzsye.png)

`Flag: ACECTF{y0u_h4v3_f0und_17}`

## Deep Memory Dive

Used `Volatility3` to list memory processes and found a potential file named `last_part_is{...}.exe`.
Then, ran `strings file | grep -i "flag"` on memory to find the remaining `flag` string.
However, this wasn't enough, so I searched further with s`trings file | grep -i "echo"` and found an additional part, which I combined to form the complete `flag`

![Screenshot 2025-02-28 213328](https://hackmd.io/_uploads/SkvtCJGsJg.png)

![Screenshot 2025-02-28 213402](https://hackmd.io/_uploads/r18qAJfi1e.png)

`Flag: ACECTF{3xplor1n6_th3_c0nc3al3d_r1ddl3s}`

## Another Reading between the Lines?

When opening the file with `HxD`, I noticed that most of the bytes were `0D` and `0A`.
After searching on `Google`, I found that there is a difference in line breaks between `Windows` and `Linux`:

* `0D 0A` represents a newline on `Windows`.
* `0A` represents a newline on `Linux`.
Based on this, I treated `0D 0A` as bit `1` and `0A` as bit `0`, then converted them to obtain the `flag`.

![image](https://hackmd.io/_uploads/BJp-jgGokx.png)

link at [here](https://cyberchef.io/#recipe=Find_/_Replace(%7B'option':'Regex','string':'0D%200A'%7D,'1',true,false,true,false)Find_/_Replace(%7B'option':'Regex','string':'0A'%7D,'0',true,false,true,false)Find_/_Replace(%7B'option':'Regex','string':'%20'%7D,'',true,false,true,false)From_Binary('None',8)&input=MEEgMEQgMEEgMEEgMEEgMEEgMEEgMEEgMEQgMEEgMEEgMEQgMEEgMEEgMEEgMEEgMEEgMEQgMEEgMEQgMEEgMEEgMEQgMEEgMEEgMEEgMEEgMEQgMEEgMEEgMEQgMEEgMEEgMEQgMEEgMEEgMEEgMEEgMEEgMEQgMEEgMEQgMEEgMEEgMEQgMEEgMEEgMEQgMEEgMEEgMEQgMEEgMEEgMEEgMEEgMEQgMEEgMEEgMEEgMEEgMEQgMEEgMEQgMEEgMEEgMEEgMEQgMEEgMEQgMEEgMEQgMEEgMEQgMEEgMEEgMEQgMEEgMEQgMEEgMEEgMEQgMEEgMEQgMEEgMEEgMEQgMEEgMEQgMEEgMEQgMEEgMEEgMEEgMEEgMEQgMEEgMEQgMEEgMEEgMEEgMEEgMEEgMEEgMEQgMEEgMEEgMEQgMEEgMEQgMEEgMEQgMEEgMEQgMEEgMEQgMEEgMEEgMEQgMEEgMEQgMEEgMEQgMEEgMEEgMEEgMEQgMEEgMEEgMEEgMEEgMEQgMEEgMEQgMEEgMEEgMEEgMEQgMEEgMEQgMEEgMEEgMEEgMEQgMEEgMEQgMEEgMEEgMEQgMEEgMEEgMEEgMEEgMEQgMEEgMEQgMEEgMEEgMEEgMEQgMEEgMEEgMEEgMEEgMEEgMEQgMEEgMEQgMEEgMEEgMEEgMEEgMEQgMEEgMEEgMEQgMEEgMEQgMEEgMEEgMEQgMEEgMEQgMEEgMEQgMEEgMEEgMEEgMEEgMEQgMEEgMEQgMEEgMEEgMEQgMEEgMEQgMEEgMEEgMEEgMEQgMEEgMEEgMEQgMEEgMEQgMEEgMEQgMEEgMEQgMEEgMEQgMEEgMEEgMEQgMEEgMEQgMEEgMEEgMEEgMEEgMEQgMEEgMEEgMEEgMEQgMEEgMEQgMEEgMEEgMEEgMEQgMEEgMEEgMEQgMEEgMEEgMEEgMEQgMEEgMEQgMEEgMEEgMEQgMEEgMEQgMEEgMEQgMEEgMEEgMEQgMEEgMEQgMEEgMEQgMEEgMEEgMEQgMEEgMEQgMEEgMEQgMEEgMEEgMEEgMEQgMEEgMEQgMEEgMEEgMEEgMEQgMEEgMEQgMEEgMEEgMEEgMEQgMEEgMEQgMEEgMEEgMEEgMEQgMEEgMEQgMEEgMEEgMEQgMEEgMEQgMEEgMEEgMEQgMEEgMEQgMEEgMEQgMEEgMEEgMEEgMEQgMEEgMEEgMEQgMEEgMEQgMEEgMEQgMEEgMEQgMEEgMEQgMEEgMEEgMEEgMEQgMEEgMEQgMEEgMEEgMEQgMEEgMEQgMEEgMEQgMEEgMEEgMEQgMEEgMEQgMEEgMEEgMEQgMEEgMEEgMEEgMEEgMEEgMEEgMEQgMEEgMEQgMEEgMEEgMEEgMEQgMEEgMEQgMEEgMEEgMEQgMEEgMEEgMEQgMEEgMEQgMEEgMEQgMEEgMEQgMEEgMEQgMEEgMEEgMEQgMEEgMEQgMEEgMEEgMEQgMEEgMEQgMEEgMEEgMEEgMEEgMEEgMEQgMEEgMEQgMEEgMEEgMEEgMEEgMEQgMEEgMEEgMEQgMEEgMEQgMEEgMEEgMEQgMEEgMEQgMEEgMEQgMEEgMEEgMEEgMEEgMEQgMEEgMEQgMEEgMEEgMEEgMEQgMEEgMEQgMEEgMEEgMEEgMEQgMEEgMEQgMEEgMEEgMEQgMEEgMEEgMEQgMEEgMEEgMEQgMEEgMEQgMEEgMEQgMEEgMEQgMEEgMEQgMEEgMEEgMEQgMEE)

`Flag: ACECTF{n0_r34d1n6_be7w33n_7h3_l1n35}`

## Fractured Frames

In this challenge, I adjusted the height to reveal the `flag`

![image](https://hackmd.io/_uploads/ByywheGsyg.png)

![image](https://hackmd.io/_uploads/Syjw2eGjJg.png)

`Flag: ACECTF{th1s_sh0uld_b3_en0u6h}`

# OSINT
## Fall of 2022

The challenge mentioned a `TXT` file and a `website`, so I immediately checked the `records` of this `website`

```
nslookup -type=TXT acectf.tech
```

```
Server:  cachingdns1.vnpt.vn
Address:  123.23.23.23

Non-authoritative answer:
acectf.tech     text =

        "ACECTF{y0u_g07_7h3_73x7}"
acectf.tech     text =

        "v=spf1 include:_spf.mx.cloudflare.net ~all"
```
`Flag: ACECTF{y0u_g07_7h3_73x7}`

