-
Notifications
You must be signed in to change notification settings - Fork 27
/
InjectCheck.js
117 lines (90 loc) · 6.1 KB
/
InjectCheck.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
function InjectCheck(Arg1) {
// Based on help from its-a-feature & xorrior
// Also inspired by SimpleXPCApp from r3ggi
//Usage:
//InjectCheck("All") --for all apps in '/Applications'
//InjectCheck("/Applications/Firefox.app") --for a specific Application Bundle
var output = "";
// Getting code signature information
function codeSign(pathToapplication) {
ObjC.import("Security");
let staticCode = Ref();
path = $.CFURLCreateFromFileSystemRepresentation($.kCFAllocatorDefault, pathToapplication, pathToapplication.length, true);
$.SecStaticCodeCreateWithPath(path, 0, staticCode);
let codeInfo = Ref();
$.SecCodeCopySigningInformation(staticCode[0], 0x7F, codeInfo);
ObjC.bindFunction('CFMakeCollectable', ['id', ['void *']]);
codeInfo_c = $.CFMakeCollectable(codeInfo[0]);
var signingInformationString = JSON.stringify(ObjC.deepUnwrap(codeInfo_c), null, 2);
//Full Signing Information for Debugging
//output += "----FullInfo----" + '\n' + signingInformationString)
var signingInformation = ObjC.deepUnwrap(codeInfo_c)
//Get Hardened Runtime
let applicationName = signingInformation["info-plist"].CFBundleExecutable
output += "************************************** " + applicationName + " ************************************** " + '\n'
let hardenedRuntimeFlag = 10000
let signingFlags = signingInformation.flags.toString(16)
output += "The " + applicationName + " application has a Hardened Runtime Value of " + signingFlags + '\n'
if (signingFlags < hardenedRuntimeFlag) {
output += "Hardened Runtime is not set for the " + applicationName + " application. " + '\n' + "Nice and easy injection option: use 'DYLD_INSERT_LIBRARIES'. (e.g.: DYLD_INSERT_LIBRARIES=/PATH_TO/evil.dylib /Applications/Calculator.app/Contents/MacOS/Calculator &) or Attempt injection with listtasks/libinject in Mythic Agent poseidon" + '\n'
} else {
output += "Hardened Runtime is set" + '\n'
//Get Entitlements
let entitlements = signingInformation["entitlements-dict"]
//Set Problematic Entitlements
let disableDylbkeyExists = entitlements["com.apple.security.cs.disable-library-validation"]
let allowDylibkeyExsists = entitlements["com.apple.security.cs.allow-dyld-environment-variables"]
let unsignMemkeyExists = entitlements["com.apple.security.cs.allow-unsigned-executable-memory"]
let getTaskkeyExists = entitlements["com.apple.security.get-task-allow"]
if (disableDylbkeyExists && allowDylibkeyExsists) {
output += "The " + applicationName + " application contains the 'com.apple.security.cs.disable-library-validation (allows any dylib)' and 'com.apple.security.cs.allow-dyld-environment-variables' (allows DYLD_INSERT_LIBRARIES abuses) entitlements are present." + '\n' + "Nice and easy injection option: use 'DYLD_INSERT_LIBRARIES'. (e.g.: DYLD_INSERT_LIBRARIES=/PATH_TO/evil.dylib /Applications/Calculator.app/Contents/MacOS/Calculator &" + '\n'
}
if (unsignMemkeyExists && allowDylibkeyExsists) {
output += "The " + applicationName + " application contains the 'com.apple.security.cs.allow-unsigned-executable-memory' (allows shellcode injection) and 'com.apple.security.cs.allow-dyld-environment-variables' (allows DYLD_INSERT_LIBRARIES abuses) entitlements are present." + '\n' + "Code injection is possible but requires some creativity that cannot be automated." + '\n'
} else if (unsignMemkeyExists && disableDylbkeyExists) {
output += "The " + applicationName + " application contains the 'com.apple.security.cs.allow-unsigned-executable-memory' (allows shellcode injection) and 'com.apple.security.cs.disable-library-validation' (allows library injection) entitlements." + '\n' + "Code injection is possible but requires some creativity that cannot be automated. Look into dylib hijacks or proxying" + '\n'
} else if (unsignMemkeyExists && allowDylibkeyExsists == false) {
output += "The " + applicationName + " application contains the 'com.apple.security.cs.allow-unsigned-executable-memory' entitlement is present. " + '\n' + "Code injection is possible but requires some creativity that cannot be automated." + '\n'
}
if (getTaskkeyExists) {
output += "The " + applicationName + " application contains the 'com.apple.security.get-task-allow' entitlements is present. Attempt injection with listtasks/libinject in Mythic Agent poseidon" + '\n'
}
}
//Electron App Check
let filePath = pathToapplication + "/Contents/Resources/app.asar"
let asarExistscheck = $.NSFileManager.alloc.init.fileExistsAtPath(filePath)
if (asarExistscheck == true) {
output += "The " + applicationName + " application contains an app.asar file and is likely an Electron app. Can abuse ELECTRON_RUN_AS_NODE environment variable for injection. e.g: create plist and use launchctl to load tamper plist. Example at https://blog.xpnsec.com/macos-injection-via-third-party-frameworks/" + '\n'
} else {
output += "No 'app.asar' file. Likely not an Electron app" + '\n'
}
}
function listDirectory(strPath) {
var fm = $.NSFileManager.defaultManager;
return ObjC.unwrap(
fm.contentsOfDirectoryAtPathError($(strPath)
.stringByExpandingTildeInPath, null))
.map(ObjC.unwrap);
}
if (Arg1 == "All") {
let enumerateFolderContents = listDirectory('/Applications')
function stoperror() {
return true;
}
var installedApps = []
for (var key in enumerateFolderContents) {
try {
codeSign("/Applications/" + enumerateFolderContents[key])
} catch (e) {
stoperror(e)
}
}
} else {
try {
codeSign(Arg1)
} catch (e) {
stoperror(e)
}
}
return output
}