渗透技巧之白加黑实战篇

admin 2024年4月24日19:40:15评论25 views字数 4281阅读14分16秒阅读模式

最近需要做一些免杀和后渗透的工作,将一些偏向实战性质的笔记发在这里,给博客清清灰。

1.白加黑原理

1.1 什么是DLL

动态链接库 (DLL) 是一个模块,其中包含可由另一个模块 (应用程序或 DLL) 使用的函数和数据。DLL 可以定义两种类型的函数:导出函数和内部函数。导出的函数旨在由其他模块调用,以及从定义它们的 DLL 中调用。

DLL 提供了一种模块化应用程序的方法,以便可以更轻松地更新和重复使用其功能。当多个应用程序同时使用相同的功能时,DLL 还有助于减少内存开销。这也就是DLL的实际应用场景

1.2 加载DLL的两种方式

加载DLL的可以有两种方式动态加载和静态加载,动态加载,下面我们编写一个dll,实现一个

首先在vs中创建动态链接库项目

可以看到有如下目录结构,可以看到有framework.h、pch.h、dllmain.cpp、pch.cpp四个文件:

其中

framework.h 文件用于包含项目中需要使用的头文件,可以看到已经默认包含了windows头文件

pch.h 是预编译标头文件,dll的导出函数应该在此处定义

dllmain.cpp 文件包含程序的入口点,在 dllmain.cpp 中实现的在 pch.h 中定义函数,当然也可以在其他 cpp 文件中实现,如 pch.cpp 等

DLL_PROCESS_ATTACH: // 当DLL被进程加载时执行,每个新进程只初始化一次。

DLL_THREAD_ATTACH: // 当线程被创建时调用

DLL_THREAD_DETACH: // 当线程结束时执行

DLL_PROCESS_DETACH: // 当DLL被进程卸载时执行

1.2.1 动态加载

生成 windows 空项目

然后创建a.cpp文件

 1 #include <iostream>
 2 #include <Windows.h>
 3 using namespace std;
 4 int main(){
 5     // 加载 DLL
 6     HINSTANCE hDLL = LoadLibrary(L"DemoDLL.dll");  //动态加载dll链接库
 7     if (hDLL == NULL) {
 8         std::cerr << "Failed to load DLL." << std::endl;
 9         return 1;
10     }
11     // 获取 DLL 中的函数指针
12     typedef void (*DllHiJackFunc)();         // 定义Dllfunction函数类
13     DllHiJackFunc dllHiJackFunc = (DllHiJackFunc)GetProcAddress(hDLL, "DllHiJack");
14     if (dllHiJackFunc == NULL) {
15         std::cerr << "Failed to locate function." << std::endl;
16         return 1;
17     }
18
19     // 调用 DLL 中的函数
20     dllHiJackFunc();
21
22     // 卸载 DLL
23     FreeLibrary(hDLL);
24 }

此时如果删除DemoDll.dll,一般情况下程序会奔溃退出,而不会弹窗

1.2.2 静态加载

将pch.h、demoDLL.lib、DemoDLL.dll复制到当前loadDll的项目根目录文件夹下面

lib 文件中包含一些索引信息,记录了 dll 中函数的入口和位置,lib 用于在开发编译时使用,dll 则在运行时使用。

在开发程序时使用 lib 需要两个文件:

.h 头文件,包含 lib 中说明输出的类或符号原型或数据结构。

.lib 文件。

如果你将导出函数定义在 pch.h 文件中,那么开发时就使用如下代码包含这两个文件,当然不要忘记将这俩个文件复制到 dlltest 项目下:

1#include "pch.h"
2#pragma comment (lib, "Dll3.lib")

这样在开发时就可以直接使用 Dll3.dll 中的导出函数了,不需要使用 LoadLibrary 导入 dll,程序执行后会自动寻找相应的 dll 并导入。

 1#include <iostream>
 2
 3// 引用dll的函数定义的头文件
 4#include "pch.h" 
 5
 6// 加载dll的lib库文件
 7#pragma comment(lib,"D:\Desktop\cs\20240401白加黑\LoadDll2\DemoDLL.lib")  
 8
 9// 声明 DllHiJack 函数
10void DllHiJack();
11
12int main() {
13    // 调用 DLL 中的函数
14    DllHiJack();
15
16    return 0;
17}

此时如果删除DemoDll.dll,运行会报错

1.3 什么是白加黑DLL劫持

