BKSec Recruitment Writeups
Welcome
BKSEC{ctf_has_always_been_fun_til_now?}
very cool native app (REV)
The challenge provides an ipa.

Inside it, there are 2 files that caught my eye: the Mach-O64 HermesChallenge and the binary main.jsbundle.
I tried analyzing the Mach-O64 but it didn’t give me anything useful.
I proceed edto analyzing the .jsbundle, putting it in DiE

With that information, I found the tool : https://github.com/P1sec/hermes-dec (after struggling a bit with the syntax) I got the desired .js; let’s take a look:

We have an “unfinished” flag at _q3m.
Scroll down a little

There are some suspicious skips,
This _w9p should be the one that checks those missing characters.


I fed it all to the LLM and it got me the full thing:

IoT_ez_or_hard
This challenge is about inspecting a firmware update. %% (which was kind of broken and my task is to analyze to see how it works and recovers the flag (the author accidentally hinted this)) %%
Extracting
The challenge provides me a router_fw.bin.
I asked the LLM for the tools and how could i extract the data from this, after a while i got what i wanted
%%0x7e = 126%%
Found an executable cloudsync. Let’s dive into that
If nothing is suspicious, it passes us to the sub_1a70
Let’s take a look at sub_1a70
%%that wall of vars jumpscared me%%
scrolling through, these are noticeable:
- it reads the serial
- it reads itself
- loads something from
0x31c0-0x3220 - it reads the
backup.dat(the backup file for syncing?) - it has its own reading func
sub_19b0 sub_1900andsub_1710were called several times (together)- There is a XOR check loop at the end
- 128 bits = 16 bytes
Analyzing & guessing sub_1900 & sub_1710

it loads some hard coded vals, i’m curious what those were


That code pattern appeared several more times:

So there is a high chance the LLM was right %%(there is no chance we have a custom hashing/encrypting here, yeah?)%%
From what i have known: SHA256 has 3 parts: init, update and finalize I derived that
sub_1900(state, src, len)~sha_updatesub_1710(state, dest)~sha_finalize
Reconstructing
Now i can rewrite the first part with python

import hashlib
sugar = bytes.fromhex("4C18217E0A6B2D72334F5561102A3C19")[::-1]
exe_bytes = open("cloudsync", "rb").read()
self_has = hashlib.sha256(exe_bytes).digest()
serial = b'ROUTER-61AAE6FC6A83FD56'
first_dish = hashlib.sha256(serial + sugar + self_has).digest()
The first_dish is our router’s “signature”
it then goes to the HMAC and was checked with the tag from the backup.dat
dat = open("backup.dat", "rb").read()
tag = dat[0x19 + 39 : 0x19 + 39 + 32]
import hmac
assert hmac.new(first_dish, dat[5:0x19+39], hashlib.sha256).digest() == tag, "HMAC not ok"
print("HMAC ok")
I copied all the file in the same folder tested it and it said “ok” %%jackpot!%%. Our key first_dish is correct.
aaaaanddddddd….. did i miss something? isn’t it supposed to have a decrypting fuction? (so this is the part where it was broken)
looked around and found this untouched sub_2340

rewirite:
key = hashlib.sha256(key1 + key2 + b'\x00\x00\x00\x00').digest()
key += hashlib.sha256(key1 + key2 + b'\x01\x00\x00\x00').digest()
...
flag = xor(cipher, key)
Finishing
With further inspection of the backup.dat and trying out the combinations (with LLM), i got the right combinations, the full script was written as below
import hashlib, hmac
from pwn import xor
sugar = bytes.fromhex("4C18217E0A6B2D72334F5561102A3C19")[::-1]
exe_bytes = open("cloudsync", "rb").read()
self_has = hashlib.sha256(exe_bytes).digest()
serial = b'ROUTER-61AAE6FC6A83FD56'
first_dish = hashlib.sha256(serial + sugar + self_has).digest()
dat = open("backup.dat", "rb").read()
ntwice = dat[5 : 0x15]
tag = dat[0x40:]
assert hmac.new(first_dish, dat[5:0x19+39], hashlib.sha256).digest() == tag, "HMAC not ok"
print("HMAC ok")
skibidi = dat[0x19 : 0x19 + 39]
bo_pi_xi = hashlib.sha256(first_dish[:16] + ntwice + b'\x00\x00\x00\x00').digest()
bo_pi_xi += hashlib.sha256(first_dish[:16] + ntwice + b'\x01\x00\x00\x00').digest()
print(xor(skibidi, bo_pi_xi))
