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 -