1. Если вы только начинаете программировать на ассемблере и не знаете с чего начать, тогда попробуйте среду разработки ASM Visual IDE
    (c) на правах рекламы
    Скрыть объявление

Введение в реверсинг с нуля, используя IDA PRO. Часть 54.

Дата публикации 22 окт 2018 | Редактировалось 26 окт 2018
Мы собираемся немного изменить предыдущее упражнение, а также сделаем программу для пользовательского режима, прямо в PYTHON.

Для этого, на целевой машине, где запущен драйвер, мы должны установить PYTHON. Я установил версию 2.7, а также загрузил инсталлятор PYWIN32, который соответствует моей версии PYTHON.

https://sourceforge.net/projects/pywin32/files/pywin32/Build 214/

Поскольку моя версия PYTHON равна 2.7, то скачайте этот файл.

1.png

Это инсталлятор. Запускаем его и он устанавливается. С этой программой мы сможем запустить скрипт PYTHON, который заменит предыдущую пользовательскую программу.

Мы видим, что у драйвера теперь есть еще два кода IOCTL.

2.png

В дополнение к коду IOCTL_SAYHELLO, который у нас уже был, теперь есть два новых: код IOCTL_HOOK и код IOCTL_UNHOOK.

3.png

Мы видим, что внутри CASE, когда MAJORFUNCTION равен IRP_MJ_DEVICE_CONTROL, есть еще один переключатель, который имеет три CASE IOCTL.

Мы видим, что код IOCTL, который мы имели раньше, все еще печатает только фразу “HELLO WORLD

case IOCTL_SAYHELLO:
DbgPrint("Hello World!\n");
status = STATUS_SUCCESS;
break;

Давайте посмотрим другие два.

case IOCTL_HOOK:
PsSetCreateProcessNotifyRoutine(
DriverProcessNotifyRoutine, FALSE);
break;
case IOCTL_UNHOOK:
PsSetCreateProcessNotifyRoutine(
DriverProcessNotifyRoutine, TRUE);
break;

Мы видим, что драйвер использует функцию PSSETCREATEPROCESSNOTIFYROUTINE

4.png

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

Наша функция, в которую будет переходить драйвер, называется DRIVERPROCESSNOTIFYROUTINE, и если условие CREATE истинно, драйвер печатает, что создан новый процесс, PID родительского процесса, который его создал, и сам ID процесса.

VOID DriverProcessNotifyRoutine(
IN HANDLE ParentId,
IN HANDLE ProcessId,
IN BOOLEAN Create)
{
if (Create)
{
DbgPrint("Process %d created process %d\n",
ParentId, ProcessId);
}
else
{
DbgPrint("Process %d has ended\n",
ProcessId);
}
}

И когда процесс завершается, так как условие CREATE будет ложным, драйвер напечатает, что процесс завершился и его PID.

Конечно, вы должны убедиться, что перед остановкой драйвера, что функция будет отключена, иначе драйвер будет переходить к функции, которая не существует, и будет вызывать BSOD.

case IOCTL_UNHOOK:
PsSetCreateProcessNotifyRoutine(
DriverProcessNotifyRoutine, TRUE);
break;

Второй аргумент установленный в TRUE отключает функцию - и система продолжает работать нормально.

Хорошо. Исходный код драйвера будет доступен во вложении. Помните, что если вы скомпилируете его в VISUAL STUDIO, вы должны изменить НАСТРОЙКИ в WINDOWS 7 и свойства DESKTOP, а также снизить уровень строгости ошибок с 4 уровня до 1 или 2.

Хорошо. Теперь идет скрипт PYTHON, который отправит IOCTL драйверу, когда тот будет запущен.

5.png

Мы видим, что это небольшой скрипт. Вам нужно импортировать модули WIN32API и WIN32FILE, в дополнение к WINIOCTLCON. Всё это входит в пакет PYWIN32, который мы установили. Если вы его не установили, это даст вам ошибку.

IOCTL_HOOK =winioctlcon.CTL_CODE( FILE_DEVICE_HELLOWORLD, 0x01, METHOD_BUFFERED, FILE_ANY_ACCESS )

IOCTL_UNHOOK =winioctlcon.CTL_CODE( FILE_DEVICE_HELLOWORLD, 0x02, METHOD_BUFFERED, FILE_ANY_ACCESS )


IOCTL_SAYHELLO=winioctlcon.CTL_CODE( FILE_DEVICE_HELLOWORLD, 0x00, METHOD_BUFFERED, FILE_ANY_ACCESS )

Мы видим, что функция CTL_CODE, которую мы используем, когда мы создали исполняемый файл на C++, чтобы найти IOCTL. В PYTHON импортирует их из модуля WINIOCTLCON. Мы сможем найти три IOCTL.

Затем у нас идёт вызов функции CREATEFILE.

hDevice = win32file.CreateFile(r"\\.\HelloWorld",win32file.GENERIC_READ | win32file.GENERIC_WRITE, 0, None,win32file.OPEN_EXISTING, win32file.FILE_ATTRIBUTE_NORMAL, 0)

В этом случае, в имени драйвера вам нужно просто добавить обратную косую черту. Остальная часть строки похожа на константы для аргументов, которые находятся в модуле WIN32FILE.

И затем происходит вызов функции DEVICEIOCONTROL. Мы предлагаем, что пользователь вводить клавишу и в зависимости от того, что он выбирает, мы отправляем драйверу соответствующий код. Если пользователь выбирает нуль, перед выходом их программы, он отключит эту функцию, чтобы избежать BSOD.

while 1:
print "1=HELLO\n","2=HOOK\n","3=UNHOOK\n","0=UNHOOK AND EXIT\n"

case=raw_input()
if case ==0:
break
if
case==1:
win32file.DeviceIoControl(hDevice,IOCTL_SAYHELLO, None, None, None)
if case == 2:
win32file.DeviceIoControl(hDevice,IOCTL_HOOK, None, None, None)
if case == 3:
win32file.DeviceIoControl(hDevice,IOCTL_UNHOOK, None, None, None)

win32file.DeviceIoControl(hDevice,IOCTL_UNHOOK, None, None, None)
win32file.CloseHandle(hDevice)

С помощью этого скрипта мы могли бы управлять драйвером, отправляя разные коды IOCTL. Давайте протестируем его.

6.png

Я запускаю целевую систему и запускаю драйвер с помощью OSRLOADER, и оставляю его запущенным. Теперь я буду использовать скрипт PYTHON, чтобы узнать, работает ли он.

Мы видим, что после того, как нам напечатается дескриптор драйвера, нам покажутся опции для выбора.

7.png

Если я нажму 1, то ничего не происходит. Что же произошло?

case=raw_input()
1
case
type(case)

Out[6]: str

Ааа. Результат RAW_INPUT - это строка, и мы сравниваем ее с целым числом. Давайте изменим это.

8.png

Посмотрим сейчас.

9.png

Теперь всё работает. Когда мы нажимаем 1, нам показывается перехваченная фраза “HELLO WORLD”. Сейчас я нажимаю 2.

10.png

Теперь позапускаем некоторые программы в машине.

11.png

Мы видим, как драйвер логирует процессы, которые запускаются и закрываются. В моем случае, запускается INTERNET EXPLORER.

12.png

PID IE равен 4084, а родителем является – EXPLORER. При запуске двойным щелчком, любой процесс, который запускается на машине или останавливается будет логироваться. Теперь я закрываю IE.

13.png

Хорошо. Всё работает. Теперь выключим перехват через пункт 3. Мы видим, что процессы, которые мы открываем и закрываем, больше не регистрируются.

Что касается реверсинга, то это похоже на предыдущий случай.

14.png

В обработчике мы видим, что в этом случае регистр EDI, равен IRP + 0x60. Он будет иметь адрес структуры _IO_STACK_LOCATION. Кроме того, поставим там BP. Как только мы синхронизируем необходимые структуры в LOCAL TYPES, нам покажут, что это поле MAJORFUNCTION.

15.png

В случае, когда MAJORFUNCTION равно 0xE, другими словами, когда мы используем DEVICEIOCONTROL. Мы нажимаем T и из всех опций, которые есть, мы выбираем, те для которых используется DEVICEIOCONTROL.

16.png

Мы видим, что когда код равен IOCTL_SAYHELLO, драйвер переходит к желтому блоку, который напечатает HELLO WORLD. В двух других случаях он идёт в зеленые блоки. В случае IOCTL_HOOK выполняется инструкция PUSH ESI, регистр которой равен нулю, чтобы передать аргумент FALSE в API PSSETCREATEPROCESSNOTIFYROUTINE@8, а в случае IOCTL_UNHOOK исполняет инструкцию PUSH 1, что является TRUE.

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

17.png

Если мы сделаем щелчок здесь, мы перейдём к этой функции.

18.png

Здесь мы видим, если переменная CREATE ложная, т.е. равна нулю, драйвер переходит в PROCESS (PID) HAS ENDED, а если переменная истинна, то переходит в ROCESS (PID) CREATED PROCESS (PID)

Если мы поставим BP здесь, драйвер будет останавливаться каждый раз, когда мы запускам процесс, после того, как я нажму 2 в скрипте PYTHON для ПЕРЕХВАТА.

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

=======================================================
Автор текста: Рикардо Нарваха - Ricardo Narvaja (@ricnar456)
Перевод на русский с испанского: Яша_Добрый_Хакер(Ростовский фанат Нарвахи).
Перевод специально для форума системного и низкоуровневого программирования — WASM.IN
26.10.2018
Версия 1.0

0 653
yashechka

yashechka
Ростовский фанат Нарвахи

Регистрация:
2 янв 2012
Публикаций:
90