REVERSE
MouseTrap
Description
APT27 targeted us and something was leaked can you help and identify what was leaked ?
Goal
Decrypt the PCAP traffic to retrieve the flag.
Challenge
Static Analysis (IDA)
Load MouseTrap.exe
into IDA.
Main function

Anti-debugging
The calls
CreateDesktopA("LuckyMouse")
andSwitchDesktop
move the process to a private desktop, which blanks your screen and hides any UI on a black/empty desktop.The call
NtSetInformationThread(..., 17)
, an anti-debug tactic that blocks first-chance exceptions and debugging events from reaching WinDbg/IDA.
To debug and analyze, I NOP
’d these anti-debug sections.
Patched version

Dynamic Analysis (Procmon)
Setup
Configure Procmon to monitor MouseTrap.exe.

Findings
Run the malware

The malware tries to open C:\creds.txt
. If it doesn’t exist, it exits.
Create C:\creds.txt and run again

Run the malware again


The malware reads the file via ReadFileEx
, encrypts the content, and attempts to connect to 127.0.0.1:13337
to send the encrypted data (the same traffic seen in the PCAP).
Dynamic Analysis (IDA/WinDbg)
Catching the crypto
Initial setup
Set a breakpoint on kernel32!ReadFileEx
, continue, and configure the debugger not to break on exceptions.


After resuming execution, the ReadFileEx breakpoint triggered.


Based on the stack arguments, lpBuffer is 0x005853B0 in .data
(dword_5853B0
); 0x005853B0 holds the content.
Set a hardware read breakpoint on
dword_5853B0
and continue.

A read triggers inside a routine at
sub_401000
function (Encryption)


Identifying the algorithm
Search the constants used by the routine

Searching these leads to SPC (a tweakable Lai-Massey block cipher using a SipHash-like core). The implementation matches the public reference (SPC over 64-bit words, 128-bit key, 128-bit block, 56-bit tweak folded into a 64-bit word).
Decrypt the PCAP Traffic
I reproduced the SPC round function in Python via GPT 5 and used the key/tweak lifted from .data section.
Export the TCP stream from the PCAP as hex and feed it to the script to obtain the plaintext.

Script
# solution.py
from binascii import unhexlify, hexlify
MASK64 = (1 << 64) - 1
def rotl(x, b): return ((x << b) & MASK64) | (x >> (64 - b))
def sipround(v0, v1, v2, v3):
v0 = (v0 + v1) & MASK64
v1 = v0 ^ rotl(v1, 13)
v0 = rotl(v0, 32)
v2 = (v2 + v3) & MASK64
v3 = v2 ^ rotl(v3, 16)
v0 = (v0 + v3) & MASK64
v3 = v0 ^ rotl(v3, 21)
v2 = (v2 + v1) & MASK64
v1 = v2 ^ rotl(v1, 17)
v2 = rotl(v2, 32)
return v0, v1, v2, v3
def sha4(round_i, k0, k1, tw, X):
v0 = 0x50726f736563636f ^ k0
v1 = 0x43686f636f6c6174 ^ k1
v2 = 0x01f32d1f4361f48e ^ k0
v3 = ((round_i & 0xFF) << 56) ^ tw ^ k1
v3 ^= X
v0, v1, v2, v3 = sipround(v0, v1, v2, v3)
v0 ^= X
v2 ^= 16
v0, v1, v2, v3 = sipround(v0, v1, v2, v3)
v0, v1, v2, v3 = sipround(v0, v1, v2, v3)
return (v0 ^ v1 ^ v2 ^ v3) & MASK64
def sigma(L):
X = L & 0xffffffff
return ((X << 32) | (((L >> 32) ^ X) & 0xffffffff)) & MASK64
def unsigma(L):
X = (L >> 32) & 0xffffffff # upper 32
Y = L & 0xffffffff # lower 32
return (((Y ^ X) << 32) | X) & MASK64
def le64(b): return int.from_bytes(b, 'little')
def be64(x): return x.to_bytes(8, 'little')
# Keys/tweak lifted from .data segment
KEY = bytes.fromhex("3d1790908e448599b0829e584cf2cd56")
TWEAK = bytes.fromhex("aa12de3344b4c6f8")
def decrypt_block(ct16, key=KEY, tweak=TWEAK):
k0 = le64(key[:8]); k1 = le64(key[8:])
tw = le64(tweak)
L = le64(ct16[:8]); R = le64(ct16[8:])
for i in (3, 2, 1, 0):
L = unsigma(L)
X = sha4(i, k0, k1, tw, L ^ R)
L ^= X; R ^= X
return be64(L) + be64(R)
def decrypt(hex_str, key=KEY, tweak=TWEAK):
h = ''.join(hex_str.split()).lower()
if len(h) % 32 != 0:
raise ValueError("Ciphertext hex length must be a multiple of 32 (16 bytes per block).")
data = unhexlify(h)
out = bytearray()
for off in range(0, len(data), 16):
out += decrypt_block(data[off:off+16], key, tweak)
return bytes(out)
def pretty_ascii(b):
return ''.join(chr(x) if 32 <= x < 127 else '.' for x in b)
if __name__ == "__main__":
ct_hex = "2f012a1e13a9a54b103424d8873cf1685e61ccc93f9dcae98e7b8f3ed0f862a66c72df99dcf517982af398a726d8d22f881635d66b8d0a5c67582f397a88f8b3131a5bab38430b60a068eaeb3638712f9376b89eb05adb31e8a8472f5060aab8ab880ed106e9d743cc34f7a593b25283bfcc23d8f03ddf79fa319ed355c85e9779ae9ee61878f0832c9b5825a664c8f922303edc220256435fdff0b650d7ea6c88f2961aa53da9f69bb7849f582c79794e5d6aa9bf2f3210013d5bb7c8a2b819dfa8a1ee0f1cf71172995895e5778796624178017ea89df5f949f7bf7a800a7a740d6070117f1742b41eb8cb5bc7f02b42a4476da7657deacf13147e1b879d40d20d0fd34c6d055aca1368b3803384c74d8108b1c58f14d77dc10b3e6d9a095aa9e13ec09f009a7c97e2cd9d883bab15de027e8ffe45552941f2f9e33e16b0f0afe3abbc865ff7c629ca794e4e1c159c53a0174a57f4f94b979e8551796a1418548916de67c13cf83400427edfcce65f41582ea54541f1dacf2a65b90607e123c2718f610e0ae2527ea40b3ad82a6692896d36b65a1e465bb7abcbaf7f44017f8d3535d4c1beeb3ed5be6a061fa3e6d9e656e910f7ed9a3080d7f044786c9a86e54ed1d87c03dde9c8b70703e6376aa65bcc02690a67cbaf1b0cbb3b944383bd87f6ab3f9aa2c29a3a2f260f844ee064ec3ed0e3c84c63979507e9ab3e7e94af9088d622aea6ca505048e859bef1138e5fa9115d1aab7249345aa0e356c781da361f8599a6ae63103f0c5f4754b2e8ce9b43c90e069aef908353b2db47722906bc097009d2fe651f1c9034d7782bd75a4a44050e46d7bcf93038ae1c1da11b5f07bbf8e1f56c26250b1b3636b5f884a5f0176bad7f1a1c74dad8c99e06f691686ce428e71b6cf62143c7e5b6aeb19fe68912bd8183287fec70205eba34fda3a873cdf753ac8389817610a93a04e5478de9a7246d157ac33033d12bb622f266ec6e332b816c87a4ff31adc191a5e7e548eed8ea93ddb5c77cf2ab8c1ab398bfd2ec86b3164fd546e41dbe3ec1054efb632c77fea51e6bd14c10185c8d963d84d9805faabc76bb5a1adbf6be795f4fc57d9bf3527cb0fa90afd1c1f83863161f33ea452c78c298ef1920bc54f7b24c4de64a3aa2312c338dc49efd3bb37029db5680049c85cbc803cc4ef1a013c435e529333f29faffe7fee727c86c08279e6d31005951c55dc571509ac997e24965caea41a3ebd6e99fa3280c0f499774abe2e85abb329a01f55692c12d6acc0bc81d870e584c58d5f3187b967bad9ceb02ab07a130f2864e7663926a1e8885ee76294eaf346e5c8cb0335bc58b1e6f47476448e081e25e09407e4ca6a7f00876843a1494e1c93778d23b7832d3a7d66fa69fb2589ba1f3af974d1dd651b5f7b718f924dc661ead149e9fbd6f11dced48e934f0"
pt = decrypt(ct_hex)
print("PT hex :", hexlify(pt).decode())
print("PT ascii:", pretty_ascii(pt))
Last updated
Was this helpful?