Skip to content

Commit

Permalink
Merge pull request #22 from rockbruno/deobfuscate-logs
Browse files Browse the repository at this point in the history
Log deobfuscation / Plist features
  • Loading branch information
Bruno Rocha authored Sep 24, 2018
2 parents 93fb3f2 + d53c1d5 commit 3fe6440
Show file tree
Hide file tree
Showing 33 changed files with 1,452 additions and 167 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@

*.profraw
14 changes: 11 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,14 +43,15 @@ class fjiovh4894bvic: XbuinvcxoDHFh3fjid {
```


## 💥 Dealing with encrypted crash logs / analytics
## 💥 Deobfuscating encrypted Crash logs

After succesfully encrypting your project, SwiftShield generates a `conversionMap.txt` file with all the changes it made to your project, allowing you to pinpoint what an encrypted object really is.
After succesfully encrypting your project, SwiftShield will generate an output folder containing a `conversionMap.txt` file containing with all the changes it made to your project. allowing you to pinpoint what an encrypted object really is.

````
//
// SwiftShield
// Conversion Map
// Automatic mode for MyApp 2.0 153, 2018-09-24 10.23.48
//
Data:
Expand All @@ -60,6 +61,13 @@ AppDelegate ===> uJXJkhVbwdQGNhh
SuperImportantClassThatShouldBeHidden ===> GDqKGsHjJsWQzdq
````

You can use this file to automatically deobfuscate any kind of text-based crash file by running:

```
swiftshield -deobfuscate CRASH_FILE -deobfuscate-map PATH_TO_CONVERSION_MAP
```

<img src="https://i.imgur.com/qMKy84P.png" alt="SwiftShield logo" height="172">

## 🚨 Requirements

Expand All @@ -72,7 +80,7 @@ If one or more modules/extensions of your app fail to satify these conditions, y
4. Latest Swift version and Xcode command line tools (works on all versions, but might have different results due to different SourceKit versions)
5. Make sure your project doesn't contain one of [SourceKit's bugs](SOURCEKITISSUES.md). Although the bugs won't prevent the project from being obfuscated, some of them might require some manual fixing afterwards.

If your project contains app extensions that use the `NSPrincipalClass` or `NSExtensionPrincipalClass` properties in their `Info.plist` (like Rich Notifications), you'll have to manually update such properties with the obfuscated name. This is going to be automated in future releases, but you can also avoid this by not obfuscating the extensions with `-ignore-modules`.
(App Extensions that use `NSExtensionPrincipalClass` or variants in their `Info.plist` (like Rich Notifications/Watch apps) will have such references obfuscated as well, but will assume that you haven't changed them from their default `$(PRODUCT_MODULE_NAME).ClassName` value. If you modified these plists to point to classes in different modules, you'll have to manually change them after running this tool.)

### Manual mode:

Expand Down
Binary file not shown.
16 changes: 16 additions & 0 deletions SwiftShieldExample/SwiftShieldExample/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -41,5 +41,21 @@
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>NSExtensionPrincipalClass</key>
<string>$(PRODUCT_MODULE_NAME).AClass</string>
<key>WKExtensionDelegateClassName</key>
<string>$(PRODUCT_MODULE_NAME).AClass</string>
<key>CLKComplicationPrincipalClass</key>
<string>$(PRODUCT_MODULE_NAME).AClass</string>
<key>New item</key>
<dict>
<key>NSExtensionPrincipalClass</key>
<string>$(PRODUCT_MODULE_NAME).AClass</string>
<key>New item</key>
<dict>
<key>WKExtensionDelegateClassName</key>
<string>$(PRODUCT_MODULE_NAME).AClass</string>
</dict>
</dict>
</dict>
</plist>
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,10 @@
import XCTest

class AutomaticSwiftShieldTests: XCTestCase {
func testObfuscationDataCreation() {
let modules: [Module] = [Module(name: "test", sourceFiles: [], xibFiles: [File(filePath: "/Users/bruno.rocha/Desktop/test/test/BLABLA.xib"), File(filePath: "/Users/bruno.rocha/Desktop/test/test/Base.lproj/LaunchScreen.storyboard"), File(filePath: "/Users/bruno.rocha/Desktop/test/test/Base.lproj/Main.storyboard")], compilerArguments: []), Module(name: "MyLib", sourceFiles: [], xibFiles: [File(filePath: "/Users/bruno.rocha/Desktop/test/RapiddoUtils/Sources/Assets/StatusLine.xib")], compilerArguments: [])]
let protector = AutomaticSwiftShield(basePath: "abc", projectToBuild: "abc", schemeToBuild: "abc", modulesToIgnore: [], protectedClassNameSize: 0)
let obfuscationData = protector.getObfuscationData(from: modules)
XCTAssertEqual(obfuscationData.storyboardsToObfuscate, modules.flatMap { $0.xibFiles })
XCTAssertEqual(obfuscationData.moduleNames, ["test", "MyLib"])
}

func testObfuscator() {
let obfuscationData = ObfuscationData()
let obfuscationData = AutomaticObfuscationData()
obfuscationData.obfuscationDict["ViewController"] = "AAAAA"
obfuscationData.obfuscationDict["CustomViewController"] = "BBBBB"
obfuscationData.obfuscationDict["CustomViewController"] = "BBBBBBBBBBBBBBBBBBB"
obfuscationData.obfuscationDict["++++"] = "SHOULDNOTWORK"
obfuscationData.obfuscationDict["myProperty"] = "CCCCC"
obfuscationData.obfuscationDict["MyType"] = "DDDDD"
Expand All @@ -42,4 +34,27 @@ class AutomaticSwiftShieldTests: XCTestCase {
let expectedFile = String(data: expectedFileData, encoding: .utf8)!
XCTAssertEqual(obfuscatedFile, expectedFile)
}

func testPlistExtractor() {
let protector = AutomaticSwiftShield(basePath: "abc", projectToBuild: "abc", schemeToBuild: "abc", modulesToIgnore: [], protectedClassNameSize: 0)
let plist = path(for: "MockPlist", ofType: "plist")
let file = File(filePath: plist)
let data = protector.getPlistVersionAndNumber(file)!
XCTAssertEqual("1.0", data.0)
XCTAssertEqual("1", data.1)
}

func testPlistPrincipalClassObfuscation() {
let protector = AutomaticSwiftShield(basePath: "abc", projectToBuild: "abc", schemeToBuild: "abc", modulesToIgnore: [], protectedClassNameSize: 0)
let plist = path(for: "MockPlist", ofType: "plist")
let file = MockFile(path: plist)
let obfuscationData = AutomaticObfuscationData(modules: [Module(name: "mock", plists: [file])])
obfuscationData.obfuscationDict["AClass"] = "ZZZZZ"
protector.obfuscateNSPrincipalClassPlists(obfuscationData: obfuscationData)
let expectedPlistData = loadFile("MockPlistObfuscatedPrincipalClass", ofType: "plist")
let expectedPlistString = String(data: expectedPlistData, encoding: .utf8)!
let origXml = try! AEXMLDocument(xml: file.writtenData)
let expectedXml = try! AEXMLDocument(xml: expectedPlistString)
XCTAssertEqual(origXml.xml, expectedXml.xml)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
class ViewController__s: CustomVC__s {

@IBAction func myMethod__s(_ sender: Any) {}
public static func ++++(lhs: ViewController__s, rhs: ViewController__s) {}

public var myProperty__s: MyType__s = ""

override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
print(ViewController__s.fakeMethod__s())
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
class AAAAA: BBBBB {
class AAAAA: BBBBBBBBBBBBBBBBBBB {

@IBAction func FFFFF(_ sender: Any) {}
public static func ++++(lhs: AAAAA, rhs: AAAAA) {}
Expand Down
61 changes: 61 additions & 0 deletions SwiftShieldTests/AutomaticSwiftShieldTests/MockPlist.plist
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIMainStoryboardFile</key>
<string>Main</string>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>
</array>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>NSExtensionPrincipalClass</key>
<string>$(PRODUCT_MODULE_NAME).AClass</string>
<key>WKExtensionDelegateClassName</key>
<string>$(PRODUCT_MODULE_NAME).AClass</string>
<key>CLKComplicationPrincipalClass</key>
<string>$(PRODUCT_MODULE_NAME).AClass</string>
<key>New item</key>
<dict>
<key>NSExtensionPrincipalClass</key>
<string>$(PRODUCT_MODULE_NAME).AClass</string>
<key>New item</key>
<dict>
<key>WKExtensionDelegateClassName</key>
<string>$(PRODUCT_MODULE_NAME).AClass</string>
</dict>
</dict>
</dict>
</plist>
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIMainStoryboardFile</key>
<string>Main</string>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>
</array>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>NSExtensionPrincipalClass</key>
<string>$(PRODUCT_MODULE_NAME).ZZZZZ</string>
<key>WKExtensionDelegateClassName</key>
<string>$(PRODUCT_MODULE_NAME).ZZZZZ</string>
<key>CLKComplicationPrincipalClass</key>
<string>$(PRODUCT_MODULE_NAME).ZZZZZ</string>
<key>New item</key>
<dict>
<key>NSExtensionPrincipalClass</key>
<string>$(PRODUCT_MODULE_NAME).ZZZZZ</string>
<key>New item</key>
<dict>
<key>WKExtensionDelegateClassName</key>
<string>$(PRODUCT_MODULE_NAME).ZZZZZ</string>
</dict>
</dict>
</dict>
</plist>
26 changes: 26 additions & 0 deletions SwiftShieldTests/DeobfuscatorTests/DeobfuscatorTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
//
// DeobfuscatorTests.swift
// SwiftShieldTests
//
// Created by Bruno Rocha on 9/22/18.
// Copyright © 2018 Bruno Rocha. All rights reserved.
//

import XCTest

class DeobfuscatorTests: XCTestCase {

let mockObfuscatedLog = "0 vn#nfibffffffff 0x10050090c specialized 38fhdb3i.383(bvjn9fjd, argument : ksadbDs) -> GHInfa (MyFile.swift:73)"
let mockDeobfuscatedLog = "0 SwiftShield 0x10050090c specialized AClass.myMethod(BClass, argument : CClass) -> DClass (MyFile.swift:73)"
let mockDict: [String: String] = ["SwiftShield": "vn#nfibffffffff", "AClass": "38fhdb3i", "myMethod": "383", "BClass": "bvjn9fjd", "CClass": "ksadbDs", "DClass": "GHInfa"]

func testRunner() {
let mockFile = MockFile(data: mockObfuscatedLog)
let obfuscationData = ObfuscationData()
obfuscationData.obfuscationDict = mockDict
let mapOutput = Protector.mapData(from: obfuscationData, info: "")
let mockMapFile = MockFile(data: mapOutput)
Deobfuscator.deobfuscate(file: mockFile, mapFile: mockMapFile)
XCTAssertEqual(mockFile.writtenData, mockDeobfuscatedLog)
}
}
19 changes: 19 additions & 0 deletions SwiftShieldTests/DeobfuscatorTests/MockFile.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import Foundation

final class MockFile: File {
let data: String
var writtenData: String = ""

init(data: String? = nil, path: String = "") {
self.data = data ?? ""
super.init(filePath: path)
}

override func read() -> String {
return data
}

override func write(_ text: String) {
writtenData = text
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
//
// AutomaticSwiftShieldTests.swift
// SwiftShieldTests
//
// Created by Bruno Rocha on 9/24/18.
// Copyright © 2018 Bruno Rocha. All rights reserved.
//

import XCTest

class ManualSwiftShieldTests: XCTestCase {
func testObfuscator() {
let ss = ManualSwiftShield(basePath: "abc", tag: "__s", protectedClassNameSize: 32)
let obfuscationData = ObfuscationData()
obfuscationData.obfuscationDict["ViewController__s"] = "AAAAA"
obfuscationData.obfuscationDict["CustomVC__s"] = "BBBBBBBBBBBBBBBBBBB"
obfuscationData.obfuscationDict["myProperty__s"] = "CCCCC"
obfuscationData.obfuscationDict["MyType__s"] = "DDDDD"
obfuscationData.obfuscationDict["fakeMethod__s"] = "EEEEE"
obfuscationData.obfuscationDict["myMethod__s"] = "FFFFF"
let originalFileData = loadFile("MockManualOriginalFile", ofType: "txt")
let originalFile = String(data: originalFileData, encoding: .utf8)!
let obfuscatedFile = ss.obfuscateReferences(fileString: originalFile, obfsData: obfuscationData)
let expectedFileData = loadFile("MockObfuscatedFile", ofType: "txt")
let expectedFile = String(data: expectedFileData, encoding: .utf8)!
print(obfuscatedFile)
XCTAssertEqual(obfuscatedFile, expectedFile)
}
}
Loading

0 comments on commit 3fe6440

Please sign in to comment.