您好,欢迎访问三七文档
当前位置:首页 > 商业/管理/HR > 信息化管理 > 黑客手册第二十八课Win32调试API第一部分
黑客手册第二十八课Win32调试API第一部分在本教程中,我们将学习Win32提供给开发者的用于调试的原语在教梧的结尾,我们将学习如何调试个进程.例子.理论:Win32有些供程序员使用的API,它们提供相当于调试器的功能.他们被称作Win32调试API(或原语).利用这些API,我们可以:.加载个程序或捆绑到个正在运行的程序上以供调试.获得被调试的程序的低层信息,例如进程ID,进入地址,映像基址等.·当发生与调试有关的事件时被通知,例如进程/线梧的开始/结束,DLL的加载/释放等.修改被调试的进程或线理简而言之,我们可以用这些API写一个简单的调试器.由于这个题目有些过大,我把它分为几部分,而本教f'E就是它的第一部分.在本教程中,我将讲解一些基本概念及Win32调试API的大致框;!J,口.使用Win32调试API的步骤如下:1.创建个进程或捆绑到个运行中的进程上.这是使用Win32调试API的第步.由于我们的程序要扮演调试器的角色,我们要找个供调试的程序.个被调试的程序被称为debuggee可以通过以下两种方式获得debuggee:。通过CreateProcess创建debuggee进程.为了创建被调试的进程,必须指定DEBUGPROCESS标志这标志告诉Windows我们要调试该进程当debuggee中发生重要的与调试有关的事件(调试事件)时,Windows会向我们的程序发送通知debuggee会立即挂起以等待我们的程序准备好.如果debuggee还创建了子进稽,Windows还会为每个子进程中的调试事件向我们的程序发送通知.这特性通常是不必要的.我们可以通过指定DEBUGONLYTHISPROCESS与DEBUGPROCESS的组合标志来禁止它。我们也可以用DebugActiveProcess标志捆绑到个运行中的进程上2.等待调试事件.在获得了个debuggee进程后,debuggee的主线理被挂起,这种状况将持续到我们的程序调用WaitForDebugEvent为止这个函数和其他的WaitForXXX函数相似,比如说,它阻塞调用线理直到等待的事件发生.对这个函数来说,它等待自Windows发送的调试事件下面是它的定义·WaitForDebugEventprotolpDebugEvent:DWORD,dwMilliseconds:DWORDlpDebugEventistheaddressofaDEBUGEVENT这个结构将被填入关于debuggee中发生的调试事件的信息.dwMilliseconds该函数等待调试事件的时间,以毫秒为单位.如果这段时间没有调试事件发生,WaitForDebugEvent返回调用者另方面,如果将该参数指定为INFINITE常数,函数将直等待直到调试事件发生现在我们看下DEBUGEVENT结构DEBUGEVENl、STRUCTdwDebugEventCodedd?dwProcesslddd?dwTbreadlddd?uDEBUGSTRUCTDEBUGEVE阳回DSdwDebugEventCode该值指定了等待发生的调试事件的类型因为有很多种类型的事件发生,我们的程序要检查该值,知道要发生事件的类型并做出口向应.该值可能的取值如下:取值含义进程被创建当debuggee进程刚被创建(还未运行)或CREATEPROCESSDEBUGEVENT我们的程序刚以DebugActiveProcess被捆绑到个运行中的进程时事件发生这是我们的程序应该获得的第个事件|EXItPROCESSDE即飞EVE盯11进程退出当个新线埋在deuggee进程中创建或我们的程序首CREATETHEADDEBUGEVENT次捆绑到运行中的进程时事件发生.要注意的是当debugge的主线理被创建时不会收到该通知debuggee中的线理退出时事件发生.debugee的主线理退出时不会收到该通知我们可以认为debuggee的主EXITn配EADDEBUGEVENT线理与debugge进程是同义词因此,当我们的程序看到CREATEPROCESSDEBUGEVENT标志时,对主线理来说,就是CREATETHREADDEBUGEV四T标志.debuggee装入个DLL当PE装载器第次分解指向LOADDLLDEBUGEVENTDLL的链接时,我们将收到这事件.(当调用CreateProcess装入debuggeeS才)并且当debuggee调用LoadLibrary时也会发生|UNLOADDLLDEBU飞EV四T11个DLL从debuggee中卸载时事件发生在debuggee中发生异常时事件发生.注意:该事件仅在debuggee开始它的第条指令之前发生次异常实际上是个调试中断(int3h).如果想恢复EXCEPTIONDEBUGEVENTdebuggee事,以DBGCONTINUE标志调用ContinueDebugEvent函数.不要使用DBGEXCEPTIONNOTHANDLED标志否则debuggee会在NT下拒绝运行(Win98下运行得很好).OUTPUTDEBUGSTRINGEV四T当debuggee调用DebugOutputString函数向我们的理序发送消息字符串时该事件发生IRIP_EV四T11系统调试发生错误dwProcessld和dwTbreadld发生调试事件的进程和线理Id.我们可以用这些值作为我们感兴趣的进程或线梧的标志符.记住如果我们使用CreateProcess来装载debuggee,我们仍可在PROCESSINFO结构中获得debuggee的进程和线理我们可以用这些值来区别调试事件是发生在debuggee中还是它的子进程中(当没有指定DEBUGONLYTHISPROCESS标志时)u是个联合,包含了调试事件的更多信息.根据上面dwDebugEventCode的不同,它可以是以下结构:dwDebugEventCodeU的解释11CREATEPROCESSDEBUGEVENT名为CreateProcesslnfo的CREATEPROCESSDEBUGINFO结构1EXIT_PROCESS_DEBU飞EVE盯11名为ExitProce础EXItmCESSDEBU飞INFO结构ICREATE_THREA飞DEBUG卫V四DI名为Crea臼Thread的CREATETHREA飞DEBUGINFO结构1EXIT_THREAD_DEBUG_EVENT11名为ExitThread的EXITTHREωDEBU飞EVENT结构1LOAD_DLL_DEBUG_EVENT11名为Loa川的LOADDLLDEBU飞INFO结构|四川飞DLLDEBU飞EV四T11名为UnloadDll的四川飞DLLDEBU飞INFO结构1EXCEPTION_DE即飞EVE盯11名为Exception的EXCEPTION一DEBUGINFO结构IOUTPUT_DEBU飞STRING卫V四DI名为Deb时tring的OUTPUTDEBU飞STRINGINFO结构11名为Ripln叫RIPINFO结构我不会在这个教程里讲所有这些结构的细节,这里只详细讲下CREATEPROCESSDEBUGINFO结构.假设我们的程序调用了WaitForDebugEvent函数并返回,我们要做的第一件事就是检查dwDebugEventCode中的值来看debuggee进程中发生了那种类型的调试事件.比如说,如果dwDebugEventCode的值为CREATEPROCESSDEBUGEVENT,就可认为U的成员为CreateProcesslnfo并用u.CreateProcesslnfo来访问.3.在我们的程序中做对调试事件的晌应.当WaitForDebugEvent返回时,这意味着在debuggee进程中发生了调试事件或者发生了超时.所以我们的程序要检查dwDebugEventCode来作出适当的反应这里有些象处理Windows消息:由用户来选择和忽略消息.4.继续运行debuggee当调试事件发生时,Windows挂起了debuggee,所以当我们处理完调试事件,还要让debuggee继续运行.调用ContinueDebugEvent函数来完成这过程.ContinueDebugEventprotodwProcessld:DWORD,dwThreadld:DWORD,dwContinueStatus:DWORD该函数恢复由于调试事件而挂起的线理.dwProcessld和dwThreadld是要恢复的线梧的进程ID和线理由,通常这两个值从DEBUGEVE盯结构的dwProcessld和dwThreadld成员获得.dwContinueStatus显示了如何继续报告调试事件的线稽可能的取值有两个·DBGCONTINUE和DBGEXCEPTIONNOTHANDLED.对大多数调试事件,这两个值都样·恢复线理.唯的例外是EXCEPTION_DEBUG_EVENT,如果线理报告发生了个异常调试事件,这意味着在debuggee的线程中发生了个异常.如果指定了DBG_CONTINUE,线程将忽略它自己的异常处理部分并继续执行.在这种情况下,我们的程序必须在以DBGCONTINUE恢复线稽之前检查并处理异常,否则异常将生生不息地不断发生....如果我们指定了DBGEXCEPTIONNOTHANDLED值,就是告诉Windows我们的程序并不处理异常:Windows将使用debuggee的默认异常处理函数来处理异常.总而言之,如果我们的程序没有考虑异常,而调试事件又指向debuggee进程中的个异常的话,就应调用含DBGCONTINUE标志的ContinueDebugEvent函数.否则,我们的程序就必须以DBGEXCEPTIONNOTHANDLED调用ContinueDebugEvent.但在下面这种情况下必须使用DBGCONTINUE标志:第个在ExceptionCode成员中有值EXCEPTIONBREAKPOINT的EXCEPTIONDEBUGEVENT事件.当debuggee开始执行它的第条指令时,我们的函数将接受到异常调试事件.它事实上是个调试中断(int3h).如果我们以DBGEXCEPTIONNOTHANDLED调用ContinueDebugEvent来晌应调试事件,WindowsNT会拒绝执行debuggee(因为它没有异常处理).所以在这种情况下,要用DBGCONTINUE标志告诉Windows我们希望该线理继续执行.5.继续上面的步骤循环直到debuggee进程退出.我们的程序必须在个很象消息循环的无限循环中直到debuggee结束.该循环大体如下:.whi1eTRUEinvokeWaitForDebugEvent,addrDebugEvent,INFINITE.break.ifDebugEvent.dwDebugEventCode二EXITPROCESSDEBUGEVENT〈调试事件处理〉invokeContinueDebugEvent,DebugEvent.dwProcessld,DebugEvent.dwThreadld,DBGEXCEPTIONNOTHANDLED.endw就是说,当开始调试程序时,我们的程序不能和debuggee分开直到它结束我们再来总结下这些步骤·1.创建一个进程或捆绑我们的程序到运行中的进程上-2.等待调试事件3.晌应调试事件.4.继续执行debuggee.5.继续这一无尽循环直到debuggee进程结束例子:这个例子调试个win32程序并显示诸如进程句柄,进程Id,映象基址等.386mode1f1at,stdca11optioncasemap:noneinc1ude\masm32\inc1ude\windows.incinc1ude\masm32\inc1ude\kerne132.incinc1ude\masm32\inc1ude\comd1g32.incinc1ude\masm32\inc1ude\user32.i
本文标题:黑客手册第二十八课Win32调试API第一部分
链接地址:https://www.777doc.com/doc-1927516 .html