-
Notifications
You must be signed in to change notification settings - Fork 3
/
hook.c
181 lines (155 loc) · 4.19 KB
/
hook.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
/*
* Copyright 2010 by Coldbird
*
* hook.c - Import Hooking Functions
*
* This file is part of Adhoc Emulator.
*
* Adhoc Emulator is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Adhoc Emulator 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Adhoc Emulator. If not, see <http://www.gnu.org/licenses/>.
*/
#include <pspsysmem_kernel.h>
#include <psputilsforkernel.h>
#include <psputils.h>
#include <string.h>
#include "hook.h"
#include "logger.h"
typedef struct
{
const char * name;
unsigned short version;
unsigned short attribute;
unsigned char entLen;
unsigned char varCount;
unsigned short funcCount;
unsigned int * fnids;
unsigned int * funcs;
unsigned int * vnids;
unsigned int * vars;
}PspModuleImport;
PspModuleImport * find_import_lib(SceModule2 * module, const char * library)
{
//library import pointer
PspModuleImport * result = NULL;
//valid arguments
if(module && library)
{
//check stub table
unsigned int x = 0; while(x < module->stub_size)
{
//grab library stub
result = (PspModuleImport *)(module->stub_top + x);
//library found
if(result->name && strcmp(result->name, library) == 0)
{
//stop search
break;
}
//move forward
x += result->entLen * 4;
}
//library not found
if(x == module->stub_size) result = NULL;
}
//return library import pointer
return result;
}
void list_imports(SceModule2 * module, const char * library)
{
//find library import
PspModuleImport * import = find_import_lib(module, library);
//found import
if(import)
{
//find stub
unsigned int x = 0; for(; x < import->funcCount; x++)
{
//found stub
kprintf("%s: %08X\n", library, import->fnids[x]);
}
}
}
unsigned int find_import_bynid(SceModule2 * module, const char * library, unsigned int nid)
{
//stub address
unsigned int result = 0;
//find library import
PspModuleImport * import = find_import_lib(module, library);
//found import
if(import)
{
//kprintf("%s: Found import lib: %s\n", __FILE__, library);
//find stub
unsigned int x = 0; for(; x < import->funcCount; x++)
{
//kprintf("%s: checking import NID: %08X\n", __FILE__, import->fnids[x]);
//found stub
if(import->fnids[x] == nid)
{
//save stub address
result = (unsigned int)&import->funcs[x * 2];
//stop search
break;
}
}
}
//return stub address
return result;
}
void api_hook_import(unsigned int address, void * function)
{
//valid address
if(address)
{
//asm jmp
*(unsigned int *)(address) = 0x08000000 | ((unsigned int)function & 0x0FFFFFFF) >> 2;
//asm nop
*(unsigned int *)(address + 4) = 0;
//flush cache
sceKernelDcacheWritebackInvalidateRange((const void *)address, 8);
sceKernelIcacheInvalidateRange((const void *)address, 8);
}
}
void api_hook_import_syscall(unsigned int address, void * function)
{
//valid address
if(address)
{
//asm jr $ra
*(unsigned int *)(address) = 0x03E00008;
//asm syscall #
*(unsigned int *)(address + 4) = (((sceKernelQuerySystemCall(function)) << 6) | 12);
//flush cache
sceKernelDcacheWritebackInvalidateRange((const void *)address, 8);
sceKernelIcacheInvalidateRange((const void *)address, 8);
}
}
int hook_import_bynid(SceModule2 * module, const char * library, unsigned int nid, void * function, int syscall)
{
//result
int result = 0;
//find import stub
unsigned int stub = find_import_bynid(module, library, nid);
//found stub
if(stub)
{
//write syscall
if(syscall) api_hook_import_syscall(stub, function);
//write jump
else api_hook_import(stub, function);
}
//stub not found
else result = -1;
//return result
return result;
}