【逆向】在程序空白区添加Shellcode

目录

 硬编码

内存对齐和文件对齐

节表

实战


滴水逆向03-17

#include <windows.h>LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
{// 定义窗口类WNDCLASS wc = { 0 };wc.lpfnWndProc = WndProc;wc.hInstance = hInstance;wc.lpszClassName = L"MyWindowClass";wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);// 注册窗口类if (!RegisterClass(&wc)){MessageBox(NULL, L"窗口注册失败!", L"错误", MB_ICONERROR);return 0;}// 创建窗口HWND hwnd = CreateWindow(L"MyWindowClass",            // 窗口类名L"Hello, Windows!",          // 窗口标题WS_OVERLAPPEDWINDOW,         // 窗口样式CW_USEDEFAULT, CW_USEDEFAULT, // 窗口位置400, 200,                    // 窗口大小NULL,                        // 父窗口NULL,                        // 菜单句柄hInstance,                   // 实例句柄NULL                         // 附加参数);if (!hwnd){MessageBox(NULL, L"窗口创建失败!", L"错误", MB_ICONERROR);return 0;}// 显示窗口ShowWindow(hwnd, iCmdShow);UpdateWindow(hwnd);// 进入消息循环MSG msg;while (GetMessage(&msg, NULL, 0, 0)){TranslateMessage(&msg);DispatchMessage(&msg);}return msg.wParam;
}LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{switch (msg){case WM_PAINT:{PAINTSTRUCT ps;HDC hdc = BeginPaint(hwnd, &ps);TextOut(hdc, 10, 10, L"Hello, Windows!", 15);EndPaint(hwnd, &ps);}return 0;case WM_CLOSE:DestroyWindow(hwnd);return 0;case WM_DESTROY:PostQuitMessage(0);return 0;}return DefWindowProc(hwnd, msg, wParam, lParam);
}

链接:https://pan.baidu.com/s/1CfdGhw4S-iHOlYu-jb8bvg?pwd=l0ug 
提取码:l0ug

这是我编写好的,尽量和我的一致吧

随便写一个简单的GUI程序。,功能就是简单地弹出一个窗口

我们的目的是在代码空白区段添加一个shellcode,添加一个MessageBox函数

开始:

 硬编码

E8:Call

E9:   Jmp
举个例子

call 0x77E5425FE8 13 88 E1 76jmp 0x2345678E9 2B 2B 00 00

但是我们分析可以发现,无论是E8还是E9,后面的地址貌似都不是直接小端序转化过来的地址

真正要跳转的地址=E8这条指令的下一条指令的地址 + X X=真正要跳转的地址 - E8要要跳转的地址的下一条指令的地址

这里用具体例子分析

#include <iostream>
using namespace std;void func()
{cout << "666" << endl;
}int main()
{func();return 0;
}int main()
{
00DA25C0 55                   push        ebp  
00DA25C1 8B EC                mov         ebp,esp  
00DA25C3 81 EC C0 00 00 00    sub         esp,0C0h  
00DA25C9 53                   push        ebx  
00DA25CA 56                   push        esi  
00DA25CB 57                   push        edi  
00DA25CC 8B FD                mov         edi,ebp  
00DA25CE 33 C9                xor         ecx,ecx  
00DA25D0 B8 CC CC CC CC       mov         eax,0CCCCCCCCh  
00DA25D5 F3 AB                rep stos    dword ptr es:[edi]  
00DA25D7 B9 29 F0 DA 00       mov         ecx,offset _8810881B_stack@cpp (0DAF029h)  
00DA25DC E8 A3 ED FF FF       call        @__CheckForDebuggerJustMyCode@4 (0DA1384h)  func();
00DA25E1 E8 62 ED FF FF       call        func (0DA1348h)  return 0;
00DA25E6 33 C0                xor         eax,eax  
}
00DA25E8 5F                   pop         edi  
00DA25E9 5E                   pop         esi  
00DA25EA 5B                   pop         ebx  
00DA25EB 81 C4 C0 00 00 00    add         esp,0C0h  
00DA25F1 3B EC                cmp         ebp,esp  
00DA25F3 E8 97 EC FF FF       call        __RTC_CheckEsp (0DA128Fh)  

对照着汇编可以看到call func 的机器码对应的是E8 62 ED FF FF
之前说的
真正要跳转的地址=E8这条指令的下一条指令的地址 + X
X=真正要跳转的地址 - E8要要跳转的地址的下一条指令的地址


我们来实际计算一下
真正要跳转的地址是0XDA1348
Call结束的下一个地址是0xDA25E6
因此我们用计算器算一下

刚好就是对应着FF FF ED 62,小端序转换就是62 ED FF FF ,和我们看到的对应的机器码是一样的

