2012-09-15 50 views
3

我有一个遗留应用程序,其中包含一个需要提取数据的网格。如何将DLL注入到Delphi程序中

我没有该应用程序的代码,并且不可能通过常规方式(如以编程方式选择所有单元格并将它们复制到剪贴板中)从其中获取数据。

所以我决定用DLL注入作为

节“二,远程线程&调用LoadLibrary技术”描述

http://www.codeproject.com/Articles/4610/Three-Ways-to-Inject-Your-Code-into-Another-Proces

我的计划是

  1. 到DLL加载到地址遗留应用程序的空间。
  2. 使DLL从网格读取数据并将其写出(例如通过命名管道)。

的第一步是将DLL注入到遗留应用的地址空间(步骤a)上文)。

我已经写了下面的代码为:

int InjectDll   (HANDLE hProcess); 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    printf("DllInjector\n"); 

    /** 
    * Find out PID of the legacy application (START) 
    */ 
    HWND windowHandle = FindWindowW(NULL, L"FORMSSSSS"); 
    DWORD* processID = new DWORD; 
    GetWindowThreadProcessId(windowHandle, processID); 

    DWORD delphiAppProcessId = *processID; 
    /** 
    * Find out PID of the legacy application (END) 
    */ 

    printf("Process ID of legacy app: %lu\n", delphiAppProcessId); 

    // Now we need the handle of the legacy app 
    HANDLE hProcess = OpenProcess(
    PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ, 
    FALSE, delphiAppProcessId); 

    if (hProcess != NULL) 
    { 
     printf("Found handle, ready for injection\n"); 
     int result = InjectDll(hProcess); 
     CloseHandle(hProcess); 
     printf("Injection complete, result=%d\n", result); 

    } 
    else 
    { 
     printf("Handle not found\n"); 
    } 

    system("pause"); 

    return 0; 
} 

int InjectDll(HANDLE hProcess) 
{ 
    HANDLE hThread; 
    const char* const szLibPath = "D:\\mycompany\\SampleDll\\Debug\\SampleDll.dll"; 
    void* pLibRemote = 0; // the address (in the remote process) where 
          // szLibPath will be copied to; 
    DWORD hLibModule = 0; // base adress of loaded module (==HMODULE); 

    HMODULE hKernel32 = ::GetModuleHandle(L"Kernel32"); 

    // 1. Allocate memory in the remote process for szLibPath 
    // 2. Write szLibPath to the allocated memory 
    pLibRemote = ::VirtualAllocEx(hProcess, NULL, sizeof(szLibPath), MEM_COMMIT, PAGE_READWRITE); 
    if(pLibRemote == NULL) 
     return false; 
    ::WriteProcessMemory(hProcess, pLibRemote, (void*)szLibPath,sizeof(szLibPath),NULL); 

    // Load "LibSpy.dll" into the remote process 
    // (via CreateRemoteThread & LoadLibrary) 
    hThread = ::CreateRemoteThread(hProcess, NULL, 0, 
        (LPTHREAD_START_ROUTINE) ::GetProcAddress(hKernel32,"LoadLibraryA"), 
        pLibRemote, 0, NULL); 
    if(hThread == NULL) 
     goto JUMP; 

    ::WaitForSingleObject(hThread, INFINITE); 

    // Get handle of loaded module 
    ::GetExitCodeThread(hThread, &hLibModule); 
    ::CloseHandle(hThread); 

JUMP: 
    ::VirtualFreeEx(hProcess, pLibRemote, sizeof(szLibPath), MEM_RELEASE); 
    if(hLibModule == NULL) // (1) 
     return false; 


    // Unload "LibSpy.dll" from the remote process 
    // (via CreateRemoteThread & FreeLibrary) 
    hThread = ::CreateRemoteThread(hProcess, 
       NULL, 0, 
       (LPTHREAD_START_ROUTINE) ::GetProcAddress(hKernel32,"FreeLibrary"), 
       (void*)hLibModule, 
       0, NULL); 
    if(hThread == NULL) // failed to unload 
     return false; 

    ::WaitForSingleObject(hThread, INFINITE); 
    ::GetExitCodeThread(hThread, &hLibModule); 
    ::CloseHandle(hThread); 

    // return value of remote FreeLibrary (=nonzero on success) 
    return hLibModule; 
} 

