zoukankan      html  css  js  c++  java
  • 无导入表编译原理

    前置知识

    pe文件结构
    windows api
    API字符串隐藏原理
    

    思路

    - 获取kernel32.dll 基地址;
    - 定位 GetProcAddress函数的地址;
    - 使用GetProcAddress确定 LoadLibrary函数的地址;
    - 然后使用 LoadLibrary加载DLL文件(例如user32.dll);
    - 使用 GetProcAddress查找某个函数的地址(例如MessageBox);
    - 指定函数参数;
    - 调用函数。
    

    通过PEB获取kernel32.dll 基地址

    在windows操作系统中每一个进程系统都维护着一个描述该进程的结构体,我们称之为peb(进程环境块),如可执行文件加载到内存的位置,模块列表(DLL),指示进程是否被调试的标志,不同发行版的windows系统该结构体可能存在着差异,在这个结构体里就维护者一个描述所有载入模块的链表(InMemoryOrderModuleList),无论我们是否使用,系统都会载入kernel32.dll到进程的虚拟地址空间。

    C++代码

    // ConsoleApplication6.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
    //
     
    #include "pch.h"
    #include <stdio.h>
    #include "windows.h"
     
    #define NT_SUCCESS(x) ((x) >= 0)
    #define ProcessBasicInformation 0
     
    typedef NTSTATUS(NTAPI *pfnNtWow64QueryInformationProcess64)(
        IN HANDLE ProcessHandle,
        IN ULONG ProcessInformationClass,
        OUT PVOID ProcessInformation,
        IN ULONG ProcessInformationLength,
        OUT PULONG ReturnLength OPTIONAL
        );
     
     
    typedef NTSTATUS(NTAPI *pfnNtWow64ReadVirtualMemory64)(
        IN HANDLE ProcessHandle,
        IN PVOID64 BaseAddress,
        OUT PVOID Buffer,
        IN ULONG64 Size,
        OUT PULONG64 NumberOfBytesRead
        );
     
    typedef
    NTSTATUS(WINAPI *pfnNtQueryInformationProcess)
    (HANDLE ProcessHandle, ULONG ProcessInformationClass,
        PVOID ProcessInformation, UINT32 ProcessInformationLength,
        UINT32* ReturnLength);
     
    typedef struct _PROCESS_BASIC_INFORMATION32 {
        NTSTATUS ExitStatus;
        UINT32 PebBaseAddress;
        UINT32 AffinityMask;
        UINT32 BasePriority;
        UINT32 UniqueProcessId;
        UINT32 InheritedFromUniqueProcessId;
    } PROCESS_BASIC_INFORMATION32;
     
    typedef struct _UNICODE_STRING32
    {
        USHORT Length;
        USHORT MaximumLength;
        PWSTR Buffer;
    } UNICODE_STRING32, *PUNICODE_STRING32;
     
    typedef struct _PEB32
    {
        UCHAR InheritedAddressSpace;
        UCHAR ReadImageFileExecOptions;
        UCHAR BeingDebugged;
        UCHAR BitField;
        ULONG Mutant;
        ULONG ImageBaseAddress;
        ULONG Ldr;
        ULONG ProcessParameters;
        ULONG SubSystemData;
        ULONG ProcessHeap;
        ULONG FastPebLock;
        ULONG AtlThunkSListPtr;
        ULONG IFEOKey;
        ULONG CrossProcessFlags;
        ULONG UserSharedInfoPtr;
        ULONG SystemReserved;
        ULONG AtlThunkSListPtr32;
        ULONG ApiSetMap;
    } PEB32, *PPEB32;
     
    typedef struct _PEB_LDR_DATA32
    {
        ULONG Length;
        BOOLEAN Initialized;
        ULONG SsHandle;
        LIST_ENTRY32 InLoadOrderModuleList;
        LIST_ENTRY32 InMemoryOrderModuleList;
        LIST_ENTRY32 InInitializationOrderModuleList;
        ULONG EntryInProgress;
    } PEB_LDR_DATA32, *PPEB_LDR_DATA32;
     
    typedef struct _LDR_DATA_TABLE_ENTRY32
    {
        LIST_ENTRY32 InLoadOrderLinks;
        LIST_ENTRY32 InMemoryOrderModuleList;
        LIST_ENTRY32 InInitializationOrderModuleList;
        ULONG DllBase;
        ULONG EntryPoint;
        ULONG SizeOfImage;
        UNICODE_STRING32 FullDllName;
        UNICODE_STRING32 BaseDllName;
        ULONG Flags;
        USHORT LoadCount;
        USHORT TlsIndex;
        union
        {
            LIST_ENTRY32 HashLinks;
            ULONG SectionPointer;
        };
        ULONG CheckSum;
        union
        {
            ULONG TimeDateStamp;
            ULONG LoadedImports;
        };
        ULONG EntryPointActivationContext;
        ULONG PatchInformation;
    } LDR_DATA_TABLE_ENTRY32, *PLDR_DATA_TABLE_ENTRY32;
     
    typedef struct _PROCESS_BASIC_INFORMATION64 {
        NTSTATUS ExitStatus;
        UINT32 Reserved0;
        UINT64 PebBaseAddress;
        UINT64 AffinityMask;
        UINT32 BasePriority;
        UINT32 Reserved1;
        UINT64 UniqueProcessId;
        UINT64 InheritedFromUniqueProcessId;
    } PROCESS_BASIC_INFORMATION64;
    typedef struct _PEB64
    {
        UCHAR InheritedAddressSpace;
        UCHAR ReadImageFileExecOptions;
        UCHAR BeingDebugged;
        UCHAR BitField;
        ULONG64 Mutant;
        ULONG64 ImageBaseAddress;
        ULONG64 Ldr;
        ULONG64 ProcessParameters;
        ULONG64 SubSystemData;
        ULONG64 ProcessHeap;
        ULONG64 FastPebLock;
        ULONG64 AtlThunkSListPtr;
        ULONG64 IFEOKey;
        ULONG64 CrossProcessFlags;
        ULONG64 UserSharedInfoPtr;
        ULONG SystemReserved;
        ULONG AtlThunkSListPtr32;
        ULONG64 ApiSetMap;
    } PEB64, *PPEB64;
     
    typedef struct _PEB_LDR_DATA64
    {
        ULONG Length;
        BOOLEAN Initialized;
        ULONG64 SsHandle;
        LIST_ENTRY64 InLoadOrderModuleList;
        LIST_ENTRY64 InMemoryOrderModuleList;
        LIST_ENTRY64 InInitializationOrderModuleList;
        ULONG64 EntryInProgress;
    } PEB_LDR_DATA64, *PPEB_LDR_DATA64;
     
    typedef struct _UNICODE_STRING64
    {
        USHORT Length;
        USHORT MaximumLength;
        ULONG64 Buffer;
    } UNICODE_STRING64, *PUNICODE_STRING64;
     
    typedef struct _LDR_DATA_TABLE_ENTRY64
    {
        LIST_ENTRY64 InLoadOrderLinks;
        LIST_ENTRY64 InMemoryOrderModuleList;
        LIST_ENTRY64 InInitializationOrderModuleList;
        ULONG64 DllBase;
        ULONG64 EntryPoint;
        ULONG SizeOfImage;
        UNICODE_STRING64 FullDllName;
        UNICODE_STRING64 BaseDllName;
        ULONG Flags;
        USHORT LoadCount;
        USHORT TlsIndex;
        union
        {
            LIST_ENTRY64 HashLinks;
            ULONG64 SectionPointer;
        };
        ULONG CheckSum;
        union
        {
            ULONG TimeDateStamp;
            ULONG64 LoadedImports;
        };
        ULONG64 EntryPointActivationContext;
        ULONG64 PatchInformation;
    } LDR_DATA_TABLE_ENTRY64, *PLDR_DATA_TABLE_ENTRY64;
     
    int main()
    {
        DWORD dwPid = 4480;
        HANDLE m_ProcessHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPid);
        BOOL bTarget = FALSE;
        BOOL bSource = FALSE;
     
        IsWow64Process(GetCurrentProcess(), &bSource);
        IsWow64Process(m_ProcessHandle, &bTarget);
     
        SYSTEM_INFO si;
        GetSystemInfo(&si);
     
        if (bTarget == FALSE && bSource == TRUE)
        {
            HMODULE NtdllModule = GetModuleHandle(L"ntdll.dll");
            pfnNtWow64QueryInformationProcess64 NtWow64QueryInformationProcess64 = (pfnNtWow64QueryInformationProcess64)GetProcAddress(NtdllModule, "NtWow64QueryInformationProcess64");
            pfnNtWow64ReadVirtualMemory64 NtWow64ReadVirtualMemory64 = (pfnNtWow64ReadVirtualMemory64)GetProcAddress(NtdllModule, "NtWow64ReadVirtualMemory64");
            PROCESS_BASIC_INFORMATION64 pbi64 = { 0 };
            if (NT_SUCCESS(NtWow64QueryInformationProcess64(m_ProcessHandle, ProcessBasicInformation, &pbi64, sizeof(pbi64), NULL)))
            {
                DWORD64 Ldr64 = 0;
                LIST_ENTRY64 ListEntry64 = { 0 };
                LDR_DATA_TABLE_ENTRY64 LDTE64 = { 0 };
                wchar_t ProPath64[256];
                if (NT_SUCCESS(NtWow64ReadVirtualMemory64(m_ProcessHandle, (PVOID64)(pbi64.PebBaseAddress + offsetof(PEB64, Ldr)), &Ldr64, sizeof(Ldr64), NULL)))
                {
                    if (NT_SUCCESS(NtWow64ReadVirtualMemory64(m_ProcessHandle, (PVOID64)(Ldr64 + offsetof(PEB_LDR_DATA64, InLoadOrderModuleList)), &ListEntry64, sizeof(LIST_ENTRY64), NULL)))
                    {
                        if (NT_SUCCESS(NtWow64ReadVirtualMemory64(m_ProcessHandle, (PVOID64)(ListEntry64.Flink), &LDTE64, sizeof(_LDR_DATA_TABLE_ENTRY64), NULL)))
                        {
                            while (1)
                            {
                                if (LDTE64.InLoadOrderLinks.Flink == ListEntry64.Flink) break;
                                if (NT_SUCCESS(NtWow64ReadVirtualMemory64(m_ProcessHandle, (PVOID64)LDTE64.FullDllName.Buffer, ProPath64, sizeof(ProPath64), NULL)))
                                {
                                    printf("模块基址:0x%llX
    模块大小:0x%X
    模块路径:%ls
    ", LDTE64.DllBase, LDTE64.SizeOfImage, ProPath64);
                                }
                                if (!NT_SUCCESS(NtWow64ReadVirtualMemory64(m_ProcessHandle, (PVOID64)LDTE64.InLoadOrderLinks.Flink, &LDTE64, sizeof(_LDR_DATA_TABLE_ENTRY64), NULL))) break;
                            }
                        }
                    }
                }
            }
     
        }
        else if (bTarget == TRUE && bSource == TRUE || si.wProcessorArchitecture != PROCESSOR_ARCHITECTURE_AMD64 ||
            si.wProcessorArchitecture != PROCESSOR_ARCHITECTURE_IA64)
        {
            HMODULE NtdllModule = GetModuleHandle(L"ntdll.dll");
            pfnNtQueryInformationProcess NtQueryInformationProcess = (pfnNtQueryInformationProcess)GetProcAddress(NtdllModule, "NtQueryInformationProcess");
            PROCESS_BASIC_INFORMATION32 pbi32 = { 0 };
            if (NT_SUCCESS(NtQueryInformationProcess(m_ProcessHandle, ProcessBasicInformation, &pbi32, sizeof(pbi32), NULL)))
            {
                DWORD Ldr32 = 0;
                LIST_ENTRY32 ListEntry32 = { 0 };
                LDR_DATA_TABLE_ENTRY32 LDTE32 = { 0 };
                wchar_t ProPath32[256];
                if (ReadProcessMemory(m_ProcessHandle, (PVOID)(pbi32.PebBaseAddress + offsetof(PEB32, Ldr)), &Ldr32, sizeof(Ldr32), NULL))
                {
                    if (ReadProcessMemory(m_ProcessHandle, (PVOID)(Ldr32 + offsetof(PEB_LDR_DATA32, InLoadOrderModuleList)), &ListEntry32, sizeof(LIST_ENTRY32), NULL))
                    {
                        if (ReadProcessMemory(m_ProcessHandle, (PVOID)(ListEntry32.Flink), &LDTE32, sizeof(_LDR_DATA_TABLE_ENTRY32), NULL))
                        {
                            while (1)
                            {
                                if (LDTE32.InLoadOrderLinks.Flink == ListEntry32.Flink) break;
                                if (ReadProcessMemory(m_ProcessHandle, (PVOID)LDTE32.FullDllName.Buffer, ProPath32, sizeof(ProPath32), NULL))
                                {
                                    printf("模块基址:0x%X
    模块大小:0x%X
    模块路径:%ls
    ",LDTE32.DllBase,LDTE32.SizeOfImage,ProPath32);
                                }
                                if (!ReadProcessMemory(m_ProcessHandle, (PVOID)LDTE32.InLoadOrderLinks.Flink, &LDTE32, sizeof(_LDR_DATA_TABLE_ENTRY32), NULL)) break;
                            }
                        }
                    }
                }
            }
        }
        CloseHandle(m_ProcessHandle);
        getchar();
    }
     
    // 运行程序: Ctrl + F5 或调试 >“开始执行(不调试)”菜单
    // 调试程序: F5 或调试 >“开始调试”菜单
     
    // 入门提示: 
    //   1. 使用解决方案资源管理器窗口添加/管理文件
    //   2. 使用团队资源管理器窗口连接到源代码管理
    //   3. 使用输出窗口查看生成输出和其他消息
    //   4. 使用错误列表窗口查看错误
    //   5. 转到“项目”>“添加新项”以创建新的代码文件,或转到“项目”>“添加现有项”以将现有代码文件添加到项目
    //   6. 将来,若要再次打开此项目,请转到“文件”>“打开”>“项目”并选择 .sln 文件
    

    汇编代码

    HMODULE GetKernel32() {
        HMODULE hModule;
        _asm {
           mov eax, fs: [0x30]//fs:[00]位置存放着当前线程的线程环境块(teb),teb的0x30偏移处存放着当前线程所属进程的peb。
           mov eax, [eax + 0xc]//EAX = PEB->Ldr
           mov esi, [eax + 0x14]//ESI = PEB->Ldr.InMemOrder
           lodsd          //EAX = Second module
           xchg eax, esi     //EAX = ESI, ESI = EAX
           lodsd          //Next module
           mov ebx, [eax + 0x10]//EBX = Base address
           mov hModule,ebx
        }
        return hModule;
    }
    

    无导入表运行shellcode

    int main() {
        //UCHAR shellcode[] =  {'xbd','xb0','x63','xa7','x89','xda','..........【shellcode】..........'};
    
    
        typedef LPVOID(WINAPI *pVirtualAlloc)(LPVOID, DWORD, DWORD, DWORD);
        typedef BOOL(WINAPI *pVirtualProtect)(LPVOID,DWORD,DWORD,PDWORD);
        typedef BOOL(WINAPI* pWriteProcessMemory)(HANDLE, LPVOID, LPVOID, DWORD, LPDWORD);
    
        DWORD oldProtect=0;
        HMODULE hKernal32 = GetKernal32();
        pVirtualAlloc VirtualAlloc=(pVirtualAlloc)GetProcAddress(hKernal32, "VirtualAlloc");
        pVirtualProtect VirtualProtect = (pVirtualProtect)GetProcAddress(hKernal32, "VirtualProtect");
        pWriteProcessMemory WriteProcessMemory = (pWriteProcessMemory)GetProcAddress(hKernal32, "WriteProcessMemory");
    
        //PVOID Address = VirtualAlloc(NULL, sizeof(shellcode) + 1, MEM_COMMIT, PAGE_READWRITE);
    
        //WriteProcessMemory(GetCurrentProcess(), Address, &shellcode, sizeof(shellcode), NULL);
    
    
        //VirtualProtect(Address, sizeof(shellcode), PAGE_EXECUTE_READWRITE, &oldProtect);
        VirtualProtect(&shellcode, sizeof(shellcode), PAGE_EXECUTE_READWRITE, &oldProtect);
        ((void(*)(void)) &shellcode)();
        VirtualProtect(&shellcode, sizeof(shellcode), oldProtect, NULL);
        //VirtualProtect(Address, sizeof(shellcode), oldProtect, NULL);
    
        return 0;
    }
    

    参考

    【1】WOW64通过PEB获取32/64位进程模块信息 https://www.52pojie.cn/thread-872501-1-1.html
    【2】过所有主流杀软查杀的“免杀壳”编写揭秘 https://bbs.pediy.com/thread-252772.htm
    【3】重新编译开源代码绕过杀毒软件 https://www.t00ls.net/thread-53697-1-1.html
    【4】通过重写ring3 API函数实现免杀 https://www.t00ls.net/thread-53717-1-1.html
    【5】勒索软件中的API哈希-为什么以及如何做? https://blag.nullteilerfrei.de/2019/11/09/api-hashing-why-and-how/

  • 相关阅读:
    五星评价
    IE9以上 CSS文件因Mime类型不匹配而被忽略 其他浏览器及IE8以下显示正常
    js时间显示设置
    jq手风琴---点击时列表的左边距逐渐减小
    break continue return
    validate插件:验证密码没有空格 用户名是5-10位 至少包含数字和大小写字母中的两种字符
    Commons IO
    Servlet & JSP
    设计模式
    Table of Contents
  • 原文地址:https://www.cnblogs.com/17bdw/p/11889233.html
Copyright © 2011-2022 走看看