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.