在PE中,新增節,添加代碼


在PE中,新增節,添加代碼

一、先判斷節表后是否有空閑位置,添加節表信息,必須多出兩個節表位置,最后以零結尾。

二、新增節后,需要修改以下信息

  1、添加一個新節,可以復制一份,最好是擁有可執行屬性的節,如.text。

  2、在節表區,新增節的后面,填充一個節,用零填充。

  3、修改標准PE頭中節的數量。

  4、修改SizeOfImage的大小。

  5、在原有數據的后面,新增一個節的數據(內存對齊的整倍數)。

  6、修正新增節表的屬性。

三、新節各個屬性修改說明

  1、Name:名字隨便修改,不能超過八個字節。

  2、VirtualSize:申請的新節空間大小,比如1000

  3、VirtualAddress:等於上一個節的VirtualAddress  +  SizeOfRawData

  4、SizeOfRawData:設置可以和VirtualSize一樣,比如1000

  5、PointerToRawData:等於上一個節的PointerToRawData+  SizeOfRawData

  6、PointerToRelocation:設置成零

  7、PointerToLineNumbers:設置成零

  8、NumberOfLineRelocations:設置成零

  9、NumberOfLineNumbers:設置成零

  10、Characteristics:塊屬性0x20000060  可以取上一個節表和本節表的屬性值,進行異或  如x|y

標志(屬性塊) 常用特征值對照表:

