Arbitrary User Agent Strings for Opera

Arbitrary User Agent Strings for Opera

Post by tgoe on Sun Sep 28, 2008 4:46 pm
([msg=12748]see Arbitrary User Agent Strings for Opera[/msg])

Hi. First of all, I'm new to this site and not sure where to post this so I'll put it here. :D

I just finished setting up my shiny new FreeBSD 7 desktop system. After struggling to get Flash9 working properly, I finally settled on Opera running under Wine. Everything works perfectly except for one tiny problem... I want websites to see me as a FreeBSD user even though I'm running Opera/Wine, dammit. :evil: There is no way to do this within Opera's settings (you can only select from a predefined list of user agent strings) and Google only turns up people who are frustrated by the predefined list. So, I wrote a little C utility to do it for us. :twisted:

Code: Select all

* 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;


    while((ch = getopt(argc, argv, "s:e:a:c")) != -1) {
        switch(ch) {
            case 's': offset1 = strtol(optarg, NULL, 0);
            case 'e': offset2 = strtol(optarg, NULL, 0);
            case 'a': ua = optarg;
            case 'c': recomp = 0;
            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);


    return 0;

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

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

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);
                    die("Error reading opera.dll!\n");
                if(! feof(cur))
                    fputc(ch, bak);
                    die("Can't write to opera.dll backup!\n");

    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;

        return -1;


    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) {

TO USE(windows)
  • Get a copy of the upx command ( and place it in Opera's directory
  • Compile the obove source (gcc -o uass uass.c) and put the resulting binary in Opera's directory
  • Close Opera
  • From a command shell in Opera's directory type:
    uass -a "Your Agent String Here"
  • Visit opera:config#UserAgent|SpoofUserAgentID and set that value to '2'.
    (You only have to do this last step once)

  • The steps vary slightly between Windows/Linux/FreeBSD
  • Your Agent strings must be 73 characters or less
  • It would be way cooler to insert the UA string while Opera is running... but I don't know how to do that :?
  • Have a nice day

-- Tue Mar 17, 2009 9:47 am --

Just an update for myself and anyone else that might be using the latest release(9.64) of Opera to do missions that require a user agent change. Things in the dll have changed and moved around but the above program will still work, it just needs some flags.

Code: Select all
./uass -s 0x6c80c8 -e 0x6c8110 -a "Opera/9.64 (FreeBSD i386/Wine; U; en)"
User avatar
Posts: 621
Joined: Sun Sep 28, 2008 2:33 pm
Location: q3dm7
Blog: View Blog (0)

Return to C and C++

Who is online

Users browsing this forum: No registered users and 0 guests