Skip navigation.

Eolass patent bites the dust

Some background:
Eolas (E) is a company that patented a certain way of interacting with embedded objects on web pages. This is why in Opera, you sometimes have to click (for example) a flash player to "activate" it before it can actually be controlled. That sucks.

Opera is the only browser that I know of, that currently have this annoying system in place. IE had it, but it reached to a pocket full of money to buy a license from E.

Other (open source) browsers don't implement this mechanism because E was kind enough to commit not to pursue legal actions against open source browsers that are violating its patent. Why? I guess because it wouldn't really be able to enforce that anyway. Builds without this future would pop up everywhere in no-time.

Solution:
Make a "custom" Opera build.

Now I look at it, finding out how to bypass this system took more time then it had to.

My starting point was to grab onto the string "Click to activate and use this control". It's displayed in status bar when hovering over non-activated embed.
It can be found in english.lng listed as:
-191213401="Click to activate and use this control"

Looks like Opera is using signed long's to identify strings. We can't just search for this number in opera.dll file and expect to find it there. Storing numbers as strings would be highly inefficient. Programs store numbers in hexadecimal instead so we have to convert this value to hex. Even windows calc will do the job in Scientific mode.
decimal -191213401 is 0xF49A50A7 in hex but we won't find that too in compiled file (even if we do, it won't be relevant to what we are looking for). PC's use little endian byte order so we have to search for reversed bytes: 0xA7509AF4, actually.

In a build I've been working on, this address was found twice in opera.dll. Those were the places where Opera actually referenced this string and as there were only two of those, it wasn't really hard to figure out that first one was the one I was looking for.

Found that out by setting a breakpoint in both of them and reloading a page that contained "non-activated" embed. Only one of those breakpoints triggered.

Tracing back from a code that references string, I eventually came to a code that created an "overlay" window. This is how Opera implemented "click-to-activate" thing. Invisible window is being positioned on top of non-activated embed and prevents interaction with it until clicked (when it is destroyed).

Cutting story short (I don't recall exact steps of this process as I've done that months ago - only some residual logs made this post possible), I've traced back again to find out where Opera decided to call CreateWindowEx function, that created our evil overlay. And below are the results of this work.

Patch:
For current versions of Opera 10 (alpha) and Opera 9.64 this change does the trick:
search: F7 D8 1B C0 F7 D8 C2 04 00 FF 74
replace: F7 D8 1B C0 B0 01 C2 04 00 FF 74

For Opera 9.63 (thanks Lex1 for correcting):
search: F7 D8 1B C0 F7 D8 5B C2 04 00
replace: F7 D8 1B C0 B0 01 5B C2 04 00

In 10alpha, search pattern can be found two times but only first one is relevant. Second match is actually involved in HTTPS related stuff so better not touch it.

Before hexediting opera.dll it has to be unpacked first. Use UPX command: "upx -d opera.dll"
For hex editing free XVI32 will do the job (not very friendly hexeditor though).

Download:
If you prefer to use a "ready to go" package then download this file, extract to Opera directory and run patch_click_to_activate.bat.
Patch for Opera 9.64 and Opera 10: opera-c2a.zip

For some 32/64 bit linux distributions use this patch script (thanks kylebaker for structuring script nicely): click-to-activate-removal-opera-10.sh
To use, download to any directory and execute these commands as a root:
chmod +x click-to-activate-removal-opera-10.sh
./click-to-activate-removal-opera-10.sh

PS. Pun intended in title ;>

Updated Gallery Viewer to v1.2Better Gmail title tweak

Comments

z@h3k 3. February 2009, 22:12

ooh thanks :smile:

Daniel Davis 5. February 2009, 00:37

I wish their patent really would bite the dust - one of the most ridiculous hindrances to usability.

Thanks for posting your work.

João Eiras 5. February 2009, 00:46

cool! what about a one-click patch file ?

Kyle Baker 5. February 2009, 03:35

Excellent write-up! I toyed around in Ubuntu trying to see if I could find the same hex strings to replace, but returned with no luck. I guess I need to unpack it first, but I'm really not sure how to do that on Linux.

@xErath
+1

It would be really cool to see a multi-platform (open source) patch tool for Opera. :wink: I'll dig around in Linux and see what I can come up with, but a tool should definitely be made!

Rafal 5. February 2009, 10:45

xErath: added patches.

kylebaker: I doubt that opera executable is packed in linux. Still unlikely to find that code there as different compilers produce different code.

Wasacz 5. February 2009, 12:17

Awesome job, thanks aka dzięki :D

Tamil 5. February 2009, 12:23

FataL 5. February 2009, 19:50

Great! :up:

Kyle Baker 5. February 2009, 21:54

@d.i.z.
Where is the lang file or what's it called in Windows so I can try to find the same in Linux? If I can come across it then I'll contribute that here to further extend your project!

Tamil 5. February 2009, 21:57

Originally posted by kyleabaker:

Where is the lang file or what's it called in Windows

english.lng in Opera installation directory.

Kyle Baker 5. February 2009, 22:11

@Tamil
Thanks, looks like I'll have to do some snooping in Linux. So far I've found A7509AF4 in the /usr/lib/opera/10.00/opera file. So should the find and replace be in the same file or a different one if it's even the same in the Linux build?

Rafal 5. February 2009, 22:17

opera IS the file you would have to modify.

Now you found those bytes in opera, you would have to find some debugger that you could use to set a breakpoint on that memory location.

Or wait, I can try to find that location in disassembler...

Kyle Baker 5. February 2009, 22:25

@d.i.z.
I can wait. P: Just having fun learning a thing or two from your approach to this. :D

Rafal 5. February 2009, 22:57

for opera linux, at offset 0x254E6E there should be 0F95C0. Try changing to B00190

Not tested (based on dead listing only) but code looks a bit similar to windows code so that might be it.

EDIT: just realized that offset will probably vary from type of build you have (shared, static, qt3/4 etc.).
I've been analyzing opera-10.00-4126.gcc4-qt4.i386

Kyle Baker 5. February 2009, 23:53

@d.i.z.
Yes, they are different depending on how they were compiled.

I've disassembled it and was before using a regular hex editor, but I have no clue how you were able to find that point without using break points. I've given it a good look over, but I think I need to learn a little more about that stuff first. :D

It would be interesting if I could figure out how you pin pointed that chunk and knew what to change it to, because I was thinking about writing a script that would disassemble, find the chunk to change and what to change it to and print it out...possibly auto-hex edit if possible all from a script, but that's not looking too promising at this point.

Rafal 6. February 2009, 00:30

I have used windows build as a reference.

I have found where language id is moved into memory location in the disassembled code (just searched for string hex id).
In this very same function where that is done, several lines up, there is a call to the function that needs patching. I have found it in windows build by searching for that magic bytes mentioned in the post.

In linux builds, similar looking call is also located several lines up from where string id is copied into memory.

Windows:
.text:67BE82A4 arg_0           = dword ptr  4

.text:67BE82A4
.text:67BE82A4 push 0
.text:67BE82A6 xor eax, eax
.text:67BE82A8 inc eax
.text:67BE82A9 push eax
.text:67BE82AA push [esp+8+arg_0]
.text:67BE82AE mov dx, 2Ah
.text:67BE82B2 push 17h
.text:67BE82B4 pop ecx
.text:67BE82B5 call sub_678983E0
.text:67BE82BA neg eax
.text:67BE82BC sbb eax, eax
.text:67BE82BE neg eax
.text:67BE82C0 retn 4
.text:67BE82C0 sub_67BE82A4 endp


Linux
.text:0829CE30 var_18          = dword ptr -18h

