summaryrefslogtreecommitdiffstats
path: root/irecovery.c
diff options
context:
space:
mode:
Diffstat (limited to 'irecovery.c')
-rw-r--r--irecovery.c344
1 files changed, 344 insertions, 0 deletions
diff --git a/irecovery.c b/irecovery.c
new file mode 100644
index 0000000..39ac425
--- /dev/null
+++ b/irecovery.c
@@ -0,0 +1,344 @@
1/**
2 * GreenPois0n iRecovery - irecovery.c
3 * Copyright (C) 2010 Chronic-Dev Team
4 * Copyright (C) 2010 Joshua Hill
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 **/
19
20#include <stdio.h>
21#include <stdlib.h>
22#include <unistd.h>
23#include <libirecovery.h>
24#include <readline/readline.h>
25#include <readline/history.h>
26
27#define FILE_HISTORY_PATH ".irecovery"
28#define debug(...) if(verbose) fprintf(stderr, __VA_ARGS__)
29
30enum {
31 kResetDevice, kStartShell, kSendCommand, kSendFile, kSendExploit, kSendScript
32};
33
34static unsigned int quit = 0;
35static unsigned int verbose = 0;
36
37void print_progress_bar(double progress);
38int received_cb(irecv_client_t client, const irecv_event_t* event);
39int progress_cb(irecv_client_t client, const irecv_event_t* event);
40int precommand_cb(irecv_client_t client, const irecv_event_t* event);
41int postcommand_cb(irecv_client_t client, const irecv_event_t* event);
42
43void shell_usage() {
44 printf("Usage:\n");
45 printf("\t/upload <file>\tSend file to client.\n");
46 printf("\t/exploit [file]\tSend usb exploit with optional payload\n");
47 printf("\t/help\t\tShow this help.\n");
48 printf("\t/exit\t\tExit interactive shell.\n");
49}
50
51void parse_command(irecv_client_t client, unsigned char* command, unsigned int size) {
52 char* cmd = strdup(command);
53 char* action = strtok(cmd, " ");
54 debug("Executing %s\n", action);
55 if (!strcmp(cmd, "/exit")) {
56 quit = 1;
57 } else
58
59 if (!strcmp(cmd, "/help")) {
60 shell_usage();
61 } else
62
63 if (!strcmp(cmd, "/upload")) {
64 char* filename = strtok(NULL, " ");
65 debug("Uploading files %s\n", filename);
66 if (filename != NULL) {
67 irecv_send_file(client, filename, 0);
68 }
69 } else
70
71 if (!strcmp(cmd, "/exploit")) {
72 char* filename = strtok(NULL, " ");
73 debug("Sending exploit %s\n", filename);
74 if (filename != NULL) {
75 irecv_send_file(client, filename, 0);
76 }
77 irecv_send_exploit(client);
78 } else
79
80 if (!strcmp(cmd, "/execute")) {
81 char* filename = strtok(NULL, " ");
82 debug("Executing script %s\n", filename);
83 if (filename != NULL) {
84 irecv_execute_script(client, filename);
85 }
86 }
87
88
89 free(action);
90}
91
92void load_command_history() {
93 read_history(FILE_HISTORY_PATH);
94}
95
96void append_command_to_history(char* cmd) {
97 add_history(cmd);
98 write_history(FILE_HISTORY_PATH);
99}
100
101void init_shell(irecv_client_t client) {
102 irecv_error_t error = 0;
103 load_command_history();
104 irecv_event_subscribe(client, IRECV_PROGRESS, &progress_cb, NULL);
105 irecv_event_subscribe(client, IRECV_RECEIVED, &received_cb, NULL);
106 irecv_event_subscribe(client, IRECV_PRECOMMAND, &precommand_cb, NULL);
107 irecv_event_subscribe(client, IRECV_POSTCOMMAND, &postcommand_cb, NULL);
108 while (!quit) {
109 error = irecv_receive(client);
110 if (error != IRECV_E_SUCCESS) {
111 debug("%s\n", irecv_strerror(error));
112 break;
113 }
114
115 char* cmd = readline("> ");
116 if (cmd && *cmd) {
117 error = irecv_send_command(client, cmd);
118 if (error != IRECV_E_SUCCESS) {
119 quit = 1;
120 }
121
122 append_command_to_history(cmd);
123 free(cmd);
124 }
125 }
126}
127
128int received_cb(irecv_client_t client, const irecv_event_t* event) {
129 if (event->type == IRECV_RECEIVED) {
130 int i = 0;
131 int size = event->size;
132 char* data = event->data;
133 for (i = 0; i < size; i++) {
134 printf("%c", data[i]);
135 }
136 }
137 return 0;
138}
139
140int precommand_cb(irecv_client_t client, const irecv_event_t* event) {
141 if (event->type == IRECV_PRECOMMAND) {
142 irecv_error_t error = 0;
143 if (event->data[0] == '/') {
144 parse_command(client, event->data, event->size);
145 return -1;
146 }
147 }
148 return 0;
149}
150
151int postcommand_cb(irecv_client_t client, const irecv_event_t* event) {
152 char* value = NULL;
153 char* action = NULL;
154 char* command = NULL;
155 char* argument = NULL;
156 irecv_error_t error = IRECV_E_SUCCESS;
157
158 if (event->type == IRECV_POSTCOMMAND) {
159 command = strdup(event->data);
160 action = strtok(command, " ");
161 if (!strcmp(action, "getenv")) {
162 argument = strtok(NULL, " ");
163 error = irecv_getenv(client, argument, &value);
164 if (error != IRECV_E_SUCCESS) {
165 debug("%s\n", irecv_strerror(error));
166 free(command);
167 return error;
168 }
169 printf("%s\n", value);
170 free(value);
171 }
172
173 if (!strcmp(action, "reboot")) {
174 quit = 1;
175 }
176 }
177
178 if (command) free(command);
179 return 0;
180}
181
182int progress_cb(irecv_client_t client, const irecv_event_t* event) {
183 if (event->type == IRECV_PROGRESS) {
184 print_progress_bar(event->progress);
185 }
186 return 0;
187}
188
189void print_progress_bar(double progress) {
190 int i = 0;
191 if(progress < 0) {
192 return;
193 }
194
195 if(progress > 100) {
196 progress = 100;
197 }
198
199 printf("\r[");
200 for(i = 0; i < 50; i++) {
201 if(i < progress / 2) {
202 printf("=");
203 } else {
204 printf(" ");
205 }
206 }
207
208 printf("] %3.1f%%", progress);
209 fflush(stdout);
210 if(progress == 100) {
211 printf("\n");
212 }
213}
214
215void print_usage() {
216 printf("iRecovery - iDevice Recovery Utility\n");
217 printf("Usage: ./irecovery [args]\n");
218 printf("\t-v\t\tStart irecovery in verbose mode.\n");
219 printf("\t-c <cmd>\tSend command to client.\n");
220 printf("\t-f <file>\tSend file to client.\n");
221 printf("\t-k [payload]\tSend usb exploit to client.\n");
222 printf("\t-h\t\tShow this help.\n");
223 printf("\t-r\t\tReset client.\n");
224 printf("\t-s\t\tStart interactive shell.\n");
225 printf("\t-e <script>\tExecutes recovery shell script.\n");
226 exit(1);
227}
228
229int main(int argc, char* argv[]) {
230 int i = 0;
231 int opt = 0;
232 int action = 0;
233 char* argument = NULL;
234 irecv_error_t error = 0;
235 if (argc == 1) print_usage();
236 while ((opt = getopt(argc, argv, "vhrsc:f:e:k::")) > 0) {
237 switch (opt) {
238 case 'v':
239 verbose += 1;
240 break;
241
242 case 'h':
243 print_usage();
244 break;
245
246 case 'r':
247 action = kResetDevice;
248 break;
249
250 case 's':
251 action = kStartShell;
252 break;
253
254 case 'f':
255 action = kSendFile;
256 argument = optarg;
257 break;
258
259 case 'c':
260 action = kSendCommand;
261 argument = optarg;
262 break;
263
264 case 'k':
265 action = kSendExploit;
266 argument = optarg;
267 break;
268
269 case 'e':
270 action = kSendScript;
271 argument = optarg;
272 break;
273
274 default:
275 fprintf(stderr, "Unknown argument\n");
276 return -1;
277 }
278 }
279
280 irecv_client_t client = NULL;
281 for (i = 0; i <= 5; i++) {
282 debug("Attempting to connect... \n");
283
284 if (irecv_open(&client) != IRECV_E_SUCCESS)
285 sleep(1);
286 else
287 break;
288
289 if (i == 5) {
290 return -1;
291 }
292 }
293
294 if (verbose) irecv_set_debug_level(verbose);
295
296 switch (action) {
297 case kResetDevice:
298 irecv_reset(client);
299 break;
300
301 case kSendFile:
302 irecv_event_subscribe(client, IRECV_PROGRESS, &progress_cb, NULL);
303 error = irecv_send_file(client, argument, 0);
304 debug("%s\n", irecv_strerror(error));
305 break;
306
307 case kSendCommand:
308 error = irecv_send_command(client, argument);
309 debug("%s\n", irecv_strerror(error));
310 break;
311
312 case kSendExploit:
313 if (argument != NULL) {
314 irecv_event_subscribe(client, IRECV_PROGRESS, &progress_cb, NULL);
315 error = irecv_send_file(client, argument, 0);
316 if (error != IRECV_E_SUCCESS) {
317 debug("%s\n", irecv_strerror(error));
318 break;
319 }
320 }
321 error = irecv_send_exploit(client);
322 debug("%s\n", irecv_strerror(error));
323 break;
324
325 case kStartShell:
326 init_shell(client);
327 break;
328
329 case kSendScript:
330 error = irecv_execute_script(client, argument);
331 if(error != IRECV_E_SUCCESS) {
332 debug("%s\n", irecv_strerror(error));
333 }
334 break;
335
336 default:
337 fprintf(stderr, "Unknown action\n");
338 break;
339 }
340
341 irecv_close(client);
342 return 0;
343}
344