@sddvxd

Почему компилятор возвращает эту ошибку (undefined reference)?

Здравствуйте

Моя программа инжектит DLL файл, который устанавливает хуки на NtCreateFile и MoveFileExW и спрашивает разрешения у пользователя (разрешить скопировать/переместить файл по указанному пути)

Вот код DLL модуля:

#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;
}


Компилятор возвращает:

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
  • Вопрос задан
  • 156 просмотров
Решения вопроса 1
15432
@15432
Системный программист ^_^
Ну теперь всё понятнее. У вас в коде такая вот штука
retValue = NtCreateFile
А должен быть вызов через ваш ранее разрезолвенный и сохранённый указатель pOrigMBAddress_1

Аналогично со второй функцией. Вызывая её "по-старинке", вы уйдётё в собственный обработчкик и зациклитесь. А ошибку компилятор выдает, потому что не знает описания NtCreateFile. Для MoveFileEx видимо есть заголовочный файл, вот и не ругается.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы