首页
社区
课程
招聘
[旧帖] [求助]使用调试API时,为何在写入INT3机器码时无法写入 0.00雪花
发表于: 2011-12-4 10:36 1128

[旧帖] [求助]使用调试API时,为何在写入INT3机器码时无法写入 0.00雪花

2011-12-4 10:36
1128
我用C来按罗云斌书上的代码重写,调试其书上的提的Test.exe
当现在为CREATE_PROCESS_DEBUG_EVENT时,则写入INT 3中断,
但在WriteProcessMemory无法把其写入,查看其ErrorCode为0x12b
ERROR_PARTIAL_COPY

我在 WriteProcessMemory前加上
VirtualProtectEx(ProcessInfo.hProcess, pBreak_point1, 1, PAGE_READWRITE, PAGE_READONLY);
也不行
而且VirtualProtectEx也返回了0。

请问是什么原因呢?要怎样才能写入INT 3?

下面列出代码

#include<windows.h>
#include<process.h>
#include "resource.h"

PROCESS_INFORMATION ProcessInfo;//进程信息结构
STARTUPINFO         startupInfo;//指定新进程的主窗口特性结构
DEBUG_EVENT         debugEvent;//调试事件结构
//汇编中要加上align dword将它定义为双字对齐
CONTEXT             context;//存储的是寄存器状态,参考老罗P489

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow )
{
        BOOL        processSuccess, processWrite, processChange;
        //WORD        infoBuffer;
        DWORD       patch = 0x9090;
        DWORD       oldByte = 0x60;//入口处的原数据
        DWORD       int3 = 0xCC; //int 3中断
        DWORD                lastErrorCode;
        DWORD       patch_position = 0x00401004;//被修改的地址
        DWORD       break_point1 = 0x00405120;//第一个断点
        DWORD       break_point2 = 0x00401000;//第二个断点
        LPVOID      pBreak_point1 = (LPVOID)break_point1;
        LPVOID      pBreak_point2 = (LPVOID)break_point2;
        LPVOID      pInt3 = (LPVOID)int3;
        LPVOID                pOldByte = (LPVOID)oldByte;
        LPVOID                pPatch_position = (LPVOID)patch_position;
        LPVOID                pPatch = (LPVOID)patch;
   
                GetStartupInfo(&startupInfo);//返回进程在启动时被指定的 STARTUPINFO 结构
        //创建新进程和它的主线程,成功返回非零值
        processSuccess = CreateProcess("Test.exe", NULL, NULL, NULL, 0, DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS,
                NULL, NULL, &startupInfo, &ProcessInfo);

                if(!processSuccess)
                {
                        MessageBox(NULL, TEXT("无法装载文件!"), NULL, MB_OK | MB_ICONSTOP);
                        ExitProcess(0);
                }
        //调试进程
        while(TRUE)
        {
                WaitForDebugEvent(&debugEvent, INFINITE);//获取调试事件
                if(debugEvent.dwDebugEventCode == EXIT_PROCESS_DEBUG_EVENT)
                {//事件代码为进程退出则退出循环
                        break;
                }
                //如果进程开始,则将入口地址处的代码改为 int 3 断点中断
                if(debugEvent.dwDebugEventCode == CREATE_PROCESS_DEBUG_EVENT)
                {//写入INT 3中断机器码,使程序异常中断
                                        processChange = VirtualProtectEx(ProcessInfo.hProcess, pBreak_point1, 1, PAGE_READWRITE, PAGE_READONLY);
                    processWrite = WriteProcessMemory(ProcessInfo.hProcess, pBreak_point1, pInt3, 1, NULL);
                    lastErrorCode = GetLastError();//0x12b ERROR_PARTIAL_COPY
                                                //Only part of a ReadProcessMemory or WriteProcessMemory request was completed.
                }
                else if(debugEvent.dwDebugEventCode == EXCEPTION_DEBUG_EVENT)
                {//如果发生断点中断,则恢复断点处代码并设置单步中断
                        if(debugEvent.u.Exception.ExceptionRecord.ExceptionCode == EXCEPTION_BREAKPOINT)
                        {
                               context.ContextFlags = CONTEXT_FULL;//访问全部寄存器
                               GetThreadContext(ProcessInfo.hThread, &context);//把当前目标线程的环境返回CONTEXT结构,即取得当前寄存器值
                               if(context.Eip == break_point1 + 1)
                               {
                                                                   context.Eip -= 1;//如EIP指针已移到断点下句则返回断点处
                                                                   WriteProcessMemory(ProcessInfo.hProcess, pBreak_point1, pOldByte, 1, NULL);//恢复断点处原来的指令
                                                                   context.EFlags |= 0x100;//将单步标志置一,以后每执行一条指令会发生单步中断回到调试器中
                                                                   SetThreadContext(ProcessInfo.hThread, &context);//将线程环境设置回去
                               }
                        }
                                                else if(debugEvent.u.Exception.ExceptionRecord.ExceptionCode == EXCEPTION_SINGLE_STEP)//单步调试
                                                {
                                                        //如果单步中断到了指定位置,则进行内存补丁
                                                        context.ContextFlags = CONTEXT_FULL;//访问全部寄存器
                                                        GetThreadContext(ProcessInfo.hThread, &context);//把当前目标线程的环境返回CONTEXT结构,即取得当前寄存器值
                                                        if(context.Eip == break_point2)
                                                        {//找到程序入口处,进行补丁
                                                                WriteProcessMemory(ProcessInfo.hProcess, pPatch_position, &pPatch, sizeof(patch), NULL);
                                                                break;
                                                        }
                                                        else
                                                        {
                                                                context.EFlags |= 0x100;//将单步标志置一,以后每执行一条指令会发生单步中断回到调试器中
                                                                SetThreadContext(ProcessInfo.hThread, &context);//将线程环境设置回去
                                                        }
                                                }
                }
                                ContinueDebugEvent(debugEvent.dwProcessId, debugEvent.dwThreadId, DBG_CONTINUE);//恢复被调试进程的运行,此两ID为发生调试事件的进程线程ID
        }
                CloseHandle(ProcessInfo.hProcess);//关闭进程句柄
                CloseHandle(ProcessInfo.hThread);//关闭线程句柄
                ExitProcess(0);
}

[招生]科锐逆向工程师培训(2025年3月11日实地,远程教学同时开班, 第52期)!

收藏
免费
支持
分享
最新回复 (1)
雪    币: 1
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
你好 我都没有看明白啊
2011-12-4 10:46
0
游客
登录 | 注册 方可回帖
返回

账号登录
验证码登录

忘记密码?
没有账号?立即免费注册