把exe当dll来调用破解的技巧方法

调用第三方exe程序里面的函数,一直是大家所向往并已经讨论过不少的问题,其方法大体有三类:

1、让第三方exe启动,然后自己程序注入进去调用之;

2、让第三方exe启动,然后远程读入其内容;

3、把第三方exe,当作DLL进行加载,并调用里面的函数。

前2个方法容易实现,但无法摆脱让exe运行的缺点,今天我们讨论第三条思路,把exe向dll一样加载,然后调用里面的函数。

就此,主要面临以下三个问题:

1、导入表修复;

2、重定位dll数据,也就是exe数据。

其实这2个问题归结起来都是重定位问题,这里就不再解释重定位原理和原因了。

有些人认为PE文件重定位,就要搞重定位表,exe要输出函数,就要搞导出表,这些其实是不必要的,只要理解了他们的原理,自己实现反而更方便。当然,另外一点原因是我现在基本忘却PE结构了。以下方法不涉及给exe增加导出表或者重定位表。

举例来说碰到的问题和解决思路,exe里面有如下代码:

        push    425570                           ; /kernel32.dll
        call    dword ptr [425280]               ; \GetModuleHandleA

这个很正常,也很简单, 0x425570 指向一个字符串, [425280] 里面是 GetModuleHandleA 函数指针,也就是导入表内容。但如果把这个exe作为DLL进行LoadLibrary,你会发现这2行代码仍然如此,一点也没变,但却无法执行了,因为这时候涉及到的这2个指针,指向的内容已经不是我们预想的了,需要把它们重定位,才能让他们指向预期目的地。重定位方法也很简单:

1、 0x425570 ,这个地址,用当前自身模块基地址加上 0x25570 ,就是新的地址;

2、 0x425280 ,这个地址,用当前自身模块基地址加上 0x25280 ,就是新的地址;

理解了这一点,就知道我们需要作什么了。

口说无凭,动手为真,下面我们举例来进行说明。就采用壳狼最近写的antidebugger测试程序吧,当然没经过他的同意 :)

目的:加载 AntiDebug.exe,调用它的第一个标签里面的 Find Debugger 功能,里面有20多个选项,我们争取把它调用完!

调用函数:

简单跟踪以下,他这些反调试手段都在一个函数体内,调用方式如下:

00404FCC   .  50            push    eax
00404FCD   .  8BCB          mov     ecx, ebx        //这句无所谓,可以nop
00404FCF   .  E8 ECF1FFFF   call    004041C0

实现方式也很简单:

    hMod = LoadLibrary(ExePath);
   
    DWORD FindDebugerCall = (DWORD)hMod + 0x41C0;
   
    _asm{
        push 0xFFFFFFFF         //这里是调用标记,如果为这个参数,表示所有的反调试功能都选了
        mov  eax, FindDebugerCall
        call eax;
    }      

最终我们的目的就是要让上面这个函数正常运行。为此,我们要作以下大量工作。

一、修复输入表

    思路很简单,首先根据被加载dll的模块基地址,找到其导入表,然后根据其函数名,自己获取导入函数地址,重新填入到正常位置。
   
    在此感谢鸡蛋壳,让我在茫茫网海搜到了他的一些代码并加以改之。
   
    pDosHeader = (PIMAGE_DOS_HEADER)hMod;
    pNTHeaders = (PIMAGE_NT_HEADERS)((BYTE *)hMod + pDosHeader->e_lfanew);
    pOptHeader = (PIMAGE_OPTIONAL_HEADER)&(pNTHeaders->OptionalHeader);

    pImportDescriptor = (PIMAGE_IMPORT_DESCRIPTOR)((BYTE *)hMod + pOptHeader->DataDirectory[1].VirtualAddress);

    while(pImportDescriptor->FirstThunk)
    {
        //获取dll名称
        char * dllname = (char *)((BYTE *)hMod + pImportDescriptor->Name);

        pThunkData = (PIMAGE_THUNK_DATA)((BYTE *)hMod + pImportDescriptor->OriginalFirstThunk);

        int no = 1;
        while(pThunkData->u1.Function)
        {
            if ((pThunkData->u1.Ordinal &  IMAGE_ORDINAL_FLAG) != IMAGE_ORDINAL_FLAG)
            {
                //获取函数名称
                char *funname = (char *)((BYTE *)hMod + (DWORD)pThunkData->u1.AddressOfData + 2);
                myaddr = (int*)GetProcAddress(GetModuleHandle(dllname), funname);
            }
           
            PDWORD lpAddr = (DWORD *)((BYTE *)hMod + (DWORD)pImportDescriptor->FirstThunk) +(no-1);

            MEMORY_BASIC_INFORMATION  mbi;
            VirtualQuery(lpAddr,&mbi,sizeof(mbi));
            VirtualProtect(lpAddr,sizeof(DWORD),PAGE_READWRITE,&dwOLD);
            WriteProcessMemory(GetCurrentProcess(),
                lpAddr, &myaddr, sizeof(DWORD), NULL);
            VirtualProtect(lpAddr,sizeof(DWORD),dwOLD,0);

            no++;
            pThunkData++;
        }

        pImportDescriptor++;
    }
   
    这个东西搞完,DLL(也就是加载的exe,后面都叫dll)里面的API和其他导入函数可以正常使用了。
   

二、重定位代码段指针

    重定位意义比较广泛,大体有三类数据需要重定位。
   
    1、代码段指针。比如我上面举例的 push    425570 ,这个0x425570是个字符串指针。再比如 mov     edi, dword ptr [425400] , 这里面的 0x425400,也是指针,也需要重定位;
   
    2、数据段指针。比如这个exe里面,用到了一些SEH结构,SEH结构里面含有指向函数体的指针,比如:
   
    SEH异常处理结构:

    0042BA94  E0 1C 40 00 E6 1C 40 00 00 00 00 00 FE FF FF FF  ?@.?@…..?

相关推荐

发表评论

您的电子邮箱地址不会被公开。

QQ点我咨询