2014-08-27 2 views
4

다음 코드는 dll을 주입하고 DllMain이 호출됩니다. DllMain이 아니라 DLL로부터 특정 함수를 호출하는 방법은 무엇입니까?dll injection에서 특정 함수를 호출하는 방법은 무엇입니까?

DWORD pid; 
    HANDLE hd; 
    LPVOID gp, rs, proc; 

    gp = (LPVOID)GetProcAddress(GetModuleHandle(L"Kernel32.dll"), "LoadLibraryA"); 
    pid = 6096; 

    hd = OpenProcess(PROCESS_ALL_ACCESS, 0, pid);  


    rs = (LPVOID)VirtualAllocEx(hd, 0, sizeof(DLL_NAME), MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); 

    if (!WriteProcessMemory(hd, (LPVOID)rs, DLL_NAME, strlen(DLL_NAME), 0)) 
    { 
     printf("WriteProcessMemory %d", GetLastError()); 
    } 

    if (!CreateRemoteThread(hd, 0, 0, (LPTHREAD_START_ROUTINE)gp, rs, 0, 0)) 
    { 
     printf("CreateRemoteThread %d", GetLastError()); 
    } 

답변

3

음, 다음 접근 방식을 사용하고 있습니다. 주입되고 DLL에서

은이 같은 공유 섹션을 만들 :

#pragma data_seg(".MyShared") 

LPTHREAD_START_ROUTINE g_lpMyFunc = NULL; 

#pragma data_seg() 
#pragma section(".MyShared", read, write, shared) 

공유 부 변수 g_lpMyFunc는 다음과 같이 DllMain 내부 초기화 :

BOOL APIENTRY DllMain(HMODULE, DWORD dwReasonForCall, LPVOID) 
{ 
    if (NULL != GetModuleHandle(_T("MyApp.exe"))) 
    { 
     if (DLL_PROCESS_ATTACH == dwReasonForCall) 
     { 
      g_lpMyFunc = (LPTHREAD_START_ROUTINE)&MyFunc; 
     } 
     else if (DLL_PROCESS_DETACH == dwReasonForCall) 
     { 
      g_lpMyFunc = NULL; 
     } 
    } 
    return TRUE; 
} 

이 코드 다음을 수행합니다. 함수 호출 GetModuleHandle은 MyApp의 실행 모듈 핸들을 얻으려고합니다. 성공하면 NULL이 아닌 값을 반환하고 이는 주입 된 DLL의 DllMain이 원격 프로세스에서 호출되었음을 의미합니다. 이 경우 MyFunc의 주소는 g_lpMyFunc 공유 변수에 저장됩니다. DLL이 프로세스에서 분리되면 (예를 들어 종료 할 때), 거기에없는 원격 주소로 함수를 호출 할 수 없도록 NULL을 g_lpMyFunc으로 설정합니다.

I는 외부 함수 같은 원격 프로세스에 MyFunc를 호출 MyFuncExtern 만들 :

extern "C" __declspec(dllexport) bool __cdecl MyFuncExtern(HANDLE hProcess) 
{ 
    if (NULL == g_lpMyFunc) 
    { 
     return false; 
    } 

    return NULL != CreateRemoteThread(hProcess, NULL, 0, g_lpMyFunc, NULL, 0, NULL); 
} 

그것은 매우 단순화 된 버전입니다,하지만 주요 개념을 보여줍니다 : g_lpMyFunc이 NULL이 아닌 경우,이 생성 주소가 g_lpMyFunc 인 함수를 호출하는 (사용자 코드와 마찬가지로) hProcess에있는 원격 스레드. CreateRemoteThread 이후 원격 기능에 대해 하나 개의 인자를하지만

그 기능에 대한 몇 가지 제한이있다 (당신은 패스 더, 그러나 그것은 훨씬 더 복잡한 접근 방식이 필요합니다 수), 당신은 반환 값이 필요한 경우는 것입니다 원격 스레드가 실행을 완료하고 그 종료 코드 인 DWORD을 기다려야합니다.

이 접근법은 Initialize/Uninitialize 함수를 작성하는 데 적합하며 관리되는 C++/CLI DLL에서도 완벽하게 작동합니다.

물론 다른 교차 프로세스 데이터 저장소를 사용하여 함수 포인터를 저장할 수 있습니다. 메모리 매핑 된 파일은 좋은 예입니다.

5

주입 된 DLL의 DllMain이 처음 실행되면 CreateThread으로 전화하여 원하는대로 수행 할 수있는 새 스레드를 만드십시오. 문서에 설명 된대로 DllMain에서 임의의 코드를 호출 할 수 없습니다. 따라서 DllMain에서 CreateThread으로 전화하십시오.