blob: f2e685ab896bf7c11f093051fea19486d7719a6a [file] [log] [blame]
Nolen Johnson802fd002019-08-07 23:56:48 -04001/*
2 * loki_unlok
3 *
4 * A utility to revert the changes made by loki_patch.
5 *
6 * by Dan Rosenberg (@djrbliss)
7 *
8 */
9
10#include <stdio.h>
11#include <fcntl.h>
12#include <sys/mman.h>
13#include <sys/stat.h>
14#include <string.h>
15#include <stdlib.h>
16#include <unistd.h>
17#include "loki.h"
18
19static unsigned char patch[] = PATCH;
20
21/* Find the original address of the ramdisk, which
22 * was embedded in the shellcode. */
23int find_ramdisk_addr(void *img, int sz)
24{
25
26 int i, ramdisk = 0;
27
28 for (i = 0; i < sz - (sizeof(patch) - 9); i++) {
29 if (!memcmp((char *)img + i, patch, sizeof(patch)-9)) {
30 ramdisk = *(int *)(img + i + sizeof(patch) - 5);
31 break;
32 }
33 }
34
35 return ramdisk;
36}
37
38int loki_unlok(const char* in_image, const char* out_image)
39{
40 int ifd, ofd;
41 unsigned int orig_ramdisk_size, orig_kernel_size, orig_ramdisk_addr;
42 unsigned int page_kernel_size, page_ramdisk_size, page_size, page_mask, fake_size;
43 void *orig;
44 struct stat st;
45 struct boot_img_hdr *hdr;
46 struct loki_hdr *loki_hdr;
47
48 ifd = open(in_image, O_RDONLY);
49 if (ifd < 0) {
50 printf("[-] Failed to open %s for reading.\n", in_image);
51 return 1;
52 }
53
54 ofd = open(out_image, O_WRONLY|O_CREAT|O_TRUNC, 0644);
55 if (ofd < 0) {
56 printf("[-] Failed to open %s for writing.\n", out_image);
57 return 1;
58 }
59
60 /* Map the original boot/recovery image */
61 if (fstat(ifd, &st)) {
62 printf("[-] fstat() failed.\n");
63 return 1;
64 }
65
66 orig = mmap(0, (st.st_size + 0x2000 + 0xfff) & ~0xfff, PROT_READ|PROT_WRITE, MAP_PRIVATE, ifd, 0);
67 if (orig == MAP_FAILED) {
68 printf("[-] Failed to mmap input file.\n");
69 return 1;
70 }
71
72 hdr = orig;
73 loki_hdr = orig + 0x400;
74
75 if (memcmp(loki_hdr->magic, "LOKI", 4)) {
76 printf("[-] Input file is not a Loki image.\n");
77
78 /* Copy the entire file to the output transparently */
79 if (write(ofd, orig, st.st_size) != st.st_size) {
80 printf("[-] Failed to copy Loki image.\n");
81 return 1;
82 }
83
84 printf("[+] Copied Loki image to %s.\n", out_image);
85
86 return 0;
87 }
88
89 page_size = hdr->page_size;
90 page_mask = hdr->page_size - 1;
91
92 /* Infer the size of the fake block based on the newer ramdisk address */
93 if (hdr->ramdisk_addr > 0x88f00000 || hdr->ramdisk_addr < 0xfa00000)
94 fake_size = page_size;
95 else
96 fake_size = 0x200;
97
98 orig_ramdisk_addr = find_ramdisk_addr(orig, st.st_size);
99 if (orig_ramdisk_addr == 0) {
100 printf("[-] Failed to find original ramdisk address.\n");
101 return 1;
102 }
103
104 /* Restore the original header values */
105 hdr->ramdisk_addr = orig_ramdisk_addr;
106 hdr->kernel_size = orig_kernel_size = loki_hdr->orig_kernel_size;
107 hdr->ramdisk_size = orig_ramdisk_size = loki_hdr->orig_ramdisk_size;
108
109 /* Erase the loki header */
110 memset(loki_hdr, 0, sizeof(*loki_hdr));
111
112 /* Write the image header */
113 if (write(ofd, orig, page_size) != page_size) {
114 printf("[-] Failed to write header to output file.\n");
115 return 1;
116 }
117
118 page_kernel_size = (orig_kernel_size + page_mask) & ~page_mask;
119
120 /* Write the kernel */
121 if (write(ofd, orig + page_size, page_kernel_size) != page_kernel_size) {
122 printf("[-] Failed to write kernel to output file.\n");
123 return 1;
124 }
125
126 page_ramdisk_size = (orig_ramdisk_size + page_mask) & ~page_mask;
127
128 /* Write the ramdisk */
129 if (write(ofd, orig + page_size + page_kernel_size, page_ramdisk_size) != page_ramdisk_size) {
130 printf("[-] Failed to write ramdisk to output file.\n");
131 return 1;
132 }
133
134 /* Write the device tree if needed */
135 if (hdr->dt_size) {
136
137 printf("[+] Writing device tree.\n");
138
139 /* Skip an additional fake_size (page_size of 0x200) bytes */
140 if (write(ofd, orig + page_size + page_kernel_size + page_ramdisk_size + fake_size, hdr->dt_size) != hdr->dt_size) {
141 printf("[-] Failed to write device tree to output file.\n");
142 return 1;
143 }
144 }
145
146 close(ifd);
147 close(ofd);
148
149 printf("[+] Output file written to %s\n", out_image);
150
151 return 0;
152}