ЗЛОУПОТРЕБЛЕНИЕ ICALL GADGET ДЛЯ СВЯЗИ
Общая информация: это находится в ядре Windows и позволит нам осуществлять связь в нашем драйвере, не будучи обнаруженными античитами
Итак, я просматривал код в IDA и нашёл это
image
После дальнейшего изучения мы видим, что она вызывает функцию под названием _guard_dispatch_icall_ptr. icall по сути представляет собой jmp на rax, так что если немного подумать, мы можем изменить всю эту функцию, чтобы вместо этого вызвать наш обработчик с помощью шелл-кода.
Наш шелл-код
Мы собираемся создать шелл-код, который устанавливает rax в указатель на нашу функцию-обработчик. Таким образом, когда функция будет вызвана, она выполнит наш шелл-код и вызовет наш обработчик. Мы должны убедиться, что при создании шелл-кода его размер в байтах точно совпадает с размером кода, который мы изменяем. Вот пример шелл-кода, который я использовал на ассемблере; вам нужно будет преобразовать его в байты.
sub rsp,0x38
movabs rax,0xdeadbeef #placeholder for handler
movabs r10,0xab39cfee
inc rax
dec rax
call QWORD PTR [rip+0x720d4] # 0x720f8
jmp 0x29
Наш код
В C++ нам просто нужно получить адрес функции, а затем записать наш шелл-код в неё, но здесь и начинаются сложности: если мы сделаем это просто как есть, мы повредим стек и время от времени будем получать синий экран. Чтобы избежать этого, нам нужно восстановить стек. Поэтому вместо возврата внутри нашего обработчика мы должны выполнять те же операции, которые выполняла бы функция, если бы мы её не изменяли. Я оставлю это читателю для самостоятельной реализации, потому что не хочу разжёвывать потрясающий метод обхода античитов, но помните, что нужно посмотреть на оригинальный ассемблер функции и увидеть, что именно мы изменяем. ПОБОЧНОЕ ЗАМЕЧАНИЕ: если вы исправите повреждение стека и сделаете внутри своего обработчика то, что функция должна была делать, это будет выглядеть так, будто ничего не было изменено! :)
//getting address to function
FunctionAddress = module + 0xD70C;
BYTE shellcode[] = { 0x48, 0x83, 0xEC, 0x38, 0x48, 0xB8, 0xEF, 0xBE, 0xAD, 0xDE, 0x00, 0x00, 0x00, 0x00, 0x49, 0xBA, 0xEE, 0xCF, 0x39, 0xAB, 0x00, 0x00, 0x00, 0x00, 0x48, 0xFF, 0xC0, 0x48, 0xFF, 0xC8, 0xFF, 0x15, 0xD4, 0x20, 0x07, 0x00, 0xE9, 0x00, 0x00, 0x00, 0x00 };
memcpy(&shellcode[6], &hkfunction, 8);
DisableWriteProtection();
memcpy((PVOID)FunctionAddress, &shellcode, sizeof(shellcode));
EnableWriteProtection();
Заключение
Надеюсь, вы почерпнули что-то из этой краткой заметки; просто знайте, что вы можете найти и другие гаджеты, которые сделают гораздо больше — чем сложнее, тем лучше.