来到VirtualProtect函数地址 跟随 可以明显看到调用了ntdll.NtProtectVirtualMemory,跟随 看到syscall 下断 重写api函数最大的难点是确定最开始调用的参数放哪了,会不会放到别的寄存器或者堆栈里头,而x64默认规定rcx,rdx,r8,r9,为前四个参数,第五个放在[rsp+28],第六个放在[rsp+28+8],依次类推。我们去看看NtProtectVirtualMemory的参数跟原先函数的参数之间的关系。由第一张图和第二张图可知,原始参数为 07FF6B7A2130C(要改变属性的地址),5(要改变地址属性的长度,没啥用,他是按页直接改的,不会具体到某个长度,按目前照操作系统的话,只能是1000的整数倍),PAGE_EXECUTE_READWRITE(是个宏,就是40,就是要改成什么样的属性),7FF6B7A2C190(为存放旧属性的地址,方便恢复)。观察下断后的状态,rcx是FFFFFFFFFFFFFFFF,就是负一,这个参数说明要改的地址的所属进程是本身,rdx是000000BC0A2FFC98,我们放到内存去看 这个rdx里面的值当做地址,这个地址存放着原始函数的第一个参数,也就是要改变属性的地址,再往前看r8的值000000BC0A2FFC90,再放到ce内存去看, 是原先函数的第二个参数5,再看r9,是原先函数的第三个参数40,再观察 原先函数的第最后一个参数放在了rsp+28的位置。因为NtProtectVirtualMemory直接调用了syscall,所以我们重写的是这个NtProtectVirtualMemory函数,因为VirtualProtect调用了NtProtectVirtualMemory,所以我们从VirtualProtect入手。本质就是研究这两个函数的参数是什么关系,那由前面可知,这两个函数的参数关系为 NtProtectVirtualMemory多了参数,其实是进程句柄,所以我们可以推断VirtualProtectEx(远程改变进程地址的属性)也是调用了NtProtectVirtualMemory。
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!