.text:0829CE30 var_14 = dword ptr -14h
.text:0829CE30 var_10 = dword ptr -10h
.text:0829CE30 var_C = dword ptr -0Ch
.text:0829CE30 var_8 = dword ptr -8
.text:0829CE30 var_4 = dword ptr -4
.text:0829CE30 arg_0 = dword ptr 8
.text:0829CE30
.text:0829CE30 push ebp
.text:0829CE31 mov eax, 1
.text:0829CE36 mov ebp, esp
.text:0829CE38 sub esp, 18h
.text:0829CE3B mov [esp+18h+var_4], eax
.text:0829CE3F mov eax, 17h
.text:0829CE44 mov [esp+18h+var_8], eax
.text:0829CE48 xor eax, eax
.text:0829CE4A mov [esp+18h+var_C], eax
.text:0829CE4E mov eax, 1
.text:0829CE53 mov [esp+18h+var_10], eax
.text:0829CE57 mov eax, 2Ah
.text:0829CE5C mov [esp+18h+var_14], eax
.text:0829CE60 mov eax, [ebp+arg_0]
.text:0829CE63 mov [esp+18h+var_18], eax
.text:0829CE66 call sub_82974B0
.text:0829CE6B leave
.text:0829CE6C test eax, eax
.text:0829CE6E setnz al
.text:0829CE71 movzx eax, al
.text:0829CE74 retn
.text:0829CE74 sub_829CE30 endp



Looks similar (while using very different instructions) to me.

I have a linux patch that one can try. Go to where opera binary is and run this lengthy command:
sed -e 's/\xB8\x2A\x00\x00\x00\x89\x44\x24\x04\x8B\x45\x08\x89\x04\x24\xE8\(....\)\xC9\x85\xC0\x0F\x95\xC0\x0F\xB6\xC0\xC3\x90/\xB8\x2A\x00\x00\x00\x89\x44\x24\x04\x8B\x45\x08\x89\x04\x24\xE8\1\xC9\x85\xC0\xB0\x01\x90\x0F\xB6\xC0\xC3\x90/' opera > opera_patched

opera_patched should have no more c2a. Maybe... not tested.

Kyle Baker 6. February 2009, 00:47

haha, wow. I'll give it a shot and let you know..

Artur "Jurgi" Jurgawka 6. February 2009, 09:26

Good job in an oldschool way. :sherlock:

Rafal 8. February 2009, 15:29

Bytes I've posted above generally works for current Linux build but not when using sed.
I've upload shell script here:
http://files.myopera.com/d.i.z./files/patch10.sh
which tries to patch opera binary in two different ways (because different builds have different compiled code).

To use, download to some directory and execute those commands as a root:
chmod +x patch10.sh
./patch10.sh
(rather poor try at shell programming but works for me)

Kyle Baker 11. February 2009, 04:09

@d.i.z.
For the script I get:
"Search pattern couldn't be found. File NOT patched."

I checked out the script, but haven't found a fix.

Rafal 11. February 2009, 08:50

http://snapshot.opera.com/unix/snapshot-4126/
Which build are you using exactly?

Rafal 11. February 2009, 19:20

Hmm, 64bit, no wonder it doesn't work.
Freeware IDA does not support 64bit binaries. Oh well.

João Eiras 11. February 2009, 19:58

d.i.z., the linux patch should actually tell if it's for 32 or 64 bits, the cpu and qt version.
Type opera--full-version to get that info.

Kyle Baker 11. February 2009, 20:41

@xErath
Good call on that command, just to correct it a little..there should actually be a space after opera.."opera --full-version".

@d.i.z.
After checking for 32 vs 64 your script could apply the correct operation still. I can pastebin the hex if that would help.

EDIT:
You could use the following (or flip it):

#!/bin/sh


opera=`opera --full-version | grep "x86_64"`
if [ "$opera" != "" ]; then
echo "64"
#64-bit operations here..
else
echo "32"
#32-bit operations here..
fi

Rafal 11. February 2009, 21:52

Kyle Baker 11. February 2009, 22:19

