| 
 | 
			
 
这个方法的原理就是: 
①首先在API头部写一个CC断点 
②中断的时候程序收到消息,并且读出参数 
 
需要注意的地方只有修正EIP寄存器,和读取参数的问题。 
因为API采用STDCALL的方式调用,所以参数是从右向左压进堆栈的。 
还有就是API的开头是 
mov edi,edi 
push ebp 
mov ebp,esp 
 
我们要注意,因为我们是在头部断下的,还没有执行push ebp,而执行了push ebp之后esp会减4,也就是说,我们在头部中断的时候要把esp-4才能拿ESP来读取参数! 
 
还要注意的就是,如何不执行API直接跳转到返回地址,一般ESP储存的地址指向的就是返回地址,所以我们只要把EIP修改就好,如果你要设置返回值,那么就修改EAX为返回值。(记得修正ESP) 
 
如何单步?这也是一个问题,我们可以在第一条指令中断之后,在第二条指令下CC断点,同时还原第一条指令,等到第二条指令触发中断事件时,我们再在第一条指令上下CC断点,再还原第二条指令,这就模拟了一次单步。 
 
我把代码贴出来,使用VC2010编译 
 
#include <stdio.h> 
#include <windows.h> 
 
#define SE_DEBUG_PRIVILEGE 20 
typedef  DWORD(WINAPI *PRtlAdjustPrivilege)   ///未文档化函数声明 
( 
ULONG    Privilege, 
BOOLEAN Enable, 
BOOLEAN CurrentThread, 
PBOOLEAN Enabled 
); 
 
void WINAPI AdjustPrivilege()         ///ntdll中的提权函数 
{ 
        BOOLEAN Enabled; 
        PRtlAdjustPrivilege RtlAdjustPrivilege = (PRtlAdjustPrivilege)GetProcAddress(LoadLibrary((LPCSTR)"ntdll.dll"), "RtlAdjustPrivilege"); 
        RtlAdjustPrivilege(SE_DEBUG_PRIVILEGE, TRUE, FALSE, &Enabled); 
} 
 
