S
S
sddvxd2018-06-24 13:16:12
C++ / C#
sddvxd, 2018-06-24 13:16:12

Why does the compiler return this error (undefined reference)?

Hello
My program injects a DLL file that installs hooks on NtCreateFile and MoveFileExW and asks the user for permission (allow copy / move the file to the specified path)
Here is the code of the DLL module:

#define MYLIBAPI extern "C"  __declspec(dllexport)

#include "head.h"

#define SIZE 6


 typedef int (WINAPI *pMessageBoxW)(HWND, LPCWSTR, LPCWSTR, UINT);  // Messagebox prototype
 typedef int (WINAPI *pCreateFile)(LPCTSTR, DWORD, DWORD, LPSECURITY_ATTRIBUTES, DWORD, DWORD, HANDLE);
 typedef NTSTATUS (WINAPI *pNtCreateFile)(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, PIO_STATUS_BLOCK, PLARGE_INTEGER,
                                           ULONG, ULONG, ULONG, ULONG, PVOID, ULONG);
 typedef BOOL (WINAPI * pMoveFileExW)(LPCWSTR, LPCWSTR, DWORD);
 int WINAPI MyMessageBoxW(HWND, LPCWSTR, LPCWSTR, UINT);            // Our detour
 HANDLE WINAPI MyCreateFileW(LPCWSTR, DWORD, DWORD, LPSECURITY_ATTRIBUTES, DWORD, DWORD, HANDLE);
 NTSTATUS MyNtCreateFile(
        PHANDLE            FileHandle,
        ACCESS_MASK        DesiredAccess,
        POBJECT_ATTRIBUTES ObjectAttributes,
        PIO_STATUS_BLOCK   IoStatusBlock,
        PLARGE_INTEGER     AllocationSize,
        ULONG              FileAttributes,
        ULONG              ShareAccess,
        ULONG              CreateDisposition,
        ULONG              CreateOptions,
        PVOID              EaBuffer,
        ULONG              EaLength
);

