ASASLUOCC 发表于 2023-7-17 16:44

滴水三期课后作业求教FileBuffer-ImageBuffer的存盘问题

本帖最后由 苏紫方璇 于 2023-7-17 16:48 编辑

各位大佬好!各位观众老爷好!
【任务说明】这是一个把notepad.exe在缓冲区读取并拉伸,再按硬盘上的内存空间大小存盘的程序,即,notepad.exe先在堆上申请一个缓冲区并读取,然后再申请一个缓冲区用于拉伸成操作系统可执行的实际内存运行大小(即ImageBuffer),最后再将这个可执行的内存大小缓冲区里的数据再按之前硬盘上的文件大小再次存入到新的缓冲区,最后存到另一个文件里。
【遇到问题】在winxp的VC6++上编译成功后,实际打开Stack程序被弹出窗口说“遇到问题”(已附件图片),我不明所以,请教各位走过路过的大佬求解答~!
```
#include "stdafx.h"
#include <windows.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
LPVOID ReadPEFile (LPSTR FilePath)
{
      //设置文件空指针,打开文件,指向文件,确认是否打开
      FILE* pFile = NULL;
      pFile = fopen(FilePath, "rb+");
      if(pFile == NULL)
      {
                printf("打开失败\n");
                return NULL;
      }
      //返回文件大小,为随后申请堆空间做准备
      fseek(pFile,0,SEEK_END);
      long size = ftell(pFile);
      rewind(pFile);
      //设置堆指针(初始化为NULL),开始申请堆空间
      LPVOID pFileBuffer;
      pFileBuffer = malloc(size);
      //判断是否申请成功
      if(pFileBuffer == NULL)
      {
                printf("申请失败\n");
                fclose(pFile);
                return NULL;
      }
      //初始化malloc空间
      memset(pFileBuffer,0,size);
      //读取到内存中
      fread(pFileBuffer,1,size,pFile);
      //读取完毕,做清理工作
      fclose(pFile);
      return pFileBuffer;
}
                                        //拷贝为内存中运行状态的大小
LPVOID CopytoImageBuffer (LPVOID pFileBuffer)
{
      //准备指针,初始化为NULL

      PIMAGE_DOS_HEADER pDosHeader = NULL;//DOS头指针

      PIMAGE_NT_HEADERS pNTHeader = NULL;//NT头指针

      PIMAGE_FILE_HEADER pFileHeader = NULL;//标准PE头指针

      PIMAGE_OPTIONAL_HEADER32 pOptionalHeader = NULL;//可选PE头指针

      PIMAGE_SECTION_HEADER pSectionHeader = NULL;//节表指针
      
      //接收缓冲区指针,设置各指针位置
      //pFileBuffer = ReadPEFile ("C:\\WINDOWS\\system32\\notepad.exe");

      pDosHeader = (PIMAGE_DOS_HEADER) pFileBuffer;

      pNTHeader = (PIMAGE_NT_HEADERS) ((DWORD)pFileBuffer+pDosHeader->e_lfanew);

      pFileHeader = (PIMAGE_FILE_HEADER) ( (DWORD) pNTHeader+4);

      pOptionalHeader = (PIMAGE_OPTIONAL_HEADER32)( (DWORD) pFileHeader+IMAGE_SIZEOF_FILE_HEADER );

      pSectionHeader =(PIMAGE_SECTION_HEADER) ((DWORD)pOptionalHeader+pFileHeader->SizeOfOptionalHeader);

      //判断是否读取成功
      if(!pFileBuffer)
      {
                printf("读取失败\n");
                free(pFileBuffer);
                return NULL;
      }
      if(*(PWORD)pFileBuffer != IMAGE_DOS_SIGNATURE)
      {
                printf("不是有效的MZ标志\n");
                free(pFileBuffer);
                return NULL;
      }
      //打印DOS头
      printf("*************DOS头如下*************\n");
      printf("%x\n",pDosHeader->e_magic);
      printf("%x\n",pDosHeader->e_lfanew);
      //判断PE签名
      if(*( (PDWORD) ((DWORD)pFileBuffer+pDosHeader->e_lfanew) ) != IMAGE_NT_SIGNATURE)
      {
                printf("%x:不是有效的PE签名\n",(pNTHeader->Signature));
                free(pFileBuffer);
                return NULL;
      }
      //打印PE签名
      printf("%x:是有效的PE签名\n",pNTHeader->Signature);

      //打印标准PE头
      printf("*************标准PE头大小如下*************\n");
      printf("%x\n",(pFileHeader->Machine));
      printf("%x\n",(pFileHeader->NumberOfSections));

      //打印可选PE头大小
      printf("*************可选PE头大小如下*************\n");
      printf("%x\n",pOptionalHeader->Magic);

      //打印节表头-
      for(int i =0;i<pFileHeader->NumberOfSections;i++)
      {
                printf("*************各节表头如下*************\n");
                printf("%s\n",pSectionHeader->Name);
                //pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pSectionHeader+IMAGE_SIZEOF_SECTION_HEADER);
                pSectionHeader++;
      }
      pSectionHeader = (PIMAGE_SECTION_HEADER) ((DWORD)pOptionalHeader+pFileHeader->SizeOfOptionalHeader);
      
      //申请Image指针
      LPVOID pImageBuffer = NULL;
      //读取Imagesize大小,申请malloc空间
      pImageBuffer = malloc(pOptionalHeader->SizeOfImage);//printf("%x",pOptionalHeader->SizeOfImage);
      //检查是否申请成功
      if(!pImageBuffer)
      {
                printf("申请Image缓冲区失败");
                free(pFileBuffer);
                return NULL;
      }
      //初始化malloc空间
      memset(pImageBuffer,0,pOptionalHeader->SizeOfImage);
      //开始拷贝各头+节表大小——依据:optional头中的SizeOfHeaders;
      memcpy(pImageBuffer,pFileBuffer,pOptionalHeader->SizeOfHeaders);
      //开始循环拷贝节
      for(int k=0;k<pFileHeader->NumberOfSections;k++)
      {
                //memcpy( ( (PDWORD)pImageBuffer+pSectionHeader->VirtualAddress),( (PDWORD)pFileBuffer+pSectionHeader->PointerToRawData),pSectionHeader->SizeOfRawData);
                //printf("%x\n",( (PDWORD)pImageBuffer+pSectionHeader->VirtualAddress));
                memcpy( ( (char*)pImageBuffer+pSectionHeader->VirtualAddress),( (char*)pFileBuffer+pSectionHeader->PointerToRawData),pSectionHeader->SizeOfRawData);
                printf("%x\n",( (char*)pImageBuffer+pSectionHeader->VirtualAddress));
                pSectionHeader++;
      }
      //free(pFileBuffer);
      return pImageBuffer;
}


void CopytoNewBuffer_Save(LPVOID pImageBuffer)
{
      //准备指针,初始化为NULL

      PIMAGE_DOS_HEADER pDosHeader = NULL;//DOS头指针

      PIMAGE_NT_HEADERS pNTHeader = NULL;//NT头指针

      PIMAGE_FILE_HEADER pFileHeader = NULL;//标准PE头指针

      PIMAGE_OPTIONAL_HEADER32 pOptionalHeader = NULL;//可选PE头指针

      PIMAGE_SECTION_HEADER pSectionHeader = NULL;//节表指针
      
      //接收缓冲区指针,设置各指针位置
      //pImageBuffer = ReadPEFile ("C:\\WINDOWS\\system32\\notepad.exe");

      pDosHeader = (PIMAGE_DOS_HEADER) pImageBuffer;

      pNTHeader = (PIMAGE_NT_HEADERS) ((DWORD)pImageBuffer+pDosHeader->e_lfanew);

      pFileHeader = (PIMAGE_FILE_HEADER) ( (DWORD) pNTHeader+4);

      pOptionalHeader = (PIMAGE_OPTIONAL_HEADER32)( (DWORD) pFileHeader+IMAGE_SIZEOF_FILE_HEADER );

      pSectionHeader =(PIMAGE_SECTION_HEADER) ((DWORD)pOptionalHeader+pFileHeader->SizeOfOptionalHeader);

      //再次申请NewBuffer内存空间,确认并初始化
      //设置文件空指针,打开文件,指向文件,确认是否打开
      FILE* pFile = NULL;
      pFile = fopen("C:\\WINDOWS\\system32\\notepad.exe", "rb+");
      if(pFile == NULL)
      {
                printf("打开失败\n");
                return;
      }
      //返回文件大小,为随后申请堆空间做准备
      fseek(pFile,0,SEEK_END);
      long size = ftell(pFile);
      rewind(pFile);
      //设置堆指针(初始化为NULL),开始申请堆空间
      LPVOID pNewBuffer;
      pNewBuffer = malloc(size);
      //判断是否申请成功
      if(pNewBuffer == NULL)
      {
                printf("申请失败\n");
                fclose(pFile);
                return;
      }
      //初始化malloc空间
      memset(pNewBuffer,0,size);
      //开始拷贝头们+节表
      memcpy(pNewBuffer,pImageBuffer,pOptionalHeader->SizeOfHeaders);
      //循环拷贝三个节
      for(int i=0;i<pFileHeader->NumberOfSections;i++)
      {
                memcpy((char*)pNewBuffer+pSectionHeader->PointerToRawData,(char*)pImageBuffer+pSectionHeader->VirtualAddress,pSectionHeader->SizeOfRawData);
                char* tempNewBuffer = (char*)pNewBuffer + pSectionHeader->PointerToRawData + pSectionHeader->SizeOfRawData;
                char* tempImageBuffer = (char*)pImageBuffer + pSectionHeader->VirtualAddress + pSectionHeader->Misc.VirtualSize;
      }
      //准备一个新文件用于接收NewBuffer缓冲区的内存数据
      FILE* pNewFile = NULL;
      pNewFile = fopen("C:\\Documents and Settings\\Administrator\\桌面\\Stack.exe","wb+");
      if(!pNewFile)
      {
                printf("接收的文件打开失败");
                free(pNewBuffer);
                return;
      }
      //写入新硬盘
      fwrite(pNewBuffer,size,1,pNewFile);
      free(pNewBuffer);
      free(pImageBuffer);
      return;
}
int main(int argc, char* argv[])
{
      LPVOID pFileBuffer = ReadPEFile ("C:\\WINDOWS\\system32\\notepad.exe");
      LPVOID pImageBuffer = CopytoImageBuffer(pFileBuffer);
      CopytoNewBuffer_Save(pImageBuffer);
      return 0;
}
```

ASASLUOCC 发表于 2023-7-17 16:44

为啥用了md插件还是有几行漏在外面。。。。

苏紫方璇 发表于 2023-7-17 16:48

ASASLUOCC 发表于 2023-7-17 16:44
为啥用了md插件还是有几行漏在外面。。。。

帮你修改了一下,现在可以了

ASASLUOCC 发表于 2023-7-17 17:09

苏紫方璇 发表于 2023-7-17 16:48
帮你修改了一下,现在可以了

哇版主大大!感谢感谢!看来我发帖还发错版块了{:1_923:}

幽溪左畔 发表于 2023-7-17 19:38

本帖最后由 幽溪左畔 于 2023-7-18 06:51 编辑

//循环拷贝三个节
      for(int i=0;i<pFileHeader->NumberOfSections;i++)
      {
                memcpy((char*)pNewBuffer+pSectionHeader->PointerToRawData,(char*)pImageBuffer+pSectionHeader->VirtualAddress,pSectionHeader->SizeOfRawData);
                char* tempNewBuffer = (char*)pNewBuffer + pSectionHeader->PointerToRawData + pSectionHeader->SizeOfRawData;
                char* tempImageBuffer = (char*)pImageBuffer + pSectionHeader->VirtualAddress + pSectionHeader->Misc.VirtualSize;
      }

这里没循环所有的节



devil_bruce 发表于 2023-7-17 19:40

记的当时做的时候成品没有一个能在win10上能跑起来的, 双击之后就没反应了,也不报错, 找了半天没找到原因就继续往下做了...然后到win32直接被薄纱{:301_1006:}收获是真正的理解了C语言指针{:301_1004:}

ASASLUOCC 发表于 2023-7-18 03:10

幽溪左畔 发表于 2023-7-17 19:38
导入表处理了吗

我只看到FileBuffer-Imagebuffer这节课,还没看到导入表,而作业留的是FileBuffer-Imagebuffer这节课,应该不会牵涉到没学的导入表知识。
我在想会不会是转的时候没有对齐

ASASLUOCC 发表于 2023-7-18 03:11

devil_bruce 发表于 2023-7-17 19:40
记的当时做的时候成品没有一个能在win10上能跑起来的, 双击之后就没反应了,也不报错, 找了半天没找到原因就 ...

太幸福了叭!我看海东的视频真的是前一天还在 char*指针,下一秒就直接LPVOID这个没学过的新东西了
页: [1]
查看完整版本: 滴水三期课后作业求教FileBuffer-ImageBuffer的存盘问题