1. 程式人生 > >在32位PE文件中的任意一個節中添加代碼

在32位PE文件中的任意一個節中添加代碼

for 特定 fine lib demo 控制 num fun tar


// 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\n");
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\n");
return -1;
}

//2、相應節的文件對齊空間要足夠代碼Code存放
//unsigned int CodeSize = sizeof(Code);
//printf("CodeSize %d\n",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\n");
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 = [email protected] - 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

在32位PE文件中的任意一個節中添加代碼