Pnig0s1992 p.s:
使用编写调试器的一组DebugApi编写了一个ApiMonitor的雏形,可以对正在进行的进程,或者直接启动被监控程序进行监控。特点在于所有的Api签名全部写到了xml文件中,可以从外部进行导入,增强了定制性。成品用到项目中了,这里只实现个基本思想,核心代码采用C/C++编写,后来项目需要又通过Invoke,.Net互操作,因为C代码中是一个动态的调试循环所以没法写成Dll,只能把所有代码全部移植到C#平台下~这里贴出来C代码吧,一个Header.h一个MonApi.cpp,能力有限,错误在所难免,欢迎批评指正~
Header.h:
- #include <Windows.h>
- #include <stdio.h>
- #include <map>
- #include <queue>
- #include <string>
- #include <stack>
- using namespace std;
- BYTE bGetReceive;
- DWORD PID;
- HANDLE hProcess;
- HANDLE hThread;
- INT iflag = 1;
- INT iRunTime = 1;
- std::map<DWORD, HANDLE> m_thread;
- std::map<DWORD,BYTE> m_code;
- std::map<DWORD,LPVOID> m_singlethread;
- std::queue<INT> s_breakpoint;
- typedef std::queue<LPSTR> FUNC_PARAM;
- std::map<std::string,std::string> m_autoprintf;
- std::queue<CHAR> q_string;
- typedef struct FUNCINFO{
- LPSTR lpApiName;
- FUNC_PARAM fpParamList;
- LPSTR lpReturnValue;
- } FUNCINFO,*LPFUNCINFO; //定义函数信息结构体
MonApi.cpp
- #include <Windows.h>
- #include <stdio.h>
- #include <iostream>
- #include <string>
- #include <TlHelp32.h>
- #include <ImageHlp.h>
- #include <Psapi.h>
- #include <map>
- #include <queue>
- #include <stack>
- #include "header.h"
- using namespace std;
- #define STRING_LENGTH 512
- #define BUFSIZE 512
- #define PARAM_SIZE 10
- #pragma comment(lib,"psapi.lib")
- ///////////////////赋予进程DEBUG权限Done///////////////////
- string DealString(HANDLE hTarProcess,DWORD dwStringAddr);
- BOOL ImprovePriv()
- {
- HANDLE hToken;
- if(!OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES,&hToken))
- {
- printf("\n打开进程失败.(%d)",GetLastError());
- return FALSE;
- }
- TOKEN_PRIVILEGES tkp;
- tkp.PrivilegeCount = 1;
- if(!LookupPrivilegeValue(NULL,SE_DEBUG_NAME,&tkp.Privileges[0].Luid))
- { //查看指定权限对应的LUID
- printf("\n查看进程权限信息失败.(%d)",GetLastError());
- return FALSE;
- }
- tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
- if(!AdjustTokenPrivileges(hToken,FALSE,&tkp,0,NULL,NULL))
- { //调整令牌权限
- printf("\n调整令牌权限失败.(%d)",GetLastError());
- return FALSE;
- }
- CloseHandle(hToken);
- CloseHandle(hProcess);
- return TRUE;
- }
- /////////////////////////////////////////////////////////////////////
- ////////////////////////////////动态输出函数参数及返回值///////////////////////////////
- BOOL AutoPrint(HANDLE hMyProcess,LPCONTEXT pCt,FUNCINFO * pApiName,INT isReturn)
- {
- FUNCINFO ApiInfo = *pApiName;
- LPTSTR lpFormatString;
- lpFormatString = (LPSTR)HeapAlloc(GetProcessHeap(),0,BUFSIZE);
- ZeroMemory(lpFormatString,MAX_PATH);
- if(!isReturn){
- LPSTR lpPreFormat = "\nParam %d[%s]:";
- INT paramSize =ApiInfo.fpParamList.size();
- LPBYTE callMem = NULL;
- DWORD dwHasRead;
- int nMemLen = 4*paramSize;
- callMem = (LPBYTE)malloc(nMemLen);
- ReadProcessMemory(hMyProcess, (void*)(pCt->Esp + 4), callMem, nMemLen, &dwHasRead);
- DWORD* pMem = (DWORD*)callMem;
- for(int index = 0;index<paramSize;index++)
- {
- LPSTR paramTemp = (LPSTR)m_autoprintf[ApiInfo.fpParamList.front()].data();
- if(strcmp(paramTemp,"%s") == 0)
- {
- string TempStr= DealString(hMyProcess,*(pMem+index));
- LPSTR lpGetString = (LPSTR)TempStr.data();
- printf("\nParam %d[%s]:%s",index+1,ApiInfo.fpParamList.front(),lpGetString);
- }else
- {
- wsprintf(lpFormatString,paramTemp,*(pMem+index));
- printf("\nParam %d[%s]:%s",index+1,ApiInfo.fpParamList.front(),lpFormatString);
- }
- ApiInfo.fpParamList.pop();
- }
- }else
- {
- DWORD dwRc = pCt->Eax;
- LPSTR returnTemp = (LPSTR)m_autoprintf[ApiInfo.lpReturnValue].data();
- if(strcmp(returnTemp,"%s") == 0)
- {
- string TempStr = DealString(hMyProcess,dwRc);
- LPSTR lpGetString = (LPSTR)TempStr.data();
- printf("\nReturn param[%s]:%s",ApiInfo.lpReturnValue,lpGetString);
- }else
- {
- wsprintf(lpFormatString,returnTemp,dwRc);
- printf("\nReturn param[%s]:%s",ApiInfo.lpReturnValue,lpFormatString);
- }
- }
- return TRUE;
- }
- ////////////////////////////////////////////////////////////////////////////////////////////////////////
- ///////////////////////////////处理变长字符串/////////////////////////////////////
- string DealString(HANDLE hTarProcess,DWORD dwStringAddr)
- {
- DWORD dwHasRead;
- INT iIndex = 0;
- INT iCount = 0;
- CHAR ctemp;
- do{
- ReadProcessMemory(hTarProcess,(PVOID)(dwStringAddr+iIndex),&ctemp,sizeof(BYTE),&dwHasRead);
- q_string.push(ctemp);
- iIndex++;
- }while((ctemp)!= '\0');
- string sfinal;
- int len = q_string.size();
- while(iCount < len - 1)
- {
- sfinal += q_string.front();
- q_string.pop();
- iCount++;
- }
- q_string.pop(); //弹出最后的截断字符
- return sfinal;
- //return lpVarLenString;
- }
- //////////////////////////////////////////////////////////////////////////////////////////
- ////////////////////////////初始化映射表Done//////////////////////////////////
- VOID InitMap(){
- m_autoprintf.insert(make_pair("HWND","0x%08X"));
- m_autoprintf.insert(make_pair("LPCSTR","%s"));
- m_autoprintf.insert(make_pair("UINT","0x%08X"));
- m_autoprintf.insert(make_pair("INT","0x%08X"));
- }
- //////////////////////////////////////////////////////////////////////////////////////////
- ///////////////////断点处理过程Done/////////////////////
- BYTE SetBreakPoint(DWORD pAddr,BYTE code){
- BOOL bResult = TRUE;
- DWORD dwHasRead,dwOldFlag;
- if(pAddr >= 0x80000000 || pAddr == 0){
- printf("\n函数地址非法.(%d)",GetLastError());
- CloseHandle(hProcess);
- return code;
- }
- bResult = ReadProcessMemory(hProcess,(LPVOID)pAddr,&m_code[pAddr],sizeof(BYTE),&dwHasRead);//读出函数入口出的原始代码
- if(bResult == 0){
- printf("\n读取内存失败.(%d)",GetLastError());
- CloseHandle(hProcess);
- return code;
- }
- VirtualProtectEx(hProcess,(LPVOID)pAddr,sizeof(UCHAR),PAGE_READWRITE,&dwOldFlag); //更改内存区域保护属性
- WriteProcessMemory(hProcess,(LPVOID)pAddr,&code,sizeof(UCHAR),&dwHasRead); //向进程内存中写入数据
- VirtualProtectEx(hProcess,(LPVOID)pAddr,sizeof(UCHAR),dwOldFlag,&dwOldFlag); //将内存保护属性改回初始状态
- return m_code[pAddr];
- }
- ///////////////////////////////////////////////////
- ////////////////////中断处理过程///////////////////
- BOOL WINAPI DealDebugException(DEBUG_EVENT *pEvent,FUNCINFO * pApiInfo){
- DWORD dwHasRead;
- LPVOID lpBreakAddr = pEvent->u.Exception.ExceptionRecord.ExceptionAddress;
- CONTEXT ct;
- DWORD code = pEvent->u.Exception.ExceptionRecord.ExceptionCode;
- HANDLE hMyThread = m_thread[pEvent->dwThreadId];
- switch (code)
- {
- case STATUS_BREAKPOINT:
- SuspendThread(hMyThread);
- ct.ContextFlags = CONTEXT_FULL;
- GetThreadContext(hMyThread,&ct);
- ResumeThread(hMyThread);
- if(iRunTime == 1){
- s_breakpoint.push(1);
- }
- if (s_breakpoint.front() == 1)
- {
- if((DWORD)lpBreakAddr < 0x80000000){
- printf("\n\n::[API]:%s",pApiInfo->lpApiName);
- printf("\n::[MSG]BreakPoint at 0x%08X.",lpBreakAddr);
- AutoPrint(hProcess,&ct,pApiInfo,0);
- SuspendThread(hThread);
- ct.Eip--;
- ct.EFlags |= 0x00100;
- m_singlethread[pEvent->dwThreadId] = lpBreakAddr;
- SetBreakPoint((DWORD)lpBreakAddr,m_code[(DWORD)lpBreakAddr]);
- SetThreadContext(hMyThread,&ct);
- ResumeThread(hThread);
- void * lpCallBackAddr;
- DWORD buf;
- ReadProcessMemory(hProcess,(void*)ct.Esp,&buf,sizeof(buf),&dwHasRead);
- lpCallBackAddr = (void *)buf;
- if((DWORD)lpCallBackAddr < 0x80000000)
- {
- m_code[(DWORD)lpCallBackAddr] = SetBreakPoint((DWORD)lpCallBackAddr,0xCC);
- }
- }
- s_breakpoint.push(2);
- }
- ///////////////////////////////////////////两次中断分割///////////////////////////////////
- if (s_breakpoint.front() == 2)
- {
- DWORD dwRc = ct.Eax;
- printf("\n::[MSG]CallBackAddr:%p",lpBreakAddr);
- AutoPrint(hProcess,&ct,pApiInfo,1);
- SuspendThread(hMyThread);
- ct.Eip--;
- SetBreakPoint((DWORD)lpBreakAddr,m_code[(DWORD)lpBreakAddr]);
- SetThreadContext(hMyThread, &ct);
- m_singlethread[pEvent->dwThreadId] = lpBreakAddr;
- ResumeThread(hMyThread);
- s_breakpoint.push(1);
- }
- s_breakpoint.pop();
- iRunTime++;
- break;
- case EXCEPTION_SINGLE_STEP:
- SetBreakPoint((DWORD)m_singlethread[pEvent->dwThreadId],0xCC);
- m_singlethread.erase(pEvent->dwThreadId);
- break;
- default:
- return FALSE;
- }
- return TRUE;
- }
- ///////////////////////////////////////////////////////////////////////////////
- /////////////////////获得被调试程序模块列表Done////////////////////
- BOOL GetFileNameFromHandle(HANDLE hFile)
- {
- BOOL bSuccess = FALSE;
- TCHAR pszFilename[MAX_PATH+1];
- HANDLE hFileMap;
- LPSTR strFilename;
- strFilename = (LPSTR) HeapAlloc(GetProcessHeap(),0,MAX_PATH);
- ZeroMemory(strFilename,MAX_PATH);
- DWORD dwFileSizeHi = 0;
- DWORD dwFileSizeLo = GetFileSize(hFile, &dwFileSizeHi);
- if( dwFileSizeLo == 0 && dwFileSizeHi == 0 )
- {
- return FALSE;
- }
- hFileMap = CreateFileMapping(hFile,
- NULL,
- PAGE_READONLY,
- 0,
- 1,
- NULL);
- if (hFileMap)
- {
- void* pMem = MapViewOfFile(hFileMap, FILE_MAP_READ, 0, 0,1);
- if (pMem)
- {
- if (GetMappedFileName (GetCurrentProcess(),
- pMem,
- pszFilename,
- MAX_PATH))
- {
- TCHAR szTemp[BUFSIZE];
- szTemp[0] = '\0';
- if (GetLogicalDriveStrings(BUFSIZE-1, szTemp))
- {
- TCHAR szName[MAX_PATH];
- TCHAR szDrive[3] = TEXT(" :");
- BOOL bFound = FALSE;
- TCHAR* p = szTemp;
- do
- {
- *szDrive = *p;
- if (QueryDosDevice(szDrive, szName, MAX_PATH))
- {
- size_t uNameLen = lstrlen(szName);
- if (uNameLen < MAX_PATH)
- {
- bFound = strnicmp(pszFilename, szName,
- uNameLen) == 0;
- if (bFound)
- {
- wsprintf(strFilename,"%s%s",szDrive, pszFilename+uNameLen);
- printf("\n%s",strFilename);
- }
- }
- }
- while (*p++);
- } while (!bFound && *p);
- }
- }
- bSuccess = TRUE;
- UnmapViewOfFile(pMem);
- }
- CloseHandle(hFileMap);
- }
- return TRUE;
- }
- ///////////////////////////////////////////////////////////////
- ///////////////////调试监视处理过程Done/////////////////////////////
- BOOL WINAPI DealDebugEvent(DEBUG_EVENT * pEvent,FUNCINFO * pApiInfo){
- BOOL bResult = TRUE;
- switch (pEvent->dwDebugEventCode)
- {
- case CREATE_PROCESS_DEBUG_EVENT:
- hProcess = pEvent->u.CreateProcessInfo.hProcess;
- m_thread[pEvent->dwThreadId] = pEvent->u.CreateProcessInfo.hThread;
- break;
- case CREATE_THREAD_DEBUG_EVENT:
- m_thread[pEvent->dwThreadId] = pEvent->u.CreateProcessInfo.hThread;
- break;
- case EXIT_THREAD_DEBUG_EVENT:
- break;
- case EXIT_PROCESS_DEBUG_EVENT:
- break;
- case EXCEPTION_DEBUG_EVENT:
- if(iflag > 1){
- bResult = DealDebugException(pEvent,pApiInfo);
- }
- iflag++;
- break;
- case LOAD_DLL_DEBUG_EVENT:
- bResult = GetFileNameFromHandle(pEvent->u.LoadDll.hFile);
- break;
- default:
- break;
- }
- return bResult;
- }
- /////////////////////////////////////////////////////////////
- //////////////////////设置断点线程Done//////////////////////////
- DWORD WINAPI SetBreakProc(LPVOID lpParam){
- DWORD dwFuncAddress;
- Sleep(1000);
- dwFuncAddress =(DWORD) GetProcAddress(LoadLibrary("User32.dll"),"MessageBoxA");
- m_code[dwFuncAddress] = SetBreakPoint(dwFuncAddress,0xCC); //在函数入口点处设置断点
- if(bGetReceive == 0xCC){
- printf("\n设置断点失败.(%d)",GetLastError());
- return 0;
- }else{
- printf("\n设置断点成功.");
- }
- return 1;
- }
- ////////////////////////////////////////////////////////////
- /////////////////////调试器处理线程Done/////////////////////////
- DWORD WINAPI DebugProc(LPVOID lpParam){
- if(ImprovePriv()){
- printf("提权成功.\n");
- }
- //////////////////////////////////挂载运行时进程将此段注释掉/////////////////////////////////////
- LPSTR lpCmdLine = "WaitMessageBox.exe";
- DEBUG_EVENT dbe;
- BOOL bResult = TRUE;
- STARTUPINFO si;
- PROCESS_INFORMATION pi;
- ZeroMemory(&si,sizeof(si));
- ZeroMemory(&pi,sizeof(pi));
- si.cb = sizeof(si);
- if(!CreateProcess(NULL, (LPTSTR)(LPCTSTR)lpCmdLine, NULL, NULL, FALSE,
- DEBUG_ONLY_THIS_PROCESS,
- NULL, NULL, &si, &pi)){
- printf("\n启动被调试程序失败.(%d)",GetLastError());
- return 0;
- }
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- /*DebugActiveProcess(6032);*/ //先启动WaitMessageBox将PID值更新并取消注释
- while (WaitForDebugEvent(&dbe,INFINITE)) //循环等待Debug事件结束
- {
- if(dbe.dwDebugEventCode == EXIT_PROCESS_DEBUG_EVENT)
- {
- break;
- }
- bResult = DealDebugEvent(&dbe,(FUNCINFO *)lpParam);
- if(bResult){
- ContinueDebugEvent(dbe.dwProcessId,dbe.dwThreadId,DBG_CONTINUE); //若Debug事件成功处理则继续执行
- }else{
- ContinueDebugEvent(dbe.dwProcessId,dbe.dwThreadId,DBG_EXCEPTION_NOT_HANDLED);
- }
- }
- // CloseHandle(pi.hThread);
- // CloseHandle(pi.hProcess);
- return 1;
- }
- ///////////////////////////////////////////////////////////
- int main(int argc,char * argv[]){
- DWORD dwTid;
- DWORD dwNewTid;
- HANDLE hNewThread[2];
- FUNCINFO fpInfo;
- //初始化函数信息结构体
- fpInfo.lpApiName = "MessageBoxA";
- fpInfo.fpParamList.push("HWND");
- fpInfo.fpParamList.push("LPCSTR");
- fpInfo.fpParamList.push("LPCSTR");
- fpInfo.fpParamList.push("UINT");
- fpInfo.lpReturnValue = "INT";
- InitMap(); //初始化字符映射表
- //启动调试线程和断点设置线程
- hNewThread[0] = CreateThread(NULL,0,DebugProc,(LPVOID)&fpInfo,NULL,&dwTid);
- if(hNewThread[0] == NULL){
- printf("\n启动调试线程失败.(%d)",GetLastError());
- return 0;
- }
- hNewThread[1] = CreateThread(NULL,0,SetBreakProc,NULL,NULL,&dwNewTid);
- WaitForMultipleObjects(2,hNewThread,TRUE,INFINITE);
- CloseHandle(hNewThread[0]);
- CloseHandle(hNewThread[1]);
- return 1;
- }
本文转hackfreer51CTO博客,原文链接:http://blog.51cto.com/pnig0s1992/782233,如需转载请自行联系原作者