Программа-невидимка

В последнее время интерес к программам-невидимкам снова возрос. В первую очередь это связано с появлением у рядовых пользователей WinXP. Эта ОСь, как известно, обладает всеми защитными особенностями линейки NT. И поэтому левые процессы стало "немножко" сложнее прятать от пользователя. Но и появление новых методов сокрытия присутствия существенно прибавилось ;). В данной статья я расскажу о новом способе "невидимости" (причём этот способ хорошо работает как в 9x, так и в XP). Суть его заключается в следующем: мы берём какую-либо программу, которая есть у более чем 90% пользователей и немножко изменяем её. (Из представленного ниже каркаса можно сделать всё что угодно!) Плюсы этого метода очевидны – раз заражённой нами прогой пользуются почти (а лучше без "почти") все, то на неё никто ничего плохого не подумает, к тому же наш кусок кода НИГДЕ НЕ БУДЕТ ВИДЕН. Это актуально особенно для XP, так как в ней куча недокументированных функций (в том числе и для работы с процессами) и NtQuerySystemInformation не самая "опасная" для нас в данной ОСи. Так что осталось только выбрать прогу приступить :).

Мой выбор пал на Explorer :). Он есть почти у всех счастливых обладателей виндовОза. Какую его часть мы будем мучить? Ну, например, посмотрим в левый нижний угол :). Да, именно часы станут нашей жертвой.

Для начала немного теории. Наша программка будет состоять из 3-х файлов. (Exe – 1 штука, DLL – 2 штука :)). Нашей задачей будет какая-либо вставка кода в "механизм часов". Лучшее для этого дела место это оконная процедура окна класса TrayClockWClass. После выбора жертвы всё становиться просто. Получается так: Exe будет всё это запускать, одна из ДЛЛок будет содержать хук и проникать в процесс Explorer’а, другая же – будет содержать его новую оконную процедуру. Для проникновения мы воспользуемся SetWindowsHookEx с параметром WH_GETMESSAGE... Но сначала посмотрим на экзэшник. Его целью будет загрузка ДЛЛки с хуком, затем мы подождём немного (sleep(1000)), и пошлём часам мессагу, чтобы попасть в их процесс.


uses  
 windows,messages,shellapi;  
  
{$R *.res}  
var h:integer;  
    FI:NOTIFYICONDATA;  
    i:integer;  
procedure RunStopHook(b:boolean);stdcall;external 'hdll.dll'; // проца в нашей DLL’ке с хуком.  
begin  
 RunStopHook(true);  
 h := FindWindowEx(0, 0, 'Shell_TrayWnd', nil);  
 h := FindWindowEx(h, 0, 'TrayNotifyWnd', nil);  
 h := FindWindowEx(h, 0, 'TrayClockWClass', nil);  
 sleep(1000); // что бы наша Dll’ка успела загрузиться.  
 postmessage(h,wm_paint,0,0);  
 zeromemory(@FI,sizeof(FI));  
 FI.cbSize:=sizeof(FI);  
 FI.szTip:='Hello temp';  
 FI.uFlags:=NIF_TIP;  
 FI.Wnd:=GetDeskTopWindow;  
 Shell_NotifyIcon(NIM_ADD,@FI); // у часов мы в дальнейшем поменяем отрисовку (для наглядности)  
 Shell_NotifyIcon(NIM_DELETE,@FI);  
end. 

Так-с. Теперь подумаем о реализации ДЛЛки с хуком. Процедура перехвата должна сверять хэндл часов с хэндлом перехватываемого message’а. Если они равны, то ДЛЛка в процессе Explorer’а. И тут мы уже можем менять процедуру окна часов. Но всё по порядку :).


library hdll;  
  
uses  
  SysUtils,  
  Classes,  
  windows,  
  messages;  
  
{$R *.res}  
  
var syshook:hhook; // переменная для хука  
  
procedure GetAndSet(h:integer);stdcall; external 'gas.dll'; // процедура из 2-ой ДЛЛки, которая заменит оконную процедуру часов.  
  
function CallWndProc(  
    nCode:integer ; // hook code  
    wParam:    WPARAM ; // current-process flag  
    lParam:    LPARAM   // address of structure with message data  
    ):LRESULT;stdcall;  
var h:integer;  
    ok:boolean; // переменная влияющая на снятие хука.  
                // т.е. показывающая, что оконная процедура часов изменена)  
