2021-09-21


前言

提示:这里可以添加本文要记录的大概内容:
例如:随着人工智能的不断发展,机器学习这门技术也越来越重要,很多人都开启了学习机器学习,本文就介绍了机器学习的基础内容。


提示:以下是本篇文章正文内容,下面案例可供参考

一、反调试

PEB相关
BegingDebugged标记位可以使用FS寄存器访问到,也可以使用API函数IsDebuggerpressent()检查,如果其值为1则证明本进程处于被调式状态

#include <stdio.h>
#include <Windows.h>
bool PEB_BegingDebugged()
{

	bool BegingDebugged = false;
	_asm
	{
		MOV EAX, DWORD PTR FS : [0X30] ;
		MOV AL, BYTE PTR DS : [EAX + 0X02] ;
		MOV BegingDebugged, AL;
	}
	return BegingDebugged;
}




int main()
{
	bool Ret = PEB_BegingDebugged();

	if (Ret == false)
	{
		printf("啥事没有");
	}
	else
	{
		printf("有危险,快跑!!!");
	}

	system("pause");

	return 0;
}

NtQueryinformationProcess相关

**NtQueryinformationProcess是一个可以同时在R0及R3运行的函数,它的主要作用是查看进程相关的各种信息
根据想要查看的信息类型不同,我们给它的第二个参数Process Information Class传递的值也不同,根据Process Information Class的类别可知,此函数可以查看大概60余种进程相关的信息
ProcessDebugPort可以获取目标进程的调试端口,如果目标进程未出与调试状态,此端口为0,否则为0xFFFFFFFF**
#include <Windows.h>
#include <stdio.h>
#include <winternl.h>

#pragma comment(lib,"ntdll.lib")
bool NQIP_ProessDebugPort()
{

	//ProcessDebugPort可以获取目标进程的调试端口,如果目标进程未出与调试状态,此端口为0,否则为0xFFFFFFFF
	int nDebugPort = 0;
	NtQueryInformationProcess(
		GetCurrentProcess(),
		ProcessDebugPort,
		&nDebugPort,
		sizeof(nDebugPort),
		NULL);
	return nDebugPort == 0xFFFFFFFF ? true : false;
}


int main()
{
	bool Ret = NQIP_ProessDebugPort();
	if (Ret == true)
	{
		printf("有危险\n");
	}
	else
	{
		printf("啦啦啦啦");
	}
	system("pause");

	return 0;
}

*ProcessDebugObjectHandle可以获取目标进程的调试对象句柄,如果未处于调试状态则获取的值为NULL

#include <Windows.h>
#include <stdio.h>
#include <winternl.h>

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



bool NQIP_ProcessDebugObjectHandle()
{
	HANDLE hPorcessDebugObjecthandle = 0;
	//ProcessDebugObjectHandle可以获取目标进程的调试对象句柄,如果未处于调试状态则获取值为NULL
	NtQueryInformationProcess(
		GetCurrentProcess(),                  //目标进程句柄
		(PROCESSINFOCLASS)0x1E,               //查询信息类型
		&hPorcessDebugObjecthandle,           //输出查询信息
		sizeof(hPorcessDebugObjecthandle),    //输出查询类型大小
		NULL                                  //实际返回大小
	);

	return (hPorcessDebugObjecthandle == 0) ? true:false;
}

