运行时进程内存修补以恢复状态

Luc*_*uca 8 c++ memory patch process

我正在寻找一种存储过程存储器的方法,并在以后的某些条件下恢复它.

...

其实我已经读过有关它的问题......这似乎是一个很大的挑战!

因此,让我们分析一下:应用程序是分布式应用程序,但许多进程都是无状态的(请求将其状态发送到集中式服务器).进程使用网络连接和共享内存与其他进程通信.

中央服务器应通过转储其进程内存来保存其状态,该进程内存应在稍后的某些条件下恢复.(1)

我知道ReadProcessMemoryWriteProcessMemory函数,它们允许进程读取自身并覆盖已经分配的内存,不是吗?所以,我需要的是我开始读/写的地址,以及读/写的字节数.那么...... 什么地址?我读过的很多代码都使用VirtualAlloc返回的地址,但我不知道这对我是否有用.

我假设进程可执行段没有改变,所以它们不需要红色/写入.在恢复时,我还可以假设当主线程读取内存时,所有进程线程都处于相同的执行位置.

它仍然是堆栈内存和堆内存,它们是我感兴趣的内存段.

可能吗?

(1)问我为什么要这样做是完全合法的.原因是...像往常一样复杂.但是,假设应用程序具有非常复杂的状态,则需要过于复杂的状态保存算法.另一个替代方案(在分析主题中)是记录器/重放机制的实现,其能够再现已经对修改状态做出贡献的每个事件.


我想起了malloc&co.钩.所以我可以跟踪进程分配的内存.但实际上我注意到了_CrtMemState结构,但我不知道它是否对我有用.

Jer*_*fin 8

ReadProcessMemory用于读取另一个进程的内存.在进程内部,它是不必要的 - 您可以在同一进程中取消引用指向读取内存的指针.

要查找进程中的内存块,可以使用VirtualQuery.每个块都将被标记为状态,类型,大小等.这是我几年前写的一些代码,用于指定进程的阻止列表(使用VirtualQueryEx).您使用的方式VirtualQuery几乎相同,只是您不必指定进程,因为它总是遍历运行的进程.

#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>

unsigned long usage;

void show_modules(HANDLE process) {

    unsigned char *p = NULL;
    MEMORY_BASIC_INFORMATION info;

    for ( p = NULL;
        VirtualQueryEx(process, p, &info, sizeof(info)) == sizeof(info);
        p += info.RegionSize ) 
    {
        printf("%#10.10x (%6uK)\t", info.BaseAddress, info.RegionSize/1024);

        switch (info.State) {
        case MEM_COMMIT:
            printf("Committed");
            break;
        case MEM_RESERVE:
            printf("Reserved");
            break;
        case MEM_FREE:
            printf("Free");
            break;
        }
        printf("\t");
        switch (info.Type) {
        case MEM_IMAGE:
            printf("Code Module");
            break;
        case MEM_MAPPED:
            printf("Mapped     ");
            break;
        case MEM_PRIVATE:
            printf("Private    ");
        }
        printf("\t");

        if ((info.State == MEM_COMMIT) && (info.Type == MEM_PRIVATE))
            usage +=info.RegionSize;

        int guard = 0, nocache = 0;

        if ( info.AllocationProtect & PAGE_NOCACHE)
            nocache = 1;
        if ( info.AllocationProtect & PAGE_GUARD )
            guard = 1;

        info.AllocationProtect &= ~(PAGE_GUARD | PAGE_NOCACHE);

        switch (info.AllocationProtect) {
        case PAGE_READONLY:
            printf("Read Only");
            break;
        case PAGE_READWRITE:
            printf("Read/Write");
            break;
        case PAGE_WRITECOPY:
            printf("Copy on Write");
            break;
        case PAGE_EXECUTE:
            printf("Execute only");
            break;
        case PAGE_EXECUTE_READ:
            printf("Execute/Read");
            break;
        case PAGE_EXECUTE_READWRITE:
            printf("Execute/Read/Write");
            break;
        case PAGE_EXECUTE_WRITECOPY:
            printf("COW Executable");
            break;
        }

        if (guard)
            printf("\tguard page");
        if (nocache)
            printf("\tnon-cachable");
        printf("\n");
    }
}

int main(int argc, char **argv) {

    int pid;

    if (argc != 2) {
        fprintf(stderr, "Usage: %s <process ID>", argv[0]);
        return 1;
    }

    sscanf(argv[1], "%i", &pid);

    HANDLE process = OpenProcess( 
        PROCESS_VM_READ | PROCESS_QUERY_INFORMATION, 
        false,
        pid);

    show_modules(process);
    printf("Total memory used: %luKB\n", usage/1024);
    return 0;
}        
Run Code Online (Sandbox Code Playgroud)