FileBfufer转ImageBuffer【滴水逆向三期43作业源码】

简介: FileBfufer转ImageBuffer【滴水逆向三期43作业源码】

作业要求我们在上一章已经说明了,还有不懂的可以去上一张看一下,这里直接给出源码,代码我们就不做解释了,自己写出来或着自己理解一遍或许对PE会有更好的理解。

编写一个程序,实现从FileBuffer拉升到ImageBuffer再转回FileBuffer并且完成存盘:

这是主函数部分:

#include <stdio.h>
#include <windows.h>
#include <stdlib.h>
#include "Function.h"
int main(int argc, char** argv) {
  char *File_Buffer,*Image_Buffer,*New_Buffer;
  char filepath[]="E:\\个人\\逆向\\练习.exe";
  //打开文件,读取到File_Buffer
  File_Buffer=ReadToFile_Buffer(filepath);
  //将File_Buffer拉伸存到Image_Buffer 
  Image_Buffer=FileBufferToImageBuffer(File_Buffer);
  //将Image_Buffer再存到New_Buffer
  New_Buffer=ImageBufferToNewBuffer(Image_Buffer);
  //将文件存盘
  char newname[]="NewBuffer.exe";
  save(newname,New_Buffer);
  //释放申请的内存
  free(File_Buffer);
  free(Image_Buffer);
  free(New_Buffer); 
  return 0;
}

这是Function(函数说明部分):

