aswcy815174418 发表于 2021-11-27 20:23

原创首发,不调用CreateProcess,启动Win32程序

本帖最后由 aswcy815174418 于 2021-11-27 20:48 编辑

**大体思路:拉伸→修复导入表→修复重定位表→创建线程(定义winmain函数指针,并传入参数调用),效果图在最底下
**

**写这个源码的缘由: 前几天面试了一家安全公司,面试官问我,内核重载后,全局变量怎么处理,我想了想
不是修复重定位表就可以了嘛?后来仔细想了想,重定位只是修复了全局变量的地址,并没有初始化内核重载后,
全局变量所存的值,后来研究了下,什么时候全局变量会初始化
一丶编译前就赋了初始值,没有的话默认就赋值为0
二丶从main函数开始初始化(并没有准确的说,就是在main函数初始化,也可能是main函数调了其它函数进行初始化的)
内核文件,经过研究发现,全局变量用的是第二种进行初始化,如果把内核文件,拉伸,重定位,修复导入表
如果知道内核main函数参数,用文中的方法,可能会解决掉全局变量的处理(意味着,可以不用老内核的数据,直接用新内核数据)
**
**测试用到的文件: [点我下载](https://www.lanzouw.com/iXUaywyrqze
)**
```
// LoadProcess.cpp : Defines the entry point for the console application.
//

#include "windows.h"
#include "stdio.h"
//隐藏控制台
//#pragma   comment(linker,"/subsystem:\"windows\"/entry:\"mainCRTStartup\""   )

//重定位
BOOL modify_base_table(TCHAR* imagebuffer, DWORD new_imagebasse);


DWORD ThreadProc(PVOID Parameter) {

      typedef BOOL(APIENTRY *CallMain)(HMODULE hModule,
                DWORDul_reason_for_call,
                LPVOID lpReserved
                );
      PIMAGE_DOS_HEADER h_dos_header = (PIMAGE_DOS_HEADER)Parameter;//dos头
      PIMAGE_NT_HEADERS hNt = (PIMAGE_NT_HEADERS)((DWORD)Parameter + h_dos_header->e_lfanew);//nt头

      DWORD OEP = hNt->OptionalHeader.AddressOfEntryPoint + (DWORD)Parameter;

      CallMain p = OEP;

      p((DWORD)Parameter, 1, 0);

      return 0;
}

int main(int argc, char* argv[]) {
      DWORD size_file = 0;//文件大小
      char* filebuffer = NULL;//filebuffer
      char* imagebuffer = NULL;//imagebase
      DWORD sizeofimage = NULL;//文件的sizeofimage
      DWORD number_section = 0;//节的数量
      DWORD size_all_headers = 0;//所有头的大小


      //用fopen打开一个进程
      FILE* h_file = fopen("C:\\win32.exe", "rb+");
      DWORD DD = GetLastError();
      if (NULL == h_file) {
                printf("用fopen打开文件失败,请检查文件地址是否错误\n");
                return -1;
      }
      //得到其大小
      fseek(h_file, 0, SEEK_END);
      size_file = ftell(h_file);
      fseek(h_file, 0, SEEK_SET);
      //为其申请内存
      filebuffer = (char*)malloc(size_file);
      //初始化内存
      memset(filebuffer, 0, size_file);
      if (NULL == filebuffer) {
                printf("申请filebuffer失败\n");
                return -1;
      }
      //文件写入内存
      fread(filebuffer, 1, size_file, h_file);
      if (IMAGE_DOS_SIGNATURE != *(short*)filebuffer) {
                printf("该文件不是PE文件\n");
                return -1;
      }
      //得到其sizeofimage
      PIMAGE_DOS_HEADER hDos = (PIMAGE_DOS_HEADER)filebuffer;//dos头
      PIMAGE_NT_HEADERS hNt = (PIMAGE_NT_HEADERS)(filebuffer + hDos->e_lfanew);//nt头

      if (IMAGE_NT_SIGNATURE != hNt->Signature) {
                printf("该文件不是PE文件\n");
                return -1;
      }
      sizeofimage = hNt->OptionalHeader.SizeOfImage;
      //拉伸
      //申请内存
      imagebuffer = (char*)malloc(sizeofimage);
      if (NULL == imagebuffer) {
                printf("申请imagebuffer失败\n");
                return -1;
      }

      //初始化内存
      memset(imagebuffer, 0, sizeofimage);
      //得到节表
      PIMAGE_SECTION_HEADER SectionArr = (PIMAGE_SECTION_HEADER)((DWORD)hNt + 24 + hNt->FileHeader.SizeOfOptionalHeader);
      //得到节的数量
      number_section = hNt->FileHeader.NumberOfSections;
      //得到所有头的大小
      size_all_headers = hNt->OptionalHeader.SizeOfHeaders;
      //复制头
      memcpy(imagebuffer, filebuffer, size_all_headers);
      //复制节区
      while (number_section--) {
                DWORD VirtualAddress = 0;
                DWORD PointerToRawData = 0;
                DWORD SizeOfRawData = 0;
                //得到VirtualAddress
                VirtualAddress = SectionArr->VirtualAddress;
                //得到PointerToRawData
                PointerToRawData = SectionArr->PointerToRawData;
                //得到SizeOfRawData
                SizeOfRawData = SectionArr->SizeOfRawData;
                memcpy(imagebuffer + VirtualAddress, filebuffer + PointerToRawData, SizeOfRawData);
                SectionArr++;
      }

      //修复iat表
      //得到导入表
      PIMAGE_IMPORT_DESCRIPTOR ImportTable = (PIMAGE_IMPORT_DESCRIPTOR)(imagebuffer + hNt->OptionalHeader.DataDirectory.VirtualAddress);
      while (0 != ImportTable->FirstThunk) {
                //得到dll名字
                char* dll_name = imagebuffer + ImportTable->Name;
                //得到iat表
                int* IatTable = (int*)(imagebuffer + ImportTable->FirstThunk);
                while (*IatTable) {
                        //判断最高位是不是1
                        if ((*IatTable) & 0x80000000) {
                              *IatTable = (DWORD)GetProcAddress(LoadLibrary(dll_name), (char*)((*IatTable) & 0x7FFFFFFF));
                              IatTable++;
                        } else {
                              //得到By_Name结构体
                              PIMAGE_IMPORT_BY_NAME by_name = (PIMAGE_IMPORT_BY_NAME)(imagebuffer + *IatTable);
                              char* function_name = (char*)by_name->Name;
                              *IatTable = (DWORD)GetProcAddress(LoadLibrary(dll_name), function_name);
                              IatTable++;
                        }
                }
                ImportTable++;
      }

      //修复重定位表
      if (FALSE == modify_base_table((TCHAR*)imagebuffer, (DWORD)imagebuffer)) {
                printf("重定位失败\n");

                return -1;
      }

      //老属性
      DWORD old;
      //修改为可执行,可读可写
      VirtualProtect(imagebuffer, hNt->OptionalHeader.SizeOfImage, PAGE_EXECUTE_READWRITE, &old);

      //从OEP开始跑
      HANDLE hThread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)ThreadProc, imagebuffer, 0, 0);

      WaitForSingleObject(hThread, -1);
      fclose(h_file);
      free(filebuffer);
      free(imagebuffer);
      return 0;
}


BOOL modify_base_table(TCHAR* imagebuffer, DWORD new_imagebasse) {
      DWORD imagebase = 0;
      //判断有没有重定位表
                //得到NT头
      PIMAGE_DOS_HEADER exe_f_dos_header = (PIMAGE_DOS_HEADER)imagebuffer;
      PIMAGE_NT_HEADERS exe_f_nt_header = (PIMAGE_NT_HEADERS)((DWORD)imagebuffer + (DWORD)exe_f_dos_header->e_lfanew);
      //得到imagebase
      imagebase = exe_f_nt_header->OptionalHeader.ImageBase;
      //得到重定位表
      PIMAGE_BASE_RELOCATION exe_f_base_relocation = (PIMAGE_BASE_RELOCATION)(imagebuffer + exe_f_nt_header->OptionalHeader.DataDirectory.VirtualAddress);
      //判断
      if (0 == exe_f_base_relocation->VirtualAddress && 0 == exe_f_base_relocation->SizeOfBlock) {
                return FALSE;
      }
      //修复
      while (0 != exe_f_base_relocation->VirtualAddress && 0 != exe_f_base_relocation->SizeOfBlock) {
                int* virtual_add = NULL;
                short value = 0;
                //得到要修复的数量
                DWORD number_of_modify = (exe_f_base_relocation->SizeOfBlock - 8) / 2;
                //得到要修复的位置
                short* adderss_of_modify = (short*)((DWORD)exe_f_base_relocation + 8);
                //开始
                while (number_of_modify--) {
                        value = *adderss_of_modify;
                        //判断最高位是不是3
                        if (value >> 12 == 3) {
                              //去掉前面的属性
                              value = value & 0x0FFF;
                              virtual_add = (int*)(imagebuffer + exe_f_base_relocation->VirtualAddress + value);
                              *virtual_add = *virtual_add - imagebase + new_imagebasse;
                        }
                        adderss_of_modify++;
                }
                //得到下一个块的地址
                exe_f_base_relocation = (PIMAGE_BASE_RELOCATION)((DWORD)exe_f_base_relocation + exe_f_base_relocation->SizeOfBlock);
      }
      //更改imagebase
      exe_f_nt_header->OptionalHeader.ImageBase = new_imagebasse;
      return TRUE;
}



```

苏紫方璇 发表于 2021-11-28 17:11

想起来在哪里看到过类似的了,这个操作其他进程的,原理应该差不多
https://blog.csdn.net/xfgryujk/article/details/81360292

rogxo 发表于 2021-11-27 21:17

牛逼,长知识了

nimeilai 发表于 2021-11-27 22:23

学 习 了 {:1_893:}

CC000731 发表于 2021-11-27 22:28

这不是PE的知识么?

aswcy815174418 发表于 2021-11-27 22:33

CC000731 发表于 2021-11-27 22:28
这不是PE的知识么?

就是PE知识

非洲小白脸. 发表于 2021-11-28 04:14

易语言EXE没有重定位怎么办?

xiaoshu1688 发表于 2021-11-28 07:59

涨知识了,不错。

segasonyn64 发表于 2021-11-28 09:35

感谢,请问能否搞成支持X64的???

asts 发表于 2021-11-28 10:01

今天又学习了一个新知识!!

CD3 发表于 2021-11-28 10:04

支持原创
页: [1] 2
查看完整版本: 原创首发,不调用CreateProcess,启动Win32程序