mirror of
https://github.com/topjohnwu/Magisk.git
synced 2024-11-23 18:15:30 +00:00
More cpio features
This commit is contained in:
parent
1e3bcfc8cd
commit
3f3568d8af
@ -9,7 +9,7 @@ LOCAL_C_INCLUDES := \
|
||||
jni/ndk-compression/lz4/lib/ \
|
||||
jni/ndk-compression/bzip2/
|
||||
|
||||
LOCAL_SRC_FILES := main.c unpack.c repack.c hexpatch.c parseimg.c compress.c utils.c cpio.c
|
||||
LOCAL_SRC_FILES := main.c unpack.c repack.c hexpatch.c parseimg.c compress.c utils.c cpio.c sha1.c
|
||||
LOCAL_CFLAGS += -DZLIB_CONST
|
||||
include $(BUILD_EXECUTABLE)
|
||||
|
||||
|
@ -13,10 +13,10 @@ static void write_file(const int fd, const void *buf, const size_t size, const c
|
||||
static void report(const int mode, const char* filename) {
|
||||
switch(mode) {
|
||||
case 0:
|
||||
printf("Decompressing to %s\n", filename);
|
||||
printf("Decompressing to [%s]\n\n", filename);
|
||||
break;
|
||||
default:
|
||||
printf("Compressing to %s\n", filename);
|
||||
printf("Compressing to [%s]\n\n", filename);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -30,6 +30,9 @@ static void cpio_vec_insert(vector *v, cpio_file *n) {
|
||||
t = f;
|
||||
if (strcmp(f->filename, n->filename) == 0) {
|
||||
// Replace, then all is done
|
||||
free(f->filename);
|
||||
free(f->data);
|
||||
free(f);
|
||||
vec_entry(v)[_i] = n;
|
||||
return;
|
||||
} else if (strcmp(f->filename, n->filename) > 0) {
|
||||
@ -42,9 +45,13 @@ static void cpio_vec_insert(vector *v, cpio_file *n) {
|
||||
vec_push_back(v, t);
|
||||
}
|
||||
|
||||
static int cpio_compare(const void *a, const void *b) {
|
||||
return strcmp((*(cpio_file **) a)->filename, (*(cpio_file **) b)->filename);
|
||||
}
|
||||
|
||||
// Parse cpio file to a vector of cpio_file
|
||||
void parse_cpio(const char *filename, vector *v) {
|
||||
printf("\nLoading cpio: [%s]\n\n", filename);
|
||||
static void parse_cpio(const char *filename, vector *v) {
|
||||
printf("Loading cpio: [%s]\n\n", filename);
|
||||
int fd = open(filename, O_RDONLY);
|
||||
if (fd < 0)
|
||||
error(1, "Cannot open %s", filename);
|
||||
@ -68,6 +75,11 @@ void parse_cpio(const char *filename, vector *v) {
|
||||
f->filename = malloc(f->namesize);
|
||||
read(fd, f->filename, f->namesize);
|
||||
file_align(fd, 4, 0);
|
||||
if (strcmp(f->filename, "TRAILER!!!") == 0 || strcmp(f->filename, ".") == 0) {
|
||||
free(f->filename);
|
||||
free(f);
|
||||
break;
|
||||
}
|
||||
if (f->filesize) {
|
||||
f->data = malloc(f->filesize);
|
||||
read(fd, f->data, f->filesize);
|
||||
@ -76,10 +88,12 @@ void parse_cpio(const char *filename, vector *v) {
|
||||
vec_push_back(v, f);
|
||||
}
|
||||
close(fd);
|
||||
// Sort by name
|
||||
vec_sort(v, cpio_compare);
|
||||
}
|
||||
|
||||
void dump_cpio(const char *filename, vector *v) {
|
||||
printf("\nDump cpio: [%s]\n\n", filename);
|
||||
static void dump_cpio(const char *filename, vector *v) {
|
||||
printf("Dump cpio: [%s]\n\n", filename);
|
||||
int fd = open_new(filename);
|
||||
unsigned inode = 300000;
|
||||
char header[111];
|
||||
@ -109,9 +123,14 @@ void dump_cpio(const char *filename, vector *v) {
|
||||
file_align(fd, 4, 1);
|
||||
}
|
||||
}
|
||||
// Write trailer
|
||||
sprintf(header, "070701%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x", inode++, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 11, 0);
|
||||
write(fd, header, 110);
|
||||
write(fd, "TRAILER!!!\0", 11);
|
||||
file_align(fd, 4, 1);
|
||||
}
|
||||
|
||||
void cpio_vec_destroy(vector *v) {
|
||||
static void cpio_vec_destroy(vector *v) {
|
||||
// Free each cpio_file
|
||||
cpio_file *f;
|
||||
vec_for_each(v, f) {
|
||||
@ -122,7 +141,7 @@ void cpio_vec_destroy(vector *v) {
|
||||
vec_destroy(v);
|
||||
}
|
||||
|
||||
void cpio_rm(int recursive, const char *entry, vector *v) {
|
||||
static void cpio_rm(int recursive, const char *entry, vector *v) {
|
||||
cpio_file *f;
|
||||
vec_for_each(v, f) {
|
||||
if ((recursive && strncmp(f->filename, entry, strlen(entry)) == 0)
|
||||
@ -132,7 +151,7 @@ void cpio_rm(int recursive, const char *entry, vector *v) {
|
||||
}
|
||||
}
|
||||
|
||||
void cpio_mkdir(mode_t mode, const char *entry, vector *v) {
|
||||
static void cpio_mkdir(mode_t mode, const char *entry, vector *v) {
|
||||
cpio_file *f = calloc(sizeof(*f), 1);
|
||||
f->mode = S_IFDIR | mode;
|
||||
f->namesize = strlen(entry) + 1;
|
||||
@ -141,7 +160,7 @@ void cpio_mkdir(mode_t mode, const char *entry, vector *v) {
|
||||
cpio_vec_insert(v, f);
|
||||
}
|
||||
|
||||
void cpio_add(mode_t mode, const char *entry, const char *filename, vector *v) {
|
||||
static void cpio_add(mode_t mode, const char *entry, const char *filename, vector *v) {
|
||||
int fd = open(filename, O_RDONLY);
|
||||
if (fd < 0)
|
||||
error(1, "Cannot open %s", filename);
|
||||
@ -156,3 +175,156 @@ void cpio_add(mode_t mode, const char *entry, const char *filename, vector *v) {
|
||||
read(fd, f->data, f->filesize);
|
||||
cpio_vec_insert(v, f);
|
||||
}
|
||||
|
||||
static void cpio_test(vector *v) {
|
||||
int ret = 0;
|
||||
cpio_file *f;
|
||||
vec_for_each(v, f) {
|
||||
if (strcmp(f->filename, "sbin/launch_daemonsu.sh") == 0) {
|
||||
if (!ret) ret = 2;
|
||||
} else if (strcmp(f->filename, "magisk") == 0) {
|
||||
ret = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
cpio_vec_destroy(v);
|
||||
exit(ret);
|
||||
}
|
||||
|
||||
static int check_verity_pattern(const char *s) {
|
||||
int pos = 0;
|
||||
if (s[0] == ',') ++pos;
|
||||
if (strncmp(s + pos, "verify", 6) != 0) return -1;
|
||||
pos += 6;
|
||||
if (s[pos] == '=') {
|
||||
while (s[pos] != ' ' && s[pos] != '\n' && s[pos] != ',') ++pos;
|
||||
}
|
||||
return pos;
|
||||
}
|
||||
|
||||
static void cpio_dmverity(vector *v) {
|
||||
cpio_file *f;
|
||||
size_t read, write;
|
||||
int skip;
|
||||
vec_for_each(v, f) {
|
||||
if (strstr(f->filename, "fstab") != NULL && S_ISREG(f->mode)) {
|
||||
for (read = 0, write = 0; read < f->filesize; ++read, ++write) {
|
||||
skip = check_verity_pattern(f->data + read);
|
||||
if (skip > 0) {
|
||||
printf("Remove pattern [%.*s] in [%s]\n", (int) skip, f->data + read, f->filename);
|
||||
read += skip;
|
||||
}
|
||||
f->data[write] = f->data[read];
|
||||
}
|
||||
f->filesize = write;
|
||||
} else if (strcmp(f->filename, "verity_key") == 0) {
|
||||
f->remove = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
static void cpio_forceencrypt(vector *v) {
|
||||
cpio_file *f;
|
||||
size_t read, write;
|
||||
#define ENCRYPT_LIST_SIZE 2
|
||||
const char *ENCRYPT_LIST[ENCRYPT_LIST_SIZE] = { "forceencrypt", "forcefdeorfbe" };
|
||||
vec_for_each(v, f) {
|
||||
if (strstr(f->filename, "fstab") != NULL && S_ISREG(f->mode)) {
|
||||
for (read = 0, write = 0; read < f->filesize; ++read, ++write) {
|
||||
for (int i = 0 ; i < ENCRYPT_LIST_SIZE; ++i) {
|
||||
if (strncmp(f->data + read, ENCRYPT_LIST[i], strlen(ENCRYPT_LIST[i])) == 0) {
|
||||
memcpy(f->data + write, "encryptable", 11);
|
||||
printf("Replace [%s] with [%s] in [%s]\n", ENCRYPT_LIST[i], "encryptable", f->filename);
|
||||
write += 11;
|
||||
read += strlen(ENCRYPT_LIST[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
f->data[write] = f->data[read];
|
||||
}
|
||||
f->filesize = write;
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
static void cpio_extract(const char *entry, const char *filename, vector *v) {
|
||||
cpio_file *f;
|
||||
vec_for_each(v, f) {
|
||||
if (strcmp(f->filename, entry) == 0 && S_ISREG(f->mode)) {
|
||||
printf("Extracting [%s] to [%s]\n\n", entry, filename);
|
||||
int fd = open_new(filename);
|
||||
write(fd, f->data, f->filesize);
|
||||
fchmod(fd, f->mode);
|
||||
fchown(fd, f->uid, f->gid);
|
||||
close(fd);
|
||||
return;
|
||||
}
|
||||
}
|
||||
error(1, "Cannot find the file entry [%s]", entry);
|
||||
}
|
||||
|
||||
int cpio_commands(const char *command, int argc, char *argv[]) {
|
||||
int recursive = 0;
|
||||
command_t cmd;
|
||||
char *incpio = argv[0];
|
||||
++argv;
|
||||
--argc;
|
||||
if (strcmp(command, "test") == 0) {
|
||||
cmd = TEST;
|
||||
} else if (strcmp(command, "patch-dmverity") == 0) {
|
||||
cmd = DMVERITY;
|
||||
} else if (strcmp(command, "patch-forceencrypt") == 0) {
|
||||
cmd = FORCEENCRYPT;
|
||||
} else if (argc == 2 && strcmp(command, "extract") == 0) {
|
||||
cmd = EXTRACT;
|
||||
} else if (argc > 0 && strcmp(command, "rm") == 0) {
|
||||
cmd = RM;
|
||||
if (argc == 2 && strcmp(argv[0], "-r") == 0) {
|
||||
recursive = 1;
|
||||
++argv;
|
||||
--argc;
|
||||
}
|
||||
} else if (argc == 2 && strcmp(command, "mkdir") == 0) {
|
||||
cmd = MKDIR;
|
||||
} else if (argc == 3 && strcmp(command, "add") == 0) {
|
||||
cmd = ADD;
|
||||
} else {
|
||||
cmd = NONE;
|
||||
return 1;
|
||||
}
|
||||
vector v;
|
||||
vec_init(&v);
|
||||
parse_cpio(incpio, &v);
|
||||
switch(cmd) {
|
||||
case TEST:
|
||||
cpio_test(&v);
|
||||
break;
|
||||
case DMVERITY:
|
||||
cpio_dmverity(&v);
|
||||
break;
|
||||
case FORCEENCRYPT:
|
||||
cpio_forceencrypt(&v);
|
||||
break;
|
||||
case EXTRACT:
|
||||
cpio_extract(argv[0], argv[1], &v);
|
||||
break;
|
||||
case RM:
|
||||
cpio_rm(recursive, argv[0], &v);
|
||||
break;
|
||||
case MKDIR:
|
||||
cpio_mkdir(strtoul(argv[0], NULL, 8), argv[1], &v);
|
||||
break;
|
||||
case ADD:
|
||||
cpio_add(strtoul(argv[0], NULL, 8), argv[1], argv[2], &v);
|
||||
break;
|
||||
default:
|
||||
// Never happen
|
||||
break;
|
||||
}
|
||||
dump_cpio(incpio, &v);
|
||||
cpio_vec_destroy(&v);
|
||||
return 0;
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ typedef struct cpio_file {
|
||||
uint32_t namesize;
|
||||
// uint32_t check;
|
||||
char *filename;
|
||||
void *data;
|
||||
char *data;
|
||||
int remove;
|
||||
} cpio_file;
|
||||
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "bootimg.h"
|
||||
#include "sha1.h"
|
||||
|
||||
#define windowBits 15
|
||||
#define ZLIB_GZIP 16
|
||||
@ -54,7 +55,11 @@ typedef enum {
|
||||
NONE,
|
||||
RM,
|
||||
MKDIR,
|
||||
ADD
|
||||
ADD,
|
||||
EXTRACT,
|
||||
TEST,
|
||||
DMVERITY,
|
||||
FORCEENCRYPT
|
||||
} command_t;
|
||||
|
||||
extern char *SUP_EXT_LIST[SUP_NUM];
|
||||
@ -71,6 +76,7 @@ typedef struct vector {
|
||||
} vector;
|
||||
void vec_init(vector *v);
|
||||
void vec_push_back(vector *v, void *p);
|
||||
void vec_sort(vector *v, int (*compar)(const void *, const void *));
|
||||
void vec_destroy(vector *v);
|
||||
|
||||
#define vec_size(v) (v)->size
|
||||
@ -93,6 +99,7 @@ void repack(const char* orig_image, const char* out_image);
|
||||
void hexpatch(const char *image, const char *from, const char *to);
|
||||
void error(int rc, const char *msg, ...);
|
||||
void parse_img(unsigned char *orig, size_t size);
|
||||
int cpio_commands(const char *command, int argc, char *argv[]);
|
||||
void cleanup();
|
||||
|
||||
// Compressions
|
||||
@ -105,14 +112,6 @@ void comp_file(const char *method, const char *from);
|
||||
int decomp(file_t type, const char *to, const unsigned char *from, size_t size);
|
||||
void decomp_file(char *from);
|
||||
|
||||
// CPIO
|
||||
void parse_cpio(const char *filename, vector *v);
|
||||
void dump_cpio(const char *filename, vector *v);
|
||||
void cpio_vec_destroy(vector *v);
|
||||
void cpio_rm(int recursive, const char *entry, vector *v);
|
||||
void cpio_mkdir(mode_t mode, const char *entry, vector *v);
|
||||
void cpio_add(mode_t mode, const char *entry, const char *filename, vector *v);
|
||||
|
||||
// Utils
|
||||
void mmap_ro(const char *filename, unsigned char **buf, size_t *size);
|
||||
void mmap_rw(const char *filename, unsigned char **buf, size_t *size);
|
||||
|
@ -5,36 +5,48 @@
|
||||
*********************/
|
||||
|
||||
static void usage(char *arg0) {
|
||||
fprintf(stderr, "\n");
|
||||
fprintf(stderr, "%s --unpack <bootimg>\n", arg0);
|
||||
fprintf(stderr, " Unpack <bootimg> to kernel, ramdisk.cpio, (second), (dtb) into the\n current directory\n\n");
|
||||
fprintf(stderr, " Unpack <bootimg> to kernel, ramdisk.cpio, (second), (dtb) into the\n current directory\n");
|
||||
fprintf(stderr, "\n");
|
||||
|
||||
fprintf(stderr, "%s --repack <origbootimg> [outbootimg]\n", arg0);
|
||||
fprintf(stderr, " Repack kernel, ramdisk.cpio[.ext], second, dtb... from current directory\n");
|
||||
fprintf(stderr, " to [outbootimg], or new-boot.img if not specified.\n");
|
||||
fprintf(stderr, " It will compress ramdisk.cpio with the same method used in <origbootimg>\n");
|
||||
fprintf(stderr, " if exists, or attempt to find ramdisk.cpio.[ext], and repack\n");
|
||||
fprintf(stderr, " directly with the compressed ramdisk file\n\n");
|
||||
fprintf(stderr, " directly with the compressed ramdisk file\n");
|
||||
fprintf(stderr, "\n");
|
||||
|
||||
fprintf(stderr, "%s --hexpatch <file> <hexpattern1> <hexpattern2>\n", arg0);
|
||||
fprintf(stderr, " Search <hexpattern1> in <file>, and replace with <hexpattern2>\n\n");
|
||||
fprintf(stderr, " Search <hexpattern1> in <file>, and replace with <hexpattern2>\n");
|
||||
fprintf(stderr, "\n");
|
||||
|
||||
fprintf(stderr, "%s --cpio-<cmd> <incpio> <outcpio> [flags...] [params...]\n", arg0);
|
||||
fprintf(stderr, " Do cpio related cmds to <incpio> and output to <outcpio>\n Supported commands:\n");
|
||||
fprintf(stderr, " --cpio-rm [-r] <entry>\n Remove entry from cpio, flag -r to remove recursively\n");
|
||||
fprintf(stderr, " --cpio-mkdir <mode> <entry>\n Create directory as an <entry>\n");
|
||||
fprintf(stderr, " --cpio-add <mode> <entry> <infile>\n Add <infile> as an <entry>; will replace <entry> if already exists\n");
|
||||
fprintf(stderr, " e.g: the command to add /tmp/tmpfile as entry init.magisk.rc:\n");
|
||||
fprintf(stderr, " %s --cpio-add <incpio> <outcpio> 0750 init.magisk.rc /tmp/tmpfile\n\n", arg0);
|
||||
fprintf(stderr, "%s --cpio-<cmd> <incpio> [flags...] [params...]\n", arg0);
|
||||
fprintf(stderr, " Do cpio related cmds to <incpio> (modifications are done directly)\n Supported commands:\n");
|
||||
fprintf(stderr, " --cpio-rm <incpio> [-r] <entry>\n Remove entry from cpio, flag -r to remove recursively\n");
|
||||
fprintf(stderr, " --cpio-mkdir <incpio> <mode> <entry>\n Create directory as an <entry>\n");
|
||||
fprintf(stderr, " --cpio-add <incpio> <mode> <entry> <infile>\n Add <infile> as an <entry>; replaces <entry> if already exists\n");
|
||||
fprintf(stderr, " --cpio-extract <incpio> <entry> <outfile>\n Extract <entry> to <outfile>\n");
|
||||
fprintf(stderr, " --cpio-test <incpio>\n Return value: 0/not patched 1/Magisk 2/SuperSU\n");
|
||||
fprintf(stderr, " --cpio-patch-dmverity <incpio>\n Remove dm-verity\n");
|
||||
fprintf(stderr, " --cpio-patch-forceencrypt <incpio>\n Change forceencrypt flag to encryptable\n");
|
||||
fprintf(stderr, "\n");
|
||||
|
||||
fprintf(stderr, "%s --compress[=method] <file>\n", arg0);
|
||||
fprintf(stderr, " Compress <file> with [method], or gzip if not specified.\n Supported methods: " SUP_LIST "\n\n");
|
||||
fprintf(stderr, " Compress <file> with [method], or gzip if not specified.\n Supported methods: " SUP_LIST "\n");
|
||||
fprintf(stderr, "\n");
|
||||
|
||||
fprintf(stderr, "%s --decompress <file>\n", arg0);
|
||||
fprintf(stderr, " Auto check file type, and decompress <file> accordingly\n Supported methods: " SUP_LIST "\n\n");
|
||||
fprintf(stderr, " Auto check file type, and decompress <file> accordingly\n Supported methods: " SUP_LIST "\n");
|
||||
fprintf(stderr, "\n");
|
||||
|
||||
fprintf(stderr, "%s --sha1 <file>\n", arg0);
|
||||
fprintf(stderr, " Print the SHA1 checksum for <file>\n");
|
||||
fprintf(stderr, "\n");
|
||||
|
||||
fprintf(stderr, "%s --cleanup\n", arg0);
|
||||
fprintf(stderr, " Cleanup the current working directory\n\n");
|
||||
fprintf(stderr, " Cleanup the current working directory\n");
|
||||
fprintf(stderr, "\n");
|
||||
|
||||
exit(1);
|
||||
}
|
||||
@ -49,10 +61,19 @@ void error(int rc, const char *msg, ...) {
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
printf("MagiskBoot (by topjohnwu) - Boot Image Modification Tool\n");
|
||||
printf("MagiskBoot (by topjohnwu) - Boot Image Modification Tool\n\n");
|
||||
|
||||
if (argc > 1 && strcmp(argv[1], "--cleanup") == 0) {
|
||||
cleanup();
|
||||
} else if (argc > 2 && strcmp(argv[1], "--sha1") == 0) {
|
||||
char sha1[21], *buf;
|
||||
size_t size;
|
||||
mmap_ro(argv[2], (unsigned char **) &buf, &size);
|
||||
SHA1(sha1, buf, size);
|
||||
for (int i = 0; i < 20; ++i)
|
||||
printf("%02x", sha1[i]);
|
||||
printf("\n");
|
||||
munmap(buf, size);
|
||||
} else if (argc > 2 && strcmp(argv[1], "--unpack") == 0) {
|
||||
unpack(argv[2]);
|
||||
} else if (argc > 2 && strcmp(argv[1], "--repack") == 0) {
|
||||
@ -67,47 +88,12 @@ int main(int argc, char *argv[]) {
|
||||
comp_file(method, argv[2]);
|
||||
} else if (argc > 4 && strcmp(argv[1], "--hexpatch") == 0) {
|
||||
hexpatch(argv[2], argv[3], argv[4]);
|
||||
} else if (argc > 4 && strncmp(argv[1], "--cpio", 6) == 0) {
|
||||
int recursive = 0;
|
||||
} else if (argc > 2 && strncmp(argv[1], "--cpio", 6) == 0) {
|
||||
char *command;
|
||||
command_t cmd;
|
||||
command = strchr(argv[1] + 2, '-');
|
||||
if (command == NULL) usage(argv[0]);
|
||||
else command++;
|
||||
if (strcmp(command, "rm") == 0) {
|
||||
cmd = RM;
|
||||
if (argc > 5 && strcmp(argv[4], "-r") == 0) {
|
||||
recursive = 1;
|
||||
argv[4] = argv[5];
|
||||
argc--;
|
||||
}
|
||||
} else if (argc > 5 && strcmp(command, "mkdir") == 0) {
|
||||
cmd = MKDIR;
|
||||
} else if (argc > 6 && strcmp(command, "add") == 0) {
|
||||
cmd = ADD;
|
||||
} else {
|
||||
cmd = NONE;
|
||||
usage(argv[0]);
|
||||
}
|
||||
vector v;
|
||||
vec_init(&v);
|
||||
parse_cpio(argv[2], &v);
|
||||
switch(cmd) {
|
||||
case RM:
|
||||
cpio_rm(recursive, argv[4], &v);
|
||||
break;
|
||||
case MKDIR:
|
||||
cpio_mkdir(strtoul(argv[4], NULL, 8), argv[5], &v);
|
||||
break;
|
||||
case ADD:
|
||||
cpio_add(strtoul(argv[4], NULL, 8), argv[5], argv[6], &v);
|
||||
break;
|
||||
default:
|
||||
// Never happen
|
||||
break;
|
||||
}
|
||||
dump_cpio(argv[3], &v);
|
||||
cpio_vec_destroy(&v);
|
||||
else ++command;
|
||||
if (cpio_commands(command, argc - 2, argv + 2)) usage(argv[0]);
|
||||
} else {
|
||||
usage(argv[0]);
|
||||
}
|
||||
|
@ -29,7 +29,7 @@ void repack(const char* orig_image, const char* out_image) {
|
||||
mmap_ro(orig_image, &orig, &size);
|
||||
|
||||
// Parse original image
|
||||
printf("\nParsing boot image: [%s]\n\n", orig_image);
|
||||
printf("Parsing boot image: [%s]\n\n", orig_image);
|
||||
parse_img(orig, size);
|
||||
|
||||
// Create new image
|
||||
@ -105,7 +105,7 @@ void repack(const char* orig_image, const char* out_image) {
|
||||
}
|
||||
|
||||
// Write header back
|
||||
printf("\nRepack to boot image: [%s]\n\n", out_image);
|
||||
printf("Repack to boot image: [%s]\n\n", out_image);
|
||||
print_info();
|
||||
lseek(fd, 0, SEEK_SET);
|
||||
write(fd, &hdr, sizeof(hdr));
|
||||
|
295
jni/magiskboot/sha1.c
Normal file
295
jni/magiskboot/sha1.c
Normal file
@ -0,0 +1,295 @@
|
||||
/*
|
||||
SHA-1 in C
|
||||
By Steve Reid <steve@edmweb.com>
|
||||
100% Public Domain
|
||||
|
||||
Test Vectors (from FIPS PUB 180-1)
|
||||
"abc"
|
||||
A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
|
||||
"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
|
||||
84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
|
||||
A million repetitions of "a"
|
||||
34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
|
||||
*/
|
||||
|
||||
/* #define LITTLE_ENDIAN * This should be #define'd already, if true. */
|
||||
/* #define SHA1HANDSOFF * Copies data before messing with it. */
|
||||
|
||||
#define SHA1HANDSOFF
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
/* for uint32_t */
|
||||
#include <stdint.h>
|
||||
|
||||
#include "sha1.h"
|
||||
|
||||
|
||||
#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
|
||||
|
||||
/* blk0() and blk() perform the initial expand. */
|
||||
/* I got the idea of expanding during the round function from SSLeay */
|
||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||
#define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \
|
||||
|(rol(block->l[i],8)&0x00FF00FF))
|
||||
#elif BYTE_ORDER == BIG_ENDIAN
|
||||
#define blk0(i) block->l[i]
|
||||
#else
|
||||
#error "Endianness not defined!"
|
||||
#endif
|
||||
#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \
|
||||
^block->l[(i+2)&15]^block->l[i&15],1))
|
||||
|
||||
/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
|
||||
#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30);
|
||||
#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30);
|
||||
#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
|
||||
#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);
|
||||
#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);
|
||||
|
||||
|
||||
/* Hash a single 512-bit block. This is the core of the algorithm. */
|
||||
|
||||
void SHA1Transform(
|
||||
uint32_t state[5],
|
||||
const unsigned char buffer[64]
|
||||
)
|
||||
{
|
||||
uint32_t a, b, c, d, e;
|
||||
|
||||
typedef union
|
||||
{
|
||||
unsigned char c[64];
|
||||
uint32_t l[16];
|
||||
} CHAR64LONG16;
|
||||
|
||||
#ifdef SHA1HANDSOFF
|
||||
CHAR64LONG16 block[1]; /* use array to appear as a pointer */
|
||||
|
||||
memcpy(block, buffer, 64);
|
||||
#else
|
||||
/* The following had better never be used because it causes the
|
||||
* pointer-to-const buffer to be cast into a pointer to non-const.
|
||||
* And the result is written through. I threw a "const" in, hoping
|
||||
* this will cause a diagnostic.
|
||||
*/
|
||||
CHAR64LONG16 *block = (const CHAR64LONG16 *) buffer;
|
||||
#endif
|
||||
/* Copy context->state[] to working vars */
|
||||
a = state[0];
|
||||
b = state[1];
|
||||
c = state[2];
|
||||
d = state[3];
|
||||
e = state[4];
|
||||
/* 4 rounds of 20 operations each. Loop unrolled. */
|
||||
R0(a, b, c, d, e, 0);
|
||||
R0(e, a, b, c, d, 1);
|
||||
R0(d, e, a, b, c, 2);
|
||||
R0(c, d, e, a, b, 3);
|
||||
R0(b, c, d, e, a, 4);
|
||||
R0(a, b, c, d, e, 5);
|
||||
R0(e, a, b, c, d, 6);
|
||||
R0(d, e, a, b, c, 7);
|
||||
R0(c, d, e, a, b, 8);
|
||||
R0(b, c, d, e, a, 9);
|
||||
R0(a, b, c, d, e, 10);
|
||||
R0(e, a, b, c, d, 11);
|
||||
R0(d, e, a, b, c, 12);
|
||||
R0(c, d, e, a, b, 13);
|
||||
R0(b, c, d, e, a, 14);
|
||||
R0(a, b, c, d, e, 15);
|
||||
R1(e, a, b, c, d, 16);
|
||||
R1(d, e, a, b, c, 17);
|
||||
R1(c, d, e, a, b, 18);
|
||||
R1(b, c, d, e, a, 19);
|
||||
R2(a, b, c, d, e, 20);
|
||||
R2(e, a, b, c, d, 21);
|
||||
R2(d, e, a, b, c, 22);
|
||||
R2(c, d, e, a, b, 23);
|
||||
R2(b, c, d, e, a, 24);
|
||||
R2(a, b, c, d, e, 25);
|
||||
R2(e, a, b, c, d, 26);
|
||||
R2(d, e, a, b, c, 27);
|
||||
R2(c, d, e, a, b, 28);
|
||||
R2(b, c, d, e, a, 29);
|
||||
R2(a, b, c, d, e, 30);
|
||||
R2(e, a, b, c, d, 31);
|
||||
R2(d, e, a, b, c, 32);
|
||||
R2(c, d, e, a, b, 33);
|
||||
R2(b, c, d, e, a, 34);
|
||||
R2(a, b, c, d, e, 35);
|
||||
R2(e, a, b, c, d, 36);
|
||||
R2(d, e, a, b, c, 37);
|
||||
R2(c, d, e, a, b, 38);
|
||||
R2(b, c, d, e, a, 39);
|
||||
R3(a, b, c, d, e, 40);
|
||||
R3(e, a, b, c, d, 41);
|
||||
R3(d, e, a, b, c, 42);
|
||||
R3(c, d, e, a, b, 43);
|
||||
R3(b, c, d, e, a, 44);
|
||||
R3(a, b, c, d, e, 45);
|
||||
R3(e, a, b, c, d, 46);
|
||||
R3(d, e, a, b, c, 47);
|
||||
R3(c, d, e, a, b, 48);
|
||||
R3(b, c, d, e, a, 49);
|
||||
R3(a, b, c, d, e, 50);
|
||||
R3(e, a, b, c, d, 51);
|
||||
R3(d, e, a, b, c, 52);
|
||||
R3(c, d, e, a, b, 53);
|
||||
R3(b, c, d, e, a, 54);
|
||||
R3(a, b, c, d, e, 55);
|
||||
R3(e, a, b, c, d, 56);
|
||||
R3(d, e, a, b, c, 57);
|
||||
R3(c, d, e, a, b, 58);
|
||||
R3(b, c, d, e, a, 59);
|
||||
R4(a, b, c, d, e, 60);
|
||||
R4(e, a, b, c, d, 61);
|
||||
R4(d, e, a, b, c, 62);
|
||||
R4(c, d, e, a, b, 63);
|
||||
R4(b, c, d, e, a, 64);
|
||||
R4(a, b, c, d, e, 65);
|
||||
R4(e, a, b, c, d, 66);
|
||||
R4(d, e, a, b, c, 67);
|
||||
R4(c, d, e, a, b, 68);
|
||||
R4(b, c, d, e, a, 69);
|
||||
R4(a, b, c, d, e, 70);
|
||||
R4(e, a, b, c, d, 71);
|
||||
R4(d, e, a, b, c, 72);
|
||||
R4(c, d, e, a, b, 73);
|
||||
R4(b, c, d, e, a, 74);
|
||||
R4(a, b, c, d, e, 75);
|
||||
R4(e, a, b, c, d, 76);
|
||||
R4(d, e, a, b, c, 77);
|
||||
R4(c, d, e, a, b, 78);
|
||||
R4(b, c, d, e, a, 79);
|
||||
/* Add the working vars back into context.state[] */
|
||||
state[0] += a;
|
||||
state[1] += b;
|
||||
state[2] += c;
|
||||
state[3] += d;
|
||||
state[4] += e;
|
||||
/* Wipe variables */
|
||||
a = b = c = d = e = 0;
|
||||
#ifdef SHA1HANDSOFF
|
||||
memset(block, '\0', sizeof(block));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/* SHA1Init - Initialize new context */
|
||||
|
||||
void SHA1Init(
|
||||
SHA1_CTX * context
|
||||
)
|
||||
{
|
||||
/* SHA1 initialization constants */
|
||||
context->state[0] = 0x67452301;
|
||||
context->state[1] = 0xEFCDAB89;
|
||||
context->state[2] = 0x98BADCFE;
|
||||
context->state[3] = 0x10325476;
|
||||
context->state[4] = 0xC3D2E1F0;
|
||||
context->count[0] = context->count[1] = 0;
|
||||
}
|
||||
|
||||
|
||||
/* Run your data through this. */
|
||||
|
||||
void SHA1Update(
|
||||
SHA1_CTX * context,
|
||||
const unsigned char *data,
|
||||
uint32_t len
|
||||
)
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
uint32_t j;
|
||||
|
||||
j = context->count[0];
|
||||
if ((context->count[0] += len << 3) < j)
|
||||
context->count[1]++;
|
||||
context->count[1] += (len >> 29);
|
||||
j = (j >> 3) & 63;
|
||||
if ((j + len) > 63)
|
||||
{
|
||||
memcpy(&context->buffer[j], data, (i = 64 - j));
|
||||
SHA1Transform(context->state, context->buffer);
|
||||
for (; i + 63 < len; i += 64)
|
||||
{
|
||||
SHA1Transform(context->state, &data[i]);
|
||||
}
|
||||
j = 0;
|
||||
}
|
||||
else
|
||||
i = 0;
|
||||
memcpy(&context->buffer[j], &data[i], len - i);
|
||||
}
|
||||
|
||||
|
||||
/* Add padding and return the message digest. */
|
||||
|
||||
void SHA1Final(
|
||||
unsigned char digest[20],
|
||||
SHA1_CTX * context
|
||||
)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
unsigned char finalcount[8];
|
||||
|
||||
unsigned char c;
|
||||
|
||||
#if 0 /* untested "improvement" by DHR */
|
||||
/* Convert context->count to a sequence of bytes
|
||||
* in finalcount. Second element first, but
|
||||
* big-endian order within element.
|
||||
* But we do it all backwards.
|
||||
*/
|
||||
unsigned char *fcp = &finalcount[8];
|
||||
|
||||
for (i = 0; i < 2; i++)
|
||||
{
|
||||
uint32_t t = context->count[i];
|
||||
|
||||
int j;
|
||||
|
||||
for (j = 0; j < 4; t >>= 8, j++)
|
||||
*--fcp = (unsigned char) t}
|
||||
#else
|
||||
for (i = 0; i < 8; i++)
|
||||
{
|
||||
finalcount[i] = (unsigned char) ((context->count[(i >= 4 ? 0 : 1)] >> ((3 - (i & 3)) * 8)) & 255); /* Endian independent */
|
||||
}
|
||||
#endif
|
||||
c = 0200;
|
||||
SHA1Update(context, &c, 1);
|
||||
while ((context->count[0] & 504) != 448)
|
||||
{
|
||||
c = 0000;
|
||||
SHA1Update(context, &c, 1);
|
||||
}
|
||||
SHA1Update(context, finalcount, 8); /* Should cause a SHA1Transform() */
|
||||
for (i = 0; i < 20; i++)
|
||||
{
|
||||
digest[i] = (unsigned char)
|
||||
((context->state[i >> 2] >> ((3 - (i & 3)) * 8)) & 255);
|
||||
}
|
||||
/* Wipe variables */
|
||||
memset(context, '\0', sizeof(*context));
|
||||
memset(&finalcount, '\0', sizeof(finalcount));
|
||||
}
|
||||
|
||||
void SHA1(
|
||||
char *hash_out,
|
||||
const char *str,
|
||||
int len)
|
||||
{
|
||||
SHA1_CTX ctx;
|
||||
unsigned int ii;
|
||||
|
||||
SHA1Init(&ctx);
|
||||
for (ii=0; ii<len; ii+=1)
|
||||
SHA1Update(&ctx, (const unsigned char*)str + ii, 1);
|
||||
SHA1Final((unsigned char *)hash_out, &ctx);
|
||||
hash_out[20] = '\0';
|
||||
}
|
44
jni/magiskboot/sha1.h
Normal file
44
jni/magiskboot/sha1.h
Normal file
@ -0,0 +1,44 @@
|
||||
#ifndef SHA1_H
|
||||
#define SHA1_H
|
||||
|
||||
/*
|
||||
SHA-1 in C
|
||||
By Steve Reid <steve@edmweb.com>
|
||||
100% Public Domain
|
||||
*/
|
||||
|
||||
#include "stdint.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t state[5];
|
||||
uint32_t count[2];
|
||||
unsigned char buffer[64];
|
||||
} SHA1_CTX;
|
||||
|
||||
void SHA1Transform(
|
||||
uint32_t state[5],
|
||||
const unsigned char buffer[64]
|
||||
);
|
||||
|
||||
void SHA1Init(
|
||||
SHA1_CTX * context
|
||||
);
|
||||
|
||||
void SHA1Update(
|
||||
SHA1_CTX * context,
|
||||
const unsigned char *data,
|
||||
uint32_t len
|
||||
);
|
||||
|
||||
void SHA1Final(
|
||||
unsigned char digest[20],
|
||||
SHA1_CTX * context
|
||||
);
|
||||
|
||||
void SHA1(
|
||||
char *hash_out,
|
||||
const char *str,
|
||||
int len);
|
||||
|
||||
#endif /* SHA1_H */
|
@ -13,7 +13,7 @@ void unpack(const char* image) {
|
||||
mmap_ro(image, &orig, &size);
|
||||
|
||||
// Parse image
|
||||
printf("\nParsing boot image: [%s]\n\n", image);
|
||||
printf("Parsing boot image: [%s]\n\n", image);
|
||||
parse_img(orig, size);
|
||||
|
||||
if (boot_type == CHROMEOS) {
|
||||
|
@ -124,6 +124,7 @@ void print_info() {
|
||||
default:
|
||||
fprintf(stderr, "Unknown ramdisk format!\n");
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
void cleanup() {
|
||||
@ -157,6 +158,10 @@ void vec_push_back(vector *v, void *p) {
|
||||
++vec_size(v);
|
||||
}
|
||||
|
||||
void vec_sort(vector *v, int (*compar)(const void *, const void *)) {
|
||||
qsort(vec_entry(v), vec_size(v), sizeof(void*), compar);
|
||||
}
|
||||
|
||||
void vec_destroy(vector *v) {
|
||||
// Will not free each entry!
|
||||
// Manually free each entry, then call this function
|
||||
|
Loading…
Reference in New Issue
Block a user