2012-04-07 4 views
5

私が作成した注入されたDLLのリモートプロセスで関数を呼び出したい。注入されたDLLの関数を呼び出す

CreateRemoteThread(pHandle, NULL, 0, (LPTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle("kernel32"), "LoadLibraryA"), pLibRemote, 0, NULL); 

にDllMainが実行され、DLLが待機モードで実行されている:

は、私は正常に私のDLLを注入しています。私がやりたいことは、何らかの作業をするために何とかリモートでロードされたDLLを呼び出すことです。

私はこのような機能を輸出しようとしている:

extern "C" __declspec(dllexport) void MyFunc(void) 

し、このように関数を実行:

CreateRemoteThread(pHandle, NULL, 0, (LPTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle("mydll"), "MyFunc"), NULL, 0, NULL); 

が、それはクラッシュにつながります。

どうすればこの問題を解決できますか?

+0

GetModuleHandleは何を返しますか? GetProcAddressは何を返しますか? –

+0

両方とも0を返します。GetModuleHandleは、ロードしていないホストプロセス内のモジュールのハンドルを取得しようとします。 –

答えて

13

GetModuleHandleを呼び出すと、DLLがプロセスにマップされたときにそのDLLのベースが取得されます。だから、まずDLL内の関数をエクスポートすることを確認する必要があります。図のようにファイル.defを作成して作成することができます(here)。その後:理論的には

  1. は、それが現在のプロセスにDLLを注入
  2. でロードされたターゲットプロセスにDLLを注入し、ベースアドレスを取得します。エクスポートされた関数とDLLのベースとの間のオフセットを見つけるには、GetProcAddressを使用します。
  3. 手順1で取得したベースアドレスにこのオフセットを追加します。CreateRemoteThreadこの位置にあります。

実践で

あなたのDLLインジェクションを行う場合、あなたのDLLがターゲットにロードされたベースを取得することが可能です。

HMODULE hInjected; 

hThread = CreateRemoteThread(hProcess, NULL, 0, 
     (LPTHREAD_START_ROUTINE)(GetProcAddress(hMod, 
     "LoadLibraryW")), lpAddress, 0, NULL); 

// Locate address our payload was loaded 
if(hThread != 0) { 
    WaitForSingleObject(hThread, INFINITE); 
    GetExitCodeThread(hThread, (LPDWORD)&hInjected); 
    CloseHandle(hThread); 
} 

hInjectedは、注入されたDLLのベースになります。

void* GetPayloadExportAddr(LPCWSTR lpPath, HMODULE hPayloadBase, LPCSTR lpFunctionName) { 
    // Load payload in our own virtual address space 
    HMODULE hLoaded = LoadLibrary(lpPath); 

    if(hLoaded == NULL) { 
    return NULL; 
    } else { 
    void* lpFunc = GetProcAddress(hLoaded, lpFunctionName); 
    DWORD dwOffset = (char*)lpFunc - (char*)hLoaded; 

    FreeLibrary(hLoaded); 
    return (DWORD)hPayloadBase + dwOffset; 
    } 
} 

これは、最初に私たち自身の仮想アドレス空間にペイロードを読み込みます。その後、 GetProcAddressを使用して、エクスポートされた関数のアドレスを取得できます。これから、関数のオフセットをDLLの基底から得ることができます。このオフセットをhInjectedに追加すると、CreateRemoteThreadの呼び出しがどこにあるかがわかります。あなたがそうのように電話をかけることができるように:

BOOL InitPayload(HANDLE hProcess, LPCWSTR lpPath, HMODULE hPayloadBase, HWND hwndDlg) { 
    void* lpInit = GetPayloadExportAddr(lpPath, hPayloadBase, "Init"); 
    if(lpInit == NULL) { 
    return FALSE; 
    } else { 
    HANDLE hThread = CreateRemoteThread(hProcess, NULL, 0, 
     lpInit, hwndDlg, 0, NULL); 

    if(hThread == NULL) { 
     return FALSE; 
    } else { 
     CloseHandle(hThread); 
    } 
    } 

    return TRUE; 
} 

これはold project I haveの外にリッピングされたすべてのコードです。あなたはコードを受け取り、それを使って何でもしても構いませんが、コードを今書き直すかどうかは別です。

2

マイケルの答えは、32ビットDLLを32ビットプロセスに注入する場合に機能します。

64ビットDLLを64ビットプロセスに注入する場合は、DLLのベースアドレスをから得ることができません。これは、64ビットアドレスの下位32ビットのみを提供するためです。

この場合正しいアドレスを取得するには、LoadLibraryを呼び出して(プロセスメモリの特定の場所に結果を格納する)コードブロックを記述し、このコードブロックを実行します(CreateRemoteThreadを使用)。 ReadProcessMemoryを使用してその場所からアドレスを読み取ってください。

あなたはここ(PowerShellとASMコードを含む)、ここで、このためのより多くの詳細を見つけることができます。 http://clymb3r.wordpress.com/2013/05/26/implementing-remote-loadlibrary-and-remote-getprocaddress-using-powershell-and-assembly/

次に、あなたのエクスポート機能マイクは説明と同じようにオフセットを計算することができ、その違いを保存するために気を付けます64ビット値ではなく、DWORD(32ビット)ではありません。

関連する問題