CheckRemoteDebuggerPresent反调试

当软件被调试时isDebugged的值为1,当软件没有被调试时isDebugged的值为0
反调试

# include<Windows.h>
# include<stdio.h>
BOOL CheckDebug()
{
	BOOL isDebugged;

	CheckRemoteDebuggerPresent(GetCurrentProcess(), &isDebugged);
	return isDebugged;
}
int main()
{
	while (1)
	{
		if (CheckDebug())
		{
			MessageBox(0, L"软件正在被调试", 0, 0);
			return 0;
		}
		printf("I am running...\n");
		Sleep(600);
	}
	return 0;
}

反反调试
hook掉CheckRemoteDebuggerPresent对isDebugged的赋值
以下是CheckRemoteDebuggerPresent的汇编代码

76673310 >  8BFF            mov edi,edi
76673312    55              push ebp
76673313    8BEC            mov ebp,esp
76673315    51              push ecx                                 ; CheckRem.0088A015
76673316    837D 08 00      cmp dword ptr ss:[ebp+0x8],0x0
7667331A    56              push esi
7667331B    74 36           je short KernelBa.76673353
7667331D    8B75 0C         mov esi,dword ptr ss:[ebp+0xC]           ; CheckRem.<ModuleEntryPoint>
76673320    85F6            test esi,esi
76673322    74 2F           je short KernelBa.76673353
76673324    6A 00           push 0x0
76673326    6A 04           push 0x4
76673328    8D45 FC         lea eax,dword ptr ss:[ebp-0x4]
7667332B    50              push eax
7667332C    6A 07           push 0x7
7667332E    FF75 08         push dword ptr ss:[ebp+0x8]              ; CheckRem.<ModuleEntryPoint>
76673331    FF15 F0A26976   call dword ptr ds:[<&ntdll.NtQueryInform>; ntdll.ZwQueryInformationProcess
76673337    85C0            test eax,eax
76673339    79 09           jns short KernelBa.76673344
7667333B    8BC8            mov ecx,eax
7667333D    E8 7EF0F4FF     call KernelBa.765C23C0
76673342    EB 17           jmp short KernelBa.7667335B
76673344    33C0            xor eax,eax
76673346    3945 FC         cmp dword ptr ss:[ebp-0x4],eax
76673349    0f95c0          setne al
7667334C    8906            mov dword ptr ds:[esi],eax -------------hook处
7667334E    33C0            xor eax,eax
76673350    40              inc eax
76673351    EB 0A           jmp short KernelBa.7667335D
76673353    6A 57           push 0x57
76673355    FF15 C8A06976   call dword ptr ds:[<&ntdll.RtlSetLastWin>; ntdll.RtlSetLastWin32Error
7667335B    33C0            xor eax,eax
7667335D    5E              pop esi                                  ; CheckRem.007C356E
7667335E    C9              leave
7667335F    C2 0800         retn 0x8

将mov dword ptr ds:[esi],eax 更改为 mov dword ptr ds:[esi],0,即89 06 33 c0 40 eb 0a更改为c7 06 00 00 00 00 90,其结果是让 CheckRemoteDebuggerPresent一直对isDebugged赋值0
关键代码实现

# include<Windows.h>
# include<Tlhelp32.h>
# include<stdio.h>
//==================================================================
//函数名: GetProcessPID
//功能:获取指定进程名的进程的PID
//输入参数1:IN,目标进程的名称
//返回值:获取成功返回PID,获取失败返回NULL
//==================================================================
DWORD GetProcessPID(PCWCHAR name)
{

    //初始化进程快照
    PROCESSENTRY32 pe32;
    pe32.dwSize = sizeof(PROCESSENTRY32);
    HANDLE hProcessSanp = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);  //获得快照句柄

    Process32First(hProcessSanp, &pe32);  //获取第一个进程
    do
    {


        if (wcscmp(name, pe32.szExeFile) == 0)
        {
            CloseHandle(hProcessSanp);//关闭快照句柄,避免内存泄漏
            return pe32.th32ProcessID; //注意这里使用的权限

        }
    } while (Process32Next(hProcessSanp, &pe32));

    CloseHandle(hProcessSanp);//关闭快照句柄,避免内存泄漏
    return NULL;


}
//==================================================================
//函数名: GetModuleInfo
//功能:获取指定进程的对应模块名的模块的信息  
//输入参数1:IN,目标进程的PID
//输入参数2:IN,指定模块的模块名
//输入参数3:OUT,模块的信息结构体 PMODULEENTRY32
//返回值:获取成功返回TRUE,获取失败返回FALSE
//注意:模块名区分大小写
//==================================================================
BOOL GetModuleInfo(DWORD pid, PCWCHAR ModuleName, OUT PMODULEENTRY32 pme32)
{
    MODULEENTRY32 me32;
    me32.dwSize = sizeof(MODULEENTRY32);                                    //在使用这个结构前,先设置它的大小
    HANDLE hModuleSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pid);  //HANDLE也是属于句柄,是通用句柄  ,HWND是窗口句柄

    if (hModuleSnap == INVALID_HANDLE_VALUE)     //INVALID_HANDLE_VALUE表示无效的句柄
    {
        printf("模块读取失败\n");
        return FALSE;
    }
    BOOL bMore = Module32First(hModuleSnap, &me32);    //获取第一个模块信息
    if (wcscmp(ModuleName, me32.szModule) == 0)
    {
        //printf("module name=%ws\n", me32.szModule);
        *pme32 = me32;
        return TRUE;
    }
    while (bMore)
    {
        bMore = Module32Next(hModuleSnap, &me32);
        if (wcscmp(ModuleName, me32.szModule) == 0)
        {
            //printf("module name=%ws\n", me32.szModule);
            *pme32 = me32;
            return TRUE;
        }
    }
    return FALSE;
}
//==================================================================
//函数名: HookModule
//功能:hook模块 
//输入参数1:IN,目标进程的进程名
//输入参数2:IN,指定模块的模块名
//输入参数3:IN,想要hook的位置与想要hook的模块的基地址的偏移
//输入参数4:IN,hook代码
//输入参数5:IN,hook代码的长度
//返回值:hook成功返回TRUE,hook失败返回FALSE
//==================================================================
BOOL HookModule(LPCWCHAR ExeName, LPCWCHAR ModuleName,DWORD Offset, char* code, DWORD Length)
{
    //devenv.exe
    DWORD ExePID = GetProcessPID(ExeName);
    printf("ExePID=%d\n", ExePID);
    if (ExePID == NULL)
    {
        printf("获取程序PID失败\n");
        return FALSE;
    }
    MODULEENTRY32 me;
    BOOL result = GetModuleInfo(ExePID, ModuleName, &me);
    if (result == FALSE)
    {
        printf("获取模块信息失败\n");
        return FALSE;
    }
    printf("module name=%ws\n", me.szModule);
    HMODULE hModule = GetModuleHandle(ModuleName);
    LONG StartPos = (LONG)hModule + (LONG)Offset;
    HANDLE hExe = OpenProcess(PROCESS_ALL_ACCESS, FALSE, ExePID);
    if (result == 0)
    {
        printf("打开进程失败\n");
        return FALSE;
    }
    DWORD NumberOfBytesRead;
    DWORD NumberOfBytesWritten;
    DWORD OldProtect;
    result = VirtualProtectEx(hExe, (PVOID)StartPos, Length, PAGE_EXECUTE_READWRITE, &OldProtect);
    if (result == 0)
    {
        printf("更改目标程序内存属性失败,错误信息=%d\n", GetLastError());
        return FALSE;
    }
    result = WriteProcessMemory(hExe, (PVOID)StartPos, code, Length, &NumberOfBytesWritten);
    if (result == 0)
    {
        printf("写内存失败\n");
        return FALSE;
    }
    result = VirtualProtectEx(hExe, (PVOID)StartPos, Length, OldProtect, &OldProtect);
    if (result == 0)
    {
        printf("恢复目标程序内存属性失败\n");
        return FALSE;
    }
    CloseHandle(hExe);
    return TRUE;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值