d173220523 发表于 2023-2-6 22:08

滴水逆向 FileBuffer--->ImageBuffer

本帖最后由 d173220523 于 2023-2-9 21:09 编辑

把第4行的PVOID *pFileBuffer和第29行的*pFileBuffer前面的*去掉,再把第139行的&pFileBuffer前面的&去掉为什么程序会运行不成#include <iostream>
#include <windows.h>
// 读取PE,返回PE大小
DWORD ToLoaderPE(LPSTR file_path, PVOID *pFileBuffer){
      FILE *pFile = NULL;
      DWORD FileSize = 0;
      PVOID pFileBufferTemp = NULL;
      pFile = fopen(file_path, "rb");
      if(!pFile){
                printf("Can not open file\n");
                return 0;
      }
      fseek(pFile, 0, SEEK_END);
      FileSize = ftell(pFile);
      printf("FileBuffer Size: %x\n",FileSize);
      fseek(pFile, 0, SEEK_SET);
      pFileBufferTemp = malloc(FileSize);
      if(!pFileBufferTemp){
                printf("malloc fail!\n");
                fclose(pFile);
      }
      DWORD n = fread(pFileBufferTemp, FileSize, 1, pFile);
      if(!n){
                printf("read file failed!\n");
                free(pFileBufferTemp);
                fclose(pFile);
                return 0;
      }
      *pFileBuffer = pFileBufferTemp;
      pFileBufferTemp = NULL;
      fclose(pFile);
      return FileSize;
}
DWORD CopyFileBufferToImageBuffer(PVOID pFileBuffer, PVOID* pImageBuffer){
      PIMAGE_DOS_HEADER pDosHeader = NULL;
      PIMAGE_NT_HEADERS pNTHeader = NULL;
      PIMAGE_FILE_HEADER pPEHeader = NULL;
      PIMAGE_OPTIONAL_HEADER32 pOptionHeader = NULL;
      PIMAGE_SECTION_HEADER pSectionHeader = NULL;
      if(!pFileBuffer){
                printf("file loader failed!\n");
                return 0;
      }
      if(*((PWORD)pFileBuffer) != IMAGE_DOS_SIGNATURE){
                printf("Don not hava MZ!\n");
                return 0;
      }
      // 找出各个结构的起始地址
      pDosHeader = (PIMAGE_DOS_HEADER)pFileBuffer;
      if(*((LPDWORD)((DWORD)pFileBuffer + pDosHeader->e_lfanew)) != IMAGE_NT_SIGNATURE){
                printf("没有PE符号");
                return 0;
      }
      pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)pFileBuffer + pDosHeader->e_lfanew);
      pPEHeader = (PIMAGE_FILE_HEADER)((DWORD)pNTHeader + 4);
      pOptionHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pPEHeader + IMAGE_SIZEOF_FILE_HEADER);
      pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pOptionHeader + pPEHeader->SizeOfOptionalHeader);
      // 头部,节表等内容拉伸放入内存
      PVOID pImageTemp = malloc(pOptionHeader -> SizeOfImage);
      if(!pImageTemp){
                printf("申请内存映像失败!");
                free(pImageTemp);
                return 0;
      }
      memset(pImageTemp, 0, pOptionHeader->SizeOfImage);
      memcpy(pImageTemp, pFileBuffer, pOptionHeader->SizeOfHeaders);
      int n;
      PIMAGE_SECTION_HEADER pSectionHeaderTemp = pSectionHeader;
      printf("节表数量:%d\n", pPEHeader->NumberOfSections);
      for(n=0; n < pPEHeader->NumberOfSections; n++, pSectionHeaderTemp++){
                memcpy((PVOID)((DWORD)pImageTemp + pSectionHeaderTemp->VirtualAddress), (PVOID)((DWORD)pFileBuffer + pSectionHeaderTemp ->PointerToRawData), pSectionHeaderTemp->SizeOfRawData);
                printf("第%d节表:内存偏移%x,磁盘偏移%x\n", n, pSectionHeaderTemp->VirtualAddress, pSectionHeaderTemp->PointerToRawData);
      }
      *pImageBuffer = pImageTemp;
      pImageTemp = NULL;
      return pOptionHeader->SizeOfImage;
}
DWORD CopyImageBufferToNewBuffer(PVOID pImageBuffer, PVOID* pNewFileBuffer){
      PIMAGE_DOS_HEADER pDosHeader = NULL;
      PIMAGE_NT_HEADERS pNTHeader = NULL;
      PIMAGE_FILE_HEADER pPEHeader = NULL;
      PIMAGE_OPTIONAL_HEADER32 pOptionHeader = NULL;
      PIMAGE_SECTION_HEADER pSectionHeader = NULL;
      if(!pImageBuffer){
                printf("内存加载失败!\n");
                return 0;
      }
      if(*((PWORD)pImageBuffer) != IMAGE_DOS_SIGNATURE){
                printf("Don not hava MZ!\n");
                return 0;
      }
      // 找出头部各个结构的起始地址
      pDosHeader = (PIMAGE_DOS_HEADER)pImageBuffer;
      if(*((PDWORD)((DWORD)pImageBuffer + pDosHeader->e_lfanew)) != IMAGE_NT_SIGNATURE){
                printf("没有PE符号");
                return 0;
      }      
      pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)pImageBuffer + pDosHeader->e_lfanew);
      pPEHeader = (PIMAGE_FILE_HEADER)((DWORD)pNTHeader + 4);
      pOptionHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pPEHeader + IMAGE_SIZEOF_FILE_HEADER);
      pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pOptionHeader + pPEHeader->SizeOfOptionalHeader);
      // 计算要申请空间
      int new_file_size = pOptionHeader->SizeOfHeaders;
      for(int i=0; i < pPEHeader->NumberOfSections; i++){
                new_file_size += pSectionHeader.SizeOfRawData;
      }
      // 申请文件存盘空间
      LPVOID pNewFileBufferTemp = malloc(new_file_size);
      if(!pNewFileBufferTemp){
                printf("存盘空间申请失败!");
                return 0;
      }
      // 头部放进去
      memset(pNewFileBufferTemp, 0, new_file_size);
      memcpy(pNewFileBufferTemp, pDosHeader, pOptionHeader->SizeOfHeaders);
      // 各个节表放进去
      PIMAGE_SECTION_HEADER pSectionHeaderTemp = pSectionHeader;
      for(i=0; i < pPEHeader->NumberOfSections; i++, pSectionHeaderTemp++)
                memcpy((PVOID)((DWORD)pNewFileBufferTemp + pSectionHeaderTemp->PointerToRawData), (PVOID)((DWORD)pImageBuffer + pSectionHeaderTemp->VirtualAddress), pSectionHeaderTemp->SizeOfRawData);
      *pNewFileBuffer = pNewFileBufferTemp;
      pNewFileBufferTemp = NULL;
      return new_file_size;
}
int newbuffer_write2_exe(PVOID NewFileBuffer,DWORD FileSize, LPSTR FilePath){
      FILE* fp1 = fopen(FilePath,"wb");
      if(fp1 != NULL)
                fwrite(NewFileBuffer,FileSize,1,fp1);
      fclose(fp1);
      return 1;
}
int main()
{
      LPSTR file_path = "C:\\WINDOWS\\system32\\notepad.exe";
      LPSTR write_file_path = "c:\\2.exe";
      LPVOID pFileBuffer = NULL; // 从磁盘读取到缓存
      LPVOID pImageBuffer = NULL;// 缓存拉伸存放到内存
      LPVOID pNewFileBuffer = NULL; // 存盘
      // 读取PE到缓存
      DWORD FileSize = ToLoaderPE(file_path, &pFileBuffer);
      printf("exe to buffer : %x\n", FileSize);
      // 缓存拉伸到内存
      DWORD ImageSize = CopyFileBufferToImageBuffer(pFileBuffer, &pImageBuffer);
      printf("拉伸到内存的大小 : %x\n", ImageSize);
      DWORD NewFileSize = CopyImageBufferToNewBuffer(pImageBuffer, &pNewFileBuffer);
      printf("要存盘的大小:%x\n", NewFileSize);
      int ret4 = newbuffer_write2_exe(pNewFileBuffer, NewFileSize, write_file_path);
      printf("newbuffer->存盘返回值为:%d\n",ret4);
      return 0;
}