//打开文件,将数据读取到Fiel_Buffer
//该函数返回值为一个指针,指向File_Buffer
char*ReadToFile_Buffer(char *filepath){
  FILE *fp;
  char *File_Buffer=NULL;
  int length;
  //打开文件 
  if((fp=fopen(filepath,"rb"))==NULL){
    printf("文件打开失败!\n");
    exit(0);
  }else{
    printf("打开文件成功。\n");
  }
  //计算文件大小
  fseek(fp,0,SEEK_END);
  length=ftell(fp);
  fseek(fp,0,SEEK_SET);
  //动态申请内存
  File_Buffer=(char*)malloc(length)
  if(File_Buffer==NULL){
    printf("申请内存失败!\n");
  }else{
    printf("申请内存成功。\n");
  }
  //将文件数据读取到File_Buffer
  if(fread(File_Buffer,1,length,fp)){
    printf("读取文件成功。\n"); 
  }else{
    printf("读取文件失败!\n");
  }
  //关闭文件
  if(fclose(fp)){
    printf("关闭文件失败!\n");
    exit(0);
  }else{
    printf("关闭文件成功。\n");
  }
  return File_Buffer;
}
//将Fiel_Buffer读取到Image_Buffer
//该函数返回一个指针,指向Image_Buffer
char *FileBufferToImageBuffer(char *File_Buffer){
  char *Image_Buffer=NULL;
  IMAGE_DOS_HEADER *pDosHeader=(IMAGE_DOS_HEADER*)File_Buffer;
  IMAGE_FILE_HEADER *pFileHeader=(IMAGE_FILE_HEADER*)(File_Buffer+pDosHeader->e_lfanew+4);
  IMAGE_OPTIONAL_HEADER *pOptionalHeader=(IMAGE_OPTIONAL_HEADER*)((char*)pFileHeader+20);
  IMAGE_SECTION_HEADER *pSectionHeader=(IMAGE_SECTION_HEADER*)((char*)pOptionalHeader+pFileHeader->SizeOfOptionalHeader);
  //动态申请内存
  Image_Buffer=(char*)malloc(pOptionalHeader->SizeOfImage);
  if(Image_Buffer==NULL){
    printf("内存申请失败!\n");
  }else{
    printf("内存申请成功。\n");
  }
  //初始化申请的内存
  int i=0;
  while(i<=pOptionalHeader->SizeOfImage){
    *(Image_Buffer + i)= 0x00; 
    i++; 
  } 
  //读取数据到Image_Buffer
  //复制所有头
  int j=0;
  for(j=0;j<pOptionalHeader->SizeOfHeaders;j++){
    *(Image_Buffer + j)= *(File_Buffer + j);
  }
  //复制所有节信息
  int k,x;
  for(k=0;k<pOptionalHeader->SizeOfHeaders;k++){
    for(x=0;x<pSectionHeader->SizeOfRawData;x++){
      *(Image_Buffer+pSectionHeader->VirtualAddress)=*(File_Buffer+pSectionHeader->PointerToRawData+x);
    }
    pSectionHeader++;
  }
  return Image_Buffer;
}
//将Image_Buffer存到New_Buffer
//该函数需要一个指向File_Buffer的指针
//该函数返回一个指针,指向New_Buffer 
char *ImageBufferToNewBuffer(char *Image_Buffer){
  char *New_Buffer;
  //定义PE头部结构体
  IMAGE_DOS_HEADER *pDosHeader=(IMAGE_DOS_HEADER*)Image_Buffer;
  IMAGE_FILE_HEADER *pFileHeader=(IMAGE_FILE_HEADER*)(Image_Buffer+pDosHeader->e_lfanew+4);
  IMAGE_OPTIONAL_HEADER *pOptionalHeader=(IMAGE_OPTIONAL_HEADER*)((char*)pFileHeader+20);
  IMAGE_SECTION_HEADER *pSectionHeader=(IMAGE_SECTION_HEADER*)(pOptionalHeader+pFileHeader->SizeOfOptionalHeader);
  //计算所需内存大小
  IMAGE_SECTION_HEADER *temp=pSectionHeader;
  temp=pSectionHeader+pFileHeader->NumberOfSections-1;
  int length=temp->PointerToRawData+temp->VirtualAddress;
  //申请内存
  New_Buffer=(char*)malloc(length);
  //初始化申请的内存
  int i;
  for(i=0;i<length;i++){
    *(New_Buffer+i)=0x00;
  } 
  //复制所有头
  int j;
  for(j=0;j<pOptionalHeader->SizeOfHeaders;j++){
    *(New_Buffer+j)=*(Image_Buffer+j);
  }
  //复制所有节
  int k,x;
  for(k=0;k<pFileHeader->NumberOfSections;k++){
    for(x=0;x<pSectionHeader->SizeOfRawData;x++){
      *(New_Buffer+pSectionHeader->PointerToRawData+x)=*(Image_Buffer+pSectionHeader->PointerToRawData+x);
    }
    pSectionHeader++; 
  }
  return New_Buffer;
}
void save(char *newname,char *New_Buffer){
  //定义PE头部结构
  IMAGE_DOS_HEADER *pDosHeader=(IMAGE_DOS_HEADER*)New_Buffer;
  IMAGE_FILE_HEADER *pFileHeader=(IMAGE_FILE_HEADER*)((char*)New_Buffer+pDosHeader->e_lfanew+4);
  IMAGE_OPTIONAL_HEADER *pOptionalHeader=(IMAGE_OPTIONAL_HEADER*)((char*)pFileHeader+0x20);
  IMAGE_SECTION_HEADER *pSectionHeader=(IMAGE_SECTION_HEADER*)(pOptionalHeader+pFileHeader->SizeOfOptionalHeader);
  //计算New_Buffer大小
  IMAGE_SECTION_HEADER *temp=pSectionHeader;
  temp=pSectionHeader+pFileHeader->NumberOfSections-1; 
  int length=temp->PointerToRawData+temp->VirtualAddress;
  //新建文件
  FILE *fp;
  if((fp=fopen(newname,"wb"))==NULL){
    printf("文件新建失败!\n");
  }else{
    printf("文件新建成功。\n");
  }
  //将New_Buffer读写到文件中
  if(fwrite(New_Buffer,length,1,fp)){
    printf("存盘成功。\n");
  }else{
    printf("存盘失败!\n");
    exit(0);
  }
  if(fclose(fp)){
    printf("关闭文件成功。\n");
  }else{
    printf("关闭文件失败!\n");
  }
}

代码中还有很多可以优化的地方,或者是有一些错误的地方希望大家指出来,我会非常虚心地学习,也希望我们能够共同进步!

