IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> 滴水逆向三期实践6:扩大节注入代码 -> 正文阅读

[C++知识库]滴水逆向三期实践6:扩大节注入代码

扩大节:

1、拉伸到内存(只是逻辑上,实际代码操作并不需要这一步),需要注入的代码为 ShellCode

2、分配一块新的空间:SizeOfImage + sizeof ( ShellCode)

3、扩大节,修改最后一个节的 SizeOfRawData 和 VirtualSize

? ?OrgSecSize?= max ( SizeOfRawData 或 VirtualSize内存对齐后的值 )?

? ?∵?有些初始化数据未全部写入文件,VirtualSize?可能比?SizeOfRawData?大,必须保证添加的代码不影响到原程序

? ?VirtualSize =?OrgSecSize + sizeof ( ShellCode)

? ?SizeOfRawData =?( OrgSecSize + sizeof(ShellCode) ) 按文件对齐后的值

4、修改SizeOfImage大小

? ?SizeOfImage = (最后一节 VirtualAddress + VirtualSize) 按内存对齐后的值

这里依然在扩大节中植入弹窗代码,和前面一样的操作,详见前面的文章

注意,这里因为要使被扩节?执行代码,?所以需要在被扩节的Characteristics?按位或 一份可执行的设置

这里为? | 0x60000020??

上代码附详细注释:

用到的所有自定义函数均可在前面的章节找到


#include "windows.h"
#include "stdio.h"

#define MESSAGEBOXADDR 0x76AF39A0   //这个值需要将任一exe文件拖入OD打开,搜索 MessageBoxA 记录它的地址到这里(每次开机都不同)

unsigned char ShellCode320[] =
{
	0x6A,0x00,0x6A,0x00,0x6A,0x00,0x6A,0x00,
	0xE8,0x00,0x00,0x00,0x00,
	0xE9,0x00,0x00,0x00,0x00
};

