董督秀 发表于 2024-5-18 11:13

指针调用函数写内存失败等原因是什么?

本帖最后由 董督秀 于 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;
}

moshi 发表于 2024-5-18 12:48

你使用的是函数指针,建议打断点一个一个调试

xlhwxyh 发表于 2024-5-18 13:46

代码没问题!

yes2 发表于 2024-5-21 10:28

要确认内存页属性是否可写,不是可写的话要VirtualProtect一下

董督秀 发表于 2024-5-31 11:10

yes2 发表于 2024-5-21 10:28
要确认内存页属性是否可写,不是可写的话要VirtualProtect一下

还是不行。你试一下上面的节选代码,没法写内存。

yes2 发表于 2024-6-3 08:52

不会delphi,只会C。你写64位目标的时候是编译成64位的进程吗?

董督秀 发表于 2024-6-3 09:17

yes2 发表于 2024-6-3 08:52
不会delphi,只会C。你写64位目标的时候是编译成64位的进程吗?

上面的是c的代码,这份代码我测试写64位进程内存失败。{:1_923:}

yes2 发表于 2024-6-3 15:44

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]
查看完整版本: 指针调用函数写内存失败等原因是什么?