LIMB
Вход Регистрация

тема

Введение в FASM. Путаем DIE

skeet · · 11 ответов · 565 просмотров

Введение в ассемблер FASM​

Здравствуйте дорогие форумчане, это будет вводная статья в ассемблер, а именно FASM.
Почему именно FASM, а не например MASM, NASM, TASM?
По моему личному мнению FASM является более удобным чем остальные: FASM подходит под маленькие приложения, MASM для создания драйверов под Windows, а NASM как конкурент GAS в Linux.
Надеюсь вы получили ответ на этот вопрос, теперь - что такое DIE, и как он работает?

Спойлер: Информация про DIE
Detect It Easy (DiE) — это мощный инструмент для определения типа файлов, популярный среди аналитиков вредоносного ПО, экспертов в области кибербезопасности и реверс-инженеров по всему миру. Поддерживая как основанный на сигнатурах, так и эвристический анализ, DiE обеспечивает эффективную проверку файлов на широком диапазоне платформ, включая Windows, Linux и MacOS. Его адаптируемая, управляемая скриптами архитектура обнаружения делает его одним из самых универсальных инструментов в этой области с обширным списком поддерживаемых образов ОС.
Это оффициальная информация с гитхаба самого DIE

Но, как же он работает? - Зайдя в папку db - PE - Можно увидеть большое количество обфускаторов/протекторов и прочего мусора но сейчас нас интересует пакер UPX

Спойлер: Нахождение UPX
// Detect It Easy: detection rule file

// Authors: ajax, adoxa, DosX

meta("packer", "UPX");

function isPatchedUPX() {

    var isDetected = 0,

        nNumberOfFunctions = PE.getNumberOfImportThunks(0);

    if (nNumberOfFunctions > 1 && nNumberOfFunctions < 7) {

        if (PE.getSizeOfCode() && PE.getSizeOfUninitializedData() && PE.section.length > 2 && PE.section.FileSize == 0) {

            var funcCounter = 0;

            if (PE.getImportFunctionName(0, 0) == "LoadLibraryA") {

                funcCounter++;

            }

            if (PE.getImportFunctionName(0, 1) == "GetProcAddress") {

                funcCounter++;

            }

            if (nNumberOfFunctions == 4) {

                if (PE.getImportFunctionName(0, 2) == "VirtualProtect") {

                    funcCounter++;

                }

                if (PE.getImportFunctionName(0, 3) == "ExitProcess") {

                    funcCounter++;

                }

            }

            if (nNumberOfFunctions >= 3 && funcCounter < 4) {

                if (PE.getImportFunctionName(0, 2) == "ExitProcess") {

                    funcCounter++;

                } else if (PE.isDll()) {

                    if (PE.getImportFunctionName(0, 2) == "VirtualProtect") {

                        funcCounter++;

                    }

                }

            }

            if (nNumberOfFunctions == 6) {

                if (PE.getImportFunctionName(0, 2) == "VirtualProtect") {

                    funcCounter++;

                }

                if (PE.getImportFunctionName(0, 3) == "VirtualAlloc") {

                    funcCounter++;

                }

                if (PE.getImportFunctionName(0, 4) == "VirtualFree") {

                    funcCounter++;

                }

                if (PE.getImportFunctionName(0, 5) == "ExitProcess") {

                    funcCounter++;

                }

            }

            if (funcCounter == 2 && nNumberOfFunctions == 2 ||

                funcCounter == 3 && nNumberOfFunctions >= 3 ||

                funcCounter == 4 && nNumberOfFunctions == 4 ||

                funcCounter == 6 && nNumberOfFunctions == 6) {

                isDetected = true;

            }

            if (isDetected) {

                if (PE.getAddressOfEntryPoint() == 0x00001018) {

                    // (Win)Upack

                    isDetected = false;

                }

            }

        }

    }

    return isDetected;

}

function getUPXOptions(nOffset) {

    var nMethod = PE.readByte(nOffset + 2),

        nLevel = PE.readByte(nOffset + 3),

        sCompression = "";

switch (nMethod) // From http://sourceforge.net/p/upx/code/ci/default/tree/src/conf.h

    {

        case 2: case 3:

        case 4: case 5:

        case 6: case 7:

        case 8: case 9:

        case 10: sCompression = "NRV"; break;

        case 14: sCompression = "LZMA"; break;

        case 15: sCompression = "zlib"; break;

    }

    if (sCompression) {

        sOptions = sOptions.append(sCompression);

        if (nLevel == 8) {

            sOptions = sOptions.append("best");

        } else {

            sOptions = sOptions.append("brute");

        }

    }

}

