All pastes #2124052 Raw Edit

Someone

public text v1 · immutable
#2124052 ·published 2012-03-04 16:52 UTC
rendered paste body

/*
 * uass - User Agent String Switcher
 *
 * Inserts an arbitrary User Agent string into
 * Opera's opera.dll
 * 
 * Tested:
 * Opera 9.52 for Windows on Windows XP and FreeBSD under Wine
 *
 * For now, we're going to insist that this UA
 * must be <= 73 bytes. This is the longest UA
 * found in the binary and starts at offset 0x6B2DD8
 * and ends at 0x6B2E20 (after upx decompression).
 *
*/


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#define D_OFFSET1 0x6B2DD8
#define D_OFFSET2 0x6B2E20
#define D_UA "Opera/9.52 (FreeBSD i386/Wine; U; en)"
#define MAX_UA_LEN 73


void usage(char *name);
void die(char *msg);
void cleanup(void);
int setup(void); 
int check_ua(char *ua, char **nua);
int patch(long int offset1, long int offset2, char *ua, int recomp);

int main(int argc, char *argv[]) {
    int ch = 0;
    char *ua = D_UA;
    char *nua = NULL;
    long int offset1 = D_OFFSET1;
    long int offset2 = D_OFFSET2;
    int recomp = 1;

    atexit(&cleanup);

    while((ch = getopt(argc, argv, "s:e:a:c")) != -1) {
        switch(ch) {
            case 's': offset1 = strtol(optarg, NULL, 0);
                      break;
            case 'e': offset2 = strtol(optarg, NULL, 0);
                      break;
            case 'a': ua = optarg;
                      break;
            case 'c': recomp = 0;
                      break;
            default: usage(argv[0]);
        }
    }
    argc -= optind;
    argv += optind;

    if((offset2 - offset1) >= MAX_UA_LEN || ((offset2 - offset1) < 1))
        die("Invalid offsets!\n");
    if(! check_ua(ua, &nua))
        die("Invalid UA string!\n");
    if(! setup())
        die("Preparing opera.dll failed!\n");
    if(! patch(offset1, offset2, ua, recomp))
        die("Patching opera.dll failed!\n");

    printf("UA slot 2 is now:\n%s\n"
           "Visit \"opera:config#UserAgent|SpoofUserAgentID\"\n"
           "And set the value to '2' if you haven't yet.\n", nua);

    free(nua);

    return 0;
}

void usage(char *name) {
    printf("USAGE: %s [-c] [-s offset] [-e offset] [-a \"UA\"]\n", name);
    exit(0);
}

void die(char *msg) {
    printf("%s", msg);
    exit(0);
}

int setup(void) {
    FILE *bak;
    FILE *cur;
    char ch;
    int ret = 0;

    if((bak = fopen("opera.bak.dll", "rb")) == NULL) {
        if((cur = fopen("opera.dll", "rb")) == NULL)
            die("Can't find opera.dll!\n");
        if((bak = fopen("opera.bak.dll", "wb")) == NULL)
            die("Can't create a backup opera.dll!\n");
        else {
            while(! feof(cur)) {
                ch = fgetc(cur);
                if(ferror(cur))
                    die("Error reading opera.dll!\n");
                if(! feof(cur))
                    fputc(ch, bak);
                if(ferror(bak))
                    die("Can't write to opera.dll backup!\n");
            }
            fclose(cur);
            fclose(bak);
        }
    }

    printf("Decompressing opera.dll\n");
    ret = system("upx -d opera.dll > upxout");
    if(ret == -1 || ret == 127 || ret == 1)
        die("upx decompression failed!\n");

    return 1;
}

int patch(long int offset1, long int offset2, char *ua, int recomp) {
    FILE *fp;
    int ret = 0;

    if((fp = fopen("opera.dll", "r+b")) == NULL)
        return -1;

    printf("Inserting UA...\n");

    if(fseek(fp, offset1, SEEK_SET) != 0)
        die("a mysterious death...\n");

    if(fwrite(ua, sizeof(char), MAX_UA_LEN, fp) != MAX_UA_LEN)
        return -1;

    if(ferror(fp))
        return -1;

    fclose(fp);

    if(recomp) {
        printf("Recompressing (may take a minute)...\n");
        ret = system("upx -3 opera.dll > upxout");
        if (ret == -1 || ret == 127 || ret == 1)
            die("upx compression seems to have failed!\n");
    }

    return 1;
}

int check_ua(char *ua, char **nua) {
    int ua_len = 0;
    char *tmp = NULL;

    ua_len = strlen(ua);
    if(ua_len > MAX_UA_LEN)
        return 0;

    if((tmp = malloc(sizeof(char) * MAX_UA_LEN + 1)) == NULL)
        die("Memory allocation failed!\n");

    *nua = (char *) memset(tmp, 0x00, MAX_UA_LEN + 1);
    *nua = (char *) memset(tmp, ' ', MAX_UA_LEN);
    strncpy(*nua, ua, ua_len);

    return 1;
}

void cleanup(void) {
    remove("upxout");
}