找回密码
 注册

QQ登录

只需一步,快速开始

智能终端设备维修查询系统注册会员邮箱认证须知!
查看: 2889|回复: 1

[VC函数例程] 监视其它进程中某一内存的数据的变化

[复制链接]
  • TA的每日心情

    2025-6-23 21:25
  • 签到天数: 126 天

    [LV.7]常住居民III

    admin 发表于 2010-9-28 21:01:05 | 显示全部楼层 |阅读模式

    欢迎您注册加入!这里有您将更精采!

    您需要 登录 才可以下载或查看,没有账号?注册

    ×
    怎么样才能得知其他进程中某一内存的内容发生了变化?有几个条件我想首先说明一下,在win32系统下想实时得到其他进程一段内存的内容变化是不可能的。
    唯一的可能是定时扫描。另外如果想要得知内核态内存的变化也是不太容易实现(姑且允许我这么我这么说,因为在方面我没有进行深入的调查)。
    还有CPU的要求我现在只是针对intel,因为手头没有AMD的CPU,所以就没有测试过。

    如果想要实时得到其他进程的内存内容的变化,有两种方案,其一是修改反汇编后的源程序,其二是debug源程序。
    对于第一种方案来说,工作量和汇编知识要求相对要高一点。那么第二种方案只需要一些win32 程序的debug技术就可以了,相对来说就比较容易实现。
    在这里我们采用第二种方案。

    intel cpu提供了一组调试寄存器可以用来帮助我们跟踪我们感兴趣的内存地址。下面我来详细的介绍一下这些寄存器的功能。
    1.jpg

    DR0-DR3是四个调试地址寄存器(debug adress register),其每个寄存器都包含跟四个断点状态有关的线性地址。
    地址。断点的状态由DR7来给出。
    不管有没有分页的情况,这四个寄存器都是有效的。
    DR4-DR5 保留。
    DR7 调试控制寄存器(debug control register)
            调试控制寄存器是用来设定debug condition。对应于DR0-DR3,DR7中相应的R/W0-R/W3指出了产生断点的条件。RW占据2bit。有一下四种组合。
            00 : 表示单条指令中断。(single step)
            01 : 表示只当数据被写入的时候中断。
            10 : 没有定义。
            11 : 表示当数据被读,或写入的时候中断。
    对应于DR0-DR3,DR7中相应的LEN0-LEN3指出了所要观测的数据长度。
            00: 表示一个字节。
            01:表示两个字节10:没有定义。
            11: 表示四个字节。如果RWn是0的话<指令断点>那么LENn也应该是0。
    DR7的低八位支持DR0-DR3哪个寄存器被激活。其中L表示局部激活,它的意思是当发生任务切换时CPU将自动重设Ln的值。
    其中G表示全局激活,它的意思是当发生任务切换时CPU不会自动重设Gn的值。
    DR6 调试状态寄存器(debug status register)调试状态寄存器的作用是用查询当前是何种调试状态。
            当CPU碰到一个激活的调试异常,CPU将B0-B3中的一个值设为1。
    BT的含义是: debug trap bit.当发生任务切换时,cpu负责在进入调试异常处理函数之前把这个标志位设为1。
    BS 是EFLAGS寄存器的TF标志位。
    BD: 当执行下一条指令前,如果上面的八个寄存器中一个发生了改变,CPU这个位设为1。
    以上就是调试寄存器的一些关键位的解释。下面我们来看看具体的代码是怎么实现的。
    Debug API 可以查看MSDN这里就不多解释了。
    函数的调用原型:
    int WatchAddrss(LPVOID address, BYTE len, LPSTR pszExe);
    为了测试的方便,我们可以在被测试程序中设一个全局变量,那么下次启动时它的地址就不会改变了。然后在测试程序中以一定时间间隔修改它的值。
            我们的调试程序把修改完的值实时的打印出来。好,现在我们就来看看
    int WatchAddrss(LPVOID address, BYTE len, LPSTR pszExe)的实现。这是一个简化的版本,大家可以扩充。
    int WatchMemory(DWORD address, BYTE len,LPSTR pszExe)
    {
            STARTUPINFO si;  
            PROCESS_INFORMATION pi;  
            ZeroMemory(&si,sizeof(si));  
            ZeroMemory(&si,sizeof(pi));  
            si.cb = sizeof(STARTUPINFO);  
            CreateProcess(pszExe,NULL,NULL,NULL,TRUE,DEBUG_PROCESS|NORMAL_PRIORITY_CLASS, NULL,NULL,&si,&pi);  
            DEBUG_EVENT DebugEv;                // debugging event information  
            DWORD dwContinueStatus = DBG_CONTINUE; // exception continuation  
            CONTEXT Regs;  
            Regs.ContextFlags=CONTEXT_FULL|CONTEXT_DEBUG_REGISTERS;  
            int DR0E = 1;         //enable Dr0   
            int LEBPME = 0x100;   //1 0000 0000 : locally enable Dr0   
            int RW = 0x30000;     //break when data read or write int WATCHLEN = 0;     //byte length to be watched.
            char *szNTDll = "ntdll";  
            char *szNTCont =  "NtContinue";
            DWORD NTContAddr = 0;  
            HMODULE ntdll;  
            DWORD febx=0;  
            DWORD dwBytesRead;  
            DWORD dwBytesWritten;  
            DWORD dwBuff;  
            DWORD dwBPCnt=0;  
            DWORD dwSSCnt=0;  
            DWORD value = 0;
            ResumeThread(pi.hThread);  
            switch(len) {
            case 2:  
                    WATCHLEN = 1 << 18;
                    break;
            case 4:  
                    WATCHLEN = (1 << 19) + (1 << 18);  
                    break;
            default:  
                    WATCHLEN = 0;  
                    break;
            }
            for(;;)
            {   
                    // Wait for debugging event to occur   
                    WaitForDebugEvent(&DebugEv, INFINITE);   
                    dwContinueStatus=DBG_EXCEPTION_NOT_HANDLED;   
                    if (DebugEv.dwDebugEventCode == EXCEPTION_DEBUG_EVENT)   
                    {   
                            if (DebugEv.u.Exception.ExceptionRecord.ExceptionCode == EXCEPTION_BREAKPOINT)   
                            {     
                                    dwContinueStatus=DBG_CONTINUE;     
                                    dwBPCnt++;     
                                    if (dwBPCnt == 1)  
                                    {  
                                            GetThreadContext(pi.hThread,&Regs);  
                                            Regs.Dr7= LEBPME + DR0E;     
                                            ntdll=GetModuleHandle(szNTDll);  
                                            if (ntdll==NULL) //这里的处理是因为第一次中断是由ntdll引起的,为什么要这么做,MS没给解释   
                                                    return 0;   
                                            NTContAddr=(DWORD)GetProcAddress(ntdll, szNTCont);
                                            Regs.Dr0=NTContAddr;     
                                            SetThreadContext(pi.hThread, &Regs);   
                                    }   
                            }   
                            else if (DebugEv.u.Exception.ExceptionRecord.ExceptionCode == EXCEPTION_SINGLE_STEP)   
                            {   
                                    dwContinueStatus = DBG_CONTINUE;   
                                    dwSSCnt++;  
                                    if (dwSSCnt == 1)  
                                    {     
                                            GetThreadContext(pi.hThread,&Regs);   
                                            febx = Regs.Esp;     
                                            febx += 4; //这里加4的是为了获得CONTEXT的地址,原理可以参考BugSlayer专栏,MSDN上有。
                                            ReadProcessMemory(pi.hProcess,(void*)febx,&dwBuff,4,&dwBytesRead);  
                                            ReadProcessMemory(pi.hProcess,(void*)dwBuff,(void*)&Regs,sizeof(CONTEXT), &dwBytesRead);     
                                            Regs.Dr0 = address;             //关联要观测的地址   
                                            Regs.Dr7 = RW + LEBPME + DR0E; //设置断点发生的条件。   
                                            WriteProcessMemory(pi.hProcess,(void*)dwBuff,(void*)&Regs, sizeof(CONTEXT),&dwBytesWritten);     
                                            SetThreadContext(pi.hThread,&Regs);         
                                    }   
                                    else   
                                    {      
                                            /*     //如果想要清除断点的话可以使用下面注释的代码  
                                            GetThreadContext(pi.hThread,&Regs);   
                                            Regs.Dr0 = 0;     
                                            Regs.Dr7 = 0;   
                                            SetThreadContext(pi.hThread,&Regs);  
                                            */     //获取要检测内存的内容并且打印出来。  
                                            BOOL ret = ReadProcessMemory(pi.hProcess,(void*)address,&value,len,&dwBytesRead);   
                                            printf("ret = %d\t%d\n",ret,value);   
                                    }  
                            }  
                    }  
                    else if (DebugEv.dwDebugEventCode == EXIT_PROCESS_DEBUG_EVENT)  
                    {   
                            return 0;   
                    }   
                            ContinueDebugEvent(DebugEv.dwProcessId,DebugEv.dwThreadId, dwContinueStatus);
                    }  
                    return 0;
            }

            调用例程:
    int main(int argc, char* argv[])
    {   
            WatchMemory(0x4168fc,4,"TobeDebug.exe");  
            return 1;
    }
    写在后面:  要获取其他程序全局变量的RVA可以静态分析它的PE文件。下次准备写这方面的东西。(^_^,有很多人写过)
  • TA的每日心情

    2012-10-18 09:20
  • 签到天数: 4 天

    [LV.2]偶尔看看I

    wangzewu 发表于 2010-10-30 11:02:17 | 显示全部楼层
    我是初学者,没看懂.希望早日....
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 注册

    本版积分规则

    免责声明

    本站中所有被研究的素材与信息全部来源于互联网,版权争议与本站无关。本站所发布的任何软件编程开发或软件的逆向分析文章、逆向分析视频、补丁、注册机和注册信息,仅限用于学习和研究软件安全的目的。全体用户必须在下载后的24个小时之内,从您的电脑中彻底删除上述内容。学习编程开发技术或逆向分析技术是为了更好的完善软件可能存在的不安全因素,提升软件安全意识。所以您如果喜欢某程序,请购买注册正版软件,获得正版优质服务!不得将上述内容私自传播、销售或者用于商业用途!否则,一切后果请用户自负!

    QQ|Archiver|手机版|小黑屋|联系我们|宝峰科技 ( 滇ICP备09007156号-2|53050202000040 )

    Copyright © 2001-2023 Discuz! Team. GMT+8, 2026-1-27 01:38 , Processed in 0.095007 second(s), 14 queries , File On Powered by Discuz! X3.59© 2001-2025 Discuz! Team.

    快速回复 返回顶部 返回列表