Windows 下获得当前线程上下文并保存到dump文件测试之2

1 篇文章 0 订阅
#include <Windows.h>
#include <Dbghelp.h>
#include <excpt.h>
#include <exception>
#include <iostream>
#include <thread>

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

void DumpMiniDump(unsigned long code, PEXCEPTION_POINTERS excpInfo)
{
	std::cout << "exception code =" << code << std::endl;
	MINIDUMP_EXCEPTION_INFORMATION eInfo;
	eInfo.ThreadId = GetCurrentThreadId();
	eInfo.ExceptionPointers = excpInfo;
	eInfo.ClientPointers = false;
	HANDLE hFile = CreateFile(L"MiniDumpX.dmp", GENERIC_READ | GENERIC_WRITE,
		0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);

	::MiniDumpWriteDump(
		GetCurrentProcess(),
		GetCurrentProcessId(),
		hFile,
		MiniDumpNormal,
		&eInfo,
		NULL,
		NULL);

	::CloseHandle(hFile);

}

#define CAPTURE_CTX_CUSTOM 0xC0160010L

void throwEx(std::exception& except)
{
	unsigned long code = 0;

	__try
	{
		RaiseException(CAPTURE_CTX_CUSTOM, 0, 0, NULL);
	}
	__except (DumpMiniDump(GetExceptionCode(), GetExceptionInformation()), EXCEPTION_EXECUTE_HANDLER)
	{
		throw except;
	}
}


void getSelfContext()
{
	DWORD id = ::GetCurrentThreadId();
	static bool  b = false;
	HANDLE h = OpenThread(
		THREAD_ALL_ACCESS,
		TRUE,
		id
	); //获得真实句柄

	std::thread _th([=] {
		::SuspendThread(h);
		CONTEXT ctx = { 0 };
		::GetThreadContext(h, &ctx);
		MINIDUMP_EXCEPTION_INFORMATION eInfo;

		EXCEPTION_POINTERS excpInfo;
		excpInfo.ExceptionRecord = NULL;
		excpInfo.ContextRecord = &ctx;

		eInfo.ThreadId = GetCurrentThreadId(); 
		eInfo.ExceptionPointers = &excpInfo;
		eInfo.ClientPointers = FALSE;

		HANDLE hFile = CreateFile(L"MiniDump.dmp", GENERIC_READ | GENERIC_WRITE,
			0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);

		::MiniDumpWriteDump(
			GetCurrentProcess(),
			GetCurrentProcessId(),
			hFile,
			MiniDumpNormal,
			&eInfo,
			NULL,
			NULL);

		::CloseHandle(hFile);
		::ResumeThread(h);

		b = true;
		});

	_th.detach();

	while (!b)
		::Sleep(200);
}

#define THROWX(x) throwEx(x)

void XX()
{
	std::cout << "inside it" << std::endl;
	std::exception exp("what is the matter?");
	throw exp;
}

bool JmpHook(unsigned char* func, unsigned char* dst)
{
	char original_bytes[16];

	DWORD old_protection;
	if (0 == VirtualProtect(func, 1024, PAGE_EXECUTE_READWRITE, &old_protection))
		return false;

	memcpy(original_bytes, dst, sizeof(void*) == 4 ? 5 : 14);

#if defined(_M_X64) || defined(__amd64__) // x86_64
	func[0] = 0xFF; // absolute jmp
	func[1] = 0x25; // absolute jmp
	*(uint32_t*)(func + 2) = 0;
	*(uint64_t*)(func + 6) = (uint64_t)dst;
#else
	*(unsigned char*)func = (char)0xE9; //relative jmp near instruction
	*(uint32_t*)((unsigned char*)func + 1) = (unsigned char*)dst - (unsigned char*)func - 5;
#endif

#if defined(_WIN32)
	if (!VirtualProtect(func, 1024, old_protection, &old_protection))
	{
		memcpy(func, original_bytes, sizeof(void*) == 4 ? 5 : 14);
		return false;
	}
#endif

	return true;
}

VOID WINAPI RaiseException_HOOK(
	_In_ DWORD dwExceptionCode,
	_In_ DWORD dwExceptionFlags,
	_In_ DWORD nNumberOfArguments,
	_In_reads_opt_(nNumberOfArguments) CONST ULONG_PTR* lpArguments
)
{
#if 0
	std::exception e("what is the matter\n");
	THROWX(e); //引起递归
#endif

	getSelfContext();
}


