Skip to content

Commit 5ea814a

Browse files
committed
fix: bad recursive target selection
Signed-off-by: 82Flex <82flex@gmail.com>
1 parent 5ca2550 commit 5ea814a

3 files changed

Lines changed: 33 additions & 2 deletions

File tree

TrollFools/InjectorV3+Backup.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import Foundation
1010
extension InjectorV3 {
1111
// MARK: - Constants
1212

13-
private static let alternateSuffix = "troll-fools.bak"
13+
static let alternateSuffix = "troll-fools.bak"
1414

1515
static func alternateURL(for target: URL) -> URL {
1616
target.appendingPathExtension(Self.alternateSuffix)

TrollFools/InjectorV3+Bundle.swift

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,10 @@ extension InjectorV3 {
6363
enumerator.skipDescendants()
6464
continue
6565
}
66+
// Skip backup files created before injection
67+
if itemURL.path.hasSuffix(".\(Self.alternateSuffix)") {
68+
continue
69+
}
6670
if enumerator.level == 2 {
6771
enumeratedURLs.append(itemURL)
6872
if isMachO(itemURL) {
@@ -113,6 +117,30 @@ extension InjectorV3 {
113117
}
114118
}
115119

120+
// Filter out previously-injected Mach-Os by diffing current vs. backup load commands.
121+
// Any load command present in the current binary but absent from its backup was added by injection.
122+
var injectedAssetNames = Set<String>()
123+
for machO in (allMachOsInFrameworks.elements + [executableURL]) where hasAlternate(machO) {
124+
if let current = try? loadedDylibsOfMachO(machO),
125+
let original = try? loadedDylibsOfMachO(Self.alternateURL(for: machO))
126+
{
127+
for name in current where !original.contains(name) {
128+
injectedAssetNames.insert(URL(fileURLWithPath: name).lastPathComponent)
129+
}
130+
}
131+
}
132+
if !injectedAssetNames.isEmpty {
133+
let preFilterCount = machOs.count
134+
machOs = machOs.filter { !injectedAssetNames.contains($0.lastPathComponent) }
135+
let excludedCount = preFilterCount - machOs.count
136+
if excludedCount > 0 {
137+
DDLogInfo(
138+
"Excluded \(excludedCount) previously-injected Mach-Os by backup diff: \(injectedAssetNames.sorted())",
139+
ddlog: logger
140+
)
141+
}
142+
}
143+
116144
var sortedMachOs: [URL] =
117145
switch injectStrategy {
118146
case .lexicographic:

TrollFools/InjectorV3+MachO.swift

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,10 @@ extension InjectorV3 {
6666
var newCollected = collected
6767
newCollected.append(target)
6868

69-
let loadedDylibs = try loadedDylibsOfMachO(target).compactMap({ resolveLoadCommand($0) })
69+
// If the Mach-O has a backup (made before injection), read load commands
70+
// from the original to avoid picking up previously-injected dylibs.
71+
let readTarget = hasAlternate(target) ? Self.alternateURL(for: target) : target
72+
let loadedDylibs = try loadedDylibsOfMachO(readTarget).compactMap({ resolveLoadCommand($0) })
7073
for dylib in loadedDylibs {
7174
newCollected = try linkedDylibsRecursivelyOfMachO(dylib, collected: newCollected)
7275
}

0 commit comments

Comments
 (0)