Created
October 3, 2012 05:54
-
-
Save crimsonwoods/3825289 to your computer and use it in GitHub Desktop.
fix signature field into ODEX file.
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
#include <stdio.h> | |
#include <stdint.h> | |
#include <stdlib.h> | |
#include <unistd.h> | |
#include <fcntl.h> | |
#include <errno.h> | |
#include <string.h> | |
typedef struct app_args_t { | |
char const * orig_odex; | |
char const * targ_odex; | |
} app_args_t; | |
static int parse_args(app_args_t *args, int argc, char **argv); | |
static void show_usage(); | |
static int sigfix(app_args_t const *args); | |
int main(int argc, char **argv) | |
{ | |
app_args_t args; | |
if (0 != parse_args(&args, argc, argv)) { | |
return -1; | |
} | |
return sigfix(&args); | |
} | |
static int parse_args(app_args_t *args, int argc, char **argv) | |
{ | |
if (argc < 3) { | |
show_usage(); | |
return -1; | |
} | |
args->orig_odex = argv[1]; | |
args->targ_odex = argv[2]; | |
return 0; | |
} | |
static void show_usage() | |
{ | |
printf("Usage: odexsigfix original.odex target.odex\n"); | |
} | |
#define SIGNATURE_SIZE 20 | |
typedef struct dex_header_t { | |
uint8_t magic[8]; | |
uint32_t checksum; | |
uint8_t signature[SIGNATURE_SIZE]; | |
uint32_t fileSize; | |
uint32_t headerSize; | |
uint32_t endianTag; | |
uint32_t linkSize; | |
uint32_t linkOff; | |
uint32_t mapOff; | |
uint32_t stringIdsSize; | |
uint32_t stringIdsOff; | |
uint32_t typeIdsSize; | |
uint32_t typeIdsOff; | |
uint32_t protoIdsSize; | |
uint32_t protoIdsOff; | |
uint32_t fieldIdsSize; | |
uint32_t fieldIdsOff; | |
uint32_t methodIdsSize; | |
uint32_t medhotIdsOff; | |
uint32_t classDefsSize; | |
uint32_t classDefsOff; | |
uint32_t dataSize; | |
uint32_t dataOff; | |
} dex_header_t; | |
typedef struct dex_opt_header_t { | |
uint8_t magic[8]; | |
uint32_t dexOffset; | |
uint32_t dexLength; | |
uint32_t depsOffset; | |
uint32_t optOffset; | |
uint32_t optLength; | |
uint32_t flags; | |
uint32_t checksum; | |
} dex_opt_header_t; | |
#define DEX_MAGIC "dex\n" | |
#define DEX_OPT_MAGIC "dey\n" | |
static off_t find_seek_position(int fd); | |
static int get_dex_header(int fd, dex_header_t *hdr); | |
static int write_dex_header(int fd, dex_header_t const *hdr); | |
static int sigfix(app_args_t const *args) | |
{ | |
int err = 0; | |
int orig_fd = -1; | |
int targ_fd = -1; | |
dex_header_t orig_hdr; | |
dex_header_t targ_hdr; | |
orig_fd = open(args->orig_odex, O_RDONLY); | |
if (-1 == orig_fd) { | |
err = errno; | |
fprintf(stderr, "failed to open original odex file"); | |
goto cleanup; | |
} | |
targ_fd = open(args->targ_odex, O_RDWR); | |
if (-1 == targ_fd) { | |
err = errno; | |
fprintf(stderr, "failed to open target odex file"); | |
goto cleanup; | |
} | |
err = get_dex_header(orig_fd, &orig_hdr); | |
if (0 != err) { | |
goto cleanup; | |
} | |
err = get_dex_header(targ_fd, &targ_hdr); | |
if (0 != err) { | |
goto cleanup; | |
} | |
// copy signature from original to target | |
memcpy(targ_hdr.signature, orig_hdr.signature, SIGNATURE_SIZE); | |
err = write_dex_header(targ_fd, &targ_hdr); | |
if (0 != err) { | |
goto cleanup; | |
} | |
cleanup: | |
if (0 != err) { | |
fprintf(stderr, " (%s).\n", strerror(err)); | |
} | |
close(targ_fd); | |
close(orig_fd); | |
return err; | |
} | |
static off_t find_seek_position(int fd) | |
{ | |
dex_opt_header_t opt_hdr; | |
int n; | |
size_t size; | |
off_t offst; | |
errno = 0; | |
if (-1 == lseek(fd, 0, SEEK_SET)) { | |
return -1; | |
} | |
size = sizeof(opt_hdr); | |
n = read(fd, &opt_hdr, size); | |
if (n != size) { | |
return -1; | |
} | |
if (0 != strncmp((char const *)opt_hdr.magic, DEX_OPT_MAGIC, 4)) { | |
if (0 != strncmp((char const *)opt_hdr.magic, DEX_MAGIC, 4)) { | |
return -1; | |
} | |
offst = 0; | |
} else { | |
offst = opt_hdr.dexOffset; | |
} | |
return offst; | |
} | |
static int get_dex_header(int fd, dex_header_t *hdr) | |
{ | |
int n; | |
size_t size; | |
off_t const offst = find_seek_position(fd); | |
if (-1 == offst) { | |
int err = errno; | |
fprintf(stderr, "failed to lookup the signature"); | |
return 0 != err ? err : EIO; | |
} | |
if (-1 == lseek(fd, offst, SEEK_SET)) { | |
int err = errno; | |
fprintf(stderr, "failed to seek"); | |
return err; | |
} | |
size = sizeof(dex_header_t); | |
n = read(fd, hdr, size); | |
if (n != size) { | |
fprintf(stderr, "failed to read ODEX file"); | |
return EIO; | |
} | |
return 0; | |
} | |
static int write_dex_header(int fd, dex_header_t const *hdr) | |
{ | |
int n; | |
size_t size; | |
off_t const offst = find_seek_position(fd); | |
if (-1 == offst) { | |
int err = errno; | |
fprintf(stderr, "failed to lookup the signature"); | |
return 0 != err ? err : EIO; | |
} | |
if (-1 == lseek(fd, offst, SEEK_SET)) { | |
int err = errno; | |
fprintf(stderr, "failed to seek"); | |
return err; | |
} | |
size = sizeof(dex_header_t); | |
n = write(fd, hdr, size); | |
if (n != size) { | |
fprintf(stderr, "failed to write ODEX file"); | |
return EIO; | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment