Если я правильно понимаю, ваш главный вопрос о том, как имитировать вывод из шестнадцатеричных редакторов.
Это можно разбить на 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;
}
Вам нужно будет проделать немного больше работы, чтобы проверить ошибки и сделать все хорошо, но, надеюсь, это даст вам хорошее представление о том, что можно сделать.