Рассмотрим следующий код:
#include <stdio.h>
#include <inttypes.h>
#include <Windows.h>
int f(int x)
{
return x+1;
}
// using vs 2019 debug|x86
int main()
{
// visual studio's creates a label for f, which eventually jumps to it's implmentation.
// the jump instruction is E9, then an offset to the implementation.
// this calculates the actual address of f, by getting f+5(the length of the jump instruction)+the jump offset
unsigned char *fAddr = (unsigned char*)f + 5 + *(int*)((char*)f + 1);
printf("printing f bytes (pid %d at 0x%" PRIXPTR "):\n", GetCurrentProcessId(), fAddr);
int fLen = 0x45; // for me, function size was 0x42
for (int i = 0; i < fLen;)
{
for (int j = 0; j < 10 && i < fLen; ++j)
printf("%02X ", fAddr[i++]);
printf("\n");
}
getchar();
return 0;
}
Приведенный выше код в основном выводит байты кода f
.
Теперь, если я поставлю программную точку останова внутри f
, значение этого байта изменится на 0xCC.
И это будет отражено, когда main
напечатает f
.
Я ожидаю, что при вызове ReadProcessMemory по адресу точки останова я также получу 0xCC вместо исходного значения байта.
Это действительно то, что происходит, когда я устанавливаю точку останова с помощью Visual Studio.
Однако когда я устанавливаю точку останова с помощью WinDbg, ReadProcessMemory возвращает исходное значение байта.
- Кто-нибудь знает, почему это происходит и что в WinDbg отличается от Visual Studio? В конце концов, они оба устанавливают программные точки останова.
- Есть ли способ узнать, каково реальное значение адреса памяти?
Edit:
Вот код, который я использовал для вызова ReadProcessMemory:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <inttypes.h>
#include <Windows.h>
int main()
{
int *fPid;
int *fAddr;
printf("Please enter the pid of f (upper case hex digits, no 0x): ");
scanf("%X", &fPid);
printf("Please enter the address of f (upper case hex digits, no 0x): ");
scanf("%X", &fAddr);
printf("printing f bytes (pid 0x%X at 0x%X):\n", fPid, fAddr);
HANDLE process;
if ((process = OpenProcess(PROCESS_VM_READ, FALSE, fPid)) == INVALID_HANDLE_VALUE)
{
DWORD err = GetLastError();
printf("OpenProcess error: %d\n", err);
char cmd[100];
sprintf(cmd, "net helpmsg %d", err);
system(cmd);
return 1;
}
int fLen = 0x45;
unsigned char *buf = malloc(fLen);
if (!ReadProcessMemory(process, fAddr, buf, fLen, NULL))
{
DWORD err = GetLastError();
printf("ReadProcessMemory error: %d\n", err);
char cmd[100];
sprintf(cmd, "net helpmsg %d", err);
system(cmd);
return 1;
}
for (int i = 0; i < fLen;)
{
for (int j = 0; j < 10 && i < fLen; ++j)
printf("%02x ", buf[i++]);
printf("\n");
}
free(buf);
return 0;
}
Что касается точки останова, в VS я просто поставил точку останова на return x+1
.
В WinDBG я использовал bp cpp_exe!f+20
, предполагая, что имя модуля (exe) cpp_exe
.