注册机偷懒写法4、之调试模式下获取

注册机偷懒写法1、之直接扣代码

注册机偷懒写法2、之直接调用源程序的函数

注册机偷懒写法3、内联Hook让程序自己弹出注册码

注册机偷懒写法4、调试模式下获取

这个方法可能会比较通用,编写个简单调试器,调试源程序,从内存或者寄存器中获取注册码。

#include<Windows.h>
#include<iostream>
#include <DbgHelp.h>
#pragma comment(lib, "dbghelp.lib")
#include<vector>
using std::vector;

typedef struct _SOFTBREAKEPOINT
{
	LPVOID address;		//地址
	BYTE   old_byte;	//原始数据
	DWORD old_protect;  //页面属性
	BOOL enbale;		//断点是否启用

}SOFTBREAKEPOINT, *PSOFTBREAKEPOINT;
/*
找到关键代码的地址,下断点,让后在从内存中读取
*/
typedef struct _DBG_REG7
{
	/*
	// 局部断点(L0~3)与全局断点(G0~3)的标记位
	*/
	unsigned L0 : 1;  // 对Dr0保存的地址启用 局部断点
	unsigned G0 : 1;  // 对Dr0保存的地址启用 全局断点
	unsigned L1 : 1;  // 对Dr1保存的地址启用 局部断点
	unsigned G1 : 1;  // 对Dr1保存的地址启用 全局断点
	unsigned L2 : 1;  // 对Dr2保存的地址启用 局部断点
	unsigned G2 : 1;  // 对Dr2保存的地址启用 全局断点
	unsigned L3 : 1;  // 对Dr3保存的地址启用 局部断点
	unsigned G3 : 1;  // 对Dr3保存的地址启用 全局断点
	/*
	// 【以弃用】用于降低CPU频率,以方便准确检测断点异常
	*/
	unsigned LE : 1;
	unsigned GE : 1;
	/*
	// 保留字段
	*/
	unsigned Reserve1 : 3;
	/*
	// 保护调试寄存器标志位,如果此位为1,则有指令修改条是寄存器时会触发异常
	*/
	unsigned GD : 1;
	/*
	// 保留字段
	*/
	unsigned Reserve2 : 2;
	/*
	// 保存Dr0~Dr3地址所指向位置的断点类型(RW0~3)与断点长度(LEN0~3),状态描述如下:
	*/
	unsigned RW0 : 2;  // 设定Dr0指向地址的断点类型
	unsigned LEN0 : 2;  // 设定Dr0指向地址的断点长度
	unsigned RW1 : 2;  // 设定Dr1指向地址的断点类型
	unsigned LEN1 : 2;  // 设定Dr1指向地址的断点长度
	unsigned RW2 : 2;  // 设定Dr2指向地址的断点类型
	unsigned LEN2 : 2;  // 设定Dr2指向地址的断点长度
	unsigned RW3 : 2;  // 设定Dr3指向地址的断点类型
	unsigned LEN3 : 2;  // 设定Dr3指向地址的断点长度
}DBG_REG7, PDBG_REG7;
LPVOID m_addr;					//异常地址
BOOL m_Exit = FALSE;			//是否退出
LPVOID m_ImageBase;				//基址
DWORD m_tid;					//当前线程ID
PROCESS_INFORMATION pi = { 0 };

vector<SOFTBREAKEPOINT>m_bplist;	//软件断点列表

BOOL create_process(const char * path_name);
BOOL create_ActiveProces(DWORD pid);
BOOL loopDebugEvent();
BOOL loopDebugEvent();
DWORD OnExceptionDispatch(EXCEPTION_DEBUG_INFO * dbg_execption);
//DWORD OnException_Sinlge();
DWORD OnException_breakpoint();
//void SetHardRegist(LPVOID addr, DWORD type, DWORD len);
BOOL SetBrekePoint(LPVOID address);
BOOL RecoveBrekePoint(LPVOID address);

BOOL m_systembp = TRUE;			//系统断点


int main()
{
	create_process("Dope2112.1.exe");
	loopDebugEvent();
	return 0;
}

//打开方式
BOOL create_process(const char * path_name)
{
	STARTUPINFO sf = { sizeof(sf) };
	//PROCESS_INFORMATION pi = { 0 };
	BOOL bret = CreateProcess(
		path_name, //exe路径
		NULL,		//命令行参数
		NULL,		//进程安全属性
		NULL,		//线程安全属性
		FALSE,		//是否继承句柄
		//只调试方式启动,创建控制台
		DEBUG_ONLY_THIS_PROCESS | CREATE_NEW_CONSOLE,
		NULL,		//运行环境变量
		NULL,		//工作目录
		&sf,		//启动信息
		&pi);		//进程信息
	//SymSetOptions(SYMOPT_UNDNAME | SYMOPT_DEFERRED_LOADS);
	SymInitialize(pi.hProcess, NULL, FALSE);
	return bret;
}
//附加
BOOL create_ActiveProces(DWORD pid)
{
	return DebugActiveProcess(pid);
}

