如何按指定格式输出进程内存数据并解决大内存读取限制
问题解答
首先先贴出你的代码方便参考:
void update_memblock(MEMBLOCK *mb) { static unsigned char tempbuf[128 * 1024]; SIZE_T bytes_left; SIZE_T total_read; SIZE_T bytes_to_read; SIZE_T bytes_read; bytes_left = mb->size; total_read = 0; while (bytes_left) { bytes_to_read = (bytes_left > sizeof(tempbuf)) ? sizeof(tempbuf) : bytes_left; ReadProcessMemory(mb->hProc, mb->addr + total_read, tempbuf, bytes_to_read, &bytes_read); if (bytes_read != bytes_to_read) break; memcpy(mb->buffer + total_read, tempbuf, bytes_read); bytes_left -= bytes_read; total_read += bytes_read; } mb->size = total_read; }
一、实现内存数据的格式化输出(类似图片中的内存查看器格式)
你需要写一个专门的格式化函数,把字节数据转换成「地址+十六进制+ASCII」的标准内存dump格式。这里给你一个示例实现:
#include <stdio.h> #include <ctype.h> #include <stdint.h> void print_memory_dump(const unsigned char *data, SIZE_T size, uintptr_t base_addr) { // 遍历每一行(每行16字节) for (SIZE_T i = 0; i < size; i += 16) { // 打印当前行的起始地址(8位十六进制) printf("%08X ", base_addr + i); // 打印十六进制部分:16个字节,每8个字节加一个空格分隔 for (SIZE_T j = 0; j < 16; j++) { if (i + j < size) { printf("%02X ", data[i + j]); } else { printf(" "); // 不足16字节时补空格对齐 } if (j == 7) { printf(" "); // 8字节后加分隔空格 } } // 打印ASCII部分:可见字符直接输出,不可见字符用.代替 printf(" "); for (SIZE_T j = 0; j < 16; j++) { if (i + j < size) { unsigned char c = data[i + j]; printf("%c", isprint((unsigned char)c) ? c : '.'); } else { printf(" "); } } printf("\n"); } }
使用方法很简单:在你读取完tempbuf的bytes_read字节后,调用这个函数即可:
// 比如在memcpy之后添加 print_memory_dump(tempbuf, bytes_read, mb->addr + total_read);
二、突破tempbuf大小限制读取更多数据
你的代码其实已经具备循环读取大内存的逻辑了——每次用tempbuf读取一部分,然后复制到mb->buffer,直到所有数据读完。出现「只能读取tempbuf大小数据」的问题,大概率是这两个原因之一:
1. 确保mb->buffer有足够的存储空间
在调用update_memblock之前,你必须确保mb->buffer已经预先分配了至少mb->size大小的内存(比如用malloc(mb->size))。如果mb->buffer太小,后续的memcpy会导致缓冲区溢出,数据无法正确存储。
2. 优化读取逻辑(可选:用动态缓冲区代替静态数组)
如果想减少循环次数,或者需要更大的单次读取缓冲区,可以把静态的tempbuf改成动态分配的:
void update_memblock(MEMBLOCK *mb) { SIZE_T bytes_left; SIZE_T total_read; SIZE_T bytes_to_read; SIZE_T bytes_read; // 动态分配缓冲区,这里设为1MB,你可以根据需求调整 SIZE_T tempbuf_size = 1024 * 1024; unsigned char *tempbuf = malloc(tempbuf_size); if (!tempbuf) { // 内存分配失败,返回已读取的字节数 mb->size = 0; return; } bytes_left = mb->size; total_read = 0; while (bytes_left) { bytes_to_read = (bytes_left > tempbuf_size) ? tempbuf_size : bytes_left; // 先检查ReadProcessMemory的返回值,更健壮 if (!ReadProcessMemory(mb->hProc, mb->addr + total_read, tempbuf, bytes_to_read, &bytes_read)) { break; // 读取失败,退出循环 } if (bytes_read == 0) { break; // 未读取到任何数据 } memcpy(mb->buffer + total_read, tempbuf, bytes_read); bytes_left -= bytes_read; total_read += bytes_read; } mb->size = total_read; free(tempbuf); // 释放动态分配的内存 }
另外,原代码中只检查bytes_read != bytes_to_read就退出,其实不够严谨——有时候ReadProcessMemory会成功但返回的字节数小于请求值(比如读取到进程内存的边界),这种情况可以继续尝试读取剩余数据,而不是直接退出。你可以把原有的if (bytes_read != bytes_to_read) break;改成:
if (bytes_read == 0) break; // 只有当没读到数据时才退出
这样就能尽可能读取所有可访问的内存数据了。
内容的提问来源于stack exchange,提问作者Total Anime Immersion
相关产品推荐
相关产品推荐

