指针调用函数写内存失败等原因是什么?
本帖最后由 董督秀 于 2024-5-18 11:37 编辑情况:
我尝试通过指针调用函数进行写内存,对于此函数,调用之后写内存失败。
问题:
1. 代码编译无误,是什么原因导致写内存失败?我通过调试器跟踪了下,传入的参数没问题,但写内存失败,错误返回值保存在rax/eax里,提示CX0000XX,好像是拒绝(...)?即使是通过管理员身份启动,也无法写内存。另外,实验的就是普通的进程,例如自己编译的Hello world!控制台程序,非驱动保护的进程,并且如果换成WriteProcessMemory就成功(我已经调用了OpenProcess)。如何解决?
2. 这节代码在一些系统上,调用此函数有概率能对32位进程写内存成功;但是对于64位进程,则写内存失败,为什么?
我的源码节选如下:
BOOL _NtWriteProcessMemory(HANDLE hprocess, PVOID address, PVOID buffer, ULONG readSize, ULONG* realSize);
typedef NTSTATUS(NTAPI* PfnNtWriteVirtualMemory)(
HANDLE ProcessHandle,
PVOID BaseAddress,
PVOID Buffer,
ULONG NumberOfBytesToWrite,
PULONG NumberOfBytesWritten OPTIONAL);
BOOL _NtWriteProcessMemory(HANDLE hprocess, PVOID address, PVOID buffer, ULONG readSize, ULONG* realSize)
{
HMODULE hModule = LoadLibrary("ntdll.dll");
if (!hModule)
{
return FALSE;
}
PfnNtWriteVirtualMemory p_NtWriteVirtualMemory = (PfnNtWriteVirtualMemory)GetProcAddress(hModule, "NtWriteVirtualMemory");
if (!p_NtWriteVirtualMemory)
{
return FALSE;
}
if (p_NtWriteVirtualMemory(hprocess, address, buffer, readSize, realSize) == STATUS_SUCCESS)
{
return TRUE;
}
return FALSE;
} 你使用的是函数指针,建议打断点一个一个调试 代码没问题! 要确认内存页属性是否可写,不是可写的话要VirtualProtect一下 yes2 发表于 2024-5-21 10:28
要确认内存页属性是否可写,不是可写的话要VirtualProtect一下
还是不行。你试一下上面的节选代码,没法写内存。 不会delphi,只会C。你写64位目标的时候是编译成64位的进程吗? yes2 发表于 2024-6-3 08:52
不会delphi,只会C。你写64位目标的时候是编译成64位的进程吗?
上面的是c的代码,这份代码我测试写64位进程内存失败。{:1_923:} BOOL _NtWriteProcessMemory(HANDLE hprocess, PVOID address, PVOID buffer, SIZE_T readSize, SIZE_T* realSize);
typedef NTSTATUS(NTAPI* PfnNtWriteVirtualMemory)(
HANDLE ProcessHandle,
PVOID BaseAddress,
PVOID Buffer,
SIZE_T NumberOfBytesToWrite,
SIZE_T* NumberOfBytesWritten OPTIONAL);
BOOL _NtWriteProcessMemory(HANDLE hprocess, PVOID address, PVOID buffer, SIZE_T readSize, SIZE_T* realSize)
{
HMODULE hModule = LoadLibraryA("ntdll.dll");
if (!hModule)
{
return FALSE;
}
PfnNtWriteVirtualMemory p_NtWriteVirtualMemory = (PfnNtWriteVirtualMemory)GetProcAddress(hModule, "NtWriteVirtualMemory");
if (!p_NtWriteVirtualMemory)
{
return FALSE;
}
if (p_NtWriteVirtualMemory(hprocess, address, buffer, readSize, realSize) == 0)
{
return TRUE;
}
return FALSE;
}
int _tmain(int argc, _TCHAR* argv[])
{
DWORD processId = 0xDA4; // notepad pid
HANDLE hProcess = OpenProcess(PROCESS_VM_READ | PROCESS_VM_WRITE, FALSE, processId);
if (hProcess == NULL) {
printf("Failed to open process: %d\n", GetLastError());
return 1;
}
wchar_t buf[] = L"hahaha";
SIZE_T writed;
_NtWriteProcessMemory(hProcess, (PVOID)0x450930, // ce搜索出来的记事本的文本地址
buf, wcslen(buf)*sizeof(wchar_t), &writed);
CloseHandle(hProcess);
return 0;
}
这个代码测试是通过的,编译成64位程序,对64位的记事本进行写入,可以成功
页:
[1]