Как внедрить DLL в программу Delphi

У меня есть устаревшее приложение, которое содержит сетку с данными, которые мне нужно извлечь.

У меня нет кода для этого приложения, и невозможно извлечь из него данные обычным способом (например, программным путем выбрать все ячейки и скопировать их в буфер обмена).

Поэтому я решил использовать DLL-инъекцию, как описано в разделе «II. CreateRemoteThread & LoadLibrary Technique «в

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

Мой план

  1. Чтобы загрузить DLL в адресное пространство старого приложения.
  2. Заставьте DLL прочитать данные из сетки и записать их (например, через именованный канал).

Первым шагом является внедрение DLL в адресное пространство унаследованного приложения (шаг а) выше).

Я написал следующий код для этого:

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»?

Обновление от 16.09.2012:

Я заменил все вхождения

SizeOf (szLibPath)

по длине, где

const int pathLength = strlen (szLibPath) +1;

Сейчас в

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

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

hLibModule не равен нулю, что означает, что инъекция прошла успешно.

Но я все еще не вижу вывод журнала образца DLL в выводе программы.

Обновление от 16.09.2012 (2):

Когда я

а) добавить вызов AllocConsole () в DllMain примера DLL,
б) восстановить его и
в) выполнить инъекционную программу,

затем появится консольное окно, которое имеет тот же значок, что и приложение Delphi.

Когда я удаляю AllocConsole из функции DllMain и запускаю приложение для инъекций, окно консоли не появляется.

Таким образом, инъекция может действительно работать.

3

Решение

Самая большая проблема, которую я вижу, состоит в том, что sizeof(szLibPath) оценивает размер указателя. использование strlen(szLibPath)+1 вместо.

Наверняка это означает, что ваша инъекция не удастся, потому что путь, который LoadLibraryA Получатели будут усечены. Могут быть и другие проблемы, но это место для начала.

1

Другие решения

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector