xzre
|
XZ backdoor structures and functions. More...
#include <assert.h>
#include <link.h>
#include <stddef.h>
#include <stdint.h>
#include <sys/select.h>
#include <time.h>
#include <lzma.h>
#include <openssl/dsa.h>
#include <openssl/ec.h>
#include <openssl/evp.h>
#include <openssl/rsa.h>
#include <elf.h>
#include "util.h"
Go to the source code of this file.
Data Structures | |
struct | auditstate |
struct | gnu_hash_table |
struct | audit_ifaces |
struct | lzma_sha256_state |
State for the internal SHA-256 implementation. More... | |
struct | lzma_check_state |
Structure to hold internal state of the check being calculated. More... | |
struct | sshbuf |
struct | monitor |
struct monitor from openssh-portable More... | |
struct | sensitive_data |
struct sensitive_data from openssh-portable More... | |
struct | sshkey |
struct sshkey from openssh-portable More... | |
struct | got_ctx |
struct | elf_entry_ctx |
struct | dasm_ctx |
struct | elf_info |
struct | libc_imports |
struct | imported_funcs |
struct | sshd_ctx |
struct | sshd_log_ctx |
union | sshd_offsets_kex |
union | sshd_offsets_sshbuf |
struct | sshd_offsets_fields |
struct | sshd_offsets |
struct | sshd_payload_ctx |
struct | global_context |
struct | backdoor_shared_globals |
struct | ldso_ctx |
struct | backdoor_hooks_data |
struct | backdoor_hooks_ctx |
struct | backdoor_setup_params |
struct | elf_handles |
array of ELF handles More... | |
struct | main_elf |
struct | backdoor_data_handle |
data passed to functions that access the backdoor data More... | |
struct | string_item |
struct | string_references |
struct | backdoor_data |
this structure is used to hold most of the backdoor information. it's used as a local variable in function backdoor_setup More... | |
struct | backdoor_shared_libraries_data |
union | secret_data_shift_cursor_t |
represents a shift register, which will shift a '1' into the secret data array. the low 3 bits represent the bit index, while the rest represents the byte index this is convenient, since a simple increment will increment the buffer position correctly More... | |
struct | secret_data_item |
struct | key_payload_hdr |
the payload header. also used as Chacha IV More... | |
union | u_cmd_arguments_t |
struct | cmd_arguments |
struct | key_payload_body |
struct | backdoor_payload |
the contents of the RSA 'n' field More... | |
struct | key_payload |
struct | key_ctx |
struct | monitor_data |
data used within sshd_proxy_elevate More... | |
union | backdoor_runtime_data |
union used within run_backdoor_commands More... | |
struct | run_backdoor_commands_data |
stack frame layout for run_backdoor_commands More... | |
struct | backdoor_cpuid_reloc_consts |
struct | backdoor_tls_get_addr_reloc_consts |
struct | elf_functions |
struct | fake_lzma_allocator |
struct | instruction_search_ctx |
struct | dl_tls_index |
Macros | |
#define | _GNU_SOURCE |
#define | UPTR(x) ((uptr)(x)) |
#define | PTRADD(a, b) (UPTR(a) + UPTR(b)) |
#define | PTRDIFF(a, b) (UPTR(a) - UPTR(b)) |
#define | BUILD_BUG_ON_ZERO(e) ((int)(sizeof(struct { int:(-!!(e)); }))) |
#define | __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b)) |
#define | __must_be_array(a) BUILD_BUG_ON_ZERO(__same_type((a), &(a)[0])) |
#define | ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]) + __must_be_array(arr)) |
#define | CHACHA20_KEY_SIZE 32 |
#define | CHACHA20_IV_SIZE 16 |
#define | SHA256_DIGEST_SIZE 32 |
#define | ED448_KEY_SIZE 57 |
#define | ED448_SIGNATURE_SIZE 114 |
#define | X_BN_num_bytes(bits) (((bits)+7)/8) |
#define | XZDASM_OPC(op) ((u8)(op) - 0x80) |
#define | XZDASM_TEST_MASK(mask, offset, opcode) (((mask >> ((u8)(XZDASM_OPC(opcode) + offset))) & 1) == 1) |
#define | TRUE 1 |
#define | FALSE 0 |
#define | assert_offset(t, f, o) static_assert(offsetof(t, f) == o) |
#define | CONCAT(x, y) x ## y |
#define | EXPAND(x, y) CONCAT(x, y) |
#define | PADDING(size) u8 EXPAND(_unknown, __LINE__)[size] |
#define | PERMIT_NOT_SET -1 |
#define | PERMIT_NO 0 |
#define | PERMIT_FORCED_ONLY 1 |
#define | PERMIT_NO_PASSWD 2 |
#define | PERMIT_YES 3 |
#define | X86_MODRM_BYTE(mod, reg, rm) |
#define | X86_REX_BYTE(w, r, x, b) |
#define | X86_REX_W X86_REX_BYTE(1,0,0,0) |
#define | XZDASM_MODRM_MAKE(mod, reg, rm) |
#define | TEST_FLAG(x, flag) (((x) & (flag)) != 0) |
Typedefs | |
typedef uint8_t | u8 |
typedef uint16_t | u16 |
typedef uint32_t | u32 |
typedef uint64_t | u64 |
typedef uintptr_t | uptr |
typedef Elf64_Xword | Elf64_Relr |
typedef struct link_map * | lookup_t |
typedef struct gnu_hash_table | gnu_hash_table_t |
typedef int | BOOL |
typedef struct got_ctx | got_ctx_t |
typedef struct elf_entry_ctx | elf_entry_ctx_t |
typedef struct dasm_ctx | dasm_ctx_t |
typedef struct elf_info | elf_info_t |
typedef struct libc_imports | libc_imports_t |
typedef int(* | pfn_RSA_public_decrypt_t) (int flen, unsigned char *from, unsigned char *to, RSA *rsa, int padding) |
typedef int(* | pfn_EVP_PKEY_set1_RSA_t) (EVP_PKEY *pkey, struct rsa_st *key) |
typedef void(* | pfn_RSA_get0_key_t) (const RSA *r, const BIGNUM **n, const BIGNUM **e, const BIGNUM **d) |
typedef struct imported_funcs | imported_funcs_t |
typedef int(* | sshd_monitor_func_t) (struct ssh *ssh, int sock, struct sshbuf *m) |
typedef struct sshd_ctx | sshd_ctx_t |
typedef void(* | log_handler_fn) (LogLevel level, int forced, const char *msg, void *ctx) |
typedef struct sshd_log_ctx | sshd_log_ctx_t |
typedef union sshd_offsets_kex | sshd_offsets_kex_t |
typedef union sshd_offsets_sshbuf | sshd_offsets_sshbuf_t |
typedef struct sshd_offsets_fields | sshd_offsets_fields_t |
typedef struct sshd_offsets | sshd_offsets_t |
typedef struct sshd_payload_ctx | sshd_payload_ctx_t |
typedef struct global_context | global_context_t |
typedef struct backdoor_shared_globals | backdoor_shared_globals_t |
typedef struct ldso_ctx | ldso_ctx_t |
typedef struct backdoor_hooks_data | backdoor_hooks_data_t |
typedef struct backdoor_hooks_ctx | backdoor_hooks_ctx_t |
typedef struct backdoor_setup_params | backdoor_setup_params_t |
typedef struct elf_handles | elf_handles_t |
array of ELF handles More... | |
typedef struct main_elf | main_elf_t |
typedef struct backdoor_data | backdoor_data_t |
this structure is used to hold most of the backdoor information. it's used as a local variable in function backdoor_setup | |
typedef struct backdoor_data_handle | backdoor_data_handle_t |
data passed to functions that access the backdoor data | |
typedef struct string_item | string_item_t |
typedef struct string_references | string_references_t |
typedef struct backdoor_shared_libraries_data | backdoor_shared_libraries_data_t |
typedef struct secret_data_item | secret_data_item_t |
typedef struct key_payload_hdr | backdoor_payload_hdr_t |
the payload header. also used as Chacha IV More... | |
typedef struct cmd_arguments | cmd_arguments_t |
typedef struct key_payload_body | backdoor_payload_body_t |
typedef struct backdoor_payload | backdoor_payload_t |
the contents of the RSA 'n' field More... | |
typedef struct key_payload | key_payload_t |
typedef struct key_ctx | key_ctx_t |
typedef struct monitor_data | monitor_data_t |
data used within sshd_proxy_elevate | |
typedef union backdoor_runtime_data | backdoor_runtime_data_t |
union used within run_backdoor_commands | |
typedef struct run_backdoor_commands_data | run_backdoor_commands_data_t |
stack frame layout for run_backdoor_commands | |
typedef struct backdoor_cpuid_reloc_consts | backdoor_cpuid_reloc_consts_t |
typedef struct backdoor_tls_get_addr_reloc_consts | backdoor_tls_get_addr_reloc_consts_t |
typedef struct elf_functions | elf_functions_t |
typedef struct fake_lzma_allocator | fake_lzma_allocator_t |
typedef struct instruction_search_ctx | instruction_search_ctx_t |
typedef struct dl_tls_index | tls_index |
Enumerations | |
enum | X86_OPCODE { X86_OPCODE_LEA = 0x8D , X86_OPCODE_CALL = 0xE8 , X86_OPCODE_CMP = 0x3B , X86_OPCODE_MOV = 0x89 , X86_OPCODE_MOV_LOAD = 0x8B , X86_OPCODE_MOV_STORE = 0x8C } |
enum | X86_REG { X86_REG_RBP = 5 } |
enum | InstructionFlags { DF1_LOCK_REP = 1 , DF1_SEG = 2 , DF1_OSIZE = 4 , DF1_ASIZE = 8 , DF1_VEX = 0x10 , DF1_REX = 0x20 , DF1_MODRM = 0x40 , DF1_SIB = 0x80 } |
enum | InstructionFlags2 { DF2_MEM_DISP = 0x1 , DF2_MEM_DISP8 = 0x2 , DF2_MEM_SEG_OFFS = 0x4 , DF2_FLAGS_MEM = DF2_MEM_DISP | DF2_MEM_DISP8 | DF2_MEM_SEG_OFFS , DF2_IMM = 0x8 , DF2_IMM64 = 0x10 } |
enum | ElfFlags { X_ELF_PLTREL = 0x1 , X_ELF_RELA = 0x2 , X_ELF_RELR = 0x4 , X_ELF_VERDEF = 0x8 , X_ELF_VERSYM = 0x10 , X_ELF_NOW = 0x20 } |
enum | ModRm_Mod { MRM_I_REG , MRM_I_DISP1 , MRM_I_DISP4 , MRM_D_REG } |
enum | FuncFindType { FIND_ENDBR64 , FIND_NOP } |
enum | ElfId { X_ELF_MAIN = 0 , X_ELF_DYNAMIC_LINKER = 1 , X_ELF_LIBC = 2 , X_ELF_LIBCRYPTO = 3 } |
enum | StringXrefId { XREF_xcalloc_zero_size = 0 , XREF_Could_not_chdir_to_home_directory_s_s = 1 , XREF_list_hostkey_types = 2 , XREF_demote_sensitive_data = 3 , XREF_mm_terminate = 4 , XREF_mm_pty_allocate = 5 , XREF_mm_do_pam_account = 6 , XREF_mm_session_pty_cleanup2 = 7 , XREF_mm_getpwnamallow = 8 , XREF_mm_sshpam_init_ctx = 9 , XREF_mm_sshpam_query = 10 , XREF_mm_sshpam_respond = 11 , XREF_mm_sshpam_free_ctx = 12 , XREF_mm_choose_dh = 13 , XREF_sshpam_respond = 14 , XREF_sshpam_auth_passwd = 15 , XREF_sshpam_query = 16 , XREF_start_pam = 17 , XREF_mm_request_send = 18 , XREF_mm_log_handler = 19 , XREF_Could_not_get_agent_socket = 20 , XREF_auth_root_allowed = 21 , XREF_mm_answer_authpassword = 22 , XREF_mm_answer_keyallowed = 23 , XREF_mm_answer_keyverify = 24 , XREF_48s_48s_d_pid_ld_ = 25 , XREF_Unrecognized_internal_syslog_level_code_d = 26 } |
enum | EncodedStringId { STR_from = 0x810 , STR_ssh2 = 0x678 , STR_48s_48s_d_pid_ld_ = 0xd8 , STR_s = 0x708 , STR_usr_sbin_sshd = 0x108 , STR_Accepted_password_for = 0x870 , STR_Accepted_publickey_for = 0x1a0 , STR_BN_bin2bn = 0xc40 , STR_BN_bn2bin = 0x6d0 , STR_BN_dup = 0x958 , STR_BN_free = 0x418 , STR_BN_num_bits = 0x4e0 , STR_Connection_closed_by = 0x790 , STR_Could_not_chdir_to_home_directory_s_s = 0x18 , STR_Could_not_get_agent_socket = 0xb0 , STR_DISPLAY = 0x960 , STR_DSA_get0_pqg = 0x9d0 , STR_DSA_get0_pub_key = 0x468 , STR_EC_KEY_get0_group = 0x7e8 , STR_EC_KEY_get0_public_key = 0x268 , STR_EC_POINT_point2oct = 0x6e0 , STR_EVP_CIPHER_CTX_free = 0xb28 , STR_EVP_CIPHER_CTX_new = 0x838 , STR_EVP_DecryptFinal_ex = 0x2a8 , STR_EVP_DecryptInit_ex = 0xc08 , STR_EVP_DecryptUpdate = 0x3f0 , STR_EVP_Digest = 0xf8 , STR_EVP_DigestVerify = 0x408 , STR_EVP_DigestVerifyInit = 0x118 , STR_EVP_MD_CTX_free = 0xd10 , STR_EVP_MD_CTX_new = 0xaf8 , STR_EVP_PKEY_free = 0x6f8 , STR_EVP_PKEY_new_raw_public_key = 0x758 , STR_EVP_PKEY_set1_RSA = 0x510 , STR_EVP_chacha20 = 0xc28 , STR_EVP_sha256 = 0xc60 , STR_EVP_sm = 0x188 , STR_GLIBC_2_2_5 = 0x8c0 , STR_GLRO_dl_naudit_naudit = 0x6a8 , STR_KRB5CCNAME = 0x1e0 , STR_LD_AUDIT = 0xcf0 , STR_LD_BIND_NOT = 0xbc0 , STR_LD_DEBUG = 0xa90 , STR_LD_PROFILE = 0xb98 , STR_LD_USE_LOAD_BIAS = 0x3e0 , STR_LINES = 0xa88 , STR_RSA_free = 0xac0 , STR_RSA_get0_key = 0x798 , STR_RSA_new = 0x918 , STR_RSA_public_decrypt = 0x1d0 , STR_RSA_set0_key = 0x540 , STR_RSA_sign = 0x8f8 , STR_SSH_2_0 = 0x990 , STR_TERM = 0x4a8 , STR_Unrecognized_internal_syslog_level_code_d = 0xe0 , STR_WAYLAND_DISPLAY = 0x158 , STR_errno_location = 0x878 , STR_libc_stack_end = 0x2b0 , STR_libc_start_main = 0x228 , STR_dl_audit_preinit = 0xa60 , STR_dl_audit_symbind_alt = 0x9c8 , STR_exit = 0x8a8 , STR_r_debug = 0x5b0 , STR_rtld_global = 0x5b8 , STR_rtld_global_ro = 0xa98 , STR_auth_root_allowed = 0xb8 , STR_authenticating = 0x1d8 , STR_demote_sensitive_data = 0x28 , STR_getuid = 0x348 , STR_ld_linux_x86_64_so = 0xa48 , STR_libc_so = 0x7d0 , STR_libcrypto_so = 0x7c0 , STR_liblzma_so = 0x590 , STR_libsystemd_so = 0x938 , STR_list_hostkey_types = 0x20 , STR_malloc_usable_size = 0x440 , STR_mm_answer_authpassword = 0xc0 , STR_mm_answer_keyallowed = 0xc8 , STR_mm_answer_keyverify = 0xd0 , STR_mm_answer_pam_start = 0x948 , STR_mm_choose_dh = 0x78 , STR_mm_do_pam_account = 0x40 , STR_mm_getpwnamallow = 0x50 , STR_mm_log_handler = 0xa8 , STR_mm_pty_allocate = 0x38 , STR_mm_request_send = 0xa0 , STR_mm_session_pty_cleanup2 = 0x48 , STR_mm_sshpam_free_ctx = 0x70 , STR_mm_sshpam_init_ctx = 0x58 , STR_mm_sshpam_query = 0x60 , STR_mm_sshpam_respond = 0x68 , STR_mm_terminate = 0x30 , STR_parse_PAM = 0xc58 , STR_password = 0x400 , STR_preauth = 0x4f0 , STR_pselect = 0x690 , STR_publickey = 0x7b8 , STR_read = 0x308 , STR_rsa_sha2_256 = 0x710 , STR_setlogmask = 0x428 , STR_setresgid = 0x5f0 , STR_setresuid = 0xab8 , STR_shutdown = 0x760 , STR_ssh_2_0 = 0xd08 , STR_ssh_rsa_cert_v01_openssh_com = 0x2c8 , STR_sshpam_auth_passwd = 0x88 , STR_sshpam_query = 0x90 , STR_sshpam_respond = 0x80 , STR_start_pam = 0x98 , STR_system = 0x9f8 , STR_unknown = 0x198 , STR_user = 0xb10 , STR_write = 0x380 , STR_xcalloc_zero_size = 0x10 , STR_yolAbejyiejuvnupEvjtgvsh5okmkAvj = 0xb00 , STR_ELF = 0x300 } |
enum | PayloadState { PAYLOAD_STATE_INITIAL = -1 } |
enum | dasm_modrm_mask { XZ_MODRM_RM = 0xFF000000 , XZ_MODRM_REG = 0x00FF0000 , XZ_MODRM_MOD = 0x0000FF00 , XZ_MODRM_RAW = 0x000000FF } |
enum | LogLevel { SYSLOG_LEVEL_QUIET , SYSLOG_LEVEL_FATAL , SYSLOG_LEVEL_ERROR , SYSLOG_LEVEL_INFO , SYSLOG_LEVEL_VERBOSE , SYSLOG_LEVEL_DEBUG1 , SYSLOG_LEVEL_DEBUG2 , SYSLOG_LEVEL_DEBUG3 , SYSLOG_LEVEL_NOT_SET = -1 } |
enum | CommandFlags1 { X_FLAGS1_8BYTES = 0x1 , X_FLAGS1_SETLOGMASK = 0x4 , X_FLAGS1_SOCKET_INDEX = 0x20 , X_FLAGS1_DISABLE_PAM = 0x40 , X_FLAGS1_NO_EXTENDED_SIZE = 0x80 } |
enum | CommandFlags2 { X_FLAGS2_IMPERSONATE = 0x1 , X_FLAGS2_CHANGE_MONITOR_REQ = 0x2 , X_FLAGS2_AUTH_BYPASS = 0x4 , X_FLAGS2_CONTINUATION = 0x40 , X_FLAGS2_PSELECT = 0xC0 , X_FLAGS2_SOCKFD_MASK = 0x78 } |
enum | CommandFlags3 { X_FLAGS3_SOCKET_NUM = 0x1F , X_FLAGS3_MONITOR_REQ_VAL = 0x3F } |
enum | SocketMode { DIR_WRITE = 0 , DIR_READ = 1 } |
Functions | |
assert_offset (got_ctx_t, got_ptr, 0) | |
assert_offset (got_ctx_t, return_address, 0x8) | |
assert_offset (got_ctx_t, cpuid_fn, 0x10) | |
assert_offset (got_ctx_t, got_offset, 0x18) | |
assert_offset (elf_entry_ctx_t, symbol_ptr, 0) | |
assert_offset (elf_entry_ctx_t, got_ctx, 0x8) | |
assert_offset (elf_entry_ctx_t, frame_address, 0x28) | |
assert_offset (dasm_ctx_t, instruction, 0) | |
assert_offset (dasm_ctx_t, instruction_size, 8) | |
assert_offset (dasm_ctx_t, flags, 0x10) | |
assert_offset (dasm_ctx_t, flags2, 0x11) | |
assert_offset (dasm_ctx_t, lock_rep_byte, 0x14) | |
assert_offset (dasm_ctx_t, seg_byte, 0x15) | |
assert_offset (dasm_ctx_t, osize_byte, 0x16) | |
assert_offset (dasm_ctx_t, asize_byte, 0x17) | |
assert_offset (dasm_ctx_t, vex_byte, 0x18) | |
assert_offset (dasm_ctx_t, vex_byte2, 0x19) | |
assert_offset (dasm_ctx_t, vex_byte3, 0x1A) | |
assert_offset (dasm_ctx_t, rex_byte, 0x1B) | |
assert_offset (dasm_ctx_t, modrm, 0x1C) | |
assert_offset (dasm_ctx_t, modrm_mod, 0x1D) | |
assert_offset (dasm_ctx_t, modrm_reg, 0x1E) | |
assert_offset (dasm_ctx_t, modrm_rm, 0x1F) | |
assert_offset (dasm_ctx_t, imm64_reg, 0x20) | |
assert_offset (dasm_ctx_t, sib, 0x21) | |
assert_offset (dasm_ctx_t, sib_scale, 0x22) | |
assert_offset (dasm_ctx_t, sib_index, 0x23) | |
assert_offset (dasm_ctx_t, sib_base, 0x24) | |
assert_offset (dasm_ctx_t, opcode, 0x28) | |
assert_offset (dasm_ctx_t, mem_disp, 0x30) | |
assert_offset (dasm_ctx_t, operand, 0x38) | |
assert_offset (dasm_ctx_t, operand_zeroextended, 0x40) | |
assert_offset (dasm_ctx_t, operand_size, 0x48) | |
assert_offset (dasm_ctx_t, insn_offset, 0x50) | |
assert_offset (elf_info_t, elfbase, 0x0) | |
assert_offset (elf_info_t, first_vaddr, 0x8) | |
assert_offset (elf_info_t, phdrs, 0x10) | |
assert_offset (elf_info_t, e_phnum, 0x18) | |
assert_offset (elf_info_t, dyn, 0x20) | |
assert_offset (elf_info_t, dyn_num_entries, 0x28) | |
assert_offset (elf_info_t, strtab, 0x30) | |
assert_offset (elf_info_t, symtab, 0x38) | |
assert_offset (elf_info_t, plt_relocs, 0x40) | |
assert_offset (elf_info_t, plt_relocs_num, 0x48) | |
assert_offset (elf_info_t, gnurelro_found, 0x4C) | |
assert_offset (elf_info_t, gnurelro_vaddr, 0x50) | |
assert_offset (elf_info_t, gnurelro_memsize, 0x58) | |
assert_offset (elf_info_t, verdef, 0x60) | |
assert_offset (elf_info_t, verdef_num, 0x68) | |
assert_offset (elf_info_t, versym, 0x70) | |
assert_offset (elf_info_t, rela_relocs, 0x78) | |
assert_offset (elf_info_t, rela_relocs_num, 0x80) | |
assert_offset (elf_info_t, relr_relocs, 0x88) | |
assert_offset (elf_info_t, relr_relocs_num, 0x90) | |
assert_offset (elf_info_t, code_segment_start, 0x98) | |
assert_offset (elf_info_t, code_segment_size, 0xA0) | |
assert_offset (elf_info_t, rodata_segment_start, 0xA8) | |
assert_offset (elf_info_t, rodata_segment_size, 0xB0) | |
assert_offset (elf_info_t, data_segment_start, 0xB8) | |
assert_offset (elf_info_t, data_segment_size, 0xC0) | |
assert_offset (elf_info_t, data_segment_alignment, 0xC8) | |
assert_offset (elf_info_t, flags, 0xD0) | |
assert_offset (elf_info_t, gnu_hash_nbuckets, 0xd8) | |
assert_offset (elf_info_t, gnu_hash_last_bloom, 0xdc) | |
assert_offset (elf_info_t, gnu_hash_bloom_shift, 0xe0) | |
assert_offset (elf_info_t, gnu_hash_bloom, 0xe8) | |
assert_offset (elf_info_t, gnu_hash_buckets, 0xf0) | |
assert_offset (elf_info_t, gnu_hash_chain, 0xf8) | |
assert_offset (libc_imports_t, resolved_imports_count, 0) | |
assert_offset (libc_imports_t, malloc_usable_size, 8) | |
assert_offset (libc_imports_t, getuid, 0x10) | |
assert_offset (libc_imports_t, exit, 0x18) | |
assert_offset (libc_imports_t, setresgid, 0x20) | |
assert_offset (libc_imports_t, setresuid, 0x28) | |
assert_offset (libc_imports_t, system, 0x30) | |
assert_offset (libc_imports_t, write, 0x38) | |
assert_offset (libc_imports_t, pselect, 0x40) | |
assert_offset (libc_imports_t, read, 0x48) | |
assert_offset (libc_imports_t, __errno_location, 0x50) | |
assert_offset (libc_imports_t, setlogmask, 0x58) | |
assert_offset (libc_imports_t, shutdown, 0x60) | |
assert_offset (libc_imports_t, __libc_stack_end, 0x68) | |
assert_offset (imported_funcs_t, RSA_public_decrypt, 0) | |
assert_offset (imported_funcs_t, EVP_PKEY_set1_RSA, 8) | |
assert_offset (imported_funcs_t, RSA_get0_key_null, 0x10) | |
assert_offset (imported_funcs_t, RSA_public_decrypt_plt, 0x18) | |
assert_offset (imported_funcs_t, EVP_PKEY_set1_RSA_plt, 0x20) | |
assert_offset (imported_funcs_t, RSA_get0_key_plt, 0x28) | |
assert_offset (imported_funcs_t, DSA_get0_pqg, 0x30) | |
assert_offset (imported_funcs_t, DSA_get0_pub_key, 0x38) | |
assert_offset (imported_funcs_t, EC_POINT_point2oct, 0x40) | |
assert_offset (imported_funcs_t, EC_KEY_get0_public_key, 0x48) | |
assert_offset (imported_funcs_t, EC_KEY_get0_group, 0x50) | |
assert_offset (imported_funcs_t, EVP_sha256, 0x58) | |
assert_offset (imported_funcs_t, RSA_get0_key, 0x60) | |
assert_offset (imported_funcs_t, BN_num_bits, 0x68) | |
assert_offset (imported_funcs_t, EVP_PKEY_new_raw_public_key, 0x70) | |
assert_offset (imported_funcs_t, EVP_MD_CTX_new, 0x78) | |
assert_offset (imported_funcs_t, EVP_DigestVerifyInit, 0x80) | |
assert_offset (imported_funcs_t, EVP_DigestVerify, 0x88) | |
assert_offset (imported_funcs_t, EVP_MD_CTX_free, 0x90) | |
assert_offset (imported_funcs_t, EVP_PKEY_free, 0x98) | |
assert_offset (imported_funcs_t, EVP_CIPHER_CTX_new, 0xA0) | |
assert_offset (imported_funcs_t, EVP_DecryptInit_ex, 0xA8) | |
assert_offset (imported_funcs_t, EVP_DecryptUpdate, 0xB0) | |
assert_offset (imported_funcs_t, EVP_DecryptFinal_ex, 0xB8) | |
assert_offset (imported_funcs_t, EVP_CIPHER_CTX_free, 0xC0) | |
assert_offset (imported_funcs_t, EVP_chacha20, 0xC8) | |
assert_offset (imported_funcs_t, RSA_new, 0xD0) | |
assert_offset (imported_funcs_t, BN_dup, 0xD8) | |
assert_offset (imported_funcs_t, BN_bin2bn, 0xE0) | |
assert_offset (imported_funcs_t, RSA_set0_key, 0xE8) | |
assert_offset (imported_funcs_t, EVP_Digest, 0xF0) | |
assert_offset (imported_funcs_t, RSA_sign, 0xF8) | |
assert_offset (imported_funcs_t, BN_bn2bin, 0x100) | |
assert_offset (imported_funcs_t, RSA_free, 0x108) | |
assert_offset (imported_funcs_t, BN_free, 0x110) | |
assert_offset (imported_funcs_t, libc, 0x118) | |
assert_offset (imported_funcs_t, resolved_imports_count, 0x120) | |
assert_offset (sshd_ctx_t, have_mm_answer_keyallowed, 0x0) | |
assert_offset (sshd_ctx_t, have_mm_answer_authpassword, 0x4) | |
assert_offset (sshd_ctx_t, have_mm_answer_keyverify, 0x8) | |
assert_offset (sshd_ctx_t, mm_answer_authpassword_hook, 0x10) | |
assert_offset (sshd_ctx_t, mm_answer_keyallowed, 0x18) | |
assert_offset (sshd_ctx_t, mm_answer_keyverify, 0x20) | |
assert_offset (sshd_ctx_t, mm_answer_authpassword_start, 0x28) | |
assert_offset (sshd_ctx_t, mm_answer_authpassword_end, 0x30) | |
assert_offset (sshd_ctx_t, mm_answer_authpassword_ptr, 0x38) | |
assert_offset (sshd_ctx_t, monitor_reqtype_authpassword, 0x40) | |
assert_offset (sshd_ctx_t, mm_answer_keyallowed_start, 0x48) | |
assert_offset (sshd_ctx_t, mm_answer_keyallowed_end, 0x50) | |
assert_offset (sshd_ctx_t, mm_answer_keyallowed_ptr, 0x58) | |
assert_offset (sshd_ctx_t, mm_answer_keyallowed_reqtype, 0x60) | |
assert_offset (sshd_ctx_t, mm_answer_keyverify_start, 0x68) | |
assert_offset (sshd_ctx_t, mm_answer_keyverify_end, 0x70) | |
assert_offset (sshd_ctx_t, mm_answer_keyverify_ptr, 0x78) | |
assert_offset (sshd_ctx_t, writebuf_size, 0x84) | |
assert_offset (sshd_ctx_t, writebuf, 0x88) | |
assert_offset (sshd_ctx_t, STR_unknown_ptr, 0xA0) | |
assert_offset (sshd_ctx_t, mm_request_send_start, 0xA8) | |
assert_offset (sshd_ctx_t, mm_request_send_end, 0xB0) | |
assert_offset (sshd_ctx_t, use_pam_ptr, 0xC0) | |
assert_offset (sshd_ctx_t, permit_root_login_ptr, 0xC8) | |
assert_offset (sshd_ctx_t, STR_without_password, 0xD0) | |
assert_offset (sshd_ctx_t, STR_publickey, 0xD8) | |
assert_offset (sshd_log_ctx_t, logging_disabled, 0x0) | |
assert_offset (sshd_log_ctx_t, log_hooking_possible, 0x4) | |
assert_offset (sshd_log_ctx_t, syslog_disabled, 0x8) | |
assert_offset (sshd_log_ctx_t, STR_percent_s, 0x10) | |
assert_offset (sshd_log_ctx_t, STR_Connection_closed_by, 0x18) | |
assert_offset (sshd_log_ctx_t, STR_preauth, 0x20) | |
assert_offset (sshd_log_ctx_t, STR_authenticating, 0x28) | |
assert_offset (sshd_log_ctx_t, STR_user, 0x30) | |
assert_offset (sshd_log_ctx_t, log_handler_ptr, 0x38) | |
assert_offset (sshd_log_ctx_t, log_handler_ctx_ptr, 0x40) | |
assert_offset (sshd_log_ctx_t, orig_log_handler, 0x48) | |
assert_offset (sshd_log_ctx_t, orig_log_handler_ctx, 0x50) | |
assert_offset (sshd_log_ctx_t, sshlogv, 0x58) | |
assert_offset (sshd_log_ctx_t, mm_log_handler, 0x60) | |
assert_offset (global_context_t, uses_endbr64, 0x0) | |
assert_offset (global_context_t, imported_funcs, 0x8) | |
assert_offset (global_context_t, libc_imports, 0x10) | |
assert_offset (global_context_t, disable_backdoor, 0x18) | |
assert_offset (global_context_t, sshd_ctx, 0x20) | |
assert_offset (global_context_t, sshd_sensitive_data, 0x28) | |
assert_offset (global_context_t, sshd_log_ctx, 0x30) | |
assert_offset (global_context_t, STR_ssh_rsa_cert_v01_openssh_com, 0x38) | |
assert_offset (global_context_t, STR_rsa_sha2_256, 0x40) | |
assert_offset (global_context_t, struct_monitor_ptr_address, 0x48) | |
assert_offset (global_context_t, exit_flag, 0x50) | |
assert_offset (global_context_t, sshd_offsets, 0x54) | |
assert_offset (global_context_t, sshd_code_start, 0x58) | |
assert_offset (global_context_t, sshd_code_end, 0x60) | |
assert_offset (global_context_t, sshd_data_start, 0x68) | |
assert_offset (global_context_t, sshd_data_end, 0x70) | |
assert_offset (global_context_t, lzma_code_start, 0x80) | |
assert_offset (global_context_t, lzma_code_end, 0x88) | |
assert_offset (global_context_t, uid, 0x90) | |
assert_offset (global_context_t, sock_read_buf_size, 0x98) | |
assert_offset (global_context_t, sock_read_buf, 0xA0) | |
assert_offset (global_context_t, payload_data_size, 0xE0) | |
assert_offset (global_context_t, current_data_size, 0xE8) | |
assert_offset (global_context_t, payload_data, 0xF0) | |
assert_offset (global_context_t, sshd_payload_ctx, 0xF8) | |
assert_offset (global_context_t, sshd_host_pubkey_idx, 0x100) | |
assert_offset (global_context_t, payload_state, 0x104) | |
assert_offset (global_context_t, secret_data, 0x108) | |
assert_offset (global_context_t, shift_operations, 0x141) | |
assert_offset (global_context_t, num_shifted_bits, 0x160) | |
assert_offset (backdoor_shared_globals_t, mm_answer_authpassword_hook, 0x0) | |
assert_offset (backdoor_shared_globals_t, hook_EVP_PKEY_set1_RSA, 0x8) | |
assert_offset (backdoor_shared_globals_t, globals, 0x10) | |
assert_offset (ldso_ctx_t, libcrypto_auditstate_bindflags_ptr, 0x40) | |
assert_offset (ldso_ctx_t, libcrypto_auditstate_bindflags_old_value, 0x48) | |
assert_offset (ldso_ctx_t, sshd_auditstate_bindflags_ptr, 0x50) | |
assert_offset (ldso_ctx_t, sshd_auditstate_bindflags_old_value, 0x58) | |
assert_offset (ldso_ctx_t, sshd_link_map_l_audit_any_plt_addr, 0x60) | |
assert_offset (ldso_ctx_t, link_map_l_audit_any_plt_bitmask, 0x68) | |
assert_offset (ldso_ctx_t, _dl_audit_ptr, 0x70) | |
assert_offset (ldso_ctx_t, _dl_naudit_ptr, 0x78) | |
assert_offset (ldso_ctx_t, hooked_audit_ifaces, 0x80) | |
assert_offset (ldso_ctx_t, libcrypto_l_name, 0xF8) | |
assert_offset (ldso_ctx_t, _dl_audit_symbind_alt, 0x100) | |
assert_offset (ldso_ctx_t, _dl_audit_symbind_alt__size, 0x108) | |
assert_offset (ldso_ctx_t, hook_RSA_public_decrypt, 0x110) | |
assert_offset (ldso_ctx_t, hook_EVP_PKEY_set1_RSA, 0x118) | |
assert_offset (ldso_ctx_t, hook_RSA_get0_key, 0x120) | |
assert_offset (ldso_ctx_t, imported_funcs, 0x128) | |
assert_offset (ldso_ctx_t, hooks_installed, 0x130) | |
assert_offset (backdoor_hooks_data_t, ldso_ctx, 0) | |
assert_offset (backdoor_hooks_data_t, global_ctx, 0x138) | |
assert_offset (backdoor_hooks_data_t, imported_funcs, 0x2A0) | |
assert_offset (backdoor_hooks_data_t, sshd_ctx, 0x3C8) | |
assert_offset (backdoor_hooks_data_t, libc_imports, 0x4A8) | |
assert_offset (backdoor_hooks_data_t, sshd_log_ctx, 0x518) | |
assert_offset (backdoor_hooks_data_t, signed_data_size, 0x580) | |
assert_offset (backdoor_hooks_data_t, signed_data, 0x588) | |
assert_offset (backdoor_hooks_ctx_t, shared, 0x30) | |
assert_offset (backdoor_hooks_ctx_t, hooks_data_addr, 0x38) | |
assert_offset (backdoor_hooks_ctx_t, symbind64, 0x40) | |
assert_offset (backdoor_hooks_ctx_t, hook_RSA_public_decrypt, 0x48) | |
assert_offset (backdoor_hooks_ctx_t, hook_RSA_get0_key, 0x50) | |
assert_offset (backdoor_hooks_ctx_t, mm_log_handler, 0x58) | |
assert_offset (backdoor_hooks_ctx_t, mm_answer_keyallowed, 0x70) | |
assert_offset (backdoor_hooks_ctx_t, mm_answer_keyverify, 0x78) | |
assert_offset (backdoor_setup_params_t, shared, 0x8) | |
assert_offset (backdoor_setup_params_t, hook_params, 0x10) | |
assert_offset (backdoor_setup_params_t, entry_ctx, 0x80) | |
assert_offset (elf_handles_t, main, 0x0) | |
assert_offset (elf_handles_t, dynamic_linker, 0x8) | |
assert_offset (elf_handles_t, libc, 0x10) | |
assert_offset (elf_handles_t, liblzma, 0x18) | |
assert_offset (elf_handles_t, libcrypto, 0x20) | |
assert_offset (main_elf_t, elf_handles, 0x0) | |
assert_offset (main_elf_t, dynamic_linker_ehdr, 0x8) | |
assert_offset (main_elf_t, __libc_stack_end, 0x10) | |
assert_offset (backdoor_data_handle_t, data, 0x0) | |
assert_offset (backdoor_data_handle_t, elf_handles, 0x8) | |
assert_offset (string_item_t, string_id, 0) | |
assert_offset (string_item_t, func_start, 0x8) | |
assert_offset (string_item_t, func_end, 0x10) | |
assert_offset (string_item_t, xref, 0x18) | |
assert_offset (string_references_t, entries, 0) | |
assert_offset (backdoor_data_t, main_map, 0) | |
assert_offset (backdoor_data_t, dynamic_linker_map, 0x8) | |
assert_offset (backdoor_data_t, liblzma_map, 0x10) | |
assert_offset (backdoor_data_t, libcrypto_map, 0x18) | |
assert_offset (backdoor_data_t, libsystemd_map, 0x20) | |
assert_offset (backdoor_data_t, libc_map, 0x28) | |
assert_offset (backdoor_data_t, elf_handles, 0x30) | |
assert_offset (backdoor_data_t, data_handle, 0x58) | |
assert_offset (backdoor_data_t, main_info, 0x68) | |
assert_offset (backdoor_data_t, dynamic_linker_info, 0x168) | |
assert_offset (backdoor_data_t, libc_info, 0x268) | |
assert_offset (backdoor_data_t, liblzma_info, 0x368) | |
assert_offset (backdoor_data_t, libcrypto_info, 0x468) | |
assert_offset (backdoor_data_t, libc_imports, 0x568) | |
assert_offset (backdoor_data_t, string_refs, 0x5D8) | |
assert_offset (backdoor_data_t, fake_allocator, 0x938) | |
assert_offset (backdoor_data_t, import_resolver, 0x950) | |
assert_offset (backdoor_shared_libraries_data_t, data, 0x0) | |
assert_offset (backdoor_shared_libraries_data_t, elf_handles, 0x8) | |
assert_offset (backdoor_shared_libraries_data_t, RSA_public_decrypt_plt, 0x10) | |
assert_offset (backdoor_shared_libraries_data_t, EVP_PKEY_set1_RSA_plt, 0x18) | |
assert_offset (backdoor_shared_libraries_data_t, RSA_get0_key_plt, 0x20) | |
assert_offset (backdoor_shared_libraries_data_t, hooks_data_addr, 0x28) | |
assert_offset (backdoor_shared_libraries_data_t, libc_imports, 0x30) | |
assert_offset (secret_data_item_t, code, 0x0) | |
assert_offset (secret_data_item_t, shift_cursor, 0x8) | |
assert_offset (secret_data_item_t, operation_index, 0xC) | |
assert_offset (secret_data_item_t, shift_count, 0x10) | |
assert_offset (secret_data_item_t, index, 0x14) | |
assert_offset (backdoor_payload_body_t, args, 0x72) | |
assert_offset (backdoor_payload_t, header, 0) | |
assert_offset (backdoor_payload_t, body, 16) | |
assert_offset (key_payload_t, hdr, 0) | |
assert_offset (key_payload_t, body_length, 16) | |
assert_offset (key_payload_t, body, 18) | |
assert_offset (cmd_arguments_t, flags1, 0) | |
assert_offset (cmd_arguments_t, flags2, 1) | |
assert_offset (cmd_arguments_t, flags3, 2) | |
assert_offset (cmd_arguments_t, u, 3) | |
assert_offset (key_ctx_t, rsa_n, 0) | |
assert_offset (key_ctx_t, rsa_e, 0x8) | |
assert_offset (key_ctx_t, args, 0x10) | |
assert_offset (key_ctx_t, payload, 0x15) | |
assert_offset (key_ctx_t, ivec, 0x26D) | |
assert_offset (key_ctx_t, ed448_key, 0x27D) | |
assert_offset (monitor_data_t, cmd_type, 0) | |
assert_offset (monitor_data_t, args, 0x8) | |
assert_offset (monitor_data_t, rsa_n, 0x10) | |
assert_offset (monitor_data_t, rsa_e, 0x18) | |
assert_offset (monitor_data_t, payload_body, 0x20) | |
assert_offset (monitor_data_t, payload_body_size, 0x28) | |
assert_offset (monitor_data_t, rsa, 0x30) | |
assert_offset (run_backdoor_commands_data_t, body_size, 0) | |
assert_offset (run_backdoor_commands_data_t, p_do_orig, 8) | |
assert_offset (run_backdoor_commands_data_t, payload_size, 0x10) | |
assert_offset (run_backdoor_commands_data_t, hostkey_hash_offset, 0x18) | |
assert_offset (run_backdoor_commands_data_t, rsa, 0x20) | |
assert_offset (run_backdoor_commands_data_t, ed448_key_ptr, 0x30) | |
assert_offset (run_backdoor_commands_data_t, num_keys, 0x38) | |
assert_offset (run_backdoor_commands_data_t, key_cur_idx, 0x44) | |
assert_offset (run_backdoor_commands_data_t, key_prev_idx, 0x48) | |
assert_offset (run_backdoor_commands_data_t, unk57, 0x57) | |
assert_offset (run_backdoor_commands_data_t, u.keys.num_host_keys, 0x58) | |
assert_offset (run_backdoor_commands_data_t, u.keys.num_host_pubkeys, 0x60) | |
assert_offset (run_backdoor_commands_data_t, u.keys.ed448_key, 0x68) | |
assert_offset (run_backdoor_commands_data_t, data, 0xA8) | |
assert_offset (run_backdoor_commands_data_t, kctx, 0x308) | |
assert_offset (backdoor_cpuid_reloc_consts_t, cpuid_random_symbol_got_offset, 0) | |
assert_offset (backdoor_cpuid_reloc_consts_t, cpuid_got_index, 0x8) | |
assert_offset (backdoor_cpuid_reloc_consts_t, backdoor_init_stage2_got_offset, 0x10) | |
assert_offset (backdoor_tls_get_addr_reloc_consts_t, tls_get_addr_plt_offset, 0) | |
assert_offset (backdoor_tls_get_addr_reloc_consts_t, tls_get_addr_random_symbol_got_offset, 0x8) | |
assert_offset (elf_functions_t, init_hook_functions, 0x8) | |
assert_offset (elf_functions_t, elf_symbol_get_addr, 0x20) | |
assert_offset (elf_functions_t, elf_parse, 0x30) | |
assert_offset (fake_lzma_allocator_t, allocator.alloc, 0x8) | |
assert_offset (fake_lzma_allocator_t, allocator.free, 0x10) | |
assert_offset (fake_lzma_allocator_t, allocator.opaque, 0x18) | |
assert_offset (instruction_search_ctx_t, start_addr, 0) | |
assert_offset (instruction_search_ctx_t, end_addr, 0x8) | |
assert_offset (instruction_search_ctx_t, offset_to_match, 0x10) | |
assert_offset (instruction_search_ctx_t, output_register_to_match, 0x18) | |
assert_offset (instruction_search_ctx_t, output_register, 0x20) | |
assert_offset (instruction_search_ctx_t, result, 0x28) | |
assert_offset (instruction_search_ctx_t, hooks, 0x30) | |
assert_offset (instruction_search_ctx_t, imported_funcs, 0x38) | |
BOOL | sshd_proxy_elevate (monitor_data_t *args, global_context_t *ctx) |
forges a new MONITOR_REQ_KEYALLOWED packet, and injects it into the server to gain root privileges through the sshd monitor. More... | |
BOOL | x86_dasm (dasm_ctx_t *ctx, u8 *code_start, u8 *code_end) |
disassembles the given x64 code More... | |
BOOL | find_call_instruction (u8 *code_start, u8 *code_end, u8 *call_target, dasm_ctx_t *dctx) |
finds a call instruction More... | |
BOOL | find_lea_instruction (u8 *code_start, u8 *code_end, u64 displacement) |
finds a lea instruction More... | |
BOOL | find_instruction_with_mem_operand (u8 *code_start, u8 *code_end, dasm_ctx_t *dctx, void *mem_address) |
finds a LEA or MOV instruction with an immediate memory operand More... | |
BOOL | find_lea_instruction_with_mem_operand (u8 *code_start, u8 *code_end, dasm_ctx_t *dctx, void *mem_address) |
finds a LEA instruction with an immediate memory operand More... | |
BOOL | find_add_instruction_with_mem_operand (u8 *code_start, u8 *code_end, dasm_ctx_t *dctx, void *mem_address) |
finds an ADD instruction with an immediate memory operand More... | |
BOOL | find_mov_lea_instruction (u8 *code_start, u8 *code_end, BOOL is_64bit_operand, BOOL load_flag, dasm_ctx_t *dctx) |
like find_mov_instruction, but also considers LEA instructions More... | |
BOOL | find_mov_instruction (u8 *code_start, u8 *code_end, BOOL is_64bit_operand, BOOL load_flag, dasm_ctx_t *dctx) |
finds a MOV instruction. More... | |
BOOL | find_instruction_with_mem_operand_ex (u8 *code_start, u8 *code_end, dasm_ctx_t *dctx, int opcode, void *mem_address) |
finds an instruction with an immediate memory operand More... | |
BOOL | is_endbr64_instruction (u8 *code_start, u8 *code_end, u32 low_mask_part) |
Checks if the code between code_start and code_end is an endbr64 instruction. More... | |
u8 * | find_string_reference (u8 *code_start, u8 *code_end, const char *str) |
finds an instruction that references the given string More... | |
u8 * | elf_find_string_reference (elf_info_t *elf_info, EncodedStringId encoded_string_id, u8 *code_start, u8 *code_end) |
finds an instruction that references the given string More... | |
BOOL | find_reg2reg_instruction (u8 *code_start, u8 *code_end, dasm_ctx_t *dctx) |
finds a reg2reg instruction More... | |
BOOL | find_function_prologue (u8 *code_start, u8 *code_end, u8 **output, FuncFindType find_mode) |
locates the function prologue More... | |
BOOL | find_function (u8 *code_start, void **func_start, void **func_end, u8 *search_base, u8 *code_end, FuncFindType find_mode) |
locates the function boundaries. More... | |
BOOL | elf_contains_vaddr (elf_info_t *elf_info, void *vaddr, u64 size, u32 p_flags) |
checks if given ELF file contains the range [vaddr, vaddr+size) in a segment with the specified memory protection flags More... | |
BOOL | elf_contains_vaddr_relro (elf_info_t *elf_info, u64 vaddr, u64 size, u32 p_flags) |
checks if given ELF file contains the range [vaddr, vaddr+size) in the gnurelro segment More... | |
BOOL | elf_parse (Elf64_Ehdr *ehdr, elf_info_t *elf_info) |
Parses the given in-memory ELF file into elf_info. More... | |
BOOL | is_gnu_relro (Elf64_Word p_type, u32 addend) |
checks if the provided identifiers represent a PT_GNU_RELRO More... | |
BOOL | main_elf_parse (main_elf_t *main_elf) |
Parses the main executable from the provided structure. As part of the process the arguments and environment is checked. More... | |
char * | check_argument (char arg_first_char, char *arg_name) |
BOOL | process_is_sshd (elf_info_t *elf, u8 *stack_end) |
checks if the current process is sshd by inspecting argv and envp . More... | |
BOOL | elf_find_string_references (elf_info_t *elf_info, string_references_t *refs) |
parses the ELF rodata section, looking for strings and the instructions that reference them More... | |
Elf64_Sym * | elf_symbol_get (elf_info_t *elf_info, EncodedStringId encoded_string_id, EncodedStringId sym_version) |
Looks up an ELF symbol from a parsed ELF. More... | |
void * | elf_symbol_get_addr (elf_info_t *elf_info, EncodedStringId encoded_string_id) |
Looks up an ELF symbol from a parsed ELF, and returns its memory address. More... | |
void * | elf_get_code_segment (elf_info_t *elf_info, u64 *pSize) |
Obtains the address and size of the first executable segment in the given ELF file. More... | |
void * | elf_get_rodata_segment (elf_info_t *elf_info, u64 *pSize) |
Obtains the address and size of the last readonly segment in the given ELF file this corresponds to the segment that typically contains .rodata. More... | |
void * | elf_get_data_segment (elf_info_t *elf_info, u64 *pSize, BOOL get_alignment) |
Obtains the address and size of the last read-write segment in the given ELF file this is typically the segment that contains the following sections: More... | |
void * | elf_get_reloc_symbol (elf_info_t *elf_info, Elf64_Rela *relocs, u32 num_relocs, u64 reloc_type, EncodedStringId encoded_string_id) |
Searches the ELF relocations for a symbol having name encoded_string id and relocation of type reloc_type . More... | |
void * | elf_get_plt_symbol (elf_info_t *elf_info, EncodedStringId encoded_string_id) |
Gets the PLT symbol with name encoded_string_id from the parsed ELF file. More... | |
void * | elf_get_got_symbol (elf_info_t *elf_info, EncodedStringId encoded_string_id) |
Gets the GOT symbol with name encoded_string_id from the parsed ELF file. More... | |
BOOL | elf_find_function_pointer (StringXrefId xref_id, void **pOutCodeStart, void **pOutCodeEnd, void **pOutFptrAddr, elf_info_t *elf_info, string_references_t *xrefs, global_context_t *ctx) |
this function searches for a function pointer, pointing to a function designated by the given xref_id More... | |
char * | elf_find_string (elf_info_t *elf_info, EncodedStringId *stringId_inOut, void *rodata_start_ptr) |
Locates a string in the ELF .rodata section. More... | |
lzma_allocator * | get_lzma_allocator (void) |
gets the fake LZMA allocator, used for imports resolution the "opaque" field of the structure holds a pointer to More... | |
fake_lzma_allocator_t * | get_lzma_allocator_address (void) |
gets the address of the fake LZMA allocator More... | |
void * | fake_lzma_alloc (void *opaque, size_t nmemb, size_t size) |
a fake alloc function called by lzma_alloc() that then calls elf_symbol_get_addr() More... | |
void | fake_lzma_free (void *opaque, void *ptr) |
a fake free function called by lzma_free() More... | |
elf_functions_t * | get_elf_functions_address (void) |
gets the address of the elf_functions More... | |
BOOL | secret_data_append_from_instruction (dasm_ctx_t *dctx, secret_data_shift_cursor_t *cursor) |
BOOL | secret_data_append_from_code (void *code_start, void *code_end, secret_data_shift_cursor_t shift_cursor, unsigned shift_count, BOOL start_from_call) |
Pushes secret data by validating the given code block. More... | |
BOOL | secret_data_append_item (secret_data_shift_cursor_t shift_cursor, unsigned operation_index, unsigned shift_count, int index, u8 *code) |
Calls secret_data_append_singleton, if flags are non-zero. More... | |
BOOL | secret_data_append_items (secret_data_item_t *items, u64 items_count, BOOL(*appender)(secret_data_shift_cursor_t, unsigned, unsigned, int, u8 *)) |
appends multiple secret data items at once More... | |
BOOL | secret_data_append_from_address (void *addr, secret_data_shift_cursor_t shift_cursor, unsigned shift_count, unsigned operation_index) |
calls secret_data_append_singleton with either the given code address or the return address, if addr is <= 1 More... | |
BOOL | secret_data_append_singleton (u8 *call_site, u8 *code, secret_data_shift_cursor_t shift_cursor, unsigned shift_count, unsigned operation_index) |
Shifts data in the secret data store, after validation of code . this function is intended to be invoked only once for each operation_index value. operation_index will be used as an index into a global array of flags, so that multiple calls with the same value will be a NO-OP. More... | |
BOOL | secret_data_append_from_call_site (secret_data_shift_cursor_t shift_cursor, unsigned shift_count, unsigned operation_index, BOOL bypass) |
Shifts data in the secret data store, after validation of the call site, i.e. the caller of this function for more details, see secret_data_append_singleton. More... | |
BOOL | backdoor_setup (backdoor_setup_params_t *params) |
the backdoor main method that installs the backdoor_symbind64() callback More... | |
void | init_ldso_ctx (ldso_ctx_t *ldso_ctx) |
initializes/resets ldso data More... | |
unsigned int | backdoor_entry (unsigned int cpuid_request, u64 *caller_frame) |
calls backdoor_init while in the crc64() IFUNC resolver function More... | |
void * | backdoor_init (elf_entry_ctx_t *state, u64 *caller_frame) |
calls backdoor_init_stage2 by disguising it as a call to cpuid. More... | |
void | init_elf_entry_ctx (elf_entry_ctx_t *ctx) |
initialises the elf_entry_ctx_t More... | |
void | update_got_offset (elf_entry_ctx_t *ctx) |
updates the offset to the GOT More... | |
void | update_cpuid_got_index (elf_entry_ctx_t *ctx) |
get the cpuid() GOT index More... | |
BOOL | backdoor_init_stage2 (elf_entry_ctx_t *ctx, u64 *caller_frame, void **cpuid_got_addr, backdoor_cpuid_reloc_consts_t *reloc_consts) |
BOOL | resolve_libc_imports (struct link_map *libc, elf_info_t *libc_info, libc_imports_t *imports) |
parses the libc ELF from the supplied link map, and resolves its imports More... | |
BOOL | process_shared_libraries (backdoor_shared_libraries_data_t *data) |
scans loaded libraries to identify interesting libraries More... | |
BOOL | process_shared_libraries_map (struct link_map *r_map, backdoor_shared_libraries_data_t *data) |
scans loaded libraries to identify interesting libraries and populate related data More... | |
BOOL | chacha_decrypt (u8 *in, int inl, u8 *key, u8 *iv, u8 *out, imported_funcs_t *funcs) |
decrypts a buffer with chacha20 More... | |
BOOL | secret_data_get_decrypted (u8 *output, global_context_t *ctx) |
obtains a decrypted copy of the secret data More... | |
BOOL | is_range_mapped (u8 *addr, u64 length, global_context_t *ctx) |
verify if a memory range is mapped More... | |
u32 | count_bits (u64 x) |
returns the number of 1 bits in x More... | |
EncodedStringId | get_string_id (const char *string_begin, const char *string_end) |
Get the. More... | |
unsigned int | _get_cpuid_modified (unsigned int leaf, unsigned int *eax, unsigned int *ebx, unsigned int *ecx, unsigned int *edx, u64 *caller_frame) |
the backdoor entrypoint function, called by the IFUNC resolver for liblzma crc32() and crc64() More... | |
void | _cpuid_gcc (unsigned int level, unsigned int *a, unsigned int *b, unsigned int *c, unsigned int *d) |
actually calls cpuid instruction More... | |
int | init_hooks_ctx (backdoor_hooks_ctx_t *ctx) |
Initializes the structure with hooks-related data. More... | |
int | init_shared_globals (backdoor_shared_globals_t *shared_globals) |
Initializes the backdoor_shared_globals structure. More... | |
BOOL | init_imported_funcs (imported_funcs_t *imported_funcs) |
Initializes the imported_funcs structure. More... | |
void * | update_got_address (elf_entry_ctx_t *entry_ctx) |
finds the __tls_get_addr() GOT entry More... | |
ptrdiff_t | get_tls_get_addr_random_symbol_got_offset (elf_entry_ctx_t *ctx) |
get the tls_get_addr_random_symbol GOT offset More... | |
void * | dummy_tls_get_addr (tls_index *ti) |
a dummy function that calls __tls_get_addr, to make sure its GOT slot doesn't get removed by compiler optimizations More... | |
uintptr_t | backdoor_symbind64 (Elf64_Sym *sym, unsigned int ndx, uptr *refcook, uptr *defcook, unsigned int flags, const char *symname) |
the backdoored symbind64 installed in GLRO(dl_audit) More... | |
BOOL | run_backdoor_commands (RSA *key, global_context_t *ctx, BOOL *do_orig) |
checks if the supplied RSA public key contains the backdoor commands, and executes them if present. More... | |
BOOL | find_dl_audit_offsets (backdoor_data_handle_t *data, ptrdiff_t *libname_offset, backdoor_hooks_data_t *hooks, imported_funcs_t *imported_funcs) |
Find the various offsets in ld.so that need modification to trigger _dl_audit_symbind_alt() to call backdoor_symbind64(). More... | |
BOOL | find_link_map_l_name (backdoor_data_handle_t *data_handle, ptrdiff_t *libname_offset, backdoor_hooks_data_t *hooks, imported_funcs_t *imported_funcs) |
Find struct link_map offsets required to modify ld.so's private struct auditstate state. More... | |
BOOL | find_dl_naudit (elf_info_t *dynamic_linker_elf, elf_info_t *libcrypto_elf, backdoor_hooks_data_t *hooks, imported_funcs_t *imported_funcs) |
Find __rtld_global_ro offsets required to modify ld.so's private struct audit_ifaces state. More... | |
BOOL | find_link_map_l_audit_any_plt (backdoor_data_handle_t *data, ptrdiff_t libname_offset, backdoor_hooks_data_t *hooks, imported_funcs_t *imported_funcs) |
Find struct link_map offset required to modify ld.so's private link_map::l_audit_any_plt state. More... | |
BOOL | find_link_map_l_audit_any_plt_bitmask (backdoor_data_handle_t *data, instruction_search_ctx_t *search_ctx) |
Find the bitmask required to modify ld.so's private link_map::l_audit_any_plt state. More... | |
BOOL | sshd_get_sensitive_data_address_via_xcalloc (u8 *data_start, u8 *data_end, u8 *code_start, u8 *code_end, string_references_t *string_refs, void **sensitive_data_out) |
finds the address of sensitive_data.host_keys in sshd by using XREF_xcalloc_zero_size in xcalloc More... | |
BOOL | sshd_get_sensitive_data_address_via_krb5ccname (u8 *data_start, u8 *data_end, u8 *code_start, u8 *code_end, void **sensitive_data_out, elf_info_t *elf) |
finds the address of sensitive_data.host_keys in sshd by using getenv( STR_KRB5CCNAME ) More... | |
int | sshd_get_sensitive_data_score_in_demote_sensitive_data (void *sensitive_data, elf_info_t *elf, string_references_t *refs) |
obtains a numeric score which indicates if demote_sensitive_data accesses sensitive_data or not More... | |
int | sshd_get_sensitive_data_score_in_main (void *sensitive_data, elf_info_t *elf, string_references_t *refs) |
obtains a numeric score which indicates if main accesses sensitive_data or not More... | |
int | sshd_get_sensitive_data_score_in_do_child (void *sensitive_data, elf_info_t *elf, string_references_t *refs) |
obtains a numeric score which indicates if do_child accesses sensitive_data or not More... | |
int | sshd_get_sensitive_data_score (void *sensitive_data, elf_info_t *elf, string_references_t *refs) |
obtains a numeric score which indicates if accesses sensitive_data or not More... | |
BOOL | bignum_serialize (u8 *buffer, u64 bufferSize, u64 *pOutSize, const BIGNUM *bn, imported_funcs_t *funcs) |
Serializes the BIGNUM bn to the buffer buffer . More... | |
BOOL | sshbuf_bignum_is_negative (struct sshbuf *buf) |
checks if the given serialized BIGNUM is negative More... | |
BOOL | rsa_key_hash (const RSA *rsa, u8 *mdBuf, u64 mdBufSize, imported_funcs_t *funcs) |
obtains a SHA256 hash of the supplied RSA key More... | |
BOOL | dsa_key_hash (const DSA *dsa, u8 *mdBuf, u64 mdBufSize, global_context_t *ctx) |
obtains a SHA256 hash of the supplied RSA key More... | |
BOOL | sha256 (const void *data, size_t count, u8 *mdBuf, u64 mdBufSize, imported_funcs_t *funcs) |
computes the SHA256 hash of the supplied data More... | |
BOOL | verify_signature (struct sshkey *sshkey, u8 *signed_data, u64 sshkey_digest_offset, u64 signed_data_size, u8 *signature, u8 *ed448_raw_key, global_context_t *global_ctx) |
Checks if signed_data is signed with ed448_raw_key . More... | |
BOOL | sshd_patch_variables (BOOL skip_root_patch, BOOL disable_pam, BOOL replace_monitor_reqtype, int monitor_reqtype, global_context_t *global_ctx) |
Patches the sshd configuration. More... | |
BOOL | sshd_find_monitor_struct (elf_info_t *elf, string_references_t *refs, global_context_t *ctx) |
finds the pointer to struct monitor , and updates the global context in ctx with its location More... | |
BOOL | sshd_find_main (u8 **code_start_out, elf_info_t *sshd, elf_info_t *libcrypto, imported_funcs_t *imported_funcs) |
finds the sshd_main function More... | |
BOOL | sshd_find_monitor_field_addr_in_function (u8 *code_start, u8 *code_end, u8 *data_start, u8 *data_end, void **monitor_field_ptr_out, global_context_t *ctx) |
find a pointer to a field in struct monitor by examining code referencing it More... | |
void * | find_addr_referenced_in_mov_instruction (StringXrefId id, string_references_t *refs, void *mem_range_start, void *mem_range_end) |
find an address referenced in a function More... | |
BOOL | validate_log_handler_pointers (void *addr1, void *addr2, void *search_base, u8 *code_end, string_references_t *refs, global_context_t *global) |
Validate that the two addresses are the expected/correct ones. More... | |
BOOL | sshd_get_client_socket (global_context_t *ctx, int *pSocket, int socket_index, enum SocketMode socket_direction) |
Get either the read or write end of the sshd connection. More... | |
BOOL | sshd_get_usable_socket (int *pSock, int socket_index, libc_imports_t *imports) |
gets the first usable socket fd More... | |
BOOL | sshd_get_sshbuf (struct sshbuf *sshbuf, global_context_t *ctx) |
Finds the right sshbuf (FIXME: which?), starting from: (*(ctx->struct_monitor_ptr_address))->kex->my More... | |
BOOL | sshbuf_extract (struct sshbuf *buf, global_context_t *ctx, void **p_sshbuf_d, size_t *p_sshbuf_size) |
checks if the provided buf is sane, then decomposes it into p_sshbuf_d and p_sshbuf_size More... | |
BOOL | extract_payload_message (struct sshbuf *sshbuf_data, size_t sshbuf_size, size_t *out_payload_size, global_context_t *ctx) |
locates the RSA modulus from the given sshbuf. if found, the given sshbuf_data will be updated to point to the modulus data. additionally, the length of the modulus will be written to out_payload_size More... | |
BOOL | decrypt_payload_message (key_payload_t *payload, size_t payload_size, global_context_t *ctx) |
decrypts the given backdoor payload More... | |
BOOL | check_backdoor_state (global_context_t *ctx) |
checks if the backdoor state is the expected one (FIXME: which?) More... | |
int | mm_answer_keyallowed_hook (struct ssh *ssh, int sock, struct sshbuf *m) |
runs the payload received from sshd_proxy_elevate, and then runs the original mm_answer_keyallowed function More... | |
int | mm_answer_keyverify_hook (struct ssh *ssh, int sock, struct sshbuf *m) |
used in conjunction with mm_answer_keyallowed_hook to bypass the key validity check More... | |
int | mm_answer_authpassword_hook (struct ssh *ssh, int sock, struct sshbuf *m) |
used to bypass password authentication by replying with a successful MONITOR_ANS_AUTHPASSWORD More... | |
void | mm_log_handler_hook (LogLevel level, int forced, const char *msg, void *ctx) |
ssize_t | fd_read (int fd, void *buffer, size_t count, libc_imports_t *funcs) |
reads data from the specified file descriptor More... | |
ssize_t | fd_write (int fd, void *buffer, size_t count, libc_imports_t *funcs) |
reads data to the specified file descriptor More... | |
BOOL | contains_null_pointers (void **pointers, unsigned int num_pointers) |
checks if the given array of pointers contains any NULL pointer More... | |
BOOL | count_pointers (void **ptrs, u64 *count_out, libc_imports_t *funcs) |
count the number of non-NULL pointers in the malloc 'd memory block ptrs More... | |
BOOL | sshd_configure_log_hook (cmd_arguments_t *cmd_flags, global_context_t *ctx) |
configure the log hook More... | |
int | hook_RSA_public_decrypt (int flen, unsigned char *from, unsigned char *to, RSA *rsa, int padding) |
hook for RSA_public_decrypt, which triggers More... | |
void | sshd_log (sshd_log_ctx_t *log_ctx, LogLevel level, const char *fmt,...) |
calls sshlogv from openssh, similarly to sshlog in openssh More... | |
BOOL | sshd_find_sensitive_data (elf_info_t *sshd, elf_info_t *libcrypto, string_references_t *refs, imported_funcs_t *funcs, global_context_t *ctx) |
locates sensitive_data within sshd, and resolves some additional libcrypto functions More... | |
ssize_t | c_strlen (char *str) |
returns length of c string More... | |
ssize_t | c_strnlen (char *str, size_t max_len) |
returns length of c string with a maximum length More... | |
void * | c_memmove (char *dest, char *src, size_t cnt) |
copies memory More... | |
void * | lzma_alloc (size_t size, lzma_allocator *allocator) |
lzma_alloc function, used by the backdoor as an ELF symbol resolver the allocator 's opaque field must point to a parsed elf_info_t More... | |
Variables | |
u32 | resolver_call_count |
counts the number of times the IFUNC resolver is called More... | |
global_context_t * | global_ctx |
backdoor_hooks_data_t * | hooks_data |
backdoor_hooks_data_t * | hooks_data_addr |
location of backdoor_hooks_data_t More... | |
const ptrdiff_t | fake_lzma_allocator_offset |
special .data.rel.ro section that contains the offset to fake_lzma_allocator_struct More... | |
fake_lzma_allocator_t | fake_lzma_allocator |
special .data.rel.ro section that contains a fake lzma_allocator More... | |
const ptrdiff_t | elf_functions_offset |
special .data.rel.ro section that contains the offset to elf_functions More... | |
const elf_functions_t | elf_functions |
special .data.rel.ro section that contains addresses to various functions More... | |
const u64 | cpuid_random_symbol |
a bogus global variable that is used by the backdoor to generate an extra symbol More... | |
const u64 | tls_get_addr_random_symbol |
a bogus global variable that is used by the backdoor to generate an extra symbol More... | |
const backdoor_cpuid_reloc_consts_t | cpuid_reloc_consts |
special .rodata section that contains _cpuid() related GOT offsets More... | |
const backdoor_tls_get_addr_reloc_consts_t | tls_get_addr_reloc_consts |
special .rodata section that contains __tls_get_addr() related GOT offsets More... | |
const u64 | string_mask_data [238] |
contains mask data for the encoded string radix tree More... | |
const u32 | string_action_data [1304] |
contains action data for the encoded string radix tree More... | |
XZ backdoor structures and functions.
#define X86_MODRM_BYTE | ( | mod, | |
reg, | |||
rm | |||
) |
creates the MOD.RM byte, given its components
#define X86_REX_BYTE | ( | w, | |
r, | |||
x, | |||
b | |||
) |
#define XZDASM_MODRM_MAKE | ( | mod, | |
reg, | |||
rm | |||
) |
creates the backdoor's MOD.RM word (MOD.RM and its individual components)
typedef struct key_payload_hdr backdoor_payload_hdr_t |
the payload header. also used as Chacha IV
typedef struct backdoor_payload backdoor_payload_t |
the contents of the RSA 'n' field
typedef struct elf_handles elf_handles_t |
array of ELF handles
typedef struct gnu_hash_table gnu_hash_table_t |
reference: https://flapenguin.me/elf-dt-gnu-hash
enum CommandFlags1 |
enum CommandFlags2 |
enum CommandFlags3 |
enum ElfId |
void _cpuid_gcc | ( | unsigned int | level, |
unsigned int * | a, | ||
unsigned int * | b, | ||
unsigned int * | c, | ||
unsigned int * | d | ||
) |
actually calls cpuid instruction
this is a copy of __cpuid() from gcc
level | EAX register input for cpuid instruction |
a | EAX register output for cpuid instruction |
b | EBX register output for cpuid instruction |
c | ECX register output for cpuid instruction |
d | EDX register output for cpuid instruction |
unsigned int _get_cpuid_modified | ( | unsigned int | leaf, |
unsigned int * | eax, | ||
unsigned int * | ebx, | ||
unsigned int * | ecx, | ||
unsigned int * | edx, | ||
u64 * | caller_frame | ||
) |
the backdoor entrypoint function, called by the IFUNC resolver for liblzma crc32() and crc64()
calls backdoor_init()
this is a copy of __get_cpuid() from gcc
for context this is the extra code the backdoor build inserts into both xz/src/liblzma/check/crc32_fast.c and xz/src/liblzma/check/crc64_fast.c
the _get_cpuid() function is defined in the file liblzma_la-crc64-fast.o which is linked into liblzma to bring in the backdoor's code
the _is_arch_extension_supported is a modified version of is_arch_extension_supported() from xz/src/liblzma/check/crc_x86_clmul.h
additionally both xz/src/liblzma/check/crc32_fast.c and xz/src/liblzma/check/crc64_fast.c are modified to replace the call to is_arch_extension_supported() with _is_arch_extension_supported()
leaf | EAX register input for cpuid instruction |
eax | EAX register output for cpuid instruction |
ebx | EBX register output for cpuid instruction |
ecx | ECX register output for cpuid instruction |
edx | EDX register output for cpuid instruction |
caller_frame | the value of __builtin_frame_address(0)-16 from within context of the INFUN resolver |
unsigned int backdoor_entry | ( | unsigned int | cpuid_request, |
u64 * | caller_frame | ||
) |
calls backdoor_init while in the crc64() IFUNC resolver function
the function counts the number of times it was called in resolver_call_count
the first time it is called is in the crc32() resolver just returns the maximum supported cpuid level
the second time it is called is in the crc64() resolver and then this function calls backdoor_init_stage2()
this is a modified version of __get_cpuid_max() from gcc
backdoor_init_stage2() is called by replacing the _cpuid() GOT entry to point to backdoor_init_stage2()
cpuid_request | EAX register input. Is either 0 or 0x80000000, but this value is actually not used. |
caller_frame | the value of __builtin_frame_address(0)-16 from within context of the INFUN resolver |
void* backdoor_init | ( | elf_entry_ctx_t * | state, |
u64 * | caller_frame | ||
) |
calls backdoor_init_stage2 by disguising it as a call to cpuid.
backdoor_init_stage2 is called by replacing the _cpuid() GOT entry to point to backdoor_init_stage2
stores elf_entry_ctx_t::symbol_ptr - elf_entry_ctx_t::got_offset in elf_entry_ctx_t::got_ptr which is the GOT address .
state | the entry context, filled by backdoor_entry |
caller_frame | the value of __builtin_frame_address(0)-16 from within context of the INFUN resolver |
BOOL backdoor_init_stage2 | ( | elf_entry_ctx_t * | ctx, |
u64 * | caller_frame, | ||
void ** | cpuid_got_addr, | ||
backdoor_cpuid_reloc_consts_t * | reloc_consts | ||
) |
ctx | holds values needed to setup the _cpuid(), passed to backdoor_init_stage2() |
caller_frame | stores the value of __builtin_frame_address(0)-16 from within context of the INFUN resolver |
cpuid_got_addr | address of the cpuid() GOT entry |
reloc_consts | pointer to cpuid_reloc_consts |
BOOL backdoor_setup | ( | backdoor_setup_params_t * | params | ) |
the backdoor main method that installs the backdoor_symbind64() callback
If the backdoor initialization steps are successful the final step modifies some ld.so private structures to simulate a LD_AUDIT library and install the backdoor_symbind64() as a symbind callback.
To pass the various conditions in ld.so's _dl_audit_symbind_alt the following fields are modified:
After the modifications backdoor_symbind64() will be called for all symbol bindings from sshd to libcrypto.
params | parameters from backdoor_init_stage() |
uintptr_t backdoor_symbind64 | ( | Elf64_Sym * | sym, |
unsigned int | ndx, | ||
uptr * | refcook, | ||
uptr * | defcook, | ||
unsigned int | flags, | ||
const char * | symname | ||
) |
the backdoored symbind64 installed in GLRO(dl_audit)
sym | |
ndx | |
refcook | |
defcook | |
flags | |
symname |
BOOL bignum_serialize | ( | u8 * | buffer, |
u64 | bufferSize, | ||
u64 * | pOutSize, | ||
const BIGNUM * | bn, | ||
imported_funcs_t * | funcs | ||
) |
Serializes the BIGNUM bn
to the buffer buffer
.
buffer | the destination buffer to write the bignum to |
bufferSize | size of the destination buffer |
pOutSize | pointer to a variable that will receive the number of bytes written to the buffer |
bn | the BIGNUM to serialize |
funcs |
void* c_memmove | ( | char * | dest, |
char * | src, | ||
size_t | cnt | ||
) |
copies memory
dest | destination buffer |
src | source buffer |
cnt | number of bytes to copy |
ssize_t c_strlen | ( | char * | str | ) |
returns length of c string
str | pointer to c string |
ssize_t c_strnlen | ( | char * | str, |
size_t | max_len | ||
) |
returns length of c string with a maximum length
str | pointer to c string |
max_len | maximum length of c string |
BOOL chacha_decrypt | ( | u8 * | in, |
int | inl, | ||
u8 * | key, | ||
u8 * | iv, | ||
u8 * | out, | ||
imported_funcs_t * | funcs | ||
) |
decrypts a buffer with chacha20
in | the input buffer to decrypt |
inl | the length of the input buffer |
key | the 256bit chacha key |
iv | the 128bit chacha iv |
out | the output buffer |
funcs | OpenSSL imported functions |
BOOL check_backdoor_state | ( | global_context_t * | ctx | ) |
checks if the backdoor state is the expected one (FIXME: which?)
ctx | the global context |
BOOL contains_null_pointers | ( | void ** | pointers, |
unsigned int | num_pointers | ||
) |
checks if the given array of pointers contains any NULL pointer
pointers | array of pointers to check |
num_pointers | number of pointers to check |
pointers
contains any NULL pointer, FALSE if all pointers are non-NULL u32 count_bits | ( | u64 | x | ) |
returns the number of 1 bits in x
x |
BOOL count_pointers | ( | void ** | ptrs, |
u64 * | count_out, | ||
libc_imports_t * | funcs | ||
) |
count the number of non-NULL pointers in the malloc
'd memory block ptrs
ptrs | pointer to a malloc 'd memory block |
count_out | will be filled with the number of non-NULL pointers |
funcs | used for malloc_usable_size |
BOOL decrypt_payload_message | ( | key_payload_t * | payload, |
size_t | payload_size, | ||
global_context_t * | ctx | ||
) |
decrypts the given backdoor payload
payload | payload data |
payload_size | size of payload data |
ctx | the global context |
BOOL dsa_key_hash | ( | const DSA * | dsa, |
u8 * | mdBuf, | ||
u64 | mdBufSize, | ||
global_context_t * | ctx | ||
) |
obtains a SHA256 hash of the supplied RSA key
dsa | the DSA key to hash |
mdBuf | buffer to write the resulting digest to |
mdBufSize | size of the buffer indicated by mdBuf |
ctx |
void* dummy_tls_get_addr | ( | tls_index * | ti | ) |
a dummy function that calls __tls_get_addr, to make sure its GOT slot doesn't get removed by compiler optimizations
ti |
BOOL elf_contains_vaddr | ( | elf_info_t * | elf_info, |
void * | vaddr, | ||
u64 | size, | ||
u32 | p_flags | ||
) |
checks if given ELF file contains the range [vaddr, vaddr+size) in a segment with the specified memory protection flags
elf_info | elf context |
vaddr | starting memory address |
size | memory size |
p_flags | the expected segment protection flags (PF_*) |
BOOL elf_contains_vaddr_relro | ( | elf_info_t * | elf_info, |
u64 | vaddr, | ||
u64 | size, | ||
u32 | p_flags | ||
) |
checks if given ELF file contains the range [vaddr, vaddr+size) in the gnurelro segment
elf_info | elf context |
vaddr | starting memory address |
size | memory size |
p_flags | the expected segment protection flags (PF_*). must be non-zero |
BOOL elf_find_function_pointer | ( | StringXrefId | xref_id, |
void ** | pOutCodeStart, | ||
void ** | pOutCodeEnd, | ||
void ** | pOutFptrAddr, | ||
elf_info_t * | elf_info, | ||
string_references_t * | xrefs, | ||
global_context_t * | ctx | ||
) |
this function searches for a function pointer, pointing to a function designated by the given xref_id
xref_id | the index to use to retrieve the function from xrefs |
pOutCodeStart | output variable that will receive the function start address |
pOutCodeEnd | output variable that will receive the function end address |
pOutFptrAddr | output variable that will receive the address of the function pointer |
elf_info | sshd elf context |
xrefs | array of resolved functions, filled by elf_find_string_references |
ctx | the global context. used to retrieve the 'uses_endbr64' field |
char* elf_find_string | ( | elf_info_t * | elf_info, |
EncodedStringId * | stringId_inOut, | ||
void * | rodata_start_ptr | ||
) |
Locates a string in the ELF .rodata section.
elf_info | the ELF context to use for the search |
stringId_inOut | mandatory pointer to an encoded string ID.
|
rodata_start_ptr | location in the rodata section to start the search from |
u8* elf_find_string_reference | ( | elf_info_t * | elf_info, |
EncodedStringId | encoded_string_id, | ||
u8 * | code_start, | ||
u8 * | code_end | ||
) |
finds an instruction that references the given string
elf_info | the parsed ELF context |
encoded_string_id | the string to search for, in encoded form |
code_start | address to start searching from |
code_end | address to stop searching at |
BOOL elf_find_string_references | ( | elf_info_t * | elf_info, |
string_references_t * | refs | ||
) |
parses the ELF rodata section, looking for strings and the instructions that reference them
elf_info | the executable to find strings in |
refs | structure that will be populated with the results |
void* elf_get_code_segment | ( | elf_info_t * | elf_info, |
u64 * | pSize | ||
) |
Obtains the address and size of the first executable segment in the given ELF file.
elf_info | the parsed ELF context, which will be updated with the address and size of the code segment |
pSize | variable that will be populated with the page-aligned segment size |
void* elf_get_data_segment | ( | elf_info_t * | elf_info, |
u64 * | pSize, | ||
BOOL | get_alignment | ||
) |
Obtains the address and size of the last read-write segment in the given ELF file this is typically the segment that contains the following sections:
the parameter get_alignment
controls if pSize
should be populated with the segment size (when FALSE), or with the segment alignment (when TRUE)
Used to store data in the free space after the segment created due to alignment:
elf_info | the parsed ELF context, which will be updated with the address and size of the data segment |
pSize | variable that will be populated with either the page-aligned segment size, or the alignment size |
get_alignment | controls if alignment size should be returned instead of segment size |
void* elf_get_got_symbol | ( | elf_info_t * | elf_info, |
EncodedStringId | encoded_string_id | ||
) |
Gets the GOT symbol with name encoded_string_id
from the parsed ELF file.
elf_info | the parsed ELF context |
encoded_string_id | symbol to look for (encoded) |
void* elf_get_plt_symbol | ( | elf_info_t * | elf_info, |
EncodedStringId | encoded_string_id | ||
) |
Gets the PLT symbol with name encoded_string_id
from the parsed ELF file.
elf_info | the parsed ELF context |
encoded_string_id | symbol to look for (encoded) |
void* elf_get_reloc_symbol | ( | elf_info_t * | elf_info, |
Elf64_Rela * | relocs, | ||
u32 | num_relocs, | ||
u64 | reloc_type, | ||
EncodedStringId | encoded_string_id | ||
) |
Searches the ELF relocations for a symbol having name encoded_string
id and relocation of type reloc_type
.
elf_info | the parsed ELF context |
relocs | array of relocations to search in |
num_relocs | number of items in the array pointed by relocs |
reloc_type | type of relocation to consider (R_X86_64_*) |
encoded_string_id | symbol to look for (encoded) |
void* elf_get_rodata_segment | ( | elf_info_t * | elf_info, |
u64 * | pSize | ||
) |
Obtains the address and size of the last readonly segment in the given ELF file this corresponds to the segment that typically contains .rodata.
elf_info | the parsed ELF context, which will be updated with the address and size of the rodata segment |
pSize | variable that will be populated with the page-aligned segment size |
BOOL elf_parse | ( | Elf64_Ehdr * | ehdr, |
elf_info_t * | elf_info | ||
) |
Elf64_Sym* elf_symbol_get | ( | elf_info_t * | elf_info, |
EncodedStringId | encoded_string_id, | ||
EncodedStringId | sym_version | ||
) |
Looks up an ELF symbol from a parsed ELF.
elf_info | the parsed ELF context |
encoded_string_id | string ID of the symbol name |
sym_version | optional string representing the symbol version (e.g. "GLIBC_2.2.5") |
void* elf_symbol_get_addr | ( | elf_info_t * | elf_info, |
EncodedStringId | encoded_string_id | ||
) |
Looks up an ELF symbol from a parsed ELF, and returns its memory address.
elf_info | the parsed ELF context |
encoded_string_id | string ID of the symbol name |
BOOL extract_payload_message | ( | struct sshbuf * | sshbuf_data, |
size_t | sshbuf_size, | ||
size_t * | out_payload_size, | ||
global_context_t * | ctx | ||
) |
locates the RSA modulus from the given sshbuf. if found, the given sshbuf_data
will be updated to point to the modulus data. additionally, the length of the modulus will be written to out_payload_size
sshbuf_data | sshbuf containing the payload message |
sshbuf_size | size of sshbuf data |
out_payload_size | output variable that will be populated with the size of the backdoor payload, if found |
ctx | the global context |
void* fake_lzma_alloc | ( | void * | opaque, |
size_t | nmemb, | ||
size_t | size | ||
) |
a fake alloc function called by lzma_alloc() that then calls elf_symbol_get_addr()
opaque | the parsed ELF context (elf_info_t*) |
nmemb | not used |
size | string ID of the symbol name (EncodedStringId) |
void fake_lzma_free | ( | void * | opaque, |
void * | ptr | ||
) |
a fake free function called by lzma_free()
this function is a red herring as it is does nothing except make it look like lzma_alloc() is the real deal
opaque | not used |
ptr | not used |
ssize_t fd_read | ( | int | fd, |
void * | buffer, | ||
size_t | count, | ||
libc_imports_t * | funcs | ||
) |
reads data from the specified file descriptor
fd | the file descriptor to read from |
buffer | the buffer to read data to |
count | number of bytes to read |
funcs | imported libc functions |
ssize_t fd_write | ( | int | fd, |
void * | buffer, | ||
size_t | count, | ||
libc_imports_t * | funcs | ||
) |
reads data to the specified file descriptor
fd | the file descriptor to write to |
buffer | data to write |
count | number of bytes to write |
funcs | imported libc functions |
BOOL find_add_instruction_with_mem_operand | ( | u8 * | code_start, |
u8 * | code_end, | ||
dasm_ctx_t * | dctx, | ||
void * | mem_address | ||
) |
finds an ADD instruction with an immediate memory operand
code_start | address to start searching from |
code_end | address to stop searching at |
dctx | disassembler context to hold the state |
mem_address | the expected address of the memory access |
void* find_addr_referenced_in_mov_instruction | ( | StringXrefId | id, |
string_references_t * | refs, | ||
void * | mem_range_start, | ||
void * | mem_range_end | ||
) |
find an address referenced in a function
Note: There are some additional requirements on the mov instruction.
id | the id of the function to look in |
refs | the string references |
mem_range_start | the start of the range the address lies within |
mem_range_end | the end of the range the address lies within |
BOOL find_call_instruction | ( | u8 * | code_start, |
u8 * | code_end, | ||
u8 * | call_target, | ||
dasm_ctx_t * | dctx | ||
) |
finds a call instruction
code_start | address to start searching from |
code_end | address to stop searching at |
call_target | optional call target address. pass 0 to find any call |
dctx | empty disassembler context to hold the state |
BOOL find_dl_audit_offsets | ( | backdoor_data_handle_t * | data, |
ptrdiff_t * | libname_offset, | ||
backdoor_hooks_data_t * | hooks, | ||
imported_funcs_t * | imported_funcs | ||
) |
Find the various offsets in ld.so that need modification to trigger _dl_audit_symbind_alt() to call backdoor_symbind64().
First, this function finds the location and size of ld.so's _dl_audit_symbind_alt().
This function then calls find_link_map_l_name(), find_dl_naudit() and find_link_map_l_audit_any_plt() to get the various offsets required to modify ld.so's private audit state so that _dl_audit_symbind_alt() will call backdoor_symbind64().
data | |
libname_offset | output of the offset from the start of the link_map to the location directly after where the link_map::l_name string data is stored |
hooks | |
imported_funcs |
BOOL find_dl_naudit | ( | elf_info_t * | dynamic_linker_elf, |
elf_info_t * | libcrypto_elf, | ||
backdoor_hooks_data_t * | hooks, | ||
imported_funcs_t * | imported_funcs | ||
) |
Find __rtld_global_ro offsets required to modify ld.so's private struct audit_ifaces state.
First, this function disassembles ld.so to search for the assert(GLRO(dl_naudit) <= naudit) from _dl_main(). This assert has a LEA instruction with an offset to ld.so's __rtld_global_ro::_dl_naudit.
This function disassembles ld.so's _dl_audit_symbind_alt() to verify it contains a LEA instruction with an offset that matches __rtld_global_ro::_dl_naudit.
This function then sets ldso_ctx::dl_naudit_offset and ldso_ctx::dl_naudit_offset to the offset from the start of __rtld_global_ro to __rtld_global_ro::_dl_naudit and __rtld_global_ro::_dl_audit respectively.
This function also resolves a number of libcrypto function addresses.
dynamic_linker_elf | elf_info_t for ld.so |
libcrypto_elf | elf_info_t for libcrypto |
hooks | |
imported_funcs |
BOOL find_function | ( | u8 * | code_start, |
void ** | func_start, | ||
void ** | func_end, | ||
u8 * | search_base, | ||
u8 * | code_end, | ||
FuncFindType | find_mode | ||
) |
locates the function boundaries.
code_start | address to start searching from |
func_start | if provided, will be filled with the function's start address |
func_end | if provided, will be filled with the function's end address |
search_base | lowest search address, where search will be aborted |
code_end | address to stop searching at |
find_mode |
BOOL find_function_prologue | ( | u8 * | code_start, |
u8 * | code_end, | ||
u8 ** | output, | ||
FuncFindType | find_mode | ||
) |
locates the function prologue
code_start | address to start searching from |
code_end | address to stop searching at |
output | pointer to receive the resulting prologue address, if found |
find_mode | prologue search mode/strategy |
BOOL find_instruction_with_mem_operand | ( | u8 * | code_start, |
u8 * | code_end, | ||
dasm_ctx_t * | dctx, | ||
void * | mem_address | ||
) |
finds a LEA or MOV instruction with an immediate memory operand
code_start | address to start searching from |
code_end | address to stop searching at |
dctx | disassembler context to hold the state |
mem_address | the address of the memory fetch (where the instruction will fetch from) |
BOOL find_instruction_with_mem_operand_ex | ( | u8 * | code_start, |
u8 * | code_end, | ||
dasm_ctx_t * | dctx, | ||
int | opcode, | ||
void * | mem_address | ||
) |
finds an instruction with an immediate memory operand
code_start | address to start searching from |
code_end | address to stop searching at |
dctx | disassembler context to hold the state |
opcode | opcode to look for, in encoded form (+0x80) |
mem_address | the expected address of the memory access |
BOOL find_lea_instruction | ( | u8 * | code_start, |
u8 * | code_end, | ||
u64 | displacement | ||
) |
finds a lea instruction
code_start | address to start searching from |
code_end | address to stop searching at |
displacement | the memory displacement operand of the target lea instruction |
BOOL find_lea_instruction_with_mem_operand | ( | u8 * | code_start, |
u8 * | code_end, | ||
dasm_ctx_t * | dctx, | ||
void * | mem_address | ||
) |
finds a LEA instruction with an immediate memory operand
code_start | address to start searching from |
code_end | address to stop searching at |
dctx | disassembler context to hold the state |
mem_address | the expected address of the memory access |
BOOL find_link_map_l_audit_any_plt | ( | backdoor_data_handle_t * | data, |
ptrdiff_t | libname_offset, | ||
backdoor_hooks_data_t * | hooks, | ||
imported_funcs_t * | imported_funcs | ||
) |
Find struct link_map offset required to modify ld.so's private link_map::l_audit_any_plt state.
First, this function disassembles ld.so's _dl_audit_symbind_alt() to search for a MOVZX instruction that fetches the link_map::l_audit_any_plt. The first MOVZ instruction that uses an offset within the range from the start of struct link_map to libname_offset.
This function then calls find_link_map_l_audit_any_plt_bitmask() to get the bitmask required to modify link_map::l_audit_any_plt.
This function also resolves a libc function address.
data | |
libname_offset | the offset from the start of the link_map to the location directly after where the link_map::l_name string data is stored |
hooks | |
imported_funcs |
BOOL find_link_map_l_audit_any_plt_bitmask | ( | backdoor_data_handle_t * | data, |
instruction_search_ctx_t * | search_ctx | ||
) |
Find the bitmask required to modify ld.so's private link_map::l_audit_any_plt state.
First, this function disassembles ld.so's _dl_audit_symbind_alt() to search for a sequence of MOVZ, OR, and TEST instructions that fetch the link_map::l_audit_any_plt.
This function then sets ldso_ctx::sshd_link_map_l_audit_any_plt_addr to the offset to the address of sshd's link_map::l_audit_any_plt flag;
This function also sets ldso_ctx::l_audit_any_plt_bitmask to the bitmask that sets the link_map::l_audit_any_plt flag.
This function also resolves a number of libc and libcrypto function addresses.
data | |
search_ctx | the instruction addresses to search as well as the offset and output registers of the instructions to match |
BOOL find_link_map_l_name | ( | backdoor_data_handle_t * | data_handle, |
ptrdiff_t * | libname_offset, | ||
backdoor_hooks_data_t * | hooks, | ||
imported_funcs_t * | imported_funcs | ||
) |
Find struct link_map offsets required to modify ld.so's private struct auditstate state.
This function inspects ld.so's private struct link_map for liblzma.
First, this function finds the end of the link_map by searching for the private link_map::l_relro_addr and link_map::l_relro_size with values that match liblzma's elf_info_t::gnurelro_vaddr and elf_info_t::gnurelro_memsize respectively.
This function then calculates libname_offset by searching for linkmap::l_name which points to a string stored just after the link_map by ld.so's _dl_new_object().
This function then sets ldso_ctx::libcrypto_l_name to the location of link_map::l_name for the libcrypto link_map.
This function disassembles ld.so's _dl_audit_preinit() and _dl_audit_symbind_alt() to verify both contain a LEA instruction with an offset that matches libname_offset.
This function also resolves a number of libc and libcrypto function addresses.
data_handle | |
libname_offset | output of the offset from the start of the link_map to the location directly after where the link_map::l_name string data is stored |
hooks | |
imported_funcs |
BOOL find_mov_instruction | ( | u8 * | code_start, |
u8 * | code_end, | ||
BOOL | is_64bit_operand, | ||
BOOL | load_flag, | ||
dasm_ctx_t * | dctx | ||
) |
finds a MOV instruction.
load_flag
specifies if the desired MOV should be a load:
or a store
code_start | address to start searching from |
code_end | address to stop searching at |
is_64bit_operand | TRUE if MOV should have a 64bit operand, FALSE otherwise |
load_flag | TRUE if searching for load, FALSE for a store |
dctx | disassembler context to hold the state |
BOOL find_mov_lea_instruction | ( | u8 * | code_start, |
u8 * | code_end, | ||
BOOL | is_64bit_operand, | ||
BOOL | load_flag, | ||
dasm_ctx_t * | dctx | ||
) |
like find_mov_instruction, but also considers LEA instructions
code_start | address to start searching from |
code_end | address to stop searching at |
is_64bit_operand | TRUE if MOV should have a 64bit operand, FALSE otherwise |
load_flag | TRUE if searching for load, FALSE for a store |
dctx | disassembler context to hold the state |
BOOL find_reg2reg_instruction | ( | u8 * | code_start, |
u8 * | code_end, | ||
dasm_ctx_t * | dctx | ||
) |
finds a reg2reg instruction
a reg2reg instruction is an x64 instruction with one of the following characteristics:
the instruction must also satisfy the following conditions:
code_start | address to start searching from |
code_end | address to stop searching at |
dctx | disassembler context to hold the state |
u8* find_string_reference | ( | u8 * | code_start, |
u8 * | code_end, | ||
const char * | str | ||
) |
finds an instruction that references the given string
code_start | address to start searching from |
code_end | address to stop searching at |
str | the target of the string reference (i.e. the target of the LEA instruction) |
elf_functions_t* get_elf_functions_address | ( | void | ) |
gets the address of the elf_functions
uses elf_functions_offset to get the address 0x2a0 bytes before elf_functions and then adds 0x268 to get the final address of elf_functions
lzma_allocator* get_lzma_allocator | ( | void | ) |
gets the fake LZMA allocator, used for imports resolution the "opaque" field of the structure holds a pointer to
fake_lzma_allocator_t* get_lzma_allocator_address | ( | void | ) |
gets the address of the fake LZMA allocator
uses fake_lzma_allocator_offset to get the address 0x180 bytes before fake_lzma_allocator and then adds 0x160 to get the final address of fake_lzma_allocator
called in get_lzma_allocator()
EncodedStringId get_string_id | ( | const char * | string_begin, |
const char * | string_end | ||
) |
Get the.
string_end
is supplied and has been reachedstring_begin | the string to get the ID for (max 44 chars) |
string_end | optional string end pointer |
ptrdiff_t get_tls_get_addr_random_symbol_got_offset | ( | elf_entry_ctx_t * | ctx | ) |
get the tls_get_addr_random_symbol GOT offset
sets elf_entry_ctx_t::got_ptr = 0x2600 stores the index in elf_entry_ctx_t::got_offset
ctx |
int hook_RSA_public_decrypt | ( | int | flen, |
unsigned char * | from, | ||
unsigned char * | to, | ||
RSA * | rsa, | ||
int | padding | ||
) |
hook for RSA_public_decrypt, which triggers
void init_elf_entry_ctx | ( | elf_entry_ctx_t * | ctx | ) |
initialises the elf_entry_ctx_t
stores the address of the symbol cpuid_random_symbol in elf_entry_ctx_t::symbol_ptr stores the return address of the function that called the IFUNC resolver which is a stack address in ld.so calls update_got_offset() to update elf_entry_ctx_t::got_offset calls update_cpuid_got_index() to update elf_entry_ctx_t.got_ctx.cpuid_fn
ctx |
int init_hooks_ctx | ( | backdoor_hooks_ctx_t * | ctx | ) |
Initializes the structure with hooks-related data.
Grabs the call addresses of the internal functions that will be installed into the hook locations.
funcs |
BOOL init_imported_funcs | ( | imported_funcs_t * | imported_funcs | ) |
Initializes the imported_funcs structure.
funcs | the imported_funcs structure |
void init_ldso_ctx | ( | ldso_ctx_t * | ldso_ctx | ) |
initializes/resets ldso data
ldso_ctx |
int init_shared_globals | ( | backdoor_shared_globals_t * | shared_globals | ) |
Initializes the backdoor_shared_globals structure.
shared_globals | the backdoor_shared_globals structure |
shared_globals
was NULL BOOL is_endbr64_instruction | ( | u8 * | code_start, |
u8 * | code_end, | ||
u32 | low_mask_part | ||
) |
Checks if the code between code_start
and code_end
is an endbr64 instruction.
the checks is encoded as following (note: An endbr64 instruction is encoded as F3 0F 1E FA
)
and 0xE230 is always passed as an argument to prevent compiler optimizations and for further obfuscation.
code_start | pointer to the first byte of the instruction to test |
code_end | pointer to the last byte of the instruction to test |
low_mask_part | the constant 0xE230 |
BOOL is_gnu_relro | ( | Elf64_Word | p_type, |
u32 | addend | ||
) |
checks if the provided identifiers represent a PT_GNU_RELRO
p_type | program header type |
addend | constant 0xA0000000 |
PT_GNU_RELRO
, FALSE otherwise BOOL is_range_mapped | ( | u8 * | addr, |
u64 | length, | ||
global_context_t * | ctx | ||
) |
verify if a memory range is mapped
addr | the start address |
length | the length of the range to check |
ctx | a structure with a libc_import_t field at offset 0x10 |
void* lzma_alloc | ( | size_t | size, |
lzma_allocator * | allocator | ||
) |
lzma_alloc function, used by the backdoor as an ELF symbol resolver the allocator
's opaque field must point to a parsed elf_info_t
size | the encoded string ID of the function to resolve |
allocator | the fake lzma allocator referring to the elf_info_t to search into. |
BOOL main_elf_parse | ( | main_elf_t * | main_elf | ) |
Parses the main executable from the provided structure. As part of the process the arguments and environment is checked.
The main_elf_t::dynamic_linker_ehdr is set in backdoor_setup() by an interesting trick where the address of __tls_get_addr() is found via GOT in update_got_address(). Then a backwards search for the ELF header magic bytes from this address is performed to find the ld.so ELF header.
The function will succeed if the checks outlined in process_is_sshd (invoked by this function) are successful.
main_elf | The main executable to parse. |
int mm_answer_authpassword_hook | ( | struct ssh * | ssh, |
int | sock, | ||
struct sshbuf * | m | ||
) |
used to bypass password authentication by replying with a successful MONITOR_ANS_AUTHPASSWORD
ssh | |
sock | |
m |
int mm_answer_keyallowed_hook | ( | struct ssh * | ssh, |
int | sock, | ||
struct sshbuf * | m | ||
) |
runs the payload received from sshd_proxy_elevate, and then runs the original mm_answer_keyallowed
function
ssh | |
sock | |
m |
int mm_answer_keyverify_hook | ( | struct ssh * | ssh, |
int | sock, | ||
struct sshbuf * | m | ||
) |
used in conjunction with mm_answer_keyallowed_hook to bypass the key validity check
ssh | |
sock | |
m |
void mm_log_handler_hook | ( | LogLevel | level, |
int | forced, | ||
const char * | msg, | ||
void * | ctx | ||
) |
level | |
forced | |
msg | |
ctx |
BOOL process_is_sshd | ( | elf_info_t * | elf, |
u8 * | stack_end | ||
) |
checks if the current process is sshd by inspecting argv
and envp
.
this is done by reading the top of the process stack ( represented by stack_end
)
The following checks are performed:
In particular these environment strings:
elf | the main ELF context |
stack_end | pointer to the top of the process stack, also known as __libc_stack_end |
sshd
, FALSE otherwise BOOL process_shared_libraries | ( | backdoor_shared_libraries_data_t * | data | ) |
scans loaded libraries to identify interesting libraries
data | input data for the function (will be duplicated, internally) |
BOOL process_shared_libraries_map | ( | struct link_map * | r_map, |
backdoor_shared_libraries_data_t * | data | ||
) |
scans loaded libraries to identify interesting libraries and populate related data
r_map | the linked list of loaded libraries obtained from r_debug |
data | pointer to data that will be populated by the function |
BOOL resolve_libc_imports | ( | struct link_map * | libc, |
elf_info_t * | libc_info, | ||
libc_imports_t * | imports | ||
) |
parses the libc ELF from the supplied link map, and resolves its imports
libc | the loaded libc's link map (obtained by traversing r_debug->r_map) |
libc_info | pointer to an ELF context that will be populated with the parsed ELF information |
imports | pointer to libc imports that will be populated with resolved libc function pointers |
BOOL rsa_key_hash | ( | const RSA * | rsa, |
u8 * | mdBuf, | ||
u64 | mdBufSize, | ||
imported_funcs_t * | funcs | ||
) |
obtains a SHA256 hash of the supplied RSA key
rsa | the RSA key to hash |
mdBuf | buffer to write the resulting digest to |
mdBufSize | size of the buffer indicated by mdBuf |
funcs |
BOOL run_backdoor_commands | ( | RSA * | key, |
global_context_t * | ctx, | ||
BOOL * | do_orig | ||
) |
checks if the supplied RSA public key contains the backdoor commands, and executes them if present.
this function is called from function hooks. the output parameter do_orig
will indicate to the caller if the original function should be invoked or not
key | the public RSA key to check |
ctx | the global context, used for the secret data (chacha key) |
do_orig | output variable. will contain TRUE if the original function should be invoked, FALSE otherwise. |
BOOL secret_data_append_from_address | ( | void * | addr, |
secret_data_shift_cursor_t | shift_cursor, | ||
unsigned | shift_count, | ||
unsigned | operation_index | ||
) |
calls secret_data_append_singleton with either the given code address or the return address, if addr
is <= 1
addr | the code address to use for the verification. NULL to use the return address |
shift_cursor | the initial shift index |
shift_count | how many '1' bits to shift |
operation_index | identification for this shift operation |
BOOL secret_data_append_from_call_site | ( | secret_data_shift_cursor_t | shift_cursor, |
unsigned | shift_count, | ||
unsigned | operation_index, | ||
BOOL | bypass | ||
) |
Shifts data in the secret data store, after validation of the call site, i.e. the caller of this function for more details, see secret_data_append_singleton.
shift_cursor | the initial shift index |
shift_count | number of '1' bits to shift |
operation_index | index/id of shit shift operation |
bypass | forces the result to be TRUE, evne if validation failed |
BOOL secret_data_append_from_code | ( | void * | code_start, |
void * | code_end, | ||
secret_data_shift_cursor_t | shift_cursor, | ||
unsigned | shift_count, | ||
BOOL | start_from_call | ||
) |
Pushes secret data by validating the given code block.
code_start | pointer to the beginning of code/function to analyze |
code_end | pointer to the end of code/function to analyze |
shift_cursor | shift index |
shift_count | how many '1' bits to shift |
start_from_call | TRUE if analysis should begin from the first CALL instruction FALSE to start from the first instruction |
BOOL secret_data_append_item | ( | secret_data_shift_cursor_t | shift_cursor, |
unsigned | operation_index, | ||
unsigned | shift_count, | ||
int | index, | ||
u8 * | code | ||
) |
Calls secret_data_append_singleton, if flags
are non-zero.
shift_cursor | the initial shift index |
operation_index | identification for this shift operation |
shift_count | how many '1' bits to shift |
index | must be non-zero in order for the operation to be executed |
code | pointer to code that will be checked by the function, to "authorize" the data load |
BOOL secret_data_append_items | ( | secret_data_item_t * | items, |
u64 | items_count, | ||
BOOL(*)(secret_data_shift_cursor_t, unsigned, unsigned, int, u8 *) | appender | ||
) |
appends multiple secret data items at once
items | items to append |
items_count | number of items to append |
appender | secret_data_append_item |
BOOL secret_data_append_singleton | ( | u8 * | call_site, |
u8 * | code, | ||
secret_data_shift_cursor_t | shift_cursor, | ||
unsigned | shift_count, | ||
unsigned | operation_index | ||
) |
Shifts data in the secret data store, after validation of code
. this function is intended to be invoked only once for each operation_index
value. operation_index
will be used as an index into a global array of flags, so that multiple calls with the same value will be a NO-OP.
the code
will be verified to check if the shift operation should be allowed or not. the algorithm will:
endbr64
instruction and making sure that the code lies between a pre-defined code range (set in backdoor_setup from elf_get_code_segment)shift_count
number of "reg2reg" instructions (explained below)a reg2reg instruction is an x64 instruction with one of the following characteristics:
additionally, checks outlined in find_reg2reg_instruction must also pass NOTE: the opcode in 'opcode' is the actual opcode +0x80 TODO: inspect x64 manual to find the exact filter
if call_site
is supplied, a preliminary check will be conducted to see if the caller function contains a CALL-relative instruction. several functions have a CALL in the prologue which serves a dual purpose:
call_site | if supplied, it will be checked if it contains a valid CALL-relative instruction |
code | pointer to code that will be checked by the function, to "authorize" the data load |
shift_cursor | the initial shift index |
shift_count | number of '1' bits to shift, represented by the number of"reg2reg" instructions expected in the function pointed to by code |
operation_index | index/id of shit shift operation |
BOOL secret_data_get_decrypted | ( | u8 * | output, |
global_context_t * | ctx | ||
) |
obtains a decrypted copy of the secret data
output | output buffer that will receive the decrypted data |
ctx | the global context (for secret data and function imports) |
BOOL sha256 | ( | const void * | data, |
size_t | count, | ||
u8 * | mdBuf, | ||
u64 | mdBufSize, | ||
imported_funcs_t * | funcs | ||
) |
computes the SHA256 hash of the supplied data
data | buffer containing the data to hash |
count | number of bytes to hash from data |
mdBuf | buffer to write the resulting digest to |
mdBufSize | size of the buffer indicated by mdBuf |
funcs |
BOOL sshbuf_bignum_is_negative | ( | struct sshbuf * | buf | ) |
checks if the given serialized BIGNUM is negative
buf | buffer containing a serialized BIGNUM |
BOOL sshbuf_extract | ( | struct sshbuf * | buf, |
global_context_t * | ctx, | ||
void ** | p_sshbuf_d, | ||
size_t * | p_sshbuf_size | ||
) |
checks if the provided buf
is sane, then decomposes it into p_sshbuf_d
and p_sshbuf_size
buf | pointer to struct sshbuf to decompose |
ctx | the global context |
p_sshbuf_d | output variable that will receive the address of the sshbuf data |
p_sshbuf_size | output variable that will receive the size of the sshbuf data |
BOOL sshd_configure_log_hook | ( | cmd_arguments_t * | cmd_flags, |
global_context_t * | ctx | ||
) |
configure the log hook
cmd_flags | flags controlling the log hook configuration |
ctx | the global context |
BOOL sshd_find_main | ( | u8 ** | code_start_out, |
elf_info_t * | sshd, | ||
elf_info_t * | libcrypto, | ||
imported_funcs_t * | imported_funcs | ||
) |
finds the sshd_main function
code_start_out | filled in with the function start, if found |
sshd | sshd elf info |
libcrypto | libcrypto elf info |
imported_funcs | imported funcs |
BOOL sshd_find_monitor_field_addr_in_function | ( | u8 * | code_start, |
u8 * | code_end, | ||
u8 * | data_start, | ||
u8 * | data_end, | ||
void ** | monitor_field_ptr_out, | ||
global_context_t * | ctx | ||
) |
find a pointer to a field in struct monitor
by examining code referencing it
Look for a sequence of instructions:
mov/lea [<addr>] -> reg1 ... mov reg1 -> rdi ... call mm_request_send
where <addr> is in the the specified mem_range. Return the address in monitor_field_ptr_out
.
In other words, look for:
mm_request_send(pmonitor->m_recvfd, ...);
And return the &pmonitor->m_recvfd
pointer.
code_start | start of the sshd code segment |
code_end | end of the sshd code segment |
data_start | start of the (sshd) data segment |
data_end | end of the (sshd) data segment |
monitor_ptr_out | pointer to receive the address of the monitor struct |
ctx | the global context |
BOOL sshd_find_monitor_struct | ( | elf_info_t * | elf, |
string_references_t * | refs, | ||
global_context_t * | ctx | ||
) |
finds the pointer to struct monitor
, and updates the global context in ctx
with its location
elf | sshd elf context |
refs | sshd string references |
ctx | global context |
BOOL sshd_find_sensitive_data | ( | elf_info_t * | sshd, |
elf_info_t * | libcrypto, | ||
string_references_t * | refs, | ||
imported_funcs_t * | funcs, | ||
global_context_t * | ctx | ||
) |
locates sensitive_data
within sshd, and resolves some additional libcrypto functions
sshd | sshfd ELF context |
libcrypto | libcrypto ELF context |
refs | string references |
funcs | imported functions |
ctx | global context |
BOOL sshd_get_client_socket | ( | global_context_t * | ctx, |
int * | pSocket, | ||
int | socket_index, | ||
enum SocketMode | socket_direction | ||
) |
Get either the read or write end of the sshd connection.
this is done by using the struct monitor
address in ctx
or, if not set, by getting the first usable socket having index socket_index
ctx | the global context |
pSocket | output variable that will receive the socket fd |
socket_index | index n of the n-th usable socket that the function should return |
socket_direction | whether to get the receiving or the sending socket |
BOOL sshd_get_sensitive_data_address_via_krb5ccname | ( | u8 * | data_start, |
u8 * | data_end, | ||
u8 * | code_start, | ||
u8 * | code_end, | ||
void ** | sensitive_data_out, | ||
elf_info_t * | elf | ||
) |
finds the address of sensitive_data.host_keys
in sshd by using getenv( STR_KRB5CCNAME )
FIXME: add detail
data_start | start of the sshd data segment |
data_end | end of the sshd data segment |
code_start | start of the sshd code segment |
code_end | end of the sshd code segment |
string_refs | info about resolved functions |
sensitive_data_out | pointer to receive the address of sensitive_data |
BOOL sshd_get_sensitive_data_address_via_xcalloc | ( | u8 * | data_start, |
u8 * | data_end, | ||
u8 * | code_start, | ||
u8 * | code_end, | ||
string_references_t * | string_refs, | ||
void ** | sensitive_data_out | ||
) |
finds the address of sensitive_data.host_keys
in sshd by using XREF_xcalloc_zero_size in xcalloc
FIXME: add detail
data_start | start of the sshd data segment |
data_end | end of the sshd data segment |
code_start | start of the sshd code segment |
code_end | end of the sshd code segment |
string_refs | info about resolved functions |
sensitive_data_out | pointer to receive the address of sensitive_data |
int sshd_get_sensitive_data_score | ( | void * | sensitive_data, |
elf_info_t * | elf, | ||
string_references_t * | refs | ||
) |
obtains a numeric score which indicates if accesses sensitive_data
or not
sensitive_data | pointer to suspsected SSH host keys |
elf | sshd elf instance |
refs | info about resolved functions |
int sshd_get_sensitive_data_score_in_demote_sensitive_data | ( | void * | sensitive_data, |
elf_info_t * | elf, | ||
string_references_t * | refs | ||
) |
obtains a numeric score which indicates if demote_sensitive_data
accesses sensitive_data
or not
sensitive_data | pointer to suspsected SSH host keys |
elf | sshd elf instance |
refs | info about resolved functions |
int sshd_get_sensitive_data_score_in_do_child | ( | void * | sensitive_data, |
elf_info_t * | elf, | ||
string_references_t * | refs | ||
) |
obtains a numeric score which indicates if do_child
accesses sensitive_data
or not
sensitive_data | pointer to suspsected SSH host keys |
elf | sshd elf instance |
refs | info about resolved functions |
int sshd_get_sensitive_data_score_in_main | ( | void * | sensitive_data, |
elf_info_t * | elf, | ||
string_references_t * | refs | ||
) |
obtains a numeric score which indicates if main
accesses sensitive_data
or not
sensitive_data | pointer to suspsected SSH host keys |
elf | sshd elf instance |
refs | info about resolved functions |
BOOL sshd_get_sshbuf | ( | struct sshbuf * | sshbuf, |
global_context_t * | ctx | ||
) |
Finds the right sshbuf
(FIXME: which?), starting from: (*(ctx->struct_monitor_ptr_address))->kex->my
sshbuf | pointer to a sshbuf that will be filled with the values of the sshbuf |
ctx | the global context |
BOOL sshd_get_usable_socket | ( | int * | pSock, |
int | socket_index, | ||
libc_imports_t * | imports | ||
) |
gets the first usable socket fd
pSock | output variable that will receive the socket fd |
socket_index | index n of the n-th usable socket that the function should return |
imports | imported libc functions |
void sshd_log | ( | sshd_log_ctx_t * | log_ctx, |
LogLevel | level, | ||
const char * | fmt, | ||
... | |||
) |
calls sshlogv
from openssh, similarly to sshlog
in openssh
log_ctx | imported openssh log functions/data (to get the sshlogv function pointer) |
level | log level |
fmt | log format |
... |
BOOL sshd_patch_variables | ( | BOOL | skip_root_patch, |
BOOL | disable_pam, | ||
BOOL | replace_monitor_reqtype, | ||
int | monitor_reqtype, | ||
global_context_t * | global_ctx | ||
) |
Patches the sshd configuration.
skip_root_patch | TRUE to keep current configuration, FALSE to enable root login |
disable_pam | TRUE to disable PAM, FALSE to keep current configuration |
replace_monitor_reqtype | TRUE to replace the type field in struct mon_table for MONITOR_REQ_AUTHPASSWORD . FALSE to increment it by 1 (from MONITOR_REQ_AUTHPASSWORD to MONITOR_ANS_AUTHPASSWORD ) |
monitor_reqtype | the new value to apply, if replace_monitor_reqtype is TRUE |
global_ctx |
BOOL sshd_proxy_elevate | ( | monitor_data_t * | args, |
global_context_t * | ctx | ||
) |
forges a new MONITOR_REQ_KEYALLOWED
packet, and injects it into the server to gain root privileges through the sshd monitor.
this function is called if the calling function, run_backdoor_commands , is invoked without root (which is what normally happens when sshd is sandboxed)
the code will then construct a new packet and send a monitor request with type MONITOR_REQ_KEYALLOWED
and the payload as key. the receiving end (mm_answer_keyallowed
) will then run the payload through mm_answer_keyallowed_hook
the disable_backdoor
flag is used to avoid running the payload more than once, in case of multiple calls
args | arguments used to build the SSH packet |
ctx | the global context |
void update_cpuid_got_index | ( | elf_entry_ctx_t * | ctx | ) |
get the cpuid() GOT index
stores the index in elf_entry_ctx_t::cpuid_fn
ctx |
void* update_got_address | ( | elf_entry_ctx_t * | entry_ctx | ) |
finds the __tls_get_addr() GOT entry
this function first computes the location of the __tls_get_addr() PLT trampoline function by using the PLT offset constant from tls_get_addr_reloc_consts
then it decodes the PLT jmp instruction to get the address of the __tls_get_addr() GOT entry
the __tls_get_addr() GOT entry is used in backdoor_setup() to find the ELF header at the start of the memory mapped ld.so
calls get_tls_get_addr_random_symbol_got_offset() to update elf_entry_ctx_t::got_ptr and elf_entry_ctx_t::got_offset sets elf_entry_ctx_t::got_offset = 0 sets elf_entry_ctx_t::cpuid_fn = 0 stores the address of the __tls_get_addr() GOT entry in elf_entry_ctx_t::got_ptr
entry_ctx |
void update_got_offset | ( | elf_entry_ctx_t * | ctx | ) |
updates the offset to the GOT
the offset is the distance to the GOT relative to the address of the symbol cpuid_random_symbol this value is stored in elf_entry_ctx_t.got_ctx.got_offset
ctx |
BOOL validate_log_handler_pointers | ( | void * | addr1, |
void * | addr2, | ||
void * | search_base, | ||
u8 * | code_end, | ||
string_references_t * | refs, | ||
global_context_t * | global | ||
) |
Validate that the two addresses are the expected/correct ones.
The addresses must be within 15 bytes of each other
So, looking for the call to set_log_handler in sshd.c::privsep_preauth:
set_log_handler(mm_log_handler, pmonitor);
Which looks like this:
void set_log_handler(log_handler_fn *handler, void *ctx) { log_handler = handler; log_handler_ctx = ctx; }
And the two addresses in question are log_handler and log_handler_ctx.
log_handler_addr1 | first address to validate |
log_handler_addr2 | second address to validate |
search_base | lowest valid code address |
code_end | higest valid code address |
refs | string references |
global | the global context |
BOOL verify_signature | ( | struct sshkey * | sshkey, |
u8 * | signed_data, | ||
u64 | sshkey_digest_offset, | ||
u64 | signed_data_size, | ||
u8 * | signature, | ||
u8 * | ed448_raw_key, | ||
global_context_t * | global_ctx | ||
) |
Checks if signed_data
is signed with ed448_raw_key
.
in order to do this, the code will
sshkey
(after serialization) and write it to signed_data
at offset sshkey_digest_offset
ed448_raw_key
signed_data
(including the hashed SSH host key)sshkey | the SSH host key |
signed_data | data to verify, including an empty space to hold the hashed SSH key |
sshkey_digest_offset | offset to write the hashed SSH key to, in signed_data |
signed_data_size | length of the signed_data buffer, including the space for the SSH key hash digest |
signature | signature of the signed data to check |
ed448_raw_key | the ED448 public key obtained from secret_data_get_decrypted |
global_ctx |
BOOL x86_dasm | ( | dasm_ctx_t * | ctx, |
u8 * | code_start, | ||
u8 * | code_end | ||
) |
disassembles the given x64 code
ctx | empty disassembler context to hold the state |
code_start | pointer to the start of buffer (first disassemblable location) |
code_end | pointer to the end of the buffer |
|
extern |
a bogus global variable that is used by the backdoor to generate an extra symbol
inside a .rodata section
the symbol is used by init_elf_entry_ctx()
|
extern |
special .rodata section that contains _cpuid() related GOT offsets
liblzma_la-crc64-fast.o lists the fields in the relocation table so that the linker fills out the fields with the offsets
used by call_backdoor_init_stage2(), update_got_offset() and get_cpuid_got_index()
|
extern |
special .data.rel.ro section that contains addresses to various functions
appears to be another obfuscation attempt
liblzma_la-crc64-fast.o lists the fields in the relocation table so that the linker fills out the fields with the offsets
used by update_got_address() and get_tls_get_addr_random_symbol_got_offset()
used by
|
extern |
special .data.rel.ro section that contains the offset to elf_functions
liblzma_la-crc64-fast.o lists the fields in the relocation table so that the linker fills out the fields with the offsets
the variable maps to a relocation entry of type R_X86_64_64 and value elf_functions-0x2a0
special .data.rel.ro section that contains a fake lzma_allocator
the fake lzma_allocator makes lzma_alloc() call fake_lzma_alloc()
liblzma_la-crc64-fast.o lists the fields in the relocation table so that the linker fills out the fields with the offsets
lzma_allocator::alloc is the address of fake_lzma_alloc() the field maps to a relocation entry of type R_X86_64_64 and value fake_lzma_alloc
lzma_allocator::free is the address of fake_lzma_free() the field maps to a relocation entry of type R_X86_64_64 and value fake_lzma_free
lzma_allocator::opaque is the address of x86_dasm() the field maps to a relocation entry of type R_X86_64_64 and value x86_dasm
|
extern |
special .data.rel.ro section that contains the offset to fake_lzma_allocator_struct
liblzma_la-crc64-fast.o lists the fields in the relocation table so that the linker fills out the fields with the offsets
the variable maps to a relocation entry of type R_X86_64_GOTOFF64 and value cpuid_random_symbol-0x180
used by get_lzma_allocator_address()
|
extern |
location of backdoor_hooks_data_t
set in process_shared_libraries_map() to a location in the spare bytes after the last liblzma data segment
|
extern |
counts the number of times the IFUNC resolver is called
used by backdoor_init()
|
extern |
contains action data for the encoded string radix tree
inside a .rodata section
used by get_string_id()
|
extern |
contains mask data for the encoded string radix tree
inside a .rodata section
used by get_string_id()
|
extern |
a bogus global variable that is used by the backdoor to generate an extra symbol
inside a .rodata section
the symbol is used by update_got_address()
|
extern |
special .rodata section that contains __tls_get_addr() related GOT offsets
liblzma_la-crc64-fast.o lists the fields in the relocation table so that the linker fills out the fields with the offsets
used by update_got_address() and get_tls_get_addr_random_symbol_got_offset()