//3. 循环等待事件
BOOL loopDebugEvent()
{
	DEBUG_EVENT m_deevent;
	DWORD  dbg_continue = DBG_CONTINUE;
	//循环等待调试事件
	while (!m_Exit)
	{
		//等待调试事件
		WaitForDebugEvent(&m_deevent, -1);
		m_tid = m_deevent.dwThreadId;
		//分发调试事件
		switch (m_deevent.dwDebugEventCode)
		{
		case  EXCEPTION_DEBUG_EVENT:					//异常信息
			dbg_continue = OnExceptionDispatch(&m_deevent.u.Exception);
			break;
		case  CREATE_THREAD_DEBUG_EVENT:				//线程被创建
			m_deevent.u.CreateThread.lpStartAddress;    //线程入口点
			break;

		case  CREATE_PROCESS_DEBUG_EVENT:				//进程被创建
		{
			m_ImageBase = m_deevent.u.CreateProcessInfo.lpBaseOfImage;
		}
		break;
		case   EXIT_THREAD_DEBUG_EVENT:					//线程退出   
			break;
		case EXIT_PROCESS_DEBUG_EVENT:					// 进程退出
			m_Exit = TRUE;
			break;
		case 	LOAD_DLL_DEBUG_EVENT:					//dll加载
			break;
		case 	UNLOAD_DLL_DEBUG_EVENT:					//dll卸载
			break;
		case   OUTPUT_DEBUG_STRING_EVENT:				//调试输出
			break;
		case RIP_EVENT:									//内部错误
			break;
		}

		//回复子系统 ,事件是否处理
		ContinueDebugEvent(
			m_deevent.dwProcessId,		//进程ID
			m_deevent.dwThreadId,		//线程ID
			dbg_continue);				//事件是否处理
	}
	return TRUE;
}

DWORD OnExceptionDispatch(EXCEPTION_DEBUG_INFO * dbg_execption)
{
	DWORD dbg_continue = DBG_CONTINUE;
	//异常代码
	DWORD Code = dbg_execption->ExceptionRecord.ExceptionCode;

	//异常地址
	m_addr = dbg_execption->ExceptionRecord.ExceptionAddress;

	//检测异常类型
	switch (Code)
	{
	case EXCEPTION_BREAKPOINT:		//软件断点异常
		dbg_continue = OnException_breakpoint();
		break;
	case  EXCEPTION_ACCESS_VIOLATION: //访问异常
		break;
	case EXCEPTION_SINGLE_STEP:     //硬件断点-单步断点
		/*dbg_continue = OnException_Sinlge();*/
		break;
	}
	return dbg_continue;

}
//硬件点
//DWORD OnException_Sinlge()
//{
//	HANDLE ht = OpenThread(THREAD_ALL_ACCESS, FALSE, m_tid);
//	CONTEXT context = { CONTEXT_ALL };
//	GetThreadContext(ht, &context);
//	CloseHandle(ht);
//	DWORD temp = *(DWORD *)(context.Ebp - 18);
//	char str[20] = { 0 };
//	ReadProcessMemory(pi.hProcess, (LPCVOID)temp, str, sizeof(str), NULL);
//	printf(str);
//	getchar();
//	return DBG_CONTINUE;
//}

