• XSS.stack #1 – первый литературный журнал от юзеров форума

XSS PWN-Day - БИТВА ЗА РЕСПЕКТ 0x01 | Атакуем ядро Windows

Пожалуйста, обратите внимание, что пользователь заблокирован
Я вижу, что у людей возникли трудности с имперсонацией, поэтому мы еще на день остановимся на ней подробнее.
Ниже пример цепочки из интерфейсов, которую вы должны реализовать на языке C/C++ (за исключением последних двух), чтобы произвести имперсонацию.

GetServiceHandleByName->GetServiceProcessID->GetFirstThreadID->EnableDebugPrivilege->OpenThread->NtImpersonateThread

Если вы используете Powershell, то можете сделать это намного проще при помощи модуля NtObjectManager.
Но в первом случае вы хотя бы будете знать, как такое реализовать. Примеры кода вы можете найти на гитхабе, msdn и на форуме.
 
Скрытое содержимое
Сейчас уже примерно такая же схема реализована (за исключением того, что берется не первый поток, а главный), привилегия включена.
C++:
HANDLE hThread = ProcessMainThread(1504); //1504 - pid, хендл открыт с правами THREAD_DIRECT_IMPERSONATION
printf("\n0x%llx\n", hThread); //все ок, хендл не 0
status = NtImpersonateThread(NtCurrentThread(), hThread, &sqos);
printf("\t0x%llx\n", status); //0x0 - Исправил, теперь STATUS_SUCCESS
Но windbg говорит:
Код:
...
Impersonation Level: Anonymous
TokenType: Primary
...
 
Последнее редактирование модератором:
Пожалуйста, обратите внимание, что пользователь заблокирован
Но windbg говорит:
Честно говоря не проверял, что WinDbg отображает. Если все ок, то дескриптор устройства уже должен получить без ошибок в правах. Возможно гляну попозже в чем подвох.
 
Последнее редактирование:
Были бы хотя бы базовые навыкиа работы с ядерным отладчиком WinDbg тоже поучаствовал. Не хватает навыка и опыта для участия этого конкурса. Может следующий конкурс получиться 😅
 
Пожалуйста, обратите внимание, что пользователь заблокирован
Были бы хотя бы базовые навыкиа работы с ядерным отладчиком WinDbg тоже поучаствовал. Не хватает навыка и опыта для участия этого конкурса. Может следующий конкурс получиться 😅
А ты не сиди и не жди подходящего момента, можешь пока поизучать отладчик, время еще есть. До PoC'a первого уровня вполне сможешь добраться.
 
Пожалуйста, обратите внимание, что пользователь заблокирован
Были бы хотя бы базовые навыкиа работы с ядерным отладчиком WinDbg тоже поучаствовал.
Если есть опыт работы с отладчиками в целом, то 1-2 дня могут уйти на настройку окружения и ознакомление с базовыми командами. Но первую задачу можно решить сугубо статикой, если она крепкая. Времени еще достаточно.
 
Пожалуйста, обратите внимание, что пользователь заблокирован
Итак, надеюсь, что вы уже справились с имперсонацией и смогли получить дескриптор устройства AppID.
Осталось немного, чтобы выполнить первую задачу. Теперь вы должны отправить уязвимый входящий буфер драйверу при помощи функции DeviceIoControl с ioctl 0x22A018.
В зависимости от версии Windows размер валидного входящего буфера будет отличаться. Ниже вывод декомпилятора для функции AipDeviceIoControlDispatch.

C:
// Windows 10   
        ...
        if ( CurrentStackLocation->Parameters.DeviceIoControl.InputBufferLength == 0x18 )
        {
          status = AipSmartHashImageFile(Irp->AssociatedIrp.SystemBuffer,
                    0i64,
                    0i64,
                    0i64);
          break;
        }
InvalidParam:
        status = STATUS_INVALID_PARAMETER;
        break;
        ...
        
// Windows 11       
        ...
        if ( CurrentStackLocation->Parameters.DeviceIoControl.InputBufferLength == 0x20 )
        {
          status = AipSmartHashImageFile(
                     (smart_hash_image_file_struct *)Irp->AssociatedIrp.SystemBuffer,
                     0i64,
                     0i64,
                     0i64);
          break;
        }
InvalidParam:
        status = STATUS_INVALID_PARAMETER;
        break;
        ...


