试图从内存中打印出有用的数据

Tot*_*ion 2 c memory windows hexdump

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;
}
Run Code Online (Sandbox Code Playgroud)

这是我当前的代码,我最初正在阅读另一个进程'内存使用ReadProcessMemory.现在我存储了临时数据tempbuf.我能够以tempbuf十六进制形式输出数据.但是我打算如图所示显示它,另外我在这里遇到的另一个复杂因素是bytes_left> sizeof(tempbuf)我只读取相当于tempbuf大小的足够数据.如何读取更多数据,因为我定义的数组只能支持尽可能多的数据?

in_this_format

Inc*_*tic 5

如果我理解正确,你的主要问题是如何模仿十六进制编辑器的输出.

这可以分为3个部分:

  1. 打印地址
  2. 打印每个字节的十六进制值
  3. 打印每个字节的ASCII值

以十六进制打印地址很容易.我们可以%p用来打印像这样的指针的地址:

char* mem = malloc(99);
printf("%p\n", (void*)mem);
// output: 0xc17080
Run Code Online (Sandbox Code Playgroud)

接下来,您可以使用%02xchar(1个字节)打印字节的十六进制值.该02规定的2零填充字段宽度在这种情况下,它只是为了让0打印为00使事情排队,看起来很漂亮.

printf("%02x", mem[0]);
// output: 0A
Run Code Online (Sandbox Code Playgroud)

最后,打印ASCII是最简单的......差不多.我们可以%c用来打印某些ASCII值的字节,但是我们不想打印像\n或者这样的东西\t.为了解决这个问题,我们可以限制对ASCII表%c的字符/符号区域的使用,并打印其他所有内容..

char c = mem[0];
if ( ' ' <= c && c <= '~' ) {
     printf("%c", c);
}
else {
     printf(".");
}
//output: .
Run Code Online (Sandbox Code Playgroud)

现在我们只需要将它们组合在一起.您可以决定每行要显示的字节数,并打印"[地址] [n十六进制字节] [n ascii字节]"并重复,直到您完成整个存储区域.我在下面给出了一个示例函数,你可以在这里自己运行它.

void display_mem(void* mem, int mem_size, int line_len) {
   /*
        mem         - pointer to beggining of memory region to be printed
        mem_size    - number of bytes mem points to
        line_len    - number of bytyes to display per line
   */

    unsigned char* data = mem;
    int full_lines = mem_size / line_len;
    unsigned char* addr = mem;

    for (int linno = 0; linno < full_lines; linno++) {
        // Print Address
        printf("0x%x\t", addr);

        // Print Hex
        for (int i = 0; i < line_len; i++) {
            printf(" %02x", data[linno*line_len + i]);
        }
        printf("\t");

        // Print Ascii
        for (int i = 0; i < line_len; i++) {
            char c = data[linno*line_len + i];
            if ( 32 < c && c < 125) {
                printf(" %c", c);
            }
            else {
                printf(" .");
            }
        }
        printf("\n");

        // Incremement addr by number of bytes printed
        addr += line_len;
    }

    // Print any remaining bytes that couldn't make a full line
    int remaining = mem_size % line_len;
    if (remaining > 0) {
        // Print Address
        printf("0x%x\t", addr);

        // Print Hex
        for (int i = 0; i < remaining; i++) {
            printf(" %02x", data[line_len*full_lines + i]);
        }
        for (int i = 0; i < line_len - remaining; i++) {
            printf("  ");
        }
        printf("\t");

        // Print Hex
        for (int i = 0; i < remaining; i++) {
            char c = data[line_len*full_lines + i];
            if ( 32 < c && c < 125) {
                printf(" %c", c);
            }
            else {
                printf(" .");
            }
        }
        printf("\n");
     }
 }
Run Code Online (Sandbox Code Playgroud)

样本输出:

0x1e79010        74 65 73 74 79 2a 6e    t e s t y * n
0x1e79017        0c 3e 24 45 5e 33 27    . > $ E ^ 3 '
0x1e7901e        18 51 09 2d 76 7e 4a    . Q . - v . J
0x1e79025        12 53 0f 6e 0b 1a 6d    . S . n . . m
0x1e7902c        31 6e 03 2b 01 2f 2c    1 n . + . / ,
0x1e79033        72 59 1c 76 18 38 3c    r Y . v . 8 <
0x1e7903a        6e 6b 5b 00 36 64 25    n k [ . 6 d %
0x1e79041        2d 5c 6f 38 30 00 27    - \ o 8 0 . '
0x1e79048        33 12 15 5c 01 18 09    3 . . \ . . .
0x1e7904f        02 40 2d 6c 1a 41 63    . @ - l . A c
0x1e79056        2b 72 18 1a 5e 74 12    + r . . ^ t .
0x1e7905d        0d 51 38 33 26 28 6b    . Q 8 3 & ( k
0x1e79064        56 20 0b 0b 32 20 67    V . . . 2 . g
0x1e7906b        34 30 68 2e 70 0f 1c    4 0 h . p . .
0x1e79072        04 50                   . P
Run Code Online (Sandbox Code Playgroud)

至于你问题的第二部分,如果你不能增加当时的大小,tempbuf你就会在任何时候处理这​​段内存.

但是,如果您要执行的只是如上所述显示内存,则可以以块的形式显示每个内存部分.你可以获得一大块内存,显示它,然后获得一个新的块,显示新的块,重复.

有点像

while (bytes_left) {
    ReadProcessMemory(mb->hProc, mb->addr + total_read, tempbuf, bytes_to_read, &bytes_read);
    // Get new chunk
    memcpy(mb->buffer + total_read, tempbuf, bytes_read);

    // Display chunk
    display_mem(tempbuf, bytes_read);

    bytes_left -= bytes_read;
}
Run Code Online (Sandbox Code Playgroud)

您需要做更多的工作来检查错误并使一切看起来不错,但希望能让您对可以做的事情有所了解.