扩大节:

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.exechar CopyFilePath[] = "CrackHeadcopy.exe"; //CRACKMEcopy.EXE       CrackHeadcopy.exeLPVOID 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;//Characteristicsprintf("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 查看

修改后:

滴水逆向三期实践6:扩大节相关推荐

  1. 滴水逆向三期实践1:PE头字段解析,附PE结构下载

    视频资源详见网盘搜索 或 在线的B站滴水逆向三期 其课件也能在CSDN或百度搜索到,以下部分为课件内容摘要,部分为自己的理解 最后附上详细注释的自写代码 PE(Portable Executable) ...

  2. 滴水逆向三期实践10:动态链接库

    使用静态链接生成的可执行文件体积较大,造成浪费 我们常用的printf.memcpy.strcpy等就来自这种静态库 有维护性问题.不方便修改库中实现,修改后所有使用静态库的都要重新链接一遍 因为静态 ...

  3. 滴水逆向三期实践16:IAT表和导入表

    IAT表 在我们调用 dll 函数的时候,发现代码中的汇编,是通过间接寻址的.也就是不直接 call 函数地址,而是通过一个中间地址再跳转的. 比如调用MessageBox这类系统函数的时候(这也是个 ...

  4. 滴水逆向三期实践15:重定位表修正

    我们知道,重定位表是由于在代码中写入的绝对地址,而 DLL 不能按照设想的 ImageBase 作起始加载位置去了别的地方占坑,那么需要根据重定位表记录的这些绝对地址在内存中的位置(RVA),逐一去到 ...

  5. 静态链接库,动态链接库【滴水逆向三期48笔记】

    在开发过程中,我们通常会有很多函数,需要多次使用或在不同的程序中使用该函数,也有可能我们会将我们写好的函数给别人使用,但是我们又不想给他源代码,毕竟代码是我们花了很多功夫写出来的,那么我们如何不发给其 ...

  6. 滴水逆向三期笔记与作业——02C语言——02数据类型

    海哥牛逼 这里写自定义目录标题 一.C语言如何变成汇编 1.裸函数 二.调用约定 1.常见的几种调用约定 三.程序的真正入口 四.数据类型 4.1 C语言中的数据类型 作业 一.C语言如何变成汇编 1 ...

  7. 滴水逆向三期 win10 ASLR UnmapViewOfSection傀儡进程 加密壳项目

    特意加了一个win10标题, 碰到0xc0000005的朋友就不要再浪费时间了, 我在这个问题上花了整整一天 网上全是xp的代码, 搜到了了几个win10的也是同样的错误没法解决, 唯一一个有用的答案 ...

  8. 滴水逆向三期和中级和高期教程

    联系本人QQ747554937 原版视频,海哥教学视频,不是网页上的介绍视频

  9. IAT表入门简析【滴水逆向三期52笔记】

    在讲IAT表之前,我们来回忆一下之前学习的知识: 如果我们将函数写在程序的源文件中,那么该函数就会被编译器直接编译到程序的二进制文件中,在程序调用该函数的时候,E8后跟的地址是直接写死的,程序直接在e ...

最新文章

  1. 下列那个语句在python中是非法的_下列哪个语句在Python中是非法的()A.x=y=z=1B.x=(y=z+1)C.x,y=y,xD...
  2. 冰墩墩+周杰伦也救不了NFT
  3. LeetCode176 第二高的薪水
  4. EV3 直接命令 - 第 5 课 从 EV3 的传感器读取数据
  5. 番石榴的EventBus –简单的发布者/订阅者
  6. android WebView通过js方法与原生交互
  7. Reason: image not found
  8. Linux安装Flash脚本,Linux(CentOS)下的Shockwave Flash shell一键更新脚本
  9. 【Windows】DACL SACL
  10. win10键盘全部没反应_Win10的键盘失灵解决办法
  11. 对string类型字符串操作
  12. 20145236《信息安全系统设计基础》第1周学习总结
  13. 语音信号处理(赵力)作业答案1-3章
  14. STM32 标准外设库(STM32F107)
  15. 一起找BUG,谷歌推出全新漏洞悬赏平台
  16. Git的author与committer的区别
  17. python九宫格拼图_利用Python实现朋友圈中的九宫格图片效果
  18. 逍遥书生服务器啥时候维护完毕,《逍遥西游2》12月8日服务器维护公告
  19. axis=0与axis=1
  20. 动物派对怎么修改服务器,动物派对登录失败怎么办 Party Animals玩法进入游戏解决方法...

热门文章

  1. 【021】ColorHexa –关于色彩的百科全书
  2. 查看期刊分区及影响因子
  3. autojs文字转拼音
  4. EasyDarwin云上安装部署
  5. 一文搞懂高速电路中的电源设计
  6. jq选择器在实际使用时遇到的问题
  7. UI设计师这样面试更容易成功
  8. 有没有会的指点一下啊
  9. sql语句中不等于的使用(‘=‘ 、‘!=‘、‘<>‘、‘is null‘....)
  10. Angular2入坑指南