在博客中我还发现另一个很不错的源码:day30.1-FileBuffer-ImageBuffer

#include "stdafx.h"
#include "stdlib.h"
#define IMAGE_SIZEOF_SHORT_NAME 8
//*******************************************************************************
#pragma pack(1)
typedef struct DOS_HEADER{  //DOS头字段
    short e_magic;
    short e_cblp;
    short e_cp;
    short e_crlc;
    short e_cparhdr;
    short e_minalloc;
    short e_maxalloc;
    short e_ss;
    short e_sp;
    short e_csum;
    short e_ip;
    short e_cs;
    short e_lfarlc;
    short e_ovno;
    short e_res[4];
    short e_oemid;
    short e_oeminfo;
    short e_res2[10];
    int e_lfanew;  
}Dos;
#pragma pack()
//别忘了中间还有一个PE签名
#pragma pack(1)
typedef struct FILE_HEADER{   //标准PE头字段
    short Machine;
    short NumberOfSections;
    int TimeDateStamp;
    int PointerToSymbolTable;
    int NumberOfSymbols;
    short SizeOfOptionalHeader;
    short Characteristics;
}File;
#pragma pack()
#pragma pack(1)
typedef struct OPTIONAL_HEADER{   //可选PE头字段
    short Magic;
    char MajorLinkerVersion;
    char MinorLinkerVersion;
    int SizeOfCode;
    int SizeOfInitializedData;
    int SizeOfUninitializedData;
    int AddressOfEntryPoint;
    int BaseOfCode;
    int BaseOfData;
    int ImageBase;
    int SectionAlignment;
    int FileAlignment;
    short MajorOperatingSystemVersion;
    short MinorOperatingSystemVersion;
    short MajorImageVersion;
    short MinorImageVersion;
    short MajorSubsystemVersion;
    short MinorSubsystemVersion;
    int Win32VersionValue;
    int SizeOfImage;
    int SizeOfHeaders;
    int CheckSum;
    short Subsystem;
    short DllCharacteristics;
    int SizeOfStackReserve;
    int SizeOfStackCommit;
    int SizeOfHeapReserve;
    int SizeOfHeapCommit;
    int LoaderFlags;
    int NumberOfRvaAndSizes;
    //后面还有几个(16)个结构体,一个结构体8字节,我们先不研究,后面再说
}Op;
#pragma pack()    
#pragma pack(1)
typedef struct _IMAGE_SECTION_HEADER {
    char Name[IMAGE_SIZEOF_SHORT_NAME];  //宏定义使用
    union{
        int PhysicalAddress;
        int VirtualSize;
    }Misc;
    int VirtualAddress;
    int SizeOfRawData;
    int PointerToRawData;
    int PointerToRelocations;
    int PointerToLinenumbers;
    short NumberOfRelocations;
    short NumberOfLinenumbers;
    int Characteristics;
}Sec;
#pragma pack()
//*******************************************************************************
//将硬盘上的可执行文件数据复制一份存入FileBuffer中
char* readInFileBuffer(char* filePath){
    FILE* fp = NULL;
    char* p = NULL;
    fp = fopen(filePath,"rb");
    if(NULL == fp){
        printf("文件打开失败\n");
        fclose(fp);
        return NULL;
    }
    //计算文件长度
    fseek(fp,0,2);
    int len = ftell(fp);
    fseek(fp,0,0);
    //动态申请FileBuffer内存空间
    p = (char*)malloc(len);
    if(NULL == p){
        printf("FileBuffer内存空间分配失败\n");
        fclose(fp);
        return NULL;
    }
    //写入数据
    int isSuccessed = fread(p,len,1,fp);
    if(!isSuccessed){
        printf("写入FileBuffer失败\n");
        fclose(fp);
        free(p);
        return NULL;
    }
    fclose(fp);
    return p;  //将FileBuffer首地址返回
}
//PE装载
char* fileBufferToImageBuffer(char* fileBufferp){
    Dos* dosp = (Dos*)fileBufferp; //定义DOS结构体类型指针
    File* filep = (File*)(fileBufferp + dosp->e_lfanew + 4);//定义File结构体类型指针
    Op* opp = (Op*)((char*)filep + 20);//定义Op结构体类型指针
    Sec* secp = (Sec*)((char*)opp + filep->SizeOfOptionalHeader);//定义Sec结构体类型指针
    //动态申请ImageBuffer的内存空间
    char* ip = NULL;
    ip = (char*)malloc(opp->SizeOfImage);
    if(NULL == ip){
        printf("动态申请ImageBuffer内存失败\n");
        return NULL;
    }
    for(int i = 0;i < opp->SizeOfImage;i++){
        *(ip + i) = 0x00;
    }
    //复制所有头
    for(int j = 0;j < opp->SizeOfHeaders;j++){
        *(ip + j) = *(fileBufferp + j);
    }
    //复制所有节
    for(int k = 0;k < filep->NumberOfSections;k++){
        for(int x = 0;x < secp->SizeOfRawData;x++){
            *(ip + secp->VirtualAddress + x) = *(fileBufferp + secp->PointerToRawData + x);
        }
        secp++;
    }
    return ip; //返回ImageBuffer的起始地址
}
//ImageBuffer到NewBuffer
char* imageBufferToNewBuffer(char* imageBufferp){
    Dos* dosp = (Dos*)imageBufferp; //定义DOS结构体类型指针
    File* filep = (File*)(imageBufferp + dosp->e_lfanew + 4);//定义File结构体类型指针
    Op* opp = (Op*)((char*)filep + 20);//定义Op结构体类型指针
    Sec* secp = (Sec*)((char*)opp + filep->SizeOfOptionalHeader);//定义Sec结构体类型指针
    //计算newBuffer需要的大小
    //使用最后一个节的文件偏移地址 + 最后一个节对齐后的大小
    Sec* temp = secp;
    secp = secp + filep->NumberOfSections - 1;
    int len = secp->PointerToRawData + secp->SizeOfRawData;
    secp = temp;
    //动态分配NewBuffer内存
    char* np = (char*)malloc(len);
    if(NULL == np){
        printf("NewBuffer内存分配失败\n");
        return NULL;
    }
    for(int i = 0;i < len;i++){
        *(np + i) = 0x00;
    }
    //复制所有头
    for(int j = 0;j < opp->SizeOfHeaders;j++){
        *(np + j) = *(imageBufferp + j);
    }
    //复制所有节
    for(int k = 0;k < filep->NumberOfSections;k++){
        for(int x = 0;x < secp->SizeOfRawData;x++){
            *(np + secp->PointerToRawData + x) = *(imageBufferp + secp->VirtualAddress + x);
        }
        secp++;
    }
    return np; //返回NewBuffer的首地址
}
//将文件存盘
int save(char* savePath,char* newBufferp){
    Dos* dosp = (Dos*)newBufferp; //定义DOS结构体类型指针
    File* filep = (File*)(newBufferp + dosp->e_lfanew + 4);//定义File结构体类型指针
    Op* opp = (Op*)((char*)filep + 20);//定义Op结构体类型指针
    Sec* secp = (Sec*)((char*)opp + filep->SizeOfOptionalHeader);//定义Sec结构体类型指针
    FILE* fp = fopen(savePath,"wb");
    if(NULL == fp){
        printf("文件打开失败\n");
        fclose(fp);
        return 0;
    }
    secp = secp + filep->NumberOfSections - 1;
    int len = secp->PointerToRawData + secp->SizeOfRawData;  //得到newBuffer的大小
    int isSuccessed = fwrite(newBufferp,len,1,fp);
    if(!isSuccessed){
        printf("存盘失败\n");
        fclose(fp);
        return 0;
    }
    fclose(fp);
  printf("存盘成功\n");
    return 1;
}
int main(int argc,char*argv[]){
    //读入FileBuffer
    char filePath[] = "D:\\notepad.exe";
    char* fileBuffer = readInFileBuffer(filePath);
    if(NULL == fileBuffer){
        return 0;
    }
    //FileBuffer到ImageBuffer
    char* imageBuffer = fileBufferToImageBuffer(fileBuffer); 
    if(NULL == imageBuffer){
        printf("PE加载失败");
        free(fileBuffer);
        fileBuffer = NULL;
        return 0;
    }
    //ImageBuffer到NewBuffer
    char* newBuffer = imageBufferToNewBuffer(imageBuffer);
    if(NULL == newBuffer){
        free(fileBuffer);
        free(imageBuffer);
        fileBuffer = NULL;
      imageBuffer = NULL;
        return 0;
    }
    //存盘
    char destFilePath[] = "D:\\notepad_new.exe";
    int isSuccessed2 = save(destFilePath,newBuffer);
    if(!isSuccessed2){
        printf("存盘失败\n");
    }
    free(fileBuffer);
    free(imageBuffer);
    free(newBuffer);
    fileBuffer = NULL;
    imageBuffer = NULL;
    newBuffer = NULL;
    return 0;
}


