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")andSwitchDesktopmove 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_5853B0and continue.

A read triggers inside a routine at
sub_401000function (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?