一些评论:

  1. 遗留节目的标题为 “FORMSSSSS”。
  2. 样品DLL具有以下的DllMain方法:

-

BOOL APIENTRY DllMain(HMODULE hModule, 
DWORD ul_reason_for_call, 
LPVOID lpReserved 

{ 
    OutputDebugStringA("DllMain called: "); 
    switch (ul_reason_for_call) 
    { 
    case DLL_PROCESS_ATTACH: 
     OutputDebugStringA("DLL_PROCESS_ATTACH\n"); 
    case DLL_THREAD_ATTACH: 
     OutputDebugStringA("DLL_THREAD_ATTACH\n"); 
    case DLL_THREAD_DETACH: 
     OutputDebugStringA("DLL_THREAD_DETACH\n"); 
    case DLL_PROCESS_DETACH: 
     OutputDebugStringA("DLL_PROCESS_DETACH\n"); 
     break; 
    } 
    return TRUE; 
} 

当被调用时,文本被写入到应用程序的标准输出。


当运行上述程序(具有_tmain方法),我希望看到在控制台输出的文本

DllMain called: DLL_PROCESS_ATTACH 

(这意味着该DLL注射成功)。

但它没有发生。


的一个潜在原因是遗留应用程序的PID被错误地确定:

HWND windowHandle = FindWindowW(NULL, L"FORMSSSSS"); 
DWORD* processID = new DWORD; 
GetWindowThreadProcessId(windowHandle, processID); 

DWORD delphiAppProcessId = *processID; 

但价值delphiAppProcessId是一样的PID显示在任务管理器,这样我就可以排除这种潜在的错误。


使用,我发现,在停止执行与注释的行调试器(1):

JUMP: 
    ::VirtualFreeEx(hProcess, pLibRemote, sizeof(szLibPath), MEM_RELEASE); 
    if(hLibModule == NULL) // (1) 
     return false; 

我需要什么,以使样本DLL改变被注入地址空间的标题为“FORMSSSSS”的应用程序?

更新,2012年9月16日:

我取代

的sizeof(szLibPath)

由光程长度,所有出现的其中

const int的光程长度= strlen的(szLibPath)+ 1;

现在,在

::WaitForSingleObject(hThread, INFINITE); 
    ::GetExitCodeThread(hThread, &hLibModule); 
    ::CloseHandle(hThread); 

    // return value of remote FreeLibrary (=nonzero on success) 
    return hLibModule; 
} 

hLibModule为非零值,这意味着该注射是成功的。

但我仍然无法在程序的输出中看到示例DLL的日志输出。

更新,2012年9月16日(2):

当我

一个)DllMain中添加示例DLL, b)中重建,并 C的AllocConsole()的调用)执行注入程序

然后出现一个控制台窗口,它具有与Delphi应用程序相同的图标。

当我从DllMain函数中删除AllocConsole并执行注入应用程序时,控制台窗口不会出现。

所以注射可能实际上工作。

+0

您确定要“自己推出”,而不是只购买MadCodeHook。它可以节省大量的工作。 –

回答

1

我能看到的最大的问题是sizeof(szLibPath)评估指针的大小。改为使用strlen(szLibPath)+1

当然,这意味着您的注射将失败,因为LoadLibraryA收到的路径将被截断。可能还有其他问题,但这是开始的地方。

+0

或用const char szLibPath []代替以寻址,顺便说一句。 – WhozCraig

+0

@克雷格是的,也会这样做。 –

+0

谢谢。我已经这样做了(请参阅“更新16.09.2012”),但仍然出现问题,因为我没有在注入应用程序的输出中看到示例DLL生成的日志消息。 –

相关问题