int main()
{
	bool Ret = NQIP_ProcessDebugObjectHandle();
	if (Ret == true)
	{
		printf("啦啦啦啦啦啦啦");
	}
	else
	{
		printf("有危险,快跑!!!!");
	}

	system("pause");
	return 0;

processDebugFlag可以获取目标进程的调试标记,如果处于调试状态其值为0,否则为1

#include <Windows.h>
#include <stdio.h>
#include <winternl.h>
#pragma comment(lib,"ntdll.lib")

bool NQLP_ProcessDebugFla()
{

	//processDebugFlag可以获取目标进程的调试标记,如果处于调试状态其值为0,否则为1
	BOOL bProcessDebugFlag = 0;
	NtQueryInformationProcess(
		GetCurrentProcess(),                //目标进程句柄
		(PROCESSINFOCLASS)0x1F,             //查询信息类型
		&bProcessDebugFlag,                 //输出查询信息
		sizeof(bProcessDebugFlag),          //查询类型大小
		NULL                                //实际返回类型大小
	);
	return bProcessDebugFlag ? true : false;
}


int main()
{
	bool Ret = NQLP_ProcessDebugFla();
	if (Ret == true)
	{
		printf("啥事没有~啦啦啦啦啦");
	}
	else
	{
		printf("正在被调试,赶紧跑!!!");
		
	}

	system("pause");

	return 0;
}

ProcessBasicInformation 可以获取指定进程的父进程PID,我们可以将其与Explorer.exe的PID进行对比,如果不匹配则证明此进程不是被双击运行的

#include <Windows.h>
#include <stdio.h>
#include <winternl.h>
#pragma comment(lib,"ntdll.lib")

bool NQLP_CheckParentProcess()
{
	//ProcessBasicInformation 可以获取指定进程的父进程PID,我们可以将其与Explorer.exe的PID进行对比,如果不匹配则证明此进程不是被双击运行的
	struct PROCESS_BASE_INFORMATION {
		ULONG ExitStatus;					//进程返回码
		PPEB PebBaseAddress;				//PEB地址
		ULONG AffinityMask;					//CPU亲和性掩码
		LONG BasePriority;					//基本优先级
		ULONG uNIQUEpROCEId;			    //本进程ID
		ULONG InheritedFromUniqueProcessId;//父进程PID
	}stcProcInfo;

	NtQueryInformationProcess(
		GetCurrentProcess(),
		ProcessBasicInformation, &stcProcInfo,
		sizeof(stcProcInfo), NULL);
		
	DWORD ExPlorerPID = 0;
	DWORD CurrentPID = stcProcInfo.InheritedFromUniqueProcessId;
	GetWindowThreadProcessId(FindWindow(L"Progman",NULL),&ExPlorerPID);
	return ExPlorerPID == CurrentPID ? false : true;
}

int main()
{
	bool Ret = NQLP_CheckParentProcess();
	if (Ret == true)
	{
		printf("有危险,快跑!!!");
	}
	else
	{
		printf("啦啦啦啦啦~啥事没有!!!!");
	}
	system("pause");
	return 0;
}

NtQuerySysteminformation()函数获取当前系统是否开启调试模式


#include <Windows.h>
#include <stdio.h>
#include <winternl.h>
#pragma comment(lib,"ntdll.lib")
//

typedef enum THREAD_INFO_CLASS {
    ThreadHideFromDebugger = 17
};

typedef NTSTATUS(NTAPI* ZW_SET_INFORMATION_THREAD)(
    IN  HANDLE ThreadHandle,
    IN  THREAD_INFO_CLASS ThreadInformaitonClass,
    IN  PVOID ThreadInformation,
    IN  ULONG ThreadInformationLength);

void ZSIT_DetachDebug()
{
    ZW_SET_INFORMATION_THREAD Func;
    Func = (ZW_SET_INFORMATION_THREAD)GetProcAddress(
        LoadLibrary(L"ntdll.dll"), "ZwSetInformationThread");
    Func(GetCurrentThread(), ThreadHideFromDebugger, NULL, NULL);
}

int main()
{
    ZSIT_DetachDebug();
    system("pause");
    return 0;
}

破解函数反调试的最有效的方法就是找到具体的函数调用的地点,并分析其条件跳转,然后做暴力破解,亦或是通过HOOK的方式过滤其返回消息。想要在调试的过程种做好以上工作,最好熟记各个功能号(第二个参数传的值)的作用: 0x07 获取调试端口(processDebugPort) 0x1E获取调试句柄(processDebugObjectHandle) 0x1F获取调试标记(ProcessDebugFlags)

总结

静态反调试 1. PEB->BeingDebugged是1(偏移为PEB+0X2的位置) 2. PEB->NtGlobalFlag 是0x70(PEB+0X68) 3. PEB->.ProcessHeap ForceFlags 不为2,(PEB + 0X90 + 0X40) 4. NtQueryInformationProcess相关 5. ProcessDebugPort : 调试端口 6. ProcessDebuggObjectHandle : 调试对象的句柄 7. ProcessDebugFlag:调试标记

动态反调试:
1.
2. 攻击调试器,让调试器和被调试进程分离
3. 0xCC检查
4. 时间检查
5. 通过异常 因为有调试器的时候,UEG就会失败,那么就可以将一些关键代码隐藏在UEH中。
6. 加壳
7. 虚拟机技术
8. 代码膨胀与混淆

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值