Skip to content

Commit

Permalink
added download to sftp.py
Browse files Browse the repository at this point in the history
  • Loading branch information
checkymander committed Jun 3, 2022
1 parent 8a72443 commit 64f59dc
Show file tree
Hide file tree
Showing 4 changed files with 134 additions and 69 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -50,32 +50,35 @@ static void TestSFTP()
dict.Add("password", "RedT3amR0cks!");
dict.Add("action", "connect");
var result = JsonConvert.DeserializeObject<ResponseResult>(JsonConvert.SerializeObject(methodInfo.Invoke(null, new object[] { dict })));
dict.Add("path", "/rt/Mythic/.env");
dict["action"] = "download";
result = JsonConvert.DeserializeObject<ResponseResult>(JsonConvert.SerializeObject(methodInfo.Invoke(null, new object[] { dict })));
Console.WriteLine(result.user_output);



//dict["action"] = "ls";
////Get directory listing of base directory with an empty path
//dict["path"] = "";
//methodInfo.Invoke(null, new object[] { dict });

dict["action"] = "ls";
//Get directory listing of base directory with an empty path
dict["path"] = "";
methodInfo.Invoke(null, new object[] { dict });

//Get directory listing with a relative path
dict["action"] = "cd";
dict["path"] = "/rt/slack/C2_Profiles";
methodInfo.Invoke(null, new object[] { dict });
////Get directory listing with a relative path
//dict["action"] = "cd";
//dict["path"] = "/rt/slack/C2_Profiles";
//methodInfo.Invoke(null, new object[] { dict });

dict["action"] = "ls";
dict["path"] = "../../Athena";
methodInfo.Invoke(null, new object[] { dict });
//dict["action"] = "ls";
//dict["path"] = "../../Athena";
//methodInfo.Invoke(null, new object[] { dict });

//Get directory listing with a full path
dict["path"] = "/rt/slack/";
methodInfo.Invoke(null, new object[] { dict });
////Get directory listing with a full path
//dict["path"] = "/rt/slack/";
//methodInfo.Invoke(null, new object[] { dict });


//Get directory listing with a partial path
dict["path"] = "slack/";
methodInfo.Invoke(null, new object[] { dict });
////Get directory listing with a partial path
//dict["path"] = "slack/";
//methodInfo.Invoke(null, new object[] { dict });
}


Expand Down Expand Up @@ -103,38 +106,40 @@ static void TestSSH()
dict.Add("action", "connect");
Console.WriteLine("Connecting to host:");
var result = JsonConvert.DeserializeObject<ResponseResult>(JsonConvert.SerializeObject(methodInfo.Invoke(null, new object[] { dict })));
Console.WriteLine(result.user_output);
Console.WriteLine();
Console.WriteLine("Executing Command 'ls':");
dict = new Dictionary<string, object>();
dict.Add("task-id", "0");
dict.Add("action", "exec");
dict.Add("command", "ls");
result = JsonConvert.DeserializeObject<ResponseResult>(JsonConvert.SerializeObject(methodInfo.Invoke(null, new object[] { dict })));
Console.WriteLine(result.user_output);
Console.WriteLine("Disconnecting:");
dict["action"] = "disconnect";
result = JsonConvert.DeserializeObject<ResponseResult>(JsonConvert.SerializeObject(methodInfo.Invoke(null, new object[] { dict })));
Console.WriteLine(result.user_output);
Console.WriteLine("Connecting:");
dict["action"] = "connect";
dict.Add("host", "192.168.4.201");
dict.Add("username", "rt");
dict.Add("password", "");
result = JsonConvert.DeserializeObject<ResponseResult>(JsonConvert.SerializeObject(methodInfo.Invoke(null, new object[] { dict })));
Console.WriteLine(result.user_output);

Console.WriteLine("Executing an another 'whoami':");
dict["command"] = "whoami";
dict["action"] = "exec";
result = JsonConvert.DeserializeObject<ResponseResult>(JsonConvert.SerializeObject(methodInfo.Invoke(null, new object[] { dict })));
Console.WriteLine(result.user_output);
Console.WriteLine("Disconnecting");
dict = new Dictionary<string, object>();
dict.Add("task-id", "0");
dict.Add("action", "disconnect");
result = JsonConvert.DeserializeObject<ResponseResult>(JsonConvert.SerializeObject(methodInfo.Invoke(null, new object[] { dict })));
Console.WriteLine(JsonConvert.SerializeObject(result));


//Console.WriteLine(result.user_output);
//Console.WriteLine();
//Console.WriteLine("Executing Command 'ls':");
// dict = new Dictionary<string, object>();
// dict.Add("task-id", "0");
// dict.Add("action", "exec");
// dict.Add("command", "ls");
// result = JsonConvert.DeserializeObject<ResponseResult>(JsonConvert.SerializeObject(methodInfo.Invoke(null, new object[] { dict })));
// Console.WriteLine(result.user_output);
// Console.WriteLine("Disconnecting:");
// dict["action"] = "disconnect";
// result = JsonConvert.DeserializeObject<ResponseResult>(JsonConvert.SerializeObject(methodInfo.Invoke(null, new object[] { dict })));
// Console.WriteLine(result.user_output);
// Console.WriteLine("Connecting:");
// dict["action"] = "connect";
// dict.Add("host", "192.168.4.201");
// dict.Add("username", "rt");
// dict.Add("password", "");
// result = JsonConvert.DeserializeObject<ResponseResult>(JsonConvert.SerializeObject(methodInfo.Invoke(null, new object[] { dict })));
// Console.WriteLine(result.user_output);

// Console.WriteLine("Executing an another 'whoami':");
// dict["command"] = "whoami";
// dict["action"] = "exec";
// result = JsonConvert.DeserializeObject<ResponseResult>(JsonConvert.SerializeObject(methodInfo.Invoke(null, new object[] { dict })));
// Console.WriteLine(result.user_output);
// Console.WriteLine("Disconnecting");
// dict = new Dictionary<string, object>();
// dict.Add("task-id", "0");
// dict.Add("action", "disconnect");
// result = JsonConvert.DeserializeObject<ResponseResult>(JsonConvert.SerializeObject(methodInfo.Invoke(null, new object[] { dict })));
// Console.WriteLine(JsonConvert.SerializeObject(result));


}
Expand Down
77 changes: 77 additions & 0 deletions Payload_Type/athena/agent_code/AthenaPlugins/sftp/sftp.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ public static ResponseResult Execute(Dictionary<string, object> args)
//return RunCommand(args);
break;
case "download":
return DownloadFile(args);
//return RunCommand(args);
break;
case "connect":
Expand Down Expand Up @@ -102,6 +103,82 @@ public static ResponseResult Execute(Dictionary<string, object> args)
};
}
}

static ResponseResult DownloadFile(Dictionary<string, object> args)
{
Console.WriteLine("Downloading File.");
if (string.IsNullOrEmpty(currentSession))
{
return new FileBrowserResponseResult
{
task_id = (string)args["task-id"],
user_output = $"No active sessions.",
completed = "true",
status = "error"
};
}
else if(!args.ContainsKey("path") || string.IsNullOrEmpty((string)args["path"]))
{
return new FileBrowserResponseResult
{
task_id = (string)args["task-id"],
user_output = $"No file specified.",
completed = "true",
status = "error"
};
}
string output = "";

try
{
using (var remoteFileStream = sessions[currentSession].client.OpenRead((string)args["path"]))
{
var textReader = new System.IO.StreamReader(remoteFileStream);
output = textReader.ReadToEnd();
}


//using (MemoryStream fs = new MemoryStream())
//{
// sessions[currentSession].client.DownloadFile((string)args["path"], fs);
// StreamReader reader = new StreamReader(fs);
// output = reader.ReadToEnd();

// Console.WriteLine(output);
//}

if (!string.IsNullOrEmpty(output))
{
return new FileBrowserResponseResult
{
task_id = (string)args["task-id"],
user_output = output,
completed = "true",

};
}
else
{
return new FileBrowserResponseResult
{
task_id = (string)args["task-id"],
user_output = $"File stream was empty.",
completed = "true",
status = "error"
};
}
}
catch (Exception e) {
return new FileBrowserResponseResult
{
task_id = (string)args["task-id"],
user_output = e.ToString(),
completed = "true",
status = "error"
};
}
}

static ResponseResult Connect(Dictionary<string, object> args)
{
ConnectionInfo connectionInfo;
Expand Down
3 changes: 0 additions & 3 deletions Payload_Type/athena/mythic/agent_functions/sftp.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,14 +120,11 @@ async def parse_arguments(self):
# this means we have tasking from the file browser rather than the popup UI
# the apfell agent doesn't currently have the ability to do _remote_ listings, so we ignore it
path = temp_json["path"] + "/" + temp_json["file"]

if(path == "//"):
self.add_arg("path", "/")
else:
self.add_arg("path", temp_json["path"] + "/" + temp_json["file"])

self.add_arg("action","ls")
#self.add_arg("file_browser", True, type=ParameterType.Boolean)
else:
self.load_args_from_json_string(self.command_line)
else:
Expand Down
18 changes: 2 additions & 16 deletions Payload_Type/athena/mythic/agent_functions/ssh.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,20 +98,6 @@ def __init__(self, command_line, **kwargs):
)
],
),
# CommandParameter(
# name="session",
# cli_name="session",
# display_name="Session",
# description="The session ID to switch to",
# type=ParameterType.String,
# default_value = "",
# parameter_group_info=[
# ParameterGroupInfo(
# required=False,
# group_name="Default",
# )
# ],
# )
]

async def parse_arguments(self):
Expand Down Expand Up @@ -149,10 +135,10 @@ class SshCommand(CommandBase):
ssh connect -hostname <host/ip> -username <user> [-password <password>] [-keypath </path/to/key>]
Execute a command in the current session:
ssh exec "<command to exec>"
ssh exec <command to exec>
Switch active session:
ssh switch -session <session ID>
ssh switch <session ID>
List active sessions:
ssh list
Expand Down

0 comments on commit 64f59dc

Please sign in to comment.