(16)[系统调用]追踪系统调用(3环)

WriteProcessMemory

打开IDA,ALT + T搜索函数WriteProcessMemory(x,x,x,x,x),进入函数体

可以很清晰地看到有三个函数

NtProtectVirtualMemory(x,x,x,x,x)
NtWriteVirtualMemory(x,x,x,x,x)
NtFlushInstructionCache(x,x,x)

进入导入表查看第二个函数(其实三个函数都会最终到相似的结果,但是第三个我只能搜到Zw开头的,没有Nt开头的)
在这里插入图片描述

ntdll.dll

NtWriteVirtualMemory

搜索查看NtWriteVirtualMemory函数,很简单,只有四行

; NtProtectVirtualMemory
mov     eax, 115h        ;服务号
mov     edx, 7FFE0300h  ;指向 函数指针
call    dword ptr [edx]
retn    14h

这里有两个陌生的东西,一个是 服务号 ,另一个是那个 0x7FFE0300
服务号:一个编号,表示调用哪一个服务(函数),后面再详细了解

0x7FFE0300

在这里插入图片描述

  • 随便进一个进程空间
  • 查找刚刚看到的地址,获取这个地址里面的值
  • u 指令查询函数

主要看下面这两个函数

ntdll!KiFastSystemCall:
7c92e4f0 8bd4            mov     edx,esp //保存esp
7c92e4f2 0f34            sysenter 		 //快速调用

ntdll!KiIntSystemCall:
7c92e500 8d542408        lea     edx,[esp+8] //保存esp
7c92e504 cd2e            int     2Eh		 //中断门
7c92e506 c3              ret

那么怎么区分系统有没有快速调用呢?使用cpuid指令(eax = 1)进行查询,eax中存放的是参数,结果信息会被保存到ecx和edx寄存器中,其中edx包含SEP位(第11位),指明当前CPU是否支持快速调用
在这里插入图片描述
dl寄存器 = 0xFF = 0B1111 1111,所以是支持快速调用的

好吧,结果真是大失所望,根本看不到这个函数是怎么执行的,现在的深度还是不够啊
但是这点知识足够我们做一些小东西了

手动调用系统函数

#include <windows.h>

__declspec(naked) //自己掌握整个函数,别人写一半自己写一半不好把握
void MyWriteProcessMemory(
						HANDLE hProcess,
						LPVOID lpBaseAddress,
						LPVOID lpBuffer,
						DWORD nSize,
						LPDWORD lpNumberOfBytesWritten 
){
	_asm{
		push ebp
		mov ebp, esp
		sub esp, 0x10 //稍微提升一下堆栈,不提升也行

		push [lpNumberOfBytesWritten]
		push [nSize]
		push [lpBuffer]
		push [lpBaseAddress]
		push [hProcess]  //压入5个参数
		push 0 //push eip 本来是个call的,这里对齐一下就行
		
		//系统调用,照抄就行
		mov eax, 0x115
		mov edx, 0x7FFE0300
		call dword ptr[edx]

//		add esp, 0x04 //pop eip
//		add esp, 0x10 //不用做堆栈检查,省略这一部直接退出就行
		mov esp, ebp
		pop ebp 	//记得平衡回来
		retn 0x14 	//外部压入了5个参数
	}
}

int main(){
	DWORD val = 0x12345678;
	DWORD write_val = 0x11112222;
	//获取自己的进程PID
	DWORD curPID = GetCurrentProcessId(); 
	//下面的函数要用到这个
	HANDLE dst_hdl = OpenProcess(PROCESS_ALL_ACCESS, FALSE, curPID); 
	//自己实现的WriteProcessMemory
	//WriteProcessMemory(dst_hdl, &val, &write_val, sizeof(val), NULL);//先试试好不好使
	MyWriteProcessMemory(dst_hdl, &val, &write_val, sizeof(val), NULL);
	//两个函数的效果是一样的
	printf("%X", val);
	getchar();
	return 0;
}
//打印结果:11112222

实验成功

防:不让别人hook自己的函数或者断点找到突破口
攻:绕过别人的hook检查

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值