Use x86 with Dobby and remove Cydia Substrate
This commit is contained in:
parent
df6257646c
commit
47ad6048d7
|
|
@ -3,7 +3,6 @@ cmake_minimum_required(VERSION 3.4.1)
|
|||
add_subdirectory(xhook)
|
||||
add_subdirectory(riru)
|
||||
add_subdirectory(yahfa)
|
||||
add_subdirectory(substrate)
|
||||
add_subdirectory(android)
|
||||
|
||||
macro(SET_OPTION option value)
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Subproject commit 12dc0280760f1b891b49d7c32311e7e88b4b896d
|
||||
Subproject commit 49bcf67bffb90e9cdd6790294e6f079abe468db1
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
cmake_minimum_required(VERSION 3.4.1)
|
||||
|
||||
aux_source_directory(src SRC_LIST)
|
||||
add_library(substrate STATIC ${SRC_LIST})
|
||||
|
||||
target_include_directories(substrate INTERFACE src)
|
||||
|
|
@ -1,38 +0,0 @@
|
|||
/* 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 <http://www.gnu.org/licenses/>.
|
||||
**/
|
||||
/* }}} */
|
||||
|
||||
#ifndef SUBSTRATE_BUFFER_HPP
|
||||
#define SUBSTRATE_BUFFER_HPP
|
||||
|
||||
#include <string.h>
|
||||
|
||||
template <typename Type_>
|
||||
_disused static _finline void MSWrite(uint8_t *&buffer, Type_ value) {
|
||||
*reinterpret_cast<Type_ *>(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
|
||||
|
|
@ -1,152 +0,0 @@
|
|||
/* 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 <http://www.gnu.org/licenses/>.
|
||||
**/
|
||||
/* }}} */
|
||||
|
||||
#ifndef SUBSTRATE_H_
|
||||
#define SUBSTRATE_H_
|
||||
|
||||
#ifdef __APPLE__
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#include <mach-o/nlist.h>
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#include <objc/runtime.h>
|
||||
#include <objc/message.h>
|
||||
#endif
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#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<typename Type_>
|
||||
static inline void MSHookFunction(Type_ *symbol, Type_ *replace, Type_ **result) {
|
||||
MSHookFunction(
|
||||
reinterpret_cast<void *>(symbol),
|
||||
reinterpret_cast<void *>(replace),
|
||||
reinterpret_cast<void **>(result)
|
||||
);
|
||||
}
|
||||
|
||||
template<typename Type_>
|
||||
static inline void MSHookFunction(Type_ *symbol, Type_ *replace) {
|
||||
return MSHookFunction(symbol, replace, reinterpret_cast<Type_ **>(NULL));
|
||||
}
|
||||
|
||||
template<typename Type_>
|
||||
static inline void MSHookSymbol(Type_ *&value, const char *name, MSImageRef image = NULL) {
|
||||
value = reinterpret_cast<Type_ *>(MSFindSymbol(image, name));
|
||||
}
|
||||
|
||||
template<typename Type_>
|
||||
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_
|
||||
|
|
@ -1,67 +0,0 @@
|
|||
/* 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 <http://www.gnu.org/licenses/>.
|
||||
**/
|
||||
/* }}} */
|
||||
|
||||
#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<class T> 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
|
||||
|
|
@ -1,96 +0,0 @@
|
|||
/* 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 <http://www.gnu.org/licenses/>.
|
||||
**/
|
||||
/* }}} */
|
||||
|
||||
#include "SubstrateHook.h"
|
||||
#include "SubstrateDebug.hpp"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
_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);
|
||||
}
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
/* 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 <http://www.gnu.org/licenses/>.
|
||||
**/
|
||||
/* }}} */
|
||||
|
||||
#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
|
||||
|
|
@ -1,945 +0,0 @@
|
|||
/* 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 <http://www.gnu.org/licenses/>.
|
||||
**/
|
||||
/* }}} */
|
||||
|
||||
#define SubstrateInternal
|
||||
#include "CydiaSubstrate.h"
|
||||
|
||||
#include <sys/mman.h>
|
||||
|
||||
#define _trace() do { \
|
||||
MSLog(MSLogLevelNotice, "_trace(%u)", __LINE__); \
|
||||
} while (false)
|
||||
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
#include "hde64.h"
|
||||
#endif
|
||||
|
||||
#include "SubstrateDebug.hpp"
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <cmath>
|
||||
|
||||
#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.asm >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<ms>, cd */ \
|
||||
(0xbf00 | ((cd) << 4) | (ms))
|
||||
#define T$cbz$_rn_$im(op,rn,im) /* cb<op>z rn, #im */ \
|
||||
(0xb100 | ((op) << 11) | (((im) & 0x40) >> 6 << 9) | (((im) & 0x3e) >> 1 << 3) | (rn))
|
||||
#define T$b$_$im(cond,im) /* b<cond> #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<class T> 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<uint16_t *>(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<uintptr_t>(start) & 0x1) == 0)
|
||||
return MSGetInstructionWidthARM(start);
|
||||
else
|
||||
return MSGetInstructionWidthThumb(reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(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<uint16_t *>(symbol));
|
||||
|
||||
unsigned align((reinterpret_cast<uintptr_t>(area) & 0x2) == 0 ? 0 : 1);
|
||||
uint16_t *thumb(area + align);
|
||||
|
||||
uint32_t *arm(reinterpret_cast<uint32_t *>(thumb + 2));
|
||||
uint16_t *trail(reinterpret_cast<uint16_t *>(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<void *>(arm[1]);
|
||||
|
||||
SubstrateHookMemory code(process, arm + 1, sizeof(uint32_t) * 1);
|
||||
|
||||
arm[1] = reinterpret_cast<uint32_t>(replace);
|
||||
|
||||
return sizeof(arm[0]);
|
||||
}
|
||||
|
||||
size_t required((trail - area) * sizeof(uint16_t));
|
||||
|
||||
size_t used(0);
|
||||
while (used < required)
|
||||
used += MSGetInstructionWidthThumb(reinterpret_cast<uint8_t *>(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<uint16_t *>(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<uint32_t *>(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<uint32_t>(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<uint32_t>(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<uint32_t>(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<uint32_t>(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<uint32_t>(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<uint32_t *>(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<uint32_t>(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<uint32_t>(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<uint32_t *>(buffer + start);
|
||||
transfer[0] = A$ldr_rd_$rn_im$(A$pc, A$pc, 4 - 8);
|
||||
transfer[1] = reinterpret_cast<uint32_t>(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<uint8_t *>(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<uint32_t>(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<uint32_t *>(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<void *>(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<uint32_t *>(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<uint32_t *>(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<uint32_t>(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<uint32_t>(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<uint32_t>(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<uintptr_t>(symbol) & 0x1) == 0)
|
||||
return SubstrateHookFunctionARM(process, symbol, replace, result);
|
||||
else
|
||||
return SubstrateHookFunctionThumb(process, reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(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<uintptr_t>(symbol));
|
||||
uintptr_t target(reinterpret_cast<uintptr_t>(replace));
|
||||
|
||||
uint8_t *area(reinterpret_cast<uint8_t *>(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<void *>(source + 5 + *reinterpret_cast<uint32_t *>(backup + 1));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ia32 && backup[0] == 0xff && backup[1] == 0x25) {
|
||||
*result = *reinterpret_cast<void **>(source + 6 + *reinterpret_cast<uint32_t *>(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<int32_t *>(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<int8_t *>(backup + offset + 1));
|
||||
} else if (backup[offset] == 0xe9) {
|
||||
length -= decode.len;
|
||||
length += MSSizeOfJump(area + offset + decode.len + *reinterpret_cast<int32_t *>(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<int8_t *>(backup + offset + 1));
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t *buffer(reinterpret_cast<uint8_t *>(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<int32_t *>(backup + offset + 1));
|
||||
if (relative == 0)
|
||||
MSPushPointer(current, area + offset + decode.len);
|
||||
else {
|
||||
MSWrite<uint8_t>(current, 0xe8);
|
||||
MSWrite<int32_t>(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<int8_t *>(backup + offset + 1));
|
||||
else if (backup[offset] == 0xe9)
|
||||
MSWriteJump(current, area + offset + decode.len + *reinterpret_cast<int32_t *>(backup + offset + 1));
|
||||
else if (
|
||||
backup[offset] == 0xe3 ||
|
||||
(backup[offset] & 0xf0) == 0x70
|
||||
) {
|
||||
MSWrite<uint8_t>(current, backup[offset]);
|
||||
MSWrite<uint8_t>(current, 2);
|
||||
MSWrite<uint8_t>(current, 0xeb);
|
||||
void *destiny(area + offset + decode.len + *reinterpret_cast<int8_t *>(backup + offset + 1));
|
||||
MSWrite<uint8_t>(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<uint8_t>(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
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
#ifndef __SUBSTRATEHOOK_H__
|
||||
#define __SUBSTRATEHOOK_H__
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#define _extern extern "C" __attribute__((__visibility__("default")))
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void MSHookFunction(void *symbol, void *replace, void **result);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
@ -1,40 +0,0 @@
|
|||
/* 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 <http://www.gnu.org/licenses/>.
|
||||
**/
|
||||
/* }}} */
|
||||
|
||||
#ifndef SUBSTRATE_LOG_HPP
|
||||
#define SUBSTRATE_LOG_HPP
|
||||
|
||||
#if 0
|
||||
#include <android/log.h>
|
||||
|
||||
#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
|
||||
|
|
@ -1,75 +0,0 @@
|
|||
/* 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 <http://www.gnu.org/licenses/>.
|
||||
**/
|
||||
/* }}} */
|
||||
|
||||
#define SubstrateInternal
|
||||
#include "CydiaSubstrate.h"
|
||||
#include "SubstrateLog.hpp"
|
||||
|
||||
#include <sys/mman.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
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<uintptr_t>(data) / page * page);
|
||||
size_t width(((reinterpret_cast<uintptr_t>(data) + size - 1) / page + 1) * page - base);
|
||||
void *address(reinterpret_cast<void *>(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<char *>(memory->address_), reinterpret_cast<char *>(memory->address_) + memory->width_);
|
||||
|
||||
delete memory;
|
||||
}
|
||||
|
|
@ -1,200 +0,0 @@
|
|||
/* 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 <http://www.gnu.org/licenses/>.
|
||||
**/
|
||||
/* }}} */
|
||||
|
||||
#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<uintptr_t>(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<uintptr_t>(target), reinterpret_cast<uintptr_t>(source));
|
||||
}
|
||||
|
||||
_disused static size_t MSSizeOfJump(void *target) {
|
||||
return MSSizeOfJump(reinterpret_cast<uintptr_t>(target));
|
||||
}
|
||||
|
||||
_disused static void MSWriteSkip(uint8_t *¤t, ssize_t size) {
|
||||
MSWrite<uint8_t>(current, 0xe9);
|
||||
MSWrite<uint32_t>(current, size);
|
||||
}
|
||||
|
||||
_disused static void MSPushPointer(uint8_t *¤t, uintptr_t target) {
|
||||
MSWrite<uint8_t>(current, 0x68);
|
||||
MSWrite<uint32_t>(current, target);
|
||||
|
||||
if (uint32_t high = uint64_t(target) >> 32) {
|
||||
MSWrite<uint8_t>(current, 0xc7);
|
||||
MSWrite<uint8_t>(current, 0x44);
|
||||
MSWrite<uint8_t>(current, 0x24);
|
||||
MSWrite<uint8_t>(current, 0x04);
|
||||
MSWrite<uint32_t>(current, high);
|
||||
}
|
||||
}
|
||||
|
||||
_disused static void MSPushPointer(uint8_t *¤t, void *target) {
|
||||
return MSPushPointer(current, reinterpret_cast<uintptr_t>(target));
|
||||
}
|
||||
|
||||
_disused static void MSWriteCall(uint8_t *¤t, I$r target) {
|
||||
if (target >> 3 != 0)
|
||||
MSWrite<uint8_t>(current, 0x40 | (target & 0x08) >> 3);
|
||||
MSWrite<uint8_t>(current, 0xff);
|
||||
MSWrite<uint8_t>(current, 0xd0 | target & 0x07);
|
||||
}
|
||||
|
||||
_disused static void MSWriteCall(uint8_t *¤t, uintptr_t target) {
|
||||
uintptr_t source(reinterpret_cast<uintptr_t>(current));
|
||||
|
||||
if (ia32 || MSIs32BitOffset(target, source + 5)) {
|
||||
MSWrite<uint8_t>(current, 0xe8);
|
||||
MSWrite<uint32_t>(current, target - (source + 5));
|
||||
} else {
|
||||
MSPushPointer(current, target);
|
||||
|
||||
MSWrite<uint8_t>(current, 0x83);
|
||||
MSWrite<uint8_t>(current, 0xc4);
|
||||
MSWrite<uint8_t>(current, 0x08);
|
||||
|
||||
MSWrite<uint8_t>(current, 0x67);
|
||||
MSWrite<uint8_t>(current, 0xff);
|
||||
MSWrite<uint8_t>(current, 0x54);
|
||||
MSWrite<uint8_t>(current, 0x24);
|
||||
MSWrite<uint8_t>(current, 0xf8);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Type_>
|
||||
_disused static void MSWriteCall(uint8_t *¤t, Type_ *target) {
|
||||
return MSWriteCall(current, reinterpret_cast<uintptr_t>(target));
|
||||
}
|
||||
|
||||
_disused static void MSWriteJump(uint8_t *¤t, uintptr_t target) {
|
||||
uintptr_t source(reinterpret_cast<uintptr_t>(current));
|
||||
|
||||
if (ia32 || MSIs32BitOffset(target, source + 5))
|
||||
MSWriteSkip(current, target - (source + 5));
|
||||
else {
|
||||
MSPushPointer(current, target);
|
||||
MSWrite<uint8_t>(current, 0xc3);
|
||||
}
|
||||
}
|
||||
|
||||
_disused static void MSWriteJump(uint8_t *¤t, void *target) {
|
||||
return MSWriteJump(current, reinterpret_cast<uintptr_t>(target));
|
||||
}
|
||||
|
||||
_disused static void MSWriteJump(uint8_t *¤t, I$r target) {
|
||||
if (target >> 3 != 0)
|
||||
MSWrite<uint8_t>(current, 0x40 | (target & 0x08) >> 3);
|
||||
MSWrite<uint8_t>(current, 0xff);
|
||||
MSWrite<uint8_t>(current, 0xe0 | target & 0x07);
|
||||
}
|
||||
|
||||
_disused static void MSWritePop(uint8_t *¤t, uint8_t target) {
|
||||
if (target >> 3 != 0)
|
||||
MSWrite<uint8_t>(current, 0x40 | (target & 0x08) >> 3);
|
||||
MSWrite<uint8_t>(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<uint8_t>(current, 0x40 | (target & 0x08) >> 3);
|
||||
MSWrite<uint8_t>(current, 0x50 | target & 0x07);
|
||||
}
|
||||
|
||||
_disused static void MSWriteAdd(uint8_t *¤t, I$r target, uint8_t source) {
|
||||
MSWrite<uint8_t>(current, 0x83);
|
||||
MSWrite<uint8_t>(current, 0xc4 | target & 0x07);
|
||||
MSWrite<uint8_t>(current, source);
|
||||
}
|
||||
|
||||
_disused static void MSWriteSet64(uint8_t *¤t, I$r target, uintptr_t source) {
|
||||
MSWrite<uint8_t>(current, 0x48 | (target & 0x08) >> 3 << 2);
|
||||
MSWrite<uint8_t>(current, 0xb8 | target & 0x7);
|
||||
MSWrite<uint64_t>(current, source);
|
||||
}
|
||||
|
||||
template <typename Type_>
|
||||
_disused static void MSWriteSet64(uint8_t *¤t, I$r target, Type_ *source) {
|
||||
return MSWriteSet64(current, target, reinterpret_cast<uintptr_t>(source));
|
||||
}
|
||||
|
||||
_disused static void MSWriteMove64(uint8_t *¤t, uint8_t source, uint8_t target) {
|
||||
MSWrite<uint8_t>(current, 0x48 | (target & 0x08) >> 3 << 2 | (source & 0x08) >> 3);
|
||||
MSWrite<uint8_t>(current, 0x8b);
|
||||
MSWrite<uint8_t>(current, (target & 0x07) << 3 | source & 0x07);
|
||||
}
|
||||
|
||||
_disused static size_t MSSizeOfMove64() {
|
||||
return 3;
|
||||
}
|
||||
|
||||
#endif//SUBSTRATE_X86_HPP
|
||||
|
|
@ -1,332 +0,0 @@
|
|||
/*
|
||||
* Hacker Disassembler Engine 64 C
|
||||
* Copyright (c) 2008-2009, Vyacheslav Patkov.
|
||||
* All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
|
|
@ -1,112 +0,0 @@
|
|||
/*
|
||||
* 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 <stdint.h>
|
||||
|
||||
#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_ */
|
||||
|
|
@ -1,74 +0,0 @@
|
|||
/*
|
||||
* 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
|
||||
};
|
||||
|
|
@ -8,4 +8,4 @@ include_directories(include src)
|
|||
add_library(riru_edxp SHARED ${SRC_LIST} ${SRC_JNI_LIST})
|
||||
|
||||
find_library(log-lib log)
|
||||
target_link_libraries(riru_edxp yahfa riru xhook substrate android dobby ${log-lib})
|
||||
target_link_libraries(riru_edxp yahfa riru xhook android dobby ${log-lib})
|
||||
|
|
@ -3,7 +3,6 @@
|
|||
#include <android_build.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <SubstrateHook.h>
|
||||
#include <config_manager.h>
|
||||
#include <art/runtime/runtime.h>
|
||||
#include <dl_util.h>
|
||||
|
|
@ -48,15 +47,7 @@ namespace edxp {
|
|||
}
|
||||
LOGI("Using api level %d", api_level);
|
||||
InstallRiruHooks();
|
||||
#ifndef __i386__ // Dobby doesn't support x86 for now
|
||||
void *hook_func_symbol = (void *)DobbyHook;
|
||||
#else
|
||||
void *hook_func_symbol = (void *) MSHookFunction;
|
||||
#endif
|
||||
if (!hook_func_symbol) {
|
||||
return;
|
||||
}
|
||||
hook_func = reinterpret_cast<HookFunType>(hook_func_symbol);
|
||||
hook_func = reinterpret_cast<HookFunType>(DobbyHook);
|
||||
|
||||
// install ART hooks
|
||||
if (api_level >= __ANDROID_API_Q__) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue