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

news2024/11/18 8:52:35

目录

 硬编码

内存对齐和文件对齐

节表

实战


滴水逆向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 0x77E5425F

E8 13 88 E1 76

jmp 0x2345678

E9 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.coloradmin.cn/o/1047074.html

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

相关文章

Springboot和Vue:六、ORM介绍+MybatisPlus快速上手

ORM和Mybatis(Plus)介绍 ORM&#xff08;Object Relational Mapping 对象关系映射&#xff09;即映射程序中的对象和数据库中的数据。 MyBatis是一款优秀的数据持久层ORM框架&#xff0c;能够非常灵活地实现动态SQL&#xff0c;可以使用XML或注解来配置和映射原生信息&#xf…

联想笔记本重装系统Win10步骤和详细教程

我们给笔记本电脑重装系统可以解决运行缓慢、出现错误提示等问题&#xff0c;恢复笔记本电脑的流畅运行状态。但是&#xff0c;很多使用联想笔记本电脑的用户不知道重装系统Win10的具体步骤&#xff0c;下面小编给大家介绍关于重装联想笔记本电脑Win10系统的方法步骤吧。 推荐下…

JAMA子刊:最新研究发现腰臀比更能预测死亡

肥胖会危害健康已经称为一个共识&#xff0c;评价肥胖的指标也有多种&#xff0c;例如体质指数&#xff08;BMI)、腰围等。比如BMI大于24为超重&#xff0c;大于28为肥胖&#xff1b;男性腰围≥90cm&#xff0c;女性腰围≥85cm为中心性肥胖。 这些肥胖界值的确定&#xff0c;主…

自制网页。

文章目录 注:代码中图片等素材均来自网络,侵删 20230920_213831 index.html <!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-…

Java应用生产Full GC或者OOM问题如何定位

1 引言 生产应用服务频繁Full GC却无法释放内存&#xff0c;甚至可能OOM&#xff0c;这种情况很有可能是内存泄露或者堆内存分配不足&#xff0c;此时需要dump堆信息来定位问题&#xff0c;查看是哪些地方内存泄漏。 Dump文件也称为内存转储文件或内存快照文件&#xff0c;是…

uni-app:canvas绘制图形3

效果 代码 <template><view><!-- 创建了一个宽度为300像素&#xff0c;高度为200像素的canvas元素。canvas-id属性被设置为"firstCanvas"&#xff0c;可以用来在JavaScript中获取该canvas元素的上下文对象。 --><canvas style"width:200…

mysql面试题3:谈谈你知道的MySQL索引?MySQL中一个表可以创建多少个列索引?MySQL索引有哪几种?他们的优缺点是什么?

该文章专注于面试,面试只要回答关键点即可,不需要对框架有非常深入的回答,如果你想应付面试,是足够了,抓住关键点 面试官:谈谈你知道的MySQL索引? MySQL索引是一种特殊的数据结构,用于加速数据库的查询操作。它通过存储列值和对应记录的指针,可以快速定位到满足查询…

计算机竞赛 深度学习卷积神经网络垃圾分类系统 - 深度学习 神经网络 图像识别 垃圾分类 算法 小程序

文章目录 0 简介1 背景意义2 数据集3 数据探索4 数据增广(数据集补充)5 垃圾图像分类5.1 迁移学习5.1.1 什么是迁移学习&#xff1f;5.1.2 为什么要迁移学习&#xff1f; 5.2 模型选择5.3 训练环境5.3.1 硬件配置5.3.2 软件配置 5.4 训练过程5.5 模型分类效果(PC端) 6 构建垃圾…

计算机网络-网络层总结

目录 网络层提供的两种服务 1、分组转发和路由选择 2、网络层提供的两种服务 网际协议IP 1、虚拟互联网 2、网际协议IP 3、异构网络互连 4、IPv4地址 概述 4.1分类编址的IPv4地址 4.2划分子网的IPv4地址 4.3无分类编址的IPv4地址 4.4IPv4地址的应用规划 4.5MAC地址…

使用 Spring Data Redis 访问 Redis 的 Spring Boot 应用

使用 Spring Data Redis 访问 Redis 的 Spring Boot 应用 Redis是一个高性能的内存键值存储数据库&#xff0c;常用于缓存、会话管理和消息队列等场景。Spring Boot通过Spring Data Redis提供了方便的方式来与Redis进行交互。在本文中&#xff0c;我们将详细介绍如何使用Sprin…

nodejs+vue 经典建筑网站elementui

第1章 项目概述 1 1.1 问题描述 1 1.2 项目目标 1 1.3 项目适用范围 2 1.4 项目应遵守的规范与标准 2 1.5 涉众 2 具有功能强大、支持跨平台、运行速度快、安全性高、成本低等优点。而对于后者我们使用 来完成它&#xff0c;使其网页功能完备&#xff0c;界面友好、易开发、易…

直方图投影法判断裂缝走势(裂缝类型)

裂缝类型 裂缝类型有很多种&#xff0c;这里我们仅仅判断线性裂缝与网状裂缝&#xff0c;线性裂缝按照其走势有可分为横向裂缝、纵向裂缝和斜向裂缝。 我觉得大家应当有这样的意识&#xff0c;面对网状裂缝&#xff0c;它的二维参数是否有意义&#xff1f;答案是没有&#xf…

宝塔Node部署nuxt3

宝塔Node部署nuxt3 1、首先本地执行打包 yarn build2、然后把目录中的这个文件压缩成zip 3、在宝塔文件处添加一个网站的文件目录&#xff0c;并把文件解压到里面 4、点击左侧的网站&#xff0c;然后选择node项目&#xff0c;选择node版本安装 5、安装完后&#xff0c;点击新…

【C语言】快速排序

文章目录 一、hoare版本二、挖坑法三、前后指针法四、非递归快排五、快速排序优化1、三数取中选key值2、小区间优化 六、代码测试 一、hoare版本 快速排序是Hoare于1962年提出的一种二叉树结构的交换排序方法&#xff0c;其基本思想为&#xff1a;任取待排序元素序列中的某元素…

云中的网络Qos

在 Linux 下&#xff0c;可以通过 TC 控制网络的 QoS&#xff0c;主要就是通过队列的方式。 第一大类称为无类别排队规则&#xff08;Classless Queuing Disciplines&#xff09;。pfifo_fast 分为三个先入先出的队列&#xff0c;称为三个 Band。根据网络包里面 TOS&#xff0…

VScode调试复杂C/C++项目

以前都是用的VScode调试c/cpp的单个文件的编译和执行, 但是一遇到大型项目一般就用gdb了, gdb的调试效率和VScode差距还是比较大的, 但最近发现VScode其实也能调试复杂的cpp项目, 所以记录一下. 首先明确一下几点: 首先cpp文件需要经过编译, 生成可执行文件, 然后通过运行/调…

百度搜索逐步恢复优质网站权限

我是卢松松&#xff0c;点点上面的头像&#xff0c;欢迎关注我哦&#xff01; 从9月25日开始&#xff0c;有越来越多的站长和卢松松反馈&#xff0c;说他们的站可以正常入驻百度搜索资源平台了。我也试了试卢松松博客&#xff0c;果然&#xff0c;可以正常提交了。还是以前的…

iTOP-3568开发板Ubuntu下安装ADB工具

在虚拟机 Ubuntu 使用以下命令安装 ADB&#xff0c;如下图所示&#xff1a; sudo apt install adb 接下来进行测试&#xff0c;执行如下命令&#xff0c;确认 adb 安装是否成功。 adb version 如上图所示&#xff0c;执行命令能成功获取到 adb 版本信息&#xff0c;说明 adb …

防火墙网络接口下面多个外网地址,只有第一地址可以访问通其他不通

环境&#xff1a; 主备防火墙 8.0.75 AF-2000-FH2130B-SC 问题描述&#xff1a; 两台防火墙双击热备&#xff0c;高可用防火墙虚拟网络接口Eth4下面有多个外网地址&#xff0c;只有第一地址可以访问通其他不通 解决方案&#xff1a; 1.检查防火墙路由设置&#xff08;未解决…

3D WEB轻量化引擎HOOPS助力3D测量应用蓬勃发展:效率、精度显著提升

在3D开发工具领域&#xff0c;Tech Soft 3D打造的HOOPS SDK已经崭露头角&#xff0c;成为了全球领先的3D领域开发工具提供商。HOOPS SDK包括四种不同的3D软件开发工具&#xff0c;已成为行业的翘楚。 其中&#xff0c;HOOPS Exchange以其CAD数据转换的能力脱颖而出&#xff0c…