callback.md
Version 1.0.0 - just a simple snippet to show you what to expect
# Callback Version 1.0.0 - just a simple snippet to show you what to expect
callback.src
import_code("/home/murphy/callback/libs/graphics")
Callback = {}
Callback.constants = {}
Callback.constants.CLI_NAME = "callback"
Callback.constants.VERSION = "1.0.0"
CLI = {}
CLI.environment = {}
CLI.environment.index = {}
CLI.current_env = "index"
CLI.global_commands = {}
CLI.get_env = function()
return CLI.current_env
end function
CLI.set_env = function(env)
if CLI.environment.hasIndex(env) then
CLI.current_env = env
else
Logger.error("Environment " + env.bold() + " does not exist.")
end if
end function
CLI.get_env_text = function()
callback_txt = Callback.constants.CLI_NAME.color(Color.RED).underline()
env_txt = "[] > "
if CLI.current_env != null then
env_txt = "[" + CLI.current_env.bold() + "]" + " > "
end if
return callback_txt + env_txt
end function
CLI.add_global_command = function(name, desc, fun)
command = new Command
command.create(name, desc, @fun)
CLI.global_commands[name] = command
end function
CLI.add_command = function(env, name, desc, fun, usage=null)
if not CLI.environment.hasIndex(env) then
CLI.environment[env] = {}
end if
command = new Command
command.create(name, desc, @fun, usage)
CLI.environment[env][name] = command
end function
CLI.get_command = function(env, name)
if CLI.environment.hasIndex(env) then
if CLI.environment[env].hasIndex(name) then
return CLI.environment[env][name]
else if CLI.global_commands.hasIndex(name) then
return CLI.global_commands[name]
else if CLI.is_help_command(name) then
CLI.print_help()
else
Logger.error("Command " + name.bold() + " does not exist in environment " + env.bold() + ".")
end if
else
Logger.error("Environment " + env.bold() + " does not exist.")
end if
end function
CLI.is_help_command = function(input)
if input == "?" or input == "help" or input == "h" then
return true
end if
end function
CLI.get_input = function()
input = user_input(CLI.get_env_text())
arguments = input.split(" ")
command_name = arguments[0].trim().lower()
params = null
if arguments.len() > 1 then
params = arguments[1:]
end if
command = CLI.get_command(CLI.current_env, command_name)
if command then
if params then
command.fun(params)
else
command.fun()
end if
end if
end function
CLI.print_help = function(params=null)
help_table = new Table
help_table.clear()
help_table.HORIZONTAL_CHAR = " "
help_table.VERTICAL_CHAR = " "
help_table.CORNER_CHAR = " "
help_table.set_headings(["command","description"])
rows = []
commands = CLI.environment[CLI.current_env]
for command_name in commands.indexes
command = commands[command_name]
command_name = command.name
if command.usage != null then command_name = command.usage
rows.push([command_name, command.desc])
end for
help_table.set_rows(rows)
table_text = help_table.to_string()
print(string.NEWLINE + table_text + string.NEWLINE)
end function
CLI.are_you_sure = function(text)
resp = user_input("WARNING: ".color(Color.ORANGE) + text + " (y/N): ")
if resp.lower() == "y" then
return true
end if
return false
end function
Command = {}
Command.create = function(name, desc, fun, usage=null)
self.name = name
self.desc = desc
self.fun = @fun
self.usage = usage
end function
Machine = {}
Machine.local = get_shell.host_computer
Machine.print_machine_info = function()
print(string.NEWLINE + "Public IP: " + Machine.local.public_ip)
print("Local IP: " + Machine.local.local_ip)
print("Gateway: " + Machine.local.network_gateway + string.NEWLINE)
end function
Build = {}
Build.activate = function()
CLI.set_env("build")
end function
Build.close = function()
CLI.set_env("index")
end function
Build.generate_simple = function(params=null)
import_code("/home/murphy/callback/templates/simple")
ip = Machine.local.public_ip
port = 1222
proc_name = "ps"
if params != null then
if params.hasIndex(0) then ip = params[0]
if params.hasIndex(1) then port = params[1]
if params.hasIndex(2) then proc_name = params[2]
end if
src = SHELL_TEMPLATE.source.replace("{ip}", ip).replace("{port}", port).replace("{proc_name}", proc_name)
Logger.info("Build the following source code on the target machine: " + string.NEWLINE)
print(src + string.NEWLINE)
end function
Manage = {}
Manage.shells = {}
Manage.active_session = null
Manage.activate = function()
CLI.set_env("manage")
Manage.update_shells()
end function
Manage.close = function()
CLI.set_env("index")
end function
Manage.update_shells = function()
shells = metaxploit.rshell_server
for shell in shells
ishell = new IShell
ishell.create(shell)
end for
end function
Manage.list_shells = function()
shells = metaxploit.rshell_server
shell_table = new Table
shell_table.clear()
shell_table.HORIZONTAL_CHAR = " "
shell_table.VERTICAL_CHAR = " "
shell_table.CORNER_CHAR = " "
shell_table.set_headings(["session id", "public ip", "local ip", "user"])
for shell in shells
ishell = new IShell
ishell.create(shell)
Manage.add_shell(ishell)
session = Manage.active_session
color = null
row = [
ishell.get_id(),
ishell.get_public_ip(),
ishell.get_local_ip(),
ishell.get_user(),
]
if session then
if ishell.get_id() == Manage.active_session.get_id() then
color = Color.YELLOW
end if
end if
shell_table.insert_row(row, color)
end for
shell_table.display()
end function
Manage.add_shell = function(ishell)
shell_id = ishell.get_id()
Manage.shells[shell_id] = ishell
end function
Manage.get_session = function(params)
if not params.hasIndex(0) then
Logger.error("Session ID not provided.")
return null
end if
session = params[0]
if not Manage.shells.hasIndex(session) then
Logger.error("Session ID does not exist.")
return null
end if
return Manage.shells[session]
end function
Manage.use_shell = function(params)
session = Manage.get_session(params)
Manage.active_session = session
end function
Manage.get_active_session = function()
if Manage.active_session then
return Manage.active_session
end if
Logger.error("No active session. Run " + "use [session]".bold() + " to use an active session.")
end function
Manage.launch_shell = function()
session = Manage.get_active_session()
if session then
session.open_terminal()
end if
end function
CustomShell = {}
CustomShell.commands = {}
CustomShell.interop = {}
CustomShell.shell = null
CustomShell.interface_shell = null
CustomShell.cur_dir = null
CustomShell.init = function(ishell)
CustomShell.interface_shell = ishell
CustomShell.shell = ishell.get_shell
CustomShell.interop = CustomShell.init_interop()
CustomShell.cur_dir = CustomShell.get_cur_dir()
end function
CustomShell.get_cur_dir = function()
dir = CustomShell.interop.current_path
if dir then
return dir
else
user = CustomShell.interface_shell.get_user()
if user == "root" then
return "/root"
else
return "/home/" + user
end if
end if
end function
CustomShell.init_interop = function()
shell = CustomShell.get_shell
interop_payload_path = current_path + "/payloads/interop.src"
interop_payload = Machine.local.File(interop_payload_path)
directory = "/home/" + CustomShell.interface_shell.get_user()
if CustomShell.interface_shell.get_user() == "root" then
directory = "/root"
end if
if not interop_payload then
Logger.error("Interop payload does not exist: " + interop_payload_path)
return null
end if
interop_content = interop_payload.get_content()
interop_remote_file = shell.host_computer.touch(directory, "z.src")
if not interop_remote_file then
Logger.error("Failed to create remote interop payload.")
return null
end if
interop_remote_file_path = directory + "/z.src"
interop_remote_file_obj = shell.host_computer.File(interop_remote_file_path)
if not interop_remote_file_obj then
Logger.error("Failed to locate remote interop payload.")
return null
end if
interop_written = interop_remote_file_obj.set_content(interop_content)
if not interop_written then
Logger.error("Failed to write remote interop payload.")
return null
end if
shell.build(interop_remote_file_path, directory)
interop_binary_file = shell.host_computer.File(directory + "/z")
if not interop_binary_file then
Logger.error("Failed to locate remote interop payload binary.")
return null
end if
id = CustomShell.interface_shell.get_id()
interop_execute = shell.launch(directory + "/z", id)
delete_failed = interop_remote_file_obj.delete()
if delete_failed then
Logger.warn("Failed to delete remote interop payload source code.")
end if
interop_map = get_custom_object()
if interop_map.hasIndex(id) then
remote_binary = shell.host_computer.File(interop_map[id].program_path)
if remote_binary then
delete_failed = remote_binary.delete()
if delete_failed then
Logger.warn("Failed to delete remote interop payload binary.")
end if
else
Logger.error("Failed to locate remote interop payload binary.")
end if
return interop_map[id]
end if
return interop_map
Logger.error("Interop session not found. Shell functionality is limited.")
end function
CustomShell.add_command = function(name, desc, fun)
command = new Command
command.create(name, desc, @fun)
CustomShell.commands[name] = command
end function
CustomShell.get_command = function(name)
if CustomShell.commands.hasIndex(name) then
return CustomShell.commands[name]
else if CLI.is_help_command(name) then
CustomShell.print_help()
else
Logger.error("Command " + name.bold() + " not found.")
end if
end function
CustomShell.get_preamble = function()
shell = CustomShell.get_shell
public_ip = shell.host_computer.public_ip.color(Color.BLUE)
local_ip = shell.host_computer.local_ip.color(Color.RED)
user = CustomShell.interface_shell.get_user()
if user == "root" then user = user.color(Color.RED)
return "[" + public_ip + "]-[" + user.bold() + "@" + local_ip + "](" + self.cur_dir + ")> "
end function
CustomShell.get_shell = function()
if not CustomShell.shell then
Logger.error("CustomShell not initialized.")
exit()
end if
return CustomShell.shell
end function
CustomShell.get_input = function()
input = user_input(CustomShell.get_preamble()).trim()
arguments = input.split(" ")
command_name = arguments[0].trim().lower()
params = null
if arguments.len() > 1 then
params = arguments[1:]
end if
command = CustomShell.get_command(command_name)
if command then
if params then
command.fun(params)
else
command.fun()
end if
end if
end function
CustomShell.start_shell = function()
CustomShell.active = true
while CustomShell.active
CustomShell.get_input()
end while
end function
CustomShell.print_help = function()
help_table = new Table
help_table.clear()
help_table.HORIZONTAL_CHAR = " "
help_table.VERTICAL_CHAR = " "
help_table.CORNER_CHAR = " "
help_table.set_headings(["command","description"])
rows = []
commands = CustomShell.commands
for command_name in commands.indexes
command = commands[command_name]
command_name = command.name
if command.usage != null then command_name = command.usage
rows.push([command_name, command.desc])
end for
help_table.set_rows(rows)
table_text = help_table.to_string()
print(table_text)
end function
CustomShell.get_absolute_dir = function(dir)
if dir[0] == "/" then
absolute_dir = dir
else
absolute_dir = CustomShell.cur_dir + "/" + dir
if CustomShell.cur_dir == "/" then
absolute_dir = CustomShell.cur_dir + dir
end if
end if
return absolute_dir
end function
CustomShell.close = function()
CustomShell.active = false
end function
CustomShell.whoami = function()
user = CustomShell.interop.active_user
if user then
print(user)
else
print(CustomShell.interface_shell.get_user())
end if
end function
CustomShell.ifconfig = function()
local_ip = CustomShell.get_shell.host_computer.local_ip
gateway_ip = CustomShell.get_shell.host_computer.network_gateway
router = CustomShell.interop.get_router()
public_ip = CustomShell.get_shell.host_computer.public_ip
if router then
pubic_ip = router.public_ip
end if
print("Public IP: " + public_ip)
print("Local IP: " + local_ip)
print("Gateway IP: " + gateway_ip)
end function
CustomShell.pwd = function()
print(CustomShell.cur_dir)
end function
CustomShell.cd = function(params=null)
if not params or params.len() == 0 then
dir = CustomShell.interop.home_dir
else
dir = params[0]
end if
shell = CustomShell.get_shell
current = shell.host_computer.File(CustomShell.cur_dir)
if not current then
Logger.error("Current directory no longer exists: " + CustomShell.cur_dir)
CustomShell.cur_dir = CustomShell.interop.home_dir
return null
end if
absolute_dir = CustomShell.get_absolute_dir(dir)
next = shell.host_computer.File(absolute_dir)
if dir == ".." then
parent = current.parent
if current.parent then
next = current.parent
else
next = shell.host_computer.File("/")
end if
end if
if not next then
Logger.error("Directory " + absolute_dir.bold() + " not found")
return null
end if
CustomShell.cur_dir = next.path
end function
CustomShell.ls = function(params=null)
shell = CustomShell.get_shell
dir = CustomShell.cur_dir
if params and params.len() > 0 then
dir = CustomShell.get_absolute_dir(params[0])
end if
files = []
directory = shell.host_computer.File(dir)
if not directory then
Logger.error("Directory " + dir.bold() + " not found.")
return null
end if
if not directory.is_folder then
Logger.error(dir.bold() + " is not a directory.")
return null
end if
directory_row = [directory.permissions, directory.owner, directory.group, directory.size, "./"]
files.push(directory_row.join(" "))
for folder in directory.get_folders
folder_name = folder.name + "/"
row = [folder.permissions, folder.owner, folder.group, folder.size, folder_name.color(Color.BLUE).bold()]
files.push(row.join(" "))
end for
for file in directory.get_files
row = [file.permissions, file.owner, file.group, file.size, file.name]
files.push(row.join(" "))
end for
out_files = files.join(string.NEWLINE)
print(format_columns(out_files))
end function
CustomShell.cat = function(params=null)
shell = CustomShell.get_shell
if not params or params.len() < 1 then
Logger.error("File parameter required: " + "cat [file].".bold())
return null
end if
path = CustomShell.get_absolute_dir(params[0])
file = shell.host_computer.File(path)
if not file then
Logger.error("File " + path.bold() + " not found.")
return null
end if
if not file.has_permission("r") then
Logger.error("Permission denied.")
return null
end if
if file.is_binary or file.is_folder then
Logger.error(path.bold() + " is not a text file.")
return null
end if
content = file.get_content()
if content then
print(content)
end if
end function
CustomShell.ps = function()
shell = CustomShell.get_shell
print(format_columns(shell.host_computer.show_procs()))
end function
CustomShell.kill = function(params=null)
if not params or params.len() < 1 then
Logger.error("PID parameter required: " + "kill [PID]".bold())
return null
end if
pid = params[0].to_int()
shell = CustomShell.get_shell
success = shell.host_computer.close_program(pid)
if not success then
Logger.error("PID " + pid.bold() + " not found.")
return null
end if
print("Process " + pid.bold() + " closed.")
end function
CustomShell.rm = function(params=null)
if not params or params.len() < 1 then
Logger.error("File parameter required: " + "rm [file]".bold())
return null
end if
shell = CustomShell.get_shell
file_path = CustomShell.get_absolute_dir(params[0])
file = shell.host_computer.File(file_path)
if not file then
Logger.error("File " + file_path.bold() + " not found.")
return null
end if
if not file.has_permission("w") then
Logger.error("Permission denied.")
return null
end if
file.delete()
end function
// CustomShell command table
CustomShell.add_command("whoami", "Get current user", @CustomShell.whoami)
CustomShell.add_command("ifconfig", "Get machine network data", @CustomShell.ifconfig)
CustomShell.add_command("pwd", "Get current directory", @CustomShell.pwd)
CustomShell.add_command("cd", "Change directory", @CustomShell.cd)
CustomShell.add_command("ls", "List files in directory", @CustomShell.ls)
CustomShell.add_command("cat", "Get contents of a file", @CustomShell.cat)
CustomShell.add_command("ps", "View running processes", @CustomShell.ps)
CustomShell.add_command("kill", "Close a running process", @CustomShell.kill)
CustomShell.add_command("rm", "Remove a file/folder", @CustomShell.rm)
CustomShell.add_command("clear", "Clear the screen", @clear_screen)
CustomShell.add_command("exit", "Exit shell", @CustomShell.close)
IShell = {}
IShell.create = function(shell)
self.get_shell = shell
end function
IShell.get_id = function()
return md5(self.get_public_ip() + self.get_local_ip() + self.get_user())
end function
IShell.get_public_ip = function()
return self.get_shell.host_computer.public_ip
end function
IShell.get_local_ip = function()
return self.get_shell.host_computer.local_ip
end function
IShell.get_user = function()
folders = self.get_shell.host_computer.File("/home").get_folders()
root_file = self.get_shell.host_computer.File("/root")
if not folders then return "guest"
if root_file then
if root_file.has_permission("r") and root_file.has_permission("w") and root_file.has_permission("x") then
return "root"
end if
end if
for folder in folders
if folder.name == "guest" then continue
if folder.has_permission("r") and folder.has_permission("w") and folder.has_permission("x") then
return folder.name
end if
end for
return "guest"
end function
IShell.open_terminal = function()
CustomShell.init(self)
CustomShell.start_shell()
end function
IShell.get_files = function(path)
folder = self.get_shell.host_computer.File(path)
if not folder then
Logger.error(path.bold() + " not found.")
return null
end if
if not folder.is_folder then
Logger.error(path.bold() + " is not a folder.")
return null
end if
files = folder.get_files()
if not files then
Logger.error("No files found in " + path.bold())
return null
end if
return files
end function
// Global command table
CLI.add_global_command("clear", "Clear the screen", @clear_screen)
// Command table
CLI.add_command("index", "info", "Display your machine info", @Machine.print_machine_info)
CLI.add_command("index", "build", "Open reverse shell builder", @Build.activate)
CLI.add_command("index", "manage", "Manage your reverse shells", @Manage.activate)
CLI.add_command("index", "exit", "Exit callback", @exit)
CLI.add_command("build", "simple", "Generate a simple reverse shell", @Build.generate_simple, "simple [?ip] [?port] [?name]")
CLI.add_command("build", "exit", "Back to index page", @Build.close)
CLI.add_command("manage", "list", "List all active reverse shells", @Manage.list_shells)
CLI.add_command("manage", "use", "Set active shell session", @Manage.use_shell, "use [session]")
CLI.add_command("manage", "launch", "Launch the active shell session", @Manage.launch_shell)
CLI.add_command("manage", "exit", "Back to index page", @Manage.close)
// Find metaxploit
metaxploit = include_lib("/lib/metaxploit.so")
if not metaxploit then
metaxploit = include_lib(current_path + "/metaxploit.so")
end if
if not metaxploit then exit("Error: Can't find metaxploit library in the /lib path or the current folder")
// Run input loop
Logger.info("Welcome to " + Callback.constants.CLI_NAME + " v" + Callback.constants.VERSION.bold() + string.NEWLINE)
while true
CLI.get_input()
end while