Search code examples
c++cassemblylinker

Unresolved external symbol happend when compiling C++


im trying to make a super simple direct syscall. I have 2 file, 1 is the asm file and 1 is the main source file. The ASM look likes:

EXTERN wNtAllocateVirtualMemory: DWORD

.CODE
NtAllocateVirtualMemory proc
    mov r10, rcx
    mov eax, wNtAllocateVirtualMemory
    syscall
    ret
NtAllocateVirtualMemory endp

END

The source file:

#include<Windows.h>
#include<stdio.h>

DWORD wNtAllocateVirtualMemory;

typedef long NTSTATUS;
typedef NTSTATUS* PNTSTATUS;

extern "C" { NTSTATUS NtAllocateVirtualMemory(HANDLE ProcessHandle, PVOID BaseAddress, ULONG_PTR ZeroBits, PSIZE_T RegionSize, ULONG AllocationType, ULONG Protect); }

int main() {
    PVOID allocBuffer = NULL;
    SIZE_T buffSize = 0x1000;

    HANDLE hNtdll = GetModuleHandleA("ntdll");
    if (hNtdll == NULL) {
        perror("Fail to get handle");
        return 0;
    }

    PVOID pNtAllocateVirtualMemory = GetProcAddress((HMODULE) hNtdll, "NtAllocateVirtualMemory");
    wNtAllocateVirtualMemory = *((char*)pNtAllocateVirtualMemory + 4);
    NtAllocateVirtualMemory((HANDLE)-1, (PVOID*)&allocBuffer, (ULONG_PTR)0, &buffSize, (ULONG)(MEM_COMMIT | MEM_RESERVE), PAGE_EXECUTE_READWRITE);
}

There is no error when i change the source type from c++ to c, but if the source type is c++, error happends.

Error   LNK2019 unresolved external symbol wNtAllocateVirtualMemory referenced in function NtAllocateVirtualMemory  syscall_direct  <path>temp.obj  1       

Why is this happend and how can i fix it ?


Solution

  • As others mentioned, in C++, names are mangled to support function overloading, while in C, names are not mangled. You can resolve this issue by using extern "C" for the declaration of wNtAllocateVirtualMemory to ensure it has C linkage.

    #include <Windows.h>
    #include <stdio.h>
    
    extern "C" DWORD wNtAllocateVirtualMemory;
    
    typedef long NTSTATUS;
    typedef NTSTATUS* PNTSTATUS;
    
    extern "C" {
        NTSTATUS NtAllocateVirtualMemory(HANDLE ProcessHandle, PVOID BaseAddress, ULONG_PTR ZeroBits, PSIZE_T RegionSize, ULONG AllocationType, ULONG Protect);
    }
    
    int main() {
        PVOID allocBuffer = NULL;
        SIZE_T buffSize = 0x1000;
    
        HANDLE hNtdll = GetModuleHandleA("ntdll");
        if (hNtdll == NULL) {
            perror("Fail to get handle");
            return 0;
        }
    
        PVOID pNtAllocateVirtualMemory = GetProcAddress((HMODULE)hNtdll, "NtAllocateVirtualMemory");
        wNtAllocateVirtualMemory = *((char*)pNtAllocateVirtualMemory + 4);
        NtAllocateVirtualMemory((HANDLE)-1, (PVOID*)&allocBuffer, (ULONG_PTR)0, &buffSize, (ULONG)(MEM_COMMIT | MEM_RESERVE), PAGE_EXECUTE_READWRITE);
    }