记录黑客技术中优秀的内容, 传播黑客文化,分享黑客技术精华

使用Debug Api编写ApiMonitor

2013-01-20 01:40

使用编写调试器的一组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;  
} 

知识来源: pnigos.com/archives/96
想收藏或者和大家分享这篇好文章→复制链接地址

“使用Debug Api编写ApiMonitor”共有0条留言

发表评论

姓名:

邮箱:

网址:

验证码:

公告

九层之台,起于累土;黑客之术,始于阅读

推广

工具

标签云