Iris v2.00 build 14
[Reversing essay]

Subject: Cracking
Target: Iris v2.0

Author: BlackB
Date: 2001-03-18 Update 1
Tools used: SoftICE, ReVirgin (@ , IT Add (@, PE Editor (@, IceDump (@
Difficulty (scale 1-5): 4 (well, actually not that difficult, but it is if you don't know anything about this)

Before starting!
This essay is for knowledge purposes only!!
Software developers spend much time in making their programs. They live from the money we give them!
Please buy good software!!
published by +Tsehp march 2001
I. Introduction
Welcome again to the world of unpacking. With all the fuss around ASProtect, some people may have forgotten about other wrapping protections. In this essay we'll unwrap a PCGuard-wrapped application. After that we'll crack it too.
This program is a very nice packetanalyzer, but costs way too much: 1745$. I mailed the author about it, and he told (quote): "The right price is the one that market is willing to pay for something. Iris is targeted for corporations and they can pay that money without remorse. If IRIS helps them solve a 2000$ problem ( and this is nothing speaking of consulting fees) then is well worth it."
As you and I are no company we deserve a little cheaper product anyway.......
II. About the protection

Wrapped with PCGuard: you 'll know this when looking to the sections of a protected .exe. It uses the same importtable trick as ASProtect. Also has some basic anti-softice. Quote from the PC Guard website:

"Security envelope consist of large number of encryption layers and anti-debugging, anti reverse engineering code and contains all protection functions. Protected application becomes encrypted after protection and is distributed in encrypted state. You can put more then one protection layer around your application for better security. This makes protected application highly secure and safe from tampering."

Nice said....'easily' disproven.

III. Cracking it

In this essay I 'm going to use this approach:

I. Unwrapping

1. Finding OEiP
2. Dumping
3. ReVirgin
4. Another unwrapping way

II. Cracking

Let's begin!

I. Unwrapping

1. Finding the OEiP

This is about always the first step for unpacking programs: finding the Original Entrypoint. I already explained in previous unpacking essays how to do this, but I'll repeat it for you with some more details and an alternative method.
Program starts executing: the wrapper/packer unpacks the code in all the sections, when done, the wrapper code jumps to the start of the unpacked program (=OEiP). A scheme:

push ebp ; start of program
....instructions of the wrapper that unpack the program....
ret or jmp OEiP; wrapper jumps to the start of unpacked program

OEiP: real program starts here

Table 1: OEiP

To find the OEiP for Iris, run IceDump (to hide SoftICE for the basic anti-softice), set a breakpoint on GetProcAdress. Now run the program, SoftICE should popup. Press F5 three times (you can press it more too). Now...from there on you're on your own. Just trace, set breakpoints to get out of loops, and don't get nuts of the annoy-cracker instructions.
Well, that's the way I've found the OEiP. But there's an easier way. IceDump has a feature named TraceX. Syntax: /tracex low eip high eip . This makes SoftICE pop when the program executes an instruction lying between your set 'low eip' and 'high eip'. The only difficulty is to set the 'low eip' and 'high eip'. Well, let's take a look where we are in SoftICE: somewhere at offset 560000. I 'd bet that the original program lies somewhere between offset 400000 and 500000. Type: "/tracex 400000 500000" patient....SoftICE breaks on an instruction somwhere at 420000. You can see that it jumps back to the wrapper code, so that's not the OEiP. Trace with SoftICE until you're jumped back to the wrapper code.
Type "/tracex 400000 500000" agao, and HAVE PATIENCE. This can take quite some time!
When SoftICE pops, you're at offset 44717C at instruction 'push ebp'. Voilà, that's our OEiP! Stay where you are now......

2. Dumping

You still on that instruction? Now enter: "/dump 400000 130000 c:\progra~1\iris\dumped.exe" . The 400000 is the Image Base, the 130000 is the Image Size. You can get both of these values in PE Editor when loading the original Iris.exe in it. Now you have to fix the sections by equalizing the Raw Size to the Virtual Size (Raw Size=Virtual Size) and the Raw Offset to the Virtual Offset (Raw Offset=Virtual Offset). In PE Editor, this can be quickly done by right clicking on every section in the "Sections" menu and click on "Dumpfixer". Start from the first section and work your way down to the last.
After doing this, the Iris icon will appear on the dumped.exe file. Change the OEiP to 4717C. Try to run doesn't work. Why?

3. ReVirgin

When Iris wants to execute an API it works like this:
472000 call [4BA48C]
CDEC08 jmp kernel32!compareStringA
(in this case, the generated importtable jumps to the correct API)


472000 call [4BA48C]
CDEC08 push DFEF04
CDEC09 call 18FFE4

(in this case, the generated importtable calls a decryption routine that feeds the target's thunk import table with the right adress)

You can't find the original IAT before all this is generated at first, because it doesn't exist anymore, so you can't use procdump or a IAT rebuilder to make the app work, you have to rebuild everything this time. We *could* do this manually, but that would take a lot of time. Nowadays we have a new utility to reconstruct a *damaged* importtable. It's coded by +tsehp and is named ReVirgin. We 'll use this program to rebuild our importtable:

Run ReVirgin and take a look at it. This util is not a "push-the-button-and-i'll-do-everything-for-you". It is a Fravia's tool that needs understanding before you can use it. Some explanation of the editboxes you have to fill in yourself:

1. IAT Start RVA: offset where the generated importtable starts
2. IAT Length: length of the generated importtable
3. IT RVA: where will the importtable be in memory, when we've inserted it in the dumped.exe
Table 2: Explanation of ReVirgin options

How they can be found:

1. Run the program with a breakpoint on UpdateWindow (or another one), when SoftICE breaks, press F12 until you are back in Iris maincode. Then trace into every call you come across until you turn out to be in the jump table. A jump table looks like this:

Start partial code

015F:004469D8  JMP       [004BAF4C]
015F:004469DE JMP [004BAF50]
015F:004469E4 JMP [004BAF54]
015F:004469EA JMP [004BAF58]
015F:004469F0 JMP [004BAF5C]
015F:004469F6 JMP [004BAF60]
015F:004469FC JMP [004BAF64]
015F:00446A02 JMP [004BAF68]
015F:00446A08 JMP [004BAF6C]
015F:00446A0E JMP [004BAF70]
015F:00446A14 JMP [004BAF74]
015F:00446A1A JMP [004BAF78]
015F:00446A20 JMP [004BAF7C]
015F:00446A26 JMP [004BAF80]

End partial code

Now, scroll through the jump table and try to find the lowest jump offset (i.e. find the JMP xxxxxxxx where xxxxxxxx is the lowest value in the whole jumptable). Note that this jump table can be divided by a lot of other instructions, so you'll have to scroll to make sure you saw the whole jumptable.
Another method to find the lowest offset, is to take a random offset in the jumptable (like 4BAF80), type d 4BAF80 and scroll up in the datawindow until there's no more data, but only zeros.
In Iris, the beginning of the IAT is @ offset 4BA48C. Fill in BA48C in ReVirgin.

2. For the length of this table I usually choose a random (but big) value, like 2000 or something. This may not always work. In that case use the scroll-down method in the datawindow to find the end of the importtable. The length in our case is 1308

3. Most of the time, we will insert the new importtable at the end of the file in a new section. Just fill in the offset of the end of the dumped file (image size), which is in our case 130000.

Now run the original Iris.exe, refresh the application list in ReVirgin. Click on the Iris.exe process in ReVirgin. It should tell you that the importtable is invalid. Now, with all values filled in, push the "IAT Resolver" button. When it's finished push "Resolve again". Voila, now you should see our newly created importtable. Push "IAT Generator" and save the importtable under the file IT.BIN. Note the IT Length (which is 194 in our case). You can see the resolved importtable here and the it.bin here. You can leave ReVirgin now and exit Iris.

Next thing to do is to prepare our dumped.exe for the new importtable:

  • Open dumped.exe with PE Editor
  • Click on "Sections"
  • Right click on a section and choose "Add section"
  • Name the section .idata (any other name is good too, like .BlackB)
  • Rightclick on your section and change Raw and virtual size to 5000. Always make sure this value is at least the size of the importtable!! Otherwise it will not work
  • Rightclick on your section and click on "Dumpfixer"
  • Leave the sections
  • Click on "Directory"
  • Change importtable rva to 130000 and the length to 194
  • Change Image Size to 135000 (we added a section of 5000 => Image Size = Old Image Size + 5000 = 135000)
  • If not yet done, change the entrypoint to 4717C
  • Click on "Apply changes"
  • Leave PE Editor
Table 3: Prepare the dumped EXE

Now open dumped.exe with a hexeditor, goto the very end of the file and insert IT.BIN into it. Save the changes. Run the finally fixed dump and it runs!
You can also use an utility named IT Add by SV. Just change the OEiP and the Importtable RVA and length of your dumped.exe. Then run IT Add, and the rest is done for you.

4. Another unwrapping way

There is another way of unwrapping this protection which is much much easier and much much shorter than the previous one. Then why making it difficult when it is easy? Because this method doesn't work most of the time with such protections. You will be able to use this method to break all PCGuard protections, but it won't work with ASProtect.

Anyway, how does it work? First of all, find the OEiP. When you're AT the OEiP with SoftICE and IceDump loaded, type: /pedump 400000 44717C c:\progra~1\iris\iris_dump.exe.
After that, leave SoftICE and change the OEiP in iris_dump.exe to 4717C with PE Editor. Exit PE Editor, run your dumped file and it works. Easy huh? ;-)

Okay, last thing to do....cracking it.....

II. Cracking Iris

There's a 15-day limit and a nagscreen. I tried removing the nag by setting breakpoints on UpdateWindow and SendMessageA, but it didn't work out quite well (it did, but I found a better and much easier way). Just disassemble your dumped/fixed file and search for any ", 0Fh" occurence. You should see this:

Start partial code

004308AF loc_4308AF:                             ; CODE XREF: sub_430730+16Bj
004308AF mov dword ptr ds:498A88h, 0
004308B9 call sub_446144
004308BE mov eax, [eax+4]
004308C1 push 46295Ch
004308C6 push 462954h
004308CB push 46294Ch
004308D0 mov ecx, eax
004308D2 call sub_446444
004308D7 call sub_446144
004308DC mov eax, [eax+4]
004308DF push 46295Ch
004308E4 push 46293Ch
004308E9 push 46294Ch
004308EE mov ecx, eax
004308F0 call sub_446444
004308F5 call sub_446144
004308FA mov eax, [eax+4]
004308FD push 46295Ch
00430902 push 462934h
00430907 push 46294Ch
0043090C mov ecx, eax
0043090E call sub_446444
00430913 mov ecx, esi
00430915 call sub_431570
0043091A test ebp, ebp
0043091C jle loc_4309F0
00430922 cmp ebp, 0Fh
00430925 jg loc_4309F0

End partial code

This is where our time trial is checked. We could patch this, but the nag won't be gone and the program will display it's a demo version. Although it's a demo version it can be registered, so there must be a 'registered-or-not-flag'. If that flag is set to 'registered', the piece of code above is _never_ executed. So let's take a look where the program jumps to the 'check-trial' routine above (@ 0043089B = 430730 + 16B)

Start partial code

00430890 loc_430890:                             ; CODE XREF: sub_430730+148j
00430890 push 0
00430892 mov ecx, esi
00430894 call sub_431660
00430899 test eax, eax
0043089B jnz short loc_4308AF
0043089D push 1
0043089F mov ecx, esi
004308A1 call sub_431660
004308A6 push 0Fh
004308A8 mov ecx, esi
004308AA call sub_431210

End partial code

Whatever we'll do here, we will still end-up at the time-trial check. Let's go to the jump that jumps to this code (@ 00430878= 430730+148)

Start partial code

00430868 loc_430868:                             ; CODE XREF: sub_430730+134j
00430868 lea ecx, [esp+30h+var_14]
0043086C mov byte ptr [esp+30h+var_4], 2
00430871 call sub_44611A
00430876 test bl, bl
00430878 jz short loc_430890 <- If not registered jump, else don't jump
0043087A mov ecx, esi
0043087C mov dword ptr ds:498A88h, 378Dh <- Set registered flag
00430886 call sub_431570
0043088B jmp loc_430A14

End partial code

Pretty obvious now: just nop out the jz short loc_430890 with your favorite hexeditor. When done, run your dumped/fixed/cracked file and it works, without the nag, without the time trial!

To make it registered to your name and company, change following keys:

HKEY_CURRENT_USER\Software\eEye Digital Security\Iris\User\Nume (note that this is not a typo)
HKEY_CURRENT_USER\Software\eEye Digital Security\Iris\User\Company

This is (of course) easily found with RegMon. That's it, we're done!

IV. In the end

Lots of work on this essay, even tho it's quite short. Been working about 3 hours on it. Sometimes it's hard to remember all things I did when cracking it.....anyway.....Thx goto +tsehp for ReVirgin and help on using it, +Splaj and Risc for help on unpacking and PE structure.

Please report bugs in this essay as soon as possible @ cracking(at) and don't even think about requesting a crack/serial!


The Blackbird aka BlackB

Essay written by The Blackbird © 1999-2001
This essay can be freely distributed/ published/ printed etc... as long as no modifications are made in any way.