首页 > 系统相关 >windows栈回溯功能示例——漏洞利用检测

windows栈回溯功能示例——漏洞利用检测

时间:2024-02-06 11:55:17浏览次数:30  
标签:调用 函数 示例 windows API 回溯 堆栈

利用windows栈回溯如何进行漏洞利用检测?

利用Windows栈回溯进行漏洞利用检测是一个复杂的过程,它通常涉及监控可疑或危险函数的调用,并分析调用这些函数的上下文来判断是否存在潜在的漏洞利用尝试。这种方法需要深入理解漏洞利用技术、危险函数的正常与异常使用模式,以及堆栈回溯的技术细节。以下是一个简化的过程说明,展示如何使用栈回溯进行漏洞利用检测:

1. 确定监控目标

首先,需要确定哪些函数是潜在的漏洞利用目标。这些通常是那些可以被用来执行任意代码、修改内存或进行危险操作的函数。例如,一些内存操作函数(如memcpystrcpy等)在不正确使用时可能导致缓冲区溢出,这是一类常见的漏洞利用方法。

2. 实现函数钩子

使用API钩子技术监控这些敏感函数的调用。当这些函数被调用时,你的钩子函数将被激活。在钩子函数中,你可以实现各种检测逻辑。

3. 执行堆栈回溯

在钩子函数中,执行堆栈回溯来获取当前的调用堆栈。这可以通过CaptureStackBackTraceStackWalk64等函数实现。通过分析调用堆栈,你可以尝试识别出不正常或可疑的调用模式,这可能表明正在尝试利用漏洞。

4. 分析调用模式

分析调用堆栈,寻找异常或可疑的模式。这可能包括:

  • 不寻常的调用深度。
  • 知名危险函数的非正常调用。
  • 来自可疑内存区域(如已释放的内存、堆栈溢出区域等)的调用。
  • 其他与已知攻击模式相匹配的特征。

5. 实施检测逻辑

根据分析结果实施具体的检测逻辑。这可能包括记录详细信息、生成警报、中止可疑操作等。

示例代码

以下是一个非常基础的示例,展示如何在钩子函数中执行堆栈回溯:

#include <windows.h>
#include <DbgHelp.h>
#include <iostream>

#pragma comment(lib, "Dbghelp.lib")

void PrintStackTrace() {
    PVOID stack[128];
    USHORT frames = CaptureStackBackTrace(0, 128, stack, NULL);

    for (USHORT i = 0; i < frames; i++) {
        std::cout << "Frame " << i << ": " << stack[i] << std::endl;
    }
}

// 假设这是你的钩子函数
void MyHookedFunction() {
    PrintStackTrace();
    // 在这里实现你的检测逻辑
}

  

注意事项

  • 这种方法对性能有一定影响,尤其是在高频调用的函数上。
  • 准确性依赖于对漏洞利用技术的深入理解和准确的模式识别。
  • 需要考虑到正常程序行为的多样性,以减少误报。
  • 实现这种检测机制需要较高的权限,并可能被恶意软件检测和绕过。

总之,利用Windows栈回溯进行漏洞利用检测是一种高级且复杂的技术,它需要深厚的安全知识和经验。在实际应用中,这通常是作为更广泛的安全策略和防御机制的一部分来实施的。

 

一个获取栈回溯的示例程序:

#include <windows.h>
#include <iostream>
#include <dbghelp.h>

#pragma comment(lib, "dbghelp.lib")

void PrintStackTrace() {
	const int MaxFrames = 62;
	PVOID backTrace[MaxFrames];
	USHORT frames = CaptureStackBackTrace(0, MaxFrames, backTrace, NULL);

	// 初始化符号处理器
	SymInitialize(GetCurrentProcess(), NULL, TRUE);

	for (USHORT i = 0; i < frames; i++) {
		DWORD64 address = (DWORD64)(backTrace[i]);
		DWORD64 displacementSym = 0;
		char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR)];
		PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)buffer;

		pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO);
		pSymbol->MaxNameLen = MAX_SYM_NAME;

		if (SymFromAddr(GetCurrentProcess(), address, &displacementSym, pSymbol)) {
			std::cout << "Frame " << i << ": " << pSymbol->Name << std::endl;
		}
		else {
			std::cout << "Frame " << i << ": " << backTrace[i] << " - Symbol resolution failed." << std::endl;
		}
	}

	// 清理符号处理器
	SymCleanup(GetCurrentProcess());
}

