Underground InformatioN Center [&articles] | |
[network & security news] [RSS & Twitter] [articles, programing info] [books] [links, soft & more...] [soft archive] | [home] |
1. Зачем
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:
4. Листинг №2 - модуль внедряемой DLL // DLLToInject.cpp : Defines the entry point for the DLL application. #include "stdafx.h" // Определяем переменные, доступные всем экземплярам данной DLL #pragma data_seg("Shared") HHOOK g_hhook = NULL; // Идентификатор хука. Он необходим для вызова функции СallNextHookEx, // а так как вызов SetWindowsHookEx производится в процессе, внедряющем // DLL, то данный идентификатор возможно передать в функцию, // обрабатывающую хук, только таким образом #pragma data_seg() // Директива линкеру создать разделяемую(shared) секцию с атрибутами RWS #pragma comment(linker, "/section:Shared,rws") HINSTANCE g_hinstDll = NULL; const TCHAR g_szRegSubKey[] = __TEXT("Software\\buLLet\\Desktop Shortcuts Position Saver"); void SaveListViewItemPositions(HWND hwndLV);//сохраняет ярлыки void RestoreListViewItemPositions(HWND hwndLV);//восстанавливает ярлыки BOOL CALLBACK DlgProc(HWND hwnd, UINT uMsg,WPARAM wParam, LPARAM lParam); // Процедура диалога серверного окна void OnClose(HWND hwnd); LRESULT CALLBACK GetMsgProc (int nCode, WPARAM wParam, LPARAM lParam); // Обрабатывает хук //////////////////////////////////////////////////////////////////////// __declspec(dllexport) BOOL WINAPI InjectDLL(DWORD dwThreadId, HANDLE SwitcherEvent) { BOOL fOk = FALSE; if (dwThreadId != 0) { // Проверяем не установлен ли хук??? if(g_hhook != NULL) return fOk; // Если да, то выход ResetEvent(SwitcherEvent); // Устанавливаем хук на указанный в dwThreadId поток g_hhook = SetWindowsHookEx(WH_GETMESSAGE, GetMsgProc,g_hinstDll, dwThreadId); fOk = (g_hhook != NULL); if (fOk) // Ловушка успешно внедрена, теперь вызываем PostThreadMessage, чтобы // послать explorer сообщение, тогда ОС автоматически внедряет нашу // DLL в адресное пространство explorer и вызывает GetMsgProc fOk = PostThreadMessage(dwThreadId, WM_NULL, 0, 0); } else { // Проверяем установлен ли хук???? if(g_hhook == NULL) return FALSE; fOk = UnhookWindowsHookEx(g_hhook); // Отключаем DLL от explorer g_hhook = NULL; } return(fOk); } //////////////////////////////////////////////////////////////////////// BOOL APIENTRY DllMain( HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) { switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: // DLL привязана к какому-то потоку g_hinstDll = (HINSTANCE)hModule; break; case DLL_THREAD_ATTACH: // A new thread is being created // in the current process break; case DLL_THREAD_DETACH: // A thread is exiting cleanly break; case DLL_PROCESS_DETACH: // The calling process is detaching the // DLL from its address space break; } return TRUE; } //////////////////////////////////////////////////////////////////////// LRESULT CALLBACK GetMsgProc (int nCode, WPARAM wParam, LPARAM lParam) { static BOOL fFirstTime = TRUE; HWND hDlg; HANDLE SwitcherEvent; if (fFirstTime) { // DLL только что была внедрена в explorer fFirstTime = FALSE; // Открываем объект-событие для синхронизации с вызывающим // процессом SwitcherEvent=OpenEvent(EVENT_MODIFY_STATE,FALSE,"bullet"); if(SwitcherEvent==NULL) _INFO("Uppsss..","Error opening switcher event!!"); // Создаем скрытое окно диалога для возможности обмена сообщениями // с вызывающим процессом hDlg=CreateDialog(g_hinstDll, MAKEINTRESOURCE(IDD_SERVER_DIALOG), NULL, DlgProc); if(IsWindow(hDlg)) { // Сообщаем вызывающему процессу, что диалог создан и готов // принимать комманды SetEvent(SwitcherEvent); } } return (CallNextHookEx(g_hhook, nCode, wParam, lParam)); } //////////////////////////////////////////////////////////////////////// BOOL CALLBACK DlgProc(HWND hwnd, UINT uMsg,WPARAM wParam, LPARAM lParam) { switch (uMsg) { case WM_CLOSE: OnClose(hwnd); break; case WM_APP: HWND hwndLV,hwndDSPS; hwndDSPS = FindWindow(NULL, __TEXT("buLLet shortcut saver")); if (lParam==IDC_SAVE) { SendMessage(hwndDSPS,WM_APP,0,(LPARAM)IDC_SAVE); // Сообщить, что сохранение пошло SaveListViewItemPositions((HWND) wParam); // Сохранить позиции } if (lParam==IDC_RESTORE) { SendMessage(hwndDSPS, WM_APP, 0,(LPARAM)IDC_RESTORE); // Сообщить, что восстановление пошло RestoreListViewItemPositions((HWND) wParam); // Восстановить ярлыки } break; } return(FALSE); } //////////////////////////////////////////////////////////////////////// void OnClose(HWND hwnd) { DestroyWindow(hwnd); } //////////////////////////////////////////////////////////////////////// void SaveListViewItemPositions(HWND hwndLV) { int nItem, nMaxItems = ListView_GetItemCount(hwndLV); HKEY hkey; DWORD dwDisposition; LONG l = RegDeleteKey(HKEY_CURRENT_USER, g_szRegSubKey); l = RegCreateKeyEx(HKEY_CURRENT_USER, g_szRegSubKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, NULL, &hkey, &dwDisposition); for (nItem = 0; nItem < nMaxItems; nItem++) { TCHAR szName[1024]; POINT pt; ListView_GetItemText(hwndLV, nItem, 0, szName, 1024); ListView_GetItemPosition(hwndLV, nItem, &pt); l = RegSetValueEx(hkey, szName, 0, REG_BINARY, (PBYTE) &pt, sizeof(pt)); if(l != ERROR_SUCCESS) _INFO("OOooppss...","RegSetValueEX return ERROR"); } RegCloseKey(hkey); } //////////////////////////////////////////////////////////////////////// void RestoreListViewItemPositions(HWND hwndLV) { HKEY hkey; LONG l = RegOpenKeyEx(HKEY_CURRENT_USER, g_szRegSubKey, 0, KEY_QUERY_VALUE, &hkey); if (l == ERROR_SUCCESS) { int nIndex; DWORD dwStyle=(DWORD)GetWindowLong(hwndLV, GWL_STYLE); if (dwStyle & LVS_AUTOARRANGE) SetWindowLong(hwndLV, GWL_STYLE,dwStyle & ~LVS_AUTOARRANGE); l = NO_ERROR; for (nIndex = 0; l != ERROR_NO_MORE_ITEMS; nIndex++) { TCHAR szName[1024]; POINT pt; LV_FINDINFO lvfi; unsigned long cbValueName = 1024; LPDWORD lpcbValueName=&cbValueName; unsigned long cbData = sizeof(pt), nItem; LPDWORD lpcbData=&cbData; DWORD dwType; l = RegEnumValue(hkey, nIndex, szName, lpcbValueName, NULL, &dwType, (PBYTE) &pt, lpcbData); if (l == ERROR_NO_MORE_ITEMS) continue; if ((dwType == REG_BINARY) && (cbData == sizeof(pt))) { lvfi.flags = LVFI_STRING; lvfi.psz = szName; nItem = ListView_FindItem(hwndLV, -1, &lvfi); if (nItem != -1) { ListView_SetItemPosition(hwndLV, nItem, pt.x, pt.y); } } } SetWindowLong(hwndLV, GWL_STYLE, dwStyle); RegCloseKey(hkey); } }Ну вот вроде и все. Буду рад любым предложенным усовершенствованиям. Также с удовольствием приму все советы и дополнения. Ну и конечно с готовностью выслушаю любую критику, только весом не более 100кб :-)) Пишите!
Также прилагается полный проект для Visual C++ 6.0. Скачать
здесь
(скачано 9229 раз)
buLLet
Все документы и программы на этом сайте собраны ТОЛЬКО для образовательных целей, мы
не отвечаем ни за какие последствия, которые имели место как следствие использования
этих материалов\программ. Вы используете все вышеперечисленное на свой страх и риск. |
[network & security news] [RSS & Twitter] [articles, programing info] [books] [links, soft & more...] [soft archive] | [home] |
Underground InformatioN Center [&articles] |
2000-2015 © uinC Team |