最近突发兴趣想写一个简单的win32 程序 调试器。
看了相关资料,把程序写出来了,但是郁闷的是:导入被调试程序后,当被调试程序发生异常时,调试器却拦截不下来?
捣鼓了一整天实在想不出来是什么原因,遂发帖向csdn众高手求教。
好,现在附上源代码:
OS:windows xp sp3
开发工具:VC 2008
/*
Crash - Process Instrumentor
Copyright (C) 2005 Pedram Amini <[email protected],[email protected]> This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the Free
Software Foundation; either version 2 of the License, or (at your option)
any later version. This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details. You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place, Suite 330, Boston, MA 02111-1307 USA Return Codes:
-1 - An error occured during the process instrumentation.
0 - Process exited normally.
1 - Process generated exception.*/#include <windows.h>
#include <stdio.h>
#include <stdlib.h>#include "libdasm.h"int main (int argc, char **argv)
{
PROCESS_INFORMATION pi;
INSTRUCTION inst;
STARTUPINFO si;
DEBUG_EVENT dbg;
CONTEXT context;
HANDLE thread;
HANDLE process;
DWORD wait_time;
DWORD start_time;
BOOL ret;
BOOL exception;
// BOOL continueDebug;
u_char inst_buf[32];
char inst_string[256];
char command_line[32768];
int i; DWORD ProcessID;
//
// variable initialization.
// memset(&pi, 0, sizeof(pi));
memset(&si, 0, sizeof(si));
si.cb = sizeof(si); memset(command_line, 0, sizeof(command_line));
memset(inst_buf, 0, sizeof(inst_buf)); start_time = GetTickCount();
exception = FALSE; //
// command line processing.
// // minimum arg check.
/*
if (argc < 4)
{
fprintf(stderr, "[!] Usage: crash <path to app> <milliseconds> <arg1> [arg2 arg3 ... argn]\n\n");
return -1;
} */ // convert wait time from string to integer.
/*
if ((wait_time = atoi(argv[2])) == 0)
{
fprintf(stderr, "[!] Milliseconds argument unrecognized: %s\n\n", argv[2]);
return -1;
}
*/ // create the command line string for the call to CreateProcess().
strcpy(command_line, argv[1]); for (i = 2; i < argc; i++)
{
strcat(command_line, " ");
strcat(command_line, argv[i]);
} //
// launch the target process.
// ret = CreateProcess(NULL, // target file name.
command_line, // command line options.
NULL, // process attributes.
NULL, // thread attributes.
FALSE, // handles are not inherited.
DEBUG_PROCESS, // debug the target process and all spawned children. NULL, // use our current environment.
NULL, // use our current working directory.
&si, // pointer to STARTUPINFO structure.
&pi); // pointer to PROCESS_INFORMATION structure. ProcessID=pi.dwProcessId;
WaitForSingleObject(ProcessID,3000);
//ret=WinExec(command_line,SW_SHOW);
printf("[*] %s\n", GetCommandLine()); //Print the command line
if (!ret)
{
fprintf(stderr, "[!] CreateProcess() failed: %d\n\n", GetLastError());
return -1;
} //
// watch for an exception.
//
DebugActiveProcess(ProcessID);
while (0< 2000)
{
if (WaitForDebugEvent(&dbg, 1000))
{
// we are only interested in debug events.
if (dbg.dwDebugEventCode != EXCEPTION_DEBUG_EVENT)
{
ContinueDebugEvent(dbg.dwProcessId, dbg.dwThreadId, DBG_CONTINUE);
continue;
} // get a handle to the offending thread.
if ((thread = OpenThread(THREAD_GET_CONTEXT, FALSE, dbg.dwThreadId)) == NULL)
{
fprintf(stderr, "[!] OpenThread() failed: %d\n\n", GetLastError());
return -1;
}
context.ContextFlags=CONTEXT_FULL;
// get the context of the offending thread.
if (GetThreadContext(thread, &context) == 0)
{
fprintf(stderr, "[!] GetThreadContext() failed: %d\n\n", GetLastError());
return -1;
} // examine the exception code.
switch (dbg.u.Exception.ExceptionRecord.ExceptionCode)
{
case EXCEPTION_ACCESS_VIOLATION:
exception = TRUE;
printf("[*] Access Violation\n");
break;
case EXCEPTION_INT_DIVIDE_BY_ZERO:
exception = TRUE;
printf("[*] Divide by Zero\n");
break;
case EXCEPTION_STACK_OVERFLOW:
exception = TRUE;
printf("[*] Stack Overflow\n");
break;
default:
//printf("[*] Unknown Exception (%08x):\n", dbg.u.Exception.ExceptionRecord.ExceptionCode);
ContinueDebugEvent(dbg.dwProcessId, dbg.dwThreadId, DBG_CONTINUE);
} SuspendThread(pi.dwProcessId); // if an exception occured, print more information.
if (1)
{
// open a handle to the target process.
if ((process = OpenProcess(PROCESS_VM_READ, FALSE, dbg.dwProcessId)) == NULL)
{
fprintf(stderr, "[!] OpenProcess() failed: %d\n\n", GetLastError());
return -1;
} // grab some memory at EIP for disassembly.
ReadProcessMemory(process, (void *)context.Eip, &inst_buf, 32, NULL); // decode the instruction into a string.
get_instruction(&inst, inst_buf, MODE_32);
get_instruction_string(&inst, FORMAT_INTEL, 0, inst_string, sizeof(inst_string)); // print the exception to screen.
printf("[*] Exception caught at %08x %s\n", context.Eip, inst_string);
printf("[*] EAX:%08x EBX:%08x ECX:%08x EDX:%08x\n", context.Eax, context.Ebx, context.Ecx, context.Edx);
printf("[*] ESI:%08x EDI:%08x ESP:%08x EBP:%08x\n\n", context.Esi, context.Edi, context.Esp, context.Ebp);
return 1;
} }
}
//
// done.
// printf("[*] Process terminated normally.\n\n");
return 0;
}
看了相关资料,把程序写出来了,但是郁闷的是:导入被调试程序后,当被调试程序发生异常时,调试器却拦截不下来?
捣鼓了一整天实在想不出来是什么原因,遂发帖向csdn众高手求教。
好,现在附上源代码:
OS:windows xp sp3
开发工具:VC 2008
/*
Crash - Process Instrumentor
Copyright (C) 2005 Pedram Amini <[email protected],[email protected]> This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the Free
Software Foundation; either version 2 of the License, or (at your option)
any later version. This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details. You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place, Suite 330, Boston, MA 02111-1307 USA Return Codes:
-1 - An error occured during the process instrumentation.
0 - Process exited normally.
1 - Process generated exception.*/#include <windows.h>
#include <stdio.h>
#include <stdlib.h>#include "libdasm.h"int main (int argc, char **argv)
{
PROCESS_INFORMATION pi;
INSTRUCTION inst;
STARTUPINFO si;
DEBUG_EVENT dbg;
CONTEXT context;
HANDLE thread;
HANDLE process;
DWORD wait_time;
DWORD start_time;
BOOL ret;
BOOL exception;
// BOOL continueDebug;
u_char inst_buf[32];
char inst_string[256];
char command_line[32768];
int i; DWORD ProcessID;
//
// variable initialization.
// memset(&pi, 0, sizeof(pi));
memset(&si, 0, sizeof(si));
si.cb = sizeof(si); memset(command_line, 0, sizeof(command_line));
memset(inst_buf, 0, sizeof(inst_buf)); start_time = GetTickCount();
exception = FALSE; //
// command line processing.
// // minimum arg check.
/*
if (argc < 4)
{
fprintf(stderr, "[!] Usage: crash <path to app> <milliseconds> <arg1> [arg2 arg3 ... argn]\n\n");
return -1;
} */ // convert wait time from string to integer.
/*
if ((wait_time = atoi(argv[2])) == 0)
{
fprintf(stderr, "[!] Milliseconds argument unrecognized: %s\n\n", argv[2]);
return -1;
}
*/ // create the command line string for the call to CreateProcess().
strcpy(command_line, argv[1]); for (i = 2; i < argc; i++)
{
strcat(command_line, " ");
strcat(command_line, argv[i]);
} //
// launch the target process.
// ret = CreateProcess(NULL, // target file name.
command_line, // command line options.
NULL, // process attributes.
NULL, // thread attributes.
FALSE, // handles are not inherited.
DEBUG_PROCESS, // debug the target process and all spawned children. NULL, // use our current environment.
NULL, // use our current working directory.
&si, // pointer to STARTUPINFO structure.
&pi); // pointer to PROCESS_INFORMATION structure. ProcessID=pi.dwProcessId;
WaitForSingleObject(ProcessID,3000);
//ret=WinExec(command_line,SW_SHOW);
printf("[*] %s\n", GetCommandLine()); //Print the command line
if (!ret)
{
fprintf(stderr, "[!] CreateProcess() failed: %d\n\n", GetLastError());
return -1;
} //
// watch for an exception.
//
DebugActiveProcess(ProcessID);
while (0< 2000)
{
if (WaitForDebugEvent(&dbg, 1000))
{
// we are only interested in debug events.
if (dbg.dwDebugEventCode != EXCEPTION_DEBUG_EVENT)
{
ContinueDebugEvent(dbg.dwProcessId, dbg.dwThreadId, DBG_CONTINUE);
continue;
} // get a handle to the offending thread.
if ((thread = OpenThread(THREAD_GET_CONTEXT, FALSE, dbg.dwThreadId)) == NULL)
{
fprintf(stderr, "[!] OpenThread() failed: %d\n\n", GetLastError());
return -1;
}
context.ContextFlags=CONTEXT_FULL;
// get the context of the offending thread.
if (GetThreadContext(thread, &context) == 0)
{
fprintf(stderr, "[!] GetThreadContext() failed: %d\n\n", GetLastError());
return -1;
} // examine the exception code.
switch (dbg.u.Exception.ExceptionRecord.ExceptionCode)
{
case EXCEPTION_ACCESS_VIOLATION:
exception = TRUE;
printf("[*] Access Violation\n");
break;
case EXCEPTION_INT_DIVIDE_BY_ZERO:
exception = TRUE;
printf("[*] Divide by Zero\n");
break;
case EXCEPTION_STACK_OVERFLOW:
exception = TRUE;
printf("[*] Stack Overflow\n");
break;
default:
//printf("[*] Unknown Exception (%08x):\n", dbg.u.Exception.ExceptionRecord.ExceptionCode);
ContinueDebugEvent(dbg.dwProcessId, dbg.dwThreadId, DBG_CONTINUE);
} SuspendThread(pi.dwProcessId); // if an exception occured, print more information.
if (1)
{
// open a handle to the target process.
if ((process = OpenProcess(PROCESS_VM_READ, FALSE, dbg.dwProcessId)) == NULL)
{
fprintf(stderr, "[!] OpenProcess() failed: %d\n\n", GetLastError());
return -1;
} // grab some memory at EIP for disassembly.
ReadProcessMemory(process, (void *)context.Eip, &inst_buf, 32, NULL); // decode the instruction into a string.
get_instruction(&inst, inst_buf, MODE_32);
get_instruction_string(&inst, FORMAT_INTEL, 0, inst_string, sizeof(inst_string)); // print the exception to screen.
printf("[*] Exception caught at %08x %s\n", context.Eip, inst_string);
printf("[*] EAX:%08x EBX:%08x ECX:%08x EDX:%08x\n", context.Eax, context.Ebx, context.Ecx, context.Edx);
printf("[*] ESI:%08x EDI:%08x ESP:%08x EBP:%08x\n\n", context.Esi, context.Edi, context.Esp, context.Ebp);
return 1;
} }
}
//
// done.
// printf("[*] Process terminated normally.\n\n");
return 0;
}
解决方案 »
- 几点考虑 未知可否
- getaddrinfo 的hints参数有什么作用?
- 关于网络编程方面的一个如何放置服务程序的问题。
- 关于WSAAsyncSelect模型去ip地址的问题~
- DirectShow: 象这样释放DirectShow资源,ActiveMovieWindow窗口为何没有正常销毁?
- 吐血!如何从数据库中得到1970年以前的时间?
- 播放RM文件
- 小问题!
- mfc和stl(c++中的)混用合适吗?
- 求教各位大神关于ListCtrl的问题
- 怎样给对话框窗口添加一副背景图片?
- VC实现类似屏保一样,等待一定时间如果没有动作,就触发一个函数的问题,大家进来帮我看看啊,例外有API函数可以获得鼠标和键盘没有动作吗?
DebugActiveProcess(ProcessID);
这两行代码是多余的,去掉再看看。
还有,如果我把createprocess的参数改为:DEBUG_PROCESS改为:CREATE_NO_WINDOW,被调试程序会异常(弹出windows 默认异常处理对话框)。但是crash.exe,还是不能捕捉到异常。这到底是怎么回事呢?
只有链接,还烦请大家自己下载;
libdasm.h:
http://libemu.carnivore.it/doxygen/html/libdasm_8h-source.html
libdasm.c:
http://libemu.carnivore.it/doxygen/html/libdasm_8c-source.html
管理员权限下,debug特权默认是disable的,需要你自己在代码里提权。
int EnableDebugPriv(const char * name)
{
HANDLE hToken;
TOKEN_PRIVILEGES tp;
LUID luid; //打开进程令牌环
OpenProcessToken(GetCurrentProcess(),
TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY,
&hToken);
//获得进程本地唯一ID
LookupPrivilegeValue(NULL,name,&luid);
tp.PrivilegeCount = 1;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
tp.Privileges[0].Luid = luid;
//调整权限
AdjustTokenPrivileges(hToken,0,&tp,sizeof(TOKEN_PRIVILEGES),NULL,NULL); CloseHandle( hToken );
return 0;
}
int EnableDebugPriv(const char * name)
{
HANDLE hToken;
TOKEN_PRIVILEGES tp;
LUID luid; //打开进程令牌环
OpenProcessToken(GetCurrentProcess(),
TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY,
&hToken);
//获得进程本地唯一ID
LookupPrivilegeValue(NULL,name,&luid);
tp.PrivilegeCount = 1;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
tp.Privileges[0].Luid = luid;
//调整权限
AdjustTokenPrivileges(hToken,0,&tp,sizeof(TOKEN_PRIVILEGES),NULL,NULL); CloseHandle( hToken );
return 0;
}
TOKEN_PRIVILEGES tkp; OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken);LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &tkp.Privileges[0].Luid); tkp.PrivilegeCount = 1;
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, (PTOKEN_PRIVILEGES)NULL, 0);
CloseHandle( hToken ); 这个提权代码仅仅是你调试运行在其他帐号下的程序才需要。
// Debuger.cpp : Defines the entry point for the console application.
//#include "stdafx.h"//#include "libdasm.h" int main (int argc, char **argv)
{
PROCESS_INFORMATION pi;
//INSTRUCTION inst;
STARTUPINFO si;
DEBUG_EVENT dbg;
CONTEXT context;
HANDLE thread;
HANDLE process;
DWORD wait_time;
DWORD start_time;
BOOL ret;
BOOL exception;
// BOOL continueDebug;
u_char inst_buf[32];
char inst_string[256];
char command_line[32768];
int i; DWORD ProcessID;
//
// variable initialization.
// memset(&pi, 0, sizeof(pi));
memset(&si, 0, sizeof(si));
si.cb = sizeof(si); memset(command_line, 0, sizeof(command_line));
memset(inst_buf, 0, sizeof(inst_buf)); start_time = GetTickCount();
exception = FALSE; //
// command line processing.
// // minimum arg check.
/*
if (argc < 4)
{
fprintf(stderr, "[!] Usage: crash <path to app> <milliseconds> <arg1> [arg2 arg3 ... argn]\n\n");
return -1;
} */ // convert wait time from string to integer.
/*
if ((wait_time = atoi(argv[2])) == 0)
{
fprintf(stderr, "[!] Milliseconds argument unrecognized: %s\n\n", argv[2]);
return -1;
}
*/ // create the command line string for the call to CreateProcess().
strcpy(command_line, argv[1]); for (i = 2; i < argc; i++)
{
strcat(command_line, " ");
strcat(command_line, argv[i]);
} //
// launch the target process.
// ret = CreateProcess(NULL, // target file name.
command_line, // command line options.
NULL, // process attributes.
NULL, // thread attributes.
FALSE, // handles are not inherited.
DEBUG_PROCESS, // debug the target process and all spawned children.
NULL, // use our current environment.
NULL, // use our current working directory.
&si, // pointer to STARTUPINFO structure.
&pi); // pointer to PROCESS_INFORMATION structure.
//ProcessID=pi.dwProcessId;
//WaitForSingleObject(ProcessID,3000);
WaitForSingleObject(pi.hProcess,3000);
//ret=WinExec(command_line,SW_SHOW);
printf("[*] %s\n", GetCommandLine()); //Print the command line
if (!ret)
{
fprintf(stderr, "[!] CreateProcess() failed: %d\n\n", GetLastError());
return -1;
} //
// watch for an exception.
// //DebugActiveProcess(ProcessID);
DebugActiveProcess(pi.dwProcessId);
while (0 < 2000)
{
if (WaitForDebugEvent(&dbg, 1000))
{
// we are only interested in debug events.
if (dbg.dwDebugEventCode != EXCEPTION_DEBUG_EVENT)
{
ContinueDebugEvent(dbg.dwProcessId, dbg.dwThreadId, DBG_CONTINUE);
continue;
} // get a handle to the offending thread.
if ((thread = OpenThread(THREAD_GET_CONTEXT, FALSE, dbg.dwThreadId)) == NULL)
{
fprintf(stderr, "[!] OpenThread() failed: %d\n\n", GetLastError());
return -1;
}
context.ContextFlags=CONTEXT_FULL;
// get the context of the offending thread.
if (GetThreadContext(thread, &context) == 0)
{
fprintf(stderr, "[!] GetThreadContext() failed: %d\n\n", GetLastError());
return -1;
} // examine the exception code.
switch (dbg.u.Exception.ExceptionRecord.ExceptionCode)
{
case EXCEPTION_ACCESS_VIOLATION:
exception = TRUE;
printf("[*] Access Violation\n");
break;
case EXCEPTION_INT_DIVIDE_BY_ZERO:
exception = TRUE;
printf("[*] Divide by Zero\n");
break;
case EXCEPTION_STACK_OVERFLOW:
exception = TRUE;
printf("[*] Stack Overflow\n");
break;
default:
//printf("[*] Unknown Exception (%08x):\n", dbg.u.Exception.ExceptionRecord.ExceptionCode);
ContinueDebugEvent(dbg.dwProcessId, dbg.dwThreadId, DBG_CONTINUE);
} //SuspendThread(pi.dwProcessId);
//SuspendThread(pi.hThread); // if an exception occured, print more information.
if (1)
{
// open a handle to the target process.
if ((process = OpenProcess(PROCESS_VM_READ, FALSE, dbg.dwProcessId)) == NULL)
{
fprintf(stderr, "[!] OpenProcess() failed: %d\n\n", GetLastError());
return -1;
} // grab some memory at EIP for disassembly.
ReadProcessMemory(process, (void *)context.Eip, &inst_buf, 32, NULL); // decode the instruction into a string.
//get_instruction(&inst, inst_buf, MODE_32);
//get_instruction_string(&inst, FORMAT_INTEL, 0, inst_string, sizeof(inst_string)); // print the exception to screen.
//printf("[*] Exception caught at %08x %s\n", context.Eip, inst_string);
//printf("[*] EAX:%08x EBX:%08x ECX:%08x EDX:%08x\n", context.Eax, context.Ebx, context.Ecx, context.Edx);
//printf("[*] ESI:%08x EDI:%08x ESP:%08x EBP:%08x\n\n", context.Esi, context.Edi, context.Esp, context.Ebp); //return 1;
}
}
}
//
// done.
// printf("[*] Process terminated normally.\n\n");
return 0;
}这个是我在你的代码基础上做出修改的,可以正常捕获到异常的代码。
单步走走看看。