void FunctionD() {
	PrintStackTrace(); // 在最深的调用层中捕获堆栈回溯
}

void FunctionC() {
	FunctionD();
}

void FunctionB() {
	FunctionC();
}

void FunctionA() {
	FunctionB();
}

int main() {
	FunctionA();
	return 0;
}

  

效果:

Frame 0: PrintStackTrace
Frame 1: FunctionD
Frame 2: FunctionC
Frame 3: FunctionB
Frame 4: FunctionA
Frame 5: main
Frame 6: invoke_main
Frame 7: __scrt_common_main_seh
Frame 8: __scrt_common_main
Frame 9: mainCRTStartup
Frame 10: BaseThreadInitThunk
Frame 11: RtlGetAppContainerNamedObjectPath
Frame 12: RtlGetAppContainerNamedObjectPath

  

在这个例子中,我们首先定义了一系列嵌套调用的函数:FunctionA 调用 FunctionBFunctionB 调用 FunctionC,依此类推,直到 FunctionD。在 FunctionD 中,我们调用 PrintStackTrace 函数来捕获并打印当前的堆栈回溯。

为了使堆栈回溯更有意义,我们在 PrintStackTrace 函数中使用了符号解析。我们使用 SymInitialize 初始化符号处理器,然后对于捕获到的每个栈帧地址,我们尝试使用 SymFromAddr 获取对应的符号信息(即函数名称)。最后,我们使用 SymCleanup 清理符号处理器。

请注意,为了使符号解析工作,你可能需要确保你的程序带有调试符号,并且在适当的路径上。此外,这个示例代码在编译时需要链接 DbgHelp.lib 库。

通过这个示例,你可以看到如何在一个复杂的函数嵌套调用场景中捕获并解析堆栈回溯,从而帮助理解程序的调用流程。

 

windows栈回溯的常见API:

在Windows系统中,即使不直接使用Windows Debugging Tools,也可以通过调用Windows提供的API来获取栈回溯信息。这些API允许开发者在应用程序中直接捕获栈回溯数据,常用于错误诊断、性能分析和安全监测等场景。以下是一些用于获取栈回溯信息的Windows API:

  1. CaptureStackBackTrace

    • CaptureStackBackTrace函数可以用于捕获当前线程的调用堆栈。它是一个相对简单且常用的函数,用于快速获取栈回溯信息。
    • 示例用法:USHORT WINAPI CaptureStackBackTrace(DWORD FramesToSkip, DWORD FramesToCapture, PVOID *BackTrace, PDWORD BackTraceHash);
  2. StackWalk64

    • StackWalk64函数是一个更复杂但功能强大的API,它可以用于遍历指定线程的调用堆栈。这个函数是DbgHelp库的一部分,支持多种处理器架构。
    • 示例用法:BOOL StackWalk64(DWORD MachineType, HANDLE hProcess, HANDLE hThread, LPSTACKFRAME64 StackFrame, PVOID ContextRecord, PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemoryRoutine, PFUNCTION_TABLE_ACCESS_ROUTINE64 FunctionTableAccessRoutine, PGET_MODULE_BASE_ROUTINE64 GetModuleBaseRoutine, PTRANSLATE_ADDRESS_ROUTINE64 TranslateAddress);
  3. RtlCaptureContext

    • RtlCaptureContext函数用于获取当前线程的上下文(包括寄存器状态等)。虽然它本身不直接提供栈回溯信息,但可以与StackWalk64等函数配合使用,以获取完整的栈回溯数据。
    • 示例用法:VOID RtlCaptureContext(PCONTEXT ContextRecord);
  4. MiniDumpWriteDump

    • MiniDumpWriteDump函数用于创建当前应用程序或进程的内存转储文件(包括调用堆栈信息)。这通常用于崩溃后的调试分析。
    • 示例用法:BOOL MiniDumpWriteDump(HANDLE hProcess, DWORD ProcessId, HANDLE hFile, MINIDUMP_TYPE DumpType, PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam, PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam, PMINIDUMP_CALLBACK_INFORMATION CallbackParam);