begin  
 ok:=false;  
 H := FindWindowEx(0, 0, 'Shell_TrayWnd', nil);  
 H := FindWindowEx(H, 0, 'TrayNotifyWnd', nil);   
 // все пэрэнты часов можно узнать с помощью Spy++  
 // (а любителей кодинга отсылаю к MSDN GetParent & WindowFromPoint)  
 if tmsg(pointer(lparam)^).hwnd=H then   
  begin  
   h := FindWindowEx(H, 0, 'TrayClockWClass', nil); // получаем хэндл часов  
   loadlibrary('gas.dll'); // загружаем 2-ую ДЛЛку (чтобы она висела в процессе Explorer’а)  
   GetAndSet(h); // меняем ему процедуру  
   Invalidaterect(h,nil,false); //sendmessage(h,wm_paint,0,0);  
   ok:=true;  
  end;  
 result:=CallNextHookex(syshook,ncode,wparam,lparam);  
 if ok then   
  UnHookWindowsHookEx(syshook); // отключаем хук  
end;  
  
procedure RunStopHook(b:boolean);export;stdcall;  
begin  
 if b   
  then SyShook:=Setwindowshookex(WH_GETMESSAGE,@callWndProc,Hinstance,0)  
  else unhookwindowshookex(syshook);  
 if (syshook=cardinal(-1)) or(syshook=cardinal(0)) then  
  messagebox(0,'Suxx','',mb_ok);  
end;  
  
exports RunStopHook;  
  
begin  
end.  

Теперь самое интересное – оконная процедура часов. Её можно модифицировать для чего угодно: это может быть и героический житель трои, и клавиатурный шпион, и просто фенка (её, то, я и покажу) . При замене оконной процедуры мы создадим шрифт и им будем выводить время ежесекундно. Так же мы не должны забывать и о старой оконной процедуре, ведь она тоже выполняет не мало функций! (например вызов окна по двойному щелчку на часах и popup по правой кнопке...)


library gas;  
  
uses  
  SysUtils,  
  Classes,windows,messages,shellapi;  
  
{$R *.res}  
var SavedProc:pointer;  
    f:integer;  
procedure MyDraw(h:hwnd); // процедура "канвасинья"  
 var s:array[0..20] of char;  
 time:_systemtime;  
begin  
 s:='hh'':''mm'':''ss'; // маска времени  
 SetTextColor(h,$ff0100); // установка цвета текста  
 selectObject(h,f);  
 GetLocalTime(time);  
 GetTimeFormat(LOCALE_USER_DEFAULT,TIME_FORCE24HOURFORMAT,@time,s,s,21); // форматируем строку со временем  
 TextOut(h,0,0,@s[0],8); // Выводим строку  
end;  
  
function WinProc(hWnd: HWND; Msg: UINT;  wParam: WPARAM;  lParam: LPARAM): LRESULT; stdcall;  
 var   
  http:integer;  
  pp:PAINTSTRUCT;  
begin  
 case msg of  
  WM_PAINT: begin // перехват и обработка  
   http:=beginPaint(hwnd, pp);  
   MyDraw(http);  
   endpaint(hwnd,pp);  
   result:=0;  
  end;  
  wm_timer: begin  
   http:=getdc(hwnd);  
   MyDraw(http);  
   releasedc(hwnd,http);  
   result:=0;  
  end;  
  WM_USER+100: result:=195 +(20 shl 16); // эта фишка оконной процедуры часов.  
                                         // При этом message’е винда ожидает получить ответ о размере часов.  
  else result := CallWindowProc(SavedProc,hwnd,msg,wparam,lparam); // если мессага не наша, то пусть её   
                                                                   // обработает старый обработчик  
 end;  
end;  
  
procedure GetAndSet(h:integer);stdcall;  
var  
 p,p2:Trect;  
 hand,h2:integer;  
begin  
 if pointer(getwindowlong(h,GWL_WNDPROC))<>@winProc then   
  begin// эта фишка, служет для того чтобы не наделать лишних проц. :]  
   SavedProc:=pointer(SetWindowLong(h,GWL_WNDPROC,cardinal(@Winproc)));  
   SetTimer(h,0,1000,nil); // создаём таймер   
   f := CreateFont(20,25,0,0,FW_THIN,1,1,0,RUSSIAN_CHARSET,OUT_CHARACTER_PRECIS, CLIP_DEFAULT_PRECIS,  
                   DEFAULT_QUALITY ,FF_MODERN ,nil); // Создаём шрифт  
 end;  
end;  
  
exports GetAndSet;  
begin  
end.  

Приведённую выше процедуру отрисовки хорошо бы использовать для работы с асинхронными сокетами :). На этом пока всё.

(to be continued...)
Теги:
скрыть
Добавлено: 21 Июля 2018 12:25:22 Добавил: Андрей Ковальчук Нравится 0
Добавить
Комментарии:
Нету комментариев для вывода...