update code
This commit is contained in:
parent
419b5c7b6b
commit
41714fff62
|
@ -0,0 +1,4 @@
|
|||
@echo off
|
||||
adb push libs/armeabi-v7a/libpsmkdc_jni.so /data/local/tmp/libpsmkdc_jni.so
|
||||
adb shell "su -c 'mount -o rw,remount /system /system;mount -o rw,remount /data /data;cat /data/local/tmp/libpsmkdc_jni.so>/data/data/com.playstation.psstore/lib/libpsmkdc_jni.so'"
|
||||
adb shell "rm /data/local/tmp/libpsmkdc_jni.so"
|
|
@ -8,10 +8,12 @@ LOCAL_CFLAGS += -fno-rtti -fno-exceptions
|
|||
|
||||
LOCAL_C_INCLUDES += $(MAIN_LOCAL_PATH)
|
||||
|
||||
LOCAL_SRC_FILES := psmkdc_jni.cpp \
|
||||
nopsmdrm.cpp
|
||||
LOCAL_SRC_FILES := psmkdc_jni.c \
|
||||
nopsmdrm.c \
|
||||
hooks/inlineHook.c \
|
||||
hooks/relocate.c
|
||||
|
||||
|
||||
LOCAL_LDLIBS := -llog -landroid
|
||||
LOCAL_LDLIBS := -llog -landroid -lc
|
||||
|
||||
include $(BUILD_SHARED_LIBRARY)
|
|
@ -0,0 +1,424 @@
|
|||
/*
|
||||
thumb16 thumb32 arm32 inlineHook
|
||||
author: ele7enxxh
|
||||
mail: ele7enxxh@qq.com
|
||||
website: ele7enxxh.com
|
||||
modified time: 2015-01-23
|
||||
created time: 2015-11-30
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <dirent.h>
|
||||
#include <signal.h>
|
||||
#include <sys/mman.h>
|
||||
// #include <asm/ptrace.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/ptrace.h>
|
||||
|
||||
#include "relocate.h"
|
||||
#include "inlineHook.h"
|
||||
|
||||
#ifndef PAGE_SIZE
|
||||
#define PAGE_SIZE 4096
|
||||
#endif
|
||||
|
||||
#define PAGE_START(addr) (~(PAGE_SIZE - 1) & (addr))
|
||||
#define SET_BIT0(addr) (addr | 1)
|
||||
#define CLEAR_BIT0(addr) (addr & 0xFFFFFFFE)
|
||||
#define TEST_BIT0(addr) (addr & 1)
|
||||
|
||||
#define ACTION_ENABLE 0
|
||||
#define ACTION_DISABLE 1
|
||||
|
||||
enum hook_status {
|
||||
REGISTERED,
|
||||
HOOKED,
|
||||
};
|
||||
|
||||
struct inlineHookItem {
|
||||
uint32_t target_addr;
|
||||
uint32_t new_addr;
|
||||
uint32_t **proto_addr;
|
||||
void *orig_instructions;
|
||||
int orig_boundaries[4];
|
||||
int trampoline_boundaries[20];
|
||||
int count;
|
||||
void *trampoline_instructions;
|
||||
int length;
|
||||
int status;
|
||||
int mode;
|
||||
};
|
||||
|
||||
struct inlineHookInfo {
|
||||
struct inlineHookItem item[1024];
|
||||
int size;
|
||||
};
|
||||
|
||||
static struct inlineHookInfo info = {0};
|
||||
|
||||
static int getAllTids(pid_t exclude_tid, pid_t *tids)
|
||||
{
|
||||
char dir_path[32];
|
||||
DIR *dir;
|
||||
int i;
|
||||
struct dirent *entry;
|
||||
pid_t tid;
|
||||
|
||||
if (exclude_tid < 0) {
|
||||
snprintf(dir_path, sizeof(dir_path), "/proc/self/task");
|
||||
}
|
||||
else {
|
||||
snprintf(dir_path, sizeof(dir_path), "/proc/%d/task", exclude_tid);
|
||||
}
|
||||
|
||||
dir = opendir(dir_path);
|
||||
if (dir == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
i = 0;
|
||||
while((entry = readdir(dir)) != NULL) {
|
||||
tid = atoi(entry->d_name);
|
||||
if (tid != 0 && tid != exclude_tid) {
|
||||
tids[i++] = tid;
|
||||
}
|
||||
}
|
||||
closedir(dir);
|
||||
return i;
|
||||
}
|
||||
|
||||
static bool doProcessThreadPC(struct inlineHookItem *item, struct pt_regs *regs, int action)
|
||||
{
|
||||
int offset;
|
||||
int i;
|
||||
|
||||
switch (action)
|
||||
{
|
||||
case ACTION_ENABLE:
|
||||
offset = regs->ARM_pc - CLEAR_BIT0(item->target_addr);
|
||||
for (i = 0; i < item->count; ++i) {
|
||||
if (offset == item->orig_boundaries[i]) {
|
||||
regs->ARM_pc = (uint32_t) item->trampoline_instructions + item->trampoline_boundaries[i];
|
||||
return true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ACTION_DISABLE:
|
||||
offset = regs->ARM_pc - (int) item->trampoline_instructions;
|
||||
for (i = 0; i < item->count; ++i) {
|
||||
if (offset == item->trampoline_boundaries[i]) {
|
||||
regs->ARM_pc = CLEAR_BIT0(item->target_addr) + item->orig_boundaries[i];
|
||||
return true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void processThreadPC(pid_t tid, struct inlineHookItem *item, int action)
|
||||
{
|
||||
struct pt_regs regs;
|
||||
|
||||
if (ptrace(PTRACE_GETREGS, tid, NULL, ®s) == 0) {
|
||||
if (item == NULL) {
|
||||
int pos;
|
||||
|
||||
for (pos = 0; pos < info.size; ++pos) {
|
||||
if (doProcessThreadPC(&info.item[pos], ®s, action) == true) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
doProcessThreadPC(item, ®s, action);
|
||||
}
|
||||
|
||||
ptrace(PTRACE_SETREGS, tid, NULL, ®s);
|
||||
}
|
||||
}
|
||||
|
||||
static pid_t freeze(struct inlineHookItem *item, int action)
|
||||
{
|
||||
int count;
|
||||
pid_t tids[1024];
|
||||
pid_t pid;
|
||||
|
||||
pid = -1;
|
||||
count = getAllTids(gettid(), tids);
|
||||
if (count > 0) {
|
||||
pid = fork();
|
||||
|
||||
if (pid == 0) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < count; ++i) {
|
||||
if (ptrace(PTRACE_ATTACH, tids[i], NULL, NULL) == 0) {
|
||||
waitpid(tids[i], NULL, WUNTRACED);
|
||||
processThreadPC(tids[i], item, action);
|
||||
}
|
||||
}
|
||||
|
||||
raise(SIGSTOP);
|
||||
|
||||
for (i = 0; i < count; ++i) {
|
||||
ptrace(PTRACE_DETACH, tids[i], NULL, NULL);
|
||||
}
|
||||
|
||||
raise(SIGKILL);
|
||||
}
|
||||
|
||||
else if (pid > 0) {
|
||||
waitpid(pid, NULL, WUNTRACED);
|
||||
}
|
||||
}
|
||||
|
||||
return pid;
|
||||
}
|
||||
|
||||
static void unFreeze(pid_t pid)
|
||||
{
|
||||
if (pid < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
kill(pid, SIGCONT);
|
||||
wait(NULL);
|
||||
}
|
||||
|
||||
static bool isExecutableAddr(uint32_t addr)
|
||||
{
|
||||
FILE *fp;
|
||||
char line[1024];
|
||||
uint32_t start;
|
||||
uint32_t end;
|
||||
|
||||
fp = fopen("/proc/self/maps", "r");
|
||||
if (fp == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
while (fgets(line, sizeof(line), fp)) {
|
||||
if (strstr(line, "r-xp") || strstr(line, "rwxp")) {
|
||||
start = strtoul(strtok(line, "-"), NULL, 16);
|
||||
end = strtoul(strtok(NULL, " "), NULL, 16);
|
||||
if (addr >= start && addr <= end) {
|
||||
fclose(fp);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static struct inlineHookItem *findInlineHookItem(uint32_t target_addr)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < info.size; ++i) {
|
||||
if (info.item[i].target_addr == target_addr) {
|
||||
return &info.item[i];
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct inlineHookItem *addInlineHookItem() {
|
||||
struct inlineHookItem *item;
|
||||
|
||||
if (info.size >= 1024) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
item = &info.item[info.size];
|
||||
++info.size;
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
static void deleteInlineHookItem(int pos)
|
||||
{
|
||||
info.item[pos] = info.item[info.size - 1];
|
||||
--info.size;
|
||||
}
|
||||
|
||||
enum ele7en_status registerInlineHook(uint32_t target_addr, uint32_t new_addr, uint32_t **proto_addr)
|
||||
{
|
||||
struct inlineHookItem *item;
|
||||
|
||||
if (!isExecutableAddr(target_addr) || !isExecutableAddr(new_addr)) {
|
||||
return ELE7EN_ERROR_NOT_EXECUTABLE;
|
||||
}
|
||||
|
||||
item = findInlineHookItem(target_addr);
|
||||
if (item != NULL) {
|
||||
if (item->status == REGISTERED) {
|
||||
return ELE7EN_ERROR_ALREADY_REGISTERED;
|
||||
}
|
||||
else if (item->status == HOOKED) {
|
||||
return ELE7EN_ERROR_ALREADY_HOOKED;
|
||||
}
|
||||
else {
|
||||
return ELE7EN_ERROR_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
item = addInlineHookItem();
|
||||
|
||||
item->target_addr = target_addr;
|
||||
item->new_addr = new_addr;
|
||||
item->proto_addr = proto_addr;
|
||||
|
||||
item->length = TEST_BIT0(item->target_addr) ? 12 : 8;
|
||||
item->orig_instructions = malloc(item->length);
|
||||
memcpy(item->orig_instructions, (void *) CLEAR_BIT0(item->target_addr), item->length);
|
||||
|
||||
item->trampoline_instructions = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANONYMOUS | MAP_PRIVATE, 0, 0);
|
||||
relocateInstruction(item->target_addr, item->orig_instructions, item->length, item->trampoline_instructions, item->orig_boundaries, item->trampoline_boundaries, &item->count);
|
||||
|
||||
item->status = REGISTERED;
|
||||
|
||||
return ELE7EN_OK;
|
||||
}
|
||||
|
||||
static void doInlineUnHook(struct inlineHookItem *item, int pos)
|
||||
{
|
||||
mprotect((void *) PAGE_START(CLEAR_BIT0(item->target_addr)), PAGE_SIZE * 2, PROT_READ | PROT_WRITE | PROT_EXEC);
|
||||
memcpy((void *) CLEAR_BIT0(item->target_addr), item->orig_instructions, item->length);
|
||||
mprotect((void *) PAGE_START(CLEAR_BIT0(item->target_addr)), PAGE_SIZE * 2, PROT_READ | PROT_EXEC);
|
||||
munmap(item->trampoline_instructions, PAGE_SIZE);
|
||||
free(item->orig_instructions);
|
||||
|
||||
deleteInlineHookItem(pos);
|
||||
|
||||
cacheflush(CLEAR_BIT0(item->target_addr), CLEAR_BIT0(item->target_addr) + item->length, 0);
|
||||
}
|
||||
|
||||
enum ele7en_status inlineUnHook(uint32_t target_addr)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < info.size; ++i) {
|
||||
if (info.item[i].target_addr == target_addr && info.item[i].status == HOOKED) {
|
||||
pid_t pid;
|
||||
|
||||
pid = freeze(&info.item[i], ACTION_DISABLE);
|
||||
|
||||
doInlineUnHook(&info.item[i], i);
|
||||
|
||||
unFreeze(pid);
|
||||
|
||||
return ELE7EN_OK;
|
||||
}
|
||||
}
|
||||
|
||||
return ELE7EN_ERROR_NOT_HOOKED;
|
||||
}
|
||||
|
||||
void inlineUnHookAll()
|
||||
{
|
||||
pid_t pid;
|
||||
int i;
|
||||
|
||||
pid = freeze(NULL, ACTION_DISABLE);
|
||||
|
||||
for (i = 0; i < info.size; ++i) {
|
||||
if (info.item[i].status == HOOKED) {
|
||||
doInlineUnHook(&info.item[i], i);
|
||||
--i;
|
||||
}
|
||||
}
|
||||
|
||||
unFreeze(pid);
|
||||
}
|
||||
|
||||
static void doInlineHook(struct inlineHookItem *item)
|
||||
{
|
||||
mprotect((void *) PAGE_START(CLEAR_BIT0(item->target_addr)), PAGE_SIZE * 2, PROT_READ | PROT_WRITE | PROT_EXEC);
|
||||
|
||||
if (item->proto_addr != NULL) {
|
||||
*(item->proto_addr) = TEST_BIT0(item->target_addr) ? (uint32_t *) SET_BIT0((uint32_t) item->trampoline_instructions) : item->trampoline_instructions;
|
||||
}
|
||||
|
||||
if (TEST_BIT0(item->target_addr)) {
|
||||
int i;
|
||||
|
||||
i = 0;
|
||||
if (CLEAR_BIT0(item->target_addr) % 4 != 0) {
|
||||
((uint16_t *) CLEAR_BIT0(item->target_addr))[i++] = 0xBF00; // NOP
|
||||
}
|
||||
((uint16_t *) CLEAR_BIT0(item->target_addr))[i++] = 0xF8DF;
|
||||
((uint16_t *) CLEAR_BIT0(item->target_addr))[i++] = 0xF000; // LDR.W PC, [PC]
|
||||
((uint16_t *) CLEAR_BIT0(item->target_addr))[i++] = item->new_addr & 0xFFFF;
|
||||
((uint16_t *) CLEAR_BIT0(item->target_addr))[i++] = item->new_addr >> 16;
|
||||
}
|
||||
else {
|
||||
((uint32_t *) (item->target_addr))[0] = 0xe51ff004; // LDR PC, [PC, #-4]
|
||||
((uint32_t *) (item->target_addr))[1] = item->new_addr;
|
||||
}
|
||||
|
||||
mprotect((void *) PAGE_START(CLEAR_BIT0(item->target_addr)), PAGE_SIZE * 2, PROT_READ | PROT_EXEC);
|
||||
|
||||
item->status = HOOKED;
|
||||
|
||||
cacheflush(CLEAR_BIT0(item->target_addr), CLEAR_BIT0(item->target_addr) + item->length, 0);
|
||||
}
|
||||
|
||||
enum ele7en_status inlineHook(uint32_t target_addr)
|
||||
{
|
||||
int i;
|
||||
struct inlineHookItem *item;
|
||||
|
||||
item = NULL;
|
||||
for (i = 0; i < info.size; ++i) {
|
||||
if (info.item[i].target_addr == target_addr) {
|
||||
item = &info.item[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (item == NULL) {
|
||||
return ELE7EN_ERROR_NOT_REGISTERED;
|
||||
}
|
||||
|
||||
if (item->status == REGISTERED) {
|
||||
pid_t pid;
|
||||
|
||||
pid = freeze(item, ACTION_ENABLE);
|
||||
|
||||
doInlineHook(item);
|
||||
|
||||
unFreeze(pid);
|
||||
|
||||
return ELE7EN_OK;
|
||||
}
|
||||
else if (item->status == HOOKED) {
|
||||
return ELE7EN_ERROR_ALREADY_HOOKED;
|
||||
}
|
||||
else {
|
||||
return ELE7EN_ERROR_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
void inlineHookAll()
|
||||
{
|
||||
pid_t pid;
|
||||
int i;
|
||||
|
||||
pid = freeze(NULL, ACTION_ENABLE);
|
||||
|
||||
for (i = 0; i < info.size; ++i) {
|
||||
if (info.item[i].status == REGISTERED) {
|
||||
doInlineHook(&info.item[i]);
|
||||
}
|
||||
}
|
||||
|
||||
unFreeze(pid);
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
#ifndef _INLINEHOOK_H
|
||||
#define _INLINEHOOK_H
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
enum ele7en_status {
|
||||
ELE7EN_ERROR_UNKNOWN = -1,
|
||||
ELE7EN_OK = 0,
|
||||
ELE7EN_ERROR_NOT_INITIALIZED,
|
||||
ELE7EN_ERROR_NOT_EXECUTABLE,
|
||||
ELE7EN_ERROR_NOT_REGISTERED,
|
||||
ELE7EN_ERROR_NOT_HOOKED,
|
||||
ELE7EN_ERROR_ALREADY_REGISTERED,
|
||||
ELE7EN_ERROR_ALREADY_HOOKED,
|
||||
ELE7EN_ERROR_SO_NOT_FOUND,
|
||||
ELE7EN_ERROR_FUNCTION_NOT_FOUND
|
||||
};
|
||||
|
||||
enum ele7en_status registerInlineHook(uint32_t target_addr, uint32_t new_addr, uint32_t **proto_addr);
|
||||
enum ele7en_status inlineUnHook(uint32_t target_addr);
|
||||
void inlineUnHookAll();
|
||||
enum ele7en_status inlineHook(uint32_t target_addr);
|
||||
void inlineHookAll();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,621 @@
|
|||
/*
|
||||
relocate instruction
|
||||
author: ele7enxxh
|
||||
mail: ele7enxxh@qq.com
|
||||
website: ele7enxxh.com
|
||||
modified time: 2016-10-17
|
||||
created time: 2015-01-17
|
||||
*/
|
||||
|
||||
#include "relocate.h"
|
||||
|
||||
#define ALIGN_PC(pc) (pc & 0xFFFFFFFC)
|
||||
|
||||
enum INSTRUCTION_TYPE {
|
||||
// B <label>
|
||||
B1_THUMB16,
|
||||
// B <label>
|
||||
B2_THUMB16,
|
||||
// BX PC
|
||||
BX_THUMB16,
|
||||
// ADD <Rdn>, PC (Rd != PC, Rn != PC) 在对ADD进行修正时,采用了替换PC为Rr的方法,当Rd也为PC时,由于之前更改了Rr的值,可能会影响跳转后的正常功能。
|
||||
ADD_THUMB16,
|
||||
// MOV Rd, PC
|
||||
MOV_THUMB16,
|
||||
// ADR Rd, <label>
|
||||
ADR_THUMB16,
|
||||
// LDR Rt, <label>
|
||||
LDR_THUMB16,
|
||||
|
||||
// CB{N}Z <Rn>, <label>
|
||||
CB_THUMB16,
|
||||
|
||||
|
||||
// BLX <label>
|
||||
BLX_THUMB32,
|
||||
// BL <label>
|
||||
BL_THUMB32,
|
||||
// B.W <label>
|
||||
B1_THUMB32,
|
||||
// B.W <label>
|
||||
B2_THUMB32,
|
||||
// ADR.W Rd, <label>
|
||||
ADR1_THUMB32,
|
||||
// ADR.W Rd, <label>
|
||||
ADR2_THUMB32,
|
||||
// LDR.W Rt, <label>
|
||||
LDR_THUMB32,
|
||||
// TBB [PC, Rm]
|
||||
TBB_THUMB32,
|
||||
// TBH [PC, Rm, LSL #1]
|
||||
TBH_THUMB32,
|
||||
|
||||
// BLX <label>
|
||||
BLX_ARM,
|
||||
// BL <label>
|
||||
BL_ARM,
|
||||
// B <label>
|
||||
B_ARM,
|
||||
// BX PC
|
||||
BX_ARM,
|
||||
// ADD Rd, PC, Rm (Rd != PC, Rm != PC) 在对ADD进行修正时,采用了替换PC为Rr的方法,当Rd也为PC时,由于之前更改了Rr的值,可能会影响跳转后的正常功能;实际汇编中没有发现Rm也为PC的情况,故未做处理。
|
||||
ADD_ARM,
|
||||
// ADR Rd, <label>
|
||||
ADR1_ARM,
|
||||
// ADR Rd, <label>
|
||||
ADR2_ARM,
|
||||
// MOV Rd, PC
|
||||
MOV_ARM,
|
||||
// LDR Rt, <label>
|
||||
LDR_ARM,
|
||||
|
||||
UNDEFINE,
|
||||
};
|
||||
|
||||
static int getTypeInThumb16(uint16_t instruction)
|
||||
{
|
||||
if ((instruction & 0xF000) == 0xD000) {
|
||||
return B1_THUMB16;
|
||||
}
|
||||
if ((instruction & 0xF800) == 0xE000) {
|
||||
return B2_THUMB16;
|
||||
}
|
||||
if ((instruction & 0xFFF8) == 0x4778) {
|
||||
return BX_THUMB16;
|
||||
}
|
||||
if ((instruction & 0xFF78) == 0x4478) {
|
||||
return ADD_THUMB16;
|
||||
}
|
||||
if ((instruction & 0xFF78) == 0x4678) {
|
||||
return MOV_THUMB16;
|
||||
}
|
||||
if ((instruction & 0xF800) == 0xA000) {
|
||||
return ADR_THUMB16;
|
||||
}
|
||||
if ((instruction & 0xF800) == 0x4800) {
|
||||
return LDR_THUMB16;
|
||||
}
|
||||
if ((instruction & 0xF500) == 0xB100) {
|
||||
return CB_THUMB16;
|
||||
}
|
||||
return UNDEFINE;
|
||||
}
|
||||
|
||||
static int getTypeInThumb32(uint32_t instruction)
|
||||
{
|
||||
if ((instruction & 0xFFF0D000) == 0xF3B08000){
|
||||
// `special control operations`(eg: `DMB.W ISH`)
|
||||
// must be placed before `if ((instruction & 0xF800D000) == 0xF0008000)`
|
||||
return UNDEFINE;
|
||||
}
|
||||
if ((instruction & 0xF800D000) == 0xF000C000) {
|
||||
return BLX_THUMB32;
|
||||
}
|
||||
if ((instruction & 0xF800D000) == 0xF000D000) {
|
||||
return BL_THUMB32;
|
||||
}
|
||||
if ((instruction & 0xF800D000) == 0xF0008000) {
|
||||
return B1_THUMB32;
|
||||
}
|
||||
if ((instruction & 0xF800D000) == 0xF0009000) {
|
||||
return B2_THUMB32;
|
||||
}
|
||||
if ((instruction & 0xFBFF8000) == 0xF2AF0000) {
|
||||
return ADR1_THUMB32;
|
||||
}
|
||||
if ((instruction & 0xFBFF8000) == 0xF20F0000) {
|
||||
return ADR2_THUMB32;
|
||||
}
|
||||
if ((instruction & 0xFF7F0000) == 0xF85F0000) {
|
||||
return LDR_THUMB32;
|
||||
}
|
||||
if ((instruction & 0xFFFF00F0) == 0xE8DF0000) {
|
||||
return TBB_THUMB32;
|
||||
}
|
||||
if ((instruction & 0xFFFF00F0) == 0xE8DF0010) {
|
||||
return TBH_THUMB32;
|
||||
}
|
||||
return UNDEFINE;
|
||||
}
|
||||
|
||||
static int getTypeInArm(uint32_t instruction)
|
||||
{
|
||||
if ((instruction & 0xFE000000) == 0xFA000000) {
|
||||
return BLX_ARM;
|
||||
}
|
||||
if ((instruction & 0xF000000) == 0xB000000) {
|
||||
return BL_ARM;
|
||||
}
|
||||
if ((instruction & 0xF000000) == 0xA000000) {
|
||||
return B_ARM;
|
||||
}
|
||||
if ((instruction & 0xFF000FF) == 0x120001F) {
|
||||
return BX_ARM;
|
||||
}
|
||||
if ((instruction & 0xFEF0010) == 0x8F0000) {
|
||||
return ADD_ARM;
|
||||
}
|
||||
if ((instruction & 0xFFF0000) == 0x28F0000) {
|
||||
return ADR1_ARM;
|
||||
}
|
||||
if ((instruction & 0xFFF0000) == 0x24F0000) {
|
||||
return ADR2_ARM;
|
||||
}
|
||||
if ((instruction & 0xE5F0000) == 0x41F0000) {
|
||||
return LDR_ARM;
|
||||
}
|
||||
if ((instruction & 0xFE00FFF) == 0x1A0000F) {
|
||||
return MOV_ARM;
|
||||
}
|
||||
return UNDEFINE;
|
||||
}
|
||||
|
||||
static int relocateInstructionInThumb16(uint32_t pc, uint16_t instruction, uint16_t *trampoline_instructions)
|
||||
{
|
||||
int type;
|
||||
int offset;
|
||||
|
||||
type = getTypeInThumb16(instruction);
|
||||
if (type == B1_THUMB16 || type == B2_THUMB16 || type == BX_THUMB16) {
|
||||
uint32_t x;
|
||||
int top_bit;
|
||||
uint32_t imm32;
|
||||
uint32_t value;
|
||||
int idx;
|
||||
|
||||
idx = 0;
|
||||
if (type == B1_THUMB16) {
|
||||
x = (instruction & 0xFF) << 1;
|
||||
top_bit = x >> 8;
|
||||
imm32 = top_bit ? (x | (0xFFFFFFFF << 8)) : x;
|
||||
value = pc + imm32;
|
||||
trampoline_instructions[idx++] = instruction & 0xFF00;
|
||||
trampoline_instructions[idx++] = 0xE003; // B PC, #6
|
||||
}
|
||||
else if (type == B2_THUMB16) {
|
||||
x = (instruction & 0x7FF) << 1;
|
||||
top_bit = x >> 11;
|
||||
imm32 = top_bit ? (x | (0xFFFFFFFF << 11)) : x;
|
||||
value = pc + imm32;
|
||||
}
|
||||
else if (type == BX_THUMB16) {
|
||||
value = pc;
|
||||
}
|
||||
value |= 1; // thumb
|
||||
trampoline_instructions[idx++] = 0xF8DF;
|
||||
trampoline_instructions[idx++] = 0xF000; // LDR.W PC, [PC]
|
||||
trampoline_instructions[idx++] = value & 0xFFFF;
|
||||
trampoline_instructions[idx++] = value >> 16;
|
||||
offset = idx;
|
||||
}
|
||||
else if (type == ADD_THUMB16) {
|
||||
int rdn;
|
||||
int rm;
|
||||
int r;
|
||||
|
||||
rdn = ((instruction & 0x80) >> 4) | (instruction & 0x7);
|
||||
|
||||
for (r = 7; ; --r) {
|
||||
if (r != rdn) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
trampoline_instructions[0] = 0xB400 | (1 << r); // PUSH {Rr}
|
||||
trampoline_instructions[1] = 0x4802 | (r << 8); // LDR Rr, [PC, #8]
|
||||
trampoline_instructions[2] = (instruction & 0xFF87) | (r << 3);
|
||||
trampoline_instructions[3] = 0xBC00 | (1 << r); // POP {Rr}
|
||||
trampoline_instructions[4] = 0xE002; // B PC, #4
|
||||
trampoline_instructions[5] = 0xBF00;
|
||||
trampoline_instructions[6] = pc & 0xFFFF;
|
||||
trampoline_instructions[7] = pc >> 16;
|
||||
offset = 8;
|
||||
}
|
||||
else if (type == MOV_THUMB16 || type == ADR_THUMB16 || type == LDR_THUMB16) {
|
||||
int r;
|
||||
uint32_t value;
|
||||
|
||||
if (type == MOV_THUMB16) {
|
||||
r = instruction & 0x7;
|
||||
value = pc;
|
||||
}
|
||||
else if (type == ADR_THUMB16) {
|
||||
r = (instruction & 0x700) >> 8;
|
||||
value = ALIGN_PC(pc) + (instruction & 0xFF) << 2;
|
||||
}
|
||||
else {
|
||||
r = (instruction & 0x700) >> 8;
|
||||
value = ((uint32_t *) (ALIGN_PC(pc) + ((instruction & 0xFF) << 2)))[0];
|
||||
}
|
||||
|
||||
trampoline_instructions[0] = 0x4800 | (r << 8); // LDR Rd, [PC]
|
||||
trampoline_instructions[1] = 0xE001; // B PC, #2
|
||||
trampoline_instructions[2] = value & 0xFFFF;
|
||||
trampoline_instructions[3] = value >> 16;
|
||||
offset = 4;
|
||||
}
|
||||
else if (type == CB_THUMB16) {
|
||||
int nonzero;
|
||||
uint32_t imm32;
|
||||
uint32_t value;
|
||||
|
||||
nonzero = (instruction & 0x800) >> 11;
|
||||
imm32 = ((instruction & 0x200) >> 3) | ((instruction & 0xF8) >> 2);
|
||||
value = pc + imm32 + 1;
|
||||
|
||||
trampoline_instructions[0] = instruction & 0xFD07;
|
||||
trampoline_instructions[1] = 0xE003; // B PC, #6
|
||||
trampoline_instructions[2] = 0xF8DF;
|
||||
trampoline_instructions[3] = 0xF000; // LDR.W PC, [PC]
|
||||
trampoline_instructions[4] = value & 0xFFFF;
|
||||
trampoline_instructions[5] = value >> 16;
|
||||
offset = 6;
|
||||
}
|
||||
else {
|
||||
trampoline_instructions[0] = instruction;
|
||||
trampoline_instructions[1] = 0xBF00; // NOP
|
||||
offset = 2;
|
||||
}
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
static int relocateInstructionInThumb32(uint32_t pc, uint16_t high_instruction, uint16_t low_instruction, uint16_t *trampoline_instructions)
|
||||
{
|
||||
uint32_t instruction;
|
||||
int type;
|
||||
int idx;
|
||||
int offset;
|
||||
|
||||
instruction = (high_instruction << 16) | low_instruction;
|
||||
type = getTypeInThumb32(instruction);
|
||||
idx = 0;
|
||||
if (type == BLX_THUMB32 || type == BL_THUMB32 || type == B1_THUMB32 || type == B2_THUMB32) {
|
||||
uint32_t j1;
|
||||
uint32_t j2;
|
||||
uint32_t s;
|
||||
uint32_t i1;
|
||||
uint32_t i2;
|
||||
uint32_t x;
|
||||
uint32_t imm32;
|
||||
uint32_t value;
|
||||
|
||||
j1 = (low_instruction & 0x2000) >> 13;
|
||||
j2 = (low_instruction & 0x800) >> 11;
|
||||
s = (high_instruction & 0x400) >> 10;
|
||||
i1 = !(j1 ^ s);
|
||||
i2 = !(j2 ^ s);
|
||||
|
||||
if (type == BLX_THUMB32 || type == BL_THUMB32) {
|
||||
trampoline_instructions[idx++] = 0xF20F;
|
||||
trampoline_instructions[idx++] = 0x0E09; // ADD.W LR, PC, #9
|
||||
}
|
||||
else if (type == B1_THUMB32) {
|
||||
trampoline_instructions[idx++] = 0xD000 | ((high_instruction & 0x3C0) << 2);
|
||||
trampoline_instructions[idx++] = 0xE003; // B PC, #6
|
||||
}
|
||||
trampoline_instructions[idx++] = 0xF8DF;
|
||||
trampoline_instructions[idx++] = 0xF000; // LDR.W PC, [PC]
|
||||
if (type == BLX_THUMB32) {
|
||||
x = (s << 24) | (i1 << 23) | (i2 << 22) | ((high_instruction & 0x3FF) << 12) | ((low_instruction & 0x7FE) << 1);
|
||||
imm32 = s ? (x | (0xFFFFFFFF << 25)) : x;
|
||||
value = ALIGN_PC(pc) + imm32;
|
||||
}
|
||||
else if (type == BL_THUMB32) {
|
||||
x = (s << 24) | (i1 << 23) | (i2 << 22) | ((high_instruction & 0x3FF) << 12) | ((low_instruction & 0x7FF) << 1);
|
||||
imm32 = s ? (x | (0xFFFFFFFF << 25)) : x;
|
||||
value = ALIGN_PC(pc) + imm32 + 1;
|
||||
}
|
||||
else if (type == B1_THUMB32) {
|
||||
x = (s << 20) | (j2 << 19) | (j1 << 18) | ((high_instruction & 0x3F) << 12) | ((low_instruction & 0x7FF) << 1);
|
||||
imm32 = s ? (x | (0xFFFFFFFF << 21)) : x;
|
||||
value = ALIGN_PC(pc) + imm32 + 1;
|
||||
}
|
||||
else if (type == B2_THUMB32) {
|
||||
x = (s << 24) | (i1 << 23) | (i2 << 22) | ((high_instruction & 0x3FF) << 12) | ((low_instruction & 0x7FF) << 1);
|
||||
imm32 = s ? (x | (0xFFFFFFFF << 25)) : x;
|
||||
value = ALIGN_PC(pc) + imm32 + 1;
|
||||
}
|
||||
trampoline_instructions[idx++] = value & 0xFFFF;
|
||||
trampoline_instructions[idx++] = value >> 16;
|
||||
offset = idx;
|
||||
}
|
||||
else if (type == ADR1_THUMB32 || type == ADR2_THUMB32 || type == LDR_THUMB32) {
|
||||
int r;
|
||||
uint32_t imm32;
|
||||
uint32_t value;
|
||||
|
||||
if (type == ADR1_THUMB32 || type == ADR2_THUMB32) {
|
||||
uint32_t i;
|
||||
uint32_t imm3;
|
||||
uint32_t imm8;
|
||||
|
||||
r = (low_instruction & 0xF00) >> 8;
|
||||
i = (high_instruction & 0x400) >> 10;
|
||||
imm3 = (low_instruction & 0x7000) >> 12;
|
||||
imm8 = instruction & 0xFF;
|
||||
|
||||
imm32 = (i << 31) | (imm3 << 30) | (imm8 << 27);
|
||||
|
||||
if (type == ADR1_THUMB32) {
|
||||
value = ALIGN_PC(pc) + imm32;
|
||||
}
|
||||
else {
|
||||
value = ALIGN_PC(pc) - imm32;
|
||||
}
|
||||
}
|
||||
else {
|
||||
int is_add;
|
||||
uint32_t *addr;
|
||||
|
||||
is_add = (high_instruction & 0x80) >> 7;
|
||||
r = low_instruction >> 12;
|
||||
imm32 = low_instruction & 0xFFF;
|
||||
|
||||
if (is_add) {
|
||||
addr = (uint32_t *) (ALIGN_PC(pc) + imm32);
|
||||
}
|
||||
else {
|
||||
addr = (uint32_t *) (ALIGN_PC(pc) - imm32);
|
||||
}
|
||||
|
||||
value = addr[0];
|
||||
}
|
||||
|
||||
// LDR.W Rr, [PC, 2]
|
||||
trampoline_instructions[0] = 0xF8DF;
|
||||
trampoline_instructions[1] = r << 12 | 4;
|
||||
|
||||
trampoline_instructions[2] = 0xBF00; // nop
|
||||
trampoline_instructions[3] = 0xE001; // B PC, #2
|
||||
trampoline_instructions[4] = value & 0xFFFF;
|
||||
trampoline_instructions[5] = value >> 16;
|
||||
offset = 6;
|
||||
}
|
||||
|
||||
else if (type == TBB_THUMB32 || type == TBH_THUMB32) {
|
||||
int rm;
|
||||
int r;
|
||||
int rx;
|
||||
|
||||
rm = low_instruction & 0xF;
|
||||
|
||||
for (r = 7;; --r) {
|
||||
if (r != rm) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (rx = 7; ; --rx) {
|
||||
if (rx != rm && rx != r) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
trampoline_instructions[0] = 0xB400 | (1 << rx); // PUSH {Rx}
|
||||
trampoline_instructions[1] = 0x4805 | (r << 8); // LDR Rr, [PC, #20]
|
||||
trampoline_instructions[2] = 0x4600 | (rm << 3) | rx; // MOV Rx, Rm
|
||||
if (type == TBB_THUMB32) {
|
||||
trampoline_instructions[3] = 0xEB00 | r;
|
||||
trampoline_instructions[4] = 0x0000 | (rx << 8) | rx; // ADD.W Rx, Rr, Rx
|
||||
trampoline_instructions[5] = 0x7800 | (rx << 3) | rx; // LDRB Rx, [Rx]
|
||||
}
|
||||
else if (type == TBH_THUMB32) {
|
||||
trampoline_instructions[3] = 0xEB00 | r;
|
||||
trampoline_instructions[4] = 0x0040 | (rx << 8) | rx; // ADD.W Rx, Rr, Rx, LSL #1
|
||||
trampoline_instructions[5] = 0x8800 | (rx << 3) | rx; // LDRH Rx, [Rx]
|
||||
}
|
||||
trampoline_instructions[6] = 0xEB00 | r;
|
||||
trampoline_instructions[7] = 0x0040 | (r << 8) | rx; // ADD Rr, Rr, Rx, LSL #1
|
||||
trampoline_instructions[8] = 0x3001 | (r << 8); // ADD Rr, #1
|
||||
trampoline_instructions[9] = 0xBC00 | (1 << rx); // POP {Rx}
|
||||
trampoline_instructions[10] = 0x4700 | (r << 3); // BX Rr
|
||||
trampoline_instructions[11] = 0xBF00;
|
||||
trampoline_instructions[12] = pc & 0xFFFF;
|
||||
trampoline_instructions[13] = pc >> 16;
|
||||
offset = 14;
|
||||
}
|
||||
else {
|
||||
trampoline_instructions[0] = high_instruction;
|
||||
trampoline_instructions[1] = low_instruction;
|
||||
offset = 2;
|
||||
}
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
static void relocateInstructionInThumb(uint32_t target_addr, uint16_t *orig_instructions, int length, uint16_t *trampoline_instructions, int *orig_boundaries, int *trampoline_boundaries, int *count)
|
||||
{
|
||||
int orig_pos;
|
||||
int trampoline_pos;
|
||||
uint32_t pc;
|
||||
uint32_t lr;
|
||||
|
||||
orig_pos = 0;
|
||||
trampoline_pos = 0;
|
||||
pc = target_addr + 4;
|
||||
while (1) {
|
||||
int offset;
|
||||
|
||||
orig_boundaries[*count] = orig_pos * sizeof(uint16_t);
|
||||
trampoline_boundaries[*count] = trampoline_pos * sizeof(uint16_t);
|
||||
++(*count);
|
||||
|
||||
if ((orig_instructions[orig_pos] >> 11) >= 0x1D && (orig_instructions[orig_pos] >> 11) <= 0x1F) {
|
||||
if (orig_pos + 2 > length / sizeof(uint16_t)) {
|
||||
break;
|
||||
}
|
||||
offset = relocateInstructionInThumb32(pc, orig_instructions[orig_pos], orig_instructions[orig_pos + 1], &trampoline_instructions[trampoline_pos]);
|
||||
pc += sizeof(uint32_t);
|
||||
trampoline_pos += offset;
|
||||
orig_pos += 2;
|
||||
}
|
||||
else {
|
||||
offset = relocateInstructionInThumb16(pc, orig_instructions[orig_pos], &trampoline_instructions[trampoline_pos]);
|
||||
pc += sizeof(uint16_t);
|
||||
trampoline_pos += offset;
|
||||
++orig_pos;
|
||||
}
|
||||
|
||||
if (orig_pos >= length / sizeof(uint16_t)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
lr = target_addr + orig_pos * sizeof(uint16_t) + 1;
|
||||
trampoline_instructions[trampoline_pos] = 0xF8DF;
|
||||
trampoline_instructions[trampoline_pos + 1] = 0xF000; // LDR.W PC, [PC]
|
||||
trampoline_instructions[trampoline_pos + 2] = lr & 0xFFFF;
|
||||
trampoline_instructions[trampoline_pos + 3] = lr >> 16;
|
||||
}
|
||||
|
||||
static void relocateInstructionInArm(uint32_t target_addr, uint32_t *orig_instructions, int length, uint32_t *trampoline_instructions, int *orig_boundaries, int *trampoline_boundaries, int *count)
|
||||
{
|
||||
uint32_t pc;
|
||||
uint32_t lr;
|
||||
int orig_pos;
|
||||
int trampoline_pos;
|
||||
|
||||
pc = target_addr + 8;
|
||||
lr = target_addr + length;
|
||||
|
||||
trampoline_pos = 0;
|
||||
for (orig_pos = 0; orig_pos < length / sizeof(uint32_t); ++orig_pos) {
|
||||
uint32_t instruction;
|
||||
int type;
|
||||
|
||||
orig_boundaries[*count] = orig_pos * sizeof(uint32_t);
|
||||
trampoline_boundaries[*count] = trampoline_pos * sizeof(uint32_t);
|
||||
++(*count);
|
||||
|
||||
instruction = orig_instructions[orig_pos];
|
||||
type = getTypeInArm(instruction);
|
||||
if (type == BLX_ARM || type == BL_ARM || type == B_ARM || type == BX_ARM) {
|
||||
uint32_t x;
|
||||
int top_bit;
|
||||
uint32_t imm32;
|
||||
uint32_t value;
|
||||
|
||||
if (type == BLX_ARM || type == BL_ARM) {
|
||||
trampoline_instructions[trampoline_pos++] = 0xE28FE004; // ADD LR, PC, #4
|
||||
}
|
||||
trampoline_instructions[trampoline_pos++] = 0xE51FF004; // LDR PC, [PC, #-4]
|
||||
if (type == BLX_ARM) {
|
||||
x = ((instruction & 0xFFFFFF) << 2) | ((instruction & 0x1000000) >> 23);
|
||||
}
|
||||
else if (type == BL_ARM || type == B_ARM) {
|
||||
x = (instruction & 0xFFFFFF) << 2;
|
||||
}
|
||||
else {
|
||||
x = 0;
|
||||
}
|
||||
|
||||
top_bit = x >> 25;
|
||||
imm32 = top_bit ? (x | (0xFFFFFFFF << 26)) : x;
|
||||
if (type == BLX_ARM) {
|
||||
value = pc + imm32 + 1;
|
||||
}
|
||||
else {
|
||||
value = pc + imm32;
|
||||
}
|
||||
trampoline_instructions[trampoline_pos++] = value;
|
||||
|
||||
}
|
||||
else if (type == ADD_ARM) {
|
||||
int rd;
|
||||
int rm;
|
||||
int r;
|
||||
|
||||
rd = (instruction & 0xF000) >> 12;
|
||||
rm = instruction & 0xF;
|
||||
|
||||
for (r = 12; ; --r) {
|
||||
if (r != rd && r != rm) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
trampoline_instructions[trampoline_pos++] = 0xE52D0004 | (r << 12); // PUSH {Rr}
|
||||
trampoline_instructions[trampoline_pos++] = 0xE59F0008 | (r << 12); // LDR Rr, [PC, #8]
|
||||
trampoline_instructions[trampoline_pos++] = (instruction & 0xFFF0FFFF) | (r << 16);
|
||||
trampoline_instructions[trampoline_pos++] = 0xE49D0004 | (r << 12); // POP {Rr}
|
||||
trampoline_instructions[trampoline_pos++] = 0xE28FF000; // ADD PC, PC
|
||||
trampoline_instructions[trampoline_pos++] = pc;
|
||||
}
|
||||
else if (type == ADR1_ARM || type == ADR2_ARM || type == LDR_ARM || type == MOV_ARM) {
|
||||
int r;
|
||||
uint32_t value;
|
||||
|
||||
r = (instruction & 0xF000) >> 12;
|
||||
|
||||
if (type == ADR1_ARM || type == ADR2_ARM || type == LDR_ARM) {
|
||||
uint32_t imm32;
|
||||
|
||||
imm32 = instruction & 0xFFF;
|
||||
if (type == ADR1_ARM) {
|
||||
value = pc + imm32;
|
||||
}
|
||||
else if (type == ADR2_ARM) {
|
||||
value = pc - imm32;
|
||||
}
|
||||
else if (type == LDR_ARM) {
|
||||
int is_add;
|
||||
|
||||
is_add = (instruction & 0x800000) >> 23;
|
||||
if (is_add) {
|
||||
value = ((uint32_t *) (pc + imm32))[0];
|
||||
}
|
||||
else {
|
||||
value = ((uint32_t *) (pc - imm32))[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
value = pc;
|
||||
}
|
||||
|
||||
trampoline_instructions[trampoline_pos++] = 0xE51F0000 | (r << 12); // LDR Rr, [PC]
|
||||
trampoline_instructions[trampoline_pos++] = 0xE28FF000; // ADD PC, PC
|
||||
trampoline_instructions[trampoline_pos++] = value;
|
||||
}
|
||||
else {
|
||||
trampoline_instructions[trampoline_pos++] = instruction;
|
||||
}
|
||||
pc += sizeof(uint32_t);
|
||||
}
|
||||
|
||||
trampoline_instructions[trampoline_pos++] = 0xe51ff004; // LDR PC, [PC, #-4]
|
||||
trampoline_instructions[trampoline_pos++] = lr;
|
||||
}
|
||||
|
||||
void relocateInstruction(uint32_t target_addr, void *orig_instructions, int length, void *trampoline_instructions, int *orig_boundaries, int *trampoline_boundaries, int *count)
|
||||
{
|
||||
if (target_addr & 1 == 1) {
|
||||
relocateInstructionInThumb(target_addr - 1, (uint16_t *) orig_instructions, length, (uint16_t *) trampoline_instructions, orig_boundaries, trampoline_boundaries, count);
|
||||
}
|
||||
else {
|
||||
relocateInstructionInArm(target_addr, (uint32_t *) orig_instructions, length, (uint32_t *) trampoline_instructions, orig_boundaries, trampoline_boundaries, count);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
#ifndef _RELOCATE_H
|
||||
#define _RELOCATE_H
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
void relocateInstruction(uint32_t target_addr, void *orig_instructions, int length, void *trampoline_instructions, int *orig_boundaries, int *trampoline_boundaries, int *count);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,69 @@
|
|||
#include <stdlib.h>
|
||||
#include <android/log.h>
|
||||
#include <dlfcn.h>
|
||||
|
||||
#include "hooks/inlineHook.h"
|
||||
|
||||
#define LOG(...) __android_log_print(ANDROID_LOG_DEBUG, "NOPSMDRM", __VA_ARGS__)
|
||||
|
||||
static void* LIB_DEFAULT_HANDLE = NULL;
|
||||
static void* LIB_DEFAULT_BASE = NULL;
|
||||
|
||||
int (*memcmp_orig)(char*, char*, int) = NULL;
|
||||
|
||||
void* get_func_addr(char* function_name) {
|
||||
if(LIB_DEFAULT_HANDLE != NULL){
|
||||
uintptr_t function_addr = (uintptr_t)dlsym(LIB_DEFAULT_HANDLE, function_name);
|
||||
|
||||
LOG("load function_addr %p", function_addr);
|
||||
return function_addr;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void* get_base_addr(void* object) {
|
||||
if(LIB_DEFAULT_HANDLE != NULL){
|
||||
Dl_info inf;
|
||||
dladdr(object, &inf);
|
||||
|
||||
LOG("load inf: dli_fbase %p", inf.dli_fbase);
|
||||
LOG("load name: dli_fname %s", inf.dli_fname);
|
||||
|
||||
return inf.dli_fbase;
|
||||
}
|
||||
}
|
||||
|
||||
void load_libdefault() {
|
||||
LIB_DEFAULT_HANDLE = dlopen("/data/data/com.playstation.psstore/lib/libdefault.so", RTLD_GLOBAL | RTLD_NOW);
|
||||
LOG("LIB_DEFAULT_HANDLE %p", LIB_DEFAULT_HANDLE);
|
||||
}
|
||||
|
||||
int get_addresses() {
|
||||
load_libdefault();
|
||||
void* lib_pss_main = get_func_addr("scePssMain");
|
||||
LIB_DEFAULT_BASE = get_base_addr(lib_pss_main);
|
||||
}
|
||||
|
||||
|
||||
int memcmp_patch(char* dst, char* src, int sz){
|
||||
LOG("memcmp %p %p %x", dst, src, sz);
|
||||
|
||||
return memcmp_orig(dst, src, sz);
|
||||
}
|
||||
|
||||
int patch_libdefault() {
|
||||
|
||||
// hook the thing
|
||||
int res = registerInlineHook((uintptr_t)memcmp, (uintptr_t)memcmp_patch, (uintptr_t**)&memcmp_orig);
|
||||
LOG("res = %p", res);
|
||||
|
||||
res = inlineHook((uintptr_t)memcmp);
|
||||
LOG("res = %p", res);
|
||||
|
||||
get_addresses();
|
||||
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
#include <stdlib.h>
|
||||
|
||||
int patch_libdefault() {
|
||||
// TODO: hook into libdefault.so
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,100 @@
|
|||
#include <jni.h>
|
||||
#include <android/log.h>
|
||||
#include <string.h>
|
||||
#include <dlfcn.h>
|
||||
|
||||
#include "nopsmdrm.h"
|
||||
|
||||
#define LOGFUNCTION() __android_log_print(ANDROID_LOG_DEBUG, "LIBPSMKDC", "%s", __FUNCTION__)
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_com_playstation_psmKdcJni_Psmkdc_JNI_1scePsmDrmKdcInit(JNIEnv *env, jobject thiz, jint arr_len, jbyteArray arr,
|
||||
jstring external_files_dir, jstring internal_files_dir,
|
||||
jstring np_env, jstring deviceId, jstring serial, jstring brand,
|
||||
jstring manu, jstring model, jstring product, jstring device,
|
||||
jstring type) {
|
||||
LOGFUNCTION();
|
||||
patch_libdefault();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_com_playstation_psmKdcJni_Psmkdc_JNI_1scePsmDrmKdcTerm(JNIEnv *env, jobject thiz) {
|
||||
LOGFUNCTION();
|
||||
return 0;
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_com_playstation_psmKdcJni_Psmkdc_JNI_1scePsmDrmIsRevokedFile(JNIEnv *env, jobject thiz, jstring str,
|
||||
jbooleanArray z_arr) {
|
||||
LOGFUNCTION();
|
||||
return 0;
|
||||
}
|
||||
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_com_playstation_psmKdcJni_Psmkdc_JNI_1scePsmDrmIsRevoked(JNIEnv *env, jobject thiz, jstring str, jlong j) {
|
||||
LOGFUNCTION();
|
||||
return JNI_FALSE;
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_com_playstation_psmKdcJni_Psmkdc_JNI_1scePsmDrmIsBootable(JNIEnv *env, jobject thiz, jlong j, jstring str,
|
||||
jlongArray until) {
|
||||
LOGFUNCTION();
|
||||
return 0;
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_com_playstation_psmKdcJni_Psmkdc_JNI_1scePsmDrmAbortTransaction(JNIEnv *env, jobject thiz) {
|
||||
LOGFUNCTION();
|
||||
return 0;
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_com_playstation_psmKdcJni_Psmkdc_JNI_1scePsmDrmExecActivation(JNIEnv *env, jobject thiz, jbyteArray b_arr, jint i,
|
||||
jintArray i_arr, jintArray i_arr2, jlong j) {
|
||||
LOGFUNCTION();
|
||||
return 0;
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_com_playstation_psmKdcJni_Psmkdc_JNI_1scePsmDrmExecActivationPreCheck(JNIEnv *env, jobject thiz, jbyteArray b_arr,
|
||||
jint i, jintArray i_arr, jintArray i_arr2,
|
||||
jlong j) {
|
||||
LOGFUNCTION();
|
||||
return 0;
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_com_playstation_psmKdcJni_Psmkdc_JNI_1scePsmDrmExecDeactivation(JNIEnv *env, jobject thiz, jbyteArray b_arr, jint i,
|
||||
jintArray i_arr, jintArray i_arr2, jlong j) {
|
||||
LOGFUNCTION();
|
||||
return 0;
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_com_playstation_psmKdcJni_Psmkdc_JNI_1scePsmDrmExecRifAcquisition(JNIEnv *env, jobject thiz, jbyteArray b_arr, jint i,
|
||||
jstring str, jlong j) {
|
||||
LOGFUNCTION();
|
||||
return 0;
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_com_playstation_psmKdcJni_Psmkdc_JNI_1scePsmDrmIsActivated(JNIEnv *env, jobject thiz, jlong j, jlongArray j_arr) {
|
||||
LOGFUNCTION();
|
||||
return 0;
|
||||
}
|
||||
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_com_playstation_psmKdcJni_Psmkdc_JNI_1scePsmDrmNeedReactivation(JNIEnv *env, jobject thiz, jlong j, jintArray i_arr) {
|
||||
LOGFUNCTION();
|
||||
return 0;
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_com_playstation_psmKdcJni_Psmkdc_JNI_1scePsmDrmRemoveRif(JNIEnv *env, jobject thiz, jstring str) {
|
||||
LOGFUNCTION();
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1,103 +0,0 @@
|
|||
#include <jni.h>
|
||||
#include <android/log.h>
|
||||
#include <string.h>
|
||||
#include <dlfcn.h>
|
||||
|
||||
#include "nopsmdrm.h"
|
||||
|
||||
#define LOGFUNCTION() __android_log_print(ANDROID_LOG_DEBUG, "LIBPSMKDC", "%s", __FUNCTION__)
|
||||
|
||||
extern "C" {
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_com_playstation_psmKdcJni_Psmkdc_JNI_1scePsmDrmKdcInit(JNIEnv *env, jobject thiz, jint arr_len, jbyteArray arr,
|
||||
jstring external_files_dir, jstring internal_files_dir,
|
||||
jstring np_env, jstring deviceId, jstring serial, jstring brand,
|
||||
jstring manu, jstring model, jstring product, jstring device,
|
||||
jstring type) {
|
||||
LOGFUNCTION();
|
||||
patch_libdefault();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_com_playstation_psmKdcJni_Psmkdc_JNI_1scePsmDrmKdcTerm(JNIEnv *env, jobject thiz) {
|
||||
LOGFUNCTION();
|
||||
return 0;
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_com_playstation_psmKdcJni_Psmkdc_JNI_1scePsmDrmIsRevokedFile(JNIEnv *env, jobject thiz, jstring str,
|
||||
jbooleanArray z_arr) {
|
||||
LOGFUNCTION();
|
||||
return 0;
|
||||
}
|
||||
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_com_playstation_psmKdcJni_Psmkdc_JNI_1scePsmDrmIsRevoked(JNIEnv *env, jobject thiz, jstring str, jlong j) {
|
||||
LOGFUNCTION();
|
||||
return JNI_FALSE;
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_com_playstation_psmKdcJni_Psmkdc_JNI_1scePsmDrmIsBootable(JNIEnv *env, jobject thiz, jlong j, jstring str,
|
||||
jlongArray until) {
|
||||
LOGFUNCTION();
|
||||
return 0;
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_com_playstation_psmKdcJni_Psmkdc_JNI_1scePsmDrmAbortTransaction(JNIEnv *env, jobject thiz) {
|
||||
LOGFUNCTION();
|
||||
return 0;
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_com_playstation_psmKdcJni_Psmkdc_JNI_1scePsmDrmExecActivation(JNIEnv *env, jobject thiz, jbyteArray b_arr, jint i,
|
||||
jintArray i_arr, jintArray i_arr2, jlong j) {
|
||||
LOGFUNCTION();
|
||||
return 0;
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_com_playstation_psmKdcJni_Psmkdc_JNI_1scePsmDrmExecActivationPreCheck(JNIEnv *env, jobject thiz, jbyteArray b_arr,
|
||||
jint i, jintArray i_arr, jintArray i_arr2,
|
||||
jlong j) {
|
||||
LOGFUNCTION();
|
||||
return 0;
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_com_playstation_psmKdcJni_Psmkdc_JNI_1scePsmDrmExecDeactivation(JNIEnv *env, jobject thiz, jbyteArray b_arr, jint i,
|
||||
jintArray i_arr, jintArray i_arr2, jlong j) {
|
||||
LOGFUNCTION();
|
||||
return 0;
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_com_playstation_psmKdcJni_Psmkdc_JNI_1scePsmDrmExecRifAcquisition(JNIEnv *env, jobject thiz, jbyteArray b_arr, jint i,
|
||||
jstring str, jlong j) {
|
||||
LOGFUNCTION();
|
||||
return 0;
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_com_playstation_psmKdcJni_Psmkdc_JNI_1scePsmDrmIsActivated(JNIEnv *env, jobject thiz, jlong j, jlongArray j_arr) {
|
||||
LOGFUNCTION();
|
||||
return 0;
|
||||
}
|
||||
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_com_playstation_psmKdcJni_Psmkdc_JNI_1scePsmDrmNeedReactivation(JNIEnv *env, jobject thiz, jlong j, jintArray i_arr) {
|
||||
LOGFUNCTION();
|
||||
return 0;
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_com_playstation_psmKdcJni_Psmkdc_JNI_1scePsmDrmRemoveRif(JNIEnv *env, jobject thiz, jstring str) {
|
||||
LOGFUNCTION();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
}
|
Loading…
Reference in New Issue