
ShellcodeFluctuation PoC ported to Nim
元のリポジトリのNim移植版: https://github.com/mgeeky/ShellcodeFluctuation すべてのコメントは、元のリポジトリからそのままコピー&ペーストしました。このテクニックを理解するのに非常に役立ったからです。このテクニック自体の詳細については、元のリポジトリのREADMEを読むことを強くお勧めします!
依存関係のインストール:
nimble install winim ptr_math
このメモリ暗号化テクニックがOpSecの観点で最善とは言えないことは十分に認識しています。この手法は、定義された領域だけを正確に暗号化するだけです。例えばC2インプラントの場合、Sleep中に新たに実行されたモジュールのメモリアドレスは暗号化されません。ヒープベースの検出(Cobalt-Strikeの設定を狙ったものなど)に対しては、ここにヒープ暗号化を追加する必要があるでしょう。
それでも、このメモリ暗号化テクニックは、C2インプラントのメイン部分(for the main)でSleep中の自動メモリスキャナによる検出を回避するために十分に使用できます。私はこのPoCをCovenantと、このようなカスタマイズしたステージレスペイロードでテストし、成功しました。
この移植版では、暗号化/復号化キー、シェルコードのアドレス、その他プロテクション(RW)などの値を手動で定義する必要があります。元のリポジトリでは、シェルコードの呼び出し元アドレス(Caller-Address)は自動的に取得されていました。
Example.nim ファイルには、開始するために必要なものがすべて含まれています。もちろん、C2シェルコードを使用する場合、Sleep を自分で呼び出す必要はありません(これはPoCですべてをトリガーするためだけのものです)。その呼び出しはC2自身が行うべきです。現時点では、Win32の Sleep 関数を使用するC2フレームワークにのみ対応していますが、フックを別の関数に変更すれば、同じように動作します。
import winim
import Fluctuation
echo "Trying to hook Sleep"
if (hookSleep()):
echo "Hooked Sleep successfully!"
type
PocArray = array[12, byte]
let names: PocArray = [byte 0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA]
g_fluctuationData.shellcodeAddr = unsafeAddr names[0]
echo "Shellcode address:"
echo repr(g_fluctuationData.shellcodeAddr)
g_fluctuationData.shellcodeSize = size_t(len(names))
echo "Shellcode Size:"
echo repr(g_fluctuationData.shellcodeSize)
when defined(amd64):
g_fluctuationData.encodeKey = 0xDEADB33f
when defined(i386):
g_fluctuationData.encodeKey = 0xDEAD
g_fluctuationData.currentlyEncrypted = false
g_fluctuationData.protect = PAGE_READWRITE
g_fluctuate = FluctuateToRW
echo "Calling Sleep"
Sleep(2500)
echo "Everything went fine and as expected"
else:
echo "Failed to hook Sleep"
quit(1)
暗号化PoCのテストは、例えば次のようにして行えます:
nim c --debuginfo --linedir:on Example.nim
デバッガで開始します:
gdb Example.exe
Sleepの前後にブレークポイントを設定します:
# Before encryption
break Example.nim:31
# After encryption
break Fluctuation.nim:98
# Original value restored
break Example.nim:33
その後、各ブレークポイントでシェルコードアドレスの値を次のように確認します:

NA へのFluctuation化はまだ機能しません。私のテストではベクタード例外ハンドラ(Vectored Exception Handler)が一度もトリガーされず、アプリケーションがクラッシュしたためです。今後、追加のテストやトラブルシューティングを行う必要があります。ご自身でテストしてみてください! :-)