forked from topjohnwu/Magisk
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add extract, repack, hexpatch, sepolicy-injection
- Loading branch information
0 parents
commit 348bc1d
Showing
11 changed files
with
1,262 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
obj | ||
libs |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
[submodule "selinux"] | ||
path = selinux | ||
url = https://github.com/topjohnwu/selinux |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
my_path := $(call my-dir) | ||
|
||
LOCAL_PATH := $(my_path) | ||
|
||
include $(CLEAR_VARS) | ||
LOCAL_MODULE := bootimgtools | ||
LOCAL_MODULE_TAGS := optional | ||
LOCAL_FORCE_STATIC_EXECUTABLE := true | ||
LOCAL_LDFLAGS := -static | ||
LOCAL_STATIC_LIBRARIES := libc libcutils | ||
LOCAL_SRC_FILES := bootimgtools.c extract.c repack.c hexpatch.c | ||
LOCAL_CFLAGS += -std=gnu11 | ||
include $(BUILD_EXECUTABLE) | ||
|
||
include $(CLEAR_VARS) | ||
LOCAL_MODULE := sepolicy-inject | ||
LOCAL_MODULE_TAGS := optional | ||
LOCAL_FORCE_STATIC_EXECUTABLE := true | ||
LOCAL_LDFLAGS := -static | ||
LOCAL_STATIC_LIBRARIES := libc libcutils libsepol | ||
LOCAL_SRC_FILES := sepolicy-inject.c | ||
LOCAL_C_INCLUDES := selinux/libsepol/include/ | ||
LOCAL_CFLAGS += -std=gnu11 | ||
include $(BUILD_EXECUTABLE) | ||
|
||
include selinux/libsepol/Android.mk |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
APP_ABI := x86 armeabi | ||
APP_PIE = true |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
#include <getopt.h> | ||
#include <stdio.h> | ||
|
||
#include "bootimgtools.h" | ||
|
||
/******************** | ||
Patch Boot Image | ||
*********************/ | ||
|
||
int usage(char *arg0) { | ||
fprintf(stderr, "Boot Image Unpack/Repack Tool\n"); | ||
fprintf(stderr, "%s --extract <bootimage>\n", arg0); | ||
fprintf(stderr, " Unpack <bootimage> into current directory\n\n"); | ||
fprintf(stderr, "%s --repack <bootimage>\n", arg0); | ||
fprintf(stderr, " Repack kernel, dt, ramdisk... from current directory to new-image.img\n <bootimage> is the image you've just unpacked\n\n"); | ||
fprintf(stderr, "%s --hexpatch <bootimage> <hexpattern1> <hexpattern2>\n", arg0); | ||
fprintf(stderr, " Search <hexpattern1> in <bootimage>, and replace with <hexpattern2>\n\n"); | ||
return 1; | ||
} | ||
|
||
int main(int argc, char *argv[]) | ||
{ | ||
char ch; | ||
struct option long_options[] = { | ||
{"extract", required_argument, NULL, 'e'}, | ||
{"repack", required_argument, NULL, 'r'}, | ||
{"hexpatch", required_argument, NULL, 'p'}, | ||
{NULL, 0, NULL, 0} | ||
}; | ||
while ((ch = getopt_long(argc, argv, "e:r:p:", long_options, NULL)) != -1) { | ||
switch (ch) { | ||
case 'e': | ||
return extract(optarg); | ||
case 'r': | ||
return repack(optarg); | ||
case 'p': | ||
if (argc < 5) return usage(argv[0]); | ||
optind += 2; | ||
return hexpatch(argv[optind - 3], argv[optind - 2], argv[optind - 1]); | ||
default: | ||
return usage(argv[0]); | ||
} | ||
} | ||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
/* tools/mkbootimg/bootimg.h | ||
** | ||
** Copyright 2007, The Android Open Source Project | ||
** | ||
** Licensed under the Apache License, Version 2.0 (the "License"); | ||
** you may not use this file except in compliance with the License. | ||
** You may obtain a copy of the License at | ||
** | ||
** http://www.apache.org/licenses/LICENSE-2.0 | ||
** | ||
** Unless required by applicable law or agreed to in writing, software | ||
** distributed under the License is distributed on an "AS IS" BASIS, | ||
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
** See the License for the specific language governing permissions and | ||
** limitations under the License. | ||
*/ | ||
|
||
#include <stdint.h> | ||
|
||
#ifndef _BOOT_IMAGE_H_ | ||
#define _BOOT_IMAGE_H_ | ||
|
||
typedef struct boot_img_hdr boot_img_hdr; | ||
|
||
#define BOOT_MAGIC "ANDROID!" | ||
#define BOOT_MAGIC_SIZE 8 | ||
#define BOOT_NAME_SIZE 16 | ||
#define BOOT_ARGS_SIZE 512 | ||
#define BOOT_EXTRA_ARGS_SIZE 1024 | ||
|
||
struct boot_img_hdr | ||
{ | ||
uint8_t magic[BOOT_MAGIC_SIZE]; | ||
|
||
uint32_t kernel_size; /* size in bytes */ | ||
uint32_t kernel_addr; /* physical load addr */ | ||
|
||
uint32_t ramdisk_size; /* size in bytes */ | ||
uint32_t ramdisk_addr; /* physical load addr */ | ||
|
||
uint32_t second_size; /* size in bytes */ | ||
uint32_t second_addr; /* physical load addr */ | ||
|
||
uint32_t tags_addr; /* physical addr for kernel tags */ | ||
uint32_t page_size; /* flash page size we assume */ | ||
uint32_t unused[2]; /* future expansion: should be 0 */ | ||
|
||
uint8_t name[BOOT_NAME_SIZE]; /* asciiz product name */ | ||
|
||
uint8_t cmdline[BOOT_ARGS_SIZE]; | ||
|
||
uint32_t id[8]; /* timestamp / checksum / sha1 / etc */ | ||
|
||
/* Supplemental command line data; kept here to maintain | ||
* binary compatibility with older versions of mkbootimg */ | ||
uint8_t extra_cmdline[BOOT_EXTRA_ARGS_SIZE]; | ||
} __attribute__((packed)); | ||
|
||
/* | ||
** +-----------------+ | ||
** | boot header | 1 page | ||
** +-----------------+ | ||
** | kernel | n pages | ||
** +-----------------+ | ||
** | ramdisk | m pages | ||
** +-----------------+ | ||
** | second stage | o pages | ||
** +-----------------+ | ||
** | ||
** n = (kernel_size + page_size - 1) / page_size | ||
** m = (ramdisk_size + page_size - 1) / page_size | ||
** o = (second_size + page_size - 1) / page_size | ||
** | ||
** 0. all entities are page_size aligned in flash | ||
** 1. kernel and ramdisk are required (size != 0) | ||
** 2. second is optional (second_size == 0 -> no second) | ||
** 3. load each element (kernel, ramdisk, second) at | ||
** the specified physical address (kernel_addr, etc) | ||
** 4. prepare tags at tag_addr. kernel_args[] is | ||
** appended to the kernel commandline in the tags. | ||
** 5. r0 = 0, r1 = MACHINE_TYPE, r2 = tags_addr | ||
** 6. if second_size != 0: jump to second_addr | ||
** else: jump to kernel_addr | ||
*/ | ||
|
||
int extract(char *image); | ||
int repack(char *image); | ||
int hexpatch(char *image, char *from, char *to); | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,141 @@ | ||
#include <stdio.h> | ||
#include <stdlib.h> | ||
#include <unistd.h> | ||
#include <sys/types.h> | ||
#include <sys/stat.h> | ||
#include <sys/sendfile.h> | ||
#include <sys/mman.h> | ||
#include <fcntl.h> | ||
#include <assert.h> | ||
#include <string.h> | ||
|
||
#include "bootimgtools.h" | ||
|
||
void dump(uint8_t *ptr, size_t size, char* filename) { | ||
unlink(filename); | ||
int ofd = open(filename, O_WRONLY|O_CREAT, 0644); | ||
assert(ofd >= 0); | ||
int ret = write(ofd, ptr, size); | ||
assert(ret == size); | ||
close(ofd); | ||
} | ||
|
||
//TODO: Search for other header types | ||
void dump_ramdisk(uint8_t *ptr, size_t size) { | ||
//GZip header | ||
if(memcmp(ptr, "\x1f\x8b\x08\x00", 4) == 0) { | ||
dump(ptr, size, "ramdisk.gz"); | ||
//MTK header | ||
} else if(memcmp(ptr, "\x88\x16\x88\x58", 4) == 0) { | ||
dump(ptr, 0, "ramdisk-mtk"); //Create an mtk flag | ||
dump_ramdisk(ptr+512, size-512); | ||
} else { | ||
//Since our first aim is to extract/repack ramdisk | ||
//Stop if we can't find it | ||
//Still dump it for debug purposes | ||
dump(ptr, size, "ramdisk"); | ||
|
||
fprintf(stderr, "Unknown ramdisk type\n"); | ||
abort(); | ||
} | ||
} | ||
|
||
void search_security_hdr(uint8_t *buf, size_t size) { | ||
if(memcmp(buf, "CHROMEOS", 8) == 0) { | ||
dump(buf, 0, "chromeos"); | ||
return; | ||
} | ||
} | ||
|
||
int search_security(uint8_t *buf, size_t size, int pos) { | ||
//Rockchip signature | ||
if(memcmp(buf+1024, "SIGN", 4) == 0) { | ||
//Rockchip signature AT LEAST means the bootloader will check the crc | ||
dump(buf, 0, "rkcrc"); //Create an flag to tell it | ||
|
||
//And it's possible there is a security too | ||
return 1; | ||
} | ||
|
||
//If we didn't parse the whole file, it is highly likely there is a boot signature | ||
if(pos < size) { | ||
return 1; | ||
} | ||
|
||
return 0; | ||
} | ||
|
||
/* | ||
* TODO: | ||
* - At the moment we dump kernel + ramdisk + second + DT, it's likely we only want ramdisk | ||
* - Error-handling via assert() is perhaps not the best | ||
*/ | ||
int extract(char *image) { | ||
|
||
int fd = open(image, O_RDONLY); | ||
off_t size = lseek(fd, 0, SEEK_END); | ||
lseek(fd, 0, SEEK_SET); | ||
uint8_t *orig = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0); | ||
uint8_t *base = orig; | ||
assert(base); | ||
|
||
search_security_hdr(base, size); | ||
|
||
//We're searching for the header in the whole file, we could stop earlier. | ||
//At least HTC and nVidia have a signature header | ||
while(base<(orig+size)) { | ||
if(memcmp(base, BOOT_MAGIC, BOOT_MAGIC_SIZE) == 0) | ||
break; | ||
//We're searching every 256bytes, is it ok? | ||
base += 256; | ||
} | ||
assert(base < (orig+size)); | ||
|
||
struct boot_img_hdr *hdr = (struct boot_img_hdr*) base; | ||
assert( | ||
hdr->page_size == 2048 || | ||
hdr->page_size == 4096 || | ||
hdr->page_size == 16384 | ||
); | ||
|
||
long pos = hdr->page_size; | ||
dump(base+pos, hdr->kernel_size, "kernel"); | ||
pos += hdr->kernel_size + hdr->page_size-1; | ||
pos &= ~(hdr->page_size-1L); | ||
|
||
dump_ramdisk(base+pos, hdr->ramdisk_size); | ||
pos += hdr->ramdisk_size + hdr->page_size-1; | ||
pos &= ~(hdr->page_size-1L); | ||
|
||
if(hdr->second_size) { | ||
assert( (pos+hdr->second_size) <= size); | ||
dump(base+pos, hdr->second_size, "second"); | ||
pos += hdr->second_size + hdr->page_size-1; | ||
pos &= ~(hdr->page_size-1L); | ||
} | ||
|
||
//This is non-standard, so we triple check | ||
if( hdr->unused[0] && | ||
pos < size && | ||
(pos+hdr->unused[0]) <= size) { | ||
|
||
if(memcmp(base+pos, "QCDT", 4) == 0 || | ||
memcmp(base+pos, "SPRD", 4) == 0 || | ||
memcmp(base+pos, "DTBH", 4) == 0 | ||
) { | ||
dump(base+pos, hdr->unused[0], "dt"); | ||
pos += hdr->unused[0] + hdr->page_size-1; | ||
pos &= ~(hdr->page_size-1L); | ||
} | ||
} | ||
|
||
//If we think we find some security-related infos in the boot.img | ||
//create a "secure" flag to warn the user it is dangerous | ||
if(search_security(base, size, pos)) { | ||
dump(base, 0, "secure"); | ||
} | ||
|
||
munmap(orig, size); | ||
close(fd); | ||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
#include <getopt.h> | ||
#include <stdio.h> | ||
#include <sys/types.h> | ||
#include <sys/stat.h> | ||
#include <unistd.h> | ||
#include <fcntl.h> | ||
#include <stdlib.h> | ||
#include <string.h> | ||
|
||
#include "bootimgtools.h" | ||
|
||
int hex2int(char c) { | ||
int first = c / 16 - 3; | ||
int second = c % 16; | ||
int result = first * 10 + second; | ||
if(result > 9) result--; | ||
return result; | ||
} | ||
|
||
int hex2ascii(char c, char d) { | ||
int high = hex2int(c) * 16; | ||
int low = hex2int(d); | ||
return high+low; | ||
} | ||
|
||
void hexstr2str(char *hex, char *str) { | ||
char buf = 0; | ||
for(int i = 0, length = strlen(hex); i < length; ++i){ | ||
if(i % 2){ | ||
str[i / 2] = hex2ascii(buf, hex[i]); | ||
} else{ | ||
buf = hex[i]; | ||
} | ||
} | ||
} | ||
|
||
int hexpatch(char * image, char *from, char *to) { | ||
int fd = open(image, O_RDWR), patternsize = strlen(from) / 2, patchsize = strlen(to) / 2; | ||
off_t filesize = lseek(fd, 0, SEEK_END); | ||
char *file, *pattern, *patch, *start; | ||
file = malloc(sizeof (char) * filesize); | ||
pattern = malloc(sizeof (char) * patternsize); | ||
patch = malloc(sizeof (char) * patchsize); | ||
lseek(fd, 0, SEEK_SET); | ||
read(fd, file, filesize); | ||
hexstr2str(from, pattern); | ||
hexstr2str(to, patch); | ||
for (off_t i = 0; i < filesize;) { | ||
int j; | ||
for (j = 0; j < patternsize; ++j) { | ||
if(file[i + j] != pattern[j]) break; | ||
} | ||
if (j == patternsize) { | ||
fprintf(stderr, "Pattern %s found!\nPatching to %s\n", from, to); | ||
lseek(fd, i, SEEK_SET); | ||
write(fd, patch, patchsize); | ||
} | ||
if(j == 0) j = 1; | ||
i += j; | ||
} | ||
free(file); | ||
free(pattern); | ||
free(patch); | ||
close(fd); | ||
return 0; | ||
} |
Oops, something went wrong.