mirror of
https://github.com/topjohnwu/Magisk.git
synced 2024-12-25 09:17:50 +00:00
Move cert extraction to its own file
This commit is contained in:
parent
029422679c
commit
9f7a3db8be
@ -33,6 +33,7 @@ LOCAL_SRC_FILES := \
|
|||||||
su/su.cpp \
|
su/su.cpp \
|
||||||
su/connect.cpp \
|
su/connect.cpp \
|
||||||
su/pts.cpp \
|
su/pts.cpp \
|
||||||
|
su/cert.cpp \
|
||||||
su/su_daemon.cpp \
|
su/su_daemon.cpp \
|
||||||
zygisk/entry.cpp \
|
zygisk/entry.cpp \
|
||||||
zygisk/main.cpp \
|
zygisk/main.cpp \
|
||||||
|
136
native/jni/su/cert.cpp
Normal file
136
native/jni/su/cert.cpp
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
#include <utils.hpp>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
// Top-level block container
|
||||||
|
struct signing_block {
|
||||||
|
uint64_t len;
|
||||||
|
|
||||||
|
struct id_value_pair {
|
||||||
|
uint64_t len;
|
||||||
|
struct /* v2_signature */ {
|
||||||
|
uint32_t id;
|
||||||
|
uint8_t value[0]; // size = (len - 4)
|
||||||
|
};
|
||||||
|
} id_value_pair_sequence[0];
|
||||||
|
|
||||||
|
uint64_t block_len; // *MUST* be same as len
|
||||||
|
char magic[16]; // "APK Sig Block 42"
|
||||||
|
};
|
||||||
|
|
||||||
|
struct len_prefixed {
|
||||||
|
uint32_t len;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Generic length prefixed raw data
|
||||||
|
struct len_prefixed_value : public len_prefixed {
|
||||||
|
uint8_t value[0];
|
||||||
|
};
|
||||||
|
|
||||||
|
// V2 Signature Block
|
||||||
|
struct v2_signature {
|
||||||
|
uint32_t id; // 0x7109871a
|
||||||
|
uint32_t signer_sequence_len;
|
||||||
|
struct signer : public len_prefixed {
|
||||||
|
struct signed_data : public len_prefixed {
|
||||||
|
uint32_t digest_sequence_len;
|
||||||
|
struct : public len_prefixed {
|
||||||
|
uint32_t algorithm;
|
||||||
|
len_prefixed_value digest;
|
||||||
|
} digest_sequence[0];
|
||||||
|
|
||||||
|
uint32_t certificate_sequence_len;
|
||||||
|
len_prefixed_value certificate_sequence[0];
|
||||||
|
|
||||||
|
uint32_t attribute_sequence_len;
|
||||||
|
struct attribute : public len_prefixed {
|
||||||
|
uint32_t id;
|
||||||
|
uint8_t value[0]; // size = (len - 4)
|
||||||
|
} attribute_sequence[0];
|
||||||
|
} signed_data;
|
||||||
|
|
||||||
|
uint32_t signature_sequence_len;
|
||||||
|
struct : public len_prefixed {
|
||||||
|
uint32_t id;
|
||||||
|
len_prefixed_value signature;
|
||||||
|
} signature_sequence[0];
|
||||||
|
|
||||||
|
len_prefixed_value public_key;
|
||||||
|
} signer_sequence[0];
|
||||||
|
};
|
||||||
|
|
||||||
|
// The structures above are just for documentation purpose
|
||||||
|
// The real parsing logic is the following
|
||||||
|
|
||||||
|
string read_certificate(int fd) {
|
||||||
|
string certificate;
|
||||||
|
uint32_t size4;
|
||||||
|
uint64_t size8, size_of_block;
|
||||||
|
|
||||||
|
for (int i = 0;; i++) {
|
||||||
|
unsigned short n;
|
||||||
|
lseek(fd, -i - 2, SEEK_END);
|
||||||
|
read(fd, &n, 2);
|
||||||
|
if (n == i) {
|
||||||
|
lseek(fd, -22, SEEK_CUR);
|
||||||
|
read(fd, &size4, 4);
|
||||||
|
if (size4 == 0x6054b50u) { // central directory end magic
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (i == 0xffff) {
|
||||||
|
return certificate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lseek(fd, 12, SEEK_CUR);
|
||||||
|
|
||||||
|
read(fd, &size4, 0x4);
|
||||||
|
lseek(fd, (off_t) (size4 - 0x18), SEEK_SET);
|
||||||
|
|
||||||
|
read(fd, &size8, 0x8);
|
||||||
|
char magic[0x10] = {0};
|
||||||
|
read(fd, magic, sizeof(magic));
|
||||||
|
if (memcmp(magic, "APK Sig Block 42", sizeof(magic)) != 0) {
|
||||||
|
return certificate;
|
||||||
|
}
|
||||||
|
|
||||||
|
lseek(fd, (off_t) (size4 - (size8 + 0x8)), SEEK_SET);
|
||||||
|
read(fd, &size_of_block, 0x8);
|
||||||
|
if (size_of_block != size8) {
|
||||||
|
return certificate;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
uint32_t id;
|
||||||
|
uint32_t offset;
|
||||||
|
read(fd, &size8, 0x8); // sequence length
|
||||||
|
if (size8 == size_of_block) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
read(fd, &id, 0x4); // id
|
||||||
|
offset = 4;
|
||||||
|
|
||||||
|
if (id == 0x7109871au) {
|
||||||
|
read(fd, &size4, 0x4); // signer-sequence length
|
||||||
|
read(fd, &size4, 0x4); // signer length
|
||||||
|
read(fd, &size4, 0x4); // signed data length
|
||||||
|
offset += 0x4 * 3;
|
||||||
|
|
||||||
|
read(fd, &size4, 0x4); // digests-sequence length
|
||||||
|
lseek(fd, (off_t) (size4), SEEK_CUR);// skip digests
|
||||||
|
offset += 0x4 + size4;
|
||||||
|
|
||||||
|
read(fd, &size4, 0x4); // certificates length
|
||||||
|
read(fd, &size4, 0x4); // certificate length
|
||||||
|
offset += 0x4 * 2;
|
||||||
|
|
||||||
|
certificate.resize(size4);
|
||||||
|
read(fd, certificate.data(), size4);
|
||||||
|
|
||||||
|
offset += size4;
|
||||||
|
}
|
||||||
|
lseek(fd, (off_t) (size8 - offset), SEEK_CUR);
|
||||||
|
}
|
||||||
|
return certificate;
|
||||||
|
}
|
@ -1,10 +1,7 @@
|
|||||||
#include <sys/sendfile.h>
|
#include <sys/sendfile.h>
|
||||||
#include <linux/fs.h>
|
#include <linux/fs.h>
|
||||||
#include <stdlib.h>
|
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <errno.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <libgen.h>
|
#include <libgen.h>
|
||||||
|
|
||||||
#include <utils.hpp>
|
#include <utils.hpp>
|
||||||
@ -57,12 +54,12 @@ static void post_order_walk(int dirfd, const Func &fn) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum visit_result {
|
enum walk_result {
|
||||||
CONTINUE, SKIP, TERMINATE
|
CONTINUE, SKIP, ABORT
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Func>
|
template <typename Func>
|
||||||
static visit_result pre_order_walk(int dirfd, const Func &fn) {
|
static walk_result pre_order_walk(int dirfd, const Func &fn) {
|
||||||
auto dir = xopen_dir(dirfd);
|
auto dir = xopen_dir(dirfd);
|
||||||
if (!dir) {
|
if (!dir) {
|
||||||
close(dirfd);
|
close(dirfd);
|
||||||
@ -71,16 +68,17 @@ static visit_result pre_order_walk(int dirfd, const Func &fn) {
|
|||||||
|
|
||||||
for (dirent *entry; (entry = xreaddir(dir.get()));) {
|
for (dirent *entry; (entry = xreaddir(dir.get()));) {
|
||||||
switch (fn(dirfd, entry)) {
|
switch (fn(dirfd, entry)) {
|
||||||
case CONTINUE:
|
case CONTINUE:
|
||||||
break;
|
break;
|
||||||
case SKIP:
|
case SKIP:
|
||||||
continue;
|
continue;
|
||||||
case TERMINATE:
|
case ABORT:
|
||||||
return TERMINATE;
|
return ABORT;
|
||||||
}
|
}
|
||||||
if (entry->d_type == DT_DIR) {
|
if (entry->d_type == DT_DIR) {
|
||||||
int fd = xopenat(dirfd, entry->d_name, O_RDONLY | O_CLOEXEC);
|
int fd = xopenat(dirfd, entry->d_name, O_RDONLY | O_CLOEXEC);
|
||||||
if (pre_order_walk(fd, fn) == TERMINATE) return TERMINATE;
|
if (pre_order_walk(fd, fn) == ABORT)
|
||||||
|
return ABORT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return CONTINUE;
|
return CONTINUE;
|
||||||
@ -419,7 +417,7 @@ void backup_folder(const char *dir, vector<raw_file> &files) {
|
|||||||
char path[PATH_MAX];
|
char path[PATH_MAX];
|
||||||
xrealpath(dir, path);
|
xrealpath(dir, path);
|
||||||
int len = strlen(path);
|
int len = strlen(path);
|
||||||
pre_order_walk(xopen(dir, O_RDONLY), [&](int dfd, dirent *entry) -> visit_result {
|
pre_order_walk(xopen(dir, O_RDONLY), [&](int dfd, dirent *entry) -> walk_result {
|
||||||
int fd = xopenat(dfd, entry->d_name, O_RDONLY);
|
int fd = xopenat(dfd, entry->d_name, O_RDONLY);
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
return SKIP;
|
return SKIP;
|
||||||
@ -526,13 +524,13 @@ mmap_data::mmap_data(const char *name, bool rw) {
|
|||||||
|
|
||||||
string find_apk_path(const char *pkg) {
|
string find_apk_path(const char *pkg) {
|
||||||
char buf[PATH_MAX];
|
char buf[PATH_MAX];
|
||||||
pre_order_walk(xopen("/data/app", O_RDONLY), [&](int dfd, dirent *entry) -> visit_result {
|
pre_order_walk(xopen("/data/app", O_RDONLY), [&](int dfd, dirent *entry) -> walk_result {
|
||||||
if (entry->d_type != DT_DIR)
|
if (entry->d_type != DT_DIR)
|
||||||
return SKIP;
|
return SKIP;
|
||||||
size_t len = strlen(pkg);
|
size_t len = strlen(pkg);
|
||||||
if (strncmp(entry->d_name, pkg, len) == 0 && entry->d_name[len] == '-') {
|
if (strncmp(entry->d_name, pkg, len) == 0 && entry->d_name[len] == '-') {
|
||||||
fd_pathat(dfd, entry->d_name, buf, sizeof(buf));
|
fd_pathat(dfd, entry->d_name, buf, sizeof(buf));
|
||||||
return TERMINATE;
|
return ABORT;
|
||||||
} else if (strncmp(entry->d_name, "~~", 2) == 0) {
|
} else if (strncmp(entry->d_name, "~~", 2) == 0) {
|
||||||
return CONTINUE;
|
return CONTINUE;
|
||||||
} else return SKIP;
|
} else return SKIP;
|
||||||
@ -540,82 +538,3 @@ string find_apk_path(const char *pkg) {
|
|||||||
string path(buf);
|
string path(buf);
|
||||||
return path.append("/base.apk");
|
return path.append("/base.apk");
|
||||||
}
|
}
|
||||||
|
|
||||||
string read_certificate(string app_path) {
|
|
||||||
string certificate;
|
|
||||||
uint32_t size4;
|
|
||||||
uint64_t size8, size_of_block;
|
|
||||||
|
|
||||||
int fd = xopen(app_path.data(), O_RDONLY);
|
|
||||||
if (fd < 0) {
|
|
||||||
return certificate;
|
|
||||||
}
|
|
||||||
run_finally f([&] { close(fd); });
|
|
||||||
|
|
||||||
for (int i = 0;; i++) {
|
|
||||||
unsigned short n;
|
|
||||||
lseek(fd, -i - 2, SEEK_END);
|
|
||||||
read(fd, &n, 2);
|
|
||||||
if (n == i) {
|
|
||||||
lseek(fd, -22, SEEK_CUR);
|
|
||||||
read(fd, &size4, 4);
|
|
||||||
if (size4 == 0x6054b50u) { // central directory end magic
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (i == 0xffff) {
|
|
||||||
return certificate;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
lseek(fd, 12, SEEK_CUR);
|
|
||||||
|
|
||||||
read(fd, &size4, 0x4);
|
|
||||||
lseek(fd, (off_t) (size4 - 0x18), SEEK_SET);
|
|
||||||
|
|
||||||
read(fd, &size8, 0x8);
|
|
||||||
unsigned char buffer[0x10] = {0};
|
|
||||||
read(fd, buffer, 0x10);
|
|
||||||
if (memcmp(buffer, "APK Sig Block 42", 0x10) != 0) {
|
|
||||||
return certificate;
|
|
||||||
}
|
|
||||||
|
|
||||||
lseek(fd, (off_t) (size4 - (size8 + 0x8)), SEEK_SET);
|
|
||||||
read(fd, &size_of_block, 0x8);
|
|
||||||
if (size_of_block != size8) {
|
|
||||||
return certificate;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (;;) {
|
|
||||||
uint32_t id;
|
|
||||||
uint32_t offset;
|
|
||||||
read(fd, &size8, 0x8); // sequence length
|
|
||||||
if (size8 == size_of_block) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
read(fd, &id, 0x4); // id
|
|
||||||
offset = 4;
|
|
||||||
|
|
||||||
if (id == 0x7109871au) {
|
|
||||||
read(fd, &size4, 0x4); // signer-sequence length
|
|
||||||
read(fd, &size4, 0x4); // signer length
|
|
||||||
read(fd, &size4, 0x4); // signed data length
|
|
||||||
offset += 0x4 * 3;
|
|
||||||
|
|
||||||
read(fd, &size4, 0x4); // digests-sequence length
|
|
||||||
lseek(fd, (off_t) (size4), SEEK_CUR);// skip digests
|
|
||||||
offset += 0x4 + size4;
|
|
||||||
|
|
||||||
read(fd, &size4, 0x4); // certificates length
|
|
||||||
read(fd, &size4, 0x4); // certificate length
|
|
||||||
offset += 0x4 * 2;
|
|
||||||
|
|
||||||
certificate.resize(size4);
|
|
||||||
read(fd, certificate.data(), size4);
|
|
||||||
|
|
||||||
offset += size4;
|
|
||||||
}
|
|
||||||
lseek(fd, (off_t) (size8 - offset), SEEK_CUR);
|
|
||||||
}
|
|
||||||
return certificate;
|
|
||||||
}
|
|
||||||
|
@ -101,9 +101,7 @@ void clone_dir(int src, int dest);
|
|||||||
void parse_mnt(const char *file, const std::function<bool(mntent*)> &fn);
|
void parse_mnt(const char *file, const std::function<bool(mntent*)> &fn);
|
||||||
void backup_folder(const char *dir, std::vector<raw_file> &files);
|
void backup_folder(const char *dir, std::vector<raw_file> &files);
|
||||||
void restore_folder(const char *dir, std::vector<raw_file> &files);
|
void restore_folder(const char *dir, std::vector<raw_file> &files);
|
||||||
|
|
||||||
std::string find_apk_path(const char *pkg);
|
std::string find_apk_path(const char *pkg);
|
||||||
std::string read_certificate(std::string app_path);
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void full_read(const char *filename, T &buf, size_t &size) {
|
void full_read(const char *filename, T &buf, size_t &size) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user