BOOL WINAPI MyMoveFileExW(LPCWSTR lpExistingFileName, LPCWSTR lpNewFileName, DWORD dwFlags);

 void BeginRedirect(LPVOID, BOOL);
 pNtCreateFile pOrigMBAddress_1 = NULL;                                // address of original
 BYTE oldBytes_1[SIZE] = {0};                                         // backup
 BYTE JMP_1[SIZE] = {0};                                              // 6 byte JMP instruction
 DWORD oldProtect_1, myProtect_1 = PAGE_EXECUTE_READWRITE;
 ///
 pMoveFileExW pOrigMBAddress_2 = NULL;                                // address of original
 BYTE oldBytes_2[SIZE] = {0};                                         // backup
 BYTE JMP_2[SIZE] = {0};                                              // 6 byte JMP instruction
 DWORD oldProtect_2, myProtect_2 = PAGE_EXECUTE_READWRITE;

 INT APIENTRY DllMain(HMODULE hDLL, DWORD Reason, LPVOID Reserved)
 {
   switch(Reason)
   {
   case DLL_PROCESS_ATTACH:                                        // if attached
     pOrigMBAddress_1 = (pNtCreateFile)
       GetProcAddress(GetModuleHandle("NtDLL.dll"),               // get address of original
               "NtCreateFile");
     if(pOrigMBAddress_1 != NULL){
       BeginRedirect((LPVOID)&MyNtCreateFile, TRUE);                               // start detouring
       pOrigMBAddress_2 = (pMoveFileExW)
         GetProcAddress(GetModuleHandle("Kernel32.dll"),               // get address of original
                 "MoveFileExW");
       if(pOrigMBAddress_2!= NULL)
           BeginRedirect((LPVOID)&MyMoveFileExW, FALSE);
     }
     break;

   case DLL_PROCESS_DETACH:
     //memcpy((LPVOID)pOrigMBAddress, oldBytes, SIZE);                       // restore backup

   case DLL_THREAD_ATTACH:
   case DLL_THREAD_DETACH:
     break;
   }
   return TRUE;
 }

 void BeginRedirect(LPVOID newFunction, BOOL first)
 {
   if(first){
     BYTE tempJMP_1[SIZE] = {0xE9, 0x90, 0x90, 0x90, 0x90, 0xC3};         // 0xE9 = JMP 0x90 = NOP 0xC3 = RET
     memcpy(JMP_1, tempJMP_1, SIZE);                                        // store jmp instruction to JMP
     DWORD JMPSize_1 = (reinterpret_cast<char*>(newFunction) - reinterpret_cast<char*>(pOrigMBAddress_1) - 5);  // calculate jump distance
     VirtualProtect((LPVOID)pOrigMBAddress_1, SIZE,                       // assign read write protection
             PAGE_EXECUTE_READWRITE, &oldProtect_1);
     memcpy(oldBytes_1, (LPVOID)pOrigMBAddress_1, SIZE);                            // make backup
     memcpy(&JMP_1[1], &JMPSize_1, 4);                              // fill the nop's with the jump distance (JMP,distance(4bytes),RET)
     memcpy((LPVOID)pOrigMBAddress_1, JMP_1, SIZE);                                 // set jump instruction at the beginning of the original function
     VirtualProtect((LPVOID)pOrigMBAddress_1, SIZE, oldProtect_1, NULL);    // reset protection
   }else{
     BYTE tempJMP_2[SIZE] = {0xE9, 0x90, 0x90, 0x90, 0x90, 0xC3};         // 0xE9 = JMP 0x90 = NOP 0xC3 = RET
     memcpy(JMP_2, tempJMP_2, SIZE);                                        // store jmp instruction to JMP
     DWORD JMPSize_2 = (reinterpret_cast<char*>(newFunction) - reinterpret_cast<char*>(pOrigMBAddress_2) - 5);  // calculate jump distance
     VirtualProtect((LPVOID)pOrigMBAddress_2, SIZE,                       // assign read write protection
             PAGE_EXECUTE_READWRITE, &oldProtect_2);
     memcpy(oldBytes_2, (LPVOID)pOrigMBAddress_2, SIZE);                            // make backup
     memcpy(&JMP_2[1], &JMPSize_2, 4);                              // fill the nop's with the jump distance (JMP,distance(4bytes),RET)
     memcpy((LPVOID)pOrigMBAddress_2, JMP_2, SIZE);                                 // set jump instruction at the beginning of the original function
     VirtualProtect((LPVOID)pOrigMBAddress_2, SIZE, oldProtect_2, NULL);    // reset protection
   }

 }

 NTSTATUS MyNtCreateFile(
        PHANDLE            FileHandle,
        ACCESS_MASK        DesiredAccess,
        POBJECT_ATTRIBUTES ObjectAttributes,
        PIO_STATUS_BLOCK   IoStatusBlock,
        PLARGE_INTEGER     AllocationSize,
        ULONG              FileAttributes,
        ULONG              ShareAccess,
        ULONG              CreateDisposition,
        ULONG              CreateOptions,
        PVOID              EaBuffer,
        ULONG              EaLength
)
{
  NTSTATUS retValue;
  int res = IDYES;

  if(CreateDisposition == FILE_CREATE && CreateOptions & FILE_NON_DIRECTORY_FILE){
    res = MessageBoxW(FindWindowW(NULL, L"Корзина"), (LPCWSTR)ObjectAttributes->ObjectName->Buffer, (LPCWSTR)L"Разрешить скопировать файл по этому пути?", MB_YESNO);
  }
  if(res == IDYES){
    VirtualProtect((LPVOID)pOrigMBAddress_1, SIZE, myProtect_1, NULL);     // assign read write protection
    memcpy((LPVOID)pOrigMBAddress_1, oldBytes_1, SIZE);                            // restore backup
    retValue = NtCreateFile(FileHandle, DesiredAccess, ObjectAttributes, IoStatusBlock, AllocationSize,
                            FileAttributes, ShareAccess, CreateDisposition, CreateOptions,
                            EaBuffer, EaLength);       // get return value of original function
    memcpy((LPVOID)pOrigMBAddress_1, JMP_1, SIZE);                                 // set the jump instruction again
    VirtualProtect((LPVOID)pOrigMBAddress_1, SIZE, oldProtect_1, NULL);    // reset protection
   }
   else{
     retValue = 0;
   }


  return retValue;
}



BOOL WINAPI MyMoveFileExW(LPCWSTR lpExistingFileName, LPCWSTR lpNewFileName, DWORD dwFlags)
{
  BOOL retValue;
  int res = IDYES;

  res = MessageBoxW(FindWindowW(NULL, L"Корзина"), lpNewFileName, (LPCWSTR)L"Разрешить переместить файл по этому пути?", MB_YESNO);

  if(res == IDYES){
  VirtualProtect((LPVOID)pOrigMBAddress_2, SIZE, myProtect_2, NULL);     // assign read write protection
  memcpy((LPVOID)pOrigMBAddress_2, oldBytes_2, SIZE);                            // restore backup
  retValue = MoveFileExW(lpExistingFileName, lpNewFileName, dwFlags);
  memcpy((LPVOID)pOrigMBAddress_2, JMP_2, SIZE);                                 // set the jump instruction again
  VirtualProtect((LPVOID)pOrigMBAddress_2, SIZE, oldProtect_2, NULL);    // reset protection
  }
  else{
     retValue = FALSE;
  }

  return retValue;
}

The compiler returns:
C:\cpp\dll>g++ -shared -o mydll.dll *.cpp -m64
C:\Users\sddvxd\AppData\Local\Temp\ccYtfLJr.o:main.cpp:(.text+0x394) : undefined
reference to `NtCreateFile'
collect2.exe: error: ld returned 1 exit status

Answer the question

In order to leave comments, you need to log in

1 answer(s)
1
15432, 2018-06-24
@sddvxd

Well, now everything is clearer. You have such a thing in your code
And there should be a call through your previously resolved and saved pointer pOrigMBAddress_1
Similarly with the second function. By calling it "the old fashioned way", you will go into your own handler and get stuck. And the compiler produces an error because it does not know the description of NtCreateFile. For MoveFileEx, there is apparently a header file, so it does not swear.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question