使用这些API时,通常需要具备一定的编程知识和调试技能。开发者可以根据具体的应用场景和需求,选择合适的API来实现栈回溯信息的捕获。此外,处理和分析这些数据可能还需要对Windows系统架构和调试原理有较深的理解。

 

 

现在假如如果我要实现一个功能,监控windows特定API的调用(比如windows 网络通信),当有该API调用的时候,获取该程序的栈调用上下文,应该如何写代码实现呢?

实现一个功能来监控Windows特定API的调用,并在调用时获取该程序的栈调用上下文,通常涉及到两个关键技术:API钩子(API Hooking)和堆栈回溯(Stack Walking)。下面我将概述这个过程的基本步骤和一些可能用到的技术点。

第1步:设置API钩子

首先,你需要设置一个钩子来监控特定API的调用。这可以通过各种方法实现,比如使用Microsoft Detours库、MinHook库或其他钩子技术。以监控Windows网络API send 函数为例,你需要编写一个替代函数,当原始的send函数被调用时,你的替代函数将被执行。

使用Detours库的示例代码片段如下:

#include <windows.h>
#include <detours.h>
#include <iostream>

// 原始函数指针
static int (WINAPI *TrueSend)(SOCKET s, const char* buf, int len, int flags) = send;

// 替代函数
int WINAPI MySend(SOCKET s, const char* buf, int len, int flags) {
    std::cout << "send function called" << std::endl;
    // 这里可以调用堆栈回溯函数
    return TrueSend(s, buf, len, flags); // 调用原始send函数
}

// 安装钩子
void AttachHooks() {
    DetourTransactionBegin();
    DetourUpdateThread(GetCurrentThread());
    DetourAttach(&(PVOID&)TrueSend, MySend);
    DetourTransactionCommit();
}

// 移除钩子
void DetachHooks() {
    DetourTransactionBegin();
    DetourUpdateThread(GetCurrentThread());
    DetourDetach(&(PVOID&)TrueSend, MySend);
    DetourTransactionCommit();
}

  

第2步:堆栈回溯

在你的替代函数(如上面的MySend)中,你可以使用堆栈回溯来获取当前的调用堆栈。这可以通过CaptureStackBackTrace函数实现,或者使用更高级的方法,如StackWalk64函数,它是DbgHelp库的一部分。

下面是使用CaptureStackBackTrace的示例代码:

 
#include <windows.h>
#include <dbghelp.h>

#pragma comment(lib, "dbghelp.lib")

void PrintStackTrace() {
    const int MaxFrames = 62;
    PVOID backTrace[MaxFrames];
    USHORT frames = CaptureStackBackTrace(0, MaxFrames, backTrace, NULL);

    for (USHORT i = 0; i < frames; i++) {
        std::cout << "Frame " << i << ": " << backTrace[i] << std::endl;
    }
}

  

 

在你的MySend函数中调用PrintStackTrace函数,你可以在每次send函数被调用时打印调用堆栈。

注意事项

  • 使用API钩子可能会影响系统的稳定性和性能,特别是如果你监控的是高频调用的API。
  • 你需要管理员权限来安装钩子。
  • 确保你的代码在多线程环境下是安全的,因为API调用可能来自不同的线程。
  • 在实际部署前,彻底测试你的代码,确保它不会干扰到正常的系统或应用程序功能。

这个过程涉及到底层的Windows编程和系统编程的高级概念,因此建议有一定经验的开发者才尝试实现。此外,确保你的实现符合所有相关的隐私和安全标准。

标签:调用,函数,示例,windows,API,回溯,堆栈
From: https://www.cnblogs.com/bonelee/p/18009489

相关文章

  • Windows和浏览器的命令与快捷键
    目录一、运行常用命令二、cmd常用命令(cmd的命令是运行的命令的超集)三、Windows快捷键1、Win键2、Ctrl键3、Alt键4、F键四、浏览器快捷键五、关闭Windows防火墙、安全中心和自动更新一、运行常用命令1.基本命令cmd打开命令提示符(cmd命令行控制台)control......
  • 回溯法summary
    组合问题:从给定的一组元素中找出所有可能的组合,例如子集、组合总和等问题。排列问题:对一组元素进行排列,找出所有可能的排列方式,例如全排列问题。子集问题:找出给定集合的所有子集,包括空集和本身。棋盘类问题:如八皇后问题、数独问题,需要在一个棋盘上放置元素并满足一......
  • Windows下如何使用 Sublime Text 4 配置 C/C++ 环境(使用LSP-clangd)
    1软件安装1.1SublimeText4安装及PackageControl安装略,请自行百度/必应/谷歌。1.2Clang环境安装1.2.1Clang下载在LLVMMinGW下载最新版Clang编译器,此处应根据个人电脑系统及版本选择,本文选择llvm-mingw-20231128-ucrt-x86_64.zip,后续文件名将以此为例。各版本......
  • windows下部署Blynk服务器部署最新教学
    目录Step1.下载链接Step2.部署Step2.1软件安装及载入工程1.安装Intellij社区版正常安装即可2.下载maven并将其添加进环境变量Step1.下载链接链接:https://pan.baidu.com/s/1ysbAYhyxUGx1ZG3xNMdsAw?pwd=1fel提取码:1felStep2.部署Step2.1软件安装及载入工程1.安装Intel......
  • PowerShell是一种跨平台的任务自动化解决方案,包括命令行shell、脚本语言和配置管理框
    PowerShell是一种跨平台的任务自动化解决方案,包括命令行shell、脚本语言和配置管理框架。PowerShell提供了丰富的命令(称为cmdlet),可以用来执行许多Windows管理任务,包括但不限于用户和组管理、文件系统操作、进程和服务管理等。下面列举一些常见的net命令以及它们在PowerShell中的对......
  • 统信UOS/麒麟KYLINOS与Windows通过Open SSH实现文件传输
    原文链接:统信UOS/麒麟KYLINOS与Windows通过OpenSSH实现文件传输hello,大家好啊!今天我要给大家介绍的是在统信UOS或麒麟KYLINOS操作系统与Windows系统之间通过OpenSSH实现文件传输的方法。在日常工作中,我们经常需要在不同操作系统之间传输文件。虽然可以使用SMB文件共享等方法,但今......
  • 导出excel文件接口代码示例
    导出excel文件接口代码示例1.该导出接口,token不能通过请求头来传输,需要在get请求的参数中带出来2.验证token的方法除了在拦截器中统一拦截,针对get接口传参数的方式也需要单独在接口中验证。@RequestMapping(value="export",method=RequestMethod.GET)publicString......
  • windows 下nginx 部署VUE
    一、下载nginx   nginx下载地址:https://nginx.org/en/download.html?utm_source=so二、 nginx 命令1.win+r打开cmd;cd到nginx安装目录2.启动:startnginx3.重启服务:nginx-sreload 三、nginx 配置文件notepad++ 插件notePad++下载nginx......
  • 代号“哈德逊河谷”!新版Windows要来了:大概率不叫Windows 12
    微软正准备Windows的重大更新,有望在今年秋季向WIndows11用户推送。但有关新版本的命名一直悬而未决。是作为Windows11的一个全新版本,还是另起炉灶直接叫Windows12?据悉,新版Windows内部代号“HudsonValley”(哈德逊河谷),目前Windows11系统的内部代号为“SunValley(太阳谷)”。......
  • Windows 10 快捷键大全|日常办公效率加倍
    ##复制、粘贴及其他常规  Ctrl+X剪切选定项。Ctrl+C(或Ctrl+Insert)复制选定项。Ctrl+V(或Shift+Insert)粘贴选定项。Ctrl+Z撤消操作。Alt+Tab在打开的应用­之间切换。Alt+F4关闭活动项,­或者退­出活动应用。Windows徽标键+......