Попытка распечатать полезные данные из памяти - PullRequest
0 голосов
/ 10 мая 2018
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;
}

Это текущий код, который у меня есть, я сначала читаю память другого процесса, используя ReadProcessMemory. Теперь у меня есть временные данные, хранящиеся в tempbuf. Я могу вывести данные из tempbuf в шестнадцатеричной форме. Но я планировал отобразить его так, как показано на рисунке, и еще одна сложность, с которой я здесь сталкиваюсь, заключается в том, что если bytes_left> sizeof (tempbuf), я читаю только достаточно данных, эквивалентных размеру tempbuf. Как мне прочитать больше данных, так как определенный мной массив может поддерживать только столько данных?

in_this_format

Ответы [ 2 ]

0 голосов
/ 17 мая 2018

Если я правильно понимаю, ваш главный вопрос о том, как имитировать вывод из шестнадцатеричных редакторов.

Это можно разбить на 3 части:

  1. Печать адреса
  2. Печать шестнадцатеричного значения каждого байта
  3. Печать значения ASCII для каждого байта

Печать адреса в шестнадцатеричном формате легко. Мы можем использовать %p, чтобы напечатать адрес указателя следующим образом:

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

Далее вы можете напечатать шестнадцатеричное значение байта, используя %02x на символе (1 байт). 02 задает ширину поля с добавлением нуля, равное 2. В этом случае 0 печатается как 00, чтобы все выровнялось и выглядело красиво.

printf("%02x", mem[0]);
// output: 0A

Наконец, печать ASCII является самой легкой из всех ... почти. Мы можем использовать %c для печати байта для некоторых значений ASCII, но мы не хотим печатать такие вещи, как \n или \t. Чтобы решить эту проблему, мы можем ограничить использование %c областью символа / символа ASCII таблицы и печатью . для всего остального.

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

Теперь нам просто нужно объединить все это вместе. Вы можете решить, сколько байтов вы хотите отобразить в каждой строке, и напечатать «[адрес] [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");
     }
 }

Пример вывода:

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

Что касается второй части вашего вопроса, если вы не можете увеличить размер 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;
}

Вам нужно будет проделать немного больше работы, чтобы проверить ошибки и сделать все хорошо, но, надеюсь, это даст вам хорошее представление о том, что можно сделать.

0 голосов
/ 13 мая 2018

Нет способа сохранить больше данных, чем у вас выделено место. Если вам нужно хранить больше данных, вам нужно где-то выделить больше места (больше оперативной памяти, файл на диске и т. Д.). Сжатие позволит вам хранить немного больше данных в выделенном пространстве, но вы не собираетесь получать столько же. Для практически неограниченного хранилища вам понадобится запись на диск.

В качестве альтернативы, если вам просто нужно отобразить один раз, а затем забыть, прочитать в 16 байтах, отобразить строку и затем прочитать следующие 16 байтов в той же памяти.

...