zoukankan      html  css  js  c++  java
  • 浅谈IAT加密原理及过程

    上一次做完代码段加密后,又接触到了新的加密方式:IAT加密

    IAT加密是通过隐藏程序的导入表信息,以达到增加分析程序的难度。因为没有导入表,就无法单纯的从静态状态下分析调用了什么函数,动态调试时,也无法直接从调用处判断出调用的函数。从而增加了程序分析的难度。

    思路如下:

    1.把IAT信息全部删除掉,只留下DLL名和第一个调用函数的信息(目的是让程序在最开始运行时能正常调用那些初始化类型的函数)

    2.根据导入表的信息,自己实现函数加载,通过调用LoadLibraryA和GetProcAddress函数把DLL中的所有函数加载进来,并在程序中保存加载后的函数地址。(但由于是用程序A给程序B加密,程序B未运行时,如何获得这2个函数的地址呢?而且IAT表也已经被删掉了。此时只能借助PEB和TEB来获取这2个函数的地址,并记录在程序B中,当程序B运行时,就可以通过对应的位置取得函数地址)

    3.找到所有 “指令中包含了IAT加载地址” 的指令,并记录这些指令的位置(指令所在位置而不是指令中的地址位置)

    4.构建一个shellcode表,里面写着每个3.里所找到的指令的处理代码,简单来说就是把3.所找到的地址,修改成跳到4的这个shellcode表对应的处理指令中,这段处理指令实现和3.的指令一样的效果。

    5.把3.中的指令修改为一个jmp,jmp到4.中对应的处理代码。实现一样的效果。

    6.把重定位表中,有关于IAT表的项删掉,因为IAT加密后,原调用位置的指令是跳转到自己写的shellcode中,里面的指令是在函数运行后修改的。无需重定位了。并在在4.的shellcode中,用到了基址,这里采用的获取基址方式是通过重定位,所以要被shellcode表中的所有对应位置也添加到重定位表中。

    实现步骤:

    1.先常规的检查该程序是否为PE文件(检查"MZ"和“PE”是否存在)

    2.通过导入表,找到对应的IAT值,并构建一个向量vector用于存储。(注:这里为IAT的值,而不是IAT的值指向的地址中的值)

    3.根据2.中所找到的IAT,找到在源文件中,又那些是使用了这个值的,分别是mov exx(每个寄存器对应的二进制数不同),push,call,jmp。记得这里记录的是调用指令的位置,而不是调用指令中IAT地址所在的位置

    4.用向量vector+结构体的方式先将IAT表中的信息保存下来(DLL个数,每个DLL的名及名字的长度。这个DLL是通过什么方式导出函数(名称/序号);DLL有几个导出函数,他们分别的值是多少,如果他是以名称导出的话,该名称的长度和值分别又是多少)。

    5.接着隐藏被加密文件的导入表,每个DLL下面的INT和IAT表只保留第一个值,其他的全部赋值为0,去除掉导入信息

    6.更新重定位表数据,如果没有重定位表则跳过这项。看7.

      6.1先把重定位表的值保存下来,以便后续移动到程序末尾(这么做的目的是为了后续添加新的重定位项时,重定位块的范围能覆盖上) (例:当前程序最大内存偏移为0x15000,增加后的偏移为0x18000,如果不把重定位移到最后的话,新增加的这0x3000中就无法被重定位到)

      6.2把目标程序的重定位表数据清空

    7.将每个节的保护属性修改为可写(本来只修改.text节的属性即可,但由于该节的位置不在data数组里面记录,单凭节名判断未必准确,所以将所以节都改为可写)

    8.创建一个新的节,把4.中保存的导入表信息填充进去。由于已知这些信息的长度,写shellcode时把位置一一对应即可。

      8.1再在这个节当中,申请导入函数个数*4的空间,以便存放后续导入的函数地址

      8.2记录当前的内存地址,设为新的OEP;

      8.3整个加密最为重要的一点:编写shellcode

        8.3.1:由于LoadLibraryA和GetProcAddress都为Kernel32中的导出函数;所以先通过进程的fs:[0x30]获取到PEB结构,再在该结构的0x0C的位置获取到该进程的DLL列表指针,再通过这个列表的0x1C的位置获取初始化模块列表;通过这个初始化模块列表取得结构,对比结构成员中的长度和值,取到目标DLL(Kernel32.dll)在该程序的装载基址

        8.3.2获得Kernel32的装载基址后,把该地址当成一个PE文件处理,通过偏移取值,最后找到导出表位置,根据导出表中的数据一一比对,得到LoadLibraryA和GetProcAddress在该程序的位置。保存起来

        8.3.3根据8中保存的导入表数据,一一调用LoadLibraryA获得目标DLL的装载地址,再根据该装载地址,调用GetProcAddress把其中的函数地址全部获取出来,并按导入表的顺序,保存到8.1所预留出来的空间中

        8.3.4构造代替原导入表功能的shellcode块,每个shellcode块对应一个使用到IAT地址的位置(2.所保存的值)。

        8.3.5把原调用到IAT指令的位置,全部修改为jmp到8.3.4对应的shellcode块,注意指令长度,替换后的指令为jmp [目标shellcode块地址],占5字节,如原指令占6字节的话,填充一个nop对齐     流程为:找到调用IAT地址的指令位置(3.中保存了),将其替换成jmp [对应shellcode块地址],在对应shellcode块中,把自己在8.3.3所获得的函数地址,用混淆的方式,实现成原来的功能。(本来为mov eax [iat地址],修改成JMP 对应shellcode块,对应shellcode块里实现mov eax [自己所获得的函数地址])

    9.如果没有重定位表跳过这一步,看10.  把重定位把重定位表中有关调用函数的指令位置删掉(注:这里的位置为指令当中的地址的位置,例:E9 0X0123 4567在0x8的位置,那么地址位置就为0x9)。这么做的目的是因为IAT表加密后,函数都是自己实现导入的,原导入表的这些项无需再进行重定位了,填充时地址就已经是当前程序的位置了。

    10.由于8.3.4的shellcode块中需要用到基址,这里利用了重定位表的方式获得基址,所以要把每个shellcode块中,对应获得基址的指令地址也添加到重定位块中

    11.将新增的节按文件对齐和内存对齐后,将重定位表恢复,恢复起始位置为新增节的起始位置+对齐后的大小   

    12.IAT加密完成

    下面附上代码:

    代码长度1594 未精简,有备注     其中有涉及jit编译shellcode指令的代码,所以无法直接复制运行,这里仅提供编写思路。

    要在此再增加分析者的难度的话,可以在8.填充导入表信息时,先做异或加密处理,等运行时,再异或解密出来,因为知道位置与长度,所以很容易做到

       1 #include<iostream>
       2 #include<Windows.h>
       3 #include<map>
       4 #include<vector>
       5 #include "Asmjit\asmjit.h"
       6 
       7 using namespace std;
       8 using namespace asmjit;
       9 using namespace asmjit::x86;
      10 
      11 int g_iFileSize = 0;        //文件大小
      12 UCHAR *g_pFileSrc = NULL;  //文件内容  (此处必须为无符号字符指针,因为char会将十六进制的最高位默认为符号位)
      13 int g_iSectionAlignment = 0;//内存对齐大小
      14 int g_iFileAlignment = 0;//文件对齐大小
      15 int g_iImageBase = 0;//程序基址
      16 int g_iNewOEP = 0;//新入口点
      17 int g_iOldOEP = 0;//旧入口点
      18 
      19 struct FuncTag
      20 {
      21     BYTE iFuncNameLenth;//函数名称长度
      22     char *szFuncName;
      23 };
      24 struct DLLFuncTag
      25 {
      26     byte bDllNameLenth;//DLL名长度
      27     char *szDllName;
      28     WORD wFuncNum;//当前DLL的函数数量
      29     byte bTab;//导入方式:0为序号导入 1为名称
      30     vector<FuncTag>vFuncNAMEorNo;//注意:此时的序号已经去掉最高位
      31 };
      32 vector<DLLFuncTag>g_tagDllFunc;//存放IAT信息的结构体,成员为DLL名长度,DLL名,函数数量,标志(最高位为1则是序号,否则为一个字符串的地址),函数名列表
      33 
      34 
      35 //先通过遍历获得下面结构体中各个成员的值  注:成员的位置皆为RVA
      36 /*
      37 1.将dwRelocAddr这4字节的地址放入重定位表中,使其在运行后该位置的值变为程序基址
      38 2.先去dwCallAddr的位置,将那行代码修改为jmp dwJmpAddr(如果是mov eax,则直接修改即可,其他的则要填充多一个nop(0x90),以便对齐指令长度)
      39 3.执行shellcode时,会将2的调用地址+5/+6作为返回地址压栈 (jmp指令除外)
      40 4.将NewLatAddr的值,加上基址后,在得到的地址上取值,该地址上的值与原IAT所指向的值相同
      41 5.执行完后,根据3得到的值,返回到调用指令的下一条指令上
      42 */
      43 struct IatAddrTab
      44 {
      45     DWORD dwCallAddr;//以便区分当前是什么类型下使用了这个IAT地址  注意,这里为整个调用代码的位置,而非调用的代码的函数地址的位置    
      46     BYTE bType;//该调用类型 0-7为mov eax、edx、esp、esi、ecx、ebx、ebp、edi  8为call 9为jmp (其中8和9可以归类成一个处理方式) 10为push  
      47     DWORD dwRelocAddr;//用于添加到重定位块中,该位置存放的为基址
      48     WORD wIndex;//当前IAT位于加载表的下标 每个地址占4字节
      49     DWORD dwOldIatAddr;//原IAT地址
      50     DWORD dwNewIatAddr;//将要替换成的新IAT地址
      51     DWORD dwJmpAddr;//shellcode所在的起始位置RVA     
      52 };  
      53 vector<IatAddrTab>g_tagIAT;//存放IAT替换地址的结构体,成员为IAT地址,以及一个调用地址位置,还有一个该IAT类型
      54 
      55 
      56 vector<DWORD>g_IATaddrList;
      57 
      58 struct tagRelocation
      59 {
      60     DWORD wR_Head;
      61     vector<WORD>wR_Offset;
      62 };
      63 vector<tagRelocation>vOldReloction;
      64 
      65 
      66 VOID GetKernel32Base(X86Assembler &a)
      67 {
      68     Label GetInfoBegin = a.newLabel();
      69     Label cmpDllName = a.newLabel();
      70     Label cmpChar = a.newLabel();
      71     Label GetNextModule = a.newLabel();
      72     Label GetBaseOver = a.newLabel();
      73 
      74     a.push(ebx);
      75     a.push(ecx);
      76     a.push(edx);
      77     a.push(esi);
      78     a.push(edi);
      79     a.mov(edx, esp);
      80     a.sub(esp, 0x18);
      81     
      82     a.mov(dword_ptr(esp, 0x00), 0x0065006B);
      83     a.mov(dword_ptr(esp, 0x04), 0x006E0072);
      84     a.mov(dword_ptr(esp, 0x08), 0x006C0065);
      85     a.mov(dword_ptr(esp, 0x0C), 0x00320033);
      86     a.mov(dword_ptr(esp, 0x10), 0x0064002E);
      87     a.mov(dword_ptr(esp, 0x14), 0x006C006C);
      88     a.xor_(eax, eax);
      89     a.mov(esi, dword_ptr_abs(0x30).setSegment(fs));//获得PEB 同理mov esi,fs:[30]
      90     a.mov(esi, dword_ptr(esi, 0x0C));            //取到dll的列表指针
      91     a.mov(esi, dword_ptr(esi, 0x1C));             //取到初始化序模块化
      92 
      93     a.bind(GetInfoBegin);//遍历模块信息
      94     a.mov(edi, dword_ptr(esi, 8));//取到当前模块基址
      95     a.lea(ebx, dword_ptr(esi, 0x1c));//取到UNICODE STRING结构
      96     a.movzx(ecx, word_ptr(ebx));//取出长度
      97     a.cmp (ecx, 24);//对比长度
      98     a.jne(GetNextModule);//不等则获取下一个模块
      99     a.mov(ebx, dword_ptr(ebx , 4));//取到字符串地址  此时ebx不再为结构地址
     100     a.mov(ecx, 0);//用于遍历
     101 
     102     a.bind(cmpDllName);//对比模块名字
     103     a.cmp(ecx, 24);
     104     //遍历到字符末尾 找到目标模块(先对的长度再对的字符,排除了前面同名后面A/W的情况)
     105     a.jnl(GetBaseOver);//获取基址结束
     106     a.xor_ (eax, eax);//清空容器
     107     a.movzx(eax, word_ptr(ebx, ecx));
     108     a.cmp(eax, 0x41);//如果是大写字符(41~5A)范围内,转成小写
     109     a.jna(cmpChar);
     110     a.cmp(eax, 0x5A);
     111     a.ja(cmpChar);
     112     a.add(eax, 0x20);//大写字符的值+0x20即转成小写字符
     113     
     114     a.bind(cmpChar);//对比每个字符
     115     a.cmp(ax, word_ptr(esp, ecx));//对比字符串内容
     116     a.jne(GetNextModule);//不等则获取下一个模块
     117     a.add(ecx, 2);
     118     a.jmp(cmpDllName);
     119 
     120     a.bind(GetNextModule);//获得下一个模块信息
     121     a.mov(esi, dword_ptr(esi));//取得下一个初始化模块
     122     a.test(esi, esi);
     123     a.jnz(GetInfoBegin);//不为空则继续遍历
     124 
     125     a.bind(GetBaseOver);
     126     a.mov(eax, edi);
     127     a.add(esp, 0x18);
     128     a.pop(edi);
     129     a.pop(esi);
     130     a.pop(edx);
     131     a.pop(ecx);
     132     a.pop(ebx);
     133 }
     134 
     135 VOID GetLoadLibraryAAddr(X86Assembler &a)
     136 {
     137     //跳转标记
     138     Label FindFuncAddr = a.newLabel();
     139     Label FindFuncAddrOver = a.newLabel();
     140 
     141     a.push(ebx);
     142     a.push(ecx);
     143     a.push(esi);
     144     a.push(ebp);
     145     //记得开始获取出来的都是RVA  要加上DLL的基址edi来取值
     146     a.mov(eax, dword_ptr(edi, 0x3c));
     147     a.mov(ebx, dword_ptr(edi, eax, 0, 0x78));//NT头+0x78 = 导出表RVA
     148     //上面等价于[edi + eax + 0x78],如果没有0的话,他会把第三个参数当成2的N次方变成了edi + eax * 2的0x78次方
     149     a.add(ebx, edi);//ebx=导出表RVA+基址
     150     a.mov(ecx, dword_ptr(ebx, 0x18));//ecx=按名称导出个数
     151     a.mov(esi, dword_ptr(ebx, 0x20));//esi=导出函数名称表rva
     152     a.add(esi, edi);
     153 
     154     a.bind(FindFuncAddr);
     155     a.sub(ecx, 1);//从后面往前遍历 能少占用一个寄存器,但要记得先-1再遍历
     156     a.jz(FindFuncAddrOver);//减到0即遍历完
     157     a.mov(ebp, dword_ptr(esi, ecx, 2));//取到函数名称比拗最后一个函数名的RVA 等价于[esi,ecx*(2的n次方)]
     158     a.add(ebp, edi);
     159     a.cmp(dword_ptr(ebp), 0x64616F4C);
     160     a.jne(FindFuncAddr);
     161     a.cmp(dword_ptr(ebp, 4), 0x7262694C);
     162     a.jne(FindFuncAddr);
     163     a.cmp(dword_ptr(ebp, 8), 0x41797261);
     164     a.jne(FindFuncAddr);
     165     a.cmp(byte_ptr(ebp, 12), 0);//结束符  防止类似LoadLibrary和LoadLibraryA扩展函数名偏差出现
     166     a.jne(FindFuncAddr);
     167     //此时ecx为遍历的下标 
     168     a.mov(esi, dword_ptr(ebx, 0x24));//esi=导出函数序号表RVA(上面名称对比完 回收esi)
     169     a.add(esi, edi);
     170     a.movzx(ebp, word_ptr(esi, ecx, 1));//ebp=函数序号 ebp=[esi+ecx*2一次方]
     171     //EBP:Get=2b0 Load=3c2
     172     a.mov(esi, dword_ptr(ebx, 0x1c));//esi=函数地址表RVA
     173     a.add(esi, edi);
     174     a.mov(eax, dword_ptr(esi, ebp, 2));//地址=地址表+序号*2的2次方
     175     a.add(eax, edi);
     176     //此时eax为loadlibraryA地址
     177     a.bind(FindFuncAddrOver);
     178     a.pop(ebp);
     179     a.pop(esi);
     180     a.pop(ecx);
     181     a.pop(ebx);
     182 }
     183 
     184 VOID GetGetProcAddressAddr(X86Assembler &a)
     185 {
     186     //跳转标记
     187     Label FindFuncAddr = a.newLabel();
     188     Label FindFuncAddrOver = a.newLabel();
     189 
     190     a.push(ebx);
     191     a.push(ecx);
     192     a.push(esi);
     193     a.push(ebp);
     194     //记得开始获取出来的都是RVA  要加上DLL的基址edi来取值
     195     a.mov(eax, dword_ptr(edi, 0x3c));
     196     a.mov(ebx, dword_ptr(edi, eax, 0, 0x78));//NT头+0x78 = 导出表RVA
     197     //上面等价于[edi + eax + 0x78],如果没有0的话,他会把第三个参数当成2的N次方变成了edi + eax * 2的0x78次方
     198     a.add(ebx, edi);//ebx=导出表
     199     a.mov(ecx, dword_ptr(ebx, 0x18));//ecx=按名称导出个数
     200     a.mov(esi, dword_ptr(ebx, 0x20));//esi=导出函数名称表rva
     201     a.add(esi, edi);
     202 
     203     a.bind(FindFuncAddr);
     204     a.sub(ecx, 1);//从后面往前遍历 能少占用一个寄存器,但要记得先-1再遍历
     205     a.jz(FindFuncAddrOver);//减到0即遍历完
     206     a.mov(ebp, dword_ptr(esi, ecx, 2));//取到函数名称比拗最后一个函数名的RVA 等价于[esi,ecx*(2的n次方)]
     207     a.add(ebp, edi);
     208     a.cmp(dword_ptr(ebp), 0x50746547);
     209     a.jne(FindFuncAddr);
     210     a.cmp(dword_ptr(ebp, 4), 0x41636f72);
     211     a.jne(FindFuncAddr);
     212     a.cmp(dword_ptr(ebp, 8), 0x65726464);
     213     a.jne(FindFuncAddr);
     214     a.cmp(word_ptr(ebp, 12), 0x7373);
     215     a.jne(FindFuncAddr);
     216     a.cmp(byte_ptr(ebp, 14), 0);//结束符  防止类似LoadLibrary和LoadLibraryA扩展函数名偏差出现
     217     a.jne(FindFuncAddr);
     218 
     219     //此时ecx为遍历的下标 
     220     a.mov(esi, dword_ptr(ebx, 0x24));//esi=导出函数序号表RVA(上面名称对比完 回收esi)
     221     a.add(esi, edi);
     222     a.movzx(ebp, word_ptr(esi, ecx, 1));//ebp=函数序号 ebp=[esi+ecx*2一次方]
     223     //EBP:Get=2b0 Load=3c2
     224     a.mov(esi, dword_ptr(ebx, 0x1c));//esi=函数地址表RVA
     225     a.add(esi, edi);
     226     a.mov(eax, dword_ptr(esi, ebp, 2));//地址=地址表+序号*2的2次方
     227     a.add(eax, edi);
     228     //此时eax为loadlibraryA地址
     229     a.bind(FindFuncAddrOver);
     230     a.pop(ebp);
     231     a.pop(esi);
     232     a.pop(ecx);
     233     a.pop(ebx);
     234 }
     235 DWORD RVAtoFA(DWORD dwRVA)        //RVA转文件地址
     236 {
     237     PIMAGE_DOS_HEADER pDosHead = PIMAGE_DOS_HEADER(g_pFileSrc);
     238     PIMAGE_NT_HEADERS pNtHead = PIMAGE_NT_HEADERS((DWORD)pDosHead + pDosHead->e_lfanew);
     239     PIMAGE_SECTION_HEADER pSection = (PIMAGE_SECTION_HEADER)(pNtHead->FileHeader.SizeOfOptionalHeader + (DWORD)&pNtHead->OptionalHeader);
     240     int iSectionNum = pNtHead->FileHeader.NumberOfSections;
     241 
     242     for (int i = 0; i < iSectionNum; i++)
     243     {
     244         if (dwRVA >= pSection->VirtualAddress && dwRVA < (pSection->VirtualAddress + pSection->Misc.VirtualSize))
     245         {
     246             return (DWORD)g_pFileSrc + dwRVA - pSection->VirtualAddress + pSection->PointerToRawData;
     247         }
     248         pSection++;
     249     }
     250     return 0; //转换失败
     251 }
     252 
     253 DWORD FAtoRVA(DWORD dwFA)        //文件地址转RVA
     254 {
     255     PIMAGE_DOS_HEADER pDosHead = PIMAGE_DOS_HEADER(g_pFileSrc);
     256     PIMAGE_NT_HEADERS pNtHead = PIMAGE_NT_HEADERS((DWORD)pDosHead + pDosHead->e_lfanew);
     257     PIMAGE_SECTION_HEADER pSection = (PIMAGE_SECTION_HEADER)(pNtHead->FileHeader.SizeOfOptionalHeader + (DWORD)&pNtHead->OptionalHeader);
     258     int iSectionNum = pNtHead->FileHeader.NumberOfSections;
     259 
     260     for (int i = 0; i < iSectionNum; i++)
     261     {
     262         if (dwFA >= pSection->PointerToRawData && dwFA < (pSection->PointerToRawData + pSection->SizeOfRawData))
     263         {
     264             return (DWORD)dwFA - pSection->PointerToRawData + pSection->VirtualAddress;
     265         }
     266         pSection++;
     267     }
     268     return 0; //转换失败
     269 }
     270 
     271 
     272 BOOL LoadFile(char *pFileName)    //获取文件内容
     273 {
     274     HANDLE hFile = CreateFileA(pFileName,
     275         GENERIC_READ,
     276         FILE_SHARE_READ,
     277         NULL,
     278         OPEN_EXISTING,
     279         FILE_ATTRIBUTE_NORMAL,
     280         0);
     281     if (!hFile)
     282     {
     283         return false;
     284     }
     285     g_iFileSize = GetFileSize(hFile, NULL);
     286 
     287     g_pFileSrc = (UCHAR*)malloc(g_iFileSize);
     288     if (!g_pFileSrc)
     289     {
     290         cout << "申请内存失败" << endl;
     291         return false;
     292     }
     293 
     294     if (!ReadFile(hFile, g_pFileSrc, g_iFileSize, NULL, NULL))
     295     {
     296         cout << "读取文件失败" << endl;
     297         return false;
     298     }
     299 
     300     return true;
     301 }
     302 
     303 
     304 BOOL CheckPE()        //检查PE文件格式
     305 {
     306     PIMAGE_DOS_HEADER pDosHead = PIMAGE_DOS_HEADER(g_pFileSrc);
     307     PIMAGE_NT_HEADERS pNtHead = PIMAGE_NT_HEADERS((DWORD)pDosHead + pDosHead->e_lfanew);
     308     if (pDosHead->e_magic != 0x5a4d || pNtHead->Signature != 0x4550)
     309     {
     310         return false;
     311     }
     312     g_iImageBase = pNtHead->OptionalHeader.ImageBase;
     313     g_iFileAlignment = pNtHead->OptionalHeader.FileAlignment;
     314     g_iSectionAlignment = pNtHead->OptionalHeader.SectionAlignment;
     315     g_iOldOEP = pNtHead->OptionalHeader.AddressOfEntryPoint;
     316     return true;
     317 }
     318 
     319 
     320 
     321 BOOL FindCodeAddr()         //找到调用了IAT中的地址的代码位置
     322 {
     323     PIMAGE_DOS_HEADER pDosHead = (PIMAGE_DOS_HEADER)g_pFileSrc;
     324     PIMAGE_NT_HEADERS pNtHead = (PIMAGE_NT_HEADERS)((DWORD)pDosHead + pDosHead->e_lfanew);
     325     if (!pNtHead->OptionalHeader.DataDirectory[1].VirtualAddress)
     326     {
     327         return false;
     328     }
     329 
     330     PIMAGE_IMPORT_DESCRIPTOR pImpotrList = (PIMAGE_IMPORT_DESCRIPTOR)RVAtoFA(pNtHead->OptionalHeader.DataDirectory[1].VirtualAddress);  //IAT
     331     while (pImpotrList->FirstThunk)//获得该程序的IAT地址
     332     {
     333         int i = 0;
     334         while (1)
     335         {
     336             DWORD iIatAddr = *(DWORD*)RVAtoFA(pImpotrList->FirstThunk + i * sizeof(DWORD));
     337             if (!iIatAddr)
     338             {
     339                 break;
     340             }
     341             DWORD dwIatAddr = pImpotrList->FirstThunk + i * sizeof(DWORD);
     342             g_IATaddrList.push_back(dwIatAddr);
     343             i++;
     344         }
     345         pImpotrList++;
     346     }
     347 
     348 
     349     //获取调用这些IAT地址的代码地址
     350     for (int i = 0; i < g_iFileSize - 5; i++)
     351     {
     352         //mov eax
     353         if (g_pFileSrc[i] == 0xA1)
     354         {
     355             DWORD IatAddr = *(DWORD*)(g_pFileSrc + i + 1);
     356             for (int iNum = 0; iNum < g_IATaddrList.size(); iNum++)
     357             {
     358                 if (g_IATaddrList[iNum] == (IatAddr^g_iImageBase))
     359                 {
     360                     IatAddrTab IatInfo;
     361                     IatInfo.dwCallAddr = FAtoRVA(i);
     362                     IatInfo.bType = 0;
     363                     IatInfo.wIndex = iNum;
     364                     IatInfo.dwOldIatAddr = g_IATaddrList[iNum];
     365                     g_tagIAT.push_back(IatInfo);
     366                     i += 4;   //for循环会加1,操作符+地址共5字节
     367                     continue;
     368                 }
     369             }
     370         }
     371 
     372         //mov edx、esp、esi、ecx、ebx、ebp、edi
     373         if (g_pFileSrc[i] == 0x8B && (g_pFileSrc[i + 1] == 0x15 || g_pFileSrc[i + 1] == 0x25 || g_pFileSrc[i + 1] == 0x35 ||
     374             g_pFileSrc[i + 1] == 0x0D || g_pFileSrc[i + 1] == 0x1D || g_pFileSrc[i + 1] == 0x2D || g_pFileSrc[i + 1] == 0x3D))
     375         {
     376             DWORD IatAddr = *(DWORD*)(g_pFileSrc + i + 2);
     377             for (int iNum = 0; iNum < g_IATaddrList.size(); iNum++)
     378             {
     379                 if (g_IATaddrList[iNum] == (IatAddr^g_iImageBase))
     380                 {
     381                     DWORD ddddd = FAtoRVA(i);
     382                     if (g_pFileSrc[i + 1] == 0x15)    //edx
     383                     {
     384                         IatAddrTab IatInfo;
     385                         IatInfo.dwCallAddr = FAtoRVA(i);
     386                         IatInfo.bType = 1;
     387                         IatInfo.wIndex = iNum;
     388                         IatInfo.dwOldIatAddr = g_IATaddrList[iNum];
     389                         g_tagIAT.push_back(IatInfo);
     390                     }
     391                     else if (g_pFileSrc[i + 1] == 0x25)  //esp
     392                     {
     393                         IatAddrTab IatInfo;
     394                         IatInfo.dwCallAddr = FAtoRVA(i);
     395                         IatInfo.bType = 2;
     396                         IatInfo.wIndex = iNum;
     397                         IatInfo.dwOldIatAddr = g_IATaddrList[iNum];
     398                         g_tagIAT.push_back(IatInfo);
     399                     }
     400                     else if (g_pFileSrc[i + 1] == 0x35)        //esi
     401                     {
     402                         IatAddrTab IatInfo;
     403                         IatInfo.dwCallAddr = FAtoRVA(i);
     404                         IatInfo.bType = 3;
     405                         IatInfo.wIndex = iNum;
     406                         IatInfo.dwOldIatAddr = g_IATaddrList[iNum];
     407                         g_tagIAT.push_back(IatInfo);
     408                     }
     409                     else if (g_pFileSrc[i + 1] == 0x0D)        //ecx
     410                     {
     411                         IatAddrTab IatInfo;
     412                         IatInfo.dwCallAddr = FAtoRVA(i);
     413                         IatInfo.bType = 4;
     414                         IatInfo.wIndex = iNum;
     415                         IatInfo.dwOldIatAddr = g_IATaddrList[iNum];
     416                         g_tagIAT.push_back(IatInfo);
     417                     }
     418                     else if (g_pFileSrc[i + 1] == 0x1D)        //ebx
     419                     {
     420                         IatAddrTab IatInfo;
     421                         IatInfo.dwCallAddr = FAtoRVA(i);
     422                         IatInfo.bType = 5;
     423                         IatInfo.wIndex = iNum;
     424                         IatInfo.dwOldIatAddr = g_IATaddrList[iNum];
     425                         g_tagIAT.push_back(IatInfo);
     426                     }
     427                     else if (g_pFileSrc[i + 1] == 0x2D)        //ebp
     428                     {
     429                         IatAddrTab IatInfo;
     430                         IatInfo.dwCallAddr = FAtoRVA(i);
     431                         IatInfo.bType = 6;
     432                         IatInfo.wIndex = iNum;
     433                         IatInfo.dwOldIatAddr = g_IATaddrList[iNum];
     434                         g_tagIAT.push_back(IatInfo);
     435                     }
     436                     else if (g_pFileSrc[i + 1] == 0x3D)        //edi
     437                     {
     438                         IatAddrTab IatInfo;
     439                         IatInfo.dwCallAddr = FAtoRVA(i);
     440                         IatInfo.bType = 7;
     441                         IatInfo.wIndex = iNum;
     442                         IatInfo.dwOldIatAddr = g_IATaddrList[iNum];
     443                         g_tagIAT.push_back(IatInfo);
     444                     }
     445                     i += 5;   //for循环会加1,操作符+地址共6字节
     446                     continue;
     447                 }
     448             }
     449         }
     450 
     451         //call jmp push
     452         if (g_pFileSrc[i] == 0xFF && (g_pFileSrc[i + 1] == 0x15 || g_pFileSrc[i + 1] == 0x25 || g_pFileSrc[i + 1] == 0x35))
     453         {
     454             DWORD IatAddr = *(DWORD*)(g_pFileSrc + i + 2);
     455             for (int iNum = 0; iNum < g_IATaddrList.size(); iNum++)
     456             {
     457                 if (g_IATaddrList[iNum] == (IatAddr^g_iImageBase))
     458                 {
     459                     DWORD ddddd = FAtoRVA(i);
     460                     if (g_pFileSrc[i + 1] == 0x15) //call
     461                     {
     462                         IatAddrTab IatInfo;
     463                         IatInfo.dwCallAddr = FAtoRVA(i);
     464                         IatInfo.bType = 8;
     465                         IatInfo.wIndex = iNum;
     466                         IatInfo.dwOldIatAddr = g_IATaddrList[iNum];
     467                         g_tagIAT.push_back(IatInfo);
     468                     }
     469                     else if (g_pFileSrc[i + 1] == 0x25)  //jmp
     470                     {
     471                         IatAddrTab IatInfo;
     472                         IatInfo.dwCallAddr = FAtoRVA(i);
     473                         IatInfo.bType = 9;
     474                         IatInfo.wIndex = iNum;
     475                         IatInfo.dwOldIatAddr = g_IATaddrList[iNum];
     476                         g_tagIAT.push_back(IatInfo);
     477                     }
     478                     else if (g_pFileSrc[i + 1] == 0x35)        //push
     479                     {
     480                         IatAddrTab IatInfo;
     481                         IatInfo.dwCallAddr = FAtoRVA(i);
     482                         IatInfo.bType = 10;
     483                         IatInfo.wIndex = iNum;
     484                         IatInfo.dwOldIatAddr = g_IATaddrList[iNum];
     485                         g_tagIAT.push_back(IatInfo);
     486                     }
     487                     i += 5;   //for循环会加1,操作符+地址共6字节
     488                     continue;
     489                 }
     490             }
     491         }
     492     }
     493 
     494     return true;
     495 }
     496 
     497 
     498 bool SaveDll() //保存DLL相关数据
     499 {
     500     PIMAGE_DOS_HEADER pDosHead = (PIMAGE_DOS_HEADER)g_pFileSrc;
     501     PIMAGE_NT_HEADERS pNtHead = (PIMAGE_NT_HEADERS)((DWORD)pDosHead + pDosHead->e_lfanew);
     502     DWORD dwImportRVA = pNtHead->OptionalHeader.DataDirectory[1].VirtualAddress;
     503     PIMAGE_IMPORT_DESCRIPTOR pImport = (PIMAGE_IMPORT_DESCRIPTOR)RVAtoFA(dwImportRVA);
     504     while (pImport->FirstThunk)
     505     {
     506         DLLFuncTag tagDllList;//Dll信息结构
     507 
     508         char *szDllName = (char*)RVAtoFA(pImport->Name);
     509         int iDllNameLen = strlen(szDllName) + 1;
     510         char *szNewDllName = (char*)malloc(iDllNameLen);
     511         memcpy(szNewDllName, szDllName, iDllNameLen);
     512 
     513         tagDllList.szDllName = szNewDllName;
     514         tagDllList.bDllNameLenth = iDllNameLen;
     515 
     516         PIMAGE_THUNK_DATA pIAT = (PIMAGE_THUNK_DATA)RVAtoFA(pImport->FirstThunk);
     517         while (pIAT->u1.Function)
     518         {
     519             FuncTag tagFuncInfo;//函数信息结构
     520             DWORD dwFuncAddr = pIAT->u1.Function;
     521             if (dwFuncAddr & 0x80000000)
     522             {
     523                 tagDllList.bTab = 0;//按序号导入
     524                 tagFuncInfo.iFuncNameLenth = 4;
     525                 tagFuncInfo.szFuncName = (char*)(dwFuncAddr ^ 0x80000000);
     526                 tagDllList.vFuncNAMEorNo.push_back(tagFuncInfo);
     527             }
     528             else
     529             {
     530                 tagDllList.bTab = 1;//按名称导入
     531                 PIMAGE_IMPORT_BY_NAME pFunc = (PIMAGE_IMPORT_BY_NAME)RVAtoFA(pIAT->u1.Function);
     532                 int iFuncNameLen = strlen(pFunc->Name) + 1;
     533                 char *szFuncName = (char*)malloc(iFuncNameLen);
     534                 memcpy(szFuncName, pFunc->Name, iFuncNameLen);
     535                 tagFuncInfo.iFuncNameLenth = iFuncNameLen;
     536                 tagFuncInfo.szFuncName = szFuncName;
     537                 tagDllList.vFuncNAMEorNo.push_back(tagFuncInfo);
     538             }
     539             pIAT++;
     540         }
     541         tagDllList.wFuncNum = tagDllList.vFuncNAMEorNo.size();
     542         g_tagDllFunc.push_back(tagDllList);
     543         pImport++;
     544     }
     545 
     546     //将IAT表信息隐藏(每个DLL只有一个导入函数)
     547     PIMAGE_IMPORT_DESCRIPTOR pImpotrList = (PIMAGE_IMPORT_DESCRIPTOR)RVAtoFA(pNtHead->OptionalHeader.DataDirectory[1].VirtualAddress);
     548     while (pImpotrList->FirstThunk)
     549     {
     550         PIMAGE_THUNK_DATA pIAT = (PIMAGE_THUNK_DATA)RVAtoFA(pImpotrList->FirstThunk);
     551         PIMAGE_THUNK_DATA pINT = (PIMAGE_THUNK_DATA)RVAtoFA(pImpotrList->OriginalFirstThunk);
     552         pIAT++;//保留第一个
     553         pINT++;
     554         while (pIAT->u1.Function)//将IAT清空
     555         {
     556             pIAT->u1.Function = 0;
     557             pIAT++;
     558         }
     559         while (pINT->u1.Function)//将INT清空
     560         {
     561             pINT->u1.Function = 0;
     562             pINT++;
     563         }
     564         pImpotrList++;
     565     }
     566     return true;
     567 }
     568 
     569 
     570 
     571 
     572 bool NewIat()
     573 {
     574     PIMAGE_DOS_HEADER pDosHead = (PIMAGE_DOS_HEADER)g_pFileSrc;
     575     PIMAGE_NT_HEADERS pNtHead = (PIMAGE_NT_HEADERS)((DWORD)pDosHead + pDosHead->e_lfanew);
     576     PIMAGE_SECTION_HEADER pSection = (PIMAGE_SECTION_HEADER)((DWORD)&pNtHead->OptionalHeader + pNtHead->FileHeader.SizeOfOptionalHeader);
     577     for (int i = 0; i < pNtHead->FileHeader.NumberOfSections; i++)
     578     {
     579         //将每个节都改为可写属性,以便在后续修改。
     580         //本来只修改.text节的属性即可,但由于该节的位置不在data数组里面记录,单凭节名判断未必准确,所以将所以节都改为可写-
     581         pSection->Characteristics += 0x80000000;
     582     }
     583     if (!(pNtHead->OptionalHeader.DataDirectory[5].VirtualAddress))//当当前程序没有重定位表
     584     {
     585         PIMAGE_SECTION_HEADER pSection = (PIMAGE_SECTION_HEADER)((DWORD)&pNtHead->OptionalHeader + pNtHead->FileHeader.SizeOfOptionalHeader);
     586         pSection += pNtHead->FileHeader.NumberOfSections - 1;
     587         int iNewSectionFileAddr = pSection->PointerToRawData + pSection->SizeOfRawData;
     588         int iNewSectionFileMapAddr = 0;
     589         if (!(pSection->Misc.VirtualSize % g_iSectionAlignment))
     590         {
     591             iNewSectionFileMapAddr = pSection->VirtualAddress + pSection->Misc.VirtualSize;
     592         }
     593         else
     594         {
     595             iNewSectionFileMapAddr = pSection->VirtualAddress + pSection->Misc.VirtualSize
     596                 + g_iSectionAlignment - (pSection->Misc.VirtualSize % g_iSectionAlignment);
     597         }
     598 
     599         pSection++;
     600         memcpy(pSection->Name, ".KD", 3);
     601         pSection->VirtualAddress = iNewSectionFileMapAddr;
     602         pSection->PointerToRawData = iNewSectionFileAddr;
     603         pSection->Characteristics = (0x20000000 | 0x40000000 | 0x80000000 | 0x40); //节属性 可读可写可执行已被初始化
     604         pNtHead->FileHeader.NumberOfSections += 1;//节表数量+1
     605 
     606 
     607         //将IAT的数据压入新节中数据排列分别为DLL数量(2字节)、DLL名字长度、该
     608         int iAddIatLenth = 0;//已经增加的iat数据长度
     609         //先添加2字节数据说明该程序的DLL数量
     610         g_pFileSrc = (UCHAR*)realloc(g_pFileSrc, g_iFileSize + iAddIatLenth + 1);
     611         byte bDllNum = g_tagDllFunc.size();
     612         memcpy(g_pFileSrc + g_iFileSize + iAddIatLenth, &bDllNum, 1);
     613         iAddIatLenth += 2;
     614         for (int i = 0; i < bDllNum; i++)
     615         {
     616             //添加DLL名长度
     617             int bDllNameLenth = g_tagDllFunc[i].bDllNameLenth;
     618             g_pFileSrc = (UCHAR*)realloc(g_pFileSrc, g_iFileSize + iAddIatLenth + 2);
     619             memcpy(g_pFileSrc + g_iFileSize + iAddIatLenth, &bDllNameLenth, 2);
     620             iAddIatLenth += 2;
     621 
     622             //添加DLL名
     623             g_pFileSrc = (UCHAR*)realloc(g_pFileSrc, g_iFileSize + iAddIatLenth + bDllNameLenth);
     624             memcpy(g_pFileSrc + g_iFileSize + iAddIatLenth, g_tagDllFunc[i].szDllName, bDllNameLenth);
     625             iAddIatLenth += bDllNameLenth;
     626 
     627             //添加该DLL中的导入函数数量  方便后续遍历
     628             g_pFileSrc = (UCHAR*)realloc(g_pFileSrc, g_iFileSize + iAddIatLenth + 4);
     629             memcpy(g_pFileSrc + g_iFileSize + iAddIatLenth, (DWORD*)&g_tagDllFunc[i].wFuncNum, 4);
     630             iAddIatLenth += 4;
     631 
     632             //添加该DLL的导入方式 0为序号1为名称
     633             g_pFileSrc = (UCHAR*)realloc(g_pFileSrc, g_iFileSize + iAddIatLenth + 1);
     634             memcpy(g_pFileSrc + g_iFileSize + iAddIatLenth, (byte*)&g_tagDllFunc[i].bTab, 1);
     635             iAddIatLenth += 1;
     636             for (int j = 0; j < g_tagDllFunc[i].wFuncNum; j++)
     637             {
     638                 //添加函数名或序号
     639                 if (!(g_tagDllFunc[i].bTab)) //序号
     640                 {
     641                     g_pFileSrc = (UCHAR*)realloc(g_pFileSrc, g_iFileSize + iAddIatLenth + 6);//2长度4序号
     642                     memcpy(g_pFileSrc + g_iFileSize + iAddIatLenth, (WORD*)&g_tagDllFunc[i].vFuncNAMEorNo[j].iFuncNameLenth, 2);
     643                     iAddIatLenth += 2;
     644                     memcpy(g_pFileSrc + g_iFileSize + iAddIatLenth, (DWORD*)&g_tagDllFunc[i].vFuncNAMEorNo[j].szFuncName, 4);
     645                     iAddIatLenth += 4;
     646                 }
     647                 else  //名字
     648                 {
     649                     int iFuncNameLenth = g_tagDllFunc[i].vFuncNAMEorNo[j].iFuncNameLenth;//长度
     650                     g_pFileSrc = (UCHAR*)realloc(g_pFileSrc, g_iFileSize + iAddIatLenth + 2 + iFuncNameLenth);//前2字节存放长度 后面为函数名称
     651                     memcpy(g_pFileSrc + g_iFileSize + iAddIatLenth, (WORD*)&iFuncNameLenth, 2);
     652                     iAddIatLenth += 2;
     653                     memcpy(g_pFileSrc + g_iFileSize + iAddIatLenth, g_tagDllFunc[i].vFuncNAMEorNo[j].szFuncName, iFuncNameLenth);
     654                     iAddIatLenth += iFuncNameLenth;
     655                 }
     656             }
     657         }
     658 
     659         //获取新的OEP并修改旧的OEP
     660         g_iNewOEP = iNewSectionFileMapAddr + iAddIatLenth;//新节的
     661         pDosHead = (PIMAGE_DOS_HEADER)g_pFileSrc;
     662         pNtHead = (PIMAGE_NT_HEADERS)((DWORD)pDosHead + pDosHead->e_lfanew);
     663         pNtHead->OptionalHeader.AddressOfEntryPoint = g_iNewOEP;
     664 
     665         JitRuntime        _x86RunTimeObject;
     666         X86Assembler    a(&_x86RunTimeObject);
     667 
     668         //当程序没有重定位表时,根据call 0000 0000来获得进程基址,有重定位表时则根据重定位表
     669         char szGetOEP[] = { 0xE8, 0x00, 0x00, 0x00, 0x00 }; //同理jit.call(0x00000000);
     670         a.pop(eax);
     671         a.sub(eax, 5);//此时得到oep所在的地址 oep距离基址隔着
     672         a.sub(eax, g_iNewOEP);//OEP所在的基址-偏移  得到基址
     673         a.mov(ebp, eax);    //保存进程基址到ebp
     674         a.add(eax, g_iOldOEP);
     675         a.jmp(eax);
     676 
     677         PVOID szJit = a.make();
     678         int iJitLenth = a.getCodeSize() + 5; //包括e8 0000 0000;
     679 
     680         g_pFileSrc = (UCHAR*)realloc(g_pFileSrc, g_iFileSize + iAddIatLenth + iJitLenth);
     681         memcpy(g_pFileSrc + g_iFileSize + iAddIatLenth, szGetOEP, 5);
     682         memcpy(g_pFileSrc + g_iFileSize + iAddIatLenth + 5, szJit, iJitLenth);
     683 
     684         int iAddSrcLen = iAddIatLenth + iJitLenth;//一共增加的代码
     685         //完善节长度等数据  保守起见重新获取节表信息
     686         pDosHead = (PIMAGE_DOS_HEADER)g_pFileSrc;
     687         pNtHead = (PIMAGE_NT_HEADERS)((DWORD)pDosHead + pDosHead->e_lfanew);
     688         pSection = (PIMAGE_SECTION_HEADER)((DWORD)&pNtHead->OptionalHeader + pNtHead->FileHeader.SizeOfOptionalHeader);
     689         pSection += pNtHead->FileHeader.NumberOfSections - 1;
     690         if (!(iAddSrcLen%g_iFileAlignment))
     691         {
     692             pSection->SizeOfRawData = iAddSrcLen;
     693         }
     694         else
     695         {
     696             pSection->SizeOfRawData = iAddSrcLen + g_iFileAlignment - (iAddSrcLen%g_iFileAlignment);
     697         }
     698         if (!(iAddSrcLen%g_iSectionAlignment))
     699         {
     700             pSection->Misc.VirtualSize = iAddSrcLen;
     701         }
     702         else
     703         {
     704             pSection->Misc.VirtualSize = iAddSrcLen + g_iSectionAlignment - (iAddSrcLen%g_iSectionAlignment);
     705         }
     706         pNtHead->OptionalHeader.SizeOfImage += pSection->Misc.VirtualSize;
     707 
     708         if (iAddSrcLen != pSection->SizeOfRawData)//当新增长度与对齐后的节长度不相等时,将其补全
     709         {
     710             int iLenth = pSection->SizeOfRawData;//先保存,以免扩容后原地址被回收
     711             //g_pFileSrc = (UCHAR*)realloc(g_pFileSrc, g_iFileSize + iLenth);
     712             UCHAR *uuu = (UCHAR*)malloc(g_iFileSize + iAddSrcLen);
     713             memcpy(uuu, g_pFileSrc, g_iFileSize + iAddSrcLen);
     714             g_pFileSrc = (UCHAR*)malloc(g_iFileSize + iLenth);
     715             memcpy(g_pFileSrc, uuu, g_iFileSize + iAddSrcLen);
     716             memset(g_pFileSrc + g_iFileSize + iAddSrcLen, 0, iLenth - iAddSrcLen);
     717         }
     718         g_iFileSize += pSection->SizeOfRawData;
     719     }
     720 
     721 
     722 
     723     /////////////////////////////////////////////////////////////////////////////
     724     //当有重定位表时,先保存相关数据,删除重定位表,新增节,再在后面还原重定位表
     725     else
     726     {
     727         //把重定位表数据移动到新节当中
     728         //获取位置和长度
     729         int iRelocationAddr = pNtHead->OptionalHeader.DataDirectory[5].VirtualAddress;
     730         int iRelocationLenth = pNtHead->OptionalHeader.DataDirectory[5].Size;//数据长度
     731         char *szR_Src = (char*)malloc(iRelocationLenth);
     732         memcpy(szR_Src, (char*)RVAtoFA(iRelocationAddr), iRelocationLenth);
     733         
     734         PIMAGE_SECTION_HEADER pSection = (PIMAGE_SECTION_HEADER)((DWORD)&pNtHead->OptionalHeader + pNtHead->FileHeader.SizeOfOptionalHeader);
     735         char szR_Name[8] = { 0 };
     736         int iR_MapLenth = 0;//节中映射长度
     737         int iR_FileLenth = 0;//节中文件长度
     738         while (1)
     739         {
     740             if (pSection->VirtualAddress == iRelocationAddr) //定位到重定位表节表
     741             {
     742                 strcpy(szR_Name, (char*)pSection->Name);
     743                 iR_MapLenth = pSection->Misc.VirtualSize;
     744                 iR_FileLenth = pSection->SizeOfRawData;
     745                 break;
     746             }
     747             pSection++;
     748         }
     749 
     750         //删除重定位表相关信息
     751         memset(g_pFileSrc + g_iFileSize - iR_FileLenth, 0, iR_FileLenth);//把重定位表数据用0覆盖
     752         memset(pSection, 0, sizeof(IMAGE_SECTION_HEADER));
     753         pNtHead->FileHeader.NumberOfSections--;
     754         //调整文件内存大小
     755         int iAlignmentSize = iR_MapLenth % g_iSectionAlignment;
     756         if (!iAlignmentSize)
     757         {
     758             pNtHead->OptionalHeader.SizeOfImage -= iR_MapLenth;        //调整文件内存大小
     759         }
     760         else
     761         {
     762             pNtHead->OptionalHeader.SizeOfImage =
     763                 pNtHead->OptionalHeader.SizeOfImage
     764                 - (iR_MapLenth - iAlignmentSize + g_iSectionAlignment);
     765         }
     766         g_iFileSize -= iR_FileLenth;
     767 
     768 
     769         //新增节
     770         pSection = (PIMAGE_SECTION_HEADER)((DWORD)&pNtHead->OptionalHeader + pNtHead->FileHeader.SizeOfOptionalHeader);
     771         pSection += pNtHead->FileHeader.NumberOfSections - 1;
     772         int iNewSectionFileAddr = pSection->PointerToRawData + pSection->SizeOfRawData;
     773         int iNewSectionFileMapAddr = 0;
     774         if (!(pSection->Misc.VirtualSize % g_iSectionAlignment))
     775         {
     776             iNewSectionFileMapAddr = pSection->VirtualAddress + pSection->Misc.VirtualSize;
     777         }
     778         else
     779         {
     780             iNewSectionFileMapAddr = pSection->VirtualAddress + pSection->Misc.VirtualSize
     781                 + g_iSectionAlignment - (pSection->Misc.VirtualSize % g_iSectionAlignment);
     782         }
     783 
     784         pSection++;
     785         memcpy(pSection->Name, ".KD", 3);
     786         pSection->VirtualAddress = iNewSectionFileMapAddr;
     787         pSection->PointerToRawData = iNewSectionFileAddr;
     788         pSection->Characteristics = (0x20000000 | 0x40000000 | 0x80000000 | 0x40); //节属性 可读可写可执行已被初始化
     789         pNtHead->FileHeader.NumberOfSections += 1;//节表数量+1
     790 
     791 
     792         //将IAT的数据压入新节中数据排列分别为DLL数量(2字节)、DLL名字长度、该
     793         int iAddIatLenth = 0;//已经增加的iat数据长度
     794         //先添加1字节数据说明该程序的DLL数量
     795         g_pFileSrc = (UCHAR*)realloc(g_pFileSrc, g_iFileSize + iAddIatLenth + 1);
     796         byte bDllNum = g_tagDllFunc.size();
     797         memcpy(g_pFileSrc + g_iFileSize + iAddIatLenth, &bDllNum, 1);
     798         iAddIatLenth += 1;
     799         for (int i = 0; i < bDllNum; i++)
     800         {
     801             //添加DLL名长度
     802             byte bDllNameLenth = g_tagDllFunc[i].bDllNameLenth;
     803             g_pFileSrc = (UCHAR*)realloc(g_pFileSrc, g_iFileSize + iAddIatLenth + 1);
     804             memcpy(g_pFileSrc + g_iFileSize + iAddIatLenth, &bDllNameLenth, 1);
     805             iAddIatLenth += 1;
     806 
     807             //添加DLL名
     808             g_pFileSrc = (UCHAR*)realloc(g_pFileSrc, g_iFileSize + iAddIatLenth + bDllNameLenth);
     809             memcpy(g_pFileSrc + g_iFileSize + iAddIatLenth, g_tagDllFunc[i].szDllName, bDllNameLenth);
     810             iAddIatLenth += bDllNameLenth;
     811 
     812             //添加该DLL中的导入函数数量  方便后续遍历
     813             g_pFileSrc = (UCHAR*)realloc(g_pFileSrc, g_iFileSize + iAddIatLenth + 2);
     814             memcpy(g_pFileSrc + g_iFileSize + iAddIatLenth, (DWORD*)&g_tagDllFunc[i].wFuncNum, 2);
     815             iAddIatLenth += 2;
     816 
     817             //添加该DLL的导入方式 0为序号1为名称
     818             g_pFileSrc = (UCHAR*)realloc(g_pFileSrc, g_iFileSize + iAddIatLenth + 1);
     819             memcpy(g_pFileSrc + g_iFileSize + iAddIatLenth, (byte*)&g_tagDllFunc[i].bTab, 1);
     820             iAddIatLenth += 1;
     821             for (int j = 0; j < g_tagDllFunc[i].wFuncNum; j++)
     822             {
     823                 //添加函数名或序号
     824                 if (!(g_tagDllFunc[i].bTab)) //序号
     825                 {
     826                     g_pFileSrc = (UCHAR*)realloc(g_pFileSrc, g_iFileSize + iAddIatLenth + 5);//1长度4序号
     827                     memcpy(g_pFileSrc + g_iFileSize + iAddIatLenth, (BYTE*)&g_tagDllFunc[i].vFuncNAMEorNo[j].iFuncNameLenth, 1);
     828                     iAddIatLenth += 1;
     829                     memcpy(g_pFileSrc + g_iFileSize + iAddIatLenth, (DWORD*)&g_tagDllFunc[i].vFuncNAMEorNo[j].szFuncName, 4);
     830                     iAddIatLenth += 4;
     831                 }
     832                 else  //名字
     833                 {
     834                     int iFuncNameLenth = g_tagDllFunc[i].vFuncNAMEorNo[j].iFuncNameLenth;//长度
     835                     g_pFileSrc = (UCHAR*)realloc(g_pFileSrc, g_iFileSize + iAddIatLenth + 1 + iFuncNameLenth);//前2字节存放长度 后面为函数名称
     836                     memcpy(g_pFileSrc + g_iFileSize + iAddIatLenth, (BYTE*)&iFuncNameLenth, 1);
     837                     iAddIatLenth += 1;
     838                     memcpy(g_pFileSrc + g_iFileSize + iAddIatLenth, g_tagDllFunc[i].vFuncNAMEorNo[j].szFuncName, iFuncNameLenth);
     839                     iAddIatLenth += iFuncNameLenth;
     840                 }
     841             }
     842         }
     843 
     844         //存放加载的函数地址表的RVA
     845         int iLoadAddressTabRVA = iNewSectionFileMapAddr + iAddIatLenth;
     846         int iLoadIatLenth = g_IATaddrList.size() * 4;//用于存放加载的函数地址表长度  此处多4字节来存放基址
     847 
     848 
     849         //获取新的OEP并修改旧的OEP
     850         g_iNewOEP = iNewSectionFileMapAddr + iAddIatLenth + iLoadIatLenth;
     851         pDosHead = (PIMAGE_DOS_HEADER)g_pFileSrc;
     852         pNtHead = (PIMAGE_NT_HEADERS)((DWORD)pDosHead + pDosHead->e_lfanew);
     853          pNtHead->OptionalHeader.AddressOfEntryPoint = g_iNewOEP;
     854 
     855         JitRuntime        _x86RunTimeObject;
     856         X86Assembler    a(&_x86RunTimeObject);
     857 
     858         //跳转标记
     859         Label LoadDllBegin = a.newLabel();
     860         Label LoadDllOver = a.newLabel();
     861         
     862         Label NameExport = a.newLabel();
     863         Label NameExportBegin = a.newLabel();
     864         Label NameExportOver = a.newLabel();
     865         Label NoExportBegin = a.newLabel();
     866         Label NoExportOver = a.newLabel();
     867 
     868         //test
     869         Label lTest = a.newLabel();
     870         
     871         //当有重定位表时,将NewOEP+1新增到重定位项中,重定位后的地址-OldOEP即可得到新的基址
     872         //这里push g_iOldOEP + g_iImageBase而不是g_iImageBase(直接得到新基址 不用再-旧OEP),是因为push完还要ret到旧OEP
     873         //执行完这段后,栈上是旧OEP的地址,ebx是程序基址
     874         a.push(g_iOldOEP + g_iImageBase);
     875         a.mov(ebx, dword_ptr(esp));
     876         a.sub(ebx, g_iOldOEP);
     877         
     878         /*a.call(lTest);
     879         a.bind(lTest);
     880         a.pop(eax);*/
     881 
     882         a.pusha();
     883         a.push(ebx);//将程序基址保存到栈上
     884         a.sub(esp, 0x8);
     885         a.mov(ebp, esp); //ebp从上往下分别是LoadLibraryA函数地址、GetProcAddress函数地址和程序基址  ebp-4为Dll基址 -8为填充函数加载地址起始地址
     886         a.sub(esp, 0x8);
     887         
     888         GetKernel32Base(a);
     889         a.mov(edi, eax);//edi为所遍历到的DLL基址
     890 
     891         //计算函数地址
     892         GetLoadLibraryAAddr(a);
     893         a.mov(dword_ptr(ebp, 0), eax);//保存LoadLibraryA的值到栈上
     894         GetGetProcAddressAddr(a);
     895         a.mov(dword_ptr(ebp, 4), eax);//保存GetProcAddress的值到栈上
     896         a.mov(eax, iLoadAddressTabRVA);
     897         a.add(eax, dword_ptr(ebp, 8));//填充函数地址RVA+程序基址
     898         a.mov(dword_ptr(ebp, -8), eax);//放到ebp-8的地址上
     899 
     900 
     901         //开始遍历IAT数据,填充函数加载地址表
     902         a.mov(esi, iNewSectionFileMapAddr);
     903         a.add(esi, dword_ptr(ebp, 8));//esi为IAT数据起点
     904         a.mov(ebx, 1);//以ebx开始遍历  达到长度 退出
     905 
     906 
     907         //加载DLL
     908         a.bind(LoadDllBegin);
     909         a.cmp(ebx, iAddIatLenth);//如果遍历长度大于等于IAT数据长度
     910         a.jnl(LoadDllOver);
     911         a.movzx(ecx, byte_ptr(esi, ebx));//取得DLL名长度
     912         a.add(ebx, 1);//+Dll名长度的变量1
     913         a.lea(eax, dword_ptr(esi,ebx));//获得函数名地址
     914         a.push(eax);
     915         a.add(ebx, ecx);//+DLL名长度
     916         a.mov(eax, dword_ptr(ebp));//获得loadlibrary地址
     917         a.call(eax);
     918         a.mov(dword_ptr(ebp,-4),eax);//ebp为load.. +4为get.. +8为程序基址  -4为当前Dll基址 -8为填充函数加载地址位置
     919         a.movzx(edi, word_ptr(esi, ebx));//取出该DLL导出函数数量
     920         a.add(ebx, 2);
     921         a.movzx(edx, byte_ptr(esi, ebx));//取出导出方式
     922         a.add(ebx, 1);
     923         a.cmp(edx, 1);//为1时,名称导出
     924         a.je(NameExportBegin);
     925 
     926 
     927         //序号导出
     928         a.bind(NoExportBegin);//序号导出循环起点
     929         a.cmp(edi, 0);
     930         a.je(NoExportOver);
     931         a.add(ebx, 1);
     932         a.mov(eax, dword_ptr(esi, ebx));//取得序号
     933         a.add(ebx, 4);
     934         a.push(eax);
     935         a.push(dword_ptr(ebp, -4));
     936         a.mov(eax, dword_ptr(ebp, 4));//获得GetProcAddress
     937         a.call(eax);
     938         a.mov(edx, dword_ptr(ebp, -8));//取得装载函数表
     939         a.mov(dword_ptr(edx), eax);
     940         a.add(dword_ptr(ebp, -8), 4);//装载函数表RVA+4
     941         a.sub(edi, 1);
     942         a.jmp(NoExportBegin);
     943         a.bind(NoExportOver);//序号导出循环终点
     944         a.jmp(LoadDllBegin); //重新加载新DLL
     945 
     946         //名称导出
     947         a.bind(NameExportBegin);//名称导出循环起点
     948         a.cmp(edi, 0);
     949         a.je(NameExportOver);
     950         a.movzx(ecx, byte_ptr(esi, ebx));//取得名称长度
     951         a.add(ebx, 1);
     952         a.lea(eax, dword_ptr(esi, ebx));//名称地址
     953         a.push(eax);
     954         a.add(ebx, ecx);
     955         a.push(dword_ptr(ebp, -4));
     956         a.mov(eax, dword_ptr(ebp, 4));
     957         a.call(eax);
     958         a.mov(edx, dword_ptr(ebp, -8));//取得装载函数表
     959         a.mov(dword_ptr(edx), eax);
     960         a.add(dword_ptr(ebp, -8), 4);//装载函数表RVA+4
     961         a.sub(edi, 1);
     962         a.jmp(NameExportBegin);
     963         a.bind(NameExportOver);//名称导出循环终点
     964         a.jmp(LoadDllBegin); //重新加载新DLL
     965         
     966 
     967         
     968         ///////////开始构造替换调用代码的shellcode//////////////
     969         //注意esp为当前操作的栈顶  ebp+8为程序所在基址
     970         int iNewJitBeginAddrRva = iNewSectionFileMapAddr + iAddIatLenth + iLoadIatLenth; //替换的shellcode开始的地址
     971         int iNewJitLenth = a.getCodeSize();
     972         for (int i = 0; i < g_tagIAT.size(); i++)
     973         {
     974             if (g_tagIAT[i].bType == 0)    //EAX
     975             {
     976                 g_tagIAT[i].dwNewIatAddr = iNewSectionFileMapAddr + iAddIatLenth + g_tagIAT[i].wIndex * 4;
     977                 a.push(ebx);
     978                 a.push(ebx);
     979                 a.push(ebx);
     980                 a.push(esi);
     981                 a.mov(ebx, (int)g_tagIAT[i].dwCallAddr + 5);
     982                 a.mov(esi, g_iImageBase);//程序基址 后续会将这个位置添加到重定位块处,运行时即变为程序基址了
     983                 g_tagIAT[i].dwRelocAddr = iNewJitBeginAddrRva + a.getCodeSize() - 4;//shellcode开始的位置+当前jit长度 再往回4字节  即为存放基址的位置
     984                 a.lea(ebx, dword_ptr(ebx, esi));
     985                 a.mov(dword_ptr(esp, 0xC), ebx);//当前指令所在RVA+5+程序基址 =返回地址
     986                 a.mov(ebx, (int)g_tagIAT[i].dwNewIatAddr);
     987                 a.lea(ebx, dword_ptr(ebx, esi));
     988                 a.mov(ebx, dword_ptr(ebx));
     989                 a.mov(dword_ptr(esp, 0x8), ebx);//代替原函数地址的地址
     990                 a.pop(esi);
     991                 a.pop(ebx);
     992                 a.pop(eax);
     993                 a.ret();
     994                 g_tagIAT[i].dwJmpAddr = iNewJitBeginAddrRva + iNewJitLenth;
     995                 iNewJitLenth = a.getCodeSize();
     996             }
     997             else if (g_tagIAT[i].bType == 1) //EDX
     998             {
     999                 g_tagIAT[i].dwNewIatAddr = iNewSectionFileMapAddr + iAddIatLenth + g_tagIAT[i].wIndex * 4;
    1000                 a.push(ebx);
    1001                 a.push(ebx);
    1002                 a.push(ebx);
    1003                 a.push(esi);
    1004                 a.mov(ebx, (int)g_tagIAT[i].dwCallAddr + 6);
    1005                 a.mov(esi, g_iImageBase);//程序基址 后续会将这个位置添加到重定位块处,运行时即变为程序基址了
    1006                 g_tagIAT[i].dwRelocAddr = iNewJitBeginAddrRva + a.getCodeSize() - 4;//shellcode开始的位置+当前jit长度 再往回4字节  即为存放基址的位置
    1007                 a.lea(ebx, dword_ptr(ebx, esi));
    1008                 a.mov(dword_ptr(esp, 0xC), ebx);//当前指令所在RVA+5+程序基址 =返回地址
    1009                 a.mov(ebx, (int)g_tagIAT[i].dwNewIatAddr);
    1010                 a.lea(ebx, dword_ptr(ebx, esi));
    1011                 a.mov(ebx, dword_ptr(ebx));
    1012                 a.mov(dword_ptr(esp, 0x8), ebx);//代替原函数地址的地址
    1013                 a.pop(esi);
    1014                 a.pop(ebx);
    1015                 a.pop(edx);
    1016                 a.ret();
    1017                 g_tagIAT[i].dwJmpAddr = iNewJitBeginAddrRva + iNewJitLenth;
    1018                 iNewJitLenth = a.getCodeSize();
    1019             }
    1020             else if (g_tagIAT[i].bType == 2)    //ESP
    1021             {
    1022                 g_tagIAT[i].dwNewIatAddr = iNewSectionFileMapAddr + iAddIatLenth + g_tagIAT[i].wIndex * 4;
    1023                 a.push(ebx);
    1024                 a.push(ebx);
    1025                 a.push(ebx);
    1026                 a.push(esi);
    1027                 a.mov(ebx, (int)g_tagIAT[i].dwCallAddr + 6);
    1028                 a.mov(esi, g_iImageBase);//程序基址 后续会将这个位置添加到重定位块处,运行时即变为程序基址了
    1029                 g_tagIAT[i].dwRelocAddr = iNewJitBeginAddrRva + a.getCodeSize() - 4;//shellcode开始的位置+当前jit长度 再往回4字节  即为存放基址的位置
    1030                 a.lea(ebx, dword_ptr(ebx, esi));
    1031                 a.mov(dword_ptr(esp, 0xC), ebx);//当前指令所在RVA+6+程序基址 =返回地址
    1032                 a.mov(ebx, (int)g_tagIAT[i].dwNewIatAddr);
    1033                 a.lea(ebx, dword_ptr(ebx, esi));
    1034                 a.mov(ebx, dword_ptr(ebx));
    1035                 a.mov(dword_ptr(esp, 0x8), ebx);//代替原函数地址的地址
    1036                 a.pop(esi);
    1037                 a.pop(ebx);
    1038                 a.pop(esp);
    1039                 a.ret();
    1040                 g_tagIAT[i].dwJmpAddr = iNewJitBeginAddrRva + iNewJitLenth;
    1041                 iNewJitLenth = a.getCodeSize();
    1042             }
    1043             else if (g_tagIAT[i].bType == 3)    //ESI
    1044             {
    1045                 g_tagIAT[i].dwNewIatAddr = iNewSectionFileMapAddr + iAddIatLenth + g_tagIAT[i].wIndex * 4;
    1046                 a.push(ebx);
    1047                 a.push(ebx);
    1048                 a.push(ebx);
    1049                 a.push(esi);
    1050                 a.mov(ebx, (int)g_tagIAT[i].dwNewIatAddr);
    1051                 a.mov(esi, g_iImageBase);//程序基址 后续会将这个位置添加到重定位块处,运行时即变为程序基址了
    1052                 g_tagIAT[i].dwRelocAddr = iNewJitBeginAddrRva + a.getCodeSize() - 4;//shellcode开始的位置+当前jit长度 再往回4字节  即为存放基址的位置
    1053                 a.lea(ebx, dword_ptr(ebx, esi));
    1054                 a.mov(ebx, dword_ptr(ebx));
    1055                 a.mov(dword_ptr(esp, 0x8), ebx);//代替原函数地址的地址
    1056                 a.mov(ebx, (int)g_tagIAT[i].dwCallAddr + 6);
    1057                 a.lea(ebx, dword_ptr(ebx, esi));
    1058                 a.mov(dword_ptr(esp, 0xC), ebx);//当前指令所在RVA+6+程序基址 =返回地址
    1059                 a.pop(esi);
    1060                 a.pop(ebx);
    1061                 a.pop(esi);
    1062                 a.ret();
    1063                 g_tagIAT[i].dwJmpAddr = iNewJitBeginAddrRva + iNewJitLenth;
    1064                 iNewJitLenth = a.getCodeSize();
    1065             }
    1066             else if (g_tagIAT[i].bType == 4)    //ECX
    1067             {
    1068                 g_tagIAT[i].dwNewIatAddr = iNewSectionFileMapAddr + iAddIatLenth + g_tagIAT[i].wIndex * 4;
    1069                 a.push(ebx);
    1070                 a.push(ebx);
    1071                 a.push(ebx);
    1072                 a.push(esi);
    1073                 a.mov(ebx, (int)g_tagIAT[i].dwCallAddr + 6);
    1074                 a.mov(esi, g_iImageBase);//程序基址 后续会将这个位置添加到重定位块处,运行时即变为程序基址了
    1075                 g_tagIAT[i].dwRelocAddr = iNewJitBeginAddrRva + a.getCodeSize() - 4;//shellcode开始的位置+当前jit长度 再往回4字节  即为存放基址的位置
    1076                 a.lea(ebx, dword_ptr(ebx, esi));
    1077                 a.mov(dword_ptr(esp, 0xC), ebx);//当前指令所在RVA+6+程序基址 =返回地址
    1078                 a.mov(ebx, (int)g_tagIAT[i].dwNewIatAddr);
    1079                 a.lea(ebx, dword_ptr(ebx, esi));
    1080                 a.mov(ebx, dword_ptr(ebx));
    1081                 a.mov(dword_ptr(esp, 0x8), ebx);//代替原函数地址的地址
    1082                 a.pop(esi);
    1083                 a.pop(ebx);
    1084                 a.pop(ecx);
    1085                 a.ret();
    1086                 g_tagIAT[i].dwJmpAddr = iNewJitBeginAddrRva + iNewJitLenth;
    1087                 iNewJitLenth = a.getCodeSize();
    1088             }
    1089             else if (g_tagIAT[i].bType == 5)    //EBX
    1090             {
    1091                 g_tagIAT[i].dwNewIatAddr = iNewSectionFileMapAddr + iAddIatLenth + g_tagIAT[i].wIndex * 4;
    1092                 a.push(ebx);
    1093                 a.push(ebx);
    1094                 a.push(ebx);
    1095                 a.push(esi);
    1096                 a.mov(ebx, (int)g_tagIAT[i].dwCallAddr + 6);
    1097                 a.mov(esi, g_iImageBase);//程序基址 后续会将这个位置添加到重定位块处,运行时即变为程序基址了
    1098                 g_tagIAT[i].dwRelocAddr = iNewJitBeginAddrRva + a.getCodeSize() - 4;//shellcode开始的位置+当前jit长度 再往回4字节  即为存放基址的位置
    1099                 a.lea(ebx, dword_ptr(ebx, esi));
    1100                 a.mov(dword_ptr(esp, 0xC), ebx);//当前指令所在RVA+6+程序基址 =返回地址
    1101                 a.mov(ebx, (int)g_tagIAT[i].dwNewIatAddr);
    1102                 a.lea(ebx, dword_ptr(ebx, esi));
    1103                 a.mov(ebx, dword_ptr(ebx));
    1104                 a.mov(dword_ptr(esp, 0x8), ebx);//代替原函数地址的地址
    1105                 a.pop(esi);
    1106                 a.pop(ebx);
    1107                 a.pop(ebx);
    1108                 a.ret();
    1109                 g_tagIAT[i].dwJmpAddr = iNewJitBeginAddrRva + iNewJitLenth;
    1110                 iNewJitLenth = a.getCodeSize();
    1111             }
    1112             else if (g_tagIAT[i].bType == 6)    //EBP
    1113             {
    1114                 g_tagIAT[i].dwNewIatAddr = iNewSectionFileMapAddr + iAddIatLenth + g_tagIAT[i].wIndex * 4;
    1115                 a.push(ebx);
    1116                 a.push(ebx);
    1117                 a.push(ebx);
    1118                 a.push(esi);
    1119                 a.mov(ebx, (int)g_tagIAT[i].dwCallAddr + 6);
    1120                 a.mov(esi, g_iImageBase);//程序基址 后续会将这个位置添加到重定位块处,运行时即变为程序基址了
    1121                 g_tagIAT[i].dwRelocAddr = iNewJitBeginAddrRva + a.getCodeSize() - 4;//shellcode开始的位置+当前jit长度 再往回4字节  即为存放基址的位置
    1122                 a.lea(ebx, dword_ptr(ebx, esi));
    1123                 a.mov(dword_ptr(esp, 0xC), ebx);//当前指令所在RVA+6+程序基址 =返回地址
    1124                 a.mov(ebx, (int)g_tagIAT[i].dwNewIatAddr);
    1125                 a.lea(ebx, dword_ptr(ebx, esi));
    1126                 a.mov(ebx, dword_ptr(ebx));
    1127                 a.mov(dword_ptr(esp, 0x8), ebx);//代替原函数地址的地址
    1128                 a.pop(esi);
    1129                 a.pop(ebx);
    1130                 a.pop(ebp);
    1131                 a.ret();
    1132                 g_tagIAT[i].dwJmpAddr = iNewJitBeginAddrRva + iNewJitLenth;
    1133                 iNewJitLenth = a.getCodeSize();
    1134             }
    1135             else if (g_tagIAT[i].bType == 7)    //EDI
    1136             {
    1137                 g_tagIAT[i].dwNewIatAddr = iNewSectionFileMapAddr + iAddIatLenth + g_tagIAT[i].wIndex * 4;
    1138                 a.push(ebx);
    1139                 a.push(ebx);
    1140                 a.push(ebx);
    1141                 a.push(esi);
    1142                 a.mov(ebx, (int)g_tagIAT[i].dwCallAddr + 6);
    1143                 a.mov(esi, g_iImageBase);//程序基址 后续会将这个位置添加到重定位块处,运行时即变为程序基址了
    1144                 g_tagIAT[i].dwRelocAddr = iNewJitBeginAddrRva + a.getCodeSize() - 4;//shellcode开始的位置+当前jit长度 再往回4字节  即为存放基址的位置
    1145                 a.lea(ebx, dword_ptr(ebx, esi));
    1146                 a.mov(dword_ptr(esp, 0xC), ebx);//当前指令所在RVA+6+程序基址 =返回地址
    1147                 a.mov(ebx, (int)g_tagIAT[i].dwNewIatAddr);
    1148                 a.lea(ebx, dword_ptr(ebx, esi));
    1149                 a.mov(ebx, dword_ptr(ebx));
    1150                 a.mov(dword_ptr(esp, 0x8), ebx);//代替原函数地址的地址
    1151                 a.pop(esi);
    1152                 a.pop(ebx);
    1153                 a.pop(edi);
    1154                 a.ret();
    1155                 g_tagIAT[i].dwJmpAddr = iNewJitBeginAddrRva + iNewJitLenth;
    1156                 iNewJitLenth = a.getCodeSize();
    1157             }
    1158             else if (g_tagIAT[i].bType == 8)    //Call
    1159             {
    1160                 g_tagIAT[i].dwNewIatAddr = iNewSectionFileMapAddr + iAddIatLenth + g_tagIAT[i].wIndex * 4;
    1161                 a.push(ebx);
    1162                 a.push(ebx);
    1163                 a.push(ebx);
    1164                 a.push(esi);
    1165                 a.mov(ebx, (int)g_tagIAT[i].dwNewIatAddr);
    1166                 a.mov(esi, g_iImageBase);//程序基址 后续会将这个位置添加到重定位块处,运行时即变为程序基址了
    1167                 g_tagIAT[i].dwRelocAddr = iNewJitBeginAddrRva + a.getCodeSize() - 4;//shellcode开始的位置+当前jit长度 再往回4字节  即为存放基址的位置
    1168                 a.lea(ebx, dword_ptr(ebx, esi));
    1169                 a.mov(ebx, dword_ptr(ebx));
    1170                 a.mov(dword_ptr(esp, 8), ebx);//存放目标函数地址的地址的RVA
    1171                 a.mov(ebx, (int)g_tagIAT[i].dwCallAddr + 6);//返回地址RVA
    1172                 a.lea(ebx, dword_ptr(ebx, esi));
    1173                 a.mov(dword_ptr(esp, 0xC), ebx); 
    1174                 a.pop(esi);
    1175                 a.pop(ebx);
    1176                 a.ret();
    1177                 g_tagIAT[i].dwJmpAddr = iNewJitBeginAddrRva + iNewJitLenth;
    1178                 iNewJitLenth = a.getCodeSize();
    1179             }
    1180             else if (g_tagIAT[i].bType == 9) //JMP
    1181             {
    1182                 g_tagIAT[i].dwNewIatAddr = iNewSectionFileMapAddr + iAddIatLenth + g_tagIAT[i].wIndex * 4;
    1183                 a.push(ebx);
    1184                 a.push(ebx);
    1185                 a.push(ebx);
    1186                 a.push(esi);
    1187                 a.mov(ebx, (int)g_tagIAT[i].dwNewIatAddr);
    1188                 a.mov(esi, g_iImageBase);//程序基址 后续会将这个位置添加到重定位块处,运行时即变为程序基址了
    1189                 g_tagIAT[i].dwRelocAddr = iNewJitBeginAddrRva + a.getCodeSize() - 4;//shellcode开始的位置+当前jit长度 再往回4字节  即为存放基址的位置
    1190                 a.lea(ebx, dword_ptr(ebx, esi));
    1191                 a.mov(dword_ptr(esp,4), 0x3535);//填充垃圾数据
    1192                 a.mov(ebx, dword_ptr(ebx));
    1193                 a.mov(dword_ptr(esp, 0xC), ebx);//存放目标函数地址的地址的RVA
    1194                 a.pop(esi);
    1195                 a.pop(ebx);
    1196                 a.pop(ebx);
    1197                 a.ret();
    1198                 g_tagIAT[i].dwJmpAddr = iNewJitBeginAddrRva + iNewJitLenth;
    1199                 iNewJitLenth = a.getCodeSize();
    1200             }
    1201             else if (g_tagIAT[i].bType == 10) //PUSH
    1202             {
    1203                 g_tagIAT[i].dwNewIatAddr = iNewSectionFileMapAddr + iAddIatLenth + g_tagIAT[i].wIndex * 4;
    1204                 a.push(ebx);
    1205                 a.push(ebx);
    1206                 a.push(ebx);
    1207                 a.push(esi);
    1208                 a.mov(ebx, (int)g_tagIAT[i].dwNewIatAddr);
    1209                 a.mov(esi, g_iImageBase);//程序基址 后续会将这个位置添加到重定位块处,运行时即变为程序基址了
    1210                 g_tagIAT[i].dwRelocAddr = iNewJitBeginAddrRva + a.getCodeSize() - 4;//shellcode开始的位置+当前jit长度 再往回4字节  即为存放基址的位置
    1211                 a.lea(ebx, dword_ptr(ebx, esi));
    1212                 a.mov(ebx, dword_ptr(ebx));
    1213                 a.mov(dword_ptr(esp, 0xC), ebx);//存放目标函数地址的地址的RVA
    1214                 a.mov(ebx, (int)g_tagIAT[i].dwCallAddr + 6); //返回地址RVA
    1215                 a.lea(ebx, dword_ptr(ebx, esi));
    1216                 a.mov(dword_ptr(esp, 8), ebx);
    1217                 a.pop(esi);
    1218                 a.pop(ebx);
    1219                 a.ret();
    1220                 g_tagIAT[i].dwJmpAddr = iNewJitBeginAddrRva + iNewJitLenth;
    1221                 iNewJitLenth = a.getCodeSize();
    1222             }
    1223         }
    1224         a.bind(LoadDllOver);//加载函数地址表以及构建替代IAT的ShellCode完成
    1225         a.mov(edi, dword_ptr(ebp, 8));//获得基址
    1226         for (int i = 0; i < g_tagIAT.size(); i++)
    1227         {    
    1228             a.lea(ecx, dword_ptr(edi, g_tagIAT[i].dwCallAddr));
    1229             a.mov(byte_ptr(ecx), 0xE9);
    1230             //由于这里的E9后面的值,是偏移,所以不用加上基址。偏移量=目标地址-当前指令地址-指令长度
    1231             a.mov(dword_ptr(ecx, 1), (int)(g_tagIAT[i].dwJmpAddr - g_tagIAT[i].dwCallAddr - 5));
    1232             if (g_tagIAT[i].bType == 0)
    1233             {
    1234                 continue;
    1235             }
    1236             a.mov(byte_ptr(ecx, 5), 0x90);
    1237         }
    1238         a.add(esp, 0x10);//8+8
    1239         a.pop(ebx);
    1240         a.popa();
    1241         a.ret();
    1242 
    1243         PVOID szJit = a.make();
    1244         int iJitLenth = a.getCodeSize(); 
    1245          g_pFileSrc = (UCHAR*)realloc(g_pFileSrc, g_iFileSize + iAddIatLenth + iLoadIatLenth + iJitLenth);
    1246         memcpy(g_pFileSrc + g_iFileSize + iAddIatLenth + iLoadIatLenth , szJit, iJitLenth);
    1247 
    1248 
    1249         //一共增加的代码=IAT相关数据+加载后的函数地址表大小+JIT代码长度
    1250          int iAddSrcLen = iAddIatLenth + iLoadIatLenth + iJitLenth;
    1251         //完善节长度等数据  保守起见重新获取节表信息
    1252         pDosHead = (PIMAGE_DOS_HEADER)g_pFileSrc;
    1253         pNtHead = (PIMAGE_NT_HEADERS)((DWORD)pDosHead + pDosHead->e_lfanew);
    1254         pSection = (PIMAGE_SECTION_HEADER)((DWORD)&pNtHead->OptionalHeader + pNtHead->FileHeader.SizeOfOptionalHeader);
    1255         pSection += pNtHead->FileHeader.NumberOfSections - 1;
    1256         if (!(iAddSrcLen%g_iFileAlignment))
    1257         {
    1258             pSection->SizeOfRawData = iAddSrcLen;
    1259         }
    1260         else
    1261         {
    1262             pSection->SizeOfRawData = iAddSrcLen + g_iFileAlignment - (iAddSrcLen%g_iFileAlignment);
    1263         }
    1264         if (!(iAddSrcLen%g_iSectionAlignment))
    1265         {
    1266             pSection->Misc.VirtualSize = iAddSrcLen;
    1267         }
    1268         else
    1269         {
    1270             pSection->Misc.VirtualSize = iAddSrcLen + g_iSectionAlignment - (iAddSrcLen%g_iSectionAlignment);
    1271         }
    1272         pNtHead->OptionalHeader.SizeOfImage += pSection->Misc.VirtualSize;
    1273 
    1274         if (iAddSrcLen != pSection->SizeOfRawData)//当新增长度与对齐后的节长度不相等时,将其补全
    1275         {
    1276             int iLenth = pSection->SizeOfRawData;//先保存,以免扩容后原地址被回收
    1277             g_pFileSrc = (UCHAR*)realloc(g_pFileSrc, g_iFileSize + iLenth);
    1278             memset(g_pFileSrc + g_iFileSize + iAddSrcLen, 0, iLenth - iAddSrcLen);
    1279         }
    1280           g_iFileSize += pSection->SizeOfRawData;
    1281 
    1282         
    1283 
    1284         //将原重定位中  涉及IAT的重定位项删掉
    1285         //1.先统计IAT中的地址位置代码(除了mov eax的地址位置在指令位置+1处,其他皆为+2)
    1286         vector<WORD>vDeleteIatAddr;//需要删除的重定位信息
    1287         for (int i = 0; i < g_tagIAT.size(); i++)
    1288         {
    1289             if (g_tagIAT[i].bType==0) //mov eax  重定位地址位于调用地址+1处
    1290             {
    1291                 vDeleteIatAddr.push_back(g_tagIAT[i].dwCallAddr + 1);
    1292             }
    1293             else
    1294             {
    1295                 vDeleteIatAddr.push_back(g_tagIAT[i].dwCallAddr + 2);
    1296             }
    1297             
    1298         }
    1299 
    1300         //2.统计出重定位表有几个重定位块,每个块的基址是多少,里面有多少个偏移
    1301         for (int i = 0; i < iRelocationLenth; i++)
    1302         {
    1303             tagRelocation addR;
    1304             addR.wR_Head = *(int*)(szR_Src + i);
    1305             int iR_Lenth = *(int*)(szR_Src + i + 4);
    1306             for (int j = 8; j < iR_Lenth; j+=2)
    1307             {
    1308                 WORD ccc = *(WORD*)(szR_Src + i + j);
    1309                 addR.wR_Offset.push_back(ccc);
    1310             }
    1311             vOldReloction.push_back(addR);
    1312             i += iR_Lenth - 1;
    1313         }
    1314 
    1315         //3.根据IAT里的地址,在重定位地址表查找,找到之后将其删除 
    1316         for (int i = 0; i < vDeleteIatAddr.size(); i++)
    1317         {
    1318             for (int j = 0; j < vOldReloction.size(); j++)
    1319             {
    1320                 if ((vDeleteIatAddr[i] & 0xFFF000) > vOldReloction[j].wR_Head) //当调用地址的重定位块大于当前重定位表块时
    1321                 {
    1322                     continue;
    1323                 }
    1324                 else if ((vDeleteIatAddr[i] & 0xFFF000) < vOldReloction[j].wR_Head)
    1325                 {
    1326                     break;
    1327                 }
    1328                 else        //找到对应重定位块
    1329                 {
    1330                     for (int k = 0; k < vOldReloction[j].wR_Offset.size(); k++)
    1331                     {
    1332                         if ((vDeleteIatAddr[i] & 0xFFF) == (vOldReloction[j].wR_Offset[k] & 0xFFF))
    1333                         {
    1334                             vOldReloction[j].wR_Offset.erase(vOldReloction[j].wR_Offset.begin() + k);
    1335                             goto NextIatAddr;
    1336                         }
    1337                     }
    1338                 }
    1339 
    1340             }
    1341         NextIatAddr:;    
    1342         }
    1343 
    1344         //4.对齐重定位表数据,
    1345         /*如果重定位块中项目为偶数个,则跳过
    1346         如果是奇数个,看最后一个是否为0。如果为0,删掉;如果不为0,补0*/
    1347         for (int i = 0; i < vOldReloction.size(); i++)
    1348         {
    1349             int iReloctionNum = vOldReloction[i].wR_Offset.size();
    1350             if (iReloctionNum % 2) //取余  如果能取到 说明为奇数
    1351             {
    1352                 if (vOldReloction[i].wR_Offset[iReloctionNum-1] == 0)
    1353                 {
    1354                     vOldReloction[i].wR_Offset.pop_back();
    1355                 }
    1356                 else
    1357                 {
    1358                     vOldReloction[i].wR_Offset.push_back(0);
    1359                 }
    1360             }
    1361         }
    1362 
    1363         //恢复重定位表
    1364         szR_Src = NULL;
    1365         iRelocationLenth = 0;
    1366         for (int i = 0; i < vOldReloction.size(); i++)
    1367         {
    1368             szR_Src = (char*)realloc(szR_Src, iRelocationLenth + 8);
    1369             memcpy(szR_Src + iRelocationLenth, &vOldReloction[i].wR_Head, 4);
    1370             int iR_Lenth = vOldReloction[i].wR_Offset.size() * 2 + 8;
    1371             memcpy(szR_Src + iRelocationLenth + 4, &iR_Lenth, 4);
    1372             iRelocationLenth += 8;
    1373             for (int j = 0; j < vOldReloction[i].wR_Offset.size(); j++)
    1374             {
    1375                 szR_Src = (char*)realloc(szR_Src, iRelocationLenth + 8 + j*2);
    1376                 memcpy(szR_Src + iRelocationLenth + j*2, &vOldReloction[i].wR_Offset[j], 2);            
    1377             }
    1378             iRelocationLenth += vOldReloction[i].wR_Offset.size() * 2 ;
    1379         }
    1380         
    1381 
    1382         //增加新的重定位项
    1383         char *szAddRelocSrc = NULL;    //总新增重定位数据
    1384         char *szNowAddrelocSrc = NULL;//子新增重定位数据
    1385         int iAddRelocLen = 0;        //总重定位数据长度
    1386         int iNowAddRelocLen = 0;    //子重定位数据长度
    1387         
    1388         int iPage = 0;        //页大小
    1389         int iPageOffset = 0;    //页内偏移
    1390 
    1391 
    1392         //先增加新OEP用于求得基址的重定位项
    1393         iNowAddRelocLen = 10;  //子长度
    1394         szNowAddrelocSrc = (char*)malloc(iNowAddRelocLen);//子数据
    1395         iPage = (g_iNewOEP + 1) & 0xfff000;    //PUSH 0000 0000  重定位数据为地址 偏移+1
    1396         iPageOffset = ((g_iNewOEP + 1) & 0xfff) | 0x3000;
    1397         memcpy(szNowAddrelocSrc, &iPage, 4);//页偏移
    1398         memcpy(szNowAddrelocSrc + 4, &iNowAddRelocLen, 4);//页大小
    1399         memcpy(szNowAddrelocSrc + 8, &iPageOffset, 2);
    1400 
    1401         //开始新增shellcode中的重定位项
    1402         for (int i = 0; i < g_tagIAT.size(); i++)
    1403         {            
    1404             if (iPage == ((g_tagIAT[i].dwRelocAddr) & 0xfff000))  //判断是否与当前页大小一致
    1405             {
    1406                 szNowAddrelocSrc = (char*)realloc(szNowAddrelocSrc, iNowAddRelocLen + 2);
    1407                 iPageOffset = (g_tagIAT[i].dwRelocAddr & 0xfff) | 0x3000;
    1408                 memcpy(szNowAddrelocSrc + iNowAddRelocLen, &iPageOffset, 2);
    1409                 iNowAddRelocLen += 2;
    1410                 memcpy(szNowAddrelocSrc + 4, &iNowAddRelocLen, 4);//页大小
    1411             }
    1412             else   //开启新页
    1413             {
    1414                 if ((iNowAddRelocLen % 4))  //是否4字节对齐
    1415                 {
    1416                     szNowAddrelocSrc = (char*)realloc(szNowAddrelocSrc, iNowAddRelocLen + 2);
    1417                     memset(szNowAddrelocSrc + iNowAddRelocLen, 0, 2);
    1418                     iNowAddRelocLen += 2;
    1419                     memcpy(szNowAddrelocSrc + 4, &iNowAddRelocLen, 4);//页大小
    1420                 }
    1421                 
    1422                 szAddRelocSrc = (char*)realloc(szAddRelocSrc, iAddRelocLen + iNowAddRelocLen);//将总重定位数据扩容
    1423                 memcpy(szAddRelocSrc + iAddRelocLen, szNowAddrelocSrc, iNowAddRelocLen);    //复制子重定位块到总重定位块中
    1424                 iAddRelocLen += iNowAddRelocLen;    //更新总重定位块大小
    1425 
    1426                 iNowAddRelocLen = 10;
    1427                 szNowAddrelocSrc = (char*)malloc(iNowAddRelocLen);//子数据
    1428                 iPage = g_tagIAT[i].dwRelocAddr & 0xfff000;
    1429                 iPageOffset = (g_tagIAT[i].dwRelocAddr & 0xfff) | 0x3000;
    1430                 memcpy(szNowAddrelocSrc, &iPage, 4);//页偏移
    1431                 memcpy(szNowAddrelocSrc + 4, &iNowAddRelocLen, 4);//页大小
    1432                 memcpy(szNowAddrelocSrc + 8, &iPageOffset, 2);
    1433             }
    1434         }
    1435         //此时 由于已经遍历到tagIAT结构最后 但当前重定位块并为添加到总重定位块中,故需要再进行填充
    1436         if ((iNowAddRelocLen % 4))  //是否4字节对齐
    1437         {
    1438             szNowAddrelocSrc = (char*)realloc(szNowAddrelocSrc, iNowAddRelocLen + 2);
    1439             memset(szNowAddrelocSrc + iNowAddRelocLen, 0, 2);
    1440             iNowAddRelocLen += 2;
    1441             memcpy(szNowAddrelocSrc + 4, &iNowAddRelocLen, 4);//页大小
    1442         }
    1443 
    1444         szAddRelocSrc = (char*)realloc(szAddRelocSrc, iAddRelocLen + iNowAddRelocLen);//将总重定位数据扩容
    1445         memcpy(szAddRelocSrc + iAddRelocLen, szNowAddrelocSrc, iNowAddRelocLen);    //复制子重定位块到总重定位块中
    1446         iAddRelocLen += iNowAddRelocLen;    //更新总重定位块大小
    1447 
    1448 
    1449         if ((iR_FileLenth - iRelocationLenth) < iAddRelocLen) //节表长度和实际数据长度是否足够填充新的重定位块
    1450         {
    1451             //扩充重定位数据
    1452             //整数取余 = (新增数据总大小- 之前剩余空间间隙)%对齐大小
    1453             int iZeroLenth = (iAddRelocLen - (iR_FileLenth - iRelocationLenth)) % g_iFileAlignment;
    1454             if (iZeroLenth)
    1455             { 
    1456                 iR_FileLenth = iRelocationLenth + iAddRelocLen + g_iFileAlignment - iZeroLenth;
    1457             }
    1458             else
    1459             {
    1460                 iR_FileLenth = iRelocationLenth + iAddRelocLen;
    1461             }
    1462             szR_Src = (char*)realloc(szR_Src, iR_FileLenth);
    1463             memcpy(szR_Src + iRelocationLenth, szAddRelocSrc, iAddRelocLen);
    1464             memset(szR_Src + iRelocationLenth + iAddRelocLen, 0, iR_FileLenth - iRelocationLenth - iAddRelocLen);
    1465         }
    1466         else
    1467         {
    1468             szR_Src = (char*)realloc(szR_Src, iR_FileLenth);
    1469             memcpy(szR_Src + iRelocationLenth, szAddRelocSrc, iAddRelocLen);
    1470             iRelocationLenth += iAddRelocLen;
    1471             memset(szR_Src + iRelocationLenth, 0, iR_FileLenth - iRelocationLenth);
    1472         }
    1473 
    1474         //还原重定位
    1475         g_pFileSrc = (UCHAR*)realloc(g_pFileSrc, g_iFileSize + iR_FileLenth);
    1476         memcpy(g_pFileSrc + g_iFileSize, szR_Src, iR_FileLenth);
    1477         g_iFileSize += iR_FileLenth;
    1478         
    1479         ////直接用realloc又抽风 用其他转移吧
    1480         //char *szCopyBuff = (char*)malloc(g_iFileSize + iR_FileLenth);
    1481         //memcpy(szCopyBuff, g_pFileSrc, g_iFileSize);
    1482         //memcpy(szCopyBuff + g_iFileSize, szR_Src, iR_FileLenth);
    1483         //g_iFileSize += iR_FileLenth;
    1484         //memcpy(g_pFileSrc, szCopyBuff, g_iFileSize);
    1485         
    1486 
    1487         pDosHead = (PIMAGE_DOS_HEADER)g_pFileSrc;
    1488         pNtHead = (PIMAGE_NT_HEADERS)((DWORD)pDosHead + pDosHead->e_lfanew);
    1489         pSection = (PIMAGE_SECTION_HEADER)((DWORD)&pNtHead->OptionalHeader + pNtHead->FileHeader.SizeOfOptionalHeader);
    1490         pSection += pNtHead->FileHeader.NumberOfSections - 1;
    1491         int iR_FileAddr = pSection->PointerToRawData + pSection->SizeOfRawData;
    1492         int iR_MapAddr = 0;
    1493         if (!(pSection->Misc.VirtualSize % g_iSectionAlignment))
    1494         {
    1495             iR_MapAddr = pSection->VirtualAddress + pSection->Misc.VirtualSize;
    1496         }
    1497         else
    1498         {
    1499             iR_MapAddr = pSection->VirtualAddress + pSection->Misc.VirtualSize
    1500                 + g_iSectionAlignment - (pSection->Misc.VirtualSize % g_iSectionAlignment);
    1501         }
    1502 
    1503         pSection++;
    1504         strcpy((char*)pSection->Name, szR_Name);
    1505         pSection->Characteristics = (0x20000000 | 0x40000000 | 0x80000000 | 0x40);
    1506         pSection->VirtualAddress = iR_MapAddr;
    1507         pSection->Misc.VirtualSize = iR_FileLenth;
    1508         pSection->PointerToRawData = iR_FileAddr;
    1509         pSection->SizeOfRawData = iR_FileLenth;
    1510         pNtHead->OptionalHeader.DataDirectory[5].VirtualAddress = iR_MapAddr;
    1511         pNtHead->OptionalHeader.DataDirectory[5].Size = iRelocationLenth;
    1512         pNtHead->FileHeader.NumberOfSections += 1;
    1513         if (!(iR_FileLenth%g_iSectionAlignment))
    1514         {
    1515             pNtHead->OptionalHeader.SizeOfImage += iR_FileLenth;
    1516         }
    1517         else
    1518         {
    1519             pNtHead->OptionalHeader.SizeOfImage += iR_FileLenth + g_iSectionAlignment - (iR_FileLenth%g_iSectionAlignment);
    1520         }
    1521 
    1522     }
    1523     return true;
    1524 }
    1525 
    1526 
    1527 
    1528 int main()
    1529 {
    1530     //"C:\Users\Admin\Desktop\弹窗.exe
    1531     char FileName[] = { "C:\Users\Admin\Desktop\弹窗.exe" };
    1532     if (!LoadFile(FileName))
    1533     {
    1534         cout << "文件打开失败" << endl;
    1535         system("pause");
    1536         return -1;
    1537     }
    1538 
    1539     if (!CheckPE())
    1540     {
    1541         cout << "该程序不是PE文件" << endl;
    1542         system("pause");
    1543         return -1;
    1544     }
    1545 
    1546     if (!FindCodeAddr())    //找到对应调用IAT的地址
    1547     {
    1548         cout << "该程序没有导入表,请检查" << endl;
    1549         system("pause");
    1550         return -1;
    1551     }
    1552 
    1553     if (!SaveDll())
    1554     {
    1555         cout << "保存DLL信息失败" << endl;
    1556         system("pause");
    1557         return -1;
    1558     }
    1559 
    1560     if (!NewIat())
    1561     {
    1562         cout << "新建IAT表失败" << endl;
    1563         system("pause");
    1564         return -1;
    1565     }
    1566 
    1567     //C:\Users\Admin\Desktop\弹窗IAT加密测试.exe
    1568     char NewFilePath[] = "C:\Users\Admin\Desktop\弹窗IAT加密测试.exe";
    1569     HANDLE hNewFile = CreateFileA(NewFilePath,
    1570         GENERIC_READ | GENERIC_WRITE,
    1571         FILE_SHARE_READ | FILE_SHARE_WRITE,
    1572         NULL,
    1573         CREATE_ALWAYS,   //创建并覆盖上一个文件
    1574         FILE_ATTRIBUTE_ARCHIVE,
    1575         NULL);
    1576 
    1577     if (hNewFile == INVALID_HANDLE_VALUE)
    1578     {
    1579         printf("文件保存失败
    ");
    1580         int iError = GetLastError();
    1581         return 1;
    1582     }
    1583 
    1584     LPDWORD iNum = NULL;
    1585     WriteFile(hNewFile, g_pFileSrc, g_iFileSize, iNum, NULL); //写入文件
    1586     CloseHandle(hNewFile);
    1587     char *NewFileName1 = strrchr(NewFilePath, '\') + 1;
    1588     char *NewFileName = strtok(NewFileName1, ".");
    1589     MessageBoxA(0, NewFileName, "加密成功", 0);
    1590     MessageBoxA(0, "by:阿怪
              2020.12.26", "IAT加密", 0);
    1591 
    1592     system("pause");
    1593 }
    View Code

    加密效果:

     

     

    IAT加密相对于代码段加密较为复杂,特别是在自己实现获得函数地址,以及创建对应的shellcode,并把原调用指令全部一一修改的流程较为繁琐,需要用到各种变量记录位置。博主也是刚接触到这块的新手小白,如果有疑惑或者说的不对的地方欢迎在评论指出,互相学习。感谢!!

  • 相关阅读:
    防止头文件的重复包含问题
    git常用命令
    redis
    linux常用操作
    数据库安装
    mysql修改表结构
    mysql 忘记root密码及授权访问
    mysql连表查询
    mysql 存取ip方法
    php批量修改表结构
  • 原文地址:https://www.cnblogs.com/aaaguai/p/14207468.html
Copyright © 2011-2022 走看看