大部分程序在运行时,都会调用相应需要的dll链接库,我们可以替换这个dll文件,来执行我们自己的代码,这就是DLL劫持。如果可执行文件带了合法签名,则这个可执行文件是在杀软白名单中的,也就是白文件,我们编写一个恶意dll,搭配这个白文件就能绕过杀软检测,所以白加黑通常也就是白exe+黑dll。

当exe需要调用dll时,会去系统搜索dll的位置,默认情况下搜索的优先级如下:

加载应用程序的文件夹。

系统文件夹。使用 GetSystemDirectory 函数检索此文件夹的路径。

16 位系统文件夹。

Windows 文件夹。使用 GetWindowsDirectory 函数获取此文件夹的路径。

当前文件夹

环境变量中列出的 PATH 目录

上述搜索位置见https://learn.microsoft.com/zh-cn/windows/win32/dlls/dynamic-link-library-search-order

2. 首先寻找白加黑的exe和dll样本

手工查找:可以直接将exe复制到单独的目录,然后点击后查看缺少哪些dll,如果只缺少一个dll,则可以拿来当白文件。

自动化查找,推荐用这个工具就够了,别的也用不着那么多

https://www.bilibili.com/video/BV18N41157KF/?spm_id_from=333.788&vd_source=f1d43e0efc6a3c867b0bda5c485cefb6

https://github.com/HexNy0a/SkyShadow

3.白加黑实战

这里首先找到网易云音乐的cloudmusic_reporter.exe加载了libcurl.exe,且exe有签名,且exe为64位,完美符合我们的需求。

3.1 下面创建一个远程shellcode

 1# 将shellcode的二进制文件与0x88异或,然后以16进制保存在文本中
 2
 3def xor_with_cc(data):
 4    return bytes([byte ^ 0x88 for byte in data])
 5
 6def main():
 7    # 读取二进制文件
 8    with open("payload.bin", "rb") as f:
 9        binary_data = f.read()
10
11    # 将数据与 0xcc 进行异或操作
12    result_data = xor_with_cc(binary_data)
13
14    # 将结果以十六进制格式保存到文本文件中
15    with open("shellcode", "w") as f:
16        f.write(result_data.hex())
17
18main()

最终保证http://xxxxx.com/shellcode访问可以得到这个shellcode

3.2 创建一个dll项目,添加导出函数

下面的导出函数是从https://github.com/HexNy0a/SkyShadow工具生成的,直接将其复制到dllmain.cpp中即可

1extern "C" __declspec(dllexport) int curl_easy_getinfo() { return 0; }
2extern "C" __declspec(dllexport) int curl_global_cleanup() { return 0; }
3extern "C" __declspec(dllexport) int curl_global_init() { return 0; }
4extern "C" __declspec(dllexport) int curl_easy_perform() { return 0; }
5extern "C" __declspec(dllexport) int curl_slist_append() { return 0; }
6extern "C" __declspec(dllexport) int curl_easy_init() { return 0; }
7extern "C" __declspec(dllexport) int curl_easy_setopt() { return 0; }
8extern "C" __declspec(dllexport) int curl_easy_cleanup() { return 0; }

3.3 在dllmain中解决死锁问题

直接导入https://github.com/Neo-Maoku/DllMainHijacking/blob/master/DllMainHijacking/dllmain.cpp中的UNLOOK();函数即可

3.4 执行远程的shellcode

这里采用的是远程访问shellcode地址,然后执行shellcode,代码直接看https://github.com/xf555er/Shellcode_SeparationLoad

代码这里就不放了

4. 其他

4.1 dllmain中执行shellcode的两种方式

解决死锁问题,然后在当前进程中执行shellcode

进程注入的方式,比如“通过 CreateProcess 创建一个 rundll32 进程并在其内存中分配内存写入 shellcode,并通过修改其程序计数器 Rip 指向写入的 shellcode 地址,然后恢复线程执行 shellcode。也就是说并没有在 DllMain 中上线而是在其他程序中上线。”

4.2 关于持久化

最好是在白加黑执行过程中同时做好持久化,我喜欢用计划任务,绕过杀软的方式比较多,利用一些小众接口即可,上线后做持久化更容易被查杀

5. 参考文章

https://www.freebuf.com/articles/system/333690.html

https://cloud.tencent.com/developer/article/2360981

END

文:SAUCERMAN

链接:https://saucer-man.com/information_security/1171.html

版权声明:著作权归作者所有。如有侵权请联系删除

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年4月24日19:40:15
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   渗透技巧之白加黑实战篇http://cn-sec.com/archives/2687612.html

发表评论

匿名网友 填写信息