zoukankan      html  css  js  c++  java
  • 调试器学习

    #include "stdafx.h"
    #include <stdlib.h>
    #define WINVER 0x0501
    #include <windows.h>
    
    BOOL
    DbgNewProcess( LPTSTR szCmdLine)
    {
    	STARTUPINFO           StartupInfo;
    	PROCESS_INFORMATION   ProcessInfo;
    
    	memset ( &StartupInfo , NULL , sizeof ( STARTUPINFO ) ) ;
    	memset ( &ProcessInfo , NULL , sizeof ( PROCESS_INFORMATION ) ) ;
    
    	StartupInfo.cb = sizeof ( STARTUPINFO ) ;
    
    	//-- create the Debuggee process
    	if( !CreateProcess(
    		 0L,
    		 szCmdLine,
    		 (LPSECURITY_ATTRIBUTES) 0L,
    		 (LPSECURITY_ATTRIBUTES) 0L,
    		 TRUE,
    		 DEBUG_PROCESS | CREATE_NEW_CONSOLE | NORMAL_PRIORITY_CLASS,
    		 (LPVOID) 0L,
    		 (LPTSTR) 0L,
    		 &StartupInfo, &ProcessInfo ) ) 
    	{
    		TCHAR szMsg[MAX_PATH];
    
    		FormatMessage( 
    			FORMAT_MESSAGE_FROM_SYSTEM | 
    			FORMAT_MESSAGE_IGNORE_INSERTS,
    			NULL,
    			GetLastError(),
    			0, // Default language
    			(LPTSTR) szMsg,
    			MAX_PATH,
    			NULL 
    			);
    
    		printf("Failed in CreateProcess() with error:
      ");
    		printf(szMsg);	printf("
    ");
    		return( FALSE );
    	}
    	else
    	{
    		CloseHandle( ProcessInfo.hProcess );
    		CloseHandle( ProcessInfo.hThread );
    	}
    
    	return( TRUE );
    }
    #define MAX_DBG_EVENT 9
    LPTSTR DbgEventName[ MAX_DBG_EVENT+1] = {
        "EXCEPTION_DEBUG_EVENT",
        "CREATE_THREAD_DEBUG_EVENT",
        "CREATE_PROCESS_DEBUG_EVENT",
        "EXIT_THREAD_DEBUG_EVENT",
        "EXIT_PROCESS_DEBUG_EVENT",
        "LOAD_DLL_DEBUG_EVENT",
        "UNLOAD_DLL_DEBUG_EVENT",
    	"OUTPUT_DEBUG_STRING_EVENT",
    	"RIP_EVENT",
        "Unknown Debug Event"
    };
    //////////////////////////////在处理完调试事件后,调试器会调用 ContinueDebugEvent API来恢复调试事件
    BOOL DbgMainLoop(DWORD dwWaitMS)
    {
    	DEBUG_EVENT DbgEvt;                   // debugging event information 
    	DWORD dwContinueStatus = DBG_CONTINUE; // exception continuation 
    	BOOL bExit=FALSE;
    
    	while(!bExit) 
    	{ 
    		// Wait for a debugging event to occur. The second parameter indicates 
    		// number of milliseconds to wait for a debugging event. If the parameter
    		// is INFINITE the function does not return until a debugging event occurs. 
     
    		if(!WaitForDebugEvent(&DbgEvt, dwWaitMS))
    		{
    			printf("WaitForDebugEvent() returned False %d.
    ",GetLastError());
    			bExit=TRUE;
    			continue;
    		}
     
    		// Process the debugging event code. 
    		printf("Debug event received from process %d thread %d: %s.
    ",
    			DbgEvt.dwProcessId,	DbgEvt.dwThreadId,
    			DbgEventName[DbgEvt.dwDebugEventCode>
    				MAX_DBG_EVENT?MAX_DBG_EVENT:
    				DbgEvt.dwDebugEventCode-1]); 
    
    		switch (DbgEvt.dwDebugEventCode) 
    		{ 
    			case EXCEPTION_DEBUG_EVENT: 
    			// Process the exception code. When handling 
    			// exceptions, remember to set the continuation 
    			// status parameter (dwContinueStatus). This value 
    			// is used by the ContinueDebugEvent function. 
    				printf("-Debuggee breaks into debugger; press any key to continue.
    ");
    				getchar();
    				//return TRUE;
    
    				switch (DbgEvt.u.Exception.ExceptionRecord.ExceptionCode) 
    				{ 
    					case EXCEPTION_ACCESS_VIOLATION: 
    					// First chance: Pass this on to the system. 
    					// Last chance: Display an appropriate error. 
    						break;
     
    					case EXCEPTION_BREAKPOINT: 
    					// First chance: Display the current 
    					// instruction and register values. 
    						break;
     
    					case EXCEPTION_DATATYPE_MISALIGNMENT: 
    					// First chance: Pass this on to the system. 
    					// Last chance: Display an appropriate error. 
    						break;
     
    					case EXCEPTION_SINGLE_STEP: 
    					// First chance: Update the display of the 
    					// current instruction and register values. 
    						break;
     
    					case DBG_CONTROL_C: 
    					// First chance: Pass this on to the system. 
    					// Last chance: Display an appropriate error. 
    						break;
     
    					default:
    					// Handle other exceptions. 
    						break;
    				} 
     
    			case CREATE_THREAD_DEBUG_EVENT: 
    			// As needed, examine or change the thread's registers 
    			// with the GetThreadContext and SetThreadContext functions; 
    			// and suspend and resume thread execution with the 
    			// SuspendThread and ResumeThread functions. 
    				break;
    
    			case CREATE_PROCESS_DEBUG_EVENT: 
    			// As needed, examine or change the registers of the 
    			// process's initial thread with the GetThreadContext and 
    			// SetThreadContext functions; read from and write to the 
    			// process's virtual memory with the ReadProcessMemory and 
    			// WriteProcessMemory functions; and suspend and resume 
    			// thread execution with the SuspendThread and ResumeThread 
    			// functions. Be sure to close the handle to the process image 
    			// file with CloseHandle.
    				break;
     
    			case EXIT_THREAD_DEBUG_EVENT: 
    			// Display the thread's exit code. 
    				break;
     
    			case EXIT_PROCESS_DEBUG_EVENT: 
    			// Display the process's exit code. 
    				bExit=TRUE;
    				break;
     
    			case LOAD_DLL_DEBUG_EVENT: 
    			// Read the debugging information included in the newly 
    			// loaded DLL. Be sure to close the handle to the loaded DLL 
    			// with CloseHandle.
    				break;
     
    			case UNLOAD_DLL_DEBUG_EVENT: 
    			// Display a message that the DLL has been unloaded. 
    				break;
     
    			case OUTPUT_DEBUG_STRING_EVENT: 
    			// Display the output debugging string. 
    				break;
     
    		} 
     
    		// Resume executing the thread that reported the debugging event. 
     		ContinueDebugEvent(DbgEvt.dwProcessId, 
    			DbgEvt.dwThreadId, dwContinueStatus); 
    //Enables a debugger to continue a thread that previously reported a debugging event.
     	}
    	return TRUE;
    }
    void Help()
    {
       printf ( "TinyDbgr <PID of Program to Debug>|
        "
                 "<Full Exe File Name> [Prgram Parameters]
    " ) ;
    }
    int main(int argc, char* argv[])
    {
    	if(argc<=1) 
    	{
    		Help();	return -1;
    	}
    	if (strstr(strupr(argv[1]),".EXE"))//将字符串s转换为大写形式说明:只转换s中出现的小写字母,不改变其它字符...
    	{//从字符串str1中查找是否有字符串str2,如果有,从str1中的str2位置起,返回str1中str2起始位置的指针,如果没有,返回null。
    		TCHAR szCmdLine[ MAX_PATH ] ;
    		szCmdLine[ 0 ] = '' ;
    
    		for ( int i = 1 ; i < argc ; i++ )
    		{   
    			strcat ( szCmdLine , argv[ i ] ) ;
    			if ( i < argc )
    			{
    				strcat ( szCmdLine , " " ) ;
    			}
    		}
    		if(!DbgNewProcess(szCmdLine))
    		{
    			return -2;
    		}
    	}
    	else
    	{
    		if(!DebugActiveProcess(atoi(argv[1])))//If the function succeeds, the return value is nonzero.
    		{
    			printf("Failed in DebugActiveProcess() with %d.
    ",GetLastError());
    			return -2;
    		}
    
    		if(argc>2 && stricmp(argv[2],"-e")==0)
    		{
    			// try the DebugSetProcessKillOnExit() API
    			if(!DebugSetProcessKillOnExit(FALSE))
    			{//Sets the action to be performed when the calling thread exits.
    				printf("Failed in DebugSetProcessKillOnExit() with %d.
    ",GetLastError());
    			}
    		}
    		if(argc>2 && stricmp(argv[2],"-s")==0)
    		{
    			DbgMainLoop(10);
    			// try the DebugActiveProcessStop() API
    			if(!DebugActiveProcessStop(atoi(argv[1])))
    			{
    				printf("Failed in DebugActiveProcessStop() with %d.
    ",GetLastError());
    			}
    			else
    				printf("Detach debuggee successfully.
    ");
    			return 0;
    		}
    	}
    	return DbgMainLoop(INFINITE);
    }
    上面是学习的小调试器代码   看看就行·························

    两种方式:  

    1  输入PID   附加到已经启动的进程

    DebugActiveProcess  实现  附加功能

    BOOL WINAPI DebugSetProcessKillOnExit(
      _In_  BOOL KillOnExit
    );

    If this parameter is TRUE, the thread terminates all attached processes on exit (note that this is the default). Otherwise, the thread detaches from all processes being debugged on exit.


    2 打开程序调试

    通过创建程序时  带调试  

    CreateProcess(
    		 0L,
    		 szCmdLine,
    		 (LPSECURITY_ATTRIBUTES) 0L,
    		 (LPSECURITY_ATTRIBUTES) 0L,
    		 TRUE,
    		 DEBUG_PROCESS | CREATE_NEW_CONSOLE | NORMAL_PRIORITY_CLASS,
    		 (LPVOID) 0L,
    		 (LPTSTR) 0L,
    		 &StartupInfo, &ProcessInfo)


    最后

    BOOL WINAPI WaitForDebugEvent(
      _Out_  LPDEBUG_EVENT lpDebugEvent,   //保存 收到的调试事件
      _In_   DWORD dwMilliseconds          //指定等待的毫秒数  INFINITE 无限期等待
    );

    来供 调试器等待和接收调试事件

    在处理完调试事件后,调试器会调用 ContinueDebugEvent API来恢复调试事件

    BOOL WINAPI ContinueDebugEvent(
      _In_  DWORD dwProcessId,
      _In_  DWORD dwThreadId,
      _In_  DWORD dwContinueStatus
    );

    最后附带一个修改程序的例子:

    #include "stdio.h"
    #include "tchar.h"
    #include "windows.h"
    
    int _tmain(int argc, _TCHAR* argv[])
    {
    	STARTUPINFO stSi;
    	PROCESS_INFORMATION stPi;
    	DEBUG_EVENT stDe;
    	int nAddrOfBreakPoint = 0x0040E813; //需要下断点的地址
    	int nAddrOfPatch = 0x004010B8;    //需要打补丁处的地址
    	unsigned char cOldByte;        //用于保存nAddrOfBreakPoint断点处的原指令
    	unsigned char cBreakPoint = 0xCC;  //int 3指令
    	unsigned char cPatchByte = 0x75;  //补丁字节
        CONTEXT stThreadContext;
    	BOOL bCreated = FALSE;
    	BOOL bFinished = FALSE;
    	//LPTSTR szCmdLine = _tcsdup(TEXT("mengmeng.exe"));
    	LPTSTR szCmdLine = _T("mengmeng.exe");
    	GetStartupInfo(&stSi);
    	bCreated = CreateProcess(NULL,szCmdLine,NULL,NULL,FALSE,DEBUG_ONLY_THIS_PROCESS,NULL,NULL,&stSi,&stPi);
    	if(!bCreated){
    		MessageBox(GetActiveWindow(),TEXT("不能打开test.exe文件!"),TEXT("Result"),MB_OK);
    		//不能打开test.exe时清除资源
    		if(szCmdLine!=NULL)  free(szCmdLine);
    		return 0;
    	}
    	//开始调试运行,等待调试事件发生
    	while(WaitForDebugEvent(&stDe,INFINITE)){//有调试事件发生
    		switch(stDe.dwDebugEventCode){
    		case CREATE_PROCESS_DEBUG_EVENT:
    			//写断点(int 3[0xCC])到nAddrOfBreakPoint,之前要保存原始指令
    			ReadProcessMemory(stPi.hProcess,(LPVOID)nAddrOfBreakPoint,&cOldByte,1,NULL);
    			WriteProcessMemory(stPi.hProcess,(LPVOID)nAddrOfBreakPoint,&cBreakPoint,1,NULL);
    			break;
    		case EXCEPTION_DEBUG_EVENT:
    			if(stDe.u.Exception.ExceptionRecord.ExceptionCode == EXCEPTION_BREAKPOINT){//断点异常
    				
    				//若不是在nAddrOfBreakPoint处中断,则继续等待
    				stThreadContext.ContextFlags = CONTEXT_CONTROL;
    				GetThreadContext(stPi.hThread,&stThreadContext);
    				if(stThreadContext.Eip!=nAddrOfBreakPoint+1) break;        
    				//执行内存补丁
    				WriteProcessMemory(stPi.hProcess,(LPVOID)0x004010B8,&cPatchByte,1,NULL);
    				//恢复nAddrOfBreakPoint原始指令,并重新执行该指令
    				WriteProcessMemory(stPi.hProcess,(LPVOID)nAddrOfBreakPoint,&cOldByte,1,NULL);
    				stThreadContext.ContextFlags = CONTEXT_FULL;
    				GetThreadContext(stPi.hThread,&stThreadContext);
    				stThreadContext.Eip = nAddrOfBreakPoint;
    				SetThreadContext(stPi.hThread,&stThreadContext);
    			}
    			break;
    		case EXIT_PROCESS_DEBUG_EVENT:  
    			bFinished = TRUE;
    			
    		}
    		ContinueDebugEvent(stPi.dwProcessId,stPi.dwThreadId,DBG_CONTINUE);//继续让被调试的程序执行
    		if(bFinished)break;
    	}
    	//破解成功后清除内存资源
    	if(szCmdLine!=NULL)  free(szCmdLine);
    	CloseHandle(stPi.hThread);
    	CloseHandle(stPi.hProcess);
    	return 0;
    }
    

















  • 相关阅读:
    c# 读改xml
    window
    c# 日期字符格式化
    验证字符串是否为数字
    MySQL常用操作基本操作
    将参数扩展为指定长度的字符串,不足位数的在前方加0
    hp服务器重装后,启动apache和tomcat和mysql
    [转] 各种取整数函数(VB)
    [原] access97中textbox类似vb的maxlength功能的实现
    [转] csv文件的读写
  • 原文地址:https://www.cnblogs.com/zcc1414/p/3982428.html
Copyright © 2011-2022 走看看