用于通信的 ICALL GADGET 滥用
基本信息:这位于 Windows 内核中,它允许我们在驱动程序中通信,而不会被反作弊系统检测到
所以我在 IDA 中浏览时发现了这个
image
进一步检查后,我们可以看到它调用了一个名为 _guard_dispatch_icall_ptr 的函数。这个 icall 基本上就是跳转到 rax,所以如果你动动脑筋,我们可以修改整个函数,让它转而使用 shellcode 调用我们的处理程序。
我们的 Shellcode
我们将制作 shellcode,将 rax 设置为指向我们处理程序函数的指针。这样,当该函数被调用时,它将执行我们的 shellcode 并调用我们的处理程序。我们要确保制作 shellcode 时,其字节大小与我们修改的代码完全相同。以下是我在汇编中使用的 shellcode 示例,你需要将其转换为字节。
sub rsp,0x38
movabs rax,0xdeadbeef #处理程序的占位符
movabs r10,0xab39cfee
inc rax
dec rax
call QWORD PTR [rip+0x720d4] # 0x720f8
jmp 0x29
我们的代码
在 C++ 中,我们只需要获取函数的地址,然后将我们的 shellcode 映射到其中,但这里有个棘手的地方:如果我们简单地这样做,我们会破坏堆栈,并且时不时会蓝屏。为了避免这种情况,我们需要修复堆栈。因此,我们不应该在处理程序内部返回,而应该执行如果我们没有修改函数时该函数会执行的相同操作。我将把这个留给读者自己完成,因为我不想喂给读者一个绝佳的规避反作弊的方法,但请记住查看函数的原始汇编代码,看看我们修改了什么。附注:如果你修复了堆栈损坏,并在处理程序内部执行函数原本要做的操作,那么看起来就像什么都没被修改过一样! :)
//获取函数地址
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();
总结
希望你能从这篇快速的文章中学到一些东西,只要知道你也可以找到其他 gadget,它们能做的事情要多得多,越复杂越好。