Малварь как искусство Самомодификация и генерация кода на лету в си. Часть 1. Вкуриваем суть.

Тема в разделе "Технологии создания невидимой малвари", создана пользователем X-Shar, 11 ноя 2017.

↑ ↓
  1. X-Shar :)
    X-Shar
    Ответить в чате

    Администрация

    Регистрация:
    03.06.2012
    Сообщения:
    5.431
    Симпатии:
    57
    Пол:
    Мужской
    Репа:
    +682 / 163 / -34
    [​IMG]

    Всем привет ! :)

    Осень, дерьмовая погода и настроение жесть.

    Что-бы как-то поднять настроение, решил выпить ведро водки глянуть что-тут у нас с модификацией и генерацией кода на "лету".

    Гуглил, находил книги Криса, который говорил про исполнение кода на стеке, но чот так и не получилось у меня.

    Ибо грёбанная винда, блокирует доступ к стеку, хотя возможно руки вырасли из жопы. Но не суть в принципе можно сделать что-то такое в кучи.

    Давайте разбираться, итак как её, ах-да теория. Короче немного тут будет:

    В си есть прикольная штука, называется указатель на функцию. Смысл такой, ты делаешь какой-то абстрактный тип данных, и говоришь, "Это функция" и далее можешь использовать этот тип данных вызывая различные функции, с разным функционалом, например:
    Код:
    typedef LONG (*FunctionPointer) (LONGLONG);
    FunctionPointer наш тип данных, который указывает на функцию с параметрами (LONG, LONG).

    Далее например если у вас есть функция например функция сложения а+в, вы можете вызвать её. При помощи этого указателя, вот пример:

    FunctionPointer Summa; //Объявляем переменную с типом FunctionPointer (наш указатель на функцию)

    Допустим есть функция, которая складывает два числа:

    int tst_summ (LONG a, LONG b)
    {
    return a+b;
    }

    Далее мы можем вызвать нашу функцию например так:

    Summa = tst_summ;
    Result = Summa (1,2);

    Ну думаю понятно, что это нужно когда например в разных ситуациях выполнялся разный код, например я это использую как абстрактный тип данных при написании драйверов для различных девайсов. Например, функции чтения с различных устройств (флешки, диски и т.д.) всегда разные, но при этом можно сделать удобный интерфейс для взаимодействия, т.е. пользователь будет дёргать одну функцию, например read, а она уже будет вызывать нужную функцию чтения для нужно флешки. :)

    Ну это ладно с теорией почти закончено, а что если мы вообще не будет никак заполнять функцию, а заполним её в процессе работы программы, или например пошифруем тело нашей функции, а далее выполним код в процессе выполнения программы ?

    Как можно это сделать:

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

    Итак теперь немного про ассемблер и машинный код:

    Все вы знаете, что ассемблерные команды преобразуются в машинный код после компиляции, это можно посмотреть в любом отладчике, открыв нативную программу, например в оледбг:

    upload_2017-11-11_16-16-56.

    Тут левая крайняя колонка, это адрес, правее как раз машинный код, право крайняя колонка это ассемблерный код.

    Итак как вы думаете что будет, если мы создадим указатель на функцию, в которой генерируются эти машинные коды ? :)

    Ога, они исполнятся в программе.

    Давайте попробуем это реализовать, простая функция сложения двух чисел:

    1)Создаём абстрактный тип данных:
    Код:
    typedef LONG (*FunctionPointer) (LONGLONG);
    2)Выделяем память для функции, которую будем генерировать "на лету":
    Код:
    FunctionPointer Summa;

    Summa = (FunctionPointermalloc (11);
    3)Заполняем выделенную память опкодами:
    Код:
        ((LPBYTESumma)[0] =  0x55// push  bp
        
    ((LPBYTESumma)[1] =  0x8B// mov ebp, esp
        
    ((LPBYTESumma)[2] =  0xEC;
        ((
    LPBYTESumma)[3] =  0x8B// mov eax, [bp+8]
        
    ((LPBYTESumma)[4] =  0x45;
        ((
    LPBYTESumma)[5] =  0x08;
        ((
    LPBYTESumma)[6] =  0x03// add eax, [bp+12]
        
    ((LPBYTESumma)[7] =  0x45;
        ((
    LPBYTESumma)[8] =  0x0C;
        ((
    LPBYTESumma)[9] =  0x5D// pop ebp
        
    ((LPBYTESumma)[10] = 0xC3// ret eax

    Наконец, можно вызвать функцию VirtualProtect(). Все наши команды на месте, нам нужно просто разрешить выполнить их. Следующая команда сделает это:
    Код:
         DWORD oldprotect;
        
    VirtualProtect(Summa11PAGE_EXECUTE, &oldprotect); 
    4)В общем-то и всё, можно запускать нашу функцию:
    Код:
    int sum Summa(12);
    printf (" Summa = %d \n"sum);
    Получаем:

    upload_2017-11-11_16-25-1.

    Код программы на си (можно собрать как консольное приложение в вижуалке):

    Код:
    #include "stdafx.h"
    #include "windows.h"

    typedef LONG (*FunctionPointer) (LONGLONG);

    int _tmain(int argc_TCHARargv[])
    {
        
    FunctionPointer Summa;
        
    Summa = (FunctionPointermalloc (11);
        
        ((
    LPBYTESumma)[0] =  0x55// push ebp
        
    ((LPBYTESumma)[1] =  0x8B// mov ebp, esp
        
    ((LPBYTESumma)[2] =  0xEC;
        ((
    LPBYTESumma)[3] =  0x8B// mov eax, [bp+8]
        
    ((LPBYTESumma)[4] =  0x45;
        ((
    LPBYTESumma)[5] =  0x08;
        ((
    LPBYTESumma)[6] =  0x03// add eax, [bp+12]
        
    ((LPBYTESumma)[7] =  0x45;
        ((
    LPBYTESumma)[8] =  0x0C;
        ((
    LPBYTESumma)[9] =  0x5D// pop ebp
        
    ((LPBYTESumma)[10] = 0xC3// ret eax
        
        
    DWORD oldprotect;
        
    VirtualProtect(Summa11PAGE_EXECUTE, &oldprotect);

        
    int sum Summa(12);

        
    printf (" Summa = %d \n"sum);

        while (
    1);
        return 
    0;
    }

    Всё работает ! :)

    В следующей части, зашифруем код и исполним его после расшифровки на "лету".

    Всем удачи ! :)
     

    Вложения:

  2. X-Shar :)
    X-Shar
    Ответить в чате

    Администрация

    Регистрация:
    03.06.2012
    Сообщения:
    5.431
    Симпатии:
    57
    Пол:
    Мужской
    Репа:
    +682 / 163 / -34
Похожие темы:
  1. X-Shar
    Ответов:
    1
    Просмотров:
    3.087
  2. X-Shar
    Ответов:
    14
    Просмотров:
    3.594
  3. Indy
    Ответов:
    32
    Просмотров:
    6.541
  4. X-Shar
    Ответов:
    2
    Просмотров:
    642
  5. X-Shar
    Ответов:
    0
    Просмотров:
    80
Загрузка...