function getUPXVersion() {

    var nOffset1 = PE.findString(0, 1024, "$Id: UPX "),

        nOffset2 = PE.findString(0, 1024, "UPX!");

    if (nOffset2 != -1) {

        getUPXOptions(nOffset2 + 4);

    }

    if (nOffset1 != -1) {

        sVersion = PE.getString(nOffset1 + 9, 4);

    }

    if (!sVersion && nOffset2 != -1) {

        sVersion = PE.getString(nOffset2 - 5, 4);

    }

    if (sVersion) {

        if (+sVersion.toString() != sVersion) {

            if (PE.is64()) {

                sVersion = "3.91+";

            } else {

                sVersion = "0.89+";

            }

            sOptions = "modified";

        }

    }

}

function detect() {

    if (PE.isNet()) return; // Doesn't support .NET

    if (!PE.is64()) {

        if (PE.compareEP("60BE........8DBE........57", PE.compareEP("807C") ? 27 : 0)) {

            bDetected = true;

        } else if (PE.compareEP("60e8000000005883e8..508db8........578db0........83cd..31db9090909001db75")) {

            sVersion = "0.70";

            bDetected = true;

        }

    } else {

        if (PE.compareEP("53565755488D35........488DBE........57", PE.compareEP("4889") ? 24 : 0)) {

            bDetected = true;

        }

    }

    getUPXVersion();

    if (sVersion) {

        bDetected = true;

    }

    if (!bDetected) {

        bDetected = isPatchedUPX();

    } else {

        if (!sVersion) {

            if (PE.is64()) {

                sVersion = "3.91+"; // UPX 3.91 was the first version with a PE+ support.

            }

            sOptions = "modified";

        } else if (!PE.isSectionNamePresent("UPX0")) {

            sOptions = sOptions.append("modified");

        }

    }

    return result();

}

Теперь как мы имеем информацию про то как определяется UPX, мы можем написать на FASM "Спуфер".
Ниже приведу код программы которая вызывает в MessageBox текст SkeetLIMB

