跳至主要内容

反Hook 之自己实现GetProcAddress和LoadLibraryA(c++ version)

http://ift.tt/2AocAD0
// 课上练习.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <windows.h>
//要实现的功能:
/*
    自己实现GerProcAddress
    LoadLibraryA
*/


//思路:
/*
    GerProcAddress和LoadLibraryA都是在Kernel32.dll中的
    首要的任务就是找到Kernel32.dll,然后遍历IAT就能找到这两个函数
    现在首要的难点就是如何找到kernel32.dll()
    通过dll的加载顺序可以找到,而且虽然需要使用未文档化的API,但是好在windgb可以直接看,而且用到的也并不是很多
    懒得去晚上搜了,直接自己实现一个得了,作为演示,能用就行(最好还是搜一个正规的结构体)
*/

/*
0: kd> dt _TEB /a
nt!_TEB
+0x000 NtTib            : _NT_TIB
+0x01c EnvironmentPointer : Ptr32 Void
+0x020 ClientId         : _CLIENT_ID
+0x028 ActiveRpcHandle  : Ptr32 Void
+0x02c ThreadLocalStoragePointer : Ptr32 Void
+0x030 ProcessEnvironmentBlock : Ptr32 _PEB

//首先实现部分TEB结构体,因为只需要用的PEB的部分,所以实现到这就ok了
*/


//构建 TEB
typedef struct _TEB
{
    //保证0x30是peb的结构体就ok了
    struct _tem
    {
        DWORD a1;
        DWORD a2;
        DWORD a3;
        DWORD a4;
        DWORD a5;
        DWORD a6;
        DWORD a7;
        DWORD a8;
        DWORD a9;
        DWORD a10;
        DWORD a11;
        DWORD a12;
    }tem;
    DWORD _Peb;

}TEB,*PTEB;


//构建 局部 _PEB
/*
    0: kd> dt _PEB /b
    nt!_PEB
    +0x000 InheritedAddressSpace : UChar
    +0x001 ReadImageFileExecOptions : UChar
    +0x002 BeingDebugged    : UChar
    +0x003 BitField         : UChar
    +0x003 ImageUsesLargePages : Pos 0, 1 Bit
    +0x003 IsProtectedProcess : Pos 1, 1 Bit
    +0x003 IsLegacyProcess  : Pos 2, 1 Bit
    +0x003 IsImageDynamicallyRelocated : Pos 3, 1 Bit
    +0x003 SkipPatchingUser32Forwarders : Pos 4, 1 Bit
    +0x003 SpareBits        : Pos 5, 3 Bits
    +0x004 Mutant           : Ptr32
    +0x008 ImageBaseAddress : Ptr32
    +0x00c Ldr              : Ptr32
*/

typedef struct _PEB_LDR_DATA
{
    int Length;
    int Initialized;
    DWORD SsHandle;
    PLIST_ENTRY InLoadOrderModuleList; //只用到这里,所以到这就暂时ok吧
}PEB_LDR_DATA,*PPEB_LDR_DATA;

typedef struct _PEB
{
    DWORD tem1;
    DWORD tem2;
    DWORD tem3;
    PPEB_LDR_DATA Ldr; //需要先实现一个此结构体
}PEB,*PPEB;

typedef struct _LDR_DATA_TABLE_ENTRY
{
    struct InLoadOrderLinks
    {
        PLIST_ENTRY Flink;

        PLIST_ENTRY Blink;
    }InLoadOrderLinks;
    struct InMemoryOrderLinks
    {
        PLIST_ENTRY Flink;

        PLIST_ENTRY Blink;
    }InMemoryOrderLinks;
    struct InInitializationOrderLinks
    {
        PLIST_ENTRY Flink;

        PLIST_ENTRY Blink;
    }InInitializationOrderLinks;

    DWORD DllBase;//加载基址

}LDR_DATA_TABLE_ENTRY,*PLDR_DATA_TABLE_ENTRY;

//遍历导出表,然后根据函数名称,获取制定的函数地址

PVOID MyGetFnAddress(HMODULE hMoudle, const char * pProcName)
{
    PIMAGE_DOS_HEADER pDosHdr = (PIMAGE_DOS_HEADER)hMoudle;
    PIMAGE_NT_HEADERS pNtHdr = (PIMAGE_NT_HEADERS)(pDosHdr->e_lfanew + (ULONG_PTR)pDosHdr);
    PIMAGE_OPTIONAL_HEADER pOpHdr = (PIMAGE_OPTIONAL_HEADER)&pNtHdr->OptionalHeader;
    //获取到op头之后,就是获取导出表
    PIMAGE_EXPORT_DIRECTORY  pExportDir = (PIMAGE_EXPORT_DIRECTORY)(pOpHdr->DataDirectory[0].VirtualAddress+(ULONG)pDosHdr);


    DWORD *pEnt = (DWORD *)(pExportDir->AddressOfNames + (ULONG_PTR)pDosHdr);
    //然后就开始便利了,首先遍历的是导入名称表
    for (DWORD i =0;i<pExportDir->NumberOfNames;i++)
    {
        char * pEntName = (char*)(pEnt[i] + (ULONG_PTR)pDosHdr);
        if (strcmp(pProcName, pEntName)==0)
        {
            //说明找到了输入的函数名
            //然后去找这个函数名的在导出函数地址表中的地址
            WORD* pEot = (WORD* )(pExportDir->AddressOfNameOrdinals+(ULONG_PTR)pDosHdr);
            DWORD index = pEot[i];
            DWORD * pEat = (DWORD*)(pExportDir->AddressOfFunctions + (ULONG_PTR)pDosHdr);
            DWORD pFnAddress = pEat[index];
            return (PVOID)pFnAddress;
        }
    }
    //没有找到
    return NULL;
}


int main()
{
    
    //获取teb
    PTEB pTeb = NtCurrentTeb();
    //获取peb
    PPEB pPeb= (PPEB)pTeb->_Peb;
    
    //然后是找到ldr
    PPEB_LDR_DATA pLdr = pPeb->Ldr;

    //首先是获取InLoadOrderModuleList 
    PLIST_ENTRY pListEntry = pLdr->InLoadOrderModuleList->Flink;
    
    PLDR_DATA_TABLE_ENTRY pKernel32 = (PLDR_DATA_TABLE_ENTRY)pListEntry->Flink;

    HMODULE hMoudle = (HMODULE)pKernel32->DllBase;
    
    //定义两个函数指针
    /* 
    原型
    WINAPI
GetProcAddress(
    _In_ HMODULE hModule,
    _In_ LPCSTR lpProcName
    );

    HMODULE
    WINAPI
    LoadLibraryA(
    _In_ LPCSTR lpLibFileName
    );
    */
    typedef LPVOID(WINAPI* MYGETPROCADDRESS)(HMODULE hMoudle, LPCSTR lpProcName);
    typedef HMODULE(WINAPI*MYLOADLIBRARYA)(LPCSTR lpLibFileName);
    
    MYGETPROCADDRESS MyGetProcAddress = (MYGETPROCADDRESS)MyGetFnAddress(hMoudle, "GetProcAddress");
    MYLOADLIBRARYA MyLoadLibraryA = (MYLOADLIBRARYA)MyGetFnAddress(hMoudle, "LoadLibraryA");

//这就找到了这个2个api的地址,如果对方进行了自定义hook,这个时候大可以自定去读取OpCode进行判断

// c++ 写的比较麻烦,稍后用汇编写一个,比较简洁易懂


    return 0;
}


The post 反Hook 之自己实现GetProcAddress和LoadLibraryA(c++ version) appeared first on cole.

http://ift.tt/eA8V8J reverse engineering, reverse December 04, 2017 at 07:33PM

评论

此博客中的热门博文

IDA动态调试ELF中遇到的问题(1)

https://ift.tt/2Gxnf2F 遇到 got SIGCHLD singal(child status has changed)...这种提示 singal fork了子进程 直接点yes,然后继续单步执行,出来提示 pass to application就行了 内存查看 用od习惯了之后,凡事都想右键看一下内存,但是IDA中好像没有那么如意, 目前只是在栈中右键发现有查看hex的选项 动态调试的时候的nop ida保存动态调试的时候修改的数据 方法一:在程序运行的时候保存 The post IDA动态调试ELF中遇到的问题(1) appeared first on cole . https://ift.tt/2q9Qf5g WHATEVER April 05, 2018 at 09:44AM

手工加壳Demo- C++Version

http://ift.tt/2AAEutK // 手动加壳demo.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include <windows.h> #include <string.h> typedef struct _StubConf { IMAGE_NT_HEADERS ntheader; }STUBCONF; class PeFile { public: PeFile(); ~PeFile(); bool OpenFile(const char*FilePath); bool InitHdrs(); PIMAGE_SECTION_HEADER addSection(const char * secName, DWORD dwSecSzie); PIMAGE_SECTION_HEADER getSection(const char* secName); DWORD Size2ALi(DWORD dwSize, DWORD dwALi); void peclose(); void setOpe(DWORD newOep); LPVOID peGetProcAddress(const char* szFnName); DWORD RVATOOFFSET(DWORD rva); ULONG_PTR getfileBuff(); PIMAGE_NT_HEADERS getNtHeader(); PIMAGE_OPTIONAL_HEADER getOptionHeader(); void fixStubReloc(DWORD oldImageBase, DWORD newImageBase, DWORD oldSectionRva, DWORD newSectionRva); void setSecData(IMAGE_SECTION_HEADER* pScn, void* pSectionData, DWORD dwSectionSize); bool savea...