本站首页    管理页面    写新日志    退出


«August 2025»
12
3456789
10111213141516
17181920212223
24252627282930
31


公告

戒除浮躁,读好书,交益友


我的分类(专题)

日志更新

最新评论

留言板

链接

Blog信息
blog名称:邢红瑞的blog
日志总数:523
评论数量:1142
留言数量:0
访问次数:9692702
建立时间:2004年12月20日




[rootkit]从connect函数看stack frame 
原创空间,  软件技术,  电脑与网络

邢红瑞 发表于 2008/1/17 10:45:58

 高级语言都使用stack frame传递函数参数,机器码和汇编语言除外,至少CISC的cpu如此,RISC类型cpu寄存器众多,可以不使用stack frame。下面以stdcall调用作为例子,也就是WINDOWS API,参数从右向左入栈,其中EBP作为一个参考指针也入栈.return address是返回地址非返回值!被调用函数负责清栈,函数的最后就是ret 0c。当调用函数(CALL   FUN)时,CPU把当时的地址(IP值)压栈,再跳到函数的地址处,函数返回时,CPU再把恢复原来的地址。存ebp的原因是你要使用ebp,而一般函数调用约定不更允许调用函数返回后ebp的值被更改——因为调用者也要使用ebp。另外,Windows的函数调用还隐含规定,索引寄存器edi、esi的值不允许被更改。如果你要用到,必须先保存,用完后再恢复。堆栈段 ss 只能用 esp或ebp寄存器 其他的寄存器eax ebx edx等都不能够用 而 esp永远指向堆栈栈顶 ebp用来在堆栈段里面寻址push 指令是压栈 ESP=ESP-4pop  指令是出栈 ESP=ESP+4    返回地址其实就是调用者call指令的下一条指令地址,当执行call指令时硬件负责将其压栈,在被调函数返回执行ret指令时,由硬件负责从当前栈顶取出返回地址,并转移到返回地址继续执行——除非你明确地知道这是怎么回事,否则不要自己在程序中更改返回地址。500)this.width=500'> 使用od研究一下,winsock的connect函数。以telnet作为例子,打开od,加载telnet,在命令框中输入 bpx connect,如果没有命令框,请装相应的插件。然后运行,输入 open 192.168.31.183,这是一个telnet服务器。此时,程序停留在断点处。71A2406A >  8BFF            mov edi,edi71A2406C    55              push ebp71A2406D    8BEC            mov ebp,esp71A2406F    83EC 18         sub esp,1871A24072    57              push edi71A24073    8D45 E8         lea eax,dword ptr ss:[ebp-18]71A24076    50              push eax71A24077    8D45 EC         lea eax,dword ptr ss:[ebp-14]71A2407A    50              push eax71A2407B    FF15 2840A371   call dword ptr ds:[71A34028]      ; WS2_32.71A2263671A24081    33FF            xor edi,edi71A24083    3BC7            cmp eax,edi71A24085    8945 FC         mov dword ptr ss:[ebp-4],eax71A24088    0F85 D9010000   jnz WS2_32.71A2426771A2408E    FF75 08         push dword ptr ss:[ebp+8]71A24091    E8 ABEAFFFF     call WS2_32.71A22B4171A24096    3BC7            cmp eax,edi71A24098    8945 F0         mov dword ptr ss:[ebp-10],eax 此时,输入 dd esp ,此时的esp已不是进入时的esp了。不要忘了栈里面还有一个返回地址,显示 00A4EE68   010057DA  /CALL 到 connect 来自 telnet.010057D400A4EE6C   000000F8  |Socket = F800A4EE70   000AF158  |pSockAddr = 000AF15800A4EE74   00000010  \AddrLen = 10 (16.) 注意 010057DA 就是函数的返回地址,后面的就是connect的参数msdn的说明int connect(  SOCKET s,  const struct sockaddr FAR* name,  int namelen); 因为windows在x86的平台的stack是grow down ,向下增长的,函数是从右向左传递的,namelen最先入栈,最后是s,但由于是向下增长的,大家看到了上面的情况。esp+4 就是socket,我们主要看第二个参数 struct sockaddr_in {        short   sin_family;        u_short sin_port;        struct  in_addr sin_addr;        char    sin_zero[8];};输入 dd [esp+8]显示000AF158  17000002000AF15C  B71FA8C0000AF160  00000000000AF164  00000000AF_  地址族,序号为2,所以最后是2,注意 B71FA8C0 ,转为 ip就是 183.31.168.192,这就是ip地址,后面的参数添0,对齐为8的倍数,防止不同的编译器为了字节对齐,自己添0.大家注意一下,>71A2406A >  8BFF            mov edi,edi>71A2406C    55              push ebp>71A2406D    8BEC            mov ebp,esp有的机子是 >71A2406C    55              push ebp>71A2406D    8BEC            mov ebp,esp前面地址可以不要管,为什麽不同呢?这就是微软的同步码,70%的以上的Windows API都有这个同步码。winsows xp sp2 是5位,多了mov edi,edi, winsows xp sp1 windows 2000和2003各版本都是3位,为什麽呢?因为 jmp XXXXXXXX ,后面是一个32bit的地址,x86是32位的,jmp后面是立即操作数的编码是E9,加上后面的地址,正好是5位,微软主要是为了自己升级补丁或打sp时,OS不用重启,只是一个地址跳转,必要的时候,可以跳回去。如果是3位,麻烦就大了,必须破坏原来的函数的地址,因为一个跳转需要5位,原来的同步码有3位,还要保存原来函数地址空间的数据,否则修改后,再次调用原来的函数时,必须恢复,使用5位同步码,大大降低了黑客程序的难度,不用保存原来地址的数据。MmHotpatchRoutine就是这么做的。各位看明白了没有,其实这位黑客的留下了方便之门,5位的同步码,黑客可以轻而易举的改变connect函数,这个函数作用不大,主要是send和recv。黑客可以先loadlibrary ws2_32.dll,然后得到send和recv的地址,修改他们 ,jmp到自己的dll函数内部,得到数据后,再拆去钩子,调用原来的send和recv,发送。这就是外挂程序的原理,著名外挂WPE也是大同小异。


阅读全文(6642) | 回复(0) | 编辑 | 精华
 



发表评论:
昵称:
密码:
主页:
标题:
验证码:  (不区分大小写,请仔细填写,输错需重写评论内容!)



站点首页 | 联系我们 | 博客注册 | 博客登陆

Sponsored By W3CHINA
W3CHINA Blog 0.8 Processed in 0.047 second(s), page refreshed 144765530 times.
《全国人大常委会关于维护互联网安全的决定》  《计算机信息网络国际联网安全保护管理办法》
苏ICP备05006046号