From 6fc5bde4a67ec935ff99b22466a07b3b091fd6bd Mon Sep 17 00:00:00 2001 From: Thomas Perl Date: Tue, 25 Mar 2014 16:07:38 +0100 Subject: [PATCH] debug/wrappers: Link wrapper code directly to apkenv Instead of compiling the wrappers as separate units, built them into the main binary and use the functions directly as data (with the data fields found by the first occurence of 0xFFFFFFFF, which is not a valid ARM instruction). --- debug/wrappers.c | 55 +++++++++++-------- debug/wrappers/wrapper_code.h | 8 +++ .../{wrapper_ARM.c => wrapper_code_arm.c} | 15 ++--- ...r_GENERIC.c => wrapper_code_generic_arm.c} | 15 ++--- .../{wrapper_THUMB.c => wrapper_code_thumb.c} | 19 +++---- makefile | 42 ++++---------- tools/extract_wrapper_code.sh | 1 - tools/to_code_arm.sh | 2 - tools/to_code_thumb.sh | 23 -------- 9 files changed, 74 insertions(+), 106 deletions(-) create mode 100644 debug/wrappers/wrapper_code.h rename debug/wrappers/{wrapper_ARM.c => wrapper_code_arm.c} (78%) rename debug/wrappers/{wrapper_GENERIC.c => wrapper_code_generic_arm.c} (72%) rename debug/wrappers/{wrapper_THUMB.c => wrapper_code_thumb.c} (75%) delete mode 100755 tools/extract_wrapper_code.sh delete mode 100755 tools/to_code_arm.sh delete mode 100755 tools/to_code_thumb.sh diff --git a/debug/wrappers.c b/debug/wrappers.c index dc2135b..d56d087 100644 --- a/debug/wrappers.c +++ b/debug/wrappers.c @@ -30,6 +30,7 @@ #include "wrappers.h" #include "../compat/hooks.h" #include "../apkenv.h" +#include "wrappers/wrapper_code.h" #include #include @@ -115,14 +116,27 @@ const char *msg_thumb_injection = "called injected THUMB wrapper"; #define IS_T32(hi16) \ (((hi16) & 0xe000) == 0xe000 && ((hi16) & 0x1800)) +static size_t +get_wrapper_code_size(void *wrapper) +{ + // Find first occurence of 0xFFFFFFFF in the code object, + // which is the placeholder for the attached data words + uint32_t *ptr = wrapper; + while (*ptr != 0xFFFFFFFF) { + ptr++; + } + return ((void *)ptr - (void *)wrapper); +} + void *create_wrapper(char *symbol, void *function, int wrapper_type) { - int helper = 0; - int wrapper_size = 0; + size_t wrapper_size = 0; + void *wrapper_code = NULL; void *wrapper_addr = NULL; + int helper = 0; const char *msg = NULL; - + switch(wrapper_type) { case WRAPPER_LATEHOOK: @@ -151,41 +165,31 @@ void *create_wrapper(char *symbol, void *function, int wrapper_type) switch(wrapper_type) { case WRAPPER_LATEHOOK: - wrapper_size = -#include "wrappers/wrapper_GENERIC.size" - * sizeof(uint32_t); + wrapper_code = wrapper_code_generic; msg = msg_latehook; break; case WRAPPER_UNHOOKED: - wrapper_size = -#include "wrappers/wrapper_GENERIC.size" - * sizeof(uint32_t); + wrapper_code = wrapper_code_generic; msg = msg_unhooked; break; case WRAPPER_DYNHOOK: - wrapper_size = -#include "wrappers/wrapper_GENERIC.size" - * sizeof(uint32_t); + wrapper_code = wrapper_code_generic; msg = msg_dynhook; break; case WRAPPER_ARM_INJECTION: - wrapper_size = -#include "wrappers/wrapper_ARM.size" - * sizeof(uint32_t); // 32-Bit + wrapper_code = wrapper_code_arm; msg = msg_arm_injection; break; -#ifndef FREMANTLE case WRAPPER_THUMB_INJECTION: - wrapper_size = -#include "wrappers/wrapper_THUMB.size" - * sizeof(uint16_t); // 16-Bit + wrapper_code = wrapper_code_thumb; msg = msg_thumb_injection; break; -#endif /* FREMANTLE */ default: assert(NULL == "ERROR: invalid wrapper type!\n"); } - + + wrapper_size = get_wrapper_code_size(wrapper_code); + // 4 additional longs for data storage, see below wrapper_size += 4 * sizeof(uint32_t); @@ -204,19 +208,22 @@ void *create_wrapper(char *symbol, void *function, int wrapper_type) // this variable is used to determine how many operations we need to copy from the thumb code int thumb_fifth_nop = 0; + memcpy(wrapper_addr, wrapper_code, wrapper_size); + + // Helper = offset of data fields in wrapper_addr (interpreted as int32_t) + helper = wrapper_size / sizeof(uint32_t) - 4; + switch(wrapper_type) { case WRAPPER_LATEHOOK: case WRAPPER_UNHOOKED: case WRAPPER_DYNHOOK: -#include "wrappers/wrapper_GENERIC.instructions" ((int32_t*)wrapper_addr)[helper++] = (uint32_t)symbol; ((int32_t*)wrapper_addr)[helper++] = (uint32_t)function; ((int32_t*)wrapper_addr)[helper++] = (uint32_t)trace_callback; ((int32_t*)wrapper_addr)[helper++] = (uint32_t)msg; break; case WRAPPER_ARM_INJECTION: -#include "wrappers/wrapper_ARM.instructions" // relocate the first 2 instructions // this is EXPERIMENTAL! it works in many cases because of how // ARM methods are layout in ASM. @@ -244,7 +251,6 @@ void *create_wrapper(char *symbol, void *function, int wrapper_type) function = (void*)((char*)function - 1); // fix wrapper addr (tell the processor this is THUMB code) wrapper_addr = (void*)((char*)wrapper_addr + 1); -#include "wrappers/wrapper_THUMB.instructions" thumb_fifth_nop = IS_T32(*((int16_t*)function + 4)) && ( (!IS_T32(*((int16_t*)function)) && !IS_T32(*((int16_t*)function + 1)) && !IS_T32(*((int16_t*)function + 3))) || (!IS_T32(*((int16_t*)function)) && IS_T32(*((int16_t*)function + 1)) ) || @@ -292,6 +298,7 @@ void *create_wrapper(char *symbol, void *function, int wrapper_type) ((int16_t*)wrapper_addr)[helper++] = ((uint32_t)msg) >> 16; break; default: + assert(0); break; }; diff --git a/debug/wrappers/wrapper_code.h b/debug/wrappers/wrapper_code.h new file mode 100644 index 0000000..54b29fa --- /dev/null +++ b/debug/wrappers/wrapper_code.h @@ -0,0 +1,8 @@ +#ifndef WRAPPER_CODE_H +#define WRAPPER_CODE_H + +void wrapper_code_generic() __attribute__((naked,noinline)); +void wrapper_code_arm() __attribute__((naked,noinline)); +void wrapper_code_thumb() __attribute__((naked,noinline)); + +#endif /* WRAPPER_CODE_H */ diff --git a/debug/wrappers/wrapper_ARM.c b/debug/wrappers/wrapper_code_arm.c similarity index 78% rename from debug/wrappers/wrapper_ARM.c rename to debug/wrappers/wrapper_code_arm.c index df26d14..42da55a 100644 --- a/debug/wrappers/wrapper_ARM.c +++ b/debug/wrappers/wrapper_code_arm.c @@ -1,5 +1,7 @@ -static void dummy_f() __attribute__((naked,noinline)); -static void dummy_f() +#include "wrapper_code.h" + +void +wrapper_code_arm() { asm volatile( // don't use any labels within the code because our *.o to code converter will stop at the first label @@ -29,10 +31,9 @@ static void dummy_f() // necessary and this is easier // dummy instructions, this is where we locate our pointers - "name: mov r0, r0\n" // name of function to call - "fun: mov r0, r0\n" // function to call (actually the pointer to the third instruction) - "tc: mov r0, r0\n" // address of trace_callback - "str: mov r0, #0\n" // the string being printed in trace_callback + "name: .word 0xFFFFFFFF\n" // name of function to call + "fun: .word 0xFFFFFFFF\n" // function to call (actually the pointer to the third instruction) + "tc: .word 0xFFFFFFFF\n" // address of trace_callback + "str: .word 0xFFFFFFFF\n" // the string being printed in trace_callback ); } - diff --git a/debug/wrappers/wrapper_GENERIC.c b/debug/wrappers/wrapper_code_generic_arm.c similarity index 72% rename from debug/wrappers/wrapper_GENERIC.c rename to debug/wrappers/wrapper_code_generic_arm.c index 4a0f510..cf8a44e 100644 --- a/debug/wrappers/wrapper_GENERIC.c +++ b/debug/wrappers/wrapper_code_generic_arm.c @@ -1,5 +1,7 @@ -static void dummy_f() __attribute__((naked,noinline)); -static void dummy_f() +#include "wrapper_code.h" + +void +wrapper_code_generic() { // we can never use r0-r11, neither the stack asm volatile( @@ -21,10 +23,9 @@ static void dummy_f() // necessary and this is easier // dummy instructions, this is where we locate our pointers - "name: mov r0, #0\n" // name of function to call - "fun: mov r0, #0\n" // function to call - "tc: mov r0, #0\n" // address of trace_callback - "str: mov r0, #0\n" // the string being printed in trace_callback + "name: .word 0xFFFFFFFF\n" // name of function to call + "fun: .word 0xFFFFFFFF\n" // function to call + "tc: .word 0xFFFFFFFF\n" // address of trace_callback + "str: .word 0xFFFFFFFF\n" // the string being printed in trace_callback ); } - diff --git a/debug/wrappers/wrapper_THUMB.c b/debug/wrappers/wrapper_code_thumb.c similarity index 75% rename from debug/wrappers/wrapper_THUMB.c rename to debug/wrappers/wrapper_code_thumb.c index 494f011..2529a41 100644 --- a/debug/wrappers/wrapper_THUMB.c +++ b/debug/wrappers/wrapper_code_thumb.c @@ -1,5 +1,7 @@ -static void dummy_f() __attribute__((naked,noinline)); -static void dummy_f() +#include "wrapper_code.h" + +void +wrapper_code_thumb() { // the thumb wrapper does not work yet asm volatile( @@ -35,14 +37,9 @@ static void dummy_f() // necessary and this is easier // dummy instructions, this is where we locate our pointers - "name: mov r0, r0\n" // name of function to call - "mov r0, r0\n" - "fun: mov r0, r0\n" // function to call (actually the pointer to the third instruction) - "mov r0, r0\n" - "tc: mov r0, r0\n" // address of print_fun_name - "mov r0, r0\n" - "str: mov r0, r0\n" // the string being printed in trace_callback - "mov r0, r0\n" + "name: .word 0xFFFFFFFF\n" // name of function to call + "fun: .word 0xFFFFFFFF\n" // function to call (actually the pointer to the third instruction) + "tc: .word 0xFFFFFFFF\n" // address of print_fun_name + "str: .word 0xFFFFFFFF\n" // the string being printed in trace_callback ); } - diff --git a/makefile b/makefile index 7d91d24..9c7a268 100644 --- a/makefile +++ b/makefile @@ -21,11 +21,7 @@ IMAGELIB_SOURCES=$(wildcard imagelib/*.c) DEBUG_SOURCES=$(wildcard debug/*.c) # debug wrappers -WRAPPER_INJECT_ARM_SOURCE=debug/wrappers/wrapper_ARM.c -WRAPPER_INJECT_THUMB_SOURCE=debug/wrappers/wrapper_THUMB.c -WRAPPER_INJECT_GENERIC_SOURCE=debug/wrappers/wrapper_GENERIC.c -WRAPPER_INJECT_SOURCES=$(WRAPPER_INJECT_ARM_SOURCE) $(WRAPPER_INJECT_THUMB_SOURCE) $(WRAPPER_INJECT_GENERIC_SOURCE) -WRAPPER_INJECT_TARGETS=$(patsubst %.c,%.instructions,$(WRAPPER_INJECT_SOURCES)) +WRAPPER_SOURCES=$(wildcard debug/wrappers/*.c) TARGET = apkenv @@ -88,7 +84,15 @@ else CFLAGS += -O2 -DLINKER_DEBUG=0 endif -all: $(WRAPPER_INJECT_TARGETS) $(TARGET) $(MODULES) +all: $(TARGET) $(MODULES) + +debug/wrappers/%_thumb.o: debug/wrappers/%_thumb.c + @echo -e "\tCC (TH)\t$@" + @$(CC) -mthumb -O0 -c -o $@ $< + +debug/wrappers/%_arm.o: debug/wrappers/%_arm.c + @echo -e "\tCC\t$@" + @$(CC) -marm -O0 -c -o $@ $< %.o: %.c @echo -e "\tCC\t$@" @@ -106,30 +110,6 @@ strip: @echo -e "\tSTRIP" @strip $(TARGET) $(MODULES) -$(patsubst %.c,%.instructions,$(WRAPPER_INJECT_ARM_SOURCE)): $(WRAPPER_INJECT_ARM_SOURCE) - @echo -e "\tCC_W\t$<" - @$(CC) -marm -Wno-unused-function -O0 -c -o $(patsubst %.c,%.o,$<) $< - @echo -e "\tDEC\t$(patsubst %.c,%.o,$<)" - @$(OBJDUMP) -d $(patsubst %.c,%.o,$<) | ./tools/extract_wrapper_code.sh | ./tools/to_code_arm.sh > $(patsubst %.c,%.instructions,$<) - @echo -e "\tSIZE\t$(patsubst %.c,%.instructions,$<)" - @wc -l $(patsubst %.c,%.instructions,$<) | awk '{print $$1}' > $(patsubst %.c,%.size,$<) - -$(patsubst %.c,%.instructions,$(WRAPPER_INJECT_THUMB_SOURCE)): $(WRAPPER_INJECT_THUMB_SOURCE) - @echo -e "\tCC_W\t$<" - @$(CC) -mthumb -Wno-unused-function -O0 -c -o $(patsubst %.c,%.o,$<) $< - @echo -e "\tDEC\t$(patsubst %.c,%.o,$<)" - @$(OBJDUMP) -d $(patsubst %.c,%.o,$<) | ./tools/extract_wrapper_code.sh | ./tools/to_code_thumb.sh > $(patsubst %.c,%.instructions,$<) - @echo -e "\tSIZE\t$(patsubst %.c,%.instructions,$<)" - @wc -l $(patsubst %.c,%.instructions,$<) | awk '{print $$1}' > $(patsubst %.c,%.size,$<) - -$(patsubst %.c,%.instructions,$(WRAPPER_INJECT_GENERIC_SOURCE)): $(WRAPPER_INJECT_GENERIC_SOURCE) - @echo -e "\tCC_W\t$<" - @$(CC) -marm -Wno-unused-function -O0 -c -o $(patsubst %.c,%.o,$<) $< - @echo -e "\tDEC\t$(patsubst %.c,%.o,$<)" - @$(OBJDUMP) -d $(patsubst %.c,%.o,$<) | ./tools/extract_wrapper_code.sh | ./tools/to_code_arm.sh > $(patsubst %.c,%.instructions,$<) - @echo -e "\tSIZE\t$(patsubst %.c,%.instructions,$<)" - @wc -l $(patsubst %.c,%.instructions,$<) | awk '{print $$1}' > $(patsubst %.c,%.size,$<) - install: $(TARGET) $(MODULES) @echo -e "\tMKDIR" @mkdir -p $(DESTDIR)$(PREFIX)/{modules,bionic} @@ -154,7 +134,7 @@ endif clean: @echo -e "\tCLEAN" - @rm -rf $(TARGET) $(OBJS) $(MODULES) $(WRAPPER_INJECT_TARGETS) $(patsubst %.c,%.o, $(WRAPPER_INJECT_SOURCES)) $(patsubst %.c,%.size, $(WRAPPER_INJECT_SOURCES)) + @rm -rf $(TARGET) $(OBJS) $(MODULES) .DEFAULT: all .PHONY: strip install clean diff --git a/tools/extract_wrapper_code.sh b/tools/extract_wrapper_code.sh deleted file mode 100755 index 9b14411..0000000 --- a/tools/extract_wrapper_code.sh +++ /dev/null @@ -1 +0,0 @@ -awk '/ 0:/ {do_print=1} NF==0 {do_print=0} do_print==1 {print}' diff --git a/tools/to_code_arm.sh b/tools/to_code_arm.sh deleted file mode 100755 index bd10a6a..0000000 --- a/tools/to_code_arm.sh +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/sh -awk '{ print "((int32_t*)wrapper_addr)[helper++] = 0x"$2"; // "$3" "$4" "$5" "$6" "$7" "$8" "$9" "$10" "$11}' - diff --git a/tools/to_code_thumb.sh b/tools/to_code_thumb.sh deleted file mode 100755 index 9619cd4..0000000 --- a/tools/to_code_thumb.sh +++ /dev/null @@ -1,23 +0,0 @@ -#!/bin/sh - -while read line -do - opstart=2; - opend=2; - line=( $line ); - if [[ "${line[2]}" =~ "^[0-9a-f]+$" ]]; then - opend=3; - fi - echo -ne "((int16_t*)wrapper_addr)[helper++] = 0x"${line[1]}";" - echo -ne " // " - for i in `seq $opend ${#line[@]}` - do - echo -ne "${line[$i]} " - done - if [[ $opend -eq 2 ]]; then - echo -ne "\n" - else - echo -ne "\n((int16_t*)wrapper_addr)[helper++] = 0x"${line[2]}"; // above command continued\n" - fi -done -