Reversing IDA 4.01 - Watermarked protection scheme

by Written by Tsehp+, 8th Feb 2000

A great tool deserves a great protection and I was not disappointed by this jewel. You will deal here with RSA encryption of the main application and its modules, a license key checked everytime, reconstructing dumped dll's, and finally looking for false errors generated by the authors.


First I have to tell you :- don't make any mistake on my purposes. The main goal of this essay is to study the protection of this great tool and not to give ready made tricks for someone to spread it on the web. Discovered by Nolan Blender : IDA v4.01 includes your license information inside .idb databases in the same way it does on asm and lst files, if you apply the changes in ida.key and ida.wll this will be finished.

I was able able to remove all the watermarks of IDA 4.01 and did a serious byte compare of idb databases created with IDA. You need a regular copy of IDA v4.01 to make this work, this program contains your name watermarked everywhere and I don't tell you everything on this essay. So some watermarks will be left if you just apply what I will tell you. This tool is a must, for every serious reverser and will be improved by its authors, they really deserve the money it costs.

What are we dealing with ? Your registered name resides encrypted in your ida.key, IDA uses this all the time to validate a lot of functions. All its modules *.w32 are encrypted in part of data section with a unique key generated for your copy, its the same for the main dll ida.wll and all the different loaders *.ldw. The rest is left intact. I made this essay using Win2k final.

Tools required

SoftICE v4.01, NT_IceDump, ProcDump v1.6.2.
A HEX editor with binary file comparison functions (e.g. Hex Workshop).
One legal copy of IDA 4.01 (to apply this essay too), or two legal copies to check the watermarks.

Target's URL/FTP

Program History

On this site, Quine did some great work on previous versions. He managed to enable some crippled functions in trial versions and finally extended IDA by adding new functions. The story goes that he finally joined Ilfak (the author) to do the next versions and tried to remove his last essays.


The purpose of this tutorial is to make IDA work without watermarks. What are they ? they can take your name, strongly encrypt it and store it inside a license file (ida.key), but they can also encrypt some parts of several dlls and modules working in your application. Whats new about that ?, well DataRescue doesn't sell a mass of copies, so they have the time to customize their program for every customer. If you manage only to crack ida.key and spread the rest, they can track you. 

The watermarks consist of two parts, first a signed encryption of the executables, modules and loaders. All these decrypt at load time and are different for the encrypted part of every copy. Finally, the ida.key is used to generate your license info, clearly inserted at the top of the listings produced by IDA and embedded inside your packed idb files. Pierre Vandevenne said it was for multi-users to be able to identify authors but we aren't told this when we buy this program and can't avoid it either.

1. The ida.key protection. 

If you search on the web, you could find some older copies of IDA with ida.key generators. Don't waste your time with encryption or decryption routines, you will play their game. Its more easy just to let your PC decrypt this and check what's after. Load SoftICE and do a bpx createfilea do "d esp->4", wait for ida.key to be sent to this API. Look for the handle returned in EAX, do a bpx readfile, check for the handle pushed in esp->4 and do a d esp->8 and F12, the data is filled with the contents of the key that is used.

Be very careful here, do a bpr on a byte inside this block and you will land in a movsd instr, remove your bpr and do a bpr on the new mem location where this content is copied too. You will land again on a second movsd, do the same. You finally land at 10078231, inside ida.wll, keep the data window in view with the crypted info. Do several F12 (p ret) until you land at 10077AA6. You will see in the data section of SoftICE your personal info in reverse order. So we've gone through several routines that read the ida.key, applies the decryption and builds your info in reverse order. Press p ret until you land here :-

001B:10077848 CALL 10077A88
001B:1007784D TEST EAX,EAX
001B:1007784F JL 1007785A <-- patch this to NOP.
001B:10077851 MOVSX EAX,BYTE PTR [ESI+10]
001B:10077855 CMP EAX,3D
001B:10077858 JZ 1007785E <-- patch this to JMP 1007785E.
001B:1007785A XOR EAX,EAX
001B:1007785C JMP 1007787D
001B:1007785E PUSH 7F
001B:10077860 PUSH ESI
001B:10077861 PUSH EBX
001B:10077862 CALL 1002CEAC
001B:10077867 ADD ESP,0C
001B:1007786A MOV BYTE PTR [1009EEB4],07
001B:10077871 MOV DWORD PTR [10088844],00000001
001B:1007787B MOV EAX,EBX

