zoukankan      html  css  js  c++  java
  • 在32位PE文件中的任意一个节中添加代码


    // SectionOp.cpp : 定义控制台应用程序的入口点。
    //

    /************************************************
    *程序说明:在32位PE文件中的任意一个节中添加代码
    *          第一个参数为PE文件 第二个参数为第N个节
    *
    * 时间: 20170718
    * Win10 VS2010 测试通过  ver 0.01
    **************************************************/

    #include "stdafx.h"
    unsigned char DEMOCODE[] = {0X6A,0X00,0X6A,0X00,0X6A,0X00,0X6A,0X00,0XE8,0X00,0X00,0X00,0X00,0XE9,0X00,0X00,0X00,0X00};

    int _tmain(int argc, _TCHAR* argv[])
    {
         unsigned char* FileBuff;
         errno_t err;
         _TCHAR NewFile[1024] = L"New_";

        if(argc >1)
         {
             FileBuff = FileBuffer(argv[1]);
         }
         else
         {
             printf("No PE File ");
             return 1;
         }
         int NumOfSection = 1;
         if (argc >2 )
         {
             size_t i;
             size_t num = wcslen(argv[2]);
             char* pMBBuffer = (char*)malloc(num*2);
             wcstombs_s(&i,pMBBuffer,num*2,argv[2],num);
             NumOfSection = atoi(pMBBuffer);

            if(NumOfSection < 1)
                 NumOfSection = 1;
         }
        
         if(AddCodeAtSection(FileBuff,NumOfSection,DEMOCODE,sizeof(DEMOCODE)) != 0)
         {
             free(FileBuff);
             return -1;
         }
        
         err = wcscat_s(NewFile,argv[1]);
         if(err != 0)
         {
             return -1;
         }

        SaveFile(FileBuff,NewFile);
         free(FileBuff);
         return 0;
    }


    ==================================================================

    ////功能文件

    #include "stdafx.h"

    #define FUN_AD 0x7497D330 //修改成本机的MessageBoxW的地址

    /*********************************************
    在任意节添加代码                           
    输入:FileBuffer NoOfSection  Code CodeSize                           
    输出:添加了Code的FileBuffer,运行程序时,先运行Code再转到原来的程序入口                           
    实现步聚:    (假定FileBuffer 为Pe格式)                       
    1、NoOfSection 数量不要超过 节数量                            
    2、相应节的文件对齐空间要足够代码Code存放                           
    3、找到程序的OEP                           
    3、计算IMAGEBUFF和FILEBUFF之间节的位置转化关系                           
    4、算出JMP <原OEP> CALL〈MessageBoxW〉把位置填入Code中                            
    5、找到节的空白起始区域,存放Code   
    6、将OEP的值改成Code的RV
    **************************************************/
    //unsigned char CODE[] = {0X6A,0X00,0X6A,0X00,0X6A,0X00,0X6A,0X00,0XE8,0X00,0X00,0X00,0X00,0XE9,0X00,0X00,0X00,0X00};
    int AddCodeAtSection(unsigned char* FileBuffer,int NoOfSection,unsigned char* Code,int CodeSize)
    {
         PIMAGE_DOS_HEADER pDosHeader;
         PIMAGE_NT_HEADERS32 pNt32Header;
         PIMAGE_SECTION_HEADER pSectionHeader;

    //1、NoOfSection 数量不要超过 节数量    
         pDosHeader = (PIMAGE_DOS_HEADER)FileBuffer;
         pNt32Header = (PIMAGE_NT_HEADERS32)(FileBuffer+pDosHeader->e_lfanew);
         if(int(pNt32Header->FileHeader.NumberOfSections) < NoOfSection)
         {
             printf("NoOfSection Bigger NumberOfSections ");
             return -1;
         }

    //2、相应节的文件对齐空间要足够代码Code存放   
         //unsigned int CodeSize = sizeof(Code);
         //printf("CodeSize %d ",CodeSize);
         pSectionHeader =(PIMAGE_SECTION_HEADER)(pNt32Header+1);
         pSectionHeader = pSectionHeader +(NoOfSection-1);
         if(CodeSize > int(pSectionHeader->SizeOfRawData-pSectionHeader->Misc.VirtualSize))
         {
             printf("No space to write Code ");
             return -2;
         }

    //3、找到程序的OEP           
         int OEP = pNt32Header->OptionalHeader.AddressOfEntryPoint;

    //3、计算IMAGEBUFF和FILEBUFF之间节的位置转化关系       
        
         long InsImageRV = pSectionHeader->VirtualAddress + pSectionHeader->Misc.VirtualSize;
         long InsPostionRV = pSectionHeader->PointerToRawData + pSectionHeader->Misc.VirtualSize;
         long ImageBase = pNt32Header->OptionalHeader.ImageBase;

    //4、算出JMP <原OEP> CALL〈MessageBoxW〉把位置填入Code中 X = 真实要跳的地址-下一条指令地址    
    // YY = ImageBase+OEP - Imagebase+NEXT_Y
    // XX = MessageBoxW@AD - ImageBase+NEXT_X
         int* YY = (int*)(Code+JMP_Y);
         int* XX = (int*)(Code+CALL_X);
         *YY = (ImageBase+OEP)-(ImageBase+InsImageRV+NEXT_Y);
         *XX = FUN_AD - (ImageBase+InsImageRV+NEXT_X);

    //5、找到节的空白起始区域,存放Code
         unsigned char* InsCode = FileBuffer+InsPostionRV;
         unsigned int x  = 0;
         for (;x<CodeSize;x++)
         {
             InsCode[x] = Code[x];   
         }

    //6、将OEP的值改成Code的RV
         pNt32Header->OptionalHeader.AddressOfEntryPoint = pSectionHeader->Misc.VirtualSize + pSectionHeader->VirtualAddress;

        return 0;
    }

    ///////////////////////////////////////////////////////////

    //将PE文件读到FileBuffer

    unsigned char* FileBuffer(const _TCHAR* FileName)
    {
         unsigned char* Heap = NULL;
         FILE* Stream;
         errno_t err;
         //打开文件
         err = _wfopen_s(&Stream,FileName,L"rb");
         if(err != 0)
         {
             perror("Open File Error:");
             return NULL;
         }
         //计算文件大小
         fseek(Stream,0L,SEEK_END);
         long FileSize = ftell(Stream);
         fseek(Stream,0L,SEEK_SET);
         //分配堆空间
         Heap = (unsigned char*)malloc(sizeof(char)*FileSize);
         //将文件拷到堆
         fread(Heap,sizeof(char),FileSize,Stream);
         fclose(Stream);

        return Heap;
    }

    //////////////////////////////////////////
    //将FileBuffer 保存成文件
    int SaveFile(unsigned char* FileBuffer,const _TCHAR* FileName)
    {
         FILE* Stream;
         errno_t err;

        err = _wfopen_s(&Stream,FileName,L"wb");
         if(err != 0)
         {
             perror("File Create Error:");
             return -1;
         }

        //计算FileBuff大小
         PIMAGE_DOS_HEADER pDosHeader;
         PIMAGE_NT_HEADERS32 pNt32Header;
         PIMAGE_SECTION_HEADER pSecHeader;
         pDosHeader = (PIMAGE_DOS_HEADER)FileBuffer;
         pNt32Header = (PIMAGE_NT_HEADERS32)(FileBuffer + pDosHeader->e_lfanew);
         pSecHeader = (PIMAGE_SECTION_HEADER)(pNt32Header+1);
        
         long FileSize = pNt32Header->OptionalHeader.SizeOfHeaders;
         int NumOfSec = pNt32Header->FileHeader.NumberOfSections;
         int x;
         for(x=0;x<NumOfSec;x++)
         {
             FileSize += pSecHeader->SizeOfRawData;
             pSecHeader++;
         }

        // 写入文件
         fwrite(FileBuffer,sizeof(char),FileSize,Stream);
         fclose(Stream);
         return 0;
    }



    ========================================================

    // stdafx.h : 标准系统包含文件的包含文件,
    // 或是经常使用但不常更改的
    // 特定于项目的包含文件
    //

    #pragma once

    #include "targetver.h"

    #include <stdio.h>
    #include <tchar.h>
    #include <stdlib.h>
    #include <Windows.h>
    #include <WinNT.h>
    #include <assert.h>



    // TODO: 在此处引用程序需要的其他头文件


    int AddCodeAtSection(unsigned char* FileBuffer,int NoOfSection,unsigned char* Code,int CodeSize);
    unsigned char* FileBuffer(const _TCHAR* FileName);
    int SaveFile(unsigned char* FileBuffer,const _TCHAR* FileName);


    #ifndef _DEMO_CODE
    #define _DEMO_CODE


    #define CALL_X 9         //填写X的超始地址
    #define JMP_Y  14        //填写Y的超始地址
    #define NEXT_X 13        //X的下一条指令的地址
    #define NEXT_Y 18        //Y的下一条指令的地址

    #endif

  • 相关阅读:
    Vue3使用vue3-video-player
    centos搭建phantomjs
    windows与Linux写入后门
    webService静态调用方法
    Web开发学习笔记(日更)
    docker修改容器绑定端口
    linux下~/.bashrc、/etc/profile、 $PATH环境变量 作用和修改
    docker for windows安装,修改images位置,修改镜像源,查看/var/lib/docker/containers
    hive修改表DDL
    python 高性能异步爬虫线程&线程池
  • 原文地址:https://www.cnblogs.com/killad/p/7203517.html
Copyright © 2011-2022 走看看