美文网首页
IAT加密的一些粗浅理解

IAT加密的一些粗浅理解

作者: bluewind1230 | 来源:发表于2018-03-01 16:12 被阅读0次

    先上一段代码

    void afxiat()
    {
        
        PIMAGE_IMPORT_BY_NAME; //名称
    
        _IMAGE_THUNK_DATA32; //iat
        DWORD ImageBase = g_stubConf.ntheader.OptionalHeader.ImageBase;
    
        //导入表
        PIMAGE_IMPORT_DESCRIPTOR exeimport = 
            (PIMAGE_IMPORT_DESCRIPTOR)
            (g_stubConf.ntheader.OptionalHeader.DataDirectory[1].VirtualAddress+
            g_stubConf.ntheader.OptionalHeader.ImageBase);
    
        HANDLE heap = apis.pfnGetProcessHeap();
    
        //遍历导入表中的INT修复IAT
        while (exeimport->Name != NULL) //遍历模块
        {
            HMODULE h_dllModule = apis.pfnLoadLibraryA((char *)(exeimport->Name + ImageBase));
            PIMAGE_THUNK_DATA  import_Int = (PIMAGE_THUNK_DATA)(exeimport->OriginalFirstThunk+ImageBase);
            PIMAGE_THUNK_DATA  import_IAT = (PIMAGE_THUNK_DATA )(exeimport->FirstThunk+ ImageBase);
    
            while (import_Int->u1.Ordinal != 0) //遍历函数
            {
                UCHAR *buf = (UCHAR *)apis.pfnHeapAlloc(heap, HEAP_ZERO_MEMORY, 10);            //HeapAlloc的作用有点类似于VIrtualAlloc这个API
                buf[0] = 0xb8;
                buf[5] = 0xff;
                buf[6] = 0xe0;
                //new char[20]{ "\xB8\x00\x00\x00\0x00\0xff\0xe0" };
                DWORD opl = 0;
                apis.pfnVirtualProtect((LPVOID)buf, 20, PAGE_EXECUTE_READWRITE, &opl);
                if (import_Int->u1.Ordinal &0x80000000) //序号导出, 最高位为1,这里是获取最高位,如果最高位为1,就执行下面里面的语句,即
                                        //以序号导入 ,否则以名称导入,执行else中的语句
                {
    
                
                    //获取序号函数
                    LPVOID apiaddr =
                        apis.pfnGetProcAddress(h_dllModule, (char *)(import_Int->u1.Ordinal & 0xFFFF));
    
                    *(DWORD*)&buf[1] = (DWORD)apiaddr;  //函数写入shellcode
    
                    //DWORD funaddr = ;
                    
                
                    apis.pfnVirtualProtect((LPVOID)(import_IAT ), 4, PAGE_EXECUTE_READWRITE, &opl);
                    *(DWORD*)((DWORD)import_IAT ) = (DWORD)buf; //将函数写入到iat
                }
                else
                {
                    //DWORD Faddr = *(DWORD*)(import_Int->u1.AddressOfData + ImageBase);
                    PIMAGE_IMPORT_BY_NAME funname = (PIMAGE_IMPORT_BY_NAME)(import_Int->u1.AddressOfData+ImageBase);
                    LPVOID apiaddr =
                        apis.pfnGetProcAddress(h_dllModule, funname->Name);
    
                    *(DWORD*)&buf[1] = (DWORD)apiaddr;  //函数写入shellcode
    
                    apis.pfnVirtualProtect((LPVOID)(import_IAT), 4, PAGE_EXECUTE_READWRITE, &opl);
                    *(DWORD*)((DWORD)import_IAT ) = (DWORD)buf; //将函数写入到iat
    //              DWORD funaddr =import_IAT->u1.Function  ;  //获取iat地址
    // 
    //              apis.pfnVirtualProtect((LPVOID)funaddr, 4, PAGE_EXECUTE_READWRITE, &opl);
    //              *(DWORD*)(funaddr) = (DWORD)buf; //将函数写入到iat
                }
    
                import_Int++;
                import_IAT++;
    
            }
            exeimport++;
        }
    
    }
    

    先叙说一下整个逻辑:
    一般IAT的加密是这样的,导入表里面有一个IAT表,一般PE加载的时候会把函数地址填入这个表里面,这里一般用VirtualAlloc(上面这个例子没有用这个API)申请一块内存地址填入IAT表里面,申请的这块空间里面存放的是一段Shellcode,这个shellcode可以存放真正的地址,然后可以对地址进行加密(上面这个例子里面没有进行加密!!!,上面例子中的Shellcode的意思是:mov eax,0xXXXX(函数地址),jmp eax),如果加密了的话,汇编代码可以写成这样:

    mov eax,0x90909090(加密后的地址)
    xor eax,15151515(通过某个操作数进行异或)     (这一步的作用是得到真正的地址)
    jmp eax
    

    然后再将这段汇编代码写成Shellcode即可
    IAT不加密的话,IAT表里面存放的是原来的函数地址
    IAT加密的话,IAT里面存放的是VirtualAlloc申请出来的那块内存空间的地址,其实到达这个地址之后,可以对地址加密用一些比较复杂的算法,那样就比较难了!

    相关文章

      网友评论

          本文标题:IAT加密的一些粗浅理解

          本文链接:https://www.haomeiwen.com/subject/dsagxftx.html