内存对齐和文件对齐

由于教程使用的飞鸽.exe的 SectionAlignment和FileAlignment 大小是一样的,导致很多人没有理解到添加ShellCode的精髓,所以推荐大家用文件和内存对齐不一致的程序来练手,就比如我上传的文件

 我上传的这俩对齐大小就不一样,非常适合拿来练手

由于这俩对齐不一样,因此我们要多算一些东西,比如在在编写Shellcode的时候,使用Call,后面跟着计算出来的地址应该是以在内存中的地址算出的,而不是文件中的
以及后面E9 Jmp后面跟着的地址也是一样,都是按照拉伸后的ImageBuffer来算的

还有就是OEP,也就是  AddressOfEntryPoint ,这个入口点的计算是在内存的入口点地址直接减去ImageBase算出来的,也就是说这个偏移是内存的偏移而不是文件中的偏移!

比如我们在图片看到的OEP是0x1474,并不意味着程序入口点在文件中的位置是0x1474,它的真正意思是程序的入口点在 内存 中的地址是 ImageBase+ OEP,所以程序在内存的入口点是0x401474.  (这一点很重要,我被带沟里了,后续也会用到)

节表

typedef struct _IMAGE_SECTION_HEADER {
0x00 BYTE Name[IMAGE_SIZEOF_SHORT_NAME];
union {
0x08 DWORD PhysicalAddress;
0x08 DWORD VirtualSize;
} Misc;
0x0c DWORD VirtualAddress;
0x10 DWORD SizeOfRawData;
0x14 DWORD PointerToRawData;
0x18 DWORD PointerToRelocations;
0x1c DWORD PointerToLinenumbers;
0x20 WORD NumberOfRelocations;
0x22 WORD NumberOfLinenumbers;
0x24 DWORD Characteristics;
};/*
- Name:段名,是一个8字节的`ASCII`字符串,不足8字节用0补齐。
- VirtualSize:虚拟大小,标识节在**内存**中占用的大小,请勿与`PhysicalSize`(物理大小)混淆。(对其前得大小)这Misc联合体 双字 是该节在没有对其前的真实尺寸,该值可以不准确,(在内存中拉伸后的实际大小)
- VirtualAddress:虚拟地址,标识**节**在**内存中**对应段头的地址,与实际加载的位置有关。(**节**在内存的偏移地址,加上ImageBase才是在内存的真正地址)
- SizeOfRawData:物理大小,节在**PE文件**中该段的占用大小,不足以文件对齐单位则会进行填充。(对齐后的长度)
- PointerToRawData:物理地址,标识该段在**文件中**的偏移位置。
- PointerToRelocations:重定向表的偏移位置。
- PointerToLinenumbers:行号表的偏移位置。
- NumberOfRelocations:重定向表数量。
- NumberOfLinenumbers:行号表数量。
- Characteristics:标识该段的各种属性信息,包括下列常用属性:- IMAGE_SCN_MEM_READ:可读;- IMAGE_SCN_MEM_WRITE:可写;- IMAGE_SCN_MEM_EXECUTE:可执行;- IMAGE_SCN_CNT_CODE:代码段;- IMAGE_SCN_CNT_INITIALIZED_DATA:已初始化数据段;- IMAGE_SCN_CNT_UNINITIALIZED_DATA:未初始化数据段;- IMAGE_SCN_LNK_INFO:包含附加信息。
*/

 这是节表的结构。

这是文件和内存对齐不一致时的情况

由于存在对齐,因此在例如.text和.data段之间,可能会留下足够长的空隙让我们写入shellcode,其实在哪个段写都无所谓,重要的是添加的代码要正确,也就是shellcode地址要正确,OEP要正确,这些都是要经过计算的。

实战

 这是节表的信息

可以看到在文件中,.text结束的地址是Raw Size +Raw Offset=0x1400,放到WinHex里看看

还是可以看到有相当长的空闲区可以让我们写的,那么我们就从0X12E0开始添加我们的Shellcode吧。

我们要添加的代码就是

MessageBox(0, 0, 0, 0);
000F1A8D 8B F4                mov         esi,esp  
000F1A8F 6A 00                push        0  
000F1A91 6A 00                push        0  
000F1A93 6A 00                push        0  
000F1A95 6A 00                push        0  
000F1A97 FF 15 F4 B0 0F 00    call        dword ptr [__imp__MessageBoxW@16 (0FB0F4h)]

当然MessageBox毕竟是动态链接库里的函数,因此我们需要打开OD或者X32dbg,定位一下MessageBox的具体地址

比如我用X32dbg找到的MessageBox地址就是0x77219B00

OK,开始改

 先打个模板。