aonima 发表于 2023-2-7 00:41

你的c语言基础太差了,别研究pe了。还是先补一下c的指针吧,pFileBuffer是二级指针,取消了数据返回不了

TobyLee 发表于 2023-2-7 08:55

再看看pe前面指针那部分。变量名起的时候我个人是
一级指针加一个p(pName)
二级指针加两个p(ppName) 这样用起来比较明了

又红又专 发表于 2023-2-7 10:44

例如 int a=3    int*p =&a;   *p 其实就是a了      &其实就是类型加*了*就是获取指针里面的值了,你小子前面基础是一点没看直接到PE了

d173220523 发表于 2023-2-7 12:41

又红又专 发表于 2023-2-7 10:44
例如 int a=3    int*p =&a;   *p 其实就是a了      &其实就是类型加*了*就是获取指针里面的值了,你小子 ...

没太听懂啊,第4行形参类型是PVOID *(void**),为什么第139行实参传入的是LPVOID(void*),那个引用符号会把void*类型变成void**?

又红又专 发表于 2023-2-7 19:23

d173220523 发表于 2023-2-7 12:41
没太听懂啊,第4行形参类型是PVOID *(void**),为什么第139行实参传入的是LPVOID(void*),那个引用符 ...

对啊就那个意思啊 void* a=xxx   则void** p=&a;*p里面内容和a是一样的都是void* 类型的

