void* Resolve_ZwProtectVirtualMemory() { PVOID ZwProtectVirtualMemory = NULL; PVOID NtosBase = FindNtoskrnlBase(ZwClose); // Just start from some random symbol which is for sure in ntos... if (NtosBase == NULL) { DbgPrint("Couldn't find ntoskrnl base address!\n"); return STATUS_UNSUCCESSFUL; } //DbgPrint("Found ntoskrnl base at : %p\n", NtosBase); // We are looking for ZwProtectVirtualMemory. // Algorithm: // 1) look for an unaligned dword with value 0x104. // 2) should be prefixed by push dword (0x68) for 32 bits. // 3) should be prefixed by mov r9 (0x41, 0xb9) for 64 bits. // 4) for each occurrance: // 1) go back up to 100 bytes, look for a call (0xe8) to ZwAllocateVirtualMemory symbol // 2) if call target matches, scan forward to find the next call to our symbol (which is not ZwAllocateVirtualMemory). PIMAGE_DOS_HEADER dos = PIMAGE_DOS_HEADER(NtosBase); PIMAGE_NT_HEADERS nt = PIMAGE_NT_HEADERS(PCHAR(NtosBase) + dos->e_lfanew); PUCHAR p = (PUCHAR)NtosBase + nt->OptionalHeader.BaseOfCode; PUCHAR End = (PUCHAR)NtosBase + nt->OptionalHeader.SizeOfImage; __try { while (p++ < End) { // Look for our magic value. if (*(unsigned int*)p == 0x104) { if (nt->FileHeader.Machine == IMAGE_FILE_MACHINE_I386) { if (*(p - 1) != 0x68) // push dword opcode continue; } else { // IMAGE_FILE_MACHINE_AMD64 if (*(PUSHORT)(p - 2) != 0xb941) // mov r9, # opcode continue; } int Found = FALSE; PUCHAR Target1 = NULL, Target2 = NULL; // Look back to find a call to ZwAllocateVirtualMemory. for (int i = 0; i < 100; i++) { if (*(p - i) == 0xe8) { Target1 = GetCallTarget(p - i); if (Target1 == (PUCHAR)ZwAllocateVirtualMemory) { Found = TRUE; break; } } } if (!Found) continue; Found = FALSE; // Look forward to find another call within ~50 bytes, that's our symbol. for (int i = 0; i < 50; i++) { if (*(p + i) == 0xe8) { Target2 = (PUCHAR)GetCallTarget(p + i); // Make sure it's not the same function (such a signature is a false positive). if ((Target1 != Target2) && (Target2 >= NtosBase) && (Target2 <= End)) { ZwProtectVirtualMemory = Target2; Found = TRUE; } break; } } if (Found) break; } } } __except(1) { DbgPrint("Got an AV while resolving internal symbols!\n"); } return ZwProtectVirtualMemory; }