shellcode加密绕过检测

为shellocde瘦身: 有时候同样的功能,也许会有不同的的长度的指令,我们应该尽量使用较短的指令:

xchg eax,reg    ;交换eax和其他寄存器中的值
lodsd           ;把esi指向的一个dword装入eax,并且增加esi
lodsb           ;把esi指向的一个byte装入al,并且增加esi
stosd           ;
stosb
pushad/popad    ;从栈中存储、恢复所有寄存器的值
cdq             ;用edx把eax扩展成四字。这条指令在eax<0x80000000时可用作mov edx.

妙用内存——另类的API调用方式

有些API中许多参数都是NULL,通常的做法是多次向栈中压入NULL。如果我们换一个思路,把栈中的一大片区域一次性全部置为NULL,在调用API的时候可以只压入那些非NULL的参数,从而节省出许多压栈指令。

我们经常遇到API中需要一个很大的结构体做参数的情况,大部分时候,健壮的API都可以允许两个结构体相互重叠,尤其是当一个参数是输入结构体,另一个参数是输出结构体时。这样基金使用一个字节的段指令push esp就可以代替一大段初始化结构体的代码。

色即是空,空即是色:

很多windows的API都会要求输入参数是一中特定的数据类型,或者要求特定的取值区间,虽然如此,通过实验我们发现,大多数API出于函数健壮性的考虑,在实现时已经对非法的参数做了正确的处理。

变废为宝:——调整栈顶回收数据

普通程序员不会直接与系统栈打交道,通常与栈沟通的总时编译器,在编译器看来,栈仅仅是用来保护函数调用断点,暂存函数输入参数和返回值等的场所。但是作为一个shellcode的开发人员,必须富有想象力。栈顶之上的数据在逻辑上视为废弃数据,但其物理内容实际上并没有遭到破坏,如果栈顶上有需要的数据,不妨调整esp的值将栈顶抬高,把他们保护起来以便后面使用,这样能节省出很多有用的数据初始化指令。

打破常规,巧用寄存器
按照默认的函数调用约定,在调用API时有些寄存器总时被保护在栈中。把函数调用信息存在寄存器中而不是存在栈中会给shellcode带来很多好处。比如大多数函数的运行过程中都不会使用EBP寄存器,故我们可以使用它来保存数据。

取其精华,去其糟粕——永痕的压缩法宝,hash

实用的shellcode通常需要超过200甚至300字节的机器码,所以对原始的二进制shellcode进行编码或者压缩是值得的,上节实验在搜索API函数名时,并没有在shellcode中存储原始的函数名,而是使用了函数名的摘要。在需要的API比较多的情况下,这样能够节省不少shellcode的篇幅;

选择恰当的hash算法

我们想要在shellcode中实现的功能如下

(1)绑定一个shell到6666端口

(2)允许外部网络连接使用这个shell

(3)程序能够正常退出。

这个shellcode应当具有较强的通用性,能够咋爱Windows NT4、windows2000、windowsxp和windows 2003上运行。开发过程中实际要解决的问题有这样两个。

(1)在不同的操作系统版本中,用通用 的方法定位所需API函数的 地址。

(2)调用这些API,完成shellcode的功能

实现shellcode需要的函数包括

1.kernel32.dll中的导出函数

LoadLibraryA     用来装载ws2_32.dll

CreateProcess    用来为客户创建一个shell命令窗口

ExitPocess      用于程序的正常退出

2.ws2_32.dll中的导出函数

WSAStartup     需要初始化winsock

WSASocketA      创建套接字

bind          绑定套接字到本地端口

listen        监听外部连接

accept        处理一个外部连接

下面是选择这中算法时需要考虑的因素:

(1)所需的每个库文件(dll)内所有导出函数的函数名经过hash后的摘要不能有碰撞。

(2)函数名经过hash后得到的摘要应该最短

可认为单字节的摘要是最佳的,kernel32.dll的导出表中有超过900个函数,8bit有256中可能,应该可行。

  (3)hash算法实现所需的代码篇幅最短

(4)经过hash后的摘要可等价于指令的机器码,即把数据也当作代码使用。

查看代码
 hash_loop:
    lodsb            ;把函数名中的一个字符装入al,并且esi+1,指向函数名中下一个字符
    xor al,0x71      ;用0x71异或当前的字符
    sub dl,al        ;更新dl中的hash值
    cmp al,0x71      ;继续循环,直到遇见字符串的结尾null
    jne hash_loop
    

 

posted @ 2024-03-10 10:26  robot__i  阅读(41)  评论(0)    收藏  举报