void h320()
{
	char FilePath[] = "CrackHead.exe";	//CRACKME.EXE        CrackHead.exe
	char CopyFilePath[] = "CrackHeadcopy.exe";	//CRACKMEcopy.EXE       CrackHeadcopy.exe
	LPVOID pFileBuffer = NULL;				//会被函数改变的 函数输出之一
	LPVOID* ppFileBuffer = &pFileBuffer;	//传进函数的形参
	LPVOID pNewFileBuffer = NULL;
	int SizeOfFileBuffer;
	PIMAGE_DOS_HEADER pDosHeader = NULL;
	PIMAGE_NT_HEADERS pNTHeader = NULL;
	PIMAGE_FILE_HEADER pFileHeader = NULL;
	PIMAGE_OPTIONAL_HEADER32 pOptionalHeader = NULL;
	PIMAGE_SECTION_HEADER pSectionHeader = NULL;
	DWORD CallX = NULL;	//即E8后跟的4字节
	DWORD JmpX = NULL;	//即E9后跟的4字节

	SizeOfFileBuffer = ReadPEFile(FilePath, ppFileBuffer);	//pFileBuffer即指向已装载到内存中的exe首部
	if (!SizeOfFileBuffer)
	{
		printf("文件读取失败\n");
		return;
	}

	//Dos头
	pDosHeader = (PIMAGE_DOS_HEADER)pFileBuffer;	// 强转 DOS_HEADER 结构体指针
	//NT头
	pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)pFileBuffer + pDosHeader->e_lfanew);
	//PE头
	pFileHeader = (PIMAGE_FILE_HEADER)(((DWORD)pNTHeader) + 4);	//NT头地址 + 4 为 FileHeader 首址
	//可选PE头	
	pOptionalHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pFileHeader + IMAGE_SIZEOF_FILE_HEADER);//SIZEOF_FILE_HEADER为固定值且不存在于PE文件字段中
	//首个节表
	pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pOptionalHeader + pFileHeader->SizeOfOptionalHeader);
	for (int i = 1; i < pFileHeader->NumberOfSections; i++, pSectionHeader++)	//注意这里i从1开始 i < NumberOfSections
	{}	
	//出循环后pSectionHeader指向最后一个节表	

	// OrgSecSize 为 该节的原始大小 (最后一个节的原始大小
	printf("VirtualSize: %x\nSizeOfRawData: %x\n", pSectionHeader->Misc.VirtualSize, pSectionHeader->SizeOfRawData);
	DWORD OrgSecSize = max(pSectionHeader->Misc.VirtualSize, pSectionHeader->SizeOfRawData);
	printf("OrgSecSize: %x\n", OrgSecSize);
	
	//ShallCode即放在节区头起Size之后,这里先计算地址,再修改PE中的值与开辟空间
	//X即E8后的数 = 要跳转的地址 - (E8所在地址 + 5)            (E8 所在地址+5 即 call指令的下一条指令的地址)
	//那么要跳转的地址即messageboxA地址。E8所在地址即 ImageBase内存运行基址 + VirtualAddress节所在偏移+Size +8 才到E8 (∵ShallCode就在节开头)
	CallX = MESSAGEBOXADDR - (pOptionalHeader->ImageBase + pSectionHeader->VirtualAddress + OrgSecSize + 8 + 5);
	
	//jump 要跳转的地址即OEP程序入口点, X = 程序入口点 - E9所在地址 + 5
	//这里程序入口点即ImageBase基址 + 修改前的OddAddressOfEntryPoint         E9所在地址计算同上   下式是化简后约去了ImageBase
	//ImageBase + AddressOfEntryPoint - (ImageBase + VirtualAddress +13 +5 )
	JmpX = pOptionalHeader->AddressOfEntryPoint - (pSectionHeader->VirtualAddress + OrgSecSize + 13 + 5);
	
	//将上述计算后的值放入ShellCode320
	*(PDWORD)(ShellCode320 + 9) = CallX;
	*(PDWORD)(ShellCode320 + 14) = JmpX;
	for (int i = 0; i < sizeof(ShellCode320); i++)
	{
		printf("%x ", ShellCode320[i]);
	}
	printf("\n");
	
	//计算完地址后 计算新节表值  VirtualSize以Size + ShellCode长度 按内存对齐(其实VirtualSize可以不用内存对齐),SizeOfRawData同理
	int NewVirtualSize = OrgSecSize + sizeof(ShellCode320);
	int NewSizeOfRawData = Align(OrgSecSize + sizeof(ShellCode320), pOptionalHeader->FileAlignment);
	printf("NewSizeOfRawData%x, NewVirtualSize:%x\n", NewSizeOfRawData, NewVirtualSize);
	
	// 在修改节表值之前需要用到新旧值 ∴上述节表新值暂不真正修改只作记录。
	// 修改SizeOfImage值
	pOptionalHeader->SizeOfImage = Align(pSectionHeader->VirtualAddress + NewVirtualSize, pOptionalHeader->SectionAlignment);
	
	//在修改节表值之前新空间长度   原空间长度  减去 旧SizeOfRawData  加上新SizeOfRawData 
	int SizeOfNewFileBuffer = SizeOfFileBuffer - pSectionHeader->SizeOfRawData + NewSizeOfRawData;
	
	//修改入口点
	pOptionalHeader->AddressOfEntryPoint = pSectionHeader->VirtualAddress + OrgSecSize;
	
    //Characteristics
	printf("Characteristics:%x\n", pSectionHeader->Characteristics);
	pSectionHeader->Characteristics = pSectionHeader->Characteristics  | 0x60000020;
	printf("Characteristics:%x\n", pSectionHeader->Characteristics);
	
	//修改节表值
	pSectionHeader->Misc.VirtualSize = NewVirtualSize;
	pSectionHeader->SizeOfRawData = NewSizeOfRawData;
	//printf("VirtualSize: %x\nSizeOfRawData: %x\n", pSectionHeader->Misc.VirtualSize, pSectionHeader->SizeOfRawData);
	
	//修改值后开始重新分配空间
	pNewFileBuffer = malloc(SizeOfNewFileBuffer);
	memset(pNewFileBuffer, 0, SizeOfNewFileBuffer);
	memcpy(pNewFileBuffer, pFileBuffer, SizeOfFileBuffer);	//复制原空间
	printf("SizeOfFileBuffer:%x\nSizeOfNewFileBuffer:%x\n", SizeOfFileBuffer, SizeOfNewFileBuffer);

	// 复制新空间
	memcpy((void*)((DWORD)pNewFileBuffer + pSectionHeader->PointerToRawData + OrgSecSize), ShellCode320, sizeof(ShellCode320));
	
	//memcpy((void*)((DWORD)pNewFileBuffer + SizeOfFileBuffer), ShellCode320, sizeof(ShellCode320));	//复制ShellCode
	//剩余部分填充0
	//memset((void*)((DWORD)pNewFileBuffer + SizeOfFileBuffer + sizeof(ShellCode320)), 0, (SizeOfNewFileBuffer - SizeOfFileBuffer - sizeof(ShellCode320)));
	MemeryToFile(pNewFileBuffer, SizeOfNewFileBuffer, CopyFilePath);
	free(pNewFileBuffer);
	free(pFileBuffer);
}

运行程序打印内容如下:

VirtualSize: 468
SizeOfRawData: 600
OrgSecSize: 600
6a 0 6a 0 6a 0 6a 0 e8 93 f3 6e 76 e9 ee c9 ff ff
NewSizeOfRawData800, NewVirtualSize:612
Characteristics:c0000040
Characteristics:e0000060
SizeOfFileBuffer:1600
SizeOfNewFileBuffer:1800
success

打开程序有弹窗,确定后程序正常运行

原exe程序 PETool 查看

修改后:

?

?

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-09-30 11:45:05  更:2021-09-30 11:47:40 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 0:10:46-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码