Skip to content

Commit

Permalink
Merge pull request #80 from hwdavr/enum-support
Browse files Browse the repository at this point in the history
Add obfuscation on Enum type and Enum elements
  • Loading branch information
rockbruno committed Jan 13, 2020
2 parents b1a5fa6 + 5a13d2d commit 7cc28fd
Show file tree
Hide file tree
Showing 13 changed files with 165 additions and 7 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ If one or more modules/extensions of your app fail to satify these conditions, y
2. No Objective-C classes that call Swift methods (Swift classes that call Objective-C methods are fine, except when interfacing is involved)
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.
6. Enum and enum elements will be obfuscated, except the enum name suffixed with `CodingKeys`. Make sure the name your the CodingKeys enum ending with `CodingKeys`.

(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.)

Expand Down
18 changes: 18 additions & 0 deletions SwiftShieldExample/SwiftShieldExample.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@

/* Begin PBXBuildFile section */
690E9FDA54E33AE150456400 /* Pods_SwiftShieldExample.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 906E79CBAAED7E65DB3DE1FF /* Pods_SwiftShieldExample.framework */; };
84F0B22C23C21BB4005CEE05 /* SwiftShieldSDK.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 846A66E623AFA38D005801B8 /* SwiftShieldSDK.framework */; };
84F0B22D23C21BB4005CEE05 /* SwiftShieldSDK.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 846A66E623AFA38D005801B8 /* SwiftShieldSDK.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
FD5360EF212DFC21004FB44F /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD5360EE212DFC21004FB44F /* AppDelegate.swift */; };
FD5360F1212DFC21004FB44F /* MyViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD5360F0212DFC21004FB44F /* MyViewController.swift */; };
FD5360F4212DFC21004FB44F /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = FD5360F2212DFC21004FB44F /* Main.storyboard */; };
Expand Down Expand Up @@ -39,6 +41,20 @@
};
/* End PBXContainerItemProxy section */

/* Begin PBXCopyFilesBuildPhase section */
84F0B22E23C21BB5005CEE05 /* Embed Frameworks */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "";
dstSubfolderSpec = 10;
files = (
84F0B22D23C21BB4005CEE05 /* SwiftShieldSDK.framework in Embed Frameworks */,
);
name = "Embed Frameworks";
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXCopyFilesBuildPhase section */

/* Begin PBXFileReference section */
846A66E023AFA38C005801B8 /* SwiftShieldSDK.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = SwiftShieldSDK.xcodeproj; path = SwiftShieldSDK/SwiftShieldSDK.xcodeproj; sourceTree = "<group>"; };
887E68FDACDAF78F3E840DBC /* Pods-SwiftShieldExample.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SwiftShieldExample.debug.xcconfig"; path = "Pods/Target Support Files/Pods-SwiftShieldExample/Pods-SwiftShieldExample.debug.xcconfig"; sourceTree = "<group>"; };
Expand All @@ -58,6 +74,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
84F0B22C23C21BB4005CEE05 /* SwiftShieldSDK.framework in Frameworks */,
690E9FDA54E33AE150456400 /* Pods_SwiftShieldExample.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand Down Expand Up @@ -135,6 +152,7 @@
FD5360E8212DFC21004FB44F /* Frameworks */,
FD5360E9212DFC21004FB44F /* Resources */,
9F318FF03689B66C34DE349D /* [CP] Embed Pods Frameworks */,
84F0B22E23C21BB5005CEE05 /* Embed Frameworks */,
);
buildRules = (
);
Expand Down
9 changes: 9 additions & 0 deletions SwiftShieldExample/SwiftShieldExample/MyViewController.swift
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import UIKit
import Cartography
import Unbox
import SwiftShieldSDK

final class MyView: UILabel {}

Expand All @@ -27,6 +28,7 @@ class MyViewController: UIViewController {
// myProp = myLet * 10
// MyViewController.myStaticVar = MyViewController.myClassVar + MyViewController.myStaticLet * 5
render()
sdkTest()
}

func render() {
Expand All @@ -43,4 +45,11 @@ class MyViewController: UIViewController {
let text: String = try! box.unbox(key: "text")
view.text = text
}

func sdkTest() {
let serializer = ShieldSerializer()
serializer.jsonContactsList()
let json = "[ { \"firstName\" : \"Bruce\", \"lastName\" : \"Lee\" }, { \"firstName\" : \"Jackie\", \"lastName\" : \"Chan\" } ]"
serializer.parseContactsList(json: json)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
846A66EA23AFA3E9005801B8 /* Person.swift in Sources */ = {isa = PBXBuildFile; fileRef = 846A66E923AFA3E9005801B8 /* Person.swift */; };
846A66EC23AFA49F005801B8 /* ContactsList.swift in Sources */ = {isa = PBXBuildFile; fileRef = 846A66EB23AFA49F005801B8 /* ContactsList.swift */; };
8492DB3023B100E10015D585 /* NameList.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8492DB2F23B100E10015D585 /* NameList.swift */; };
84D94A2723B798BE005FC134 /* NameEnum.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84D94A2623B798BE005FC134 /* NameEnum.swift */; };
84F0B22A23C2161A005CEE05 /* ShieldSerializer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84F0B22923C2161A005CEE05 /* ShieldSerializer.swift */; };
/* End PBXBuildFile section */

/* Begin PBXContainerItemProxy section */
Expand All @@ -35,6 +37,8 @@
846A66E923AFA3E9005801B8 /* Person.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Person.swift; sourceTree = "<group>"; };
846A66EB23AFA49F005801B8 /* ContactsList.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContactsList.swift; sourceTree = "<group>"; };
8492DB2F23B100E10015D585 /* NameList.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NameList.swift; sourceTree = "<group>"; };
84D94A2623B798BE005FC134 /* NameEnum.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NameEnum.swift; sourceTree = "<group>"; };
84F0B22923C2161A005CEE05 /* ShieldSerializer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShieldSerializer.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
Expand Down Expand Up @@ -79,9 +83,11 @@
children = (
846A66C923AFA37C005801B8 /* SwiftShieldSDK.h */,
846A66CA23AFA37C005801B8 /* Info.plist */,
84D94A2623B798BE005FC134 /* NameEnum.swift */,
846A66E923AFA3E9005801B8 /* Person.swift */,
846A66EB23AFA49F005801B8 /* ContactsList.swift */,
8492DB2F23B100E10015D585 /* NameList.swift */,
84F0B22923C2161A005CEE05 /* ShieldSerializer.swift */,
);
path = SwiftShieldSDK;
sourceTree = "<group>";
Expand Down Expand Up @@ -207,6 +213,8 @@
846A66EC23AFA49F005801B8 /* ContactsList.swift in Sources */,
846A66EA23AFA3E9005801B8 /* Person.swift in Sources */,
8492DB3023B100E10015D585 /* NameList.swift in Sources */,
84D94A2723B798BE005FC134 /* NameEnum.swift in Sources */,
84F0B22A23C2161A005CEE05 /* ShieldSerializer.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down Expand Up @@ -373,6 +381,7 @@
PRODUCT_BUNDLE_IDENTIFIER = com.rockbruno.SwiftShieldSDK;
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
SKIP_INSTALL = YES;
SUPPORTS_MACCATALYST = NO;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
Expand Down Expand Up @@ -401,6 +410,7 @@
PRODUCT_BUNDLE_IDENTIFIER = com.rockbruno.SwiftShieldSDK;
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
SKIP_INSTALL = YES;
SUPPORTS_MACCATALYST = NO;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,33 @@
import Foundation


public class ContactsList {
public class ContactsList: Codable {
var contacts = Array<Person>()

private enum CodingKeys: String, CodingKey {
case contacts
}

required public init(from decoder:Decoder) throws {
var container = try decoder.unkeyedContainer()
var contacts = [Person]()
if let count = container.count {
contacts.reserveCapacity(count)
}

while !container.isAtEnd {
let person = try container.decode(Person.self)
contacts.append(person)
}

self.contacts = contacts
}

public func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
try container.encode(contacts)
}

public init() {
var person = Person("Bruce", "Lee")
contacts.append(person)
Expand Down
16 changes: 16 additions & 0 deletions SwiftShieldExample/SwiftShieldSDK/SwiftShieldSDK/NameEnum.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
//
// NameEnum.swift
// SwiftShieldSDK
//
// Created by Weidian on 28/12/19.
// Copyright 漏 2019 rockbruno. All rights reserved.
//

import Foundation

enum NameEnum: Int {
case
FIRST_NAME = 0,
MIDDLE_NAME,
LAST_NAME
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ open class NameList {
names.append(person)
}

public func printNames() -> String {
open func printNames() -> String {
return privatePrintNames()
}

Expand Down
18 changes: 17 additions & 1 deletion SwiftShieldExample/SwiftShieldSDK/SwiftShieldSDK/Person.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,15 @@

import Foundation

class Person {
class Person: Codable {
var firstName: String
var lastName: String

private enum _personCodingKeys: String, CodingKey {
case firstName
case lastName
}

init(_ firstName: String, _ lastName: String) {
self.firstName = firstName
self.lastName = lastName
Expand All @@ -20,5 +25,16 @@ class Person {
func fullName() -> String {
return "\(firstName) \(lastName)"
}

func getName(part: NameEnum) -> String? {
switch part {
case NameEnum.FIRST_NAME:
return firstName
case NameEnum.LAST_NAME:
return lastName
default:
return nil
}
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
//
// Serializer.swift
// SwiftShieldSDK
//
// Created by Weidian on 5/1/20.
// Copyright 漏 2020 rockbruno. All rights reserved.
//

import Foundation

open class ShieldSerializer {

public init() {}

open func jsonContactsList() -> String? {
let list = ContactsList()
let encoder = JSONEncoder()
encoder.outputFormatting = .prettyPrinted
let data = try! encoder.encode(list)
let jsonList = String(data: data, encoding: .utf8)
print(jsonList ?? "encoding error")
return jsonList
}

open func parseContactsList(json: String) -> ContactsList? {
let data = json.data(using: .utf8)!
let list = try! JSONDecoder().decode(ContactsList.self, from: data)
return list
}
}
35 changes: 31 additions & 4 deletions swiftshield-Sources/AutomaticSwiftShield.swift
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,13 @@ class AutomaticSwiftShield: Protector {
}
let name = data.name
let usr = data.usr
let kind = data.kind

if let type = self.sourceKit.referenceType(kind: kind), type == .enum && name.hasSuffix("CodingKeys") {
obfuscationData.excludedEnums.insert(self.usrWithoutSuffix(usr))
return
}

obfuscationData.usrDict.insert(usr)
if dict.getString(.receiverId) == nil {
obfuscationData.usrRelationDict[usr] = variant
Expand Down Expand Up @@ -130,7 +137,8 @@ extension AutomaticSwiftShield {
private func getNameData(from dict: SourceKitdResponse.Dictionary,
obfuscationData: ObfuscationData) -> (name: String,
usr: String,
obfuscatedName: String)? {
obfuscatedName: String,
kind: String)? {
let kind = dict.getUID(.kindId).asString
guard sourceKit.declarationType(for: kind) != nil else {
return nil
Expand All @@ -142,9 +150,18 @@ extension AutomaticSwiftShield {
guard let protected = obfuscationData.obfuscationDict[name] else {
let newName = String.random(length: self.protectedClassNameSize, excluding: obfuscationData.allObfuscatedNames)
obfuscationData.obfuscationDict[name] = newName
return (name, usr, newName)
return (name, usr, newName, kind)
}
return (name, usr, protected, kind)
}

private func usrWithoutSuffix(_ usr: String) -> String {
let lastIndex = usr.lastIndex(of: "_")
if let index = lastIndex {
let usrPrefix = usr[..<index]
return String(usrPrefix)
}
return (name, usr, protected)
return usr
}

func findReferencesInIndexed(obfuscationData: AutomaticObfuscationData) {
Expand All @@ -164,6 +181,15 @@ extension AutomaticSwiftShield {
guard obfuscationData.usrDict.contains(usr) else {
return
}


if type == .enumelement {
let usrPrefix = self.usrWithoutSuffix(usr)
if obfuscationData.excludedEnums.contains(usrPrefix) {
return
}
}

//Operators only get indexed as such if they are declared in a global scope
//Unfortunately, most people use public static func
//So we avoid obfuscating methods with small names to prevent obfuscating operators.
Expand All @@ -190,12 +216,13 @@ extension AutomaticSwiftShield {
kind: String,
variant: SourceKitdResponse.Variant,
obfuscationData: AutomaticObfuscationData) -> Bool {
guard type == .method || type == .property else {
guard type == .method || type == .property || type == .enumelement else {
return false
}
guard let usr = variant.getDictionary().getString(.usrId) else {
return false
}

if let relDict = obfuscationData.usrRelationDict[usr], relDict.val.data != variant.val.data {
return isReferencingInternal(type: type,
kind: kind,
Expand Down
1 change: 1 addition & 0 deletions swiftshield-Sources/ObfuscationData.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ final class AutomaticObfuscationData: ObfuscationData {
var referencesDict: [File: [ReferenceData]] = [:]
var usrRelationDict: [String: SourceKitdResponse.Variant] = [:]
var indexedFiles: [(File, SourceKitdResponse)] = []
var excludedEnums: Set<String> = []

var moduleNames: Set<String> {
return Set(modules.compactMap { $0.name })
Expand Down
4 changes: 4 additions & 0 deletions swiftshield-Sources/SourceKit.swift
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@ final class SourceKit {
"function.method.static",
"function.method.class":
return .method
case "enum":
return .enum
case "enumelement":
return .enumelement
default:
return nil
}
Expand Down
2 changes: 2 additions & 0 deletions swiftshield-Sources/SourceKitDeclarationType.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,7 @@ extension SourceKit {
case `protocol`
case property
case method
case `enum`
case enumelement
}
}

0 comments on commit 7cc28fd

Please sign in to comment.