Windows内核RtlZeroMemory反汇编分析
2023-06-16
98
0
Windows驱动中一个简单的代码封装,对内存进行清空操作。
NTSTATUS MyZeroMemory( PUCHAR pData, ULONG nLen)
{
RtlZeroMemory(pData, nLen);
return STATUS_SUCCESS;
}
RtlZeroMemory在头文件wdm.h使用的宏memset来实现的。
#define RtlEqualMemory(Destination,Source,Length) (!memcmp((Destination),(Source),(Length)))
#define RtlMoveMemory(Destination,Source,Length) memmove((Destination),(Source),(Length))
#define RtlCopyMemory(Destination,Source,Length) memcpy((Destination),(Source),(Length))
#define RtlFillMemory(Destination,Length,Fill) memset((Destination),(Fill),(Length))
#define RtlZeroMemory(Destination,Length) memset((Destination),0,(Length))
编译成X64反汇编之后的代码如下:
; int __fastcall MyZeroMemory(unsigned __int8 *pData, unsigned int nLen)
public MyZeroMemory
MyZeroMemory proc near
sub rsp, 28h
mov r8d, edx ; Size
xor edx, edx ; Val
call memset
xor eax, eax
add rsp, 28h
retn
MyZeroMemory endp
第4行和第9行是进行栈平衡的,可以看到,该函数使用了0x28的地址空间。
实际情况上,由于x64函数的前4个字节使用的是rcx,rdx,r8,r9来进行传递的,故其实只需要保留返回地址的空间即可。但实际上是0x28地址空间,0x28总字节数为40,在64位情况下,为5个8字节,所以其实就是对应快速调用的4个参数的空间保留和ret返回地址空间的使用。
x64默认使用的是快速调用,故MyZeroMemory的2个参数pdata使用的是rcx,长度就是rdx而memset是3个参数,故参数应为:
所以上面的代码对照这个图可知,rcx不变,rdx的值需要给r8,但是是32位的,所以就是edx传给r8d,然后edx清0(xor edx,edx),然后再调用call memset- 函数的一个返回值,是通过eax或者rax返回的,由于值为0,故对eax清0即可。