Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Document stuff run before backdoor_setup() #5

Merged
merged 5 commits into from
Apr 10, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 9 additions & 8 deletions xzre.c
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ void xzre_secret_data_test(){}

static void *get_elf_base(const char *path){
char cmdBuf[128];
char template[] = "grep -E 'r--p 00000000.*%s' /proc/%zu/maps | cut -d '-' -f1";
char template[] = "grep -E 'r--p 00000000.*%s' /proc/%d/maps | cut -d '-' -f1";
snprintf(cmdBuf, sizeof(cmdBuf), template, path, getpid());
FILE *hProc = popen(cmdBuf, "r");
memset(cmdBuf, 0x00, sizeof(cmdBuf));
Expand Down Expand Up @@ -200,7 +200,7 @@ void xzre_backdoor_setup(){
.shared = &shared,
.hook_params = &hook_params
};
printf("pid is %zu\n", getpid());
printf("pid is %d\n", getpid());
//asm volatile("jmp .");
if(!backdoor_setup(&para)){
puts("backdoor_setup() FAIL");
Expand Down Expand Up @@ -233,8 +233,8 @@ void main_shared(){
string_item_t *item = &strings.entries[i];
printf(
"----> %s\n"
"str %2d: id=0x%x, start=%p, end=%p, xref=%p (size: 0x%04lx, xref_offset: 0x%04lx\n"
"RVA_start: %p, RVA_end: %p, RVA_xref: %p\n\n",
"str %2d: id=0x%x, start=%p, end=%p, xref=%p (size: 0x%04zx, xref_offset: 0x%04zx\n"
"RVA_start: 0x%tx, RVA_end: 0x%tx, RVA_xref: 0x%tx\n\n",
StringXrefName[i],
i, item->string_id, item->func_start, item->func_end, item->xref,
(item->func_start && item->func_end) ? PTRDIFF(item->func_end, item->func_start) : 0,
Expand All @@ -258,8 +258,9 @@ int main(int argc, char *argv[]){
if(!res) break;
//hexdump(&ctx, sizeof(ctx));
printf(
"[%2d]: opcode: 0x%08x (orig:0x%08X) (l: %2llu) -- "
"modrm: 0x%02x (%d, %d, %d), operand: %lx, mem_disp: %lx, rex.br: %d, f: %02hhx\n", i,
"[%2d]: opcode: 0x%08"PRIx32" (orig:0x%08"PRIX32") (l: %2"PRIu64") -- "
"modrm: 0x%02"PRIx8" (%"PRId8", %"PRId8", %"PRId8"), operand: %"PRIx64", mem_disp: %"PRIx64", rex.br: %d, f: %02"PRIx8"\n",
i,
XZDASM_OPC(ctx.opcode), ctx.opcode,
ctx.instruction_size,
ctx.modrm, ctx.modrm_mod, ctx.modrm_reg, ctx.modrm_rm,
Expand All @@ -270,7 +271,7 @@ int main(int argc, char *argv[]){
ctx.flags);
printf(" --> ");
for(int i=0; i<ctx.instruction_size; i++){
printf("%02hhx ", ctx.instruction[i]);
printf("%02"PRIx8" ", ctx.instruction[i]);
}
printf("\n");
};
Expand Down Expand Up @@ -325,4 +326,4 @@ uint32_t __attribute__((ifunc("resolver"))) lzma_crc32(const uint8_t *buf, size
uint64_t __attribute__((ifunc("resolver"))) lzma_crc64(const uint8_t *buf, size_t size, uint64_t crc);
#endif

#endif
#endif
200 changes: 192 additions & 8 deletions xzre.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include <assert.h>
#include <stddef.h>
#include <stdint.h>
#include <sys/select.h>
#endif

#ifndef XZRE_SLIM
Expand Down Expand Up @@ -49,6 +50,7 @@ typedef struct {
#include <openssl/rsa.h>
#include <elf.h>
#include <link.h>
typedef Elf64_Xword Elf64_Relr;
#endif

#define UPTR(x) ((uptr)(x))
Expand Down Expand Up @@ -307,7 +309,7 @@ typedef struct __attribute__((packed)) {
* @brief holds the offset of the symbol relative to the GOT.
* used to derive the @ref got_ptr
*/
u64 got_offset;
ptrdiff_t got_offset;
/**
* @brief stores the value of __builtin_frame_address(0)-16
*/
Expand Down Expand Up @@ -699,6 +701,7 @@ typedef struct __attribute__((packed)) {
} backdoor_shared_globals_t;

assert_offset(backdoor_shared_globals_t, globals, 0x10);
static_assert(sizeof(backdoor_shared_globals_t) == 0x18);

typedef struct __attribute__((packed)) {
PADDING(0x70);
Expand Down Expand Up @@ -748,10 +751,22 @@ typedef struct __attribute__((packed)) {
unsigned int flags, const char *symname);
pfn_RSA_public_decrypt_t hook_RSA_public_decrypt;
pfn_RSA_get0_key_t hook_RSA_get0_key;
/**
* @brief
* set to addess of symbol .Llzma12_mode_map_part_1
*/
PADDING(sizeof(void *));
PADDING(sizeof(void *));
PADDING(sizeof(void *));
/**
* @brief
* set to addess of symbol .Lfile_info_decode_0
*/
PADDING(sizeof(void *));
/**
* @brief
* set to addess of symbol .Lbt_skip_func_part_0
*/
PADDING(sizeof(void *));
PADDING(sizeof(void *));
} backdoor_hooks_ctx_t;
Expand Down Expand Up @@ -1035,6 +1050,32 @@ assert_offset(key_ctx_t, args, 0x10);
assert_offset(key_ctx_t, payload, 0x15);
static_assert(sizeof(key_ctx_t) == 0x2B8);

typedef struct __attribute__((packed)) {
/**
* @brief offset from the symbol .Lrc_read_destroy to the GOT
*
* the field maps to a relation entry of type R_X86_64_GOTOFF64 and value .Lrc_read_destroy
*/
ptrdiff_t rc_read_destroy_got_offset;
/**
* @brief index in the GOT for _cpuid()
*
* the field maps to a relation entry of type R_X86_64_GOT64 and value _cpuid
*/
u64 cpuid_got_index;
/**
* @brief offset from the symbol backdoor_init_stage2() to the GOT
*
* the field maps to a relation entry of type R_X86_64_GOTOFF64 and value backdoor_init_stage2
*/
ptrdiff_t backdoor_init_stage2_got_offset;
} backdoor_cpuid_reloc_consts_t;

assert_offset(backdoor_cpuid_reloc_consts_t, rc_read_destroy_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);
static_assert(sizeof(backdoor_cpuid_reloc_consts_t) == 0x18);

/**
* @brief disassembles the given x64 code
*
Expand Down Expand Up @@ -1459,8 +1500,81 @@ extern BOOL secret_data_append_from_call_site(
*/
extern BOOL backdoor_setup(backdoor_setup_params_t *params);

extern void backdoor_init(elf_entry_ctx_t *ctx, u64 *caller_frame);
extern BOOL backdoor_init_stage2(elf_entry_ctx_t *ctx);
/**
* @brief calls call_backdoor_init_stage2() 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 call_backdoor_init_stage2()
*
* this is a modified version of __get_cpuid_max() from gcc
*
* @param ext EAX register input. Is either 0 or 0x80000000, but this value is actually not used.
* @param caller_frame the value of __builtin_frame_address(0)-16 from within context of the INFUN resolver
* @return unsigned int the EAX register output. Normally the maximum supported cpuid level.
*/
extern unsigned int backdoor_init(unsigned int ext, u64 *caller_frame);

/**
* @brief calls backdoor_init_stage2()
*
* 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
*
* @param ctx holds values needed to setup the _cpuid(), passed to backdoor_init_stage2()
* @param caller_frame the value of __builtin_frame_address(0)-16 from within context of the INFUN resolver
* @return void * the value elf_entry_ctx_t::got_ptr if the cpuid() GOT entry was NULL, otherwise the return value of backdoor_init_stage2()
*/
extern void *call_backdoor_init_stage2(elf_entry_ctx_t *ctx, u64 *caller_frame);

/**
* @brief initialises the elf_entry_ctx_t
*
* stores the address of the symbol 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 get_got_offset() to update elf_entry_ctx_t::got_offset
* calls get_cpuid_got_index() to update elf_entry_ctx_t::cpuid_fn
*
* @param ctx
* @return ptrdiff_t always 0
*/
extern ptrdiff_t init_elf_entry_ctx(elf_entry_ctx_t *ctx);

/**
* @brief get the offset to the GOT
*
* the offset is relative to the address of the symbol random_symbol
*
* stores the offset in elf_entry_ctx_t::got_offset
*
* @param ctx
* @return ptrdiff_t offset to GOT from the symbol random_symbol
*/
extern ptrdiff_t get_got_offset(elf_entry_ctx_t *ctx);

/**
* @brief get the cpuid() GOT index
*
* stores the index in elf_entry_ctx_t::cpuid_fn
*
* @param ctx
* @return u64 cpuid() GOT index
*/
extern u64 get_cpuid_got_index(elf_entry_ctx_t *ctx);

/**
* @brief
*
* @param ctx holds values needed to setup the _cpuid(), passed to backdoor_init_stage2()
* @param caller_frame stores the value of __builtin_frame_address(0)-16 from within context of the INFUN resolver
* @param cpuid_got_addr address of the cpuid() GOT entry
* @param reloc_consts pointer to backdoor_cpuid_reloc_consts
* @return BOOL the value elf_entry_ctx_t::got_ptr if the cpuid() GOT entry was NULL, otherwise the return value of backdoor_init_stage2()
*/
extern BOOL backdoor_init_stage2(elf_entry_ctx_t *ctx, u64 *caller_frame, void **cpuid_got_addr, backdoor_cpuid_reloc_consts_t* reloc_consts);

/**
* @brief parses the libc ELF from the supplied link map, and resolves its imports
Expand Down Expand Up @@ -1543,16 +1657,64 @@ extern BOOL is_range_mapped(u8* addr, u8 length, global_context_t* ctx);
extern EncodedStringId get_string_id(const char *string_begin, const char *string_end);

/**
* @brief the backdoor entrypoint function, called by the IFUNC resolver
* @brief the backdoor entrypoint function, called by the IFUNC resolver for liblzma crc32() and crc64()
*
* @param cpuid_request
* @return BOOL
* 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
* \code{.c}
* #if defined(CRC32_GENERIC) && defined(CRC64_GENERIC) && defined(CRC_X86_CLMUL) && defined(CRC_USE_IFUNC) && defined(PIC) && (defined(BUILDING_CRC64_CLMUL) || defined(BUILDING_CRC32_CLMUL))
* int _get_cpuid(int, void*, void*, void*, void*, void*);
*
* static inline bool _is_arch_extension_supported(void) {
* int success = 1;
* uint32_t r[4];
* success = _get_cpuid(1, &r[0], &r[1], &r[2], &r[3], ((char*) __builtin_frame_address(0))-16);
* const uint32_t ecx_mask = (1 << 1) | (1 << 9) | (1 << 19);
* return success && (r[2] & ecx_mask) == ecx_mask;
* }
*
* #else
* #define _is_arch_extension_supported() is_arch_extension_supported
* #endif
* \endcode
*
* 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()
*
* @param leaf EAX register input for cpuid instruction
* @param eax EAX register output for cpuid instruction
* @param ebx EBX register output for cpuid instruction
* @param ecx ECX register output for cpuid instruction
* @param edx EDX register output for cpuid instruction
* @param caller_frame the value of __builtin_frame_address(0)-16 from within context of the INFUN resolver
* @return BOOL TRUE if cpuid leaf supported, FALSE otherwise
*/
extern BOOL _get_cpuid(int cpuid_request, void*, void*, void*, void*, void*);
extern unsigned int _get_cpuid(unsigned int leaf, unsigned int *eax, unsigned int *ebx, unsigned int *ecx, unsigned int *edx, u64 *caller_frame);

/**
* @brief actually calls cpuid instruction
*
* this is a copy of __cpuid() from gcc
*
* @param level EAX register input for cpuid instruction
* @param a EAX register output for cpuid instruction
* @param b EBX register output for cpuid instruction
* @param c ECX register output for cpuid instruction
* @param d EDX register output for cpuid instruction
*/
extern void _cpuid(unsigned int level, unsigned int *a, unsigned int *b, unsigned int *c, unsigned int *d);

/**
* @brief Initializes the structure with hooks-related data
*
* Grabs the call addresses of the internal functions that will be installed into the hook locations.
*
* @param funcs
* @return int
*/
Expand Down Expand Up @@ -1583,10 +1745,32 @@ extern uintptr_t backdoor_symbind64(
unsigned int flags,
const char *symname);

/**
* @brief counts the number of times the IFUNC resolver is called
*
* used by backdoor_init()
*
*/
extern u32 resolver_call_count;
extern global_context_t *global_ctx;
extern lzma_allocator *fake_lzma_allocator;
extern backdoor_hooks_data_t **hooks_data_addr;
/**
* @brief a bogus global variable that is used by the backdoor to generate an extra symbol
*
* the symbol is used by init_elf_entry_ctx() and get_got_offset()
*
*/
extern const u64 random_symbol;
/**
* @brief special 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(), get_got_offset() and get_cpuid_got_index()
*
*/
extern backdoor_cpuid_reloc_consts_t backdoor_cpuid_reloc_consts;

#include "util.h"
#endif
#endif
13 changes: 13 additions & 0 deletions xzre.lds.in
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ SECTIONS_BEGIN()
DEFSYM(secret_data_append_singleton, .text.rc_read_inis)
DEFSYM(backdoor_init, .text._get_cpuia)
DEFSYM(backdoor_init_stage2, .text.lzma_validate_chaia)
DEFSYM(init_elf_entry_ctx, .text.read_output_and_waia)
DEFSYM(get_got_offset, .text.parse_delt1)
DEFSYM(get_cpuid_got_index, .text.lzma_stream_decoder_inia)
DEFSYM(backdoor_setup, .text.microlzma_encoder_inia)
DEFSYM(resolve_libc_imports, .text.lzma_index_buffer_encoda)
DEFSYM(process_shared_libraries, .text.lzma_index_stream_flaga)
Expand All @@ -53,6 +56,8 @@ SECTIONS_BEGIN()
DEFSYM(get_string_id, .text.simple_coder_updata)
DEFSYM(init_hook_functions, .text.lzma_delta_decoder_inis)
DEFSYM(_get_cpuid, .text._get_cpuid)
DEFSYM(call_backdoor_init_stage2, .text._get_cpuia)
DEFSYM(_cpuid, .text._cpuid)
DEFSYM(update_got_address, .text.lzma_stream_header_encoda)
DEFSYM(backdoor_symbind64, .text.lz_encoder_prepara)
DEFSYM(hook_RSA_get0_key, .text.lzma_index_inia)
Expand All @@ -69,3 +74,11 @@ SECTIONS_END(.bss)
SECTIONS_BEGIN()
DEFSYM(fake_lzma_allocator, .data.rel.ro.decoders0)
SECTIONS_END(.data.rel.ro)

ljbade marked this conversation as resolved.
Show resolved Hide resolved
/*
TODO map this to backdoor_cpuid_reloc_consts_t:
0000000000000000 l O .rodata.lzma12_mf_mao.0 0000000000000000 .hidden .Llzma_block_buffer_decode.0

TODO map this to random_symbol;
0000000000000000 l O .rodata.lzma_lzma_encode 0000000000000008 .hidden .Lrc_read_destroy
*/