2871人阅读
安全(ring3)(21)
CheckRemoteDebuggerPresent这个API可以检测是否有调试器的存在,而且这个和PEB里面的BeingDebugged无关了。看一下CheckRemoteDebuggerPresent的声明:
HANDLE hProcess,
PBOOL pbDebuggerPresent
第一个参数是进程句柄,第二参数用于存放结果。返回值表示函数是否执行成功,
; 堆栈示意图
hProcess ; ebp + 8
&-------------------------------------------
7C85AA22 &
MOV EDI,EDI
MOV EBP,ESP
837D 08 00
CMP DWORD PTR SS:[EBP+8],0
; hProcess == 0 ?
JE SHORT 7C85AA63
; jmp exit
MOV ESI,DWORD PTR SS:[EBP+C]
; esi = pBool
TEST ESI,ESI
; esi == 0?
JE SHORT 7C85AA63
; jmp exit
LEA EAX,DWORD PTR SS:[EBP+8] ;
; push offset hProcess
; push ProcessDebugPort
PUSH DWORD PTR SS:[EBP+8]
; push hProcess
FF15 AC10807C
CALL DWORD PTR DS:[&&ntdll.NtQueryInform&
; ntdll.ZwQueryInformationProcess
TEST EAX,EAX
; eax == 0 ?
JGE SHORT 7C85AA54
; eax &= 0 -----------
; push eax
E8 ABE9FAFF
CALL 7C8093FD
; call 7C8093FD
JMP SHORT 7C85AA6A
XOR EAX,EAX
; eax = 0 &-----------
CMP DWORD PTR SS:[EBP+8],EAX ; hProcess == 0 ?
; hProcess != 0 --& al = 1 (else al = 0)
MOV DWORD PTR DS:[ESI],EAX
; *pBool = eax
XOR EAX,EAX
JMP SHORT 7C85AA6C
; jmp ----------------
E8 D8E8FAFF
CALL 7C809342
; call 7C809342
XOR EAX,EAX
; &-------------------
--------------------------------------------------------------------------------
&span style=&font-family:Abackground-color: rgb(255, 255, 255);&&&/span&
CheckRemoteDebuggerPresent实际上调用了ntdll里面的ZwQueryInformationProcess来检测。这是一个Native API,声明如下:
NTSTATUS NtQueryInformationProcess (
__in HANDLE ProcessHandle,
__in PROCESSINFOCLASS ProcessInformationClass,
__out_bcount(ProcessInformationLength) PVOID ProcessInformation,
__in ULONG ProcessInformationLength,
__out_opt PULONG ReturnLength
&span style=&font-family:Abackground-color: rgb(255, 255, 255);&&&/span&
这里第二个参数是7,实际上被定义为ProcessDebugPort
测试代码如下:
HMODULE hKernel32Dll = ::LoadLibrary(TEXT(&kernel32.dll&));
if (NULL != hKernel32Dll)
fnCheckRemoteDebuggerPresent fn =
(fnCheckRemoteDebuggerPresent)::GetProcAddress(hKernel32Dll, &CheckRemoteDebuggerPresent&);
::FreeLibrary(hKernel32Dll);
return DGBTOOL_NO;
BOOL bDebuggerPresent = FALSE;
if(fn(GetCurrentProcess(), &bDebuggerPresent)
&&bDebuggerPresent)
::FreeLibrary(hKernel32Dll);
return DBGTOOL_CUSTOM;
::FreeLibrary(hKernel32Dll);
return DGBTOOL_NO;
return DGBTOOL_NO;
过掉方法:Hook住CheckRemoteDebuggerPresent,调用了ZwQueryInformationProcess之前的je改成jmp来跳过Zw这个函数~~OD还会在ZwQueryInformationProcess这个函数的调用地址强行改了,去调用作者的一个函数,该函数中根据是否查询的是7来决定时候调用ZwQueryInformationProcess:
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:865656次
积分:12224
积分:12224
排名:第911名
原创:399篇
转载:65篇
评论:80条
(1)(1)(4)(7)(2)(4)(1)(2)(1)(3)(3)(2)(7)(6)(3)(6)(2)(9)(8)(3)(12)(10)(7)(1)(5)(10)(1)(2)(7)(13)(12)(22)(11)(29)(14)(6)(3)(1)(30)(7)(5)(14)(24)(9)(7)(12)(4)(2)(2)(7)(10)(15)(2)(6)(3)(4)1086人阅读
调试分析(10)
技术杂烩(57)
zwsetinformationthread 调用后会修改_Ethread结构中的HideFromDebuggers
typedef enum _THREADINFOCLASS {
ThreadBasicInformation, // 0 Y N
ThreadTimes, // 1 Y N
ThreadPriority, // 2 N Y
ThreadBasePriority, // 3 N Y
ThreadAffinityMask, // 4 N Y
ThreadImpersonationToken, // 5 N Y
ThreadDescriptorTableEntry, // 6 Y N
ThreadEnableAlignmentFaultFixup, // 7 N Y
ThreadEventPair, // 8 N Y
ThreadQuerySetWin32StartAddress, // 9 Y Y
ThreadZeroTlsCell, // 10 N Y
ThreadPerformanceCount, // 11 Y N
ThreadAmILastThread, // 12 Y N
ThreadIdealProcessor, // 13 N Y
ThreadPriorityBoost, // 14 Y Y
ThreadSetTlsArrayAddress, // 15 N Y
ThreadIsIoPending, // 16 Y N
ThreadHideFromDebugger // 17 N Y
} THREAD_INFO_CLASS;
typedef NTSTATUS (NTAPI *ZwSetInformationThread)(
IN HANDLE ThreadHandle,
IN THREAD_INFO_CLASS ThreadInformaitonClass,
IN PVOID ThreadInformation,
IN ULONG ThreadInformationLength
应用层调用:
HMODULE hM
hwnd=GetCurrentThread();
hModule=LoadLibrary(&ntdll.dll&);
ZwSetInformationThread myF
myFunc=(ZwSetInformationThread)GetProcAddress(hModule,&ZwSetInformationThread&);
myFunc(hwnd,ThreadHideFromDebugger,NULL,NULL);
用IDA的字符串查看,可以看到ZwSetInformationThread来初步判断是否采用这个技术。
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:88505次
积分:1356
积分:1356
排名:千里之外
原创:39篇
转载:58篇
(1)(1)(2)(6)(5)(3)(2)(2)(7)(8)(2)(1)(5)(1)(4)(2)(3)(2)(1)(2)(1)(4)(1)(2)(1)(3)(36)最近看了一些反外挂方面的资料,里面描述了一个利用SEH结构来反调试的方式。我自己写代码测试了一下, 用官网下载的OD加载程序,确实起到了反调试的作用。我就兴冲冲的封装了一下,然后给同事测试,结果他用他的改良版OD居然能无碍的调试,我当时就泪奔了。话不多说,直接上代码。
1 #include &iostream&
3 using namespace
5 //以类成员函数作为回调
6 template&typename Obj, typename fun&
7 class ClassExc
ClassExc(Obj* o, fun f) : o_(o), f_(f)
void TriggerException()
int i = 0;
int a = 0/i;
_except(1)
(o_-&*f_)();
28 private:
33 // 普通函数作为回调
34 template&typename fun&
35 class NormalExc
37 public:
NormalExc(fun f) : f_(f)
void TriggerException()
int i = 0;
int a = 0/i;
_except(1)
55 private:
59 class My
61 public:
void Test()
cout && "MY::Test" &&
68 void NormalExcHandle()
cout && "NormalExcHandle" &&
73 int main()
typedef void (My::*myfun)();
myfun f= &My::T
ClassExc&My, myfun& e(&m, f);
e.TriggerException(); // 触发异常,流程转到了f
NormalExc&void (*)()& ne(NormalExcHandle);
ne.TriggerException(); // 出发异常, 流程转到了NormalExcHandle
getchar();
两个类模板,ClassExc类模板允许以一个类的成员函数作为回调,当异常发生时。NormalExc类模板允许以一个普通函数作为回调,当异常发生时。
代码非常简单,大家可以用一般的OD加载测试一下。
阅读(...) 评论()