about NtWaitForSingleObject

最近忙个程序,遇到不少问题,当然也都解决了。我感觉我记性不大好。别以后再碰见了想不起来为啥,就当这个是记事吧。

这个问题的目的是监控所有对NtWaitForSingleObject的调用,并尽可能的回溯出调用堆栈,然后用OutputDebugString输出。

这个问题比较复杂,因为NtWaitForSingleObject是ring3下最底层的Wait系列函数了,很多函数都会用到,比如那个OutputDebugString。这样就有个重入问题。 一开始我用的是hook NtWaitForSingleObject函数,跳到我的函数里,鉴于这些native函数太简单,就没有跳转回去,直接把他的3行代码写到我的函数里,当然之前加上对是否是重入的判断。这个判断很简单,就判断一下返回地址是否是OutputDebugString里所使用的地址,是的话直接跳过监控。这种方法大致可行。 虽然可能因为那个不完美的判断漏过一些。用这种方法,编个EXE测试是可行的。但是应用到目标就不可以了,目标比较变态,经常遇见C语言写的函数不能用,得写__declspec(naked)的才行。

后来想想 就放弃了跳转到我的hook,直接把NtWaitForSingleObject写成个0xCC,然后再异常处理里玩他,方法是先写回原值,然后回溯、输出。在EXE里也灰常成功。 弄到dll里,果然很诡异。把几个局部变量弄成全局的,好了一些,把几个函数也弄成汇编的,又好了一些。但是始只能回溯几次。

为什么在EXE里测试,灰常成功那? 一想,原来是同步问题。我的EXE是单线程的。目标里面,是多线程的。明显是当某个线程正在恢复时,其他线程又给写成0xCC了。

啊,这需要个同步呀。然而我做掉的,就是用来同步的。还是模拟个传说中的 自旋锁 吧:

 

DWORD g_SpinCount = 0;

void __declspec(naked) MySpinEnter()
{
 __asm
 {
BEGIN:
  mov eax,0;
  lea ecx,g_SpinCount;
  mov edx,1
  lock cmpxchg [ecx],edx;
  jz RETURN;
  call dword ptr[SwitchToThread];
  jmp BEGIN;
RETURN:
  ret;

 }

}
void __declspec(naked) MySpinLeave()
{
 __asm
 {
  mov eax,0;
  lock xchg eax,g_SpinCount;
  ret;
 }
}

 

哎,谁知道怎么让编译器在函数开头加一些恶心的代码,直接翻译我的代码那? 给说一下,一起交流交流呗.... 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值