首先我们要计算的是Call ,也就是计算E8后面的机器码是什么
根据前面说到的公式
X=真正要跳转的地址 - E8要要跳转的地址的下一条指令的地址

真正要跳转的地址为   0x77219B00
Call下一条指令的地址是0x12E0+0x8(4个Push 0) + 0x5(Call的长度)=0x12ED

正如我们之前所说的那样,E8 E9后面跟着的地址的计算,一切都是要以内存的地址来计算
因此在文件中的0X12ED在内存是多少呢?

首先0X12ED在.text段的偏移是   0x12ED- 0x400(.text在文件的偏移)=EED

.text段在内存的起始地址是0x1000,加上偏移就是0x1EED,再加上ImageBase就是0X401EED

所以经过计算 
X=真正要跳转的地址 - E8要要跳转的地址的下一条指令的地址
即 0x77219B00 - 0X401EED = 0x76E17C13
换成小端序就是 13 7C E1 76
 

接下来就是跳回到原来的入口点地址0x1474
0x1474在内存的地址就是0x401474
X=真正要跳转的地址 - E9要要跳转的地址的下一条指令的地址
E9要要跳转的地址的下一条指令的地址(文件中)=0X12ED+0X5=0X12F2
0x12F2在内存中的地址就是(参考之前的算法)0x1EF2,加上ImageBase就是401EF2
因此0X401474-0x401EF2=0xFFFF F582
换成小端序就是 82 F5 FF FF

最后一件事就是修改OEP了,文件中的0x12E0在内存中对应的地址是0x401EE0,所以OEP应该改为1EE0

 另存为看看

成功弹出窗口! 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/89495.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Pycharm 搭建 Django 项目,看完这一篇就够了

1. 安装需求 在使用 python 框架 Django 需要注意下面事项 Pycharm 版本是专业版而不是社区版本Pycharm 配置好了 python 解释器 &#xff08;一般我们现在用的都是python3&#xff09;我自己使用的是 Pycharm 版本是2020.1.2 2. 准备工作 2.1 新建项目 首先我们打开 Pycharm …

Linux离线安装elasticsearch|header|kibna插件最详细

1.准备软件安装包 [hadoophost152 elasticsearch]$ ll -rw-r--r--. 1 hadoop hadoop 515807354 9月 23 23:40 elasticsearch-8.1.1-linux-x86_64.tar.gz -rw-r--r--. 1 hadoop hadoop 1295593 9月 23 23:48 elasticsearch-head-master.tar.gz -rw-r--r--. 1 hadoop hadoop…

记录一个 GUI 库的对比测试结果

1&#xff0c;Java 的 JavaFX 2&#xff0c;golang 的 Fyne 1, Java 测试的是一个俄罗斯方块的 GUI 程序。一切正常。 2&#xff0c;Golang github 的原仓库网络问题&#xff0c;没能测试上&#xff0c;使用以下库 https://gitee.com/mirrors/Fyne 下载代码后提示“编译失…

Tomcat 与 JDK 对应版本关系

对应关系 Tomcat版本 jdk版本11.0.x JDK 21及以后10.1.x JDK11及以后10.0.xJDK1.8及以后9.0.x JDK1.8及以后8.5.xJDK1.7及以后8.0.x JDK1.7及以后 查看对应关系方法&#xff1a; 登陆Tomcat官网&#xff1a;Apache Tomcat - Welcome! 结果&#xff1a;

Picgo

title: “Picgo” createTime: 2021-07-01T12:05:5808:00 updateTime: 2021-07-01T12:05:5808:00 draft: false author: “name” tags: [“未标签”] categories: [“未分类”] description: “测试的” picgo 地址 : /home/zhu/software/node/node-v14.15.0-linux-x64/bin文…

河北吉力宝以步力宝健康鞋引发的全新生活生态商

在当今瞬息万变的商业世界中&#xff0c;成功企业通常都是那些不拘泥于传统、勇于创新的先锋之选。河北吉力宝正是这样一家企业&#xff0c;通过打造一双步力宝健康鞋&#xff0c;他们以功能性智能科技穿戴品为核心&#xff0c;成功创造了一种结合智能康养与时尚潮流的独特产品…

C#读取CAD文件(dwg/dxf)并处理

文章目录 一、前言二、调研过程2.1 CAD相关2.2 DWG2.3 DXF2.4 小结三、解析CAD的库3.1 netDxf3.2 Teigha3.2.1 官网获取3.2.2 网上获取四、图形计算一、前言 需求: 项目要求识别CAD图纸(图纸内容与现实事物比例是1:1)中的内容,并提取出一些关键信息。 这里的CAD图纸是指C…

unity 实用框架

单例模式基类 类不继承mono的单例基类 /// <summary> /// 单例基类 /// </summary> //泛型解决&#xff0c;给他一个约束要么是这个类本身要么是它的子类 public class SingleBase<T>where T : SingleBase<T> {protected SingleBase() { }//线程锁。…

C++ 类和对象(4)构造函数

C的目标之一是让使用类对象就像使用标准类型一样&#xff0c;但是常规的初始化语法不适用于类似类型Stock&#xff1a; int year 2001&#xff1b; struct thing {char * pn;int m; }; thing amabob {"wodget",-23}; //有效初始化 Stock hot {"Sukies Autos…

Leetcode 992. K 个不同整数的子数组

文章目录 题目代码&#xff08;9.27 首刷看解析&#xff09; 题目 Leetcode 992. K 个不同整数的子数组 代码&#xff08;9.27 首刷看解析&#xff09; 滑动窗口&#xff0c;恰好转换为&#xff1a;最多K个不同的数 - 最多K-1个不同的数 class Solution { public:int subarr…

kafka伪集群部署,使用KRAFT模式

1:拉去管理kafka界面UI镜像 docker pull provectuslabs/kafka-ui2:拉去管理kafka镜像 docker pull bitnami/kafka3:docker-compose.yml version: 3.8 services:kafka-1:container_name: kafka1image: bitnami/kafka ports:- "19092:19092"- "19093:19093&quo…

测试用例的八大基本准则

测试用例的八大基本准则 测试用例的八大基本准则功能测试性能测试兼容性测试安全测试可靠性测试易用性测试数据库测试接口测试 测试案例 测试用例的八大基本准则 上节测试用例的设计中我们讨论如何设计一个测试用例&#xff0c;知道了测试用例的设计有&#xff1a;“边界值&am…

Linux命令(87)之pwd

linux命令之pwd 1.pwd介绍 linux命令pwd(全称&#xff1a;print working directory)用来列出当前目录 2.pwd用法 pwd [参数] pwd参数(了解即可&#xff0c;99.99%用不到) 参数说明-L显示逻辑路径-P显示实际物理路径 3.实例 3.1.显示当前目录 命令&#xff1a; pwd [ro…

如何制作gif动图gif (多图合成gif、GIF录制软件、视频制作成GIF动图)

文章目录 1 在线制作多图合成gif动画2 GIF录制软件3 将现有的视频 制作成GIF动图 1 在线制作多图合成gif动画 在线制作gif动画链接:https://www.matools.com/gif ①选择需要制作gif动画的图片将其添加 ②调整时间间隔&#xff0c;图片宽高等设置 ③一键生成gif ④下载到本…

目标检测YOLO实战应用案例100讲-区域卷积网络在阴影环境目标检测上的研究与应用(下)

目录 5.2 阴影检测模块与街景检测模块实验设置 5.2.1 实验环境与工具 5.2.3 损失函数 5.2.4 实验具体流程 5.3 实验评估与对比 5.3.1 两类实验的评估标准 5.3.2 两类实验结果对比 阴影环境下街景目标检测系统的实现 6.1 系统概述 6.2 系统软硬件环境 6.3 功能模块设计 6.4 系统…

【OpenSSH漏洞修复】升级到openssh9.4p1版本

实战环境 操作系统:Centos7.9 openssh版本:7.4 重要的升级文件 使用rpm包升级 D:\Linux基线离线安装包\openssh9.4-升级包 的目录openssh-9.4p1-4.el7.x86_64.rpm openssh-clients-9.4p1-4.el7.x86_64.rpm openssh-server-9.4p1-4.el7.x86_64.rpm需要自己去官网下载离线rp…

自定义子组件的v-model

一、传统的父子传参 作为前端程序员&#xff0c;我们在开发时&#xff0c;用到最多的就是父子传参了吧&#xff0c;这一点相信大家都很熟悉了&#xff0c;在这里简单的说一下 1.父传子 &#xff08;1&#xff09; 在父组件中引入子组件&#xff0c;并在父组件的components中注…

基于PLE结合卡尔曼滤波的RSSI定位算法matlab仿真

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 5.算法完整程序工程 1.算法运行效果图预览 2.算法运行软件版本 MATLAB2022a 3.部分核心程序 ............................................................... for Num_xb Num_xb2Num_…

C++思考和一些代码规范(09/28)

文章目录 一、C的一些思考记录1&#xff09;C函数进化&#xff08;函数->函数指针->函数模板->仿函数|函数对象->lambda表达式&#xff09; 一、C的一些思考记录 1&#xff09;C函数进化&#xff08;函数->函数指针->函数模板->仿函数|函数对象->lamb…

golang: Code of Conduct

目录 1. golang: Code of Conduct 1. golang: Code of Conduct Go Community Code of Conduct