Skip to content

Instantly share code, notes, and snippets.

@crimsonwoods
Created October 3, 2012 05:54
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save crimsonwoods/3825289 to your computer and use it in GitHub Desktop.
Save crimsonwoods/3825289 to your computer and use it in GitHub Desktop.
fix signature field into ODEX file.
#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