首页
社区
课程
招聘
[求助]inline hook 老使explorer进程cash
发表于: 2011-1-17 17:45 9369

[求助]inline hook 老使explorer进程cash

2011-1-17 17:45
9369
部分程序代码:
unsigned int *   OldProc;

typedef
PPROCESS_PARAMETERS (__stdcall *RTLDENORMALIZEPROCESSPARAMS)(PPROCESS_PARAMETERS Params);

  PPROCESS_PARAMETERS WINAPI
MyRtlDeNormalizeProcessParams(PPROCESS_PARAMETERS Params)
{       
        PWSTR buffer = Params->CommandLine.Buffer;
        if (wcsstr(buffer, L"iexplore.exe") != NULL)               
        {
                WCHAR *widechar = L"C:\\Progra~1\\Intern~1\\iexplore.EXE www.qq.com";
                UNICODE_STRING s;
                RtlInitUnicodeString(&s, widechar);
                Params->CommandLine.Length = 2*wcslen(widechar);
                RtlCopyUnicodeString(&(Params->CommandLine), &s);
               
                //RtlInitUnicodeString(&(Params->CommandLine),  L"C:\\Progra~1\\Intern~1\\iexplore.EXE www.520music.com");       
                //MessageBoxW(NULL, Params->CommandLine.Buffer, L"OK", MB_OK);
                //char buf[30]={0};
                //itoa((ULONG)(void*)OldProc, buf, 16);
                //MessageBox(NULL, buf, "OK", MB_OK);
        }       
        return ((RTLDENORMALIZEPROCESSPARAMS)((int*)OldProc))(Params);
}
。。。。。。
{
。。。。。
HMODULE hd = GetModuleHandle("ntdll.dll");
                                FARPROC proceparm= GetProcAddress(hd, "RtlDeNormalizeProcessParams");
                                if(proceparm)
                                {                                       
                                        AfxHookCode((void*)proceparm, (void*)MyRtlDeNormalizeProcessParams, (void**)&OldProc, 5);                                       
                                }
。。。。。
}

现象:
   测试时,远程注入后,能正常hook住RtlDeNormalizeProcessParams函数,利用非explorer.exe进程打开url链接就能被重定向到qq主页,但如果是explorer进程,报如下错误
:“0x03624a20”指令引用“0x03624a20”指令,该内存不能“write",用windbg检查后发现这个地址就是OldProc指向的地址,内容就是被inline hook函数的前5字节。报这个错误应该是在call OldProc的时候IP指针没有加1,为什么为这样呢?很迷惑。小弟刚学inline,麻烦各位大虾给我看看是怎么回事,谢谢!

ps堆栈信息:
0:015> g
(5c0.b4): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=00000208 ebx=01380000 ecx=00000000 edx=0e840002 esi=4339c3cb edi=01380000
eip=03d04a20 esp=01a0c9f0 ebp=01a0ca30 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00010246
03d04a20 8bff            mov     edi,edi

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 0
支持
分享
最新回复 (13)
雪    币: 32
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
又是一个搞外挂的
2011-1-17 18:15
0
雪    币: 235
活跃值: (129)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
从报错那句来看,如果你没写错,表达的意思是那个函数的地址没有写权限(分配的stub 代码空间不可写?好象不应该),修改下memory protect看看.
不太清楚你用的什么hook库,看你写的代码,好象需要把oldproc初始值?
2011-1-17 21:15
0
雪    币: 250
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
感谢plume回复,“分配的stub 代码空间不可写”,我查看了explorer内存,是写进去了的,只是执行到那就出问题了,我后来用AdjustTokenPrivileges(SE_DEBUG_NAME)权限调试貌似问题依旧,至于hook库与oldproc初始值,就是常见的5字节jmp 替换型hook,oldproc负责跳回原函数5字节后(8b ff 55 8b ec e9 xxxx),卡在这好几天了,快疯了。。。。。

附加说明:RtlDeNormalizeProcessParams函数是调用CreateProcessInternalW函数后专门负责参数创建中的一个函数,勾这个函数主要目的就是测试需要,更改其传入参数。
2011-1-18 09:36
0
雪    币: 250
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
倒是与外挂无关,平时就做做测试哈
2011-1-18 09:48
0
雪    币: 235
活跃值: (129)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
我只是不清楚你用的库的具体实现方式,通常detour是inline hook最稳定的,而且你的hook错误地址那么巧合,我很怀疑是库的问题(自己写的)?如果把这个问题交给我,我认为最简单的方式是调试,毕竟执行过程中就那么几步,很容易发现.

我记得最早看到inline hook 的介绍就是hook后又写回原来函数,然后再hook,这种方式虽然可以通过同步机制解决,但始终不太可靠,我猜想你的是不是这个样子的?detour的实现方式是new出个stub代码,只需要保证安装hook时不会冲突,不必担心同步问题,而且如果知道detour的原理,自己分析指令长度也很容易写出detour的简版,你可以试下,写偏门时是还是自己实现比较好,小而且无依赖文件
2011-1-19 00:40
0
雪    币: 250
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
再次感谢plume,通过detour静态库达到了挂钩RtlDeNormalizeProcessParams函数的目的,explorer不在死了。不过原来挂钩的方式为什么就不对呢,还是有些迷惑,附上挂钩代码,忘高人解答:

bool AfxHookCode(void* TargetProc, void* NewProc,void ** l_OldProc, int bytescopy = 5)
{

        DWORD dwOldProtect;

        ::VirtualProtect((LPVOID)TargetProc, bytescopy, PAGE_EXECUTE_READWRITE, &dwOldProtect);

        *l_OldProc = new unsigned char[bytescopy+5];           // 为拷贝执行被覆盖的指令申请空间

        memcpy(*l_OldProc, TargetProc, bytescopy);            // 事先保存被破坏的指令

        *((unsigned char*)(*l_OldProc) + bytescopy) = 0xe9;     // 我的内存的代码执行完 跳到原来的 代码 + 破坏的代码的长度 上去

        //被破坏指令的长度      //E9 opcode长度           //算出偏移的OPCODE     = 被HOOK函数地址的地址 + 破坏指令的长度 - 我分配内存的结束地址                           
        *(unsigned int *)((unsigned char*)(*l_OldProc) +bytescopy           +      1)           =    (unsigned int)(TargetProc) + bytescopy - ( (unsigned int)((*l_OldProc)) + 5 + bytescopy ) ;   // 我内存代码跳到原来代码上的偏移

        *(unsigned char*)TargetProc =(unsigned char)0xe9;              //被HOOK的函数头改为jmp

        //算出偏移的OPCODE   = 代理函数地址 - 被HOOK函数地址
        *(unsigned int*)((unsigned int)TargetProc +1) = (unsigned int)NewProc - ( (unsigned int)TargetProc + 5) ; //被HOOK的地方跳到我的新过程 接受过滤

        ::VirtualProtect((LPVOID)TargetProc, bytescopy, dwOldProtect, 0);
        return true;
}

typedef
PPROCESS_PARAMETERS (__stdcall *RTLDENORMALIZEPROCESSPARAMS)(PPROCESS_PARAMETERS Params);

unsigned int *   OldProc;

PPROCESS_PARAMETERS WINAPI
MyRtlDeNormalizeProcessParams(PPROCESS_PARAMETERS Params)
{       
        。。。。
return ((RTLDENORMALIZEPROCESSPARAMS)(OldProc))(Params);
}

HMODULE hd = GetModuleHandle("ntdll.dll");
        FARPROC proceparm= GetProcAddress(hd, "RtlDeNormalizeProcessParams");
        if(proceparm)
        {         
          AfxHookCode((void*)proceparm, (void*)MyRtlDeNormalizeProcessParams, (void**)&OldProc, 5);         
        }
2011-1-19 15:21
0
雪    币: 235
活跃值: (129)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
兄弟每次都太客气了,我都不好意思拉,呵呵
你这个函数是detour的简版,detour之所以稳定的原因是加入了对修改代码长度的智能判断(甚至包括了对被修改指令的付作用的评估,例如指令受eip的影响),你的函数中有个缺省参数默认值为5,貌似大部分情况是符合的,但如果5字节不是1到多条的完整指令,就会存在问题,也就是你要对这个参数重新赋值的原因.对代码只作了初步的判断,可能还有别的问题,但这个是最浅显的潜在bug
2011-1-19 22:47
0
雪    币: 235
活跃值: (129)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
另外如果我没记错detour比你的用的函数少一个参数,这也是detour优秀的一个地方,从最终用户的角度看待逻辑(有点类似面向对象的思想了).还有detour的另一个优点是有一个线程保护的机制,当某线程指令正好位于要修改的函数的修改范围,会调整其eip(这是个被动机制),也就是你常看到别人代码里调用一个线程相关的detour api的原因,具体是什么忘记了,呵呵
2011-1-19 22:58
0
雪    币: 250
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
恩,兄弟说的很对哈5字节inline函数开头貌似这样mov edi, edi;   push ebp;  mov ebp, esp.除此之外还有7字节,10字节,某些情况下,也可以不定字节数,看各人需要,论坛上有人曾提出修改mov edi,edi第一个字节mov指令为int指令,inline 中断向量为FF的中断函数,还是好好膜拜哈大牛,多多学习才是。
2011-1-20 09:25
0
雪    币: 0
活跃值: (954)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
11
还有种写法,更简单。

//改函数头5字节
asm
  pushad  
  mov   edi, addr
  mov   esi, opcode
  mov   ecx, 5
  rep   movsb
popad

asm
    //保存原函数
    lea   edi, bak_cls
    mov   esi, address
    mov   ecx, 5
    rep   movsb
   
    lea   edi, New_cls
    lea   eax, _closesocket
    mov   ebx, Address
    sub   eax, ebx
    sub   eax, 5
    mov   byte ptr [edi], 0e9h
    mov   dword ptr [edi + 1], eax
end;
2011-1-20 10:15
0
雪    币: 250
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
游侠的inline就是5字节hook的汇编版本,像plume兄说的一样,如果某个函数而不是你这里的closesocket,就有可能从指令中间截断,造成程序运行错误哦
2011-1-20 14:46
0
雪    币: 0
活跃值: (954)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
13
这个我也有办法解决,只是贴了一个精简的写法。
2011-1-20 14:54
0
雪    币: 250
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
解决方法是不是也需要user用之前确定挂钩字节数,并以参数形式传入嘛。
2011-1-20 17:13
0
游客
登录 | 注册 方可回帖
返回
//