int main(void) 
{ 
    DWORD pid; 
    DWORD lpapi; 
    BYTE code[2]; 
    BYTE _code; 
    BYTE cc = 0xCC; 
    PDWORD p; 
    HANDLE hProcess; 
    HANDLE hThread; 
    HMODULE hMod; 
    int yes = TRUE; 
    DEBUG_EVENT dbg; 
    CONTEXT ct; 
 
    int wType; 
    char text[255]; 
    char caption[255]; 
    int hwin; 
    DWORD pt; 
 
    char ch; 
 
    AdjustPrivilege(); ///提升进程权限到DEBUG 
    printf("请输入要HOOK的进程ID:____\b\b\b\b"); 
    scanf("%d", &pid); ///获取要HOOK的进程的ID 
    hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid); 
    hMod = GetModuleHandle("user32.dll"); ///获取模块句柄 
    if (!hMod) 
        hMod = LoadLibrary("user32.dll"); ///如果没有获取到模块句柄,则加载模块 
    lpapi = (DWORD)GetProcAddress(hMod, "MessageBoxA"); ///取API地址 
    ReadProcessMemory(hProcess, (LPVOID)lpapi, code, 2, NULL); ///获取API头部两字节数据,即第一条指令 
    ReadProcessMemory(hProcess, (LPVOID)(lpapi + 2), &_code, 1, NULL); ///获取API第二条指令第一字节数据 
    WriteProcessMemory(hProcess, (LPVOID)lpapi, &cc, 1, NULL); 
    DebugActiveProcess(pid); ///开启调试会话 
    while (yes) 
    { 
        if(WaitForDebugEvent(&dbg, 20) == 0) ///如果当前还没有触发调试信息 
        { 
            Sleep(50); 
            continue; 
        } 
        if(dbg.dwDebugEventCode == EXCEPTION_DEBUG_EVENT) ///如果是调试事件 
        { 
            if(dbg.u.Exception.ExceptionRecord.ExceptionCode != EXCEPTION_BREAKPOINT) ///如果不是中断事件 
            { 
                ContinueDebugEvent(dbg.dwProcessId, dbg.dwThreadId, DBG_EXCEPTION_NOT_HANDLED); ///继续调试 
                continue; 
            } 
            if((DWORD)dbg.u.Exception.ExceptionRecord.ExceptionAddress == lpapi) 
            { 
                hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, dbg.dwThreadId); ///打开线程 
                ct.ContextFlags = CONTEXT_ALL; 
                SuspendThread(hThread); ///暂停线程,否则不可以读取线程寄存器信息 
                GetThreadContext(hThread, &ct); ///读取线程寄存器信息 
                printf("拦截到进程MessageBoxA调用!\n"); 
                ///这里为什么要-4?因为函数头部是push ebp,mov ebp,esp,而push了ebp之后,esp会-4,我们下CC断点的地方是函数头部 
                ///所以此时ESP还未-4,所以我们读取的时候要把ESP-4 
                ReadProcessMemory(hProcess, (LPVOID)(ct.Esp + 0x10), &hwin, 4, NULL); ///读取HWND参数 
                ReadProcessMemory(hProcess, (LPVOID)(ct.Esp + 0xC), &pt, 4, NULL); ///读取Text参数的指针 
                ReadProcessMemory(hProcess, (LPVOID)pt, text, 255, NULL); ///读取Text参数 
                ReadProcessMemory(hProcess, (LPVOID)(ct.Esp + 0x8), &pt, 4, NULL); ///读取Caption参数的指针 
                ReadProcessMemory(hProcess, (LPVOID)pt, caption, 255, NULL); ///读取Caption参数 
                ReadProcessMemory(hProcess, (LPVOID)(ct.Esp + 0x4), &wType, 4, NULL); ///读取wType参数 
                ReadProcessMemory(hProcess, (LPVOID)(ct.Esp), &pt, 4, NULL); ///读取返回地址 
                printf("hwnd:%d\nlpText:%s\nlpCaption:%s\nwType:%d\n", hwin, text, caption, wType); 
                printf("返回地址:%#x\n", pt); 
                printf("输入Y允许执行,输入N不允许执行,输入其他则退出:_\b"); 
                fflush(stdin); 
                scanf("%c", &ch); 
                if(ch == 'Y' || ch == 'y') 
                { 
                    ///允许执行,模拟OD单步事件 
                    WriteProcessMemory(hProcess, (LPVOID)(lpapi + 2), &cc, 1, NULL); ///在API的第二条指令下断点 
                    WriteProcessMemory(hProcess, (LPVOID)lpapi, code, 2, NULL); ///还原第一条指令 
                    ct.Eip--; ///修改EIP寄存器,使其-1,重新指向API头第一字节 
                    SetThreadContext(hThread, &ct); 
                    ResumeThread(hThread); 
                    CloseHandle(hThread); 
                } 
                else if(ch == 'N' || ch == 'n') 
                { 
                    ///不允许执行 
                    ct.Esp+= 0x14; ///修正堆栈 
                    ct.Eip = pt; ///修正EIP到返回地址 
                    SetThreadContext(hThread, &ct); 
                    ResumeThread(hThread); 
                    CloseHandle(hThread); 
                } 
                else 
                { 
                    ///退出 
                    ct.Eip--; 
                    SetThreadContext(hThread, &ct); 
                    WriteProcessMemory(hProcess, (LPVOID)lpapi, code, 2, NULL); ///还原API头部信息 
                    WriteProcessMemory(hProcess, (LPVOID)(lpapi + 2), &_code, 1, NULL); 
                    ResumeThread(hThread); 
                    CloseHandle(hThread); 
                    yes = FALSE; 
                } 
            } 
            else if((DWORD)dbg.u.Exception.ExceptionRecord.ExceptionAddress == (lpapi + 2)) ///如果是中断在第二条指令 
            { 
                hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, dbg.dwThreadId); ///打开线程 
                ct.ContextFlags = CONTEXT_ALL; 
                SuspendThread(hThread); ///暂停线程,否则不可以读取线程寄存器信息 
                GetThreadContext(hThread, &ct); ///读取线程寄存器信息 
                WriteProcessMemory(hProcess, (LPVOID)lpapi, &cc, 1, NULL); ///重新在API第一条指令上设置CC断点 
                WriteProcessMemory(hProcess, (LPVOID)(lpapi + 2), &_code, 1, NULL); ///还原第二条指令 
                ct.Eip--; ///修正EIP 
                SetThreadContext(hThread, &ct); 
                ResumeThread(hThread); 
                CloseHandle(hThread); 
            } 
 
 
 
            ContinueDebugEvent(dbg.dwProcessId, dbg.dwThreadId, DBG_CONTINUE); 
        } 
        ContinueDebugEvent(dbg.dwProcessId, dbg.dwThreadId, DBG_CONTINUE); 
    } 
    DebugActiveProcessStop(pid); 
    return 0; 
} 
 
 
 
 
 
 
 
 
 
 
 
 
代码下载: 
 
 
 
main.rar
(1.96 KB, 下载次数: 18)
 
 
 |   
 
评分
- 
|  参与人数 7 | HB +4 | 
THX +4 | 
收起
理由
 | 
 
| 
叁壹伍
 |  | 
 + 1 | 
 | 
 
| 
消逝的过去
 |  | 
 + 1 | 
 | 
 
| 
zxjzzh
 |  | 
 + 1 | 
[吾爱汇编论坛52HB.COM]-软件反汇编逆向分析,软件安全必不可少! | 
 
| 
禽大师
 |  + 1 | 
 | 
 | 
 
| 
agan8888
 |  + 1 | 
 | 
 | 
 
| 
a1453917518
 |  + 1 | 
 + 1 | 
[快捷评语] - 吃水不忘打井人,给个评分懂感恩! | 
 
| 
tianzhiya
 |  + 1 | 
 | 
吃水不忘打井人,给个评分懂感恩! | 
 
 
查看全部评分
 
 
 
 
 
 |