update libpsmkdc_stub
This commit is contained in:
parent
cc51442fcf
commit
72695d68c2
|
@ -8,10 +8,7 @@ LOCAL_CFLAGS += -fno-rtti -fno-exceptions -fPIC
|
|||
|
||||
LOCAL_C_INCLUDES += $(MAIN_LOCAL_PATH)
|
||||
|
||||
LOCAL_SRC_FILES := psmkdc_jni.c \
|
||||
nopsmdrm.c \
|
||||
hooks/inlineHook.c \
|
||||
hooks/relocate.c
|
||||
LOCAL_SRC_FILES := psmkdc_jni.c
|
||||
|
||||
|
||||
LOCAL_LDLIBS := -llog -landroid -lc
|
||||
|
|
|
@ -1,424 +0,0 @@
|
|||
/*
|
||||
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);
|
||||
}
|
|
@ -1,33 +0,0 @@
|
|||
#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
|
|
@ -1,621 +0,0 @@
|
|||
/*
|
||||
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);
|
||||
}
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
#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
|
161
jni/nopsmdrm.c
161
jni/nopsmdrm.c
|
@ -1,161 +0,0 @@
|
|||
#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__)
|
||||
#define FAKE_AID 0x0123456789ABCDEFLL
|
||||
|
||||
static void* LIB_DEFAULT_HANDLE = NULL;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char magic[0x8]; // 0x00
|
||||
uint32_t unk1; // 0x08
|
||||
uint32_t unk2; // 0x0C
|
||||
uint64_t aid; // 0x10
|
||||
uint32_t unk3; // 0x18
|
||||
uint32_t unk4; // 0x1C
|
||||
uint64_t start_time; // 0x20
|
||||
uint64_t expiration_time; // 0x28
|
||||
uint8_t act_digest[0x20]; // 0x30
|
||||
char content_id[0x30]; // 0x50
|
||||
uint8_t unk5[0x80]; // 0x80
|
||||
uint8_t key[0x200]; // 0x100
|
||||
uint8_t sha256digest[0x100]; // 0x300
|
||||
} ScePsmDrmLicense;
|
||||
|
||||
int (*scePsmDrmGetKeySet_orig)(ScePsmDrmLicense*, char*, int*, uint64_t*, uint64_t*) = NULL;
|
||||
|
||||
int (*dlopen_orig)(char*, int) = NULL;
|
||||
|
||||
void* (*scePsmDrmGetRif_orig)(char*, char*, ScePsmDrmLicense *) = 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 MakeFakeLicense(ScePsmDrmLicense* license_buf, uint8_t* klicensee) {
|
||||
ScePsmDrmLicense license;
|
||||
memset(&license, 0, sizeof(ScePsmDrmLicense));
|
||||
license.aid = FAKE_AID;
|
||||
license.unk1 = __builtin_bswap32(1);
|
||||
|
||||
memcpy(license.content_id, license_buf->content_id, 0x30);
|
||||
memcpy(license.key, klicensee, 0x200);
|
||||
|
||||
|
||||
char fakeRifPath[0x100];
|
||||
snprintf(fakeRifPath, sizeof(fakeRifPath) - 1, "/sdcard/psm/%s.rif", license_buf->content_id);
|
||||
LOG("fakeRifPath: %s", fakeRifPath);
|
||||
|
||||
mkdir("/sdcard/psm");
|
||||
|
||||
LOG("Writing fake license ...");
|
||||
|
||||
FILE* fd = fopen(fakeRifPath, "wb");
|
||||
if(fd != NULL) {
|
||||
fwrite(&license, sizeof(ScePsmDrmLicense), 1, fd);
|
||||
fclose(fd);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int scePsmDrmGetKeySet_patch(ScePsmDrmLicense *license_buf, char *klicensee, int* flags, uint64_t* start_time, uint64_t* expiration_time) {
|
||||
|
||||
LOG("license_buf %p, klicensee %p, flags %p, start_time %p, expiration_time %p", license_buf, klicensee, flags, start_time, expiration_time);
|
||||
int res = scePsmDrmGetKeySet_orig(license_buf, klicensee, flags, start_time, expiration_time);
|
||||
|
||||
|
||||
if(res >= 0) {
|
||||
LOG("Creating fake license file");
|
||||
MakeFakeLicense(license_buf, klicensee);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
int scePsmDrmGetRif_patch(char *contentid, char *psm_folder, ScePsmDrmLicense *rif_file) {
|
||||
LOG("contentid: %s psm_folder: %s", contentid, psm_folder);
|
||||
|
||||
int res = scePsmDrmGetRif_orig(contentid, psm_folder, rif_file);
|
||||
LOG("res = %x", res);
|
||||
|
||||
if(res <= 0) {
|
||||
// get title id :
|
||||
char titleid[9];
|
||||
memcpy(titleid, contentid + 7, sizeof(titleid));
|
||||
titleid[9] = '\0';
|
||||
|
||||
// locate FAKE.RIF
|
||||
char fakeRifPath[0x100];
|
||||
snprintf(fakeRifPath, sizeof(fakeRifPath) - 1, "%s/License/%s/FAKE.rif", psm_folder, titleid);
|
||||
LOG("fakeRifPath: %s", fakeRifPath);
|
||||
|
||||
|
||||
// Read FAKE.RIF into the buffer ...
|
||||
FILE* fd = fopen(fakeRifPath, "rb");
|
||||
if(fd != NULL) {
|
||||
fread(rif_file, sizeof(ScePsmDrmLicense), 1, fd);
|
||||
fclose(fd);
|
||||
}
|
||||
else {
|
||||
return res;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int dlopen_patch(char* lib, int param){
|
||||
LOG("dlopen_patch %s %x", lib, param);
|
||||
|
||||
void* ptr = dlopen_orig(lib, param);
|
||||
|
||||
if(strstr(ptr, "libdefault") != 0) {
|
||||
LIB_DEFAULT_HANDLE = ptr;
|
||||
LOG("libdeafult found %p, unhooking dlopen ...", LIB_DEFAULT_HANDLE);
|
||||
inlineUnHook((uintptr_t)dlopen); // got libdefault, unhook this now ..
|
||||
|
||||
|
||||
LOG("Hooking scePsmDrmGetRif");
|
||||
uintptr_t* scePsmDrmGetRif = get_func_addr("scePsmDrmGetRif");
|
||||
int res = registerInlineHook((uintptr_t)scePsmDrmGetRif, (uintptr_t)scePsmDrmGetRif_patch, (uintptr_t**)&scePsmDrmGetRif_orig);
|
||||
if(res == 0)
|
||||
inlineHook((uintptr_t)scePsmDrmGetRif);
|
||||
|
||||
LOG("Hooking scePsmDrmGetKeySet");
|
||||
uintptr_t* scePsmDrmGetKeySet = get_func_addr("scePsmDrmGetKeySet");
|
||||
res = registerInlineHook((uintptr_t)scePsmDrmGetKeySet, (uintptr_t)scePsmDrmGetKeySet_patch, (uintptr_t**)&scePsmDrmGetKeySet_orig);
|
||||
if(res == 0)
|
||||
inlineHook((uintptr_t)scePsmDrmGetKeySet);
|
||||
|
||||
|
||||
}
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
int patch_libdefault() {
|
||||
|
||||
// hook the thing
|
||||
LOG("HOOKING dlopen");
|
||||
int res = registerInlineHook((uintptr_t)dlopen, (uintptr_t)dlopen_patch, (uintptr_t**)&dlopen_orig);
|
||||
if(res == 0)
|
||||
inlineHook((uintptr_t)dlopen);
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
#ifndef PSM_KDC_NOPSMDRM_H
|
||||
#define PSM_KDC_NOPSMDRM_H
|
||||
|
||||
int patch_libdefault();
|
||||
|
||||
#endif //PSM_KDC_NOPSMDRM_H
|
|
@ -1,9 +1,6 @@
|
|||
#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__)
|
||||
|
||||
|
@ -14,9 +11,6 @@ Java_com_playstation_psmKdcJni_Psmkdc_JNI_1scePsmDrmKdcInit(JNIEnv *env, jobject
|
|||
jstring manu, jstring model, jstring product, jstring device,
|
||||
jstring type) {
|
||||
LOGFUNCTION();
|
||||
|
||||
patch_libdefault();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue