点击蓝字 关注我们
(本文由小貂快跑代发,原作者为“Ting”)
01
背景
02
介绍
03
base64编码混淆
原理
即对原始的shellcode进行base64编码,让其与原始的shellcode“样貌”不一,掩盖掉原始shellcode的静态特征,防止杀软辨识出来。
import base64
def base64_encode(data):
# 将字符串编码为字节流
encoded_bytes = base64.b64encode(data.encode('utf-8'))
# 将字节流解码为字符串
encoded_string = encoded_bytes.decode('utf-8')
return encoded_string
def base64_decode(encoded_string):
# 将字符串编码为字节流
encoded_bytes = encoded_string.encode('utf-8')
# 将字节流解码为字符串
decoded_bytes = base64.b64decode(encoded_bytes)
# 将字节流解码为字符串
decoded_string = decoded_bytes.decode('utf-8')
return decoded_string
# 测试加密和解密
data = "shellcode"
encoded_data = base64_encode(data)
print("编码后:", encoded_data)
decoded_data = base64_decode(encoded_data)
print("解码后:", decoded_data)
04
AES加密
原理
自己创建一个key,使用这个key对原始shellcode进行加密,修改其“样貌”,修改其静态特征。
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
from Crypto.Random import get_random_bytes
def encrypt(plaintext, key):
# 使用ECB模式
cipher = AES.new(key, AES.MODE_ECB)
ciphertext = cipher.encrypt(pad(plaintext, AES.block_size))
return ciphertext
def decrypt(ciphertext, key):
# 使用ECB模式
cipher = AES.new(key, AES.MODE_ECB)
plaintext = unpad(cipher.decrypt(ciphertext), AES.block_size)
return plaintext
# 生成随机密钥
key = get_random_bytes(16)
# 要加密的明文
plaintext = b"shellcode"
# 加密
ciphertext = encrypt(plaintext, key)
print("加密后:", ciphertext)
# 解密
decrypted_text = decrypt(ciphertext, key)
print("解密后:", decrypted_text)
05
异或加密
原理
一段二进制代码,在异或两次之后即可还原为原来的二进制码,举个例子就明白咯:
#include <stdio.h>
#include <string.h>
char shellcode[] = "shellcode";
void xor_encrypt_decrypt(size_t shellcodeSize) {
for (int i = 0; i < shellcodeSize; i++)
{
shellcode[i] ^= 0x5b;
}
}
int main() {
//获取shellcode大小
size_t shellcodeSize = strlen(shellcode);
//第一次异或
xor_encrypt_decrypt(shellcodeSize);
printf("第一次异或后:%sn", shellcode);
//第二次异或,即复原
xor_encrypt_decrypt(shellcodeSize);
printf("第二次异或后:%sn", shellcode);
return 0;
}
06
偏移量混淆
原理
这个混淆方式挺巧妙的。它不会直接存shellcode(不论加密与否)在loader中,而是存shellcode对应的字符在所有通用设备都固有的文件中的位置,生成一个存放位置的数组,再利用存放位置的数组里的元素缩影,一个个取出来去编码后的文件里面寻找对于字符,将他们重新组装成shellcode。如果还是不理解的话试试看流程图呢:
import codecs
#获取win.ini的二进制编码
with open("C:Windowswin.ini", 'rb') as file:
content = file.read()
new_file = codecs.encode(content, 'hex').decode()
#获取shellcode的二进制编码
with open("shellcode.bin", 'rb') as file:
shellcode = file.read()
new_shellcode = codecs.encode(shellcode, 'hex').decode()
#遍历查找对应的位置,并添加到数字list中
list = []
for a in new_file:
offset = new_file.find(a)
list.append(offset)
print(list)
07
uuid混淆
原理
将shellcode的字节数用空字节填充为16的倍数,然后对没连续的16个字节的shellcode进去uuid加密,然后再在memcpy进去内存之后,进行解密执行即可
import uuid
#多写几个shellcode,体会一下uuid加密的前提是位数为16的倍数
shellcode = b'shellcode,shellcode,shellcode,shellcode'
def convertToUUID(shellcode):
#如果shellcode的长度不足16位数,则需要用空字节填充shellcode为16的倍数
if len(shellcode)%16 !=0:
#计算出需要填充空字节的数量
addNullbyte = b"x00" * (16-(len(shellcode)%16))
#拼接需要填充空字节的数量
shellcode += addNullbyte
uuids = []
# 每次取出shellcode的16个字节进行uuid转换
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(shellcode)
print(str(u).replace("'","""))
08
总结
// 作者:Ting
一名大学本科在校生,参加多次演练、众测项目,一次地级市演练红队第三,i春秋特聘作家。喜欢挖洞、渗透。目前在研究代码审计和免杀,梦想做一名资深红队~
原文始发于微信公众号(赛博游民营):免杀之Shell混淆
免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论