15.ring3-反调试小结

1.IsDebuggerPresent 检测是否在函数头有普通断点,或是否被挂钩

2.CheckRemoteDebuggerPresent(ProcessDebugPort)

3.NtGlobalFlags,测试发现直接运行工程会提示有调试器,windbg初始附加运行提示有调试器,但windbg中间附加不会提示有调试器,测试失败,但可用.

0:000> dt _PEB -y NtGlobalFlag @$peb
test1!_PEB
   +0x068 NtGlobalFlag : 0x40000
DbgToolType AD_NtGlobalFlags()
{
 __asm
 {
  mov eax, fs:[30h]
  mov eax, [eax+68h]
  and eax, 0x70
  test eax, eax
  jne rt_label
  jmp rf_label
 }
rt_label:
 return DBGTOOL_CUSTOM;
rf_label:
 return DBGTOOL_NO;
}


4.通过列举运行的应用程序的窗口,并于常用调试相关工具比对(但调试器不一定附加在自己进程)

DbgToolType AD_FindDbgToolWindow()
{
 if (::FindWindow(_T("ollydbg"),NULL)
  || ::FindWindow(_T("pe--diy"),NULL))//oLLYICE的类名叫pe--diy
 {
  MyOutputDebugString(_T("[AD_FindDbgToolWindow] DBGTOOL_OD"));
  return DBGTOOL_OD;
 }

 if (::FindWindow(_T("WinDbgFrameClass"),NULL))
 {
  MyOutputDebugString(_T("[AD_FindDbgToolWindow] DBGTOOL_WINDBG"));
  return DBGTOOL_WINDBG;
 }

 return DBGTOOL_NO;
}

5.通过列举运行的应用程序的进程名,并于常用调试相关工具比对(但调试器不一定附加在自己进程)