// 软件异常
DWORD OnException_breakpoint()
{
	/*
	00421CFE                               | E8 71 36 FE FF        | call <dope2112.1.IntToString>                        | ???
	00421D03                               | 8D 55 E4              | lea edx,dword ptr ss:[ebp-1C]                        | [ebp-1C]:"46"
	00421D06                               | 33 C0                 | xor eax,eax                                          | [ebp-1c]临时变量
	00421D08                               | 8A C3                 | mov al,bl                                            |
	00421D0A                               | E8 65 36 FE FF        | call <dope2112.1.IntToString>                        | ???
	00421D0F                               | FF 75 E4              | push dword ptr ss:[ebp-1C]                           | [ebp-1C]:"46"
	00421D12                               | 68 D8 1D 42 00        | push dope2112.1.421DD8                               | 421DD8:L"-"
	00421D17                               | FF 75 F0              | push dword ptr ss:[ebp-10]                           | [ebp-10]:"114420"
	00421D1A                               | 8D 45 F4              | lea eax,dword ptr ss:[ebp-C]                         | [ebp-C]:"46-114420"
	00421D1D                               | BA 03 00 00 00        | mov edx,3                                            | [ebp-c]存储姓名计算出的密码
	00421D22                               | E8 FD 16 FE FF        | call <dope2112.1.sub_403424>                         | 1.sub_403424)
	00421D27                               | 8D 55 E8              | lea edx,dword ptr ss:[ebp-18]                        | [ebp-18]:"123456"
	*/
	//在程序运行到00421D27时[ebp-C]:"46-133490"中保存着注册码,hook 00421D27
	//计算新的位置
	LPVOID ptemp = (LPVOID)((DWORD)m_ImageBase + 0x21D27);
	//检测系统断点
	if (m_systembp)
	{
		//在00421D27设置执行断点
		SetBrekePoint(ptemp);
		m_systembp = FALSE;
	}
	else
	{
		RecoveBrekePoint(m_addr);
		if (ptemp == m_addr)
		{
			HANDLE ht = OpenThread(THREAD_ALL_ACCESS, FALSE, m_tid);
			CONTEXT context = { CONTEXT_ALL };
			GetThreadContext(ht, &context);
			CloseHandle(ht);
			DWORD temp = 0;
			ReadProcessMemory(pi.hProcess, (LPCVOID)(context.Ebp - 0xc), &temp, sizeof(temp), NULL);
			char str[20] = { 0 };
			ReadProcessMemory(pi.hProcess, (LPCVOID)temp, str, sizeof(str), NULL);
			printf(str);
			getchar();
		}
	}
	
	return DBG_CONTINUE;
}
//硬件断点
//void SetHardRegist(LPVOID addr, DWORD type, DWORD len)
//{
//	HANDLE ht = OpenThread(THREAD_ALL_ACCESS, FALSE, m_tid);
//	CONTEXT context = { CONTEXT_ALL };
//	//2.获取线程上线文
//	GetThreadContext(ht, &context);
//	auto Pctx = &context;
//	DBG_REG7* pDr7;
//	//获取Dr7字段
//	pDr7 = (DBG_REG7*)&Pctx->Dr7;
//	//检测是Dr0是否空,可以写入
//	if (Pctx->Dr0 == 0)
//	{
//		//写入地址
//		Pctx->Dr0 = (DWORD)addr;
//		//写入局部断点有效
//		pDr7->L0 = 1;
//		//断点类型,type:  0 执行,1写入 3读写
//		pDr7->RW0 = type;
//		//长度  len: 0一个字节,1两个字节 3四个字节
//		pDr7->LEN0 = len;
//	}
//	else if (Pctx->Dr1 == 0)
//	{
//		Pctx->Dr1 = (DWORD)addr;
//		pDr7->L1 = 1;
//		pDr7->RW1 = type;
//		pDr7->LEN1 = len;
//	}
//	else if (Pctx->Dr2 == 0)
//	{
//		Pctx->Dr2 = (DWORD)addr;
//		pDr7->L2 = 1;
//		pDr7->RW2 = type;
//		pDr7->LEN2 = len;
//	}
//	else if (Pctx->Dr3 == 0)
//	{
//		Pctx->Dr3 = (DWORD)addr;
//		pDr7->L3 = 1;
//		pDr7->RW3 = type;
//		pDr7->LEN3 = len;
//	}
//	if (!SetThreadContext(ht, &context))
//		printf("设置硬件断点失败!");
//	CloseHandle(ht);
//}
//设置软件断点
BOOL SetBrekePoint(LPVOID address)
{
	SOFTBREAKEPOINT bp;
	bp.address = address;
	bp.enbale = TRUE;

	//1. 打开进程
	HANDLE hps = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pi.dwProcessId);
	//2. 修改页面属性
	VirtualProtectEx(hps,
		address,
		1,
		PAGE_EXECUTE_READWRITE,
		&bp.old_protect);

	DWORD dwSize;
	//3. 读取原始数据
	ReadProcessMemory(hps, address, &bp.old_byte, 1, &dwSize);

	//4. 写入cc断点
	WriteProcessMemory(hps, address, "\xcc", 1, &dwSize);
	//5. 保存断点信息
	m_bplist.push_back(bp);
	//6. 恢复页面属性
	VirtualProtectEx(hps,
		address,
		1,
		bp.old_protect,
		&dwSize);

	//7. 关闭句柄
	CloseHandle(hps);

	return TRUE;
}
// 恢复软件断点
BOOL RecoveBrekePoint(LPVOID address)
{
	for (int i = 0; i < m_bplist.size(); i++)
	{
		//如果是断点列表中的异常
		if (m_bplist[i].address == address)
		{

			//1. 打开进程
			HANDLE hps =
				OpenProcess(PROCESS_ALL_ACCESS, FALSE, pi.dwProcessId);
			//2. 修改页面属性
			DWORD dwProtect;
			VirtualProtectEx(hps,
				address,
				1,
				PAGE_EXECUTE_READWRITE,
				&dwProtect);

			DWORD dwSize;

			//4. 写入原始数据
			WriteProcessMemory(
				hps,
				address,
				&m_bplist[i].old_byte,
				1, &dwSize);

			//6. 恢复页面属性
			VirtualProtectEx(hps,
				address,
				1,
				m_bplist[i].old_protect,
				&dwSize);

			//7. 关闭句柄
			CloseHandle(hps);
			return TRUE;
		}
	}
	return FALSE;
}

源码

https://download.csdn.net/download/u012332009/11122063

源程序的分析请看

[反汇编练习] 160个CrackMe之044
(出处: 吾爱破解论坛)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值