-
Notifications
You must be signed in to change notification settings - Fork 1
/
CustomApi_392.pbp
132 lines (113 loc) · 2.88 KB
/
CustomApi_392.pbp
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
; This patch adds custom API support.
; Custom API reveals some otherwise not available methods
; to installed apps.
; NOTE: this may break some poorly written applications!
; In such case, app creator should be notified about a bug in the app:
; dict_write_end method should never be called with NULL parameter (usually).
; How is it done:
;
; - app calls `dict_write_end` method with NULL value.
; On stock firmwares, this method accepts only one parameter in R0
; and returns 0 if this parameter is zero, thus signalling error.
;
; But if this patch is installed, then that method call with `0` in R0
; will be handled specially.
; It will then accept at least 2 arguments,
; and second one denotes an API group.
;
; Group 0 is special and is used to check whether this patch is installed.
; A call `dict_write_end(0, 0)` will return 1 (true),
; meaning that custom APIs are supported.
;
; Other groups are documented below.
; dict_write_end method (partial signature)
48 b1 02 68 22 b1 83 68 23 b1 43 60 98 1a 70 47
{
; was:
; CBZ R0, ret
; LDR R2, [R0]
B.W my_dwe
global dwe_cont
; was:
; CBZ R2, retR2
}
{
proc my_dwe
CBZ R0, our_case
; not our case -> re-execute overwritten code
LDR R2, [R0]
B.W dwe_cont
our_case:
CBZ R1, group_0
CMP R1, 1
BEQ group_1
CMP R1, 2
BEQ group_2
; ...
; nothing matched -> group not supported, return 0 to signal failure
MOV R0, 0
BX LR
group_0:
; just return 1 (true) to signal that we are here
MOV R0, 1
BX LR
group_1:
B.W group1
group_2:
B.W group2
}
; Group 1 is a custom_call sub-api,
; it allows calling certain functions by its offset and signature.
; This approach is intended for debugging only,
; because it is bound to certain firmware&hardware version.
;
; R0, R1: (can be used internally)
; R2: offset
; R3: signature (first 4 bytes)
; [SP]: arguments, if any
; If signature didn't match, returns 0xBEBEBEBE.
; This can be used to check if this group is available in certain build:
; dict_write_end(0, 1, 0x8004000, 0) -> signature will not match.
{
proc group1
; ensure that address is even (for signature), then will make it odd
TST R2, 1
BEQ is_even
SUB R2, R2, 1
is_even:
LDR R0, [R2]
; now make sure it is odd which is needed for calling
ADD R2, R2, 1
CMP R0, R3
BEQ good
; signature didn't match → return special value
MOV R0, 0xBEBEBEBE
B ret
good:
; signature matched → load possible arguments and jump
; first save func address to R4
PUSH {R4, LR}
MOV R4, R2
; We cannot know how many arguments we need,
; so load all 4 of them to R0..R3
LDR R0, [SP, 0x8] ; as [SP, 0] is our saved R4 and [SP, 4] is our LR
LDR R1, [SP, 0xC]
LDR R2, [SP, 0x10]
LDR R3, [SP, 0x14]
; shift SP to remaining aruments (if any)
ADD SP, SP, 0x18
; now call!
BLX R4
; restore&return
SUB SP, SP, 0x18
POP {R4,LR}
ret:
; now perform POP for PUSH from call_custom_proc
POP {R2,R3}
; and return
BX LR
}
{
proc group2
BX LR
}