DbgToolType AD_FindDbgToolProcess()
{
 HANDLE hProcSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
 if (INVALID_HANDLE_VALUE == hProcSnap)
 {
  return DBGTOOL_NO;
 }

 PROCESSENTRY32 pe32 = {sizeof(PROCESSENTRY32)};
 if (!Process32First(hProcSnap, &pe32))
 {
  CloseHandle(hProcSnap);

  return DBGTOOL_NO;
 }

 do 
 { 
  if (0 == _tcsicmp(pe32.szExeFile, _T("OLLYICE.EXE"))
   || 0 == _tcsicmp(pe32.szExeFile, _T("OLLYDBG.EXE")))
  {
   return DBGTOOL_OD;
  }

  if (0 == _tcsicmp(pe32.szExeFile, _T("WINDBG.EXE")))
  {
   return DBGTOOL_WINDBG;
  }

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

    CloseHandle(hProcSnap);
 return DBGTOOL_NO;
}


6.如果程序处于调试器中,那么在PEB结构中有个beingDegug标志会被设置6.如果程序处于调试器中,那么在PEB结构中有个beingDegug标志会被设置6.如果程序处于调试器中,那么在PEB结构中有个beingDegug标志会被设置

DbgToolType AD_BeingDebuggedFlag()
{
 __asm
 {
  mov eax,  fs:[30h]             ;EAX =  TEB.ProcessEnvironmentBlock
  inc eax
  inc eax
  mov eax,  [eax]
  and eax,  0x000000ff        ;AL  =  PEB.BeingDebugged
  test eax, eax
  jne rt_label
  jmp rf_label
 }
rt_label:
 return DBGTOOL_CUSTOM;
rf_label:
 return DBGTOOL_NO;
}

7.当一个进程获得SeDebugPrivilege,它就获得了对CSRSS.EXE的完全控制,这种特权也会被子进程继承, 也就是说一个被调试的程序如果获得了CSRSS.EXE的进程ID,它就可以使用openprocess操作CSRSS.EXE,加壳后发现提示有调试器,暂不用此方式

DbgToolType AD_SeDebugPrivilege()
{
	return DBGTOOL_NO;

	// 枚举进程,找到CSRSS.exe进程
	HANDLE hProcSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
	if (INVALID_HANDLE_VALUE == hProcSnap)
	{
		return DBGTOOL_NO;
	}

	PROCESSENTRY32 pe32 ={sizeof(PROCESSENTRY32)};
	if (!Process32First(hProcSnap, &pe32))
	{
		CloseHandle(hProcSnap);

		return DBGTOOL_NO;
	}

	DWORD  PID_csrss;
	bool findflag = false;
	do 
	{
		if (0 == _tcsicmp(pe32.szExeFile, _T("csrss.exe")))
		{
             PID_csrss = pe32.th32ProcessID;
			 findflag = true;
		}

	} while (Process32Next(hProcSnap, &pe32) && !findflag);

	if (findflag)
	{
		HANDLE hCrssPro = OpenProcess(PROCESS_QUERY_INFORMATION,false,PID_csrss);
		if (hCrssPro)
		{
			CloseHandle(hProcSnap);
			CloseHandle(hCrssPro);

			return DBGTOOL_CUSTOM;
		}        
	}

    CloseHandle(hProcSnap);
    return DBGTOOL_NO;
}

8.:给CloseHandle()函数一个无效句柄作为输入参数,在无调试器时,将会返回一个错误代码,而有调试器存在时,将会触发一个EXCEPTION_INVALID_HANDLE (0xc0000008)的异常

DbgToolType AD_ExceptionCloseHandle()
{
	__try
	{
		CloseHandle(HANDLE(0x00001234));
		return DBGTOOL_NO;
	}
	__except(1)
	{
		return DBGTOOL_CUSTOM;
	}
}


9.Window创建进程的时候会把STARTUPINFO结构中的值设为0,windbg启动程序,不会报,但OD启动它,会报有调试器,测试失败.但可用.

DbgToolType AD_CheckStartupInfo()
{
	STARTUPINFO si;
	ZeroMemory( &si, sizeof(si) );
	si.cb = sizeof(si);
	GetStartupInfo(&si);
	if ((si.dwX != 0) 
		|| (si.dwY !=0) 
		|| (si.dwXCountChars != 0)
		|| (si.dwYCountChars !=0 ) 
		|| (si.dwFillAttribute != 0)
		|| (si.dwXSize != 0) 
		|| (si.dwYSize != 0))
	{
		return DBGTOOL_CUSTOM;
	}
	else 
	{
		return DBGTOOL_NO;
	}
}


 

10.护页异常”是一个简单的反调试技巧。当应用程序尝试执行保护页内的代码时,将会产生一个EXCEPTION_GUARD_PAGE(0x80000001)异常,但如果存在调试器,调试器有可能接收这个异常,并允许该程序继续运行,事实上,在OD中就是这样处理的,OD使用保护页来实现内存断点

DbgToolType AD_OD_Exception_GuardPages()
{
	SYSTEM_INFO sSysInfo;
	LPVOID lpvBase;
	BYTE * lptmpB;
	GetSystemInfo(&sSysInfo);
	DWORD dwPageSize = sSysInfo.dwPageSize;
	DWORD flOldProtect;

	lpvBase = VirtualAlloc(NULL,dwPageSize,MEM_COMMIT,PAGE_READWRITE);
	if (lpvBase == NULL)
	{
		return DBGTOOL_NO;
	}

	lptmpB = (BYTE *)lpvBase;
	*lptmpB = 0xc3;//retn

	VirtualProtect(lpvBase, dwPageSize, PAGE_EXECUTE_READ | PAGE_GUARD, &flOldProtect);

	__try
	{
		__asm  call dword ptr[lpvBase];
		VirtualFree(lpvBase, 0, MEM_RELEASE);
		return DBGTOOL_CUSTOM;
	}
	__except(1)
	{
		VirtualFree(lpvBase, 0, MEM_RELEASE);
		return DBGTOOL_NO;
	}
}


 


DbgToolType AD_OD_Exception_GuardPages()
{
	SYSTEM_INFO sSysInfo;
	LPVOID lpvBase;
	BYTE * lptmpB;
	GetSystemInfo(&sSysInfo);
	DWORD dwPageSize = sSysInfo.dwPageSize;
	DWORD flOldProtect;

	lpvBase = VirtualAlloc(NULL,dwPageSize,MEM_COMMIT,PAGE_READWRITE);
	if (lpvBase == NULL)
	{
		return DBGTOOL_NO;
	}

	lptmpB = (BYTE *)lpvBase;
	*lptmpB = 0xc3;//retn

	VirtualProtect(lpvBase, dwPageSize, PAGE_EXECUTE_READ | PAGE_GUARD, &flOldProtect);

	__try
	{
		__asm  call dword ptr[lpvBase];
		VirtualFree(lpvBase, 0, MEM_RELEASE);
		return DBGTOOL_CUSTOM;
	}
	__except(1)
	{
		VirtualFree(lpvBase, 0, MEM_RELEASE);
		return DBGTOOL_NO;
	}
}


 

 

 


 

你可能感兴趣的:(安全(ring3))