我有一個遺留應用程序,其中包含一個需要提取數據的網格。如何將DLL注入到Delphi程序中
我沒有該應用程序的代碼,並且不可能通過常規方式(如以編程方式選擇所有單元格並將它們複製到剪貼板中)從其中獲取數據。
所以我決定用DLL注入作爲
節「二,遠程線程&調用LoadLibrary技術」描述http://www.codeproject.com/Articles/4610/Three-Ways-to-Inject-Your-Code-into-Another-Proces
我的計劃是
- 到DLL加載到地址遺留應用程序的空間。
- 使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;
}
一些評論:
- 遺留節目的標題爲 「FORMSSSSS」。
- 樣品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並執行注入應用程序時,控制檯窗口不會出現。
所以注射可能實際上工作。
您確定要「自己推出」,而不是隻購買MadCodeHook。它可以節省大量的工作。 –