@d.i.z.
It's missing a closing "fi" for the 64 case, other than that it works. I think I'm going to extend it a bit more though. Thanks!

Rafal 11. February 2009, 22:27

Thanks for testing. Corrected.
It's likely to break for never builds though seeing how random gcc can be.

EDIT: also forgot about renaming patched binary and chmod. corrected now

Kyle Baker 11. February 2009, 23:49

I've cleaned up the file a bit to make it easier to update and added some output to give a better idea of the code flow.

http://kyleabaker.com/downloads/opera/scripts/patches/click-to-activate-removal-opera-10.sh

I could write a script to analyze an objdump of the file to pin point the spot to edit if I understood how you are finding it...and that should make the patch apply across all unix systems instead of matching 32/64 and only having a few to test.

Kyle Baker 12. February 2009, 01:09

Patch Results thus far for Unix:
----
# intel-linux (32 bit)
----
# Method 1
opera_10.00.4126.gcc4.qt3_i386
opera_10.00.4126.gcc4.qt4_i386
opera-10.00-4126.gcc4-qt4.i386
opera-10.00-4126.gcc4-static-qt3.i386
opera-static_10.00.4126.gcc4.qt3_i386

# Method 2
opera-10.00-4126.gcc4-shared-qt3.i386

# Failed
opera-10.00-4126.gcc295-static-qt3.i386
opera-static_10.00.4126.gcc295.qt3_i386

----
# x86_64-linux/
----
# Method 1
opera-10.00-4126.gcc4-shared-qt3.x86_64
opera_10.00.4126.gcc4.qt3_amd64

# Failed
(none)

Kyle Baker 12. February 2009, 08:07

I'm working on back-tracking what you've done to make a universal patch for all. The only problem is that I'm using objdump and the output is ~230 mb per file. Using grep I should be able to grab the needed hex points or asm points that we're looking for using regex, but I just don't know exactly how you're eye-balling these differences.

This is definitely helping me understand the underlying level of how binary works. P:

Rafal 12. February 2009, 08:36

Reliable method for auto discovering that code would be tricky I guess.

When I find the string I just go up where the next ret instruction is and first call after that is the one we are looking for.

Inside the call there must be:
test eax,eax
setzn al
movzx eax,al
(in case of 64 bit it's a bit different AFAIR)
and you have to also include a lot of code before that in a pattern, so that match is found only in this specific function (there are a lot other functions that have same piece of code).

Pattern matches 4 "any" (.{4}) bytes. This is a call pointer which must be matched this way because it will always be different in different builds.

Also it would be nice to check if only one pattern matched in a file. I failed to implement that check in a shell script.
It should be done, because if there are multiple matches, it should not proceed cause that can cause problems.

Kyle Baker 12. February 2009, 09:05

If anything else, it gives me something to do with my free time. P: My only problem (other than pin-pointing the location to change...and I think I can find a way) is that I don't know how you are replacing it with what you do. So the hex that you're using in place is derived from what?

Mulitple matches...I think I can do that with a loop regex or something. If you can coach me through the process I can put a universal script together. :wink: I just very new to this and doing the best I can with hex. :smile:

Rafal 12. February 2009, 10:01

0F 95 C0 setnz al

In OllyDbg (windows) I've entered mov al,1 instead of it and it assembled it into B0 01 90.
I don't have all assembler opcodes in my head so I wouldn't be able to do that as easily in plain hex. :smile:

Kyle Baker 12. February 2009, 12:10

The true test is to see if this script carries over to the next snapshot..testing now..

EDIT:
Patch still works! And the underlining spell checker is much improved in this build!

A.Ruzanov 14. February 2009, 11:41

Thanks, it fine work in Opera 10 (win). But opera.dll from Opera 9.63 non contains «F7 D8 1B C0 F7 D8 C2 04 00 FF 74».

Found with Olly. «F7 D8 1B C0 F7 D8 5B C2 04 00» need replace to «F7 D8 1B C0 B0 01 5B C2 04 00»

kslee 14. February 2009, 15:58

Originally posted by Lex1:

«F7 D8 1B C0 F7 D8 5B C2 04 00» need replace to «F7 D8 1B C0 B0 01 5B C2 04 00»


Yes, and there are two sets of "F7 D8 1B C0 F7 D8 5B C2 04 00" in 9.63.

Originally posted by d.i.z.:

In 10alpha, search pattern can be found two times but only second one is relevant.


I can find only one set of "F7 D8 1B C0 F7 D8 C2 04 00 FF 74" in 10 alpha.
Isn't it the other way round? And thank you!

Rafal 14. February 2009, 20:03

Originally posted by Lex1:

But opera.dll from Opera 9.63 non contains


Ops, yes. I've tested on 9.63 Ibis build which I though would be the same as normal.

Originally posted by kslee:

I can find only one set of "F7 D8 1B C0 F7 D8 C2 04 00 FF 74" in 10 alpha.
Isn't it the other way round? And thank you!


Actually that varied from build to build so I'm not sure now.

Eventually I'll clean this mess and upload updated 9.6x patch.

Stahn Aileron 3. March 2009, 09:10

Pleaassseeee make this compatible with 9.6x =)

A.Ruzanov 3. March 2009, 09:32

Use patch for Opera 10. It's work with Opera 9.64.

Rafal 9. March 2009, 21:56

I've refactored patch. Available here opera-c2a.zip.

It's much better and even intelligent in some sense:
  • works for Opera 9.64 and Opera 10 (current and hopefully future versions)
  • replaces only first found match
  • detects situation when file is already patched and does not proceed then
  • made in perl so can be adopted to linux easily (it should be enough to modify hex values and use shell script as a frontend for perl script)

Rafal 3. April 2009, 21:14

Updated patch to work with 1413.
It was picking wrong place to patch. I've made it look for more known bytes before patching.
Available at same place.

Martin Rauscher 25. April 2009, 13:50

1456 has problems. Patched successfully but the slides on the right on http://www.socialmediaclub.org/ still show "click to activate"... :-/

Rafal 25. April 2009, 14:01

Originally posted by Hades32:

1456 has problems. Patched successfully but the slides on the right on http://www.socialmediaclub.org/ still show "click to activate"... :-/


Works for me. Be sure you have latest patch. It wasn't updated since March 9 but maybe you still have some older version.

Martin Rauscher 25. April 2009, 15:17

Originally posted by d.i.z.:

Works for me. Be sure you have latest patch. It wasn't updated since March 9 but maybe you still have some older version.


:whistle: Ups, my fault. Accidentally patched my old Opera 9 *g* Everything works fine, now. Thanks anyway

sebastian schuster 18. June 2009, 22:39

Thx for the patch.

BTW with there's an open source one file patcher: http://sourceforge.net/projects/hexpatcher/#item3rd-3

Maybe better than the perl implementation.

Rafal 19. June 2009, 07:32

Thanks but it looks like it does not support regexp which I use in patches.

sebastian schuster 19. June 2009, 14:38

You can search for "F7 D8 1B C0 F7 D8 C2 04 00 FF 74" directly and replace it one time. BTW: it also seems to support ? to replace one character.

A more professional tool (but not open-source): http://www.softpedia.com/get/Programming/Patchers/diablo2oo2-Universal-Patcher.shtml

Martin Rauscher 19. June 2009, 18:34

I don't like Perl, but I think it's much better this way as you can easily see what the script is doing with your browser...

Rafal 19. June 2009, 18:56

In perl I like its speed and ease of programming.

To use that freeware patching tool, everything would have to be rewritten for batch files. Batch's are a bit messy and not friendly to program in. At least for me.

How to use Quote function:

  1. Select some text
  2. Click on the Quote link

Write a comment

Comment
(BBcode and HTML is turned off for anonymous user comments.)

If you can't read the words, press the small reload icon.


Smilies