相关文章
|
Java Android开发
|
云安全 监控 安全
聊聊公有云的安全性
聊聊公有云的安全性
|
运维 监控 算法
java实现一个动态监控系统,监控接口请求超时的趋势
java实现一个动态监控系统,监控接口请求超时的趋势
612 2
|
5月前
|
机器学习/深度学习 存储 并行计算
大模型推理显存优化系列(3):FlowMLA——面向高吞吐的DP MLA零冗余显存优化
本文将介绍蚂蚁集团ASystem团队在推理显存优化上的新工作FlowMLA
|
5月前
|
编解码 Java Shell
安卓虚拟摄像头,vcam虚拟摄像头,安卓免root虚拟摄像头
采用动态Hook+视频流替换方案,通过Xposed框架拦截系统相机服务,实现免Root环境下的虚拟摄像头功能
|
12月前
|
机器学习/深度学习 分布式计算 Java
《探索 Apache Spark MLlib 与 Java 结合的卓越之道》
本文探讨了Apache Spark MLlib与Java结合的最佳实践,涵盖基础认知、数据预处理、模型选择与构建、训练调优及部署应用。Spark以其分布式计算能力著称,MLlib提供丰富的机器学习算法,Java则拥有成熟生态。两者结合可高效处理大规模数据集,构建灵活的机器学习应用。通过RDD和DataFrame API进行数据操作,利用特征工程工具优化数据,选择合适的分类、回归或聚类模型,并通过管道机制简化工作流。模型训练时合理设置参数并调优,最终将模型部署到生产环境,释放其商业价值。
216 8
|
Windows
IDEA如何查看已经安装的插件并删除
【10月更文挑战第1天】这段内容主要介绍了如何在IntelliJ IDEA中查看和删除已安装的插件。可以通过软件内的插件市场查看插件列表,包括插件名称、版本号和供应商等信息;也可以通过访问插件目录查看。删除插件则建议在插件市场中进行,包括禁用和卸载步骤,手动删除插件文件夹的方法不推荐,因为可能存在配置残留等问题。
3415 12
|
云安全 存储 安全
守护数据安全: 零信任视角下的勒索病毒防范之道
京鼎科技遭黑客勒索100万美元,全球勒索软件攻击增长,2023年涨幅37.75%。企业应采取零信任策略防止攻击:包括软件定义边界隐藏资产、颗粒度授权认证、持续信任评估和微隔离。德迅云安全提出零信任安全体系解决方案,通过网络隐身、IAM、流量控制和应用隔离保护企业免受勒索软件威胁。
|
文字识别 Python
python代码运行报错:No module named 'aliyunsdkcore'
用python调用阿里云图片OCR识别,使用的是阿里云官方给的传本地图片文件进行检测的代码,运行报错:No module named 'aliyunsdkcore'。在pycharm python软件包和终端里安装aliyunsdkcore这个模块都失败了。
|
机器学习/深度学习 数据采集 自然语言处理
【机器学习】逻辑回归:智能垃圾邮件分类实例
【机器学习】逻辑回归:智能垃圾邮件分类实例
817 0