memory allocation through VirtualAlloc Win32 API works smoothly, however, trying to make a direct system call as provided below results in 0xc0000005 error (STATUS_ACCESS_VIOLATION).
The code is as follows:
evasion.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>
extern "C" NTSTATUS myNtAllocateVirtualMemory(
HANDLE ProcessHandle,
PVOID *BaseAddress,
ULONG ZeroBits,
PULONG RegionSize,
ULONG AllocationType,
ULONG Protect
);
int main(int argc, char* argv[])
{
LPVOID rb;
NTSTATUS res = myNtAllocateVirtualMemory(GetCurrentProcess(), &rb, 0, (PULONG)0x1000, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
printf("STATUS: %x\n", res);
return 0;
}
syscall.asm:
section .text
global myNtAllocateVirtualMemory
myNtAllocateVirtualMemory:
mov r10, rcx
mov eax, 18h
syscall
ret
Compiled as follows on Linux for Windows 10 x86-64:
nasm -f win64 -o syscall.o syscall.asm
x86_64-w64-mingw32-g++ -m64 -c evasion.c -I/usr/share/mingw-w64/include/ -s -ffunction-sections -fdata-sections -Wno-write-strings -fno-exceptions -fmerge-all-constants -static-libstdc++ -static-libgcc -Wall -shared -fpermissive
x86_64-w64-mingw32-gcc evasion.o syscall.o -o evasion.exe
Any suggestions are very welcomed!
As @Luke and @OldBoy have stated in the comments, the RegionSize parameter should be a pointer to the value. As @TedLyngmo has mentioned: the BaseAddress pointer should be initialized to NULL;
Adjusting both variables accordingly did the trick.
Here is the working code:
...
ULONG regionsize = 0x1000;
int main(int argc, char* argv[])
{
LPVOID rb = NULL;
NTSTATUS res = myNtAllocateVirtualMemory(GetCurrentProcess(), &rb, 0, ®ionsize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
...
}
Appreciate your help, guys. Sorry, C is not my primary language.