• 无导入表编译原理


    前置知识

    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/

  • 相关阅读:
    (转载)SAPI 包含sphelper.h编译错误解决方案
    C++11标准的智能指针、野指针、内存泄露的理解(日后还会补充,先浅谈自己的理解)
    504. Base 7(LeetCode)
    242. Valid Anagram(LeetCode)
    169. Majority Element(LeetCode)
    100. Same Tree(LeetCode)
    171. Excel Sheet Column Number(LeetCode)
    168. Excel Sheet Column Title(LeetCode)
    122.Best Time to Buy and Sell Stock II(LeetCode)
    404. Sum of Left Leaves(LeetCode)
  • 原文地址:https://www.cnblogs.com/17bdw/p/11889233.html
Copyright © 2020-2023  润新知