Внедрение DLL с помощью ловушек - Модуль вызывающего процесса
ОГЛАВЛЕНИЕ
Страница 2 из 3
Листинг №1 - модуль вызывающего процесса
//"InjectDllH.cpp" : Defines the entry point for the application.
#include "stdafx.h"
__declspec(dllimport) BOOL WINAPI InjectDLL(DWORD dwThreadId,HANDLE
SwitcherEvent);
////////////////////////////////////////////////////////////////////////
BOOL __stdcall DlgProc(HWND hWnd,UINT iMsg,WPARAM wParam,LPARAM lParam)
{
HWND hwnd;
static HWND hwndDSPS,hwndLV,hList;
HANDLE SwitcherEvent;
char *buf;
UINT action;
switch(iMsg){
case WM_INITDIALOG:
hList=GetDlgItem(hWnd,IDC_EVENTS_HANDLER);
return TRUE;
case WM_APP:
if(lParam==IDC_SAVE)
// Получено сообщение от сервера, о том что пошло сохранение
// позиций
SendMessage(hList,LB_ADDSTRING,0,(LPARAM)"Saving in
process....");
else
//-||-||- Пошло восстановление
SendMessage(hList,LB_ADDSTRING,0,(LPARAM)"Restoring in
process....");
break;
case WM_COMMAND:
switch(LOWORD(wParam)){
case IDC_SAVE:action=IDC_SAVE;buf="Shortcuts were saved...";
goto processing;
case IDC_RESTORE:action=IDC_RESTORE;buf="Shortcuts were
restored...";
processing:
SendMessage(hList,LB_RESETCONTENT ,0,0);
// Получить описатель элемента управления "графический список"
// десктопа
hwndLV = GetFirstChild(GetFirstChild(FindWindow(__TEXT("ProgMan"),
NULL)));
if(!IsWindow(hwndLV)) {
SendMessage(hList,LB_ADDSTRING,0,(LPARAM)"Error getting explorer
handle");
goto exit;
}
SendMessage(hList,LB_ADDSTRING,0,(LPARAM)"Processing......");
// Создаем объект-событие, с помощью которого мы будем
// синхронизировать наш процесс с серверным
SwitcherEvent=CreateEvent(NULL,TRUE,TRUE,"bullet");
if(SwitcherEvent==NULL) {
_INFO("Uppsss..","Error creating switcher event!!");
goto exit;
}
SendMessage(hList,LB_ADDSTRING,0,(LPARAM)"Creating event
object....OK");
// Устанавливаем ловушку, которая внедрит нашу DLL в Експлорер.
// Таким образом мы сможем посылать сообщения нашей DLL, а она
// пошлет их элементу управления "графический список" десктопа, так
// как сообщения для стандартных элементов управления в большинстве
// своем не могут преодолеть границы процессов. Потому необходимо
// внедриться в процесс, которому принадлежит элемент и через
// механизм сообщений управлять внедренной функцией, которая в свою
// очередь будет управлять элементом. А для того чтобы можно было
// послать сообщение этой функции, необходимо связать с ней очередь
// сообщений - это возможно путем создания окна, тогда процедура
// этого окна и будет обрабатывать наши сообщения. То есть: мы
// внедряем DLL, функция хука создает окно с оконной процедурой,
// расположенной во внедренной DLL, эта программа обрабатывает наши
// сообщения, она является, по сути, перенаправлением между нашим
// процессом и элементом управления "графический список".
InjectDLL(GetWindowThreadProcessId(hwndLV,NULL),SwitcherEvent);
SendMessage(hList,LB_ADDSTRING,0,(LPARAM)"Injecting dll into
Explorer....OK");
SendMessage(hList,LB_ADDSTRING,0,(LPARAM)"Waiting for GetMessage
Proc....got");
// Ожидаем пока освободится объект-событие, сервер освобождает его,
// когда окно диалога успешно создано и ожидает сообщений
if(WaitForSingleObject(SwitcherEvent,INFINITE)==WAIT_FAILED) {
_INFO("Err...","Something is wrong with server...");
goto exit;
}
// Получить описатель диалога, созданного сервером
hwndDSPS = FindWindow(NULL, __TEXT("bullet server instance"));
// Проверяем валидность описателя
if(IsWindow(hwndDSPS)) {
SendMessage(hList,LB_ADDSTRING,0,(LPARAM)"Checking for server
window....OK");
// Даем команду процедуре диалога, внедренной в explorer,
// Начать работу с ListBox, идентифицируемым по hwndLV,
action==SAVE/RESTORE
SendMessage(hwndDSPS, WM_APP, (WPARAM) hwndLV,(LPARAM)action);
SendMessage(hList,LB_ADDSTRING,0,(LPARAM)buf);
SendMessage(hList,LB_ADDSTRING,0,(LPARAM)"Shutdowning server....");
// Уничтожить окно диалога после завершения операции
// сохранения/восстановления. Используем SendMessage, так как мы
// должны быть уверены, что окно диалога будет уничтожено до снятия
// хука, иначе произойдет нарушение доступа к памяти. Диалог получит
// сообщение и ОС передаст управление оконной процедуре,
// расположенной во внедренной DLL. Но после снятия хука эта DLL
// будет отключена от процесса->>error.
SendMessage(hwndDSPS, WM_CLOSE, 0, 0);
// Убеждаемся, что диалог уничтожен
if(!IsWindow(hwndDSPS)) {
SendMessage(hList,LB_ADDSTRING,0,(LPARAM)"Server stopped!
Releasing hook");
// Снять хук и убрать оконную процедуру серверного диалога из
// explorer
InjectDLL(0,0);
}
}
exit: return TRUE;
case IDC_EXIT:
SendMessage(hList,LB_ADDSTRING,0,(LPARAM)"Quitting...");
EndDialog(hWnd,LOWORD(wParam));
return TRUE;
}
break;
}
return FALSE;
}
////////////////////////////////////////////////////////////////////////
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
//запуск диалога
int choice=DialogBox(hInstance, MAKEINTRESOURCE(IDD_CALLER_DIALOG),
NULL, DlgProc);
return 0;
}
Я думаю, что тут все прозрачно, потому перейду сразу к коду DLL. Там все тоже в комментариях, но пару слов я скажу:
Функция InjectDLL устанавливает хук и отправляет сообщение explorer для активации нашей DLL. ОС сразу внедряет ее в адресное пространство потока ListBox. Также InjectDLL устанавливает объект "событие" в состояние ЗАНЯТО, вызывающий поток будет ждать до тех пор, пока он не освободится. Далее вызывается GetMsgProc, функция обработки хука. Она создает окно диалога и при успешном его создании устанавливает объект "событие" в свободное состояние. Тогда вызывающий процесс начинает продуцировать команды окну диалогу для их пересылки потоку ListBox. Ну а теперь source: