Skip to content

Commit

Permalink
debug/wrappers: Link wrapper code directly to apkenv
Browse files Browse the repository at this point in the history
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).
  • Loading branch information
thp committed Mar 25, 2014
1 parent 4f050c0 commit 6fc5bde
Show file tree
Hide file tree
Showing 9 changed files with 74 additions and 106 deletions.
55 changes: 31 additions & 24 deletions debug/wrappers.c
Expand Up @@ -30,6 +30,7 @@
#include "wrappers.h"
#include "../compat/hooks.h"
#include "../apkenv.h"
#include "wrappers/wrapper_code.h"

#include <stdio.h>
#include <stdlib.h>
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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);

Expand All @@ -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.
Expand Down Expand Up @@ -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)) ) ||
Expand Down Expand Up @@ -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;
};

Expand Down
8 changes: 8 additions & 0 deletions 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 */
@@ -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
Expand Down Expand Up @@ -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
);
}

@@ -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(
Expand All @@ -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
);
}

@@ -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(
Expand Down Expand Up @@ -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
);
}

42 changes: 11 additions & 31 deletions makefile
Expand Up @@ -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

Expand Down Expand Up @@ -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$@"
Expand All @@ -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}
Expand All @@ -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
Expand Down
1 change: 0 additions & 1 deletion tools/extract_wrapper_code.sh

This file was deleted.

2 changes: 0 additions & 2 deletions tools/to_code_arm.sh

This file was deleted.

23 changes: 0 additions & 23 deletions tools/to_code_thumb.sh

This file was deleted.

0 comments on commit 6fc5bde

Please sign in to comment.