# Disobey 2023 hacker badge challenge writeup

**URL:** https://discourse.hacklab.fi/t/disobey-2023-hacker-badge-challenge-writeup/1287
**Category:** Uncategorized
**Created:** [November 21, 2022, 3:48pm UTC](https://discourse.hacklab.fi/t/disobey-2023-hacker-badge-challenge-writeup/1287 "2022-11-21T15:48:05Z")
**Posts on this page:** 5
**Page:** 1

<div class="post-metadata">

### Author: ![Depili](https://discourse.hacklab.fi/user_avatar/discourse.hacklab.fi/depili/32/609_2.png) [@Depili](https://discourse.hacklab.fi/u/Depili)
#### Post date: [November 21, 2022, 3:48pm UTC](https://discourse.hacklab.fi/t/disobey-2023-hacker-badge-challenge-writeup/1287/1 "2022-11-21T15:48:05Z")

</div>

This is a barebones writeup of the Disobey 2023 hacker badge challenge and the journey to solve it

# General chain of breadcrumbs

1. Twitter post that kouvosto telecom has made some opsec mistakes
2. Google queries, find Seppo Aapakka as a kt employee
3. Find seppo’s FB posts and the saboten group aka saboten biomedical
4. Find the MRI image
5. Read the barcodes on the image / find the tweet from saboten biomedical
6. Go to [saboten.kouvostotele.com](http://saboten.kouvostotele.com) and find the correct firmware binary
7. Realize that the correct stuff to reverse engineer is the last 64kb of the binary
8. Reverse the x86 real mode stuff, get new url
9. Fetch the invoice pdf from [files.kouvostotele.com](http://files.kouvostotele.com)
10. Notice the [forensics.uxin.fi](http://forensics.uxin.fi) link and go there
11. Notice the news about [secure-files.uxin.fi](http://secure-files.uxin.fi)
12. Figure out a way to access that virtual host
13. Find [secure-files.uxin.fi/backup/users/timi/.git](http://secure-files.uxin.fi/backup/users/timi/.git)
14. Retrieve the whole git repository
15. Find the private gpg key from the repository
16. Crack the password on the key
17. Decrypt the secure uxin password file
18. Use the http basic auth on [secure-files.uxin.fi](http://secure-files.uxin.fi)
19. Use quic and http basic auth on [secure-files.uxin.fi](http://secure-files.uxin.fi)
20. Get the iphone disk image
21. Extract the iphone image with dar
22. Dig around the image, find emails
23. Get the packet capture from email attachments and the password from the email
24. Analyze the packet capture, get the data submission domain name, DNS server, submission url and dns update key name and the key
25. Do dynamic dns update on crunch.kt.3g.re domain and listen on port 80
26. Get the “sensitive data”
27. Base64 decode and hex decode and get the store link for the hacker badge

# MRI picture

## Aztec code

- Did some manipulation on the image, mainly adjusted the gamma curve to get the code to scan.
- Contents of the code are:

```auto
Saboten Biomedical
NX-H128 S/N 000000001
FCC ID: KRJFSICIIFJEIRKS

```

- Nothing really here, the FCC id just seems like random keyboard smashing
  - EDIT: FCC ID is base32 for “TRY HARDER”

## dotcode

- Getting this to work was little challenging, no image manipulation seemed to work.
- In the end I redrew the code by hand on another layer, and that worked
  - Used [DotCode Scanner | Dynamsoft SDK](https://www.dynamsoft.com/barcode-reader/barcode-types/dotcode/) to decode

- We get a URL, lets go `ftp://saboten.kouvostotele.com/prod/sb-ihv/firmware/NX-H128/0-00-3.1/bin/bin.7z`

## Alternative route

After solving the challenge I was made aware that there was a alternative route to the next stage. That involved finding a tweet from the Saboten Biomedical user, which contains a link to the root of the ftp. Unless one has been able to scan at least one of the barcodes from the image this route requires finding the correct firmware image among all of the crap on the site.

# [ftp.saboten.kouvostotele.com](http://ftp.saboten.kouvostotele.com)

- A story .odt file and bunch of compressed firmware images
- Seems like that only the one pointed by the URL contains real data
- The file is a ELF, with bunch of extra data on the end
- Loading it into ghidra it is just freebsd “sleep” command
- There are some strings refering to PCI and A padding in the end
- Looking with binwalk entropy graph there is a entropy edge at almost the start of last 64kb of the file
- There are some interesting strings refering to credentials xored with A on the part
- file doesn’t recognize it
- After a while it seems to be real mode x86 binary, the special 16bit(ish) execution mode of a x86 used for initialization on boot
  - Load it into ghidra and start digging in
  - Parts of the program seem to be
    - Initialize a heap allocator
    - Enumerate pci devices and save their config registers
      - Doesn’t look for PCI bridges and busses behind them, sloppy!

    - Execute a function that fails to decompile initially, due to polymorphic code
      - Use ghidras bytes window to patch the bytes, decompile and recreate the function
      - Does some xors and copys, add the xor region as ghidra overlay
      - xor the key mask and the checked input to get `ftp://kt:bl4de_runn3r@files.kouvostotele.com`

# [files.kouvostotele.com](http://files.kouvostotele.com)

Only one pdf here, a invoice for iphone forensics done by `https://forensics.uxin.fi`

# [forensics.uxin.fi](http://forensics.uxin.fi)

- Browse the web and run ffuf on it
- Nothing hidden found on the main domain
- There is a news entry announcing `secure-files.uxin.fi` but that domain points to localhost

## [secure-files.uxin.fi](http://secure-files.uxin.fi)

- Accessed by passing the “Host: [secure-files.uxin.fi](http://secure-files.uxin.fi)” header to requests to [forensics.uxin.fi](http://forensics.uxin.fi).
- Index is asking for http basic auth
- Start ffufing to see if there is anything to be found: `ffuf -w ~/wordlists/common.txt -H "Host: secure-files.uxin.fi" -u https://forensics.uxin.fi/FUZZ -fc 401`
- Basic ffuf finds `backups/users` dir.
- Construct a wordlist from all the names from the main uxin website
- We find `backups/users/timi/.git`
  - No directory listings enabled
  - Get `.git/config` and then `.git/refs/heads/master`
    - Start walking the objects with the aid of git cat-file
    - Get the whole bare repository in this manner
    - Later I found out that there would have been utilities like [GitHub - WangYihang/GitHacker: 🕷️ A `.git` folder exploiting tool that is able to restore the entire Git repository, including stash, common branches and common tags.](https://github.com/WangYihang/GitHacker)
      - Didn’t test the utilities myself, there weren’t that many objects to fetc

  - Exploring the git timi made some mistakes with his gpg keys
    - first commit has `.backup/public.key` that is actually a private key
      - it has a passphrase
      - Try to crack it with john
        - Success with rockyou wordlist, passphrase is `iloveyou!`

    - there are some encrypted files in `.password_store`
      - `uxin/secure/timi.gpg` contains a high-entropy string
        - Works for the basic auth

## Basic auth

```auto
curl -v -L -u "timi:{/w8P;;}aED,{8s$" -H "Host: secure-files.uxin.fi" https://forensics.uxin.fi/

```

- Has a UDP joke image in the root
- ffuf around and find another image
  - Another UDP meme…

- Portscan the site for open udp ports, find nada
- Do some googling around, like “http udp” to see if there are any udp http clients around
  - http/3 aka QUIC is UDP!

- try with browser, no dice
  - wireshark packet capture reveals we need draft-27 - draft-29 support

- curl has experimental support for QUIC, not enabled by default…
  - try and try and try to compile it from few different instructions, all using various git heads and written 1+ year ago…
    - No dice, but find a docker container: [GitHub - yurymuski/curl-http3: Curl docker image compiled with BoringSSL and quiche for HTTP3 support + httpstat](https://github.com/yurymuski/curl-http3)

- Get the index, a message telling us to analyze a iphone dump and a 3Gb 7z archive
- The docker curl gets only around 1Mb of data per invocation before the connection dies…
  - Just try harder and wrap the curl into a loop with -m 3 to limit execution to 3 seconds and -C - to continue previous transfer
    - `while ! curl -m 3 -C - --http3 -v -L -u "timi:{/w8P;;}aED,{8s$" -H "Host: secure-files.uxin.fi" https://forensics.uxin.fi/KT_Forensics_iPhone_image.7z --output KT_Forensics_iPhone_image.7z; do echo retrying; done`
      - Experiment with the timeout values to get the best performance out of your potato

    - After one afternoon we have data to analyze!

# iphone dump

- Heaps of data
- A mysterious dar extension for the filesystem image
- a nice article was found by google: [Initialization vectors: So you have a DAR file...](https://abrignoni.blogspot.com/2020/03/so-you-have-dar-file.html) by search “iphone dar forensics”
- extract the dar file with dar, doh
- Try APOLLO, get bunch of useless timeline stuff
- Try KAPE, can’t get it to execute at all
- Try iLeap, [GitHub - abrignoni/iLEAPP: iOS Logs, Events, And Plist Parser](https://github.com/abrignoni/iLEAPP), not having high hopes
  - Actually works and gives nice html to explore

- Only Whatsapp and mail have been really used on the phone
  - Whatsapp messages have memes and story stuff
  - Mail has few interesting messages
    - iLeap only shows partial contents and not the attachments, but shows a GUID
    - find that GUID on the extracted data with find
    - `private/var/mobile/Library/Mail/CEAB6F3D-B8DC-47DD-863F-F21B818B0064/INBOX.imapmbox` is where the good stuff lies
    - More story stuff and also `lb.zip` and the password for it in the mail, `hunteR2`

- Additional digging around reveals that the checkra1n jailbreak/rootkit has been installed on the phone, in `private/var/checkra1n.dmg`
  - Probably used for creating the image

## lb.zip

- The packet capture leads to `http://94.237.108.204/submit/` submissions are made with POST requests
- Interesting ips:
  - 94.237.108.204 - submission server and DNS server for kt.3g.re
    - 53/tcp open domain (unknown banner: Kouvosto Telecom DNS server v0.01 beta - in scope)

  - 94.237.109.63 - some host, SSH and 8089 open

- domain crunch.kt.3g.re is used for the data submission, has TTL of 2
- a dynamic update on that domain is done on the packet capture
  - dynamic dns key name: `updatekey.` from packet capture
    - the dot is important for tools, needs to be fully qualified…

  - if we could update it we could get a connection of the sensitive data…

- Some tries with CVE-2017-3143 exploits, didn’t lead to anywhere..
  - Things just didn’t work at all due to me not having the dot expected by the libraries in the key name…
  - Was using the wrong hmac function at the start, needed to have sha512, had sha256
  - But in the end the exploit didn’t seem to work, not sure if I had wrong payload sizes due to different hmac

- Took another look into the packet capture from a nudge of my sparring partner
  - There is a kouvosto keyserver transaction hidden in the TCP control packets
    - Wireshark → right click on packet → view flow → tcp FTW

  - We have the update key

- Modify and hack the exploit PoC, get a working dns update
- do the dns update && sudo nc -l 80
- get the sensitive data from the field

# Sensitive data

```auto
POST / HTTP/1.1
Host: crunch.kt.3g.re
User-Agent: Kouvosto Telecom sensitive data submission agent (military grade)
Transfer-Encoding: chunked
Content-Type: application/ktson
Accept-Encoding: gzip

379
{
  "beacon_name": "chipper",
  "beacon_ip_address": "172.16.104.32",
  "beacon_model": "KVR-L200",
  "beacon_firmware": "0.7.1b.83340",
  "beacon_serial": "80860600021",
  "beacon_location": "Saboten Biomaterial Factory #7",
  "timestamp": 2718658601,
  "meta_data":
    {
      "datatype": "KTBBD",
      "version": "0.7a"
    },
  "events": [
    {
      "rssi": "-42",
      "data": "aHR0cHM6Ly9ob2x2aS5jb20vc2hvcC9EaXNvYmV5L3Byb2R1Y3QvNTgyODkxZDU3YjcwZDEyOWYwN2NkZjJjNzNlMzg4NTMv",
      "srData": "I29pc2pvaGFja2VyYmFkZ2U=",
      "timestamp": 2718658599,
      "device_ktid": "5468616e-6b20-796f-7520-666f72207472-79696e672068-617264657221"
    },
    {
      "rssi": "-36",
      "data": "SXQncyBkYW5nZXJvdXMgdG8gZ28gYWxvbmUhIEhlcmUsIHRha2UgdGhpczo=",
      "timestamp": 2718658594,
      "device_ktid": "5468616e-6b20-796f-7520-666f72207472-79696e672068-617264657221"
    }
  ]
}

```

- Obvious base64 encoded stuff, also a quite obvious hex string
  - Cyberchef to quickly process them
    - It’s dangerous to go alone! Here, take this:
    - [Disobey 2021 Event Hacker Badge — Disobey WebShop](https://holvi.com/shop/Disobey/product/582891d57b70d129f07cdf2c73e38853/)
    - #oisjohackerbadge
    - “Thank you for trying harder!”

- Got there!

# Feedback

- The start requiring selling ones soul to Zuckenberg sucks
- The QUIC part was made hard and annoying just by the lack of good easily available tools
- Finding the real binary and the correct offset in the firmware blob was annoying and required quesswork
- Little bummed out that the TSIG bypass exploit didn’t work, would have been nice different path on that part

---

<div class="post-metadata">

### Author: ![Depili](https://discourse.hacklab.fi/user_avatar/discourse.hacklab.fi/depili/32/609_2.png) [@Depili](https://discourse.hacklab.fi/u/Depili)
#### Post date: [November 21, 2022, 7:40pm UTC](https://discourse.hacklab.fi/t/disobey-2023-hacker-badge-challenge-writeup/1287/2 "2022-11-21T19:40:25Z")

</div>

For the binary reverse engineering the archived ghidra project is here: [https://kissa.depili.fi/disobey\_2023.gar](https://kissa.depili.fi/disobey_2023.gar)

To open start ghidra, close any currently open project and then select file → restore project

---

<div class="post-metadata">

### Author: ![shinmai](https://discourse.hacklab.fi/user_avatar/discourse.hacklab.fi/shinmai/32/968_2.png) [@shinmai](https://discourse.hacklab.fi/u/shinmai)
#### Post date: [November 22, 2022, 7:37am UTC](https://discourse.hacklab.fi/t/disobey-2023-hacker-badge-challenge-writeup/1287/3 "2022-11-22T07:37:52Z")

</div>

> - The start requiring selling ones soul to Zuckenberg sucks
> - Finding the real binary and the correct offset in the firmware blob was annoying and required quesswork

for an alternative approach to the start of the puzzle which bypasses both of these, check out my [quick and dirty writeup](https://gist.github.com/shinmai/11764a4adb16b07f9e3928ff980335a5#file-disobey_2023_puzzle_writeup-md) 😉

---

<div class="post-metadata">

### Author: ![top1](https://discourse.hacklab.fi/user_avatar/discourse.hacklab.fi/top1/32/975_2.png) [@top1](https://discourse.hacklab.fi/u/top1)
#### Post date: [January 20, 2023, 2:31pm UTC](https://discourse.hacklab.fi/t/disobey-2023-hacker-badge-challenge-writeup/1287/4 "2023-01-20T14:31:29Z")

</div>

I got myself to step 6 and eventually stumbled through the ELF file reversing.

How did you figure out that you should XOR the latter half of the binary?  
And after that how did you know that it was x86 real mode binary?

Following this post I tried lobbing off the 65536 bytes (i.e. at what point binwalk calls: “Falling entropy edge”) and XOR-ing that and I was successful at getting the “interesting strings” out, but Ghidra wouldn’t recognize the file and when I forced the x86 real mode it found no functions.

---

<div class="post-metadata">

### Author: ![Depili](https://discourse.hacklab.fi/user_avatar/discourse.hacklab.fi/depili/32/609_2.png) [@Depili](https://discourse.hacklab.fi/u/Depili)
#### Post date: [January 21, 2023, 7:38am UTC](https://discourse.hacklab.fi/t/disobey-2023-hacker-badge-challenge-writeup/1287/5 "2023-01-21T07:38:17Z")

</div>

The real mode code isn’t xorred, mostly. Just a part of it that is xorred by the code and then executed. Lob off the last 64kbo of the file and load it straight into ghidra.

Finding the real mode stuff involved trial and error, but If you look at the shinmai’s writeup there are some hints for that I missed.