Отследите data-flow входящего буфера в цепочке.
AipSmartHashImageFile->AppHashComputeFileHashesInternal->AppHashComputeImageHashInternal
Определите каким должен быть входящий буфер, чтобы триггернуть уязвимость.
 
Уткнулся в ObfReferenceObject в драйвере, я правильно понимаю что надо создать какой-то объект и отдать его туда(например ивент)? Потому как просто рандомный поинтер крашит драйвер. Вот только не очень хорошо представляю как получить адрес объекта (одна из мыслей - как то спарсить таблицу дескрипторов). В правильном направлении иду?
 
Последнее редактирование модератором:
Пожалуйста, обратите внимание, что пользователь заблокирован
Скрытое содержимое
Все верно. В идеале там должен быть адрес любого объекта FILE_OBJECT, который можно получить через NtQuerySystemInformation. Вот здесь есть пример враппера GetObjPtr (под спойлером) для получения любых ядерных объектов по хендлу. https://xssforum7mmh3n56inuf2h73hvhnzobi7h2ytb3gvklrfqm7ut3xdnyd.onion/threads/86050/#post-599823
 
Последнее редактирование:
Пожалуйста, обратите внимание, что пользователь заблокирован
Исходя из предыдущего шага вы должны были увидеть, что в функции AppHashComputeImageHashInternal происходит разыменовывание произвольного указателя, который мы можем передать во входящем буфере. Это и есть уязвимость, а именно CWE-822: Untrusted Pointer Dereference.

Вторая и третья задачи концептуально схожи за тем исключеним, что при решении третьей задачи нужно искать подходящую функцию в GFIDS, чтобы не уронить систему с включенным HVCI. Для этого вам придется как-то сдампить названия всех функций из этой таблицы.

Целевая функция должна сделать что-то полезное - например, перезаписать какую-то память по произвольному указателю. Какую? Например, поле PreviousMode для объекта текущего потока. Для чего? Чтобы получить примитив произвольного чтения/записи.

Искать такую функцию можно в ядре, любых драйверах и тут у каждого может быть свое решение. Я лишь выделю некоторые критерии:
1. Функция в идеале должна принимать один аргумент, но в целом это не обязательно и можно получить нужные примитивы исходя из состояния регистров. Это менее надежно, т.к. значения в остальных регистрах могут отличаться от системы к системе.
2. Функция не должна быть сложной. Чем сложнее функция, тем выше риск BSOD. Ищите простые функции.
3. Функция в идеале должна перезаписать 1 байт по произвольному адресу, в противном случае стабильность не гарантируется.

Начните поиск такой функции в ntoskrnl.exe. Данный этап самый продолжительный по времени.

На текущий момент у нас появился еще один участник, выполнивший Задачу #1.
 
Последнее редактирование модератором:
Пожалуйста, обратите внимание, что пользователь заблокирован
Скрытое содержимое
Я видел, но пока нет новых претендентов, которые сдали хотя бы BSOD. Надеюсь, что он никому не попадется, а если кто умный будет сдавать 3 задачу с этим PoC, то на вопросах 100% посыпется. Вероятность того, что они использовали тот же коллбек из 8к+ функций будет мала. Хотелось бы дожать конкурс до конца.
 
Последнее редактирование:
Пожалуйста, обратите внимание, что пользователь заблокирован
Пожалуйста, обратите внимание, что пользователь заблокирован
Эх, вот и проворонил я данный конкурс, из-за лени... Удачи всем участникам!)
Конкурс еще действует. На решение первой задачи хватит времени точно.
 
Пожалуйста, обратите внимание, что пользователь заблокирован
Так решили же уже первую, не? + времени с виндбг разбираться
У нас лимит премиумов 5 штук, Эксперты безграничны, но за решения я буду спрашивать и если кто-то будет уличен в недобросовестном плагиате, то последует бан.
 
Так решили же уже первую, не? + времени с виндбг разбираться
https://github.com/4d61726b/VirtualKD-Redux - вот софт для супер простой настройки виндбг, подключается к отладчику почти из коробки. А для самого windbg надо знать буквально десяток базовых команд чтобы работать. dt, dq (и остальные d*), u/uf, ld, r, p, t, bp и еще пара других. Коллстэк можешь глянуть в View/Call Stack. Вот этого вроде бы должно хватить для bsod-a.
 


Напишите ответ...
  • Вставить:
Прикрепить файлы
Верх