首页
社区
课程
招聘
[原创]逆向破解初次体验,以及关于win10的VEH异常断点的一些解决方法
发表于: 2020-3-13 13:58 11212

[原创]逆向破解初次体验,以及关于win10的VEH异常断点的一些解决方法

2020-3-13 13:58
11212

ps:时间原因,我已经找到程序关键跳地址为 0X004010FD ,该地址指令长度为6

所逆行/破解程序没有加壳

因为程序没有加壳,我们可以直接选择使用修改二进制文件处指令为 {0x90, 0 x90, 0 x90, 0 x90, 0 x90, 0 x90}

但是我选择写C语言程序进行内存写入修改,代码如下

#define _CTR_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<windows.h>
int main1(){
	DWORD a;
    //输如PID
	scanf_s("%d", &a);
	byte buf[] = { 0x90,0x90 ,0x90 ,0x90 ,0x90 ,0x90 };
	//获取函数句柄
	HANDLE hdle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, a);
    //向指定内存地址写入修改指令
	WriteProcessMemory(hdle, (LPVOID)0x004010FD, buf, 6, NULL);
	printf("破解成功\n");
	system("pause");
	return 0;
}

执行结果

输入进程pid

注册成功截图

程序进行加壳

我们依然可以使用以上方法进行破解,但是在此我使用dll劫持进行演示

首先我们需要使用vs创建dll项目,因为我已经查看到该程序在执行时调用winspool.drv,因此我就准备劫持该dll,关键点在于我们需要将其函数进行转发。

新建项目

名称需要winspool

在编写dll时注意如下几个问题

不使用预编译头

使用字节集编码

判断程序是不是WOW64程序,代码如下

BOOL IsWow64Pro = false;
if (IsWow64Process((HANDLE)-1, &IsWow64Pro)) {
	if (IsWow64Pro)
	{
		GetSystemWow64DirectoryA(tzPath, MAX_PATH);
	}
	else {
		GetSystemDirectory(tzPath, MAX_PATH);
	}
}

然后在dllmain函数中添加程序代码

如第二种讲的一样直接修改代码

HANDLE  hadl = OpenProcess(PROCESS_ALL_ACCESS, true,GetProcessId((HANDLE)-1));
byte buf[] = { 0x90,0x90 ,0x90 ,0x90 ,0x90 ,0x90 };
WriteProcessMemory(hadl, (LPVOID)0x004010FD, buf, 6, NULL);
MessageBoxA(NULL, "成功", "标题", NULL);

效果

注册成功截图2

但是以上的代码存在一些不可预知的效果,比如程序代码还没有还原,则以上代码是无效的,因此考虑增加判断语句,创建新的线程进行判断

线程代码如下

CreateThread(NULL,NULL, threadPro, NULL, NULL, NULL);

//线程实现函数,循环检测代码是否被还原
DWORD WINAPI threadPro(_In_ LPVOID lpParam)
{
	while (true)
	{
		byte buf = 0 ;
		ReadProcessMemory((HANDLE)-1, (LPVOID)0x004010A9, &buf, 1, NULL);
		//MessageBoxA(NULL, (LPCSTR)buf,"标题" ,NULL );
		if (buf == 0x55) {
			byte buf2[] = { 0x90,0x90 ,0x90 ,0x90 ,0x90 ,0x90 };
			WriteProcessMemory((HANDLE)-1, (LPVOID)0x004010FD, buf2, 6, NULL);
			break;
		}
	}
	return 0;
}

执行效果

执行效果

程序有CRC检测,我们需要使用VEH来跳过检测

VEH就是异常,让系统捕获相关的异常,然后我们修改上下文

异常捕获代码

//异常捕获
DWORD NTAPI ExceptionHandler(EXCEPTION_POINTERS* ExceptionInfo) {
	if ((DWORD)ExceptionInfo->ExceptionRecord->ExceptionAddress == 0x004010FD) {
		ExceptionInfo->ContextRecord->Eip += 6;
        //已经处理异常,不需要再调用下一个异常来处理此异常
		return EXCEPTION_CONTINUE_EXECUTION;
	}
    //调用下一个处理器
	return EXCEPTION_CONTINUE_SEARCH;
}

注册一个VEH异常

//注册一个异常VEH
AddVectoredExceptionHandler(1,(PVECTORED_EXCEPTION_HANDLER)ExceptionHandler);

设置硬件断点

//设置硬件断点
void SetHwBreakPoint(HANDLE hThread) {
	CONTEXT ctx;
	ctx.ContextFlags = CONTEXT_ALL;
	GetThreadContext(hThread, &ctx);
	ctx.Dr0 = 0x004010FD;
	ctx.Dr7 = 0x1;
	SetThreadContext(hThread, &ctx);
}

在win7系统中,此时程序已经被破解掉,但是在win10中发现并没有按照预期进行执行,为什么呢?查询官方解释

Remarks
The function sets the thread context based on the value of the ContextFlags member of the context structure. The thread identified by the hThread parameter is typically being debugged, but the function can also operate even when the thread is not being debugged.

Do not try to set the context for a running thread; the results are unpredictable. Use the SuspendThread function to suspend the thread before calling SetThreadContext.

写的很清楚,如果需要设置断点,需要将程序进行挂起

继续更改代码

我们新建一个线程,让新的子线程来接管主线程,到达暂停主线程的目的,防止程序直接假死

创建线程

CreateThread(NULL,NULL, threadPro, (LPVOID)GetCurrentThreadId(), NULL, NULL);

线程函数

DWORD WINAPI threadPro(_In_ LPVOID lpParam)
{
	//打开主线程
	HANDLE hadl = OpenThread(THREAD_ALL_ACCESS, true, (DWORD)lpParam);
	SuspendThread((HANDLE)hadl);
	SetHwBreakPoint(hadl);
	ResumeThread((HANDLE)hadl);
	return 0;
}

执行结果

捕获到异常

执行结果

总结

在程序逆向破解的过程中,使用dll劫持、HOOK等技术,在有壳的情况小也能方便的达到我们的目的,本文教大家如何手工编写代码并进行调试,谢谢大家阅读。



[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

最后于 2020-3-13 14:39 被pangdou编辑 ,原因: 代码显示有问题
收藏
免费 3
支持
分享
最新回复 (10)
雪    币: 2510
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
2
感谢分享
2020-3-13 17:59
2
雪    币: 6664
活跃值: (957)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
学习了
2020-3-14 07:37
0
雪    币: 185
活跃值: (16)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
学习了!
2020-3-14 08:40
0
雪    币: 3574
活跃值: (3955)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
学习了。
2021-7-15 19:39
0
雪    币: 193
活跃值: (1215)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
要是有例子和源码就好了
2021-12-30 20:19
0
雪    币: 8764
活跃值: (5240)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
7
不明白,你这个是怎么过CRC检测的?
假如是程序中的一个线程对程序进行CRC校验,你设置一个硬件执行断点能起到什么作用?
2021-12-30 22:50
0
雪    币: 193
活跃值: (1215)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
问下怎么取消?
2022-1-2 14:47
0
雪    币: 792
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
9
学习 了,挺厉害。
2022-1-13 07:07
0
雪    币: 3681
活跃值: (3273)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
硬件断点触发了VEH异常,我们捕获异常同时对程序EIP位置进行修改,避过了CRC检测
2022-1-13 09:27
0
雪    币: 102
活跃值: (304)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
sunsjw 不明白,你这个是怎么过CRC检测的? 假如是程序中的一个线程对程序进行CRC校验,你设置一个硬件执行断点能起到什么作用?
设置硬件断点触发异常是不需要修改字节的所以可以通过CRC检测
2022-11-3 21:05
0
游客
登录 | 注册 方可回帖
返回
//