diff --git a/edxp-core/jni/main/Android.mk b/edxp-core/jni/main/Android.mk index 55f0035a7..46777363c 100644 --- a/edxp-core/jni/main/Android.mk +++ b/edxp-core/jni/main/Android.mk @@ -21,6 +21,10 @@ LOCAL_SRC_FILES:= \ yahfa/trampoline.c \ java_hook/java_hook.cpp \ inject/framework_hook.cpp \ - inject/config_manager.cpp + inject/config_manager.cpp \ + Substrate/SubstrateDebug.cpp \ + Substrate/SubstrateHook.cpp \ + Substrate/SubstratePosixMemory.cpp \ + Substrate/hde64.c \ include $(BUILD_SHARED_LIBRARY) \ No newline at end of file diff --git a/edxp-core/jni/main/Substrate/Buffer.hpp b/edxp-core/jni/main/Substrate/Buffer.hpp new file mode 100644 index 000000000..34d9df32e --- /dev/null +++ b/edxp-core/jni/main/Substrate/Buffer.hpp @@ -0,0 +1,38 @@ +/* Cydia Substrate - Powerful Code Insertion Platform + * Copyright (C) 2008-2011 Jay Freeman (saurik) +*/ + +/* GNU Lesser General Public License, Version 3 {{{ */ +/* + * Substrate is free software: you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * Substrate is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Substrate. If not, see . +**/ +/* }}} */ + +#ifndef SUBSTRATE_BUFFER_HPP +#define SUBSTRATE_BUFFER_HPP + +#include + +template +_disused static _finline void MSWrite(uint8_t *&buffer, Type_ value) { + *reinterpret_cast(buffer) = value; + buffer += sizeof(Type_); +} + +_disused static _finline void MSWrite(uint8_t *&buffer, uint8_t *data, size_t size) { + memcpy(buffer, data, size); + buffer += size; +} + +#endif//SUBSTRATE_BUFFER_HPP diff --git a/edxp-core/jni/main/Substrate/CydiaSubstrate.h b/edxp-core/jni/main/Substrate/CydiaSubstrate.h new file mode 100644 index 000000000..bb806aa9f --- /dev/null +++ b/edxp-core/jni/main/Substrate/CydiaSubstrate.h @@ -0,0 +1,152 @@ +/* Cydia Substrate - Powerful Code Insertion Platform + * Copyright (C) 2008-2011 Jay Freeman (saurik) +*/ + +/* GNU Lesser General Public License, Version 3 {{{ */ +/* + * Substrate is free software: you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * Substrate is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Substrate. If not, see . +**/ +/* }}} */ + +#ifndef SUBSTRATE_H_ +#define SUBSTRATE_H_ + +#ifdef __APPLE__ +#ifdef __cplusplus +extern "C" { +#endif +#include +#ifdef __cplusplus +} +#endif + +#include +#include +#endif + +#include +#include + +#define _finline \ + inline __attribute__((__always_inline__)) +#define _disused \ + __attribute__((__unused__)) + +#define _extern \ + extern "C" __attribute__((__visibility__("default"))) + +#ifdef __cplusplus +#define _default(value) = value +#else +#define _default(value) +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +bool MSHookProcess(pid_t pid, const char *library); + +typedef const void *MSImageRef; + +MSImageRef MSGetImageByName(const char *file); +void *MSFindSymbol(MSImageRef image, const char *name); + +void MSHookFunction(void *symbol, void *replace, void **result); + +#ifdef __APPLE__ +#ifdef __arm__ +__attribute__((__deprecated__)) +IMP MSHookMessage(Class _class, SEL sel, IMP imp, const char *prefix _default(NULL)); +#endif +void MSHookMessageEx(Class _class, SEL sel, IMP imp, IMP *result); +#endif + +#ifdef SubstrateInternal +typedef void *SubstrateAllocatorRef; +typedef struct __SubstrateProcess *SubstrateProcessRef; +typedef struct __SubstrateMemory *SubstrateMemoryRef; + +SubstrateProcessRef SubstrateProcessCreate(SubstrateAllocatorRef allocator, pid_t pid); +void SubstrateProcessRelease(SubstrateProcessRef process); + +SubstrateMemoryRef SubstrateMemoryCreate(SubstrateAllocatorRef allocator, SubstrateProcessRef process, void *data, size_t size); +void SubstrateMemoryRelease(SubstrateMemoryRef memory); +#endif + +#ifdef __cplusplus +} +#endif + +#ifdef __cplusplus + +#ifdef SubstrateInternal +struct SubstrateHookMemory { + SubstrateMemoryRef handle_; + + SubstrateHookMemory(SubstrateProcessRef process, void *data, size_t size) : + handle_(SubstrateMemoryCreate(NULL, NULL, data, size)) + { + } + + ~SubstrateHookMemory() { + if (handle_ != NULL) + SubstrateMemoryRelease(handle_); + } +}; +#endif + + +template +static inline void MSHookFunction(Type_ *symbol, Type_ *replace, Type_ **result) { + MSHookFunction( + reinterpret_cast(symbol), + reinterpret_cast(replace), + reinterpret_cast(result) + ); +} + +template +static inline void MSHookFunction(Type_ *symbol, Type_ *replace) { + return MSHookFunction(symbol, replace, reinterpret_cast(NULL)); +} + +template +static inline void MSHookSymbol(Type_ *&value, const char *name, MSImageRef image = NULL) { + value = reinterpret_cast(MSFindSymbol(image, name)); +} + +template +static inline void MSHookFunction(const char *name, Type_ *replace, Type_ **result = NULL) { + Type_ *symbol; + MSHookSymbol(symbol, name); + return MSHookFunction(symbol, replace, result); +} + +#endif + +#define MSHook(type, name, args...) \ + _disused static type (*_ ## name)(args); \ + static type $ ## name(args) + +#ifdef __cplusplus +#define MSHake(name) \ + &$ ## name, &_ ## name +#else +#define MSHake(name) \ + &$ ## name, (void **) &_ ## name +#endif + + +#endif//SUBSTRATE_H_ diff --git a/edxp-core/jni/main/Substrate/SubstrateARM.hpp b/edxp-core/jni/main/Substrate/SubstrateARM.hpp new file mode 100644 index 000000000..564b61d3a --- /dev/null +++ b/edxp-core/jni/main/Substrate/SubstrateARM.hpp @@ -0,0 +1,67 @@ +/* Cydia Substrate - Powerful Code Insertion Platform + * Copyright (C) 2008-2011 Jay Freeman (saurik) +*/ + +/* GNU Lesser General Public License, Version 3 {{{ */ +/* + * Substrate is free software: you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * Substrate is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Substrate. If not, see . +**/ +/* }}} */ + +#ifndef SUBSTRATE_ARM_HPP +#define SUBSTRATE_ARM_HPP + +enum A$r { + A$r0, A$r1, A$r2, A$r3, + A$r4, A$r5, A$r6, A$r7, + A$r8, A$r9, A$r10, A$r11, + A$r12, A$r13, A$r14, A$r15, + A$sp = A$r13, + A$lr = A$r14, + A$pc = A$r15 +}; + +enum A$c { + A$eq, A$ne, A$cs, A$cc, + A$mi, A$pl, A$vs, A$vc, + A$hi, A$ls, A$ge, A$lt, + A$gt, A$le, A$al, + A$hs = A$cs, + A$lo = A$cc +}; + +template static T xabs(T _Val); + +#define A$mrs_rm_cpsr(rd) /* mrs rd, cpsr */ \ + (0xe10f0000 | ((rd) << 12)) +#define A$msr_cpsr_f_rm(rm) /* msr cpsr_f, rm */ \ + (0xe128f000 | (rm)) +#define A$ldr_rd_$rn_im$(rd, rn, im) /* ldr rd, [rn, #im] */ \ + (0xe5100000 | ((im) < 0 ? 0 : 1 << 23) | ((rn) << 16) | ((rd) << 12) | xabs(im)) +#define A$str_rd_$rn_im$(rd, rn, im) /* sr rd, [rn, #im] */ \ + (0xe5000000 | ((im) < 0 ? 0 : 1 << 23) | ((rn) << 16) | ((rd) << 12) | xabs(im)) +#define A$sub_rd_rn_$im(rd, rn, im) /* sub, rd, rn, #im */ \ + (0xe2400000 | ((rn) << 16) | ((rd) << 12) | (im & 0xff)) +#define A$blx_rm(rm) /* blx rm */ \ + (0xe12fff30 | (rm)) +#define A$mov_rd_rm(rd, rm) /* mov rd, rm */ \ + (0xe1a00000 | ((rd) << 12) | (rm)) +#define A$ldmia_sp$_$rs$(rs) /* ldmia sp!, {rs} */ \ + (0xe8b00000 | (A$sp << 16) | (rs)) +#define A$stmdb_sp$_$rs$(rs) /* stmdb sp!, {rs} */ \ + (0xe9200000 | (A$sp << 16) | (rs)) +#define A$stmia_sp$_$r0$ 0xe8ad0001 /* stmia sp!, {r0} */ +#define A$bx_r0 0xe12fff10 /* bx r0 */ + +#endif//SUBSTRATE_ARM_HPP diff --git a/edxp-core/jni/main/Substrate/SubstrateDebug.cpp b/edxp-core/jni/main/Substrate/SubstrateDebug.cpp new file mode 100644 index 000000000..2df6ef487 --- /dev/null +++ b/edxp-core/jni/main/Substrate/SubstrateDebug.cpp @@ -0,0 +1,96 @@ +/* Cydia Substrate - Powerful Code Insertion Platform + * Copyright (C) 2008-2011 Jay Freeman (saurik) +*/ + +/* GNU Lesser General Public License, Version 3 {{{ */ +/* + * Substrate is free software: you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * Substrate is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Substrate. If not, see . +**/ +/* }}} */ + +#include "SubstrateHook.h" +#include "SubstrateDebug.hpp" + +#include +#include +#include + +_extern bool MSDebug; +bool MSDebug = false; + +static char _MSHexChar(uint8_t value) { + return value < 0x20 || value >= 0x80 ? '.' : value; +} + +#define HexWidth_ 16 +#define HexDepth_ 4 + +void MSLogHexEx(const void *vdata, size_t size, size_t stride, const char *mark) { + const uint8_t *data((const uint8_t *) vdata); + + size_t i(0), j; + + char d[256]; + size_t b(0); + d[0] = '\0'; + + while (i != size) { + if (i % HexWidth_ == 0) { + if (mark != NULL) + b += sprintf(d + b, "\n[%s] ", mark); + b += sprintf(d + b, "0x%.3zx:", i); + } + + b += sprintf(d + b, " "); + + for (size_t q(0); q != stride; ++q) + b += sprintf(d + b, "%.2x", data[i + stride - q - 1]); + + i += stride; + + for (size_t q(1); q != stride; ++q) + b += sprintf(d + b, " "); + + if (i % HexDepth_ == 0) + b += sprintf(d + b, " "); + + if (i % HexWidth_ == 0) { + b += sprintf(d + b, " "); + for (j = i - HexWidth_; j != i; ++j) + b += sprintf(d + b, "%c", _MSHexChar(data[j])); + + lprintf("%s", d); + b = 0; + d[0] = '\0'; + } + } + + if (i % HexWidth_ != 0) { + for (j = i % HexWidth_; j != HexWidth_; ++j) + b += sprintf(d + b, " "); + for (j = 0; j != (HexWidth_ - i % HexWidth_ + HexDepth_ - 1) / HexDepth_; ++j) + b += sprintf(d + b, " "); + b += sprintf(d + b, " "); + for (j = i / HexWidth_ * HexWidth_; j != i; ++j) + b += sprintf(d + b, "%c", _MSHexChar(data[j])); + + lprintf("%s", d); + b = 0; + d[0] = '\0'; + } +} + +void MSLogHex(const void *vdata, size_t size, const char *mark) { + return MSLogHexEx(vdata, size, 1, mark); +} diff --git a/edxp-core/jni/main/Substrate/SubstrateDebug.hpp b/edxp-core/jni/main/Substrate/SubstrateDebug.hpp new file mode 100644 index 000000000..9c554c851 --- /dev/null +++ b/edxp-core/jni/main/Substrate/SubstrateDebug.hpp @@ -0,0 +1,33 @@ +/* Cydia Substrate - Powerful Code Insertion Platform + * Copyright (C) 2008-2011 Jay Freeman (saurik) +*/ + +/* GNU Lesser General Public License, Version 3 {{{ */ +/* + * Substrate is free software: you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * Substrate is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Substrate. If not, see . +**/ +/* }}} */ + +#ifndef SUBSTRATE_DEBUG_HPP +#define SUBSTRATE_DEBUG_HPP + +#include "SubstrateLog.hpp" +#define lprintf(format, ...) \ + MSLog(MSLogLevelNotice, format, ## __VA_ARGS__) + +extern "C" bool MSDebug; +void MSLogHexEx(const void *vdata, size_t size, size_t stride, const char *mark = 0); +void MSLogHex(const void *vdata, size_t size, const char *mark = 0); + +#endif//SUBSTRATE_DEBUG_HPP diff --git a/edxp-core/jni/main/Substrate/SubstrateHook.cpp b/edxp-core/jni/main/Substrate/SubstrateHook.cpp new file mode 100644 index 000000000..7c38240f9 --- /dev/null +++ b/edxp-core/jni/main/Substrate/SubstrateHook.cpp @@ -0,0 +1,945 @@ +/* Cydia Substrate - Powerful Code Insertion Platform + * Copyright (C) 2008-2011 Jay Freeman (saurik) +*/ + +/* GNU Lesser General Public License, Version 3 {{{ */ +/* + * Substrate is free software: you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * Substrate is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Substrate. If not, see . +**/ +/* }}} */ + +#define SubstrateInternal +#include "CydiaSubstrate.h" + +#include + +#define _trace() do { \ + MSLog(MSLogLevelNotice, "_trace(%u)", __LINE__); \ +} while (false) + +#if defined(__i386__) || defined(__x86_64__) +#include "hde64.h" +#endif + +#include "SubstrateDebug.hpp" + +#include +#include +#include +#include + +#ifdef __arm__ +/* WebCore (ARM) PC-Relative: +X 1 ldr r*,[pc,r*] != + 2 fldd d*,[pc,#*] +X 5 str r*,[pc,r*] != + 8 flds s*,[pc,#*] + 400 ldr r*,[pc,r*] == + 515 add r*, pc,r* == +X 4790 ldr r*,[pc,#*] */ + +// x=0; while IFS= read -r line; do if [[ ${#line} -ne 0 && $line == +([^\;]): ]]; then x=2; elif [[ $line == ' +'* && $x -ne 0 ]]; then ((--x)); echo "$x${line}"; fi; done WebCore.pc +// grep pc WebCore.pc | cut -c 40- | sed -Ee 's/^ldr *(ip|r[0-9]*),\[pc,\#0x[0-9a-f]*\].*/ ldr r*,[pc,#*]/;s/^add *r[0-9]*,pc,r[0-9]*.*/ add r*, pc,r*/;s/^(st|ld)r *r([0-9]*),\[pc,r([0-9]*)\].*/ \1r r\2,[pc,r\3]/;s/^fld(s|d) *(s|d)[0-9]*,\[pc,#0x[0-9a-f]*].*/fld\1 \2*,[pc,#*]/' | sort | uniq -c | sort -n + +#include "SubstrateARM.hpp" + +#define T$Label(l, r) \ + (((r) - (l)) * 2 - 4 + ((l) % 2 == 0 ? 0 : 2)) + +#define T$pop_$r0$ 0xbc01 // pop {r0} +#define T$b(im) /* b im */ \ + (0xde00 | (im & 0xff)) +#define T$blx(rm) /* blx rm */ \ + (0x4780 | (rm << 3)) +#define T$bx(rm) /* bx rm */ \ + (0x4700 | (rm << 3)) +#define T$nop /* nop */ \ + (0x46c0) + +#define T$add_rd_rm(rd, rm) /* add rd, rm */ \ + (0x4400 | (((rd) & 0x8) >> 3 << 7) | (((rm) & 0x8) >> 3 << 6) | (((rm) & 0x7) << 3) | ((rd) & 0x7)) +#define T$push_r(r) /* push r... */ \ + (0xb400 | (((r) & (1 << A$lr)) >> A$lr << 8) | ((r) & 0xff)) +#define T$pop_r(r) /* pop r... */ \ + (0xbc00 | (((r) & (1 << A$pc)) >> A$pc << 8) | ((r) & 0xff)) +#define T$mov_rd_rm(rd, rm) /* mov rd, rm */ \ + (0x4600 | (((rd) & 0x8) >> 3 << 7) | (((rm) & 0x8) >> 3 << 6) | (((rm) & 0x7) << 3) | ((rd) & 0x7)) +#define T$ldr_rd_$rn_im_4$(rd, rn, im) /* ldr rd, [rn, #im * 4] */ \ + (0x6800 | (((im) & 0x1f) << 6) | ((rn) << 3) | (rd)) +#define T$ldr_rd_$pc_im_4$(rd, im) /* ldr rd, [PC, #im * 4] */ \ + (0x4800 | ((rd) << 8) | ((im) & 0xff)) +#define T$cmp_rn_$im(rn, im) /* cmp rn, #im */ \ + (0x2000 | ((rn) << 8) | ((im) & 0xff)) +#define T$it$_cd(cd, ms) /* it, cd */ \ + (0xbf00 | ((cd) << 4) | (ms)) +#define T$cbz$_rn_$im(op,rn,im) /* cbz rn, #im */ \ + (0xb100 | ((op) << 11) | (((im) & 0x40) >> 6 << 9) | (((im) & 0x3e) >> 1 << 3) | (rn)) +#define T$b$_$im(cond,im) /* b #im */ \ + (cond == A$al ? 0xe000 | (((im) >> 1) & 0x7ff) : 0xd000 | ((cond) << 8) | (((im) >> 1) & 0xff)) + +#define T1$ldr_rt_$rn_im$(rt, rn, im) /* ldr rt, [rn, #im] */ \ + (0xf850 | ((im < 0 ? 0 : 1) << 7) | (rn)) + +template T xabs(T _Val) +{ + typedef int BOOL; + if(_Val>T(0))return _Val; + return -_Val; +} + +#define T2$ldr_rt_$rn_im$(rt, rn, im) /* ldr rt, [rn, #im] */ \ + (((rt) << 12) | xabs(im)) + +#define T1$mrs_rd_apsr(rd) /* mrs rd, apsr */ \ + (0xf3ef) +#define T2$mrs_rd_apsr(rd) /* mrs rd, apsr */ \ + (0x8000 | ((rd) << 8)) + +#define T1$msr_apsr_nzcvqg_rn(rn) /* msr apsr, rn */ \ + (0xf380 | (rn)) +#define T2$msr_apsr_nzcvqg_rn(rn) /* msr apsr, rn */ \ + (0x8c00) +#define T$msr_apsr_nzcvqg_rn(rn) /* msr apsr, rn */ \ + (T2$msr_apsr_nzcvqg_rn(rn) << 16 | T1$msr_apsr_nzcvqg_rn(rn)) + +static inline bool A$pcrel$r(uint32_t ic) { + return (ic & 0x0c000000) == 0x04000000 && (ic & 0xf0000000) != 0xf0000000 && (ic & 0x000f0000) == 0x000f0000; +} + +static inline bool T$32bit$i(uint16_t ic) { + return ((ic & 0xe000) == 0xe000 && (ic & 0x1800) != 0x0000); +} + +static inline bool T$pcrel$cbz(uint16_t ic) { + return (ic & 0xf500) == 0xb100; +} + +static inline bool T$pcrel$b(uint16_t ic) { + return (ic & 0xf000) == 0xd000 && (ic & 0x0e00) != 0x0e00; +} + +static inline bool T2$pcrel$b(uint16_t *ic) { + return (ic[0] & 0xf800) == 0xf000 && ((ic[1] & 0xd000) == 0x9000 || (ic[1] & 0xd000) == 0x8000 && (ic[0] & 0x0380) != 0x0380); +} + +static inline bool T$pcrel$bl(uint16_t *ic) { + return (ic[0] & 0xf800) == 0xf000 && ((ic[1] & 0xd000) == 0xd000 || (ic[1] & 0xd001) == 0xc000); +} + +static inline bool T$pcrel$ldr(uint16_t ic) { + return (ic & 0xf800) == 0x4800; +} + +static inline bool T$pcrel$add(uint16_t ic) { + return (ic & 0xff78) == 0x4478; +} + +static inline bool T$pcrel$ldrw(uint16_t ic) { + return (ic & 0xff7f) == 0xf85f; +} + +static size_t MSGetInstructionWidthThumb(void *start) { + uint16_t *thumb(reinterpret_cast(start)); + return T$32bit$i(thumb[0]) ? 4 : 2; +} + +static size_t MSGetInstructionWidthARM(void *start) { + return 4; +} + +extern "C" size_t MSGetInstructionWidth(void *start) { + if ((reinterpret_cast(start) & 0x1) == 0) + return MSGetInstructionWidthARM(start); + else + return MSGetInstructionWidthThumb(reinterpret_cast(reinterpret_cast(start) & ~0x1)); +} + +static size_t SubstrateHookFunctionThumb(SubstrateProcessRef process, void *symbol, void *replace, void **result) { + if (symbol == NULL) + return 0; +printf("SubstrateHookFunctionThumb\n"); + uint16_t *area(reinterpret_cast(symbol)); + + unsigned align((reinterpret_cast(area) & 0x2) == 0 ? 0 : 1); + uint16_t *thumb(area + align); + + uint32_t *arm(reinterpret_cast(thumb + 2)); + uint16_t *trail(reinterpret_cast(arm + 2)); + + if ( + (align == 0 || area[0] == T$nop) && + thumb[0] == T$bx(A$pc) && + thumb[1] == T$nop && + arm[0] == A$ldr_rd_$rn_im$(A$pc, A$pc, 4 - 8) + ) { + if (result != NULL) + *result = reinterpret_cast(arm[1]); + + SubstrateHookMemory code(process, arm + 1, sizeof(uint32_t) * 1); + + arm[1] = reinterpret_cast(replace); + + return sizeof(arm[0]); + } + + size_t required((trail - area) * sizeof(uint16_t)); + + size_t used(0); + while (used < required) + used += MSGetInstructionWidthThumb(reinterpret_cast(area) + used); + used = (used + sizeof(uint16_t) - 1) / sizeof(uint16_t) * sizeof(uint16_t); + + size_t blank((used - required) / sizeof(uint16_t)); + + uint16_t backup[used / sizeof(uint16_t)]; + memcpy(backup, area, used); + + if (MSDebug) { + char name[16]; + sprintf(name, "%p", area); + MSLogHexEx(area, used + sizeof(uint16_t), 2, name); + } + + if (result != NULL) { + + size_t length(used); + for (unsigned offset(0); offset != used / sizeof(uint16_t); ++offset) + if (T$pcrel$ldr(backup[offset])) + length += 3 * sizeof(uint16_t); + else if (T$pcrel$b(backup[offset])) + length += 6 * sizeof(uint16_t); + else if (T2$pcrel$b(backup + offset)) { + length += 5 * sizeof(uint16_t); + ++offset; + } else if (T$pcrel$bl(backup + offset)) { + length += 5 * sizeof(uint16_t); + ++offset; + } else if (T$pcrel$cbz(backup[offset])) { + length += 16 * sizeof(uint16_t); + } else if (T$pcrel$ldrw(backup[offset])) { + length += 4 * sizeof(uint16_t); + ++offset; + } else if (T$pcrel$add(backup[offset])) + length += 6 * sizeof(uint16_t); + else if (T$32bit$i(backup[offset])) + ++offset; + + unsigned pad((length & 0x2) == 0 ? 0 : 1); + length += (pad + 2) * sizeof(uint16_t) + 2 * sizeof(uint32_t); + + uint16_t *buffer(reinterpret_cast(mmap( + NULL, length, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0 + ))); + + if (buffer == MAP_FAILED) { + MSLog(MSLogLevelError, "MS:Error:mmap() = %d", errno); + *result = NULL; + return 0; + } + + if (false) fail: { + munmap(buffer, length); + *result = NULL; + return 0; + } + + size_t start(pad), end(length / sizeof(uint16_t)); + uint32_t *trailer(reinterpret_cast(buffer + end)); + for (unsigned offset(0); offset != used / sizeof(uint16_t); ++offset) { + if (T$pcrel$ldr(backup[offset])) { + union { + uint16_t value; + + struct { + uint16_t immediate : 8; + uint16_t rd : 3; + uint16_t : 5; + }; + } bits = {backup[offset+0]}; + + buffer[start+0] = T$ldr_rd_$pc_im_4$(bits.rd, T$Label(start+0, end-2) / 4); + buffer[start+1] = T$ldr_rd_$rn_im_4$(bits.rd, bits.rd, 0); + + // XXX: this code "works", but is "wrong": the mechanism is more complex than this + *--trailer = ((reinterpret_cast(area + offset) + 4) & ~0x2) + bits.immediate * 4; + + start += 2; + end -= 2; + } else if (T$pcrel$b(backup[offset])) { + union { + uint16_t value; + + struct { + uint16_t imm8 : 8; + uint16_t cond : 4; + uint16_t /*1101*/ : 4; + }; + } bits = {backup[offset+0]}; + + intptr_t jump(bits.imm8 << 1); + jump |= 1; + jump <<= 23; + jump >>= 23; + + buffer[start+0] = T$b$_$im(bits.cond, (end-6 - (start+0)) * 2 - 4); + + *--trailer = reinterpret_cast(area + offset) + 4 + jump; + *--trailer = A$ldr_rd_$rn_im$(A$pc, A$pc, 4 - 8); + *--trailer = T$nop << 16 | T$bx(A$pc); + + start += 1; + end -= 6; + } else if (T2$pcrel$b(backup + offset)) { + union { + uint16_t value; + + struct { + uint16_t imm6 : 6; + uint16_t cond : 4; + uint16_t s : 1; + uint16_t : 5; + }; + } bits = {backup[offset+0]}; + + union { + uint16_t value; + + struct { + uint16_t imm11 : 11; + uint16_t j2 : 1; + uint16_t a : 1; + uint16_t j1 : 1; + uint16_t : 2; + }; + } exts = {backup[offset+1]}; + + intptr_t jump(1); + jump |= exts.imm11 << 1; + jump |= bits.imm6 << 12; + + if (exts.a) { + jump |= bits.s << 24; + jump |= (~(bits.s ^ exts.j1) & 0x1) << 23; + jump |= (~(bits.s ^ exts.j2) & 0x1) << 22; + jump |= bits.cond << 18; + jump <<= 7; + jump >>= 7; + } else { + jump |= bits.s << 20; + jump |= exts.j2 << 19; + jump |= exts.j1 << 18; + jump <<= 11; + jump >>= 11; + } + + buffer[start+0] = T$b$_$im(exts.a ? A$al : bits.cond, (end-6 - (start+0)) * 2 - 4); + + *--trailer = reinterpret_cast(area + offset) + 4 + jump; + *--trailer = A$ldr_rd_$rn_im$(A$pc, A$pc, 4 - 8); + *--trailer = T$nop << 16 | T$bx(A$pc); + + ++offset; + start += 1; + end -= 6; + } else if (T$pcrel$bl(backup + offset)) { + union { + uint16_t value; + + struct { + uint16_t immediate : 10; + uint16_t s : 1; + uint16_t : 5; + }; + } bits = {backup[offset+0]}; + + union { + uint16_t value; + + struct { + uint16_t immediate : 11; + uint16_t j2 : 1; + uint16_t x : 1; + uint16_t j1 : 1; + uint16_t : 2; + }; + } exts = {backup[offset+1]}; + + int32_t jump(0); + jump |= bits.s << 24; + jump |= (~(bits.s ^ exts.j1) & 0x1) << 23; + jump |= (~(bits.s ^ exts.j2) & 0x1) << 22; + jump |= bits.immediate << 12; + jump |= exts.immediate << 1; + jump |= exts.x; + jump <<= 7; + jump >>= 7; + + buffer[start+0] = T$push_r(1 << A$r7); + buffer[start+1] = T$ldr_rd_$pc_im_4$(A$r7, ((end-2 - (start+1)) * 2 - 4 + 2) / 4); + buffer[start+2] = T$mov_rd_rm(A$lr, A$r7); + buffer[start+3] = T$pop_r(1 << A$r7); + buffer[start+4] = T$blx(A$lr); + + *--trailer = reinterpret_cast(area + offset) + 4 + jump; + + ++offset; + start += 5; + end -= 2; + } else if (T$pcrel$cbz(backup[offset])) { + union { + uint16_t value; + + struct { + uint16_t rn : 3; + uint16_t immediate : 5; + uint16_t : 1; + uint16_t i : 1; + uint16_t : 1; + uint16_t op : 1; + uint16_t : 4; + }; + } bits = {backup[offset+0]}; + + intptr_t jump(1); + jump |= bits.i << 6; + jump |= bits.immediate << 1; + + //jump <<= 24; + //jump >>= 24; + + unsigned rn(bits.rn); + unsigned rt(rn == A$r7 ? A$r6 : A$r7); + + buffer[start+0] = T$push_r(1 << rt); + buffer[start+1] = T1$mrs_rd_apsr(rt); + buffer[start+2] = T2$mrs_rd_apsr(rt); + buffer[start+3] = T$cbz$_rn_$im(bits.op, rn, (end-10 - (start+3)) * 2 - 4); + buffer[start+4] = T1$msr_apsr_nzcvqg_rn(rt); + buffer[start+5] = T2$msr_apsr_nzcvqg_rn(rt); + buffer[start+6] = T$pop_r(1 << rt); + + *--trailer = reinterpret_cast(area + offset) + 4 + jump; + *--trailer = A$ldr_rd_$rn_im$(A$pc, A$pc, 4 - 8); + *--trailer = T$nop << 16 | T$bx(A$pc); + *--trailer = T$nop << 16 | T$pop_r(1 << rt); + *--trailer = T$msr_apsr_nzcvqg_rn(rt); + +#if 0 + if ((start & 0x1) == 0) + buffer[start++] = T$nop; + buffer[start++] = T$bx(A$pc); + buffer[start++] = T$nop; + + uint32_t *arm(reinterpret_cast(buffer + start)); + arm[0] = A$add(A$lr, A$pc, 1); + arm[1] = A$ldr_rd_$rn_im$(A$pc, A$pc, (trailer - arm) * sizeof(uint32_t) - 8); +#endif + + start += 7; + end -= 10; + } else if (T$pcrel$ldrw(backup[offset])) { + union { + uint16_t value; + + struct { + uint16_t : 7; + uint16_t u : 1; + uint16_t : 8; + }; + } bits = {backup[offset+0]}; + + union { + uint16_t value; + + struct { + uint16_t immediate : 12; + uint16_t rt : 4; + }; + } exts = {backup[offset+1]}; + + buffer[start+0] = T1$ldr_rt_$rn_im$(exts.rt, A$pc, T$Label(start+0, end-2)); + buffer[start+1] = T2$ldr_rt_$rn_im$(exts.rt, A$pc, T$Label(start+0, end-2)); + + buffer[start+2] = T1$ldr_rt_$rn_im$(exts.rt, exts.rt, 0); + buffer[start+3] = T2$ldr_rt_$rn_im$(exts.rt, exts.rt, 0); + + // XXX: this code "works", but is "wrong": the mechanism is more complex than this + *--trailer = ((reinterpret_cast(area + offset) + 4) & ~0x2) + (bits.u == 0 ? -exts.immediate : exts.immediate); + + ++offset; + start += 4; + end -= 2; + } else if (T$pcrel$add(backup[offset])) { + union { + uint16_t value; + + struct { + uint16_t rd : 3; + uint16_t rm : 3; + uint16_t h2 : 1; + uint16_t h1 : 1; + uint16_t : 8; + }; + } bits = {backup[offset+0]}; + + if (bits.h1) { + MSLog(MSLogLevelError, "MS:Error:pcrel(%u):add (rd > r7)", offset); + goto fail; + } + + unsigned rt(bits.rd == A$r7 ? A$r6 : A$r7); + + buffer[start+0] = T$push_r(1 << rt); + buffer[start+1] = T$mov_rd_rm(rt, (bits.h1 << 3) | bits.rd); + buffer[start+2] = T$ldr_rd_$pc_im_4$(bits.rd, T$Label(start+2, end-2) / 4); + buffer[start+3] = T$add_rd_rm((bits.h1 << 3) | bits.rd, rt); + buffer[start+4] = T$pop_r(1 << rt); + *--trailer = reinterpret_cast(area + offset) + 4; + + start += 5; + end -= 2; + } else if (T$32bit$i(backup[offset])) { + buffer[start++] = backup[offset]; + buffer[start++] = backup[++offset]; + } else { + buffer[start++] = backup[offset]; + } + } + + buffer[start++] = T$bx(A$pc); + buffer[start++] = T$nop; + + uint32_t *transfer = reinterpret_cast(buffer + start); + transfer[0] = A$ldr_rd_$rn_im$(A$pc, A$pc, 4 - 8); + transfer[1] = reinterpret_cast(area + used / sizeof(uint16_t)) + 1; + + if (mprotect(buffer, length, PROT_READ | PROT_EXEC) == -1) { + MSLog(MSLogLevelError, "MS:Error:mprotect():%d", errno); + return 0; + } + + *result = reinterpret_cast(buffer + pad) + 1; + + if (MSDebug) { + char name[16]; + sprintf(name, "%p", *result); + MSLogHexEx(buffer, length, 2, name); + } + + } + + { + SubstrateHookMemory code(process, area, used); + + if (align != 0) + area[0] = T$nop; + + thumb[0] = T$bx(A$pc); + thumb[1] = T$nop; + + arm[0] = A$ldr_rd_$rn_im$(A$pc, A$pc, 4 - 8); + arm[1] = reinterpret_cast(replace); + + for (unsigned offset(0); offset != blank; ++offset) + trail[offset] = T$nop; + } + + if (MSDebug) { + char name[16]; + sprintf(name, "%p", area); + MSLogHexEx(area, used + sizeof(uint16_t), 2, name); + } + + return used; +} + +static size_t SubstrateHookFunctionARM(SubstrateProcessRef process, void *symbol, void *replace, void **result) { + if (symbol == NULL) + return 0; +printf("SubstrateHookFunctionARM\n"); + uint32_t *area(reinterpret_cast(symbol)); + uint32_t *arm(area); + + const size_t used(8); + + uint32_t backup[used / sizeof(uint32_t)] = {arm[0], arm[1]}; + + if (MSDebug) { + char name[16]; + sprintf(name, "%p", area); + MSLogHexEx(area, used + sizeof(uint32_t), 4, name); + } + + if (result != NULL) { + + if (backup[0] == A$ldr_rd_$rn_im$(A$pc, A$pc, 4 - 8)) { + *result = reinterpret_cast(backup[1]); + + return sizeof(backup[0]); + } + + size_t length(used); + for (unsigned offset(0); offset != used / sizeof(uint32_t); ++offset) + if (A$pcrel$r(backup[offset])) { + if ((backup[offset] & 0x02000000) == 0 || (backup[offset] & 0x0000f000 >> 12) != (backup[offset] & 0x0000000f)) + length += 2 * sizeof(uint32_t); + else + length += 4 * sizeof(uint32_t); + } + + length += 2 * sizeof(uint32_t); + + uint32_t *buffer(reinterpret_cast(mmap( + NULL, length, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0 + ))); + + if (buffer == MAP_FAILED) { + MSLog(MSLogLevelError, "MS:Error:mmap() = %d", errno); + *result = NULL; + return 0; + } + + if (false) fail: { + munmap(buffer, length); + *result = NULL; + return 0; + } + + size_t start(0), end(length / sizeof(uint32_t)); + uint32_t *trailer(reinterpret_cast(buffer + end)); + for (unsigned offset(0); offset != used / sizeof(uint32_t); ++offset) + if (A$pcrel$r(backup[offset])) { + union { + uint32_t value; + + struct { + uint32_t rm : 4; + uint32_t : 1; + uint32_t shift : 2; + uint32_t shiftamount : 5; + uint32_t rd : 4; + uint32_t rn : 4; + uint32_t l : 1; + uint32_t w : 1; + uint32_t b : 1; + uint32_t u : 1; + uint32_t p : 1; + uint32_t mode : 1; + uint32_t type : 2; + uint32_t cond : 4; + }; + } bits = {backup[offset+0]}, copy(bits); + + bool guard; + if (bits.mode == 0 || bits.rd != bits.rm) { + copy.rn = bits.rd; + guard = false; + } else { + copy.rn = bits.rm != A$r0 ? A$r0 : A$r1; + guard = true; + } + + if (guard) + buffer[start++] = A$stmdb_sp$_$rs$((1 << copy.rn)); + + buffer[start+0] = A$ldr_rd_$rn_im$(copy.rn, A$pc, (end-1 - (start+0)) * 4 - 8); + buffer[start+1] = copy.value; + + start += 2; + + if (guard) + buffer[start++] = A$ldmia_sp$_$rs$((1 << copy.rn)); + + *--trailer = reinterpret_cast(area + offset) + 8; + end -= 1; + } else + buffer[start++] = backup[offset]; + + buffer[start+0] = A$ldr_rd_$rn_im$(A$pc, A$pc, 4 - 8); + buffer[start+1] = reinterpret_cast(area + used / sizeof(uint32_t)); + + if (mprotect(buffer, length, PROT_READ | PROT_EXEC) == -1) { + MSLog(MSLogLevelError, "MS:Error:mprotect():%d", errno); + goto fail; + } + + *result = buffer; + + if (MSDebug) { + char name[16]; + sprintf(name, "%p", *result); + MSLogHexEx(buffer, length, 4, name); + } + + } + + { + SubstrateHookMemory code(process, symbol, used); + + arm[0] = A$ldr_rd_$rn_im$(A$pc, A$pc, 4 - 8); + arm[1] = reinterpret_cast(replace); + } + + if (MSDebug) { + char name[16]; + sprintf(name, "%p", area); + MSLogHexEx(area, used + sizeof(uint32_t), 4, name); + } + + return used; +} + +static size_t SubstrateHookFunction(SubstrateProcessRef process, void *symbol, void *replace, void **result) { + if (MSDebug) + MSLog(MSLogLevelNotice, "SubstrateHookFunction(%p, %p, %p, %p)\n", process, symbol, replace, result); + if ((reinterpret_cast(symbol) & 0x1) == 0) + return SubstrateHookFunctionARM(process, symbol, replace, result); + else + return SubstrateHookFunctionThumb(process, reinterpret_cast(reinterpret_cast(symbol) & ~0x1), replace, result); +} +#endif + +#if defined(__i386__) || defined(__x86_64__) + +#include "SubstrateX86.hpp" + +static size_t MSGetInstructionWidthIntel(void *start) { + hde64s decode; + return hde64_disasm(start, &decode); +} + +static void SubstrateHookFunction(SubstrateProcessRef process, void *symbol, void *replace, void **result) { + if (MSDebug) + MSLog(MSLogLevelNotice, "MSHookFunction(%p, %p, %p)\n", symbol, replace, result); + if (symbol == NULL) + return; + + uintptr_t source(reinterpret_cast(symbol)); + uintptr_t target(reinterpret_cast(replace)); + + uint8_t *area(reinterpret_cast(symbol)); + + size_t required(MSSizeOfJump(target, source)); + + if (MSDebug) { + char name[16]; + sprintf(name, "%p", area); + MSLogHex(area, 32, name); + } + + size_t used(0); + while (used < required) { + size_t width(MSGetInstructionWidthIntel(area + used)); + if (width == 0) { + MSLog(MSLogLevelError, "MS:Error:MSGetInstructionWidthIntel(%p) == 0", area + used); + return; + } + + used += width; + } + + size_t blank(used - required); + + if (MSDebug) { + char name[16]; + sprintf(name, "%p", area); + MSLogHex(area, used + sizeof(uint16_t), name); + } + + uint8_t backup[used]; + memcpy(backup, area, used); + + if (result != NULL) { + + if (backup[0] == 0xe9) { + *result = reinterpret_cast(source + 5 + *reinterpret_cast(backup + 1)); + return; + } + + if (!ia32 && backup[0] == 0xff && backup[1] == 0x25) { + *result = *reinterpret_cast(source + 6 + *reinterpret_cast(backup + 2)); + return; + } + + size_t length(used + MSSizeOfJump(source + used)); + + for (size_t offset(0), width; offset != used; offset += width) { + hde64s decode; + hde64_disasm(backup + offset, &decode); + width = decode.len; + //_assert(width != 0 && offset + width <= used); + +#ifdef __LP64__ + if ((decode.modrm & 0xc7) == 0x05) { + if (decode.opcode == 0x8b) { + void *destiny(area + offset + width + int32_t(decode.disp.disp32)); + uint8_t reg(decode.rex_r << 3 | decode.modrm_reg); + length -= decode.len; + length += MSSizeOfPushPointer(destiny); + length += MSSizeOfPop(reg); + length += MSSizeOfMove64(); + } else { + MSLog(MSLogLevelError, "MS:Error: Unknown RIP-Relative (%.2x %.2x)", decode.opcode, decode.opcode2); + continue; + } + } else +#endif + + if (backup[offset] == 0xe8) { + int32_t relative(*reinterpret_cast(backup + offset + 1)); + void *destiny(area + offset + decode.len + relative); + + if (relative == 0) { + length -= decode.len; + length += MSSizeOfPushPointer(destiny); + } else { + length += MSSizeOfSkip(); + length += MSSizeOfJump(destiny); + } + } else if (backup[offset] == 0xeb) { + length -= decode.len; + length += MSSizeOfJump(area + offset + decode.len + *reinterpret_cast(backup + offset + 1)); + } else if (backup[offset] == 0xe9) { + length -= decode.len; + length += MSSizeOfJump(area + offset + decode.len + *reinterpret_cast(backup + offset + 1)); + } else if ( + backup[offset] == 0xe3 || + (backup[offset] & 0xf0) == 0x70 + // XXX: opcode2 & 0xf0 is 0x80? + ) { + length += decode.len; + length += MSSizeOfJump(area + offset + decode.len + *reinterpret_cast(backup + offset + 1)); + } + } + + uint8_t *buffer(reinterpret_cast(mmap( + NULL, length, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0 + ))); + + if (buffer == MAP_FAILED) { + MSLog(MSLogLevelError, "MS:Error:mmap() = %d", errno); + *result = NULL; + return; + } + + if (false) fail: { + munmap(buffer, length); + *result = NULL; + return; + } + + { + uint8_t *current(buffer); + + for (size_t offset(0), width; offset != used; offset += width) { + hde64s decode; + hde64_disasm(backup + offset, &decode); + width = decode.len; + //_assert(width != 0 && offset + width <= used); + +#ifdef __LP64__ + if ((decode.modrm & 0xc7) == 0x05) { + if (decode.opcode == 0x8b) { + void *destiny(area + offset + width + int32_t(decode.disp.disp32)); + uint8_t reg(decode.rex_r << 3 | decode.modrm_reg); + MSPushPointer(current, destiny); + MSWritePop(current, reg); + MSWriteMove64(current, reg, reg); + } else { + MSLog(MSLogLevelError, "MS:Error: Unknown RIP-Relative (%.2x %.2x)", decode.opcode, decode.opcode2); + goto copy; + } + } else +#endif + + if (backup[offset] == 0xe8) { + int32_t relative(*reinterpret_cast(backup + offset + 1)); + if (relative == 0) + MSPushPointer(current, area + offset + decode.len); + else { + MSWrite(current, 0xe8); + MSWrite(current, MSSizeOfSkip()); + void *destiny(area + offset + decode.len + relative); + MSWriteSkip(current, MSSizeOfJump(destiny, current + MSSizeOfSkip())); + MSWriteJump(current, destiny); + } + } else if (backup[offset] == 0xeb) + MSWriteJump(current, area + offset + decode.len + *reinterpret_cast(backup + offset + 1)); + else if (backup[offset] == 0xe9) + MSWriteJump(current, area + offset + decode.len + *reinterpret_cast(backup + offset + 1)); + else if ( + backup[offset] == 0xe3 || + (backup[offset] & 0xf0) == 0x70 + ) { + MSWrite(current, backup[offset]); + MSWrite(current, 2); + MSWrite(current, 0xeb); + void *destiny(area + offset + decode.len + *reinterpret_cast(backup + offset + 1)); + MSWrite(current, MSSizeOfJump(destiny, current + 1)); + MSWriteJump(current, destiny); + } else +#ifdef __LP64__ + copy: +#endif + { + MSWrite(current, backup + offset, width); + } + } + + MSWriteJump(current, area + used); + } + + if (mprotect(buffer, length, PROT_READ | PROT_EXEC) == -1) { + MSLog(MSLogLevelError, "MS:Error:mprotect():%d", errno); + goto fail; + } + + *result = buffer; + + if (MSDebug) { + char name[16]; + sprintf(name, "%p", *result); + MSLogHex(buffer, length, name); + } + + } + + { + SubstrateHookMemory code(process, area, used); + + uint8_t *current(area); + MSWriteJump(current, target); + for (unsigned offset(0); offset != blank; ++offset) + MSWrite(current, 0x90); + } + + if (MSDebug) { + char name[16]; + sprintf(name, "%p", area); + MSLogHex(area, used + sizeof(uint16_t), name); + } +} +#endif + +_extern void MSHookFunction(void *symbol, void *replace, void **result) { +#ifndef __LP64__ + SubstrateHookFunction(NULL, symbol, replace, result); +#endif +} + +#if defined(__APPLE__) && defined(__arm__) +_extern void _Z14MSHookFunctionPvS_PS_(void *symbol, void *replace, void **result) { + return MSHookFunction(symbol, replace, result); +} +#endif diff --git a/edxp-core/jni/main/Substrate/SubstrateHook.h b/edxp-core/jni/main/Substrate/SubstrateHook.h new file mode 100644 index 000000000..40a0296cb --- /dev/null +++ b/edxp-core/jni/main/Substrate/SubstrateHook.h @@ -0,0 +1,19 @@ +#ifndef __SUBSTRATEHOOK_H__ +#define __SUBSTRATEHOOK_H__ + + +#include + +#define _extern extern "C" __attribute__((__visibility__("default"))) + +#ifdef __cplusplus +extern "C" { +#endif + +void MSHookFunction(void *symbol, void *replace, void **result); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/edxp-core/jni/main/Substrate/SubstrateLog.hpp b/edxp-core/jni/main/Substrate/SubstrateLog.hpp new file mode 100644 index 000000000..3e5728014 --- /dev/null +++ b/edxp-core/jni/main/Substrate/SubstrateLog.hpp @@ -0,0 +1,40 @@ +/* Cydia Substrate - Powerful Code Insertion Platform + * Copyright (C) 2008-2011 Jay Freeman (saurik) +*/ + +/* GNU Lesser General Public License, Version 3 {{{ */ +/* + * Substrate is free software: you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * Substrate is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Substrate. If not, see . +**/ +/* }}} */ + +#ifndef SUBSTRATE_LOG_HPP +#define SUBSTRATE_LOG_HPP + +#if 0 +#include + +#define MSLog(level, format, ...) ((void)__android_log_print(level, "NNNN", format, __VA_ARGS__)) + +#define MSLogLevelNotice ANDROID_LOG_INFO +#define MSLogLevelWarning ANDROID_LOG_WARN +#define MSLogLevelError ANDROID_LOG_ERROR + +#else + +#define MSLog(level, format, ...) printf(format, __VA_ARGS__) + +#endif + +#endif//SUBSTRATE_LOG_HPP diff --git a/edxp-core/jni/main/Substrate/SubstratePosixMemory.cpp b/edxp-core/jni/main/Substrate/SubstratePosixMemory.cpp new file mode 100644 index 000000000..709cb228e --- /dev/null +++ b/edxp-core/jni/main/Substrate/SubstratePosixMemory.cpp @@ -0,0 +1,75 @@ +/* Cydia Substrate - Powerful Code Insertion Platform + * Copyright (C) 2008-2011 Jay Freeman (saurik) +*/ + +/* GNU Lesser General Public License, Version 3 {{{ */ +/* + * Substrate is free software: you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * Substrate is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Substrate. If not, see . +**/ +/* }}} */ + +#define SubstrateInternal +#include "CydiaSubstrate.h" +#include "SubstrateLog.hpp" + +#include + +#include +#include +#include + +extern "C" void __clear_cache (void *beg, void *end); + +struct __SubstrateMemory { + void *address_; + size_t width_; + + __SubstrateMemory(void *address, size_t width) : + address_(address), + width_(width) + { + } +}; + +extern "C" SubstrateMemoryRef SubstrateMemoryCreate(SubstrateAllocatorRef allocator, SubstrateProcessRef process, void *data, size_t size) { + if (allocator != NULL) { + MSLog(MSLogLevelError, "MS:Error:allocator != %d", 0); + return NULL; + } + + if (size == 0) + return NULL; + + long page(sysconf(_SC_PAGESIZE)); // Portable applications should employ sysconf(_SC_PAGESIZE) instead of getpagesize + + uintptr_t base(reinterpret_cast(data) / page * page); + size_t width(((reinterpret_cast(data) + size - 1) / page + 1) * page - base); + void *address(reinterpret_cast(base)); + + if (mprotect(address, width, PROT_READ | PROT_WRITE | PROT_EXEC) == -1) { + MSLog(MSLogLevelError, "MS:Error:mprotect() = %d", errno); + return NULL; + } + + return new __SubstrateMemory(address, width); +} + +extern "C" void SubstrateMemoryRelease(SubstrateMemoryRef memory) { + if (mprotect(memory->address_, memory->width_, PROT_READ | PROT_WRITE | PROT_EXEC) == -1) + MSLog(MSLogLevelError, "MS:Error:mprotect() = %d", errno); + + __clear_cache(reinterpret_cast(memory->address_), reinterpret_cast(memory->address_) + memory->width_); + + delete memory; +} diff --git a/edxp-core/jni/main/Substrate/SubstrateX86.hpp b/edxp-core/jni/main/Substrate/SubstrateX86.hpp new file mode 100644 index 000000000..ffe2b06e3 --- /dev/null +++ b/edxp-core/jni/main/Substrate/SubstrateX86.hpp @@ -0,0 +1,200 @@ +/* Cydia Substrate - Powerful Code Insertion Platform + * Copyright (C) 2008-2011 Jay Freeman (saurik) +*/ + +/* GNU Lesser General Public License, Version 3 {{{ */ +/* + * Substrate is free software: you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * Substrate is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Substrate. If not, see . +**/ +/* }}} */ + +#ifndef SUBSTRATE_X86_HPP +#define SUBSTRATE_X86_HPP + +#include "Buffer.hpp" + +#ifdef __LP64__ +static const bool ia32 = false; +#else +static const bool ia32 = true; +#endif + +enum I$r { + I$rax, I$rcx, I$rdx, I$rbx, + I$rsp, I$rbp, I$rsi, I$rdi, + I$r8, I$r9, I$r10, I$r11, + I$r12, I$r13, I$r14, I$r15, +}; + +_disused static bool MSIs32BitOffset(uintptr_t target, uintptr_t source) { + intptr_t offset(target - source); + return int32_t(offset) == offset; +} + +_disused static size_t MSSizeOfSkip() { + return 5; +} + +_disused static size_t MSSizeOfPushPointer(uintptr_t target) { + return uint64_t(target) >> 32 == 0 ? 5 : 13; +} + +_disused static size_t MSSizeOfPushPointer(void *target) { + return MSSizeOfPushPointer(reinterpret_cast(target)); +} + +_disused static size_t MSSizeOfJump(bool blind, uintptr_t target, uintptr_t source = 0) { + if (ia32 || !blind && MSIs32BitOffset(target, source + 5)) + return MSSizeOfSkip(); + else + return MSSizeOfPushPointer(target) + 1; +} + +_disused static size_t MSSizeOfJump(uintptr_t target, uintptr_t source) { + return MSSizeOfJump(false, target, source); +} + +_disused static size_t MSSizeOfJump(uintptr_t target) { + return MSSizeOfJump(true, target); +} + +_disused static size_t MSSizeOfJump(void *target, void *source) { + return MSSizeOfJump(reinterpret_cast(target), reinterpret_cast(source)); +} + +_disused static size_t MSSizeOfJump(void *target) { + return MSSizeOfJump(reinterpret_cast(target)); +} + +_disused static void MSWriteSkip(uint8_t *¤t, ssize_t size) { + MSWrite(current, 0xe9); + MSWrite(current, size); +} + +_disused static void MSPushPointer(uint8_t *¤t, uintptr_t target) { + MSWrite(current, 0x68); + MSWrite(current, target); + + if (uint32_t high = uint64_t(target) >> 32) { + MSWrite(current, 0xc7); + MSWrite(current, 0x44); + MSWrite(current, 0x24); + MSWrite(current, 0x04); + MSWrite(current, high); + } +} + +_disused static void MSPushPointer(uint8_t *¤t, void *target) { + return MSPushPointer(current, reinterpret_cast(target)); +} + +_disused static void MSWriteCall(uint8_t *¤t, I$r target) { + if (target >> 3 != 0) + MSWrite(current, 0x40 | (target & 0x08) >> 3); + MSWrite(current, 0xff); + MSWrite(current, 0xd0 | target & 0x07); +} + +_disused static void MSWriteCall(uint8_t *¤t, uintptr_t target) { + uintptr_t source(reinterpret_cast(current)); + + if (ia32 || MSIs32BitOffset(target, source + 5)) { + MSWrite(current, 0xe8); + MSWrite(current, target - (source + 5)); + } else { + MSPushPointer(current, target); + + MSWrite(current, 0x83); + MSWrite(current, 0xc4); + MSWrite(current, 0x08); + + MSWrite(current, 0x67); + MSWrite(current, 0xff); + MSWrite(current, 0x54); + MSWrite(current, 0x24); + MSWrite(current, 0xf8); + } +} + +template +_disused static void MSWriteCall(uint8_t *¤t, Type_ *target) { + return MSWriteCall(current, reinterpret_cast(target)); +} + +_disused static void MSWriteJump(uint8_t *¤t, uintptr_t target) { + uintptr_t source(reinterpret_cast(current)); + + if (ia32 || MSIs32BitOffset(target, source + 5)) + MSWriteSkip(current, target - (source + 5)); + else { + MSPushPointer(current, target); + MSWrite(current, 0xc3); + } +} + +_disused static void MSWriteJump(uint8_t *¤t, void *target) { + return MSWriteJump(current, reinterpret_cast(target)); +} + +_disused static void MSWriteJump(uint8_t *¤t, I$r target) { + if (target >> 3 != 0) + MSWrite(current, 0x40 | (target & 0x08) >> 3); + MSWrite(current, 0xff); + MSWrite(current, 0xe0 | target & 0x07); +} + +_disused static void MSWritePop(uint8_t *¤t, uint8_t target) { + if (target >> 3 != 0) + MSWrite(current, 0x40 | (target & 0x08) >> 3); + MSWrite(current, 0x58 | target & 0x07); +} + +_disused static size_t MSSizeOfPop(uint8_t target) { + return target >> 3 != 0 ? 2 : 1; +} + +_disused static void MSWritePush(uint8_t *¤t, I$r target) { + if (target >> 3 != 0) + MSWrite(current, 0x40 | (target & 0x08) >> 3); + MSWrite(current, 0x50 | target & 0x07); +} + +_disused static void MSWriteAdd(uint8_t *¤t, I$r target, uint8_t source) { + MSWrite(current, 0x83); + MSWrite(current, 0xc4 | target & 0x07); + MSWrite(current, source); +} + +_disused static void MSWriteSet64(uint8_t *¤t, I$r target, uintptr_t source) { + MSWrite(current, 0x48 | (target & 0x08) >> 3 << 2); + MSWrite(current, 0xb8 | target & 0x7); + MSWrite(current, source); +} + +template +_disused static void MSWriteSet64(uint8_t *¤t, I$r target, Type_ *source) { + return MSWriteSet64(current, target, reinterpret_cast(source)); +} + +_disused static void MSWriteMove64(uint8_t *¤t, uint8_t source, uint8_t target) { + MSWrite(current, 0x48 | (target & 0x08) >> 3 << 2 | (source & 0x08) >> 3); + MSWrite(current, 0x8b); + MSWrite(current, (target & 0x07) << 3 | source & 0x07); +} + +_disused static size_t MSSizeOfMove64() { + return 3; +} + +#endif//SUBSTRATE_X86_HPP diff --git a/edxp-core/jni/main/Substrate/hde64.c b/edxp-core/jni/main/Substrate/hde64.c new file mode 100644 index 000000000..d69f0c68e --- /dev/null +++ b/edxp-core/jni/main/Substrate/hde64.c @@ -0,0 +1,332 @@ +/* + * Hacker Disassembler Engine 64 C + * Copyright (c) 2008-2009, Vyacheslav Patkov. + * All rights reserved. + * + */ + +#include +#include + +#include "hde64.h" +#include "table64.h" + +unsigned int hde64_disasm(const void *code, hde64s *hs) +{ + uint8_t x, c, *p = (uint8_t *)code, cflags, opcode, pref = 0; + uint8_t *ht = hde64_table, m_mod, m_reg, m_rm, disp_size = 0; + uint8_t op64 = 0; + + memset(hs,0,sizeof(hde64s)); + char *tmp=(char*)hs; + + for (x = 16; x; x--) + switch (c = *p++) { + case 0xf3: + hs->p_rep = c; + pref |= PRE_F3; + break; + case 0xf2: + hs->p_rep = c; + pref |= PRE_F2; + break; + case 0xf0: + hs->p_lock = c; + pref |= PRE_LOCK; + break; + case 0x26: case 0x2e: case 0x36: + case 0x3e: case 0x64: case 0x65: + hs->p_seg = c; + pref |= PRE_SEG; + break; + case 0x66: + hs->p_66 = c; + pref |= PRE_66; + break; + case 0x67: + hs->p_67 = c; + pref |= PRE_67; + break; + default: + goto pref_done; + } + pref_done: + + hs->flags = (uint32_t)pref << 23; + + if (!pref) + pref |= PRE_NONE; + + if ((c & 0xf0) == 0x40) { + hs->flags |= F_PREFIX_REX; + if ((hs->rex_w = (c & 0xf) >> 3) && (*p & 0xf8) == 0xb8) + op64++; + hs->rex_r = (c & 7) >> 2; + hs->rex_x = (c & 3) >> 1; + hs->rex_b = c & 1; + if (((c = *p++) & 0xf0) == 0x40) { + opcode = c; + goto error_opcode; + } + } + + if ((hs->opcode = c) == 0x0f) { + hs->opcode2 = c = *p++; + ht += DELTA_OPCODES; + } else if (c >= 0xa0 && c <= 0xa3) { + op64++; + if (pref & PRE_67) + pref |= PRE_66; + else + pref &= ~PRE_66; + } + + opcode = c; + cflags = ht[ht[opcode / 4] + (opcode % 4)]; + + if (cflags == C_ERROR) { + error_opcode: + hs->flags |= F_ERROR | F_ERROR_OPCODE; + cflags = 0; + if ((opcode & -3) == 0x24) + cflags++; + } + + x = 0; + if (cflags & C_GROUP) { + uint16_t t; + t = *(uint16_t *)(ht + (cflags & 0x7f)); + cflags = (uint8_t)t; + x = (uint8_t)(t >> 8); + } + + if (hs->opcode2) { + ht = hde64_table + DELTA_PREFIXES; + if (ht[ht[opcode / 4] + (opcode % 4)] & pref) + hs->flags |= F_ERROR | F_ERROR_OPCODE; + } + + if (cflags & C_MODRM) { + hs->flags |= F_MODRM; + hs->modrm = c = *p++; + hs->modrm_mod = m_mod = c >> 6; + hs->modrm_rm = m_rm = c & 7; + hs->modrm_reg = m_reg = (c & 0x3f) >> 3; + + if (x && ((x << m_reg) & 0x80)) + hs->flags |= F_ERROR | F_ERROR_OPCODE; + + if (!hs->opcode2 && opcode >= 0xd9 && opcode <= 0xdf) { + uint8_t t = opcode - 0xd9; + if (m_mod == 3) { + ht = hde64_table + DELTA_FPU_MODRM + t*8; + t = ht[m_reg] << m_rm; + } else { + ht = hde64_table + DELTA_FPU_REG; + t = ht[t] << m_reg; + } + if (t & 0x80) + hs->flags |= F_ERROR | F_ERROR_OPCODE; + } + + if (pref & PRE_LOCK) { + if (m_mod == 3) { + hs->flags |= F_ERROR | F_ERROR_LOCK; + } else { + uint8_t *table_end, op = opcode; + if (hs->opcode2) { + ht = hde64_table + DELTA_OP2_LOCK_OK; + table_end = ht + DELTA_OP_ONLY_MEM - DELTA_OP2_LOCK_OK; + } else { + ht = hde64_table + DELTA_OP_LOCK_OK; + table_end = ht + DELTA_OP2_LOCK_OK - DELTA_OP_LOCK_OK; + op &= -2; + } + for (; ht != table_end; ht++) + if (*ht++ == op) { + if (!((*ht << m_reg) & 0x80)) + goto no_lock_error; + else + break; + } + hs->flags |= F_ERROR | F_ERROR_LOCK; + no_lock_error: + ; + } + } + + if (hs->opcode2) { + switch (opcode) { + case 0x20: case 0x22: + m_mod = 3; + if (m_reg > 4 || m_reg == 1) + goto error_operand; + else + goto no_error_operand; + case 0x21: case 0x23: + m_mod = 3; + if (m_reg == 4 || m_reg == 5) + goto error_operand; + else + goto no_error_operand; + } + } else { + switch (opcode) { + case 0x8c: + if (m_reg > 5) + goto error_operand; + else + goto no_error_operand; + case 0x8e: + if (m_reg == 1 || m_reg > 5) + goto error_operand; + else + goto no_error_operand; + } + } + + if (m_mod == 3) { + uint8_t *table_end; + if (hs->opcode2) { + ht = hde64_table + DELTA_OP2_ONLY_MEM; + table_end = ht + sizeof(hde64_table) - DELTA_OP2_ONLY_MEM; + } else { + ht = hde64_table + DELTA_OP_ONLY_MEM; + table_end = ht + DELTA_OP2_ONLY_MEM - DELTA_OP_ONLY_MEM; + } + for (; ht != table_end; ht += 2) + if (*ht++ == opcode) { + if (*ht++ & pref && !((*ht << m_reg) & 0x80)) + goto error_operand; + else + break; + } + goto no_error_operand; + } else if (hs->opcode2) { + switch (opcode) { + case 0x50: case 0xd7: case 0xf7: + if (pref & (PRE_NONE | PRE_66)) + goto error_operand; + break; + case 0xd6: + if (pref & (PRE_F2 | PRE_F3)) + goto error_operand; + break; + case 0xc5: + goto error_operand; + } + goto no_error_operand; + } else + goto no_error_operand; + + error_operand: + hs->flags |= F_ERROR | F_ERROR_OPERAND; + no_error_operand: + + c = *p++; + if (m_reg <= 1) { + if (opcode == 0xf6) + cflags |= C_IMM8; + else if (opcode == 0xf7) + cflags |= C_IMM_P66; + } + + switch (m_mod) { + case 0: + if (pref & PRE_67) { + if (m_rm == 6) + disp_size = 2; + } else + if (m_rm == 5) + disp_size = 4; + break; + case 1: + disp_size = 1; + break; + case 2: + disp_size = 2; + if (!(pref & PRE_67)) + disp_size <<= 1; + } + + if (m_mod != 3 && m_rm == 4) { + hs->flags |= F_SIB; + p++; + hs->sib = c; + hs->sib_scale = c >> 6; + hs->sib_index = (c & 0x3f) >> 3; + if ((hs->sib_base = c & 7) == 5 && !(m_mod & 1)) + disp_size = 4; + } + + p--; + switch (disp_size) { + case 1: + hs->flags |= F_DISP8; + hs->disp.disp8 = *p; + break; + case 2: + hs->flags |= F_DISP16; + hs->disp.disp16 = *(uint16_t *)p; + break; + case 4: + hs->flags |= F_DISP32; + hs->disp.disp32 = *(uint32_t *)p; + } + p += disp_size; + } else if (pref & PRE_LOCK) + hs->flags |= F_ERROR | F_ERROR_LOCK; + + if (cflags & C_IMM_P66) { + if (cflags & C_REL32) { + if (pref & PRE_66) { + hs->flags |= F_IMM16 | F_RELATIVE; + hs->imm.imm16 = *(uint16_t *)p; + p += 2; + goto disasm_done; + } + goto rel32_ok; + } + if (op64) { + hs->flags |= F_IMM64; + hs->imm.imm64 = *(uint64_t *)p; + p += 8; + } else if (!(pref & PRE_66)) { + hs->flags |= F_IMM32; + hs->imm.imm32 = *(uint32_t *)p; + p += 4; + } else + goto imm16_ok; + } + + + if (cflags & C_IMM16) { + imm16_ok: + hs->flags |= F_IMM16; + hs->imm.imm16 = *(uint16_t *)p; + p += 2; + } + if (cflags & C_IMM8) { + hs->flags |= F_IMM8; + hs->imm.imm8 = *p++; + } + + if (cflags & C_REL32) { + rel32_ok: + hs->flags |= F_IMM32 | F_RELATIVE; + hs->imm.imm32 = *(uint32_t *)p; + p += 4; + } else if (cflags & C_REL8) { + hs->flags |= F_IMM8 | F_RELATIVE; + hs->imm.imm8 = *p++; + } + + disasm_done: + + if ((hs->len = (uint8_t)(p-(uint8_t *)code)) > 15) { + hs->flags |= F_ERROR | F_ERROR_LENGTH; + hs->len = 15; + } + + return (unsigned int)hs->len; +} diff --git a/edxp-core/jni/main/Substrate/hde64.h b/edxp-core/jni/main/Substrate/hde64.h new file mode 100644 index 000000000..2fcc4cb25 --- /dev/null +++ b/edxp-core/jni/main/Substrate/hde64.h @@ -0,0 +1,112 @@ +/* + * Hacker Disassembler Engine 64 + * Copyright (c) 2008-2009, Vyacheslav Patkov. + * All rights reserved. + * + * hde64.h: C/C++ header file + * + */ + +#ifndef _HDE64_H_ +#define _HDE64_H_ + +/* stdint.h - C99 standard header + * http://en.wikipedia.org/wiki/stdint.h + * + * if your compiler doesn't contain "stdint.h" header (for + * example, Microsoft Visual C++), you can download file: + * http://www.azillionmonkeys.com/qed/pstdint.h + * and change next line to: + * #include "pstdint.h" + */ +#include + +#define F_MODRM 0x00000001 +#define F_SIB 0x00000002 +#define F_IMM8 0x00000004 +#define F_IMM16 0x00000008 +#define F_IMM32 0x00000010 +#define F_IMM64 0x00000020 +#define F_DISP8 0x00000040 +#define F_DISP16 0x00000080 +#define F_DISP32 0x00000100 +#define F_RELATIVE 0x00000200 +#define F_ERROR 0x00001000 +#define F_ERROR_OPCODE 0x00002000 +#define F_ERROR_LENGTH 0x00004000 +#define F_ERROR_LOCK 0x00008000 +#define F_ERROR_OPERAND 0x00010000 +#define F_PREFIX_REPNZ 0x01000000 +#define F_PREFIX_REPX 0x02000000 +#define F_PREFIX_REP 0x03000000 +#define F_PREFIX_66 0x04000000 +#define F_PREFIX_67 0x08000000 +#define F_PREFIX_LOCK 0x10000000 +#define F_PREFIX_SEG 0x20000000 +#define F_PREFIX_REX 0x40000000 +#define F_PREFIX_ANY 0x7f000000 + +#define PREFIX_SEGMENT_CS 0x2e +#define PREFIX_SEGMENT_SS 0x36 +#define PREFIX_SEGMENT_DS 0x3e +#define PREFIX_SEGMENT_ES 0x26 +#define PREFIX_SEGMENT_FS 0x64 +#define PREFIX_SEGMENT_GS 0x65 +#define PREFIX_LOCK 0xf0 +#define PREFIX_REPNZ 0xf2 +#define PREFIX_REPX 0xf3 +#define PREFIX_OPERAND_SIZE 0x66 +#define PREFIX_ADDRESS_SIZE 0x67 + +#pragma pack(push,1) + +typedef struct { + uint8_t len; + uint8_t p_rep; + uint8_t p_lock; + uint8_t p_seg; + uint8_t p_66; + uint8_t p_67; + uint8_t rex; + uint8_t rex_w; + uint8_t rex_r; + uint8_t rex_x; + uint8_t rex_b; + uint8_t opcode; + uint8_t opcode2; + uint8_t modrm; + uint8_t modrm_mod; + uint8_t modrm_reg; + uint8_t modrm_rm; + uint8_t sib; + uint8_t sib_scale; + uint8_t sib_index; + uint8_t sib_base; + union { + uint8_t imm8; + uint16_t imm16; + uint32_t imm32; + uint64_t imm64; + } imm; + union { + uint8_t disp8; + uint16_t disp16; + uint32_t disp32; + } disp; + uint32_t flags; +} hde64s; + +#pragma pack(pop) + +#ifdef __cplusplus +extern "C" { +#endif + +/* __cdecl */ +unsigned int hde64_disasm(const void *code, hde64s *hs); + +#ifdef __cplusplus +} +#endif + +#endif /* _HDE64_H_ */ diff --git a/edxp-core/jni/main/Substrate/table64.h b/edxp-core/jni/main/Substrate/table64.h new file mode 100644 index 000000000..144f29076 --- /dev/null +++ b/edxp-core/jni/main/Substrate/table64.h @@ -0,0 +1,74 @@ +/* + * Hacker Disassembler Engine 64 C + * Copyright (c) 2008-2009, Vyacheslav Patkov. + * All rights reserved. + * + */ + +#define C_NONE 0x00 +#define C_MODRM 0x01 +#define C_IMM8 0x02 +#define C_IMM16 0x04 +#define C_IMM_P66 0x10 +#define C_REL8 0x20 +#define C_REL32 0x40 +#define C_GROUP 0x80 +#define C_ERROR 0xff + +#define PRE_ANY 0x00 +#define PRE_NONE 0x01 +#define PRE_F2 0x02 +#define PRE_F3 0x04 +#define PRE_66 0x08 +#define PRE_67 0x10 +#define PRE_LOCK 0x20 +#define PRE_SEG 0x40 +#define PRE_ALL 0xff + +#define DELTA_OPCODES 0x4a +#define DELTA_FPU_REG 0xfd +#define DELTA_FPU_MODRM 0x104 +#define DELTA_PREFIXES 0x13c +#define DELTA_OP_LOCK_OK 0x1ae +#define DELTA_OP2_LOCK_OK 0x1c6 +#define DELTA_OP_ONLY_MEM 0x1d8 +#define DELTA_OP2_ONLY_MEM 0x1e7 + +unsigned char hde64_table[] = { + 0xa5,0xaa,0xa5,0xb8,0xa5,0xaa,0xa5,0xaa,0xa5,0xb8,0xa5,0xb8,0xa5,0xb8,0xa5, + 0xb8,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xac,0xc0,0xcc,0xc0,0xa1,0xa1, + 0xa1,0xa1,0xb1,0xa5,0xa5,0xa6,0xc0,0xc0,0xd7,0xda,0xe0,0xc0,0xe4,0xc0,0xea, + 0xea,0xe0,0xe0,0x98,0xc8,0xee,0xf1,0xa5,0xd3,0xa5,0xa5,0xa1,0xea,0x9e,0xc0, + 0xc0,0xc2,0xc0,0xe6,0x03,0x7f,0x11,0x7f,0x01,0x7f,0x01,0x3f,0x01,0x01,0xab, + 0x8b,0x90,0x64,0x5b,0x5b,0x5b,0x5b,0x5b,0x92,0x5b,0x5b,0x76,0x90,0x92,0x92, + 0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x6a,0x73,0x90, + 0x5b,0x52,0x52,0x52,0x52,0x5b,0x5b,0x5b,0x5b,0x77,0x7c,0x77,0x85,0x5b,0x5b, + 0x70,0x5b,0x7a,0xaf,0x76,0x76,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b, + 0x5b,0x5b,0x86,0x01,0x03,0x01,0x04,0x03,0xd5,0x03,0xd5,0x03,0xcc,0x01,0xbc, + 0x03,0xf0,0x03,0x03,0x04,0x00,0x50,0x50,0x50,0x50,0xff,0x20,0x20,0x20,0x20, + 0x01,0x01,0x01,0x01,0xc4,0x02,0x10,0xff,0xff,0xff,0x01,0x00,0x03,0x11,0xff, + 0x03,0xc4,0xc6,0xc8,0x02,0x10,0x00,0xff,0xcc,0x01,0x01,0x01,0x00,0x00,0x00, + 0x00,0x01,0x01,0x03,0x01,0xff,0xff,0xc0,0xc2,0x10,0x11,0x02,0x03,0x01,0x01, + 0x01,0xff,0xff,0xff,0x00,0x00,0x00,0xff,0x00,0x00,0xff,0xff,0xff,0xff,0x10, + 0x10,0x10,0x10,0x02,0x10,0x00,0x00,0xc6,0xc8,0x02,0x02,0x02,0x02,0x06,0x00, + 0x04,0x00,0x02,0xff,0x00,0xc0,0xc2,0x01,0x01,0x03,0x03,0x03,0xca,0x40,0x00, + 0x0a,0x00,0x04,0x00,0x00,0x00,0x00,0x7f,0x00,0x33,0x01,0x00,0x00,0x00,0x00, + 0x00,0x00,0xff,0xbf,0xff,0xff,0x00,0x00,0x00,0x00,0x07,0x00,0x00,0xff,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff, + 0x00,0x00,0x00,0xbf,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7f,0x00,0x00, + 0xff,0x40,0x40,0x40,0x40,0x41,0x49,0x40,0x40,0x40,0x40,0x4c,0x42,0x40,0x40, + 0x40,0x40,0x40,0x40,0x40,0x40,0x4f,0x44,0x53,0x40,0x40,0x40,0x44,0x57,0x43, + 0x5c,0x40,0x60,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40, + 0x40,0x40,0x64,0x66,0x6e,0x6b,0x40,0x40,0x6a,0x46,0x40,0x40,0x44,0x46,0x40, + 0x40,0x5b,0x44,0x40,0x40,0x00,0x00,0x00,0x00,0x06,0x06,0x06,0x06,0x01,0x06, + 0x06,0x02,0x06,0x06,0x00,0x06,0x00,0x0a,0x0a,0x00,0x00,0x00,0x02,0x07,0x07, + 0x06,0x02,0x0d,0x06,0x06,0x06,0x0e,0x05,0x05,0x02,0x02,0x00,0x00,0x04,0x04, + 0x04,0x04,0x05,0x06,0x06,0x06,0x00,0x00,0x00,0x0e,0x00,0x00,0x08,0x00,0x10, + 0x00,0x18,0x00,0x20,0x00,0x28,0x00,0x30,0x00,0x80,0x01,0x82,0x01,0x86,0x00, + 0xf6,0xcf,0xfe,0x3f,0xab,0x00,0xb0,0x00,0xb1,0x00,0xb3,0x00,0xba,0xf8,0xbb, + 0x00,0xc0,0x00,0xc1,0x00,0xc7,0xbf,0x62,0xff,0x00,0x8d,0xff,0x00,0xc4,0xff, + 0x00,0xc5,0xff,0x00,0xff,0xff,0xeb,0x01,0xff,0x0e,0x12,0x08,0x00,0x13,0x09, + 0x00,0x16,0x08,0x00,0x17,0x09,0x00,0x2b,0x09,0x00,0xae,0xff,0x07,0xb2,0xff, + 0x00,0xb4,0xff,0x00,0xb5,0xff,0x00,0xc3,0x01,0x00,0xc7,0xff,0xbf,0xe7,0x08, + 0x00,0xf0,0x02,0x00 +}; diff --git a/edxp-core/jni/main/native_hook/native_hook.cpp b/edxp-core/jni/main/native_hook/native_hook.cpp index 5e3021388..0c17f590c 100644 --- a/edxp-core/jni/main/native_hook/native_hook.cpp +++ b/edxp-core/jni/main/native_hook/native_hook.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include "include/logging.h" #include "native_hook.h" @@ -283,12 +284,16 @@ void install_inline_hooks() { } install_riru_hooks(); LOGI("using api level %d", api_level); +#ifdef __LP64__ void *whaleHandle = dlopen(kLibWhalePath, RTLD_LAZY | RTLD_GLOBAL); if (!whaleHandle) { LOGE("can't open libwhale: %s", dlerror()); return; } void *hookFunSym = dlsym(whaleHandle, "WInlineHookFunction"); +#else + void *hookFunSym = (void *)(MSHookFunction); +#endif if (!hookFunSym) { LOGE("can't get WInlineHookFunction: %s", dlerror()); return; @@ -309,7 +314,9 @@ void install_inline_hooks() { } else { LOGE("disableHiddenAPIPolicyImpl failed."); } +#ifdef __LP64__ dlclose(whaleHandle); +#endif dlclose(artHandle); LOGI("install inline hooks done"); }