htpidk 发表于 2020-7-31 15:25

PE文件提取

本帖最后由 htpidk 于 2020-7-31 15:36 编辑

可以提取某个PE文件中作为资源存放的其他PE文件,例如提取外挂辅助或者病毒里的功能dll,具体看源码class TiQu{
public:
      TiQu(char*);
      ~TiQu();
      int TQ();
      char* buffer;
      FILE* hf;
      long len;
};

TiQu::TiQu(char* name){
      hf=fopen(name,"rb+");
      fseek(hf,0,SEEK_END);
      len=ftell(hf);
      buffer=new char;
      fseek(hf,0,SEEK_SET);
      fread(buffer,len,1,hf);
}

TiQu::~TiQu(){
      fclose(hf);
      delete[] buffer;
}

int TiQu::TQ(){
      int numbers=0;//内含PE文件数量
      char* PEstruct={0};//存放内含的PE文件起始指针,假设文件里含有不超过10个PE文件
      char* point=buffer;
      do{
                char M=*point;
                char Z=*(point+1);
                if(M=='M' && Z=='Z'){
                        int E_lfanew=*(int*)(point+0x3c);
                        if(E_lfanew>0 && E_lfanew<0x1000){//E_lfanew偏移一般很小,注意排除负数,因为读取出来的E_lfanew可能超过有符号整数范围变成负数
                              char P=*(point+E_lfanew);
                              char E=*(point+E_lfanew+1);
                              if(P=='P' && E=='E'){
                                        PEstruct=point;
                                        numbers++;
                              }
                        }
                }
         point++;
      }while(point<buffer+len);
      //char text={0};
      //sprintf(text,"共找到%d个PE文件\r\n",numbers);
      //MessageBox(NULL,text,"提示",MB_OK);

      if(numbers>1){//如果有超过1个PE文件就提取
                for(int i=1;i<numbers;++i){//从PEstruct开始提取,PEstruct是原文件PE结构
                        int E_lfanew=*(int*)(PEstruct+0x3c);
                        PIMAGE_FILE_HEADER pfile=reinterpret_cast<PIMAGE_FILE_HEADER>(PEstruct+E_lfanew+4);
                        WORD character=pfile->Characteristics;
                        int sectionnumbers=pfile->NumberOfSections;
                        PIMAGE_SECTION_HEADER psec=reinterpret_cast<PIMAGE_SECTION_HEADER>(PEstruct+E_lfanew+sizeof(IMAGE_NT_HEADERS));
                        for(int j=1;j<sectionnumbers;++j){
                              psec++;
                        }
                        int pesize=psec->PointerToRawData+psec->SizeOfRawData;
                        char lujing={0};
                        GetCurrentDirectory(200,lujing);
                        char filename={0};
                        if((character&0x2000)==0x2000)
                              sprintf(filename,"\\%d.dll",i);
                        else
                              sprintf(filename,"\\%d.exe",i);
                        strcat(lujing,filename);
                        FILE* hfile=fopen(lujing,"wb+");
                        int error=GetLastError();
                        fwrite(PEstruct,pesize,1,hfile);
                        fclose(hfile);
                        std::cout<<"提取文件:"<<lujing<<"成功"<<std::endl;
                }
      }
      return numbers;
}

int _tmain(int argc, _TCHAR* argv[])
{
      char buffer={0};
      std::cout<<"请输入要提取的目标程序"<<std::endl;
      std::cin>>buffer;
      TiQu ceshi(buffer);
      ceshi.TQ();
      system("pause");
      return 0;
}

JuncoJet 发表于 2020-7-31 16:15

为啥写C++了,还用char* PEstruct,好怪嗷用 vector<char*> 不爽么

pizazzboy 发表于 2020-7-31 16:17

楼主 ,能直接发个EXE文件出来吗?没编译环境

htpidk 发表于 2020-7-31 16:27

JuncoJet 发表于 2020-7-31 16:15
为啥写C++了,还用char* PEstruct,好怪嗷用 vector 不爽么

刚开始考虑了,后面想想一般文件也就放两三个dll进去就图方便了,还有下面的字符串处理那里也没用string,用char自己处理的,这样速度还是要快一丢丢的吗

htpidk 发表于 2020-7-31 16:31

本帖最后由 htpidk 于 2020-7-31 17:21 编辑

pizazzboy 发表于 2020-7-31 16:17
楼主 ,能直接发个EXE文件出来吗?没编译环境
不知道你那里能不能打开,用MD方式生成,需要安装了VC2010运行库才能打开

pizazzboy 发表于 2020-8-2 16:39

htpidk 发表于 2020-7-31 16:31
不知道你那里能不能打开,用MD方式生成,需要安装了VC2010运行库才能打开

谢谢,可以打开!

xyym 发表于 2020-10-11 16:45

感谢楼主的热心分享。立马试试{:1_893:}

yiao 发表于 2020-10-12 10:43

本帖最后由 yiao 于 2020-10-12 10:44 编辑

代码不够简洁,如果商用的话需要优化:1.判断pe用windows自带的结构 2.尽量用缓冲区,加快速度 3.*(WORD*)p,或者*(DWORD*)p直接判断,int会随cpu不同位数不同 4.文件的读写另写函数实现,和pe判断分开,判断都在缓冲里面判断 5.容错需要加强,否则佷容易出错,,,

爲妳¢執著 发表于 2022-6-24 08:24

感谢分享!
页: [1]
查看完整版本: PE文件提取