Home > Net >  NtProtectVirtualMemory return STATUS_ACCESS_VIOLATION?
NtProtectVirtualMemory return STATUS_ACCESS_VIOLATION?

Time:11-06

I'm tried to invoke NtProtectVirtualMemory from my dll, that was attached to application using followed code:

typedef NTSTATUS(__stdcall* tNtProtectVirtualMemory) (HANDLE, IN OUT PVOID*, IN OUT PULONG, IN ULONG, OUT PULONG);
...
HMODULE Ntdll = GetModuleHandle("ntdll.dll");
if (!Ntdll) {
    char outtxt[64];
    sprintf(outtxt, "GetModuleHandle error %d", GetLastError());
    MessageBox(NULL, outtxt, "error", MB_OK);
}
tNtProtectVirtualMemory OrigNtProtectVirtualMemory = (tNtProtectVirtualMemory)GetProcAddress(Ntdll, "NtProtectVirtualMemory");
if (!OrigNtProtectVirtualMemory) {
    char outtxt[64];
    sprintf(outtxt, "tNtProtectVirtualMemory is null (%d)", GetLastError());
    MessageBox(NULL, outtxt, "error", MB_OK);
}
NTSTATUS sts = OrigNtProtectVirtualMemory(-1, sectionData->address, sectionData->size, protect, &oldProtect);

GetModuleHandle returns correct handle and GetProcAddress works fine. NtProtectVirtualMemory returns 0xC0000005 (STATUS_ACCESS_VIOLATION).

Now what's most interesting: VirtualProtect works without any errors:

VirtualProtect(sectionData->address, sectionData->size, protect, &oldProtect);

But I have to use exactly NtProtectVirtualMemory. Any ideas?

CodePudding user response:

Unlike VirtualProtectEx, the NtProtectVirtualMemory function takes a pointer to the pointer that points to the address of the region whose protection is to be changed, and a pointer to the size:

ULONG oldProtect;
ULONG size = sectionData->size;
PVOID address = sectionData->address;
NTSTATUS sts = OrigNtProtectVirtualMemory((HANDLE)-1, &address, &size, protect, &oldProtect);

To add more information, the (HANDLE)-1 process handle means to take the current process handle - without the need to open the current process, I found this by reversing the ntdll.dll, but couldn't find any documentation about it.

  • Related