d173220523 发表于 2023-2-8 13:58

又红又专 发表于 2023-2-7 19:23
对啊就那个意思啊 void* a=xxx   则void** p=&a;*p里面内容和a是一样的都是void* 类型的

那既然形参实参都是void**程序能运行,那我把那两个*一个&去掉,全部变成void*类型理论上不也能运行吗

d173220523 发表于 2023-2-8 14:03

aonima 发表于 2023-2-7 00:41
你的c语言基础太差了,别研究pe了。还是先补一下c的指针吧,pFileBuffer是二级指针,取消了数据返回不了

我知道pFileBuffer是二级指针,我就想问如果我把pFileBuffer变成一级指针是不是程序也能运行,两个*一个&去掉把他们全变成void*类型理论上应该也能运行啊,为什么最后运行失败了

aonima 发表于 2023-2-8 14:42

d173220523 发表于 2023-2-8 14:03
我知道pFileBuffer是二级指针,我就想问如果我把pFileBuffer变成一级指针是不是程序也能运行,两个*一个& ...

我说兄弟,你还是再去补一下c语言基础吧。你的指针没学明白,pFileBuffer你是在main函数定义的,你传入&pFileBuffer是传入的地址。取消掉&直接传入pFileBuffer,是传入null,你实在不懂就调试一下吧

又红又专 发表于 2023-2-9 09:58

本帖最后由 又红又专 于 2023-2-9 10:06 编辑

d173220523 发表于 2023-2-8 13:58
那既然形参实参都是void**程序能运行,那我把那两个*一个&去掉,全部变成void*类型理论上不也能运行吗
不行啊,你想参数传参必须用指针或者引用类型啊,因为原来就是指针了所以要用指针的指针就是二级指针,否则穿不出去了, 这个就跟void(OUT int a)差不多你想要把a传出去必须定义为 void(OUT int& a) 或者
void(OUT int* a) 这种才行 ,我明白你的意思,前面都是指针类型了,为什么还在用二级指针,而不是直接传指针呢? 但是其实你函数里面的void* 相当于我举例的int 类型了 , 这个为什么要用指针的指针跟链表操作一样 https://blog.csdn.net/qq_28816873/article/details/106576375#_180参考这个例子吧也是用指针的指针.:loveliness: 这个确实刚开始比较懵逼 但是c++写开头了,不用想就是用二级指针不管前面啥类型作为参数传出去就得用指针或者引用
页: [1]
查看完整版本: 滴水逆向 FileBuffer--->ImageBuffer