If you do a "d esi" you will see your registration info. The first thing to do is to put some FFh inside ida.key, just to remove your info from this file, you will find the corresponding bytes that you saw before after the call to readfile. All the other bytes are unused. This code is called about five times until IDA decompiles your target, you can apply 3 patches to force IDA to work without a good key. The patches are showed in the listing below, first patch on ida.wll :-

.text:1006A34E JZ short loc_0_1006A36B
.text:1006A350 MOV EAX, [EAX+8]
.text:1006A353 MOV EDX, dword_0_1009AA62
.text:1006A359 CMP EDX, 20h
.text:1006A35C JGE short loc_0_1006A376 <- patch this to jmp.
.text:1006A35E MOV ECX, EDX
.text:1006A360 MOV EDX, 1
.text:1006A365 SHL EDX, CL
.text:1006A367 TEST EDX, EAX
.text:1006A369 JNZ short loc_0_1006A376

The next patch is here :-

001B:1006A342 MOV EDX,00000001
001B:1006A347 CALL 1007774C <-- this call leads to the above listing
001B:1006A34C TEST EAX,EAX
001B:1006A34E JZ 1006A36B
001B:1006A350 MOV EAX,[EAX+08]
001B:1006A353 MOV EDX,[1009AA62]
001B:1006A359 CMP EDX,20
001B:1006A35C JGE 1006A376 <-- force this to jump
001B:1006A35E MOV ECX,EDX
001B:1006A360 MOV EDX,00000001
001B:1006A365 SHL EDX,CL
001B:1006A367 TEST EDX,EAX
001B:1006A369 JNZ 1006A376
001B:1006A36B PUSH 10087712
001B:1006A370 CALL 1005726C

This code occurs when the loaders are called by IDA, like pe.ldw for example. Those modules are used for IDA to interpret typical file formats like PE, NE, etc...But you have a big problem, you can't find those places inside idag.exe, its not normal, this program is encrypted. We will face this again later on this essay, so I will use two different approaches to allow those patches. The first technique is used here for teaching purposes, if you want to remove the watermarks it will not succeed. Why ? because idag.exe is encrypted with your license information, so the better way would be to reconstruct a virgin dumped application. 

2. Reconstructing ida.wll.

To allow the patches inside ida.wll, you have to dump it decrypted. You will use IceDump, ProcDump and a HEX editor. This technique will be further explained in the last part of this essay. First load IDA until the nag screen. Do addr idag to switch to its address context. Do bpmb 8:10001000 x, ida.wll will be stopped at its *decrypted* entry point. Look at the PE structure in ProcDump : base address 1000000 length AC000.

Exit IDA and start it again, first break at 10001000 with a ret, let it run until the second break. At the second break, all is decrypted so you can dump it. Do a pagein d 10000000 AC000 c:\temp\ida.dmp, so all the memory is dumped. We have to fix the PE header with ProcDump with these options enabled :-

* recompute object size
* optimize PE structure
* check header sections
* rebuild header
* use actual import infos

We have to manually rebuild the import table, I did a fast rebuild by copying and pasting with my HEX editor, a fast way yet we could have manually fixed the API's addresses using the PE import table structure. You can locate the import table with ProcDump by the directories function and calculate the raw offset, read the PE docs. Heres a snip of the original values in ida.wll not dumped :-

ida.wll (original)

0004A6A2 0090 C1A8 0A00 D2A8 0A00 E5A8 0A00 0000 0000 6B65 726E 656C 3332 2E64 ..................kernel32.d

0004A6BE 6C6C 0000 0047 6574 5072 6F63 4164 6472 6573 7300 0000 4765 744D 6F64 ll...GetProcAddress...GetMod

0004A6DA 756C 6548 616E 646C 6541 0000 004C 6F61 644C 6962 7261 7279 4100 0000 uleHandleA...LoadLibraryA...

0004A6F6 0000 0000 0000 0000 0000 B4A8 0A00 A4A8 0A00 0000 0000 0000 0000 0000 ............................

0004A712 0000 30A9 0A00 3BA9 0A00 0000 0000 0000 0000 0000 0000 0000 0000 0000 ..0...;.....................

0004A72E 0000 7573 6572 3332 2E64 6C6C 0043 A90A 0000 0000 0000 0045 6E75 6D54 ..user32.dll.C.........EnumT

0004A74A 6872 6561 6457 696E 646F 7773 hreadWindows

You must paste that inside your dumped ida.wll (ida.dmp) at this location :-


0008B2A2 0090 5401 0080 3B01 0080 E001 0080 0000 0000 4B45 524E 454C 3332 2E44 ..T...;...........KERNEL32.D

0008B2BE 4C4C 0000 0047 6574 5072 6F63 4164 6472 6573 7300 0000 4765 744D 6F64 LL...GetProcAddress...GetMod

0008B2DA 756C 6548 616E 646C 6541 0000 004C 6F61 644C 6962 7261 7279 4100 0000 uleHandleA...LoadLibraryA...

0008B2F6 0000 0000 0000 0000 0000 B4A8 0A00 A4A8 0A00 0000 0000 0000 0000 0000 ............................

0008B312 0000 30A9 0A00 3BA9 0A00 0000 0000 0000 0000 0000 0000 0000 0000 0000 ..0...;.....................

0008B32E 0000 5553 4552 3332 2E44 4C4C 0043 A90A 0000 0000 0000 0045 6E75 6D54 ..USER32.DLL.C.........EnumT

0008B34A 6872 6561 6457 696E 646F 7773 hreadWindows

Not at the same raw offset, because this file is expanded in memory when you dumped it and the size grew. You can rename your ida.dmp to ida.wll and find the 3 places to apply the patches I described above. After you can void your ida.key at the same places I did :-






000000C4 FFFF FFFF FFFF FFFF FFFF ..........

This section is inserted into your idb files, and no use for integrity checks. Better void it.






You can remove other bytes, try it as an exercise. All the encrypted information is removed on the second snip. After this, IDA v4.01 still works and doesn't show your license info, even on *.asm or other files it can generate. Also the embedded license info inside the idb files is not generated anymore. BUT there's still a small problem, you can try to decompile big programs, it works OK at the beginning but will crash at the end with messages like 'execution flows beyond limits' etc...

If you put back your right key, the decompiling works fine. Whats happening ?. Put back your normal key in the IDA directory. A very devious final check of your key at the end of the decompiling procedure, the one that's hard to find. How did I find it ?. I went to the patched routine at this location :-

001B:10077848 CALL 10077A88
001B:1007784D TEST EAX,EAX <-- stop here
001B:1007784F JL 1007785A <-- patch this to nop
001B:10077851 MOVSX EAX,BYTE PTR [ESI+10]

If you do a bpmb 1b:10077848 x at this place, and load idag.exe you will hit 5 times before your target is decompiled. When you stop, just do a d esi, you will see in the data section your decompiled license information. If you change the equals sign to something else in memory at the second hit the errors will happen again at the end of the decompiling. The check resides here, on your decrypted key. Yes we patched IDA but this info is kept in memory and used again. If you want to trace that by yourself, take some time and be patient, this info is copied in memory to several locations (about 300 times) before the check.

You have to do a bpmb on the equals sign and release your bpmb when this value is copied to another location, and do a bpmb at the new place. I used also other tricks not included here, but if you're patient, this method works fine. We finally land at this place inside ida.wll, when your license info is finally checked and not copied to another mem location.

0008:10013318 PUSH EBX
0008:10013319 PUSH ESI
0008:1001331A PUSH EDI
0008:1001331B PUSH EBP
0008:1001331C PUSH ECX
0008:1001331D CALL 10013298
0008:10013322 TEST AL,AL <-- You land here
0008:10013324 JNZ 100133B8
0008:1001332A MOV EAX,[100993CF]
0008:1001332F CALL 10013BE0
0008:10013334 XOR EDX,EDX
0008:10013336 MOV DL,AL
0008:10013338 MOV EAX,1008AA88
0008:1001333D MOV [ESP],EDX
0008:10013340 CALL 1001149C
0008:10013345 PUSH EAX

Guess what ? if AL contains 0 the errors occurs, and that what happens when your voided ida.key is used. The CALL 10013298 is used later at run time, so we need to patch this so it nevers put a 0 in AL. Very important :- the same technique will be used on encrypted modules of ida (find them). We have to do this on all those places because the encryption is watermarked, I mean that they used your personal info to crypt everything, I have to thank Nolan Blender who helped me a lot by providing me a sfv file (files CRC) on all the files of his copy of IDA 4.01. I needed this info to locate the different files, heres a summary of the differences :-

ida.key  4 sure ;-)
all the *.ldw and *.w32

In previous versions, only the ida.key was different and you can now see where are the watermarks. I recommend reading the stenography section to learn more about this. On every file I treated, I saw very small differences between Nolan's version and mine, that means that some watermarks remain (small encrypted parts) and are decrypted by idag.exe at run time, when the modules are loaded and initialized.

3. Restoring ida.wll and modules to their *almost* original state.

First you need to understand the PE structure before reading the rest. Ida.wll and all the modules have a normal entry point. Use ProcDump's PE editor on ida.wll you will find : 100AA000. Do a bpmb on it and load IDA.

001B:100AA000 PUSHAD <-- You land here
001B:100AA001 CALL 100AA647

Typical decryption or unpacking routine, pushad saves all the registers and the next instructions does the dll decryption and finally jumps to the real entry point. To find this place you must know something, all the dlls have a common init section, the real entry point. This init functions maps the memory, initializes the vars etc... But this functions unloads the dll too. So exit idag.exe just after the nag and the bpmb triggers again, do a p ret (f12) and  :-

001B:10001000 MOV EAX,[1007A1E0] <-- you land here

That's just the real entry of ida.wll, it's the same with all the modules, always at base address + 1000 to find the virtual address. We need to dump entirely this dll from memory to HD, I first tried ProcDump but it fails when IDA loads again the dumped dll. Why ?. Very simple, ProcDumps uses loadlibrarya to load ida.wll in its address context (a big mistake to dump protected dll's), so the init section at 10001000 is called, the memory mapped and the dll is dumped. But when the mem is mapped, the init section puts some flags on and those flags are dumped too. If IDA loads then the dumped dll, the mem flags will already be set and the protection will detect this and some errors occurs. The main flags are located in the data section, and tested at the dll's init procedure.

We just need to dump the dll just at the beginning of the init section. You will use IceDump to do that. Put a bmpb at 1b:10001000 x, load IDA, wait for the second trigger (you have a ret at 10001000 when it first triggers at decrypt time)
then you land again at the same address, but this time, the dll is loaded, the mem is paged in its data section and the flags are not set. ProcDump told you about ida.wll :-

image base 10000000
length AC000

Just use IceDump and do :- pagein d 10000000 ac000 "your path, like \??\temp\ida.dmp"

You will get an ida.dmp file, containing a header to rebuild, with all the decrypted sections. You must rebuild the header with ProcDump's automated feature. You change the entry point to 10001000 too and it's working. Don't forget to patch ida.wll so the CALL 10013298 will never put eax at 0. Find the raw offset by yourself !. Here's what I did inside ida.wll :-

0008:10013298 ADD ESP,-18
0008:1001329B XOR ECX,ECX
0008:1001329D MOV EAX,ESP
0008:1001329F MOV BYTE PTR [ESP+04],24
0008:100132A4 MOV BYTE PTR [ESP+05],20
0008:100132A9 MOV BYTE PTR [ESP+06],75
0008:100132AE MOV BYTE PTR [ESP+07],73
0008:100132B3 MOV BYTE PTR [ESP+08],65
0008:100132B8 MOV BYTE PTR [ESP+09],72
0008:100132BD MOV BYTE PTR [ESP+0A],31
0008:100132C2 MOV BYTE PTR [ESP+0B],00
0008:100132C7 LEA EDX,[ESP+04]
0008:100132CB CALL 10027448
0008:100132D0 MOV EAX,ESP
0008:100132D2 MOV CL,53
0008:100132D4 XOR EDX,EDX
0008:100132D6 CALL 10027B00
0008:100132DB TEST EAX,EAX
0008:100132DD JNZ 100132E3
0008:100132DF MOV AL,01 *patched part, it was XOR EAX,EAX
0008:100132E1 JMP 10013314
0008:100132E3 MOV EDX,[EAX+04]
0008:100132E6 CMP EDX,37D730C0
0008:100132EC JGE 100132F2
0008:100132EE MOV AL,01 *same
0008:100132F0 JMP 10013314
0008:100132F2 MOV EDX,[EAX+10]
0008:100132F5 ADD EDX,FFFFFDC9
0008:100132FB CMP EDX,A5FF0506
0008:10013301 JZ 10013307
0008:10013303 MOV AL,01 *same
0008:10013305 JMP 10013314
0008:10013307 MOV EDX,[EAX+0C]
0008:1001330A TEST EDX,EDX
0008:1001330C JZ 10013312
0008:1001330E MOV AL,01 *same
0008:10013310 JMP 10013314
0008:10013312 MOV AL,01
0008:10013314 ADD ESP,18
0008:10013317 RET

So we managed to dump ida.wll and replace the crypted one with an almost virgin one. Your IDA is now working well, decompiling everything without errors, and not signing the files, as an exercise we can bring back the *.w32 and *.ldw to their *almost* original state. We will use the same technique to dump, rebuild the header and change the entry point to base address +1000. But this time you have errors when the loadlibrarya function called from IDA tries to load the module, we take pe.ldw as a target practice.

You can use a great tool called PEbrowse to compare pe.ldw original to the dumped one, it will show you that the import section is not the same on your dumped module, why ? because when you dumped it, Windows changed the API addresses inside this section and those addresses are not valid for your dumped module. The import section is damaged. Where is it located, look in ProcDumps directory structure: import table = 178F4 (virtual address).

What is the corresponding file offset ? Look at the sections : .adata Virtual offset 17000 and Raw Offset F200.

The raw offset is (178F4-17000) = 8F4 + F200 = FAF4

You see here the imported functions in ASCII style with your HEX editor. You can do two things. The most interesting is to learn, rebuild the import table structure yourself, I did that, it takes times but you will get great rewards in your future cracks. The easy method, get the import section from your original pe.ldw :-

original pe.ldw

0000889C 6172 7920 2573 0090 C178 0100 D278 0100 E578 0100 0000 0000 6B65 726E ary %s...x...x...x......kern

000088B8 656C 3332 2E64 6C6C 0000 0047 6574 5072 6F63 4164 6472 6573 7300 0000 el32.dll...GetProcAddress...

000088D4 4765 744D 6F64 756C 6548 616E 646C 6541 0000 004C 6F61 644C 6962 7261 GetModuleHandleA...LoadLibra

000088F0 7279 4100 0000 0000 0000 0000 0000 0000 B478 0100 A478 0100 0000 0000 ryA..............x...x......

0000890C 0000 0000 0000 0000 4479 0100 5779 0100 0000 0000 0000 0000 0000 0000 ........Dy..Wy..............

00008928 4C79 0100 5F79 0100 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 Ly.._y......................

00008944 6964 612E 776C 6C00 7573 6572 3332 2E64 6C6C 0001 0000 8000 0000 0067 ida.wll.user32.dll.........g

00008960 7901 0000 0000 0000 0045 6E75 6D54 6872 6561 6457 696E 646F 7773 0000 y........EnumThreadWindows..

Compare this place to your dumped pe.ldw and copy all the bytes from 889C to 8962 from the original to your dumped ldw. The import section is now restored and points to good API addresses. Don't forget to : rebuild the PE header, change the entry point and rebuild the import sections on all the modules ldw or w32 that you want and they will be all decrypted, you can now decompile them with ida if you want to look further.

As an example I did that on my pe.ldw and Nolan's pe.ldw, three places in the dumped files still differ (first your license info in plain ASCII text in the header, easy to remove, and two other places in the files. So my essay stops here and I still will not explain how to remove the last watermarks, search for yourself, it's an easy thing for you if you understood all the essay.

Final Notes

If you manage to remove the last watermarks, don't spread this cracked tool. Software protections are getting more and more difficult to defeat. You could compromise further updates of IDA if you do that, so you will work against your reversing potential. Here's a snippet from Pierre Vandevenne, the product administrator :-

Re: Re: IDA 4.01 changing thoughts...
Wednesday, 09-Feb-2000 16:18:29 writes:


We probably don't have the same definition of stealing, but I thought I'd say a few words here

The name of the user that created the database is indeed stored in the database. No need for reverse engineering, hearsay or whatever here, the name is displayed in the beginning of the disassembly ! Several reasons for this, one of them being that some users have requested IDA Pro to be multi-user and to be able to retrieve who created the database.

About the greediness, well we could be a greedy company, but it really doesn't apply to IDA. Consider

1) that the market for advanced development tools is extremely small today.

2) that IDA is developed in a fully legal and licensed environment. We pay for compilers, for specs, for books, for packers, whatever we need and can buy. We buy from companies and companies buy from us and as a result jobs are created on both sides. Wrong ?

3) Ilfak now works full time in Belgium - guess what, we haven't imported him as an illegal alien and haven't hidden him in a cave with a 486 and an amber monitor. Anything wrong with this approach ? Doesn't he deserve a nice work environment ?

4) we give constant and immediate support to customers.

Honesty is not a function of the mood, it is an intrinsical quality. If you want to be dishonest, please feel free to do so, you don't need any justification.

Pierre Vandevenne

I just hope that everybody will understand this final advice.

If something is wrong, or updates are needed send me an e-mail.