zoukankan      html  css  js  c++  java
  • hook技术--调试法hook

    简介:

    这种方法的具体hook实施比较灵活, 这里采用对目标API入口地址下断点,当调用时即
    断下,截获参数内容后进行修改.这时可以通过修改eip的值让其跳转到任意地址.
    这种方式没有文件等其他操作,它就相当于实现了一个最简单的调试器,而对被调试进程
    进行修改内存是很正常的事件,因此被查杀可能性低
    下面是测试将notepad的内容在保存文件时小写全部转为大写
    
    
    DWORD debugHook(DWORD pid)
    {
        HANDLE hProcess;//目标进程句柄
        HANDLE hThread;//线程句柄
        DEBUG_EVENT de; //调试事件
        CONTEXT thread_context;//线程上下文,包括各个寄存器值
        char* apiBase = 0;//API基址
                          //WriteFile的2个重要参数,要写入的内容和大小
        char *buffer;
        DWORD nNumberOfBytesToWrite;
        DWORD bufferBase;
        BYTE fakeCode = 0xcc;//int 3指令
        BYTE trueCode;        //保存原来的指令
        DWORD ret;
        if (!DebugActiveProcess(pid))
        {
            return GetLastError();
        }
    
        while (WaitForDebugEvent(&de, INFINITE))
        {
            switch (de.dwDebugEventCode)
            {
            case EXIT_PROCESS_DEBUG_EVENT:
                return 1;
            case CREATE_PROCESS_DEBUG_EVENT:
                //目标程序创建进程, 附加到调试器,都会发送该调试事件
                //获取进程句柄, 通过CreateProcessInfo 成员能获取更多信息
                hProcess = de.u.CreateProcessInfo.hProcess;
                hThread = de.u.CreateProcessInfo.hThread;
                //获取目标api地址,由于kernel32.dll加载到任何进程中基址都是一样的.所以直接获取本进程的也是一样的
                apiBase = (char*)GetProcAddress(GetModuleHandleA("kernel32.dll"), "WriteFile");
                //备份原来的指令
                ReadProcessMemory(hProcess, apiBase, &trueCode, sizeof(BYTE), &ret);
                //写入int 3指令
                WriteProcessMemory(hProcess, apiBase, &fakeCode, sizeof(BYTE), &ret);
    
                ContinueDebugEvent(pid, de.dwThreadId, DBG_CONTINUE);
                break;
            case EXCEPTION_DEBUG_EVENT:
                //异常事件,程序发生异常时将发送该调试事件
                //只关心我们设下的断点异常,其他一律不处理
                if (de.u.Exception.ExceptionRecord.ExceptionCode == EXCEPTION_BREAKPOINT)
                {
                    if ((char*)de.u.Exception.ExceptionRecord.ExceptionAddress == apiBase)
                    {
                        //恢复hook
                        WriteProcessMemory(hProcess, apiBase, &trueCode, sizeof(BYTE), &ret);
                        //获取上下文
                        thread_context.ContextFlags = CONTEXT_CONTROL;
                        GetThreadContext(hThread, &thread_context);
                        //恢复正常执行流程,即将eip调整到函数入口处
                        thread_context.Eip--;
                        SetThreadContext(hThread, &thread_context);
                        //获取WriteFile的参数lpBuffer和nNumberOfBytesToWrite
                        ReadProcessMemory(hProcess, (LPCVOID)(thread_context.Esp + 0xc), &nNumberOfBytesToWrite, 4, &ret);
                        buffer = (char*)malloc(sizeof(char)*nNumberOfBytesToWrite);
                        ReadProcessMemory(hProcess, (LPVOID)(thread_context.Esp + 0x8), &bufferBase, sizeof(DWORD), NULL);
                        ReadProcessMemory(hProcess, (LPCVOID)bufferBase, (LPVOID)buffer, nNumberOfBytesToWrite, &ret);
    
                        //转为大写
                        printf("
    原始字符:
    ");
                        for (DWORD i = 0; i < nNumberOfBytesToWrite; i++)
                        {
                            printf("%c", buffer[i]);
                            if (buffer[i] <= 0x7a && buffer[i] >= 0x61)
                            {
    
                                buffer[i] -= 0x20;
                            }
                        }
                        WriteProcessMemory(hProcess, (LPVOID)(bufferBase), (LPCVOID)buffer, nNumberOfBytesToWrite, &ret);
                        free(buffer);
                        //继续运行程序
                        ContinueDebugEvent(pid, de.dwThreadId, DBG_CONTINUE);
                        Sleep(0); //释放本线程时间片
    
                        //重新勾住
                        WriteProcessMemory(hProcess, apiBase, &fakeCode, sizeof(byte), &ret);
    
                    }
                }
    
                ContinueDebugEvent(pid, de.dwThreadId, DBG_CONTINUE);
                break;
            default:
                ContinueDebugEvent(pid, de.dwThreadId, DBG_CONTINUE);
                break;
            }
    
        }
    }
  • 相关阅读:
    关于WebBrowser(浏览器)控件的调用
    SQLite3.0 beta & ADO.NET Data Provider for SQLite 0.18发布了!
    特别推荐:纯VB.NET代码直接生成Excel文件(不需要Excel)
    关于ASP.NET中独立页面设置身份认证等问题
    关于实时网站资源监控
    关于SQLite.org网站给黑...
    .NET中调用COM的一些问题
    关于数据库空字段和DEFAULT值等问题
    关于软件保护的矛与盾
    (转贴) 微软面试100题——要想成为盖茨就来试试!
  • 原文地址:https://www.cnblogs.com/freesec/p/6555975.html
Copyright © 2011-2022 走看看