手动改造UPX壳,增加IAT保护

随便拿Delphi7,新建一个VCL窗体程序,画一个按钮,写两行代码。这一步骤讲究的是什么呢?率性而为,反正没什么卵用。比如,俺写的是这玩意。

<span style="color:#666666"><span style="background-color:#ffffff">procedure TForm1.Button1Click(Sender: TObject);beginMessageBox(0, '鸿雁在天鱼在水,惆怅此情难寄!', '', MB_ICONINFORMATION);end;</span></span>


编译,打开,点按钮,确认一切无误。


给它套上一层UPX的外壳。


OllyDbg载入它,找到OEP不用我多说了吧?ESP定律干掉,或者往EP后面找popad,下面的jmp就是了。
中断在OEP后,随便找一个API调用语句,比如jmp dword ptr[xxxxxxxx],或者call dword ptr[xxxxxxxx]啦,具体是编译器来说话的。

比如我找到了这里。


在CALL上面按回车,跟进这个CALL看看。


转到DUMP窗口看看,用ADDRESS模式,发现这里就是IAT了。


 


这里有一个比较坑爹的问题了,我们知道啊,这桌面时代,就是Microsoft(巨硬)和Borland(宝兰)两个公司在干仗,开发工具一般就是这两家公司的产品。
这编译器构造PE的时候,导入表的处理就有分歧了。
Microsoft的IAT是整整齐齐,用一个DWORD类型的0,隔开每个对应每个DLL的IAT,而Borland就坑爹了,它的IAT是散乱的,也就是说,每个DLL对应的IAT表可能在内存分布中是不连续的。所以,脱壳的时候,修复IAT,这Borland就是急死人了,最好就是找到外壳填充IAT的地方,来Patch它得到一份完整的IAT表。


往下面翻一翻,就能找到MessageBoxA了。可以拉到IAT表头部之前,自己预判,然后往后面找MessageBoxA在你系统上的地址。
如果你用的Delphi是XE版本,那么要注意,你需要找MessageBoxW!
在0x4521AC下一个硬件写入断点(DWORD)长度,重新运行程序,找到外壳在这里填充IAT。
注意,我中断了两次,第一次发现0x4521AC里面是0,第二次才来到正确地方。

<span style="color:#666666"><span style="background-color:#ffffff">0046531A   .  57            PUSH EDI                                     ;  压入API名0046531B   .  48            DEC EAX0046531C   .  F2:AE         REPNE SCAS BYTE PTR ES:[EDI]0046531E   .  55            PUSH EBP                                     ;  压入DLL基址0046531F   .  FF96 F05A0600 CALL DWORD PTR DS:[ESI+0x65AF0]              ;  取地址00465325   .  09C0          OR EAX,EAX00465327   .  74 07         JE SHORT Project1.0046533000465329   .  8903          MOV DWORD PTR DS:[EBX],EAX                   ;  填充</span></span>


现在,我们来考虑一下怎么给它设计一个API重定向。我参考了一下tELOCK壳。
00A80043   /EB 01           jmp     short 00A80046
00A80045   |90              nop
00A80046   \E8 0B000000     call    00A80056
00A8004B    33C4            xor     eax, esp
00A8004D    40              inc     eax
00A8004E    E9 0B000000     jmp     00A8005E
00A80053    98              cwde
00A80054    13C7            adc     eax, edi
00A80056    B8 8EBC9725     mov     eax, 0x2597BC8E
00A8005B    C3              retn
00A8005C    0BC2            or      eax, edx
00A8005E    90              nop
00A8005F    B8 8B14A800     mov     eax, 0xA8148B
00A80064    40              inc     eax
00A80065    FF30            push    dword ptr ds:[eax]               ; kernel32.GetVersion
00A80067    C3              retn

代码执行逻辑很怪,前面都是扭曲变幻产生的垃圾指令,真正有效的只有4条。
<span style="color:#666666"><span style="background-color:#ffffff">00A8005F    B8 8B14A800     mov     eax, 0xA8148B00A80064    40              inc     eax00A80065    FF30            push    dword ptr ds:[eax]               ; kernel32.GetVersion00A80067    C3              retn</span></span>

第一条硬编码,应该是壳解码后生成的,第二条加1,然后得到指针,取出API地址,用Push Ret模拟CALL。

我缩水一下,直接
push 地址
ret
这种情况修复很简单,比如ImportREC在不能识别的IAT里面,用上反汇编功能,就OK了。不过,这里不考虑那么多。方便第一。

首先给加壳后的程序加一个区块,区块的实际大小可以为0,可是加载在内存后的大小应该填写一个较大的值(自己把握)。不理解的话,参考《PE权威指南》一书。


 



区块的属性要可写可读可执行,注意VirtualSize字段。VirtualAddr是0x67000,这是RVA地址。

现在,用OllyDbg打开程序,来到0x467000,这里有了一块全0内存。而且,这块内存的好处是,不在硬盘里面,不占用文件尺寸,是PE被系统装载的时候系统给你的。

我们来设计一下我们的加密伪代码:

首先,我们要解密IAT的代码的机器码是:
68 xx xx xx xx C3
对应了push和ret,xx表示API地址。

一段占用了6字节,然后从壳填充IAT的地方,转到我们的Patch处。保存环境,生成我们新的加密后的IAT地址,转回壳里面,让壳填充。
注意,生成解密IAT代码的时候,我们需要一个全局变量指示新的IAT地址(写入机器码),写完一段递增一次。



现在,给这个程序再添加一个区块,换个工具,因为LordPE不会自己往文件后面补数据。这次要添加在磁盘里面实际存在的区块。用来存放要执行的加密代码。 



 

<span style="color:#666666"><span style="background-color:#ffffff">pushadpushfdmov esi,dword ptr[477000]   ;取出指针地址add esi,6mov edx,esimov byte ptr[esi],0x68inc esimov dword ptr[esi],eax              ;从壳里面跳过来的时候,EAX是API地址add esi,4mov byte ptr[esi],0xC3mov dword ptr[0x477000],edx  ;更新指针popfdpopadmov eax,dword ptr[0x477000]</span></span>


0x477000记得更新为0x466FFA






Patch完成后,看0x467000



修改的地方:


 



修复时,都是无效IAT。



打包一下,修改前后:



小结:
思路很简单,找到壳填充IAT的地方,添加两个区块,一个放解密IAT的代码(stub),一个放我们加密IAT的代码。从壳跳到我们的区块去执行加密,然后,嘿嘿。

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

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

相关文章

FFMPEG+Qt 实时显示本机USB摄像头1080p画面以及同步录制mp4视频