VOID WINAPI CXXThrowExcept(void*, void*)
{
	getSelfContext();
}

int main()
{
#if 0
	auto Kernel32 = GetModuleHandleA("kernel.dll");
	if (nullptr == Kernel32)
	{
		std::cout << "couldn't find Kernel32.dll" << std::endl;
		return EXIT_FAILURE;
	}

	auto addr = GetProcAddress(Kernel32, "RaiseException");
	JmpHook(addr, RaiseException_HOOK);
#else
#ifdef _DEBUG
	auto Kernel32 = GetModuleHandleA("vcruntime140d.dll");
#else
	auto Kernel32 = GetModuleHandleA("vcruntime140.dll");
#endif
	if (nullptr == Kernel32)
	{
		std::cout << "couldn't find Kernel32.dll" << std::endl;
		return EXIT_FAILURE;
	}

	auto addr = GetProcAddress(Kernel32, "_CxxThrowException");
	JmpHook((unsigned char*)addr, (unsigned char*)CXXThrowExcept);
#endif

	try
	{
		XX();
	}
	catch(std::exception& e)
	{
		std::cout << e.what() << std::endl;
	}

	return 0;
}


#if 0
// Reminder: _WIN32 is still defined in x64 projects (at least in MSVC)

#include <iostream>
#include <stdlib.h>
#include <cstdint>

#ifdef __GNUC__
#define NOINLINE __attribute__((noinline))
#elif defined _MSC_VER
#define NOINLINE __declspec(noinline)
#endif

#if defined(_WIN32) || defined(_WIN64)
#include <windows.h>
#elif defined(__linux__)
#include <sys/mman.h>
#include <unistd.h>
#else
#error "This code is meant to run on Windows/Linux"
#endif

bool
jmp_hook(unsigned char* func, unsigned char* dst)
{
#if defined(_WIN32)
	char original_bytes[16];
	DWORD old_protection;

	if (0 == VirtualProtect(func, 1024, PAGE_EXECUTE_READWRITE, &old_protection))
		return false;

	memcpy(original_bytes, dst, sizeof(void*) == 4 ? 5 : 14);
#elif defined(__linux__)
	uintptr_t page_size = sysconf(_SC_PAGE_SIZE);
	if (0 != mprotect(func - ((uintptr_t)func % page_size), page_size, PROT_EXEC | PROT_READ | PROT_WRITE))
		return false;
#endif

#if defined(_M_X64) || defined(__amd64__) // x86_64
	func[0] = 0xFF; // absolute jmp
	func[1] = 0x25; // absolute jmp
	*(uint32_t*)(func + 2) = 0;
	*(uint64_t*)(func + 6) = (uint64_t)dst;
#else
	* func = 0xE9; //relative jmp near instruction
	*(uint32_t*)(func + 1) = dst - func - 5;
#endif

#if defined(_WIN32)
	if (!VirtualProtect(func, 1024, old_protection, &old_protection))
	{
		memcpy(func, original_bytes, sizeof(void*) == 4 ? 5 : 14);
		return false;
	}
#endif
	return true;
}

#if defined(__linux__)
NOINLINE int
example_function(const char* text)
{
	std::cout << text << std::endl;
	return 0;
}
#endif

int
#if defined(_WIN32)
__stdcall
hooked_function(
	HWND    hWnd,
	LPCSTR  lpText,
	LPCSTR  lpCaption,
	UINT    uType)
{
	std::cout << "Call to MessageBox redirected, parameters passed: " << hWnd
		<< ", " << lpText << ", " << lpCaption << ", " << uType << std::endl;

#elif defined __linux__
hooked_function(const char* text)
{
	std::cout << "hooked! original text: " << text << std::endl;
#endif
	return 0;
}

int
main(int argc, char** argv)
{
#ifdef __linux__
	example_function("test");
	jmp_hook((unsigned char*)example_function, (unsigned char*)hooked_function);
	example_function("hello world");
#elif defined _WIN32
	auto user32 = GetModuleHandleA("user32.dll");

	if (nullptr == user32)
	{
		std::cout << "couldn't find user32.dll" << std::endl;
		return EXIT_FAILURE;
	}

	auto messagebox_address = (unsigned char*)GetProcAddress(user32, "MessageBoxA");
	jmp_hook(messagebox_address, (unsigned char*)hooked_function);
	MessageBoxA(0, "hello world", "test call", MB_OK);
#endif
	return EXIT_SUCCESS;
}

#endif

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值