[值:00000020h] [IMAGE_SCN_CNT_CODE                // Section contains code.(包含可執行代碼)]

[值:00000040h] [IMAGE_SCN_CNT_INITIALIZED_DATA    // Section contains initialized data.(該塊包含已初始化的數據)]

[值:00000080h] [IMAGE_SCN_CNT_UNINITIALIZED_DATA  // Section contains uninitialized data.(該塊包含未初始化的數據)]

[值:00000200h] [IMAGE_SCN_LNK_INFO                // Section contains comments or some other type of information.]

[值:00000800h] [IMAGE_SCN_LNK_REMOVE              // Section contents will not become part of image.]

[值:00001000h] [IMAGE_SCN_LNK_COMDAT              // Section contents comdat.]

[值:00004000h] [IMAGE_SCN_NO_DEFER_SPEC_EXC       // Reset speculative exceptions handling bits in the TLB entries for this section.]

[值:00008000h] [IMAGE_SCN_GPREL                   // Section content can be accessed relative to GP.]

[值:00500000h] [IMAGE_SCN_ALIGN_16BYTES           // Default alignment if no others are specified.]

[值:01000000h] [IMAGE_SCN_LNK_NRELOC_OVFL         // Section contains extended relocations.]

[值:02000000h] [IMAGE_SCN_MEM_DISCARDABLE         // Section can be discarded.]

[值:04000000h] [IMAGE_SCN_MEM_NOT_CACHED          // Section is not cachable.]

[值:08000000h] [IMAGE_SCN_MEM_NOT_PAGED           // Section is not pageable.]

[值:10000000h] [IMAGE_SCN_MEM_SHARED              // Section is shareable(該塊為共享塊).]

[值:20000000h] [IMAGE_SCN_MEM_EXECUTE             // Section is executable.(該塊可執行)]

[值:40000000h] [IMAGE_SCN_MEM_READ                // Section is readable.(該塊可讀)]

[值:80000000h] [IMAGE_SCN_MEM_WRITE               // Section is writeable.(該塊可寫)]

-----------------------------------------------------------------------------------------------------

// mem.cpp : 定義控制台應用程序的入口點。
//PE文件從文件加載到內存,再從內存讀取,然后存盤到文件

#include "stdafx.h"
#include <windows.h>
#include <winnt.h>

//#define  PATH "C:\\Windows\\System32\\notepad.exe"
#define  PATH "C:\\Users\\Administrator\\Desktop\\ipmsg.exe"
#define  MsgADD 0x75cffde6
char Shellcode[] =
{
	0x6A, 0x00, 0x6A, 0x00, 0x6A, 0x00, 0x6A, 0x00,
	0xE8, 0x00, 0x00, 0x00, 0x00,
	0xE9, 0x00, 0x00, 0x00, 0x00
};

int Filelength(FILE *fp);
int _tmain(int argc, _TCHAR* argv[])
{
	FILE *Fp;
	fopen_s(&Fp, PATH, "rb");
	int FileSize = Filelength(Fp);//獲取文件大小
	char * FileBuffer = (char *)malloc(FileSize);//申請存放文件的內存空間
	if (FileBuffer == NULL)
	{
		printf("申請iImageBuffer失敗");
	}
	fread_s(FileBuffer, FileSize, 1, FileSize, Fp); //將文件復制到內存中
	//定位一下內存中的數據 各個頭表
	//定位標准PE頭 
	PIMAGE_FILE_HEADER MyFileHeader;
	MyFileHeader = (PIMAGE_FILE_HEADER)(char *)(FileBuffer + *(int *)(FileBuffer + 0x3c) + 0x4);
	//定位可選PE頭 
	PIMAGE_OPTIONAL_HEADER  MyOptionalHeader;
	MyOptionalHeader = (PIMAGE_OPTIONAL_HEADER)((char *)MyFileHeader + 0x14);
	//定位節表
	PIMAGE_SECTION_HEADER MySectionHeader;
	MySectionHeader = (PIMAGE_SECTION_HEADER)((char *)MyOptionalHeader + MyFileHeader->SizeOfOptionalHeader);


	//拉伸,也就是讀到內存中的狀態
	char * ImageBuffer = (char *)malloc(MyOptionalHeader->SizeOfImage+0x1000);//給拉伸申請內存空間
	ZeroMemory(ImageBuffer, MyOptionalHeader->SizeOfImage+0x1000);

	if (ImageBuffer == NULL)
	{
		printf("申請iImageBuffer失敗");
	}
	memcpy(ImageBuffer, FileBuffer, MyOptionalHeader->SizeOfHeaders);


	for (int i = 0; i < MyFileHeader->NumberOfSections; i++)
	{
		memcpy(ImageBuffer + MySectionHeader->VirtualAddress, FileBuffer + MySectionHeader->PointerToRawData, MySectionHeader->SizeOfRawData);//
		MySectionHeader++;
	}
	//新增節開始
	PIMAGE_SECTION_HEADER AddSectionHeader;
	AddSectionHeader = MySectionHeader;
	MySectionHeader--;
	//AddSectionHeader->Name = "cyp";
	//AddSectionHeader->Name = { 0 };
	AddSectionHeader->Name[0] = '.'; AddSectionHeader->Name[1] = 'c'; AddSectionHeader->Name[2] = 'y'; AddSectionHeader->Name[3] = 'p';
	AddSectionHeader->Misc.VirtualSize = 0x1000;
	AddSectionHeader->VirtualAddress = MySectionHeader->VirtualAddress + MySectionHeader->SizeOfRawData;
	AddSectionHeader->SizeOfRawData = 0x1000;
	AddSectionHeader->PointerToRawData = MySectionHeader->PointerToRawData + MySectionHeader->SizeOfRawData;
	int x = (MySectionHeader - (MyFileHeader->NumberOfSections-1))->Characteristics;
	AddSectionHeader->Characteristics = x;
	MyFileHeader->NumberOfSections += 1;
	MyOptionalHeader->SizeOfImage + 0x1000;
	//新增節結束

	//添加代碼到PE中 
	MyFileHeader = (PIMAGE_FILE_HEADER)(char *)(ImageBuffer + *(int *)(ImageBuffer + 0x3c) + 0x4);
	MyOptionalHeader = (PIMAGE_OPTIONAL_HEADER)((char *)MyFileHeader + 0x14);
	MySectionHeader = (PIMAGE_SECTION_HEADER)((char *)MyOptionalHeader + MyFileHeader->SizeOfOptionalHeader);//重新指一下,前面動過了

	//E8后面的硬編碼地址 =真正要到的地址 - E8的下一行或E8本行 +0x5
	char *CodeAdd = ImageBuffer + MySectionHeader->VirtualAddress + MySectionHeader->Misc.VirtualSize;//為要增加的代碼確定位置
	memcpy(CodeAdd, Shellcode, sizeof(Shellcode));//把硬編碼復制到指定位置
	int CallAdd = MsgADD - (MyOptionalHeader->ImageBase + ((int)(CodeAdd + 0xd) - (int)ImageBuffer));
	*(int *)(CodeAdd + 0x9) = CallAdd;//定位CALL函數位置
	int JmpAdd = MyOptionalHeader->ImageBase + MyOptionalHeader->AddressOfEntryPoint - (MyOptionalHeader->ImageBase + (CodeAdd + 0xd - ImageBuffer));//前面是真正要跳的地址  后面括號是下一條指令的地址
	*(int *)(CodeAdd + 0xe) = JmpAdd;//定位JMP 跳回位置,也就是修改程序入口
	MyOptionalHeader->AddressOfEntryPoint = CodeAdd - ImageBuffer;//重新定位程序入口處

	//添加代碼到PE結束

	//壓縮,為存盤做准備
	char *NewBuffer = (char *)malloc(FileSize+0x1000);//給壓縮申請內存空間
	if (NewBuffer == NULL)
	{
		printf("申請iImageBuffer失敗");
	}
	memcpy(NewBuffer, ImageBuffer, MyOptionalHeader->SizeOfHeaders);
	MySectionHeader = (PIMAGE_SECTION_HEADER)((char *)MyOptionalHeader + MyFileHeader->SizeOfOptionalHeader);//重新指一下,前面動過了

	for (int i = 0; i < MyFileHeader->NumberOfSections; i++)
	{
		memcpy(NewBuffer + MySectionHeader->PointerToRawData, ImageBuffer + MySectionHeader->VirtualAddress, MySectionHeader->SizeOfRawData);
		MySectionHeader++;
	}
	FILE *nFp;
	fopen_s(&nFp, "C:\\Users\\Administrator\\Desktop\\CYP.exe", "wb");
	fwrite(NewBuffer, FileSize, 1, nFp);

	//getchar();
	fclose(nFp);
	free(FileBuffer);
	free(ImageBuffer);
	free(NewBuffer);
	return 0;
}

//獲取文件大小



int Filelength(FILE *fp)
{
	int num;
	fseek(fp, 0, SEEK_END);
	num = ftell(fp);
	fseek(fp, 0, SEEK_SET);
	return num;
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM