You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
# Example: decode a JNI signature at 0x100933 of length 5 → should be ()[B
238
+
print(decode_string(0x00100933, 5))
239
+
```
240
+
241
+
</details>
237
242
238
243
- At scale, build a static map of call sites to the decoder’s arguments (encoded_ptr, size). Wrappers may hide arguments, so you may create this mapping manually from Ghidra xrefs if API recovery is noisy.
239
244
240
-
```python
241
-
# call_site -> (encoded_addr, size)
242
-
call_site_args_map = {
243
-
0x00100f8c: (0x00100b81, 0x41),
244
-
0x00100fa8: (0x00100bca, 0x04),
245
-
0x00100fcc: (0x001007a0, 0x41),
246
-
0x00100fe8: (0x00100933, 0x05),
247
-
0x0010100c: (0x00100c62, 0x41),
248
-
0x00101028: (0x00100c15, 0x16),
249
-
0x00101050: (0x00100a49, 0x101),
250
-
0x00100cf4: (0x00100821, 0x11),
251
-
0x00101170: (0x00100940, 0x101),
252
-
0x001011cc: (0x0010084e, 0x13),
253
-
0x00101334: (0x001007e9, 0x0f),
254
-
0x00101478: (0x0010087d, 0x15),
255
-
0x001014f8: (0x00100800, 0x19),
256
-
0x001015e8: (0x001008e6, 0x27),
257
-
0x0010160c: (0x00100c33, 0x13),
258
-
}
259
-
260
-
decoded_map = { hex(cs): decode_string(enc, sz)
261
-
for cs, (enc, sz) in call_site_args_map.items() }
262
-
263
-
print(json.dumps(decoded_map, indent=2))
264
-
withopen('decoded_strings.json', 'w') as f:
265
-
json.dump(decoded_map, f, indent=2)
266
-
```
245
+
<details>
246
+
<summary>Batch decode multiple call sites with angr</summary>
247
+
248
+
```python
249
+
# call_site -> (encoded_addr, size)
250
+
call_site_args_map = {
251
+
0x00100f8c: (0x00100b81, 0x41),
252
+
0x00100fa8: (0x00100bca, 0x04),
253
+
0x00100fcc: (0x001007a0, 0x41),
254
+
0x00100fe8: (0x00100933, 0x05),
255
+
0x0010100c: (0x00100c62, 0x41),
256
+
0x00101028: (0x00100c15, 0x16),
257
+
0x00101050: (0x00100a49, 0x101),
258
+
0x00100cf4: (0x00100821, 0x11),
259
+
0x00101170: (0x00100940, 0x101),
260
+
0x001011cc: (0x0010084e, 0x13),
261
+
0x00101334: (0x001007e9, 0x0f),
262
+
0x00101478: (0x0010087d, 0x15),
263
+
0x001014f8: (0x00100800, 0x19),
264
+
0x001015e8: (0x001008e6, 0x27),
265
+
0x0010160c: (0x00100c33, 0x13),
266
+
}
267
+
268
+
decoded_map = { hex(cs): decode_string(enc, sz)
269
+
for cs, (enc, sz) in call_site_args_map.items() }
270
+
271
+
import json
272
+
print(json.dumps(decoded_map, indent=2))
273
+
withopen('decoded_strings.json', 'w') as f:
274
+
json.dump(decoded_map, f, indent=2)
275
+
```
276
+
277
+
</details>
267
278
268
279
Annotate call sites in Ghidra
269
280
Option A: Jython-only comment writer (use a pre-computed JSON)
270
281
- Since angr requires CPython3, keep deobfuscation and annotation separated. First run the angr script above to produce decoded_strings.json. Then run this Jython GhidraScript to write PRE_COMMENTs at each call site (and include the caller function name for context):
271
282
272
-
```python
273
-
#@category Android/Deobfuscation
274
-
# Jython in Ghidra 10/11
275
-
import json
276
-
from ghidra.program.model.listing import CodeUnit
277
-
278
-
# Ask for the JSON produced by the angr script
279
-
f = askFile('Select decoded_strings.json', 'Load')
280
-
mapping = json.load(open(f.absolutePath, 'r')) # keys as hex strings
281
-
282
-
fm = currentProgram.getFunctionManager()
283
-
rm = currentProgram.getReferenceManager()
284
-
285
-
# Replace with your decoder address to locate call-xrefs (optional)
Option B: Single CPython script via pyhidra/ghidra_bridge
308
324
- Alternatively, use pyhidra or ghidra_bridge to drive Ghidra’s API from the same CPython process running angr. This allows calling decode_string() and immediately setting PRE_COMMENTs without an intermediate file. The logic mirrors the Jython script: build callsite→function map via ReferenceManager, decode with angr, and set comments.
@@ -410,6 +426,100 @@ idc.set_callee_name(call_ea, resolved_addr, 0) # IDA 8.3+
410
426
411
427
---
412
428
429
+
## AutoIt-based loaders: .a3x decryption, Task Scheduler masquerade and RAT injection
430
+
431
+
This intrusion pattern chains a signed MSI, AutoIt loaders compiled to .a3x, and a Task Scheduler job masquerading as a benign app.
432
+
433
+
### MSI → custom actions → AutoIt orchestrator
434
+
435
+
Process tree and commands executed by the MSI custom actions:
- Look for renamed copies of schtasks.exe co-located with Task XML: `dir /a "C:\Users\Public\Music\hwpviewer.exe"`
481
+
- Common paths: `C:\Users\Public\Music\AutoIt3.exe`, `...\IoKlTr.au3`, Startup `Smart_Web.lnk`, `%APPDATA%\Google\Browser\(adb|adv)*`
482
+
- Correlate process creation: AutoIt3.exe spawning legitimate Windows binaries (e.g., cleanmgr.exe, hncfinder.exe)
483
+
484
+
### AutoIt loaders and .a3x payload decryption → injection
485
+
486
+
- AutoIt modules are compiled with `#AutoIt3Wrapper_Outfile_type=a3x` and decrypt embedded payloads before injecting into benign processes.
487
+
- Observed families: QuasarRAT (injected into hncfinder.exe) and RftRAT/RFTServer (injected into cleanmgr.exe), as well as RemcosRAT modules (`Remcos\RunBinary.a3x`).
488
+
- Decryption pattern: derive an AES key via HMAC, decrypt the embedded blob, then inject the plaintext module.
489
+
490
+
Generic decryption skeleton (exact HMAC input/algorithm is family-specific):
- CreateProcess (suspended) of the target host (e.g., cleanmgr.exe)
506
+
- VirtualAllocEx + WriteProcessMemory with decrypted module/shellcode
507
+
- CreateRemoteThread or QueueUserAPC to execute payload
508
+
509
+
Hunting ideas
510
+
- AutoIt3.exe parented by MsiExec.exe or WScript.exe spawning system utilities
511
+
- Files with `.a3x` extensions or AutoIt script runners under public/user-writable paths
512
+
- Suspicious scheduled tasks executing AutoIt3.exe or binaries not signed by Microsoft, with minute-level triggers
513
+
514
+
### Account-takeover abuse of Android Find My Device (Find Hub)
515
+
516
+
During the Windows intrusion, operators used stolen Google credentials to repeatedly wipe the victim’s Android devices, suppressing notifications while they expanded access via the victim’s logged-in desktop messenger.
517
+
518
+
Operator steps (from a logged-in browser session):
519
+
- Review Google Account → Security → Your devices; follow Find My Phone → Find Hub (https://www.google.com/android/find)
520
+
- Select device → re-enter Google password → issue "Erase device" (factory reset); repeat to delay recovery
521
+
- Optional: clear alert e-mails in the linked mailbox (e.g., Naver) to hide security notifications
- Native Enrich: Scripting Ghidra and Frida to discover hidden JNI functions – [laripping.com](https://laripping.com/blog-posts/2021/12/20/nativeenrich.html)
432
542
-[Unit42 – AdaptixC2: A New Open-Source Framework Leveraged in Real-World Attacks](https://unit42.paloaltonetworks.com/adaptixc2-post-exploitation-framework/)
543
+
- KONNI-linked APT abuses Google Find Hub to wipe Android devices after Windows intrusion – [genians.co.kr](https://www.genians.co.kr/en/blog/threat_intelligence/android)
544
+
- Android Find My Device (Find Hub) – [google.com/android/find](https://www.google.com/android/find)
0 commit comments