@@ -17,6 +17,10 @@ import SwiftRemoteMirror
17
17
import Foundation
18
18
import SwiftInspectClientInterface
19
19
20
+ internal var WAIT_TIMEOUT_MS : DWORD {
21
+ DWORD ( SwiftInspectClientInterface . WAIT_TIMEOUT_MS)
22
+ }
23
+
20
24
internal final class WindowsRemoteProcess : RemoteProcess {
21
25
public typealias ProcessIdentifier = DWORD
22
26
public typealias ProcessHandle = HANDLE
@@ -268,7 +272,6 @@ internal final class WindowsRemoteProcess: RemoteProcess {
268
272
// memory and event objects
269
273
let bufSize = Int ( BUF_SIZE)
270
274
let sharedMemoryName = " \( SHARED_MEM_NAME_PREFIX) - \( String ( dwProcessId) ) "
271
- let waitTimeoutMs = DWORD ( WAIT_TIMEOUT_MS)
272
275
273
276
// Set up the shared memory
274
277
let hMapFile = CreateFileMappingA (
@@ -309,19 +312,18 @@ internal final class WindowsRemoteProcess: RemoteProcess {
309
312
return
310
313
}
311
314
312
- // Load the dll and start the heap walk
313
- guard
314
- let remoteAddrs = findRemoteAddresses (
315
- dwProcessId: dwProcessId, moduleName: " KERNEL32.DLL " ,
316
- symbols: [ " LoadLibraryW " , " FreeLibrary " ] )
317
- else {
315
+ guard let aEntryPoints = find ( module: " KERNEL32.DLL " ,
316
+ symbols: [ " LoadLibraryW " , " FreeLibrary " ] ,
317
+ in: dwProcessId) ? . map ( {
318
+ unsafeBitCast ( $0, to: LPTHREAD_START_ROUTINE . self)
319
+ } ) else {
318
320
print ( " Failed to find remote LoadLibraryW/FreeLibrary addresses " )
319
321
return
320
322
}
321
- let ( loadLibraryAddr, pfnFreeLibrary) = ( remoteAddrs [ 0 ] , remoteAddrs [ 1 ] )
323
+
324
+ let ( pfnLoadLibraryW, pfnFreeLibrary) = ( aEntryPoints [ 0 ] , aEntryPoints [ 1 ] )
322
325
let hThread : HANDLE = CreateRemoteThread (
323
- self . process, nil , 0 , loadLibraryAddr,
324
- dllPathRemote, 0 , nil )
326
+ self . process, nil , 0 , pfnLoadLibraryW, dllPathRemote, 0 , nil )
325
327
if hThread == HANDLE ( bitPattern: 0 ) {
326
328
print ( " CreateRemoteThread failed \( GetLastError ( ) ) " )
327
329
return
@@ -342,7 +344,7 @@ internal final class WindowsRemoteProcess: RemoteProcess {
342
344
343
345
// The main heap iteration loop.
344
346
outer: while true {
345
- let wait = WaitForSingleObject ( hReadEvent, waitTimeoutMs )
347
+ let wait = WaitForSingleObject ( hReadEvent, WAIT_TIMEOUT_MS )
346
348
if wait != WAIT_OBJECT_0 {
347
349
print ( " WaitForSingleObject failed \( wait) " )
348
350
return
@@ -378,7 +380,7 @@ internal final class WindowsRemoteProcess: RemoteProcess {
378
380
}
379
381
}
380
382
381
- let wait = WaitForSingleObject ( hThread, waitTimeoutMs )
383
+ let wait = WaitForSingleObject ( hThread, WAIT_TIMEOUT_MS )
382
384
if wait != WAIT_OBJECT_0 {
383
385
print ( " WaitForSingleObject on LoadLibrary failed \( wait) " )
384
386
return
@@ -435,43 +437,33 @@ internal final class WindowsRemoteProcess: RemoteProcess {
435
437
///
436
438
/// Performs the necessary clean up to remove the injected code from the
437
439
/// instrumented process once the heap walk is complete.
438
- private func eject( module dllPathRemote: UnsafeMutableRawPointer ,
439
- from dwProcessId: DWORD ,
440
- _ freeLibraryAddr: LPTHREAD_START_ROUTINE ) -> Bool {
441
- // Get the dll module handle in the remote process to use it to
442
- // unload it below.
443
-
444
- // GetExitCodeThread returns a DWORD (32-bit) but the HMODULE
445
- // returned from LoadLibraryW is a 64-bit pointer and may be truncated.
446
- // So, search for it using the snapshot instead.
447
- guard let hModule = find ( module: " SwiftInspectClient.dll " , in: dwProcessId) else {
440
+ private func eject( module pwszModule: UnsafeMutableRawPointer ,
441
+ from process: DWORD ,
442
+ _ pfnFunction: LPTHREAD_START_ROUTINE ) -> Bool {
443
+ // Deallocate the dll path string in the remote process
444
+ if !VirtualFreeEx( self . process, pwszModule, 0 , DWORD ( MEM_RELEASE) ) {
445
+ print ( " VirtualFreeEx failed: \( GetLastError ( ) ) " )
446
+ }
447
+
448
+ // Get the dll module handle in the remote process to use it to unload it
449
+ // below. `GetExitCodeThread` returns a `DWORD` (32-bit) but the `HMODULE`
450
+ // pointer-sized and may be truncated, so, search for it using the snapshot
451
+ // instead.
452
+ guard let hModule = find ( module: " SwiftInspectClient.dll " , in: process) else {
448
453
print ( " Failed to find the client dll " )
449
454
return false
450
455
}
456
+
451
457
// Unload the dll from the remote process
452
- let hUnloadThread = CreateRemoteThread (
453
- self . process, nil , 0 , freeLibraryAddr,
454
- UnsafeMutableRawPointer ( hModule) , 0 , nil )
455
- if hUnloadThread == HANDLE ( bitPattern: 0 ) {
458
+ guard let hThread = CreateRemoteThread ( self . process, nil , 0 , pfnFunction,
459
+ hModule, 0 , nil ) else {
456
460
print ( " CreateRemoteThread for unload failed \( GetLastError ( ) ) " )
457
461
return false
458
462
}
459
- defer { CloseHandle ( hUnloadThread) }
460
- let unload_wait = WaitForSingleObject ( hUnloadThread, DWORD ( WAIT_TIMEOUT_MS) )
461
- if unload_wait != WAIT_OBJECT_0 {
462
- print ( " WaitForSingleObject on FreeLibrary failed \( unload_wait) " )
463
- return false
464
- }
465
- var unloadExitCode : DWORD = 0
466
- GetExitCodeThread ( hUnloadThread, & unloadExitCode)
467
- if unloadExitCode == 0 {
468
- print ( " FreeLibrary failed " )
469
- return false
470
- }
463
+ defer { CloseHandle ( hThread) }
471
464
472
- // Deallocate the dll path string in the remote process
473
- if !VirtualFreeEx( self . process, dllPathRemote, 0 , DWORD ( MEM_RELEASE) ) {
474
- print ( " VirtualFreeEx failed GLE= \( GetLastError ( ) ) " )
465
+ guard WaitForSingleObject ( hThread, WAIT_TIMEOUT_MS) == WAIT_OBJECT_0 else {
466
+ print ( " WaitForSingleObject on FreeLibrary failed \( GetLastError ( ) ) " )
475
467
return false
476
468
}
477
469
@@ -513,19 +505,12 @@ internal final class WindowsRemoteProcess: RemoteProcess {
513
505
return hModule
514
506
}
515
507
516
- private func findRemoteAddresses( dwProcessId: DWORD , moduleName: String , symbols: [ String ] )
517
- -> [ LPTHREAD_START_ROUTINE ] ?
518
- {
519
- guard let hDllModule = find ( module: moduleName, in: dwProcessId) else {
520
- print ( " Failed to find remote module \( moduleName) " )
508
+ private func find( module: String , symbols: [ String ] , in process: DWORD ) -> [ FARPROC ] ? {
509
+ guard let hModule = find ( module: module, in: process) else {
510
+ print ( " Failed to find remote module \( module) " )
521
511
return nil
522
512
}
523
- var addresses : [ LPTHREAD_START_ROUTINE ] = [ ]
524
- for sym in symbols {
525
- addresses. append (
526
- unsafeBitCast ( GetProcAddress ( hDllModule, sym) , to: LPTHREAD_START_ROUTINE . self) )
527
- }
528
- return addresses
513
+ return symbols. map { GetProcAddress ( hModule, $0) }
529
514
}
530
515
531
516
private func createEventPair( _ dwProcessId: DWORD ) -> ( HANDLE , HANDLE ) ? {
0 commit comments