1
+ # Good Example of a DLL Injector
2
+ # Developed by -> numaru / https://github.com/numaru
3
+
4
+ import subprocess
5
+ from ctypes import (WinError , byref , c_int , c_long , c_ulong ,
6
+ create_string_buffer , windll )
7
+
8
+
9
+ class Injector :
10
+ PROC_ALL_ACCESS = (0x000F0000 | 0x00100000 | 0x00000FFF )
11
+ MEM_CREATE = 0x00001000 | 0x00002000
12
+ MEM_RELEASE = 0x8000
13
+ PAGE_EXECUTE_READWRITE = 0x40
14
+
15
+ def __init__ (self ):
16
+ self .kernel32 = windll .kernel32
17
+ self .user32 = windll .user32
18
+ self .pid = c_ulong ()
19
+ self .handle = None
20
+
21
+ def create_process (self , path ):
22
+ return subprocess .Popen ([path ]).pid
23
+
24
+ def load_from_pid (self , pid ):
25
+ self .unload ()
26
+ self .pid = c_ulong (pid )
27
+ self .handle = self .kernel32 .OpenProcess (self .PROC_ALL_ACCESS , 0 , pid )
28
+ if not self .handle :
29
+ raise WinError ()
30
+
31
+ def unload (self ):
32
+ if self .handle :
33
+ self .kernel32 .CloseHandle (self .handle )
34
+ if not self .handle :
35
+ raise WinError ()
36
+ self .handle = None
37
+
38
+ def alloc_remote (self , buffer , size ):
39
+ alloc = self .kernel32 .VirtualAllocEx (self .handle , None , c_int (size ),
40
+ self .MEM_CREATE , self .PAGE_EXECUTE_READWRITE )
41
+ if not alloc :
42
+ raise WinError ()
43
+ self .write_memory (alloc , buffer )
44
+ return alloc
45
+
46
+ def free_remote (self , addr , size ):
47
+ if not self .kernel32 .VirtualFreeEx (self .handle , addr , c_int (0 ), self .MEM_RELEASE ):
48
+ raise WinError ()
49
+
50
+ def get_address_from_module (self , module , function ):
51
+ module_addr = self .kernel32 .GetModuleHandleA (module .encode ("ascii" ))
52
+ if not module_addr :
53
+ raise WinError ()
54
+ function_addr = self .kernel32 .GetProcAddress (module_addr , function .encode ("ascii" ))
55
+ if not module_addr :
56
+ raise WinError ()
57
+ return function_addr
58
+
59
+ def create_remote_thread (self , function_addr , args ):
60
+ dll_addr = c_long (0 )
61
+ args_addr = self .alloc_remote (args , len (args ))
62
+ thread = self .kernel32 .CreateRemoteThread (self .handle , None , None , c_long (function_addr ),
63
+ c_long (args_addr ), None , None )
64
+ if not thread :
65
+ raise WinError ()
66
+ if self .kernel32 .WaitForSingleObject (thread , 0xFFFFFFFF ) == 0xFFFFFFFF :
67
+ raise WinError ()
68
+ if not self .kernel32 .GetExitCodeThread (thread , byref (dll_addr )):
69
+ raise WinError ()
70
+ self .free_remote (args_addr , len (args ))
71
+ return dll_addr .value
72
+
73
+ def read_memory (self , addr , size ):
74
+ buffer = create_string_buffer (size )
75
+ if not self .kernel32 .ReadProcessMemory (self .handle , c_long (addr ), buffer , size , None ):
76
+ raise WinError ()
77
+ return buffer
78
+
79
+ def write_memory (self , addr , string ):
80
+ size = len (string )
81
+ if not self .kernel32 .WriteProcessMemory (self .handle , addr , string , size , None ):
82
+ raise WinError ()
83
+
84
+ def load_library (self , buffer ):
85
+ function_addr = self .get_address_from_module ("kernel32.dll" , "LoadLibraryA" )
86
+ dll_addr = self .create_remote_thread (function_addr , buffer )
87
+ return dll_addr
88
+
89
+ def inject_dll (self , path ):
90
+ return self .load_library (path .encode ("ascii" ))
91
+
92
+ def call_from_injected (self , path , dll_addr , function , args ):
93
+ function_offset = self .get_offset_of_exported_function (path .encode ("ascii" ), function )
94
+ self .create_remote_thread (dll_addr + function_offset , args )
95
+
96
+ def get_offset_of_exported_function (self , module , function ):
97
+ base_addr = self .kernel32 .LoadLibraryA (module )
98
+ if not base_addr :
99
+ raise WinError ()
100
+ function_addr = self .kernel32 .GetProcAddress (base_addr , function .encode ("ascii" ))
101
+ if not function_addr :
102
+ raise WinError ()
103
+ if not self .kernel32 .FreeLibrary (base_addr ):
104
+ raise WinError ()
105
+ return function_addr - base_addr
0 commit comments