![]() |
![]() ![]() |
![]() |
FreeMan |
![]() ![]()
Сообщение
#1
|
- ![]() ![]() ![]() ![]() Группа: Пользователи Сообщений: 480 Пол: Мужской Репутация: ![]() ![]() ![]() |
Почти каждый, кто изучает язык ассемблера, рано или поздно пишет вирус, некоторые люди пишут вирус, когда заканчивают изучать какой-нибудь язык программирования... Прежде чем читать то, что я буду писать ниже и понимать хоть что-нибудь, вы должны:
а) знать основные команды ассемблера б) уметь пользоватся АПИ-функциями в) взять где-нибудь (можно и у меня) TASM32 (можно и другой, но каждый компилятор имеет свои особенности). г) отладчик (если собираетесь собственноручно создать зверька, то без отладки довольно трудно найти ошибки) д) прогу, которая прикреплена (на неё вопит касперский, но это не вирус!!!! ) е) иметь здоровую голову (если вы хотите испортить все компы на Земле, то ваше место в больнице, а не здесь) ё) ПОМНИТЬ, ЧТО ЭТОТ МАТЕРИАЛ ПРЕДСТАВЛЕН ТОЛЬКО В ЦЕЛЯХ ОБУЧЕНИЯ, И ЗА ПОСЛЕДСТВИЯ Я НИКАКОЙ ОТВЕТСТВЕННОСТИ НЕ НЕСУ Вроде всё. Теперь план обучения: 1) формат заголовка файла РЕ 2) разбор основных полей заголовка РЕ 3) методика заражения 4) дельта-смещение. 5) поиск АПИ 6) разбор используемых АПИ 7) пишем код 8) Reserved ![]() Прикрепленные файлы -------------------- бб
|
FreeMan |
![]()
Сообщение
#2
|
- ![]() ![]() ![]() ![]() Группа: Пользователи Сообщений: 480 Пол: Мужской Репутация: ![]() ![]() ![]() |
1. Формат заголовка РЕ
Заголовок - это структура, которая содержит информацию, которая требуется загрузчику для загрузки того или иного файла. Мы рассмотрим формат заголовка РЕ-ЕХЕ. Расширение .ЕХЕ имеют не только РЕ-ЕХЕ файлы, но ещё и старые досовские. В связи с этим в самом начале файла идёт заголовок, который полностью досовскому загрузчику и, в некоторых случаях, dos stub, прога, которая запускается, если стартовать РЕ файл из-под доса. Она в основном кричит что-то типа "This programm must cannot be run in DOS mode". Мы пишем вирус под Винду, поэтому нас дос-совместимый заголовок особо не интересует. Только пара полей Смещение (offset) Размер Описание +0h 1 w (2байта) 'MZ' сигнатура ЕХЕ файла +3Сh 1 dw (4 байта) смещение начала РЕ заголовка Вот мы и увидели, как проверить файл на "подлинность" (сигнатура). Кстати, если вы откроете command.com в каком-нибудь НЕХ-редакторе, то вы увидете, что это на самом деле не СОМ, а ЕХЕ ![]() Формат заголовка РЕ висит в прикреплённом файле. Советую распечатать. Прикрепленные файлы ![]() -------------------- бб
|
FreeMan |
![]()
Сообщение
#3
|
- ![]() ![]() ![]() ![]() Группа: Пользователи Сообщений: 480 Пол: Мужской Репутация: ![]() ![]() ![]() |
2. Разбор основных полей РЕ заголовка.
Итак, вы просмотрели вложения. Теперь расскажу подробнее о тех полях заголовка, которые мы будем использовать во время написания вируса. Как вы заметили, самое первое поле заголовка - сигнатура. Это уже проверка файла на РЕ. Тип компа нам не интересен. В файле мы имеем дело с несколькими секциями, такими как, например, секция кода или секция данных. Количество этих секций указано по смещению 6 заголовка РЕ. В файле находится таблица объектов (Object Table), элементы которой описывают секции. Мы будем работать с этими элементами. Делать это будем в цикле с заданным кол-вом повторений. Значение поля Number Of Sections и будет кол-вом этих повторений. Дальше нам понадобится поле Size Of Optional Header. Оно понадобится при расчёте смещения (offset) Object Table. Следующее поле, которое нас сильно интересует - Address Of Entry Point по смещению 28h от начала РЕ-заголовка (далее просто заголовок). Оно показывает загрузчику место старта (если это можно так назвать) проги. Значение этого поля - только RVA точки старта. Теперь несколько слов о том что такое RVA, VA... Сразу скажу, что надо просто взять и выучить, что есть что и понять как одно от другого отличается. Мне было очень сложно разобраться с этими понятиями. RVA расшифровывается как Relative Virtual Address - это смещение на что-либо относительно того места в памяти, куда загрузчик закидывает файл. Ведь файл не располагается с нулевого смещения... VA (Virtual Address) - это уже смещение, с которым мы можем работать. Теперь всё это на примере. Итак, загрузчик потрудился на славу и закинул наш файл по смещению 00040000h в память. RVA точки входа 00001000h. Ясно, если загрузчик передаст управление на смещение 00001000h, то ничего полезного не произойдёт, ведь это только RVA. Чтоб сделать из RVA VA нужно прибавить к нему 00040000h (так называемую базу образа). Прибавляем и получаем 00041000h, а это адрес точки входа (VA). Мы в основном будем получать везде RVA, и нам прийдётся преобразовывать его в VA. Виртуальные данные - термин, который служит для обозначения данных, которые висят в памяти. RAW-данные - данные, которые находятся в файле. Расположение данных в памяти и в файле отличается. Так, например, в файле код расположен по смещению 600h, в память их загрузчик может кинуть по смещению 1000h, относительно адреса загрузки (RVA). Следующее поле заголовка которое нас интересует - Image Base (00000034h). Это и есть то смещение, начиная с которого файл располагается загрузчиком в памяти. Понадобится при передаче управления зараженному объекту. Section Alignment и File Alignment - значения, на которые надо будет выровнять некоторые значения после заражения. Выравнивание - это округление какого-либо значения в большую сторону до значения, кратного выравнивающему фактору. Например, объём кода 2CDh, а File Alignment=200h (это фактор), тогда выровненное значение будет 400h. Цитата При выравнивании можно воспользоваться такой формулой: (x+(y-1))&(~(y-1)), где, x-выравниваемое значение y-выравнивающий фактор Уточнение: выравнивающий фактор должен быть степенью двойки, иначе формула не будет иметь смысла. Т.к. содержимое полей Object Align и File Align по утверждению Microsoft являются степенями двойки, мы можем смело использовать данную формулу. Хмм, это на первый взгляд выглядит сложно, на практике все просто и ясно. ;------------------------------Пример Align.asm-------------------------------- Скомпилируйте и посмотрите в отладчике, меняйте значения. Все встанет на свои места. цитата с http://wasm.ru/article.php?article=pe_inf Дальше по списку... ![]() Major Image Version и Minor Image Version - а эти поля я буду использовать как метку на зараженность, не надо ведь заражать один и тот же файл по нескольку раз, одного достаточно. ImageSize - размер загружаемого образа. Загрузчик следит за выполнением такого равенства HeaderSize (54h) + Сумма(VirtualSize[i], i) == ImageSize (50h) (все значения выровнены по ОbjAlign). Иначе визжит, что файл не является приложением Вин32. HeaderSize - из описания ясно. Вроде с полями ясно всё, если что-нибудь вспомню, расскажу в процессе. Если вам что-либо не понятно, можете спрашивать в РМ или асю. -------------------- бб
|
FreeMan |
![]()
Сообщение
#4
|
- ![]() ![]() ![]() ![]() Группа: Пользователи Сообщений: 480 Пол: Мужской Репутация: ![]() ![]() ![]() |
3. Методика заражения
Пишу в виде алгоритма, хотя я не умею их делать. Пишу с того момента, когда мы отловили адреса апишек, после всех приготовлений (об этом ниже). 1) ищем файл 2) открываем, проверяем на зараженность, если всё ОК, то идём дальше, если нет то на шаг 8 3) ищем последнюю секцию 4) пишем код ей в зад 5) фиксим некоторые поля заголовка и соответствующего элемента Object Table 6) устанавливаем метку заражения 7) закрываем 8) заразили достаточно, на шаг 10, нет - дальше 9) ищем следующий, валим на шаг 2 10) если первое поколение то просто выходим, если нет, то передаём управление носителю Что-то типа этого. На практике разберётесь (на самом деле всё сложнее немного). Продолжу, если это будет хоть кому-нибудь интересно. Кому интересно или если вы заметили какие-то ошибки или недочёты, то пишите в PM или стучите в асю 88880172, выражайте свои мысли. -------------------- бб
|
FreeMan |
![]()
Сообщение
#5
|
- ![]() ![]() ![]() ![]() Группа: Пользователи Сообщений: 480 Пол: Мужской Репутация: ![]() ![]() ![]() |
4. Дельта смещение.
При линковке программы происходит замена имён меток, переменных на их адреса в памяти. Таким образом строка mov eax, offset message превращается в mov eax, xxxxxxxx где xxxxxxxx - смещение переменной message. Для примера набейте такую прогу и сохраните в папке с ТАСМом: includelib import32.lib Скомпилируйте её. Для компиляции создайте ВАТ-файл в папке с ТАСМом и заполните его следующим содержимым: Tasm32.exe /m3 /ml /zi iasdf.asm , , ; В данном случае iasdf.asm - имя файла примера. Запустите ВАТ файл. В результате в папке появится файл iasdf.exe. Если вы посмотрите в отладчике этот файл, то увидите что-то типа:
То есть аааа - это место в памяти. Теперь посмотрим на это более внимательно... Программа, которую мы написали выше, будет выполнятся без проблем из-за того, что будет грузится с одного и того-же адреса в памяти (поле ImageBase заголовка) и после запуска в eax будет заноситься значение по адресу 0040100C. Когда тело вируса находится в конце заражаемого файла, в память его, скорее засунут тоже не в начало. Допустим, мы записали вирус (допустим это вышенаписанная прога), в конец файла. Файл имеет такую структуру в памяти: Секция смещение(VA) размер Так как мы в конце файла, то, скорее всего и в последней секции. Допустим, она была пустая, когда мы поселились, тогда у нас будет такая картина: ... Неувязка - переменная оказалась по адресу 0040400С, а в регистр попадает чёрти-что по смещению 0040100C. Проблема эта решается нахождением так называемого дельта смещения. Это значение, на которое отличается значение адреса при линковке от того, которое получилось в силу тех или иных обстоятельств. В нашем случае адреса изменились на 00404000-0401000=3000. Это и есть дельта. Как её использовать для получения реального адреса - 0401000+3000=00404000, просто добавить к обычному адресу. -------------------- бб
|
FreeMan |
![]()
Сообщение
#6
|
- ![]() ![]() ![]() ![]() Группа: Пользователи Сообщений: 480 Пол: Мужской Репутация: ![]() ![]() ![]() |
3.1 В поисках дельты.
Может вам показалось, что поиск дельты - основная сложность в написании вируса... Это не так. Это самая маленькая его часть, это даже не сложность. Как же найти дельту? Очень просто, надо взять произвольную метку и от её текущего адреса отнять тот, который был сразу после линковки. Вопрос... Как узнать тот адрес, который был при линковке? Напишите mov eax, metka_nameи скомпилируйте. В регистр всегда будет попадать (при любых обстоятельствах), адрес метки, который был изначально (как и в случае с переменной, ведь её адрес тоже оставался без изменения) Второй вопрос... Как узнать адрес, который имеет метка сейчас? А вот для этого придётся извратится... Все знают (или узнают), что при вызове функции в стек попадает адрес возврата из функции... То есть, если мы сделаем call some_funcто в стеке окажется адрес команды, которая находится за этой. А если мы знаем "обычный" адрес этой команды, то мы можем найти дельту. call delta ;вызов процедуры, в стеке текущий адрес меткиВ итоге в регистре ebp висит дельта. Теперь, если мы напишем mov eax,[ebp+aaaa], то получим значение переменной аааа, где бы она не валялась вместе со всей прогой ![]() -------------------- бб
|
FreeMan |
![]()
Сообщение
#7
|
- ![]() ![]() ![]() ![]() Группа: Пользователи Сообщений: 480 Пол: Мужской Репутация: ![]() ![]() ![]() |
5) Поиск АПИ.
Когда Винда загружает файл, она в адресное пространство кидает библиотеки, адреса имён которых содержатся в таблице импорта файла. Потом заполняет какие-то таблицы адресами АПИшек. При чём эти таблицы фиксированы. Вспомним нашу прогу(её вид в отладчике):
Это вызов АПИ функции ExitProcess из KERNEL32.dll. Неужели вы думаете, что кернел кидают сразу за файл с его функциями??? Нет, просто мы прыгаем на таблицу, а там в определённом поле (смещение 00401010) висит адрес этой функции. Но если мы заразим файл, то там не обязательно будет такая-самая таблица. Ещё меньше вероятность того, что эта таблица содержит адреса всех нужных нам АПИшек. То есть мы прыгнем по тому адресу, а там окажется фигня какая-то. Кстати вот, что видит дизассемблер по смещению 00401010 * Reference To: KERNEL32.ExitProcess, Ord:0000h | :00401010 FF2530304000 Jmp dword ptr [00403030] Вот так. То есть для того, чтоб нам в вирусе использовать АПИ, их адреса нужно найти вручную, то есть, "подражая" загрузчику, найти адреса, забить их себе в "самопальную" таблицу. Сделать это можно многими способами:
Я остановлюсь на 3 варианте. В 1ом есть шанс провалится, во 2ом ИМХО эвристик заставит антивируса визжать. Я то на нём остановился. Но тут возникает проблема - где этот кернел висит???? Это действительно вопрос!!!!! Адрес кернела тоже надо искать. -------------------- бб
|
FreeMan |
![]()
Сообщение
#8
|
- ![]() ![]() ![]() ![]() Группа: Пользователи Сообщений: 480 Пол: Мужской Репутация: ![]() ![]() ![]() |
5.1. Поиск адреса кернела
Кернел висит в памяти. Искать кернел можно многими путями. Я предпочитаю поиск через анализ SEH. SEH это фигня, которая служит для обработки исключений (непредвиденных ситуаций). Теперь теория По fs:0 начинается некоторая структура, называемая Thread Information Block (TIB). Первое поле - указатель на начало цепочки структур EXCEPTION_REGISTRATION_RECORD, каждая из которых содержит адрес процедуры обработки критической ситуации (SEH) и адрес следующей (т.е. предыдущей) структуры, этих обработчиков несколько. То есть если возникает непредвиденная ситуация, то по очереди вызываются эти обработчики, пока один из них не возьмёт на себя обработку исключения. Так вот последний обработчик висит где-то в кернеле. Так как он последний, то адрес следующего будет 0ffffffffh. Теперь предлагаю написать код поиска кернела. xor edx,edx Адреса кернела, в принципе, известны для некоторых версий винды 077e60000h в ХР 0BFF70000h в Win9x В принципе шанс не найти кернел очень маленький (практически отсутствует), поэтому можно и без проверки на РЕ-сигнатуру справится. Посмотрите это в отладчике и всё будет Ok. -------------------- бб
|
FreeMan |
![]()
Сообщение
#9
|
- ![]() ![]() ![]() ![]() Группа: Пользователи Сообщений: 480 Пол: Мужской Репутация: ![]() ![]() ![]() |
5.2 Поиск АПИ...
Теперь адрес кернела мы знаем. Теперь будем искать адреса API-шек. В кернеле есть таблица экспорта её RVA находится по смещению 78h относительно заголовка РЕ. Там начиная со смещения 1Ch идут такие элементы:
Теперь код. get_export: -------------------- бб
|
FreeMan |
![]()
Сообщение
#10
|
- ![]() ![]() ![]() ![]() Группа: Пользователи Сообщений: 480 Пол: Мужской Репутация: ![]() ![]() ![]() |
6. Pазбор используемых АПИ
Разбор сводится к копированию сюда содержимого справочника АПИ и более подробному их рассмотрению, то есть в этом разделе мы не будем придумывать ничего, никакого кода. Зато когда мы разберём АПИ, можно будет приступать к написанию кода вируса. Все приведённые здесь АПИ находятся в кернеле. Все попытки включить в список АПИ из другой библиотеки или с неправильным именем приведёт к ошибке и вы с треском вылетите. Итак, первая АПИ - GetWindowsDirectoryA Цитата UINT GetWindowsDirectory( lpBuffer - буфер, куда будет заносится строка, которая содержит путь к директории винды (C:\Windows типа этого) uSize - размер этого буфера (число от 0 до MAX_PATH) Использование: push Some_lenthКак вы заметили, всё делалось с учётом дельты. SetCurrentDirectoryA - устанавливает текущую директорию процесса Цитата BOOL SetCurrentDirectory( lpPathName - адрес строки с завершающим нулём, которая содержит путь к директории, которую нужно сделать текущей для текущего процесса. Использование: lea edi,[ebp+offset szWindowsDirectory] CreateFileA - крутая АПИ. Умеет файлы открывать. Цитата The CreateFile function creates or opens the following objects and returns a handle that can be used to access the object: · files · pipes · mailslots · communications resources · disk devices (Windows NT only) · consoles · directories (open only) HANDLE CreateFile( lpFileName - указатель на строку с именем файла dwDesiredAccess - тип доступа к объекту dwShareMode - флаг который паказывает каким образом можно юзать объект lpSecurityAttributes - чё то там связано с дочерними процессами - ставим 0 dwCreationDistribution - как создавать (открыть если существует, создать...) dwFlagsAndAttributes - с какими атрибутами файл, который открываем hTemplateFile - какой то вспомогательный файл Использование: xor eax,eax Возвращаемые значенния: Если успешно, то возвращает уникальный описатель (хендл) открытого объекта, если нет, то -1. -------------------- бб
|
FreeMan |
![]()
Сообщение
#11
|
- ![]() ![]() ![]() ![]() Группа: Пользователи Сообщений: 480 Пол: Мужской Репутация: ![]() ![]() ![]() |
FindFirstFileA - ищет файл в текущей директории
Цитата HANDLE FindFirstFile( lpFileName - маска поиска lpFindFileData - указатель на структуру WIN32_FIND_DATA (WFD) Результат работы - если успешно, то возвращает хендл поиска, который нужен при использовании таким функциям как FindNextFile. Если провал, то возвращает -1. Использование: lea eax,[ebp+offset WFD32] Структура для поиска WFD: WFD32: -------------------- бб
|
FreeMan |
![]()
Сообщение
#12
|
- ![]() ![]() ![]() ![]() Группа: Пользователи Сообщений: 480 Пол: Мужской Репутация: ![]() ![]() ![]() |
FindNextFileA - ищет следующий файл
Цитата BOOL FindNextFile( hFindFile - хендл, который возвратила ф-ия FindFirstFileA lpFindFileData - указатель на WFD Возвращает: если успех, то заполняет WFD новыми значениями и возвращает не ноль. Использование: lea eax,[ebp+offset WFD32] ;указатель на структуру CreateFileMappingA - функция, которая создаёт файловый мэппинг Цитата HANDLE CreateFileMapping( hFile - хендл файла для мэппирования lpFileMappingAttributes - указатель на какую-то структуру, у нас ноль. flProtect - защита файла. Ставим PAGE_READWRITE=00000004 dwMaximumSizeHigh - старшая половина размера мэппируемого файла dwMaximumSizeLow - младшая lpName - имя объекта Возвращает: если успех - хендл, если нет - 0 Использование: mov eax,[ebp+hFO] -------------------- бб
|
FreeMan |
![]()
Сообщение
#13
|
- ![]() ![]() ![]() ![]() Группа: Пользователи Сообщений: 480 Пол: Мужской Репутация: ![]() ![]() ![]() |
MapViewOfFile - помещает промэппированный файл в память.
Цитата LPVOID MapViewOfFile( hFileMappingObject - хендл, который остался от CreateFileMappingA dwDesiredAccess - тип доступа ставим SECTION_MAP_WRITE + SECTION_MAP_READ=2+4 dwFileOffsetHigh и dwFileOffsetLow - размер, если ноль, то столько, сколько в CreateFileMappingA dwNumberOfBytesToMap - сколько байтов фигачить в память, если 0, то все. Возвращает: если успех - адрес начала области памяти, куда всё это поместилось. Если нет - 0 Использование: xor edx,edx -------------------- бб
|
FreeMan |
![]()
Сообщение
#14
|
- ![]() ![]() ![]() ![]() Группа: Пользователи Сообщений: 480 Пол: Мужской Репутация: ![]() ![]() ![]() |
UnmapViewOfFile - полная противоположность MapViewOfFile.
Цитата BOOL UnmapViewOfFile( lpBaseAddress - адрес, который возвратила MapViewOfFile. Возвращает: не ноль, если всё ок. Использование: push [ebp+pFM] ; адрес, который достаём с переменной SetFileAttributesA - устанавливает аттрибуты файла. Цитата BOOL SetFileAttributes( lpFileName - адрес строки, содержащей имя файл. dwFileAttributes - атрибуты, которые надо установить, у нас FILE_ATTRIBUTE_NORMAL Возвращает: всё ок - не 0. Использование: lea eax,[ebp+offset FName] ; указатель на имя (берём из WFD) CloseHandle - настолько-же крутая АПИ, насколько CreateFile. Она закрывает объект. Цитата Remarks The CloseHandle function closes handles to the following objects: · Console input or output · Event file · File mapping · Mutex · Named pipe · Process · Semaphore · Thread · Token (Windows NT only) BOOL CloseHandle( hObject - хендл объекта, который надо закрыть. Этой ф-ией будем закрывать мэппинг и файл. Возвращает не 0, если успех. FindClose - закрывает хендл поиска. Цитата BOOL FindClose( hFindFile - хендл, еоторый остался после использования FindFirstFileA Возвращает не 0, если успех. Использование: push dword ptr [ebp+offset hFF]; хендл, который достаём с переменной SetComputerNameA - устанавливает имя компа. Это собственно в виде полезной нагрузки. Цитата BOOL SetComputerName( lpComputerName - указатель на новое имя компа. Возвращает не 0, если успех. Использование: lea edi,[ebp+offset NewComp] ; указатель на строку с новым именем Это тот набор АПИ, который мы будем использовать при заражении. В первом поколении мы ещё заюзаем MessageBoxA & ExitProcess, но я думаю их описывать не стоит, ведь "Привет, мир" в винде пишут обычно с использованием этих АПИ. Теперь надо начинать детально рассказывать вам о заражении, описать ещё несколько структур РЕ файла, а после этого объяснить весь код вируса. -------------------- бб
|
FreeMan |
![]()
Сообщение
#15
|
- ![]() ![]() ![]() ![]() Группа: Пользователи Сообщений: 480 Пол: Мужской Репутация: ![]() ![]() ![]() |
7. Пишем код
В исполняемый файл добавляем код вируса. Этим действием мы увеличиваем "длину" файла на "длину" вируса. Если такой файл запустить, то, скорее всего, вы увидите сообщение о том, что файл не является приложением под винду. Это происходит из-за того, что длина файла больше, чем та, которая указана в заголовке. Если мы увеличим величину Size of Image на длину вируса (которую выровняем на SectionAlignment), то опять получим сообщение об ошибке. В чём же дело, ведь все поля заголовка исправлены на нужные? Дело в том, что в файле есть ещё несколько структур, которые надо пофиксить. РЕ файл поделен на секции (секция кода, данных...). Для каждой секции есть структура, которая описывает её (object entry). Все структуры находятся одна за другой за заголовком и имеют такой формат: Object Entry: = 28h bytes Я пометил * те поля, которые нас больше всего интересуют. Виртуальный размер секции - это размер секции (когда она загружена в памяти), выравненный по SectionAlignment. Если мы записали в последнюю секцию код, то должны увеличить это поле для последней секции (не для каждой секции). Кстати, загрузчик контролирует выполнение равенства HeaderSize+Summa(VirtualSize[i],i)=Size Of Image (все значения выровнять по SectionAlignment) Section RVA - это адрес (RVA относительно ImageBase) начала секции, когда она загружена в память. Используется для нахождения новой точки входа Physical Size - размер секции, когда она в файле. Выровненное по File Alignment. Должно быть увеличено на длину виря, выровненную по File Alignment Physical Offset - смещене cекции относительно начала файла. Используем для поиска секции в файле. Object Flags - флаги. Могут иметь следующие значения или их комбинацию. Object Flags: *00000020h Секция содержит программный код 00000040h Секция содержит инициализированные данные 00000080h Секция содержит неинициализированные данные *20000000h Секция является исполняемой (см. флаг 00000020h) 40000000h Секция только для чтения *80000000h Секция может использоваться для записи и чтения Мы же будем устанавливать это поле в 0A0000020h (это комбинация отмеченных полей). Кстати pewrsec.exe, который я прикрепил в начале туториала, изменяет флаги всех секций на 0A0000020h, что позволяет нам работать с переменными, которые находятся в секции кода (и чего на него так ругаться?). Если боитесь использовать эту программу, то можете сделать для этого свою (когда мы закончим писать вирус вы будете в состоянии это сделать самостоятельно, хотя по просьбам трудящихся могу накодить и выложить код). -------------------- бб
|
FreeMan |
![]()
Сообщение
#16
|
- ![]() ![]() ![]() ![]() Группа: Пользователи Сообщений: 480 Пол: Мужской Репутация: ![]() ![]() ![]() |
То есть, для успешного заражения надо пофиксить ещё и вышеописанную структуру для секции, которую заменили. Это Сложность №1.
Сложность №2 - нахождение новой точки входа (RVA нашего кода относительно ImageBase). Тут всё просто. Мы пишемся в конец секции? RVA секции + Virtual Size = новый RVA!!!! Думаю с этим вы сами разберётесь. Сложность №3. Передача управления носителю. Тут всё ещё проще. Адрес старой точки входа мы знаем (RVA относительно ImageBase), ImageBase тоже знаем, тогда для корректной передачи управления нам нужно сделать Jump на старую точку, для чего надо знать её VA=RVA + ImageBase (это вам дельту не напоминает?) Сложность №4. Определение носителя первого поколения. Как известно, дельта первого поколения равна 0. Ведь в первом поколении нам не надо передавать управление носителю. Сложность №5. Самое сложное - распихать всё, что нам нужно по переменным так, чтоб потом найти. При работе с переменными не забывайте учитывать дельту. Сложность №6. Проверить работу, довести всё до ума. Посмотреть под отладкой, посмотреть как размножается (как быстро). Подсунуть другу (когда знаете, что работает и не портит ничего), прийти к нему через неделю, посмотреть, как всё отработано, сколько заражено. Потом, если не лень, оптимизировать (наш вирус не будет блистать оптимальностью и скоростью распространения (версия, где это будет сделано находится на стадии разработки), это сделано для того, чтоб вам было чем заняться). Не бойтесь за свой комп. Первые версии тестируйте на дискетах или в отдельных папках. Когда уверенны, что вирус не портит ничего, можете добавить "полезную нагрузку" - то, что вирус делает помимо заражения (вирус, который будет у нас, будет менять имя компа). Если вы боитесь вируса, который написали (боитесь его пускать погулять у себя на компе), то это: а) вирус, который убивает систему, зануляет биос, сжигает монитор... В этом случае обратитесь к психиатру, вы опасный для общества человек б) нежелание переустанавливать систему в случае ошибки, боязнь потерять данные... Тогда вам надо бороться с ленью, записать самые важные данные на болванки или туда, где их ничего не достанет или прекратить писать вирусы, удалить все исходники вирусов с компьютера. Всё остальное расскажу в комментариях к коду. -------------------- бб
|
FreeMan |
![]()
Сообщение
#17
|
- ![]() ![]() ![]() ![]() Группа: Пользователи Сообщений: 480 Пол: Мужской Репутация: ![]() ![]() ![]() |
7.1 Пишем код
Для разминки напишем прогу, которая определяет адрес Кернела на той системе, где она запущена. includelib import32.lib Можете компилировать и юзать. для компиляции: Tasm32.exe /m3 /ml /zi iasdf.asm , , ; Tlink32.exe /Tpe /aa /v iasdf, iasdf, ,import32.lib iasdf - имя проги юзать: запускать файл, в нашем случае iasdf.ехе. Если заметите ошибки в коде (или материале) - пишите, стучите, звоните... Просто писал перевод в символы без проверки (нет компилятора), используя не самый лучший алгоритм (просто он простой для понимания:)) Поюзав эту прогу на нескольких компах с разными операционками вы увидите, что база кернела вполне зафиксированное значение для каждой операционки. -------------------- бб
|
FreeMan |
![]()
Сообщение
#18
|
- ![]() ![]() ![]() ![]() Группа: Пользователи Сообщений: 480 Пол: Мужской Репутация: ![]() ![]() ![]() |
Кстати, вышел номер 29А... http://www.vx.netlux.org/29a/main.html
-------------------- бб
|
FreeMan |
![]()
Сообщение
#19
|
- ![]() ![]() ![]() ![]() Группа: Пользователи Сообщений: 480 Пол: Мужской Репутация: ![]() ![]() ![]() |
Теперь пришло время писать код.
includelib import32.lib продолжение ниже Сообщение отредактировано: volvo - 26.01.2009 17:45 -------------------- бб
|
FreeMan |
![]()
Сообщение
#20
|
- ![]() ![]() ![]() ![]() Группа: Пользователи Сообщений: 480 Пол: Мужской Репутация: ![]() ![]() ![]() |
ls_found: исходник лежит в прикреплённом архиве (кодировка - Cyrillic Windows). компилить: Tasm32.exe /m3 /ml /zi instan.asm , ,; Прикрепленные файлы ![]() -------------------- бб
|
![]() ![]() |
![]() |
Текстовая версия | 18.08.2024 16:10 |