FFMPEGQt 实时显示本机USB摄像头1080p画面以及同步录制mp4视频 文章目录 FFMPEGQt 实时显示本机USB摄像头1080p画面以及同步录制mp4视频1、前言1.1 目标1.2 一些说明 2、效果3、代码3.1 思路3.2 工程目录3.3 核心代码 4、全部代码获取 1、前言 本文通过FFMPEG(7.0.2)与Qt(5.13.…

YOLO系列入门:1、YOLO V11环境搭建

YOLO了解 yolo检测原理 yolo是目标检测模型&#xff0c;目标检测包含物体分类、位置预测两个内容。目前yolo的开发公司官网为&#xff1a;https://docs.ultralytics.com/zh截止到目前2024年10月&#xff0c;最新的是yolo11。关于YOLO的介绍可以参考这篇文章&#xff1a;https…

Python+Django+VUE 搭建深度学习训练界面 (持续ing)

PythonDjangoVUE 搭建深度学习训练界面 &#xff08;持续ing&#xff09; 环境说明 Pycharm 专业版2024.1.4&#xff0c;社区版不支持网页开发 下载链接&#xff1a;https://www.jetbrains.com/pycharm/download/other.html 参考链接&#xff1a;https://www.quanxiaoha.co…

es实现桶聚合

目录 聚合 聚合的分类 DSL实现桶聚合 dsl语句 结果 聚合结果排序 限定聚合范围 总结 聚合必须的三要素&#xff1a; 聚合可配置的属性 DSL实现metric聚合 例如&#xff1a;我们需要获取每个品牌的用户评分的min,max,avg等值 只求socre的max 利用RestHighLevelClien…

BIO,NIO,直接内存,零拷贝

前置知识 什么是Socket&#xff1f; Socket是应用层与TCP/IP协议族通信的中间软件抽象层&#xff0c;它是一组接口&#xff0c;一般由操作系统提供。在设计模式中&#xff0c;Socket其实就是一个门面模式&#xff0c;它把复杂的TCP/IP协议处理和通信缓存管理等等都隐藏在Sock…

vue3使用i18n做国际化多语言,实现常量跟随语言切换翻译

因为我有一个常量的配置文件在项目中&#xff0c;而且有中文内容&#xff0c;我想在切换语言的时候&#xff0c;跟着这个翻译也实时切换&#xff0c;就可以使用computed计算属性实现。 把name改成下面的样子&#xff1a; name: computed(() > t(pad.regularMode)), 就可以…

分享一款录屏、直播软件

光音录屏 光音录屏 是新一代的录屏工具&#xff0c;跟传统录屏工具相比&#xff0c;它不仅可以录制屏幕&#xff0c;还可以同时录制「人像 屏幕」&#xff0c;此外它还提供了美颜、虚拟背景、绿幕抠像、图片、文本编辑、字幕、白板等更多高级功能。你可以将录制好的视频&…

ue5实现数字滚动增长

方法1 https://www.bilibili.com/video/BV1h14y197D1/?spm_id_from333.999.0.0 b站教程 重写loop节点 方法二 写在eventtick里

ffmpeg视频滤镜: 色温- colortemperature

滤镜简述 colortemperature 官网链接 》 FFmpeg Filters Documentation 这个滤镜可以调节图片的色温&#xff0c;色温值越大显得越冷&#xff0c;可以参考一下下图&#xff1a; 咱们装修的时候可能会用到&#xff0c;比如选择灯还有地板的颜色的时候&#xff0c;选暖色调还是…

多厂商的实现不同vlan间通信

Cisco单臂路由 Cisco路由器配置 -交换机配置 -pc配置 华三的单臂路由 -路由器配置 -华三的接口默认是打开的 -pc配置及ping的结果 -注意不要忘记配置默认网关 Cisco-SVI -交换机的配置 -创建vlan -> 设置物理接口对应的Acess或Trunk -> 进入vlan接口&#xff0c;打开接…

【纯血鸿蒙】HarmonyOS和OpenHarmony 的区别

一、开源鸿蒙&#xff08;Open Harmony&#xff09; 鸿蒙系统愿来的设计初衷&#xff0c;就是让所有设备都可以运行一个系统&#xff0c;但是每个设备的运算能力和功能都不同&#xff0c;所以内核的设计上&#xff0c;采用了微内核的设计&#xff0c;除了最基础的功能放在内核…

mfc之tab标签控件的使用--附TabSheet源码

TabSheet源码 TabSheet.h #if !defined(AFX_TABSHEET_H__42EE262D_D15F_46D5_8F26_28FD049E99F4__INCLUDED_) #define AFX_TABSHEET_H__42EE262D_D15F_46D5_8F26_28FD049E99F4__INCLUDED_#if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 // TabSheet.h : …

C++面向对象编程学习

C面向对象编程学习 前言一、C面向对象编程二、知识点学习1. 定义一个类1.1 使用struct定义1.2 使用class定义1.3 struct和class的区别 2. 类的定义方式2.1 单文件定义&#xff08;Inline Definition&#xff09;2.2 分离定义&#xff08;Separate Definition&#xff09;2.3 头…

[bug] vllm 0.6.1 RuntimeError: operator torchvision::nms does not exist

[bug] vllm 0.6.1 RuntimeError: operator torchvision::nms does not exist 环境 python 3.10 torch 2.4.0cu118 torchvision 0.19.0cu118 vllm 0.6.1.post2cu118问题详情 if torch._C._d…

【华为路由】OSPF多区域配置

网络拓扑 设备接口地址 设备 端口 IP地址 RTA Loopback 0 1.1.1.1/32 G0/0/0 10.1.1.1/24 RTB Loopback 0 2.2.2.2/32 G0/0/0 10.1.1.2/24 G0/0/1 10.1.2.1/24 RTC Loopback 0 3.3.3.3/32 G0/0/0 10.1.2.2/24 G0/0/1 10.1.3.1/24 RTD Loopback 0 4.4.4…

【Jenkins】解决在Jenkins Agent节点容器内无法访问物理机的docker和docker compose的问题

解决在Jenkins Agent节点容器内无法访问物理机的docker和docker compose的问题 1. 确定物理机docker和docker compose已经安装2. 编写Jenkins Agent结点docker-compose.yaml配置文件3. 修改docker运行时文件权限4. 启动容器并验证 最近接触到一个发布产物是一个 docker镜像的项…

【K8s】Kubernetes 证书管理工具 Cert-Manager

本文内容均来自个人笔记并重新梳理&#xff0c;如有错误欢迎指正&#xff01; 如果对您有帮助&#xff0c;烦请点赞、关注、转发、订阅专栏&#xff01; 专栏订阅入口 | 精选文章 | Kubernetes | Docker | Linux | 羊毛资源 | 工具推荐 | 往期精彩文章 【Docker】&#xff08;全…

Github优质项目推荐(第八期)

文章目录 Github优质项目推荐 - 第八期一、【manim】&#xff0c;66.5k stars - 创建数学动画的 Python 框架二、【siyuan】&#xff0c;19.5k stars - 个人知识管理软件三、 【GetQzonehistory】&#xff0c;1.3k stars - 获取QQ空间发布的历史说说四、【SecLists】&#xff0…

【Linux系统编程】冯诺依曼体系结构与操作系统

目录 1、冯诺依曼体系结构 1.1 冯诺依曼体系结构的组成 1.2 程序运行时必须要加载到内存 1.3 数据通信 1.4 为什么要有内存 2、操作系统 2.1 概念 2.2 设计OS的目的 2.3 如何理解管理 2.4 系统调用和库函数的概念 1、冯诺依曼体系结构 我们常见的计算机&#xff0c;如…

transforms的使用

示例代码 from PIL import Image from torch.utils.tensorboard import SummaryWriter from torchvision import transforms#打开该图片 img_path"hymenoptera_data/val/bees/10870992_eebeeb3a12.jpg" imgImage.open(img_path) writerSummaryWriter("logs&quo…