![](https://forum.LIMB.cc/attachments/3606/?hash=a6647d082bf60d6d8b78d304ceb
format PE GUI 4.0 - Тут мы задаем что у нас програма PE - Portable Executable - GUI 4.0 то что мы будет работать не в консоли а графическое приложение
entry start - Это точка входа, Windows Начинает код с этого момента
include 'win32a.inc' - подключаем базовый WinAPI для того чтоб мы могли вызвать MessageBox
section '.code' code readable executable - каждая программа на FASM состоит из секций, это секция .code которая читается и запускается самим компилятором
start: - точка входа секции .code
    push    0              - Это стиль окна ( Кнопка OK) подробнее вы можете узнать в оффициальной документации WinApi
    push    text           - Это заголовок окна (caption)
    push    text            - Это сам текст окна
    push    0               - Дескриптор родительского окна 0 означает то что его нет, т.е без родителя
    call    [MessageBoxA] - Вызываем функции MessageBox с user32.dll.
стек в Windows API идёт в обратном порядке (сначала последний аргумент, потом первый).
    push    0               - успешное завершение программы, выход
    call    [ExitProcess]  - Вызывает функцию ExitProcess из kernel32.dll
text db 'SkeetLIMB',0    Это значение того что передавалось выше
section '.idata' import data readable writeable         - Одна из секций которая хранит внешние DLL.
library kernel32,'kernel32.dll',\
        user32,'user32.dll'
import kernel32,\   
       ExitProcess,'ExitProcess'                 - Указываем функции которые будем использовать в этих DLL
import user32,\
       MessageBoxA,'MessageBoxA'           
[/CODE]
Не удалось прогрузить медиа

Это показательный и легкий код чтоб новички понимали что такое вообще фасм, ниже приведу литературу + источники которую я советую если вы хотите развиваться в этом языке.

Спойлер: Материалы
Книги - Норсеев Сергей, разработка оконных приложений на FASM. Программирование на ассемблере на платформе x86-64. ( Книги исключетельно по FASM)
Видео - 
Не удалось прогрузить медиа
 ( Как введение с нуля ) 
Не удалось прогрузить медиа

С кодом и что такое FASM мы разобрались, теперь пишем то что я и обещал "Спуфинг DIE" сейчас я приведу и обьясню код который вызывает эти сигнатуры

![](https://forum.LIMB.cc/attachments/3607/?hash=a6647d082bf60d6d8b78d304ceb
format PE GUI on 'stub.com' - Объясню почему я импорчу не GUI 4.0 как в преведущем коде, а stub.com. Вот код stub.com
org 100h
ret
Простая заглушка, а импорчу я ее потому-что DIE теряет сигнатуру FASM при "on файл.com" это называется DOS-заглушка.
Не удалось прогрузить медиа
(Без Dos-Заглушки)
                                                                                                                                                                                                                     
entry start
include 'win32a.inc'
section 'LIMB' code readable executable
start:
    push    user32_name
    call    [LoadLibraryA]
    test    eax, eax
    jz      exit_prog
    push    msgbox_name
    push    eax
    call    [GetProcAddress]
    test    eax, eax
    jz      exit_prog
    push    0
    push    text
    push    text
    push    0
    call    eax
exit_prog:
    push    0
    call    [ExitProcess]
text db 'LIMBSkeet',0
user32_name db 'user32.dll',0
msgbox_name db 'MessageBoxA',0
section 'UPX0' code readable executable     - Секция которая используется в оригинальном UPX
    nop
section 'UPX1' code readable executable   - Секция которая используется в оригинальном UPX
    nop
section 'Skeet' import data readable writeable
library kernel32,'kernel32.dll'
import kernel32,\
       LoadLibraryA,'LoadLibraryA',\
       GetProcAddress,'GetProcAddress',\
       VirtualProtect,'VirtualProtect',\
       ExitProcess,'ExitProcess'
[/CODE]
Не удалось прогрузить медиа

И все, сканируя этот файл в DIE мы получаем сигнатуру которая находится на скрин чуть повыше.

На этом статья закончена, если вам понравилось и вы хотите чтоб я сделал вторую статью то напишете об этом в коментариях, и если понравится то я выпущу вторую статью как с файла покрытым UPX, сбить сигнатуру в DIE
👍44 😮6 👏12 💯9
Обычный рерайт мануала, совсем неинтересно.
👍2
Ответlimmoner

Обычный рерайт мануала, совсем неинтересно.

Без обидок, скидывай мануал где такое есть
Хороший мануал, закинул удочку с приманкой в виде небольшого текста, оставил способы полноценно изучить фасм.
Тем временем большинство чтобы набить символы написали бы кучу воды, обратились бы к ИИ или просто копировали чужую работу. Прямое копирование, лично я, не нашел.
👍3
Ответyngbeaver

Хороший мануал, закинул удочку с приманкой в виде небольшого текста, оставил способы полноценно изучить фасм. Тем временем большинство чтобы набить символы написали бы кучу воды, обратились бы к ИИ или просто копировали…

Цель статьи была максимально лаконично и кратко обьяснить что такое FASM, и почему именно он чтоб заинтересовать людей писать на ассемблере.
Лично я ничего не крал все что есть в статье это все с моего многолетнего опыта написания кода на этом ассемблере.
👍3
Ответskeet

Цель статьи была максимально лаконично и кратко обьяснить что такое FASM, и почему именно он чтоб заинтересовать людей писать на ассемблере. Лично я ничего не крал все что есть в статье это все с моего многолетнего…

Ну, так я и не обвиняю тебя в копирайте. Наоборот подталкиваю поделиться своим опытом в следующих мануалах.
👍4
Ответyngbeaver

Ну, так я и не обвиняю тебя в копирайте. Наоборот подталкиваю поделиться своим опытом в следующих мануалах.

Я заметил, преведущий пост в благодарность.
Ответskeet

​ Здравствуйте дорогие форумчане , это будет вводная статья в ассемблер, а именно FASM. Почему именно FASM, а не например MASM, NASM, TASM? По моему личному мнению FASM является более удобным чем остальные: FASM…

Ну, по. поводу Фасма и масма скорее наоборот. 
Чаще всего люди которые изучают Масм, это новички которые хотят научится читать код который написан на ассемблере(для реверса). А потом, когда этот человек становится более опытнее, и когда начинает кодить на самом масме, он осознает, что фасм был бы более простым и лучше, из-за этого он переходит на фасм. Все потому что Фасм удобен из-за макросов, там много плюсов. Драйвера кстати  тоже пишут на фасме

К примеру, если мне нужен драйвер где в DriverEntry будет пропатчен мой руткит, я напишу его на фасме, потому что это быстрее и более рациональнее.


Обошёл механизмы защиты винды -> Сделал драйвер на фасме с руткитом в главной функции -> Готово.
👍3
ОтветGemfory

Ну, по. поводу Фасма и масма скорее наоборот. Чаще всего люди которые изучают Масм, это новички которые хотят научится читать код который написан на ассемблере(для реверса). А потом, когда этот человек становится более…

Привет, спасибо что поделился опытом и мнением, на своем опыте скажу что чаще всего пишут драйвера на масме, но спасибо.
👍3
Для новичков статья будет полезная, как краткий экскурс, но хотелось бы побольше информации и побольше разбора и самой конкретики к каждому из действий в статье.
👍2
Мне это очень нужно в комплексе
Сам Fasm это хорошо, на нем можно писать все низкоуровневое под любую архитектуру, даже загрузчики системы. А вот свой стаб использовать (как в примере у ТС) - палево даже для статик АВ.
👍2

Гостевой просмотр. Чтобы отвечать и ставить реакции, войдите или зарегистрируйтесь.