Manually unpacking Asprotect version 1.05
Building a fake import table

Not Assigned
July 2000

by Tsehp

Courtesy of Fravia's page of reverse engineering
slightly edited
by Fravia+
There is a crack, a crack in everything That's how the light gets in

updated 02/8/2000

( )Beginner (x)Intermediate (x)Advanced ( )Expert


Manually unpacking Asprotect version 2000
Building a fake import table
Written by Tsehp


Asprotect is a well know target, this packer was studied a lot and often used as a target practice for newbies. If you don't know anything about packing, improve your knowledge on the past essays, then come back, I'll try to explain you their last tricks. I use to find this target while looking for the sandman's newbie msgboard. Thanks to a Fravia called SV that explained very well the protection on his threads, his work made me save a lot of time.

Important : This essay can bring you a working app with your actual windows version. But the import table that is rebuilt will work only on win nt 4.0/2000, why ? The commview's version I cracked is designed for win nt4/2000 , on win98 another version is installed, with a different import table. So if you want to unpack on windows 98, you can't use the build_table file I provided, use my method anyway, the code will generate a working table for win 9x.

I also used this method for picturestoexe, this app doesn't use export ordinals and the cracked target fully works on my win2000 and win 98.

This essay is provided to teach you a new technique when you unpack a target with a completly destroyed import table, so read carefully and practice everything step by step.

Tools required
Softice 4.05
Ida 4.10
An hex editor

Essay made on win 2000.
Target's URL/FTP
This is Commview 2.1, another portsniffer.


1) The anti-softice routines

Before lauching this app, you have to hide your debugger. This prog uses two typical anti softice tricks:

-Is the driver loaded ? : bpx createfileA do "d esp-4"

Commview tries to see if three different versions of softice are loaded. You will hit three times : SIWDEBUG SICE NTICE

Well it depends on the system you're on, press F12 at each time, the createfilea must return 0xFFFFFFFF If not, press F12 again and set your eip to the address pointed by the second jnz below, you will pass all the tests.

-The boundschecker trick. Sice uses int3 for its breakpoints, but when special values are set to register, especially ebp containing 'BCHK' 0x4243484b, then if an int3 is encountered, the normal interrupt handler just returns after this Int3 inside your target, so the code just after is executed if sice is present. To avoid this, press F10 several times after setting your eip, go slowly through the code until you see the int3 in sice. When you're on it, change your ebp to something else than 0x4243484b, then the program will run normally until a last check detected by bpx createfilea, just as above.

For the final check, just invert the jz after the createfileA, all the tests are now defeated.

Note : I used to munually do that, because frogsice is not actually implemented on win NT, the actual copy on nt called Ntall is not fully working, so I couldn't use a loaded device to avoid those manipulations.

2) Locating the Entry point.

If you want to dump your packed program, you must stop the target here, so all the sections would be loaded. I have to admit that I directly used the technique that Eternal Bliss found on the newbie's forum. Here it is, untouched :

1) bpx on getprocaddress
2) Once you break, look at the .idata section by "dd 4E3000". This is found by doing "map32 cv"
3) bpm on the 1st byte (just to break there) and disable getprocaddress breakpoint
4) F5 and let the program run
5) Upon breaking, disable all breakpoints
6) F12 4 times and you will land at a Xor EAX, EAX
7) Start tracing with F10
8) Everytime you come across a CALL, check that a few instructions below are JMP
9) If it is, you can trace over it
10) If it is a ret, you have to trace into that CALL with F8
11) Then step over the 2 subsequent CALLs
12) You will see the OEP moved into EAX somewhere there
13) Then you will come across a POPAD
14) The JMP stuff appears again like the start of the unpacking code.
15) Trace into the next (3rd) Call and F8 all the way till you hit a ret
16) Continue with it and you will land in on the OEP.

Just apply this and you will find it, 0x4de384 on my system. Just remember that you will find almost all the time a POPAD instruction just before the final jump.

You have to dump the exe, using icedump and procdump to rebuild the pe (this will not be explained here, if you don't know how to do this, just look at the past packer/unpacker essays).

Very important : Use those procump options when rebuilding the pe : Structure : disable optimize pe structure Import : don't rebuild import Leave other options untouched. You have to manually copy the .aspr section from cv.exe (original) to cv_dumped.exe, using your favorite hexeditor. As an example I found inside original raw offset : 5aa00 length 14800 dumped raw offset : ff400 length 14800, this manipulation will copy back the original import table.

But this dumped will not work, just try to load your dumped exe inside ida and you will notice that the import table is damaged, some virtual addresses in other sections are also pointed to wrong places. In fact we have a legal import table located inside .aspr section but almost all its imports are not used, except for loadlibrarya, getmodulehandleA and getprocaddress, the rest is here to fool us, stupid crackers ;-)

The main protection of Asprotect is just here : Some imports are fine and pointing directly to the api's addresses some other are pointing to a table (located in mem at 0x00CDxxxx) normally containing some decrypted import's addresses, and this table originally contains also some routines to decrypt other addresses when commview needs them, even if this prog is unpacked.

Well we have here a big problem : You can manually fix the import table if you convert all the tables addresses to the .idata at the right place.

So if inside you dumped app, inside .idata you have

4e328c : jmp [cd4950] and cd4950 containing 77db858e (a valid import address)

you could convert the jump at 4e328c to directly point at 77db858e.

You will spend a lot of time (about 520 addresses) then it will not work. Because inside the cdxxxx table, some addresses points to code like this : cd4950 push cd495a call 182f68 (for example)

Whats happening ? When commview does call 4e328c (import table) the routine located at cd4950 just decrypts the right import adress AT RUNTIME ! You can also try to dump the cdxxxx table, the decrypting code will still be here and definitely not working. This feature is the real improvement made since the last Asprotect versions. And they actually offer to download a version that doesn't apply that kind of protection, strange ;-) "Next thing to do is getting a virgin importtable, as the one inside our dumped file is corrupt. This is how we will work: 1. Inserting some code to build our import table 2. Dumping our import table to the harddisk 3. Fixing the adresses of the import table with a self coded program." (thanks blackb ;-) ) the previous asprotect version was more easy to unpack, the IAT was possible to locate and put back, my previous asprotect essay provided some direct mem jumps inside the import table, not generated by a getprocaddress. This works but, the target only runs on your pc, and if you update some dll's, the addresses are not the same and your target crashes.

3) Generating our string table

You are still on the int3 instruction, just do a S 0 L FFFFFFFF AC 08 C0 74 E4 and you will localize the *culprit* loop that builds the asprotect import table, just do a bpmb at the start. I found this place while logging the getmodulehandle/getprocaddress usual loop, when you pret you land after the call at 19a53a.

Here is what you find :

001B:0018A51E  AC                  LODSB
001B:0018A51F  08C0                OR        AL,AL
001B:0018A521  74E4                JZ        0018A507
001B:0018A523  4E                  DEC       ESI
001B:0018A524  56                  PUSH      ESI
001B:0018A525  53                  PUSH      EBX
001B:0018A526  80F802              CMP       AL,02
001B:0018A529  7407                JZ        0018A532
001B:0018A52B  0FB64E01            MOVZX     ECX,BYTE PTR [ESI+01]
001B:0018A52F  41                  INC       ECX
001B:0018A530  EB05                JMP       0018A537
001B:0018A532  B904000000          MOV       ECX,00000004
001B:0018A537  41                  INC       ECX
001B:0018A538  01CE                ADD       ESI,ECX
001B:0018A53A  E8B5FDFFFF          CALL      0018A2F4 <- redirect this point 
note the address 0x18a2f4.
001B:0018A53F  AB                  STOSD
001B:0018A540  EBDC                JMP       0018A51E <- note this address too, 
it's the loop back jump.

All we have to do is to find a free mem location filled with 0 so we can write a small code to modify this routine. The address 0x180000 will be used as an example.

What are we doing : to rebuild the import table, I will generate something to make it. I reversed asprotect for this and found that it's building a fake import table for the target that interacts with your app.

The thunk import table looks like this if we don't, commview calls this :

402000 call [4ebc38]; 4ebc38=cdec08 ; cdec08=jump kernel32!compareStringA a indirected api call. or cdec08:push dfef04 , call 18ffe4 ; this one is more devious, at runtime when this is called, the generated table at CDxxxx calls a decryption routine that feeds the target's thunk import table with the right address. 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.

The IAT will be rebuilded in two steps :

1)generate a dump, looking like this : <moduleName>0<procName/ordinal_number>0<corresponding target's address to copy the API address> for example :

GetcurrentThreadId0Kernel32.dll068bc4e00 and so on....about 530 groups generated, this could take a long time to do manually. Asprotect must use getmodulehandlea and getprocaddress to generate the right addresses for his Daxxxx table, so I just found the occurences inside its code and traced all the functions parameters, to get them back inside my call fixer.

2)write a code at the end of this dump to regenerate the real IAT thunk (the place where apis addresses are normally set by the os at load time)

First step

NOTE : all the addresses are different at each run of your target.

First patch 18a53a jmp 180000

Then write the following code in mem with softice :

Fake import table builder for commview 2.1 do a s 0 l ffffffff ac 08 c0 74 e4 , this search is constant. redirect the call just before the stosd to some free mem space (here at 180000) by a jump 180000, note the next address op, (here 195004) note the address called and repeat it at the beginning of this code (here 19ff00) for the last part of this code, the decryptor, find the address to call by : s 0 l ffffffff 55 8b ec 81 c4 f8 fe ff ff 53 56 note the address here (19ff08), don't forget to patch this decryptor inside asprotect by doing a d 19ff08+95 and write three nops 90 90 90, this will make a normal ret after your call. put 00 00 50 00 on address 17fff0, just at the beginning, this will start the copy at 500000 (using commview committed mem) dont forget to fill this place with 00's, with a length of 4000, just to clean up the place.

Note : This call fixer must be adapted to your target, especially for the three different cases (legal procname, ordinal and encrypted one), the tests could
be different, depending on the asprotect version and the the way it's implemented inside the target.

17fff0:00 00 50 00 ;we start to generate our dump at 500000 in mem

beginning for example at 1b:00180000
CALL      19ff00			;we put back the call that we redirected here
PUSHAD					;better save them
CMP       DWORD PTR [0012FDF3],00	;12fdf3 points to proc_name, otherwise it's a 
crypted one or an ordinal (*2)
JZ        00180065			;goes to ordinal/crypted procedure
PUSH      0012FDF3			;copy from (*1)
1b:180014 PUSH      DWORD PTR [0017FFF0]		;copy to
CALL      78281E39 			;call lstrcpy (your address could differ)
PUSH      DWORD PTR [0017FFF0]		;just to see
CALL      78291334			;how long this string is
INC       EAX
INC       EBX
ADD       [0017FFF0],EAX		;set the mem pointer to the next place, for the 
									procname string
PUSH      EBX				;ebx points to the module_name string (result from 
call 19ff00) (*3)
PUSH      DWORD PTR [0017FFF0]		
CALL      78281E39			;copy again
PUSH      DWORD PTR [0017FFF0]
CALL      78291334			;check the length
INC       EAX
ADD       [0017FFF0],EAX		;adjust the table's offset
MOV       ECX,[0017FFF0]		;ecx contains a pointer to our table next location,
to set the iat address
MOV       [ECX],EDI			; edi always contains the target's address where we 
have to put the api's address
ADD       DWORD PTR [0017FFF0],05	;set the offset to next group
POPAD					;get the registers back
JMP       00195004			;and continue the asprotect loop
1b:180065 CMP       ECX,00			;if ecx<>0 the procname is an ordinal number
JNZ       00180079			;so we go to the ordinal procedure
PUSH      DWORD PTR [EAX+01]		;to pass the right parameter to the asprotect 
decrypting procedure, normally	called at runtime
CALL      0019FF08			;decrypt the procname (*4)
PUSH      0012FDEC			;set the procname string that is now decrypted
JMP       00180014			;we have the procname string decrypted, lets continue 
inside my fixer
1b:180069 SUB ESI,4			;ESI points here to the export ordinal number (*5)
PUSH      ESI				;set the pointer to ordinal,so we copy it inside 
							the table
JMP	  180014			;we have the ordinal, let's copy it inside the table

(*1) and (*3)this 12fdf3 address was found while dwelling inside the call 19ff00, it is pushed with the one in (*3) just before a call to a getmodulehandleA and getprocaddress sequence.

(*2) I checked this value several times just after the call 19ff00, it's a constant one.

(*4) this address I found while looking into the original jumps inside the IAT, some jumps calls directly the apis, the encrypted ones always begin by push xxxxxx, call this address.

(*5) same method as (*1) I writed the mem loc and did a pret, esi is always +4 after this address in this case. Put a bpmb on the popad after the call you redirected, it will trigger when the copy is finished. finally dump your table for later use.


PAGEIN D 500000 3ba0 (for example) Just look inside the mem from 500000 down until you find the table's end, we have here all the three components needed to rebuild commview's import table, the procname or ordinal number, its dll name and the target's address to copy the imported address.

Shortcut to test your dumped commview:

If you're lazy, you have here the final result : dumped table with the rebuilder added at the end. Just take your dumped commview, you have to realign it so the rva offsets=raw offsets, add a new section (length = 3c0e) at the target's end, paste this file on the new section and change the commview's entry point at 530b45 (130b45 on procdump, the imagebase is at 400000) and watch what's happening with softice, everything is explained on the following lines.

4)Setting the rebuilder

Now that you have your dumped table and your dumped commview, we need to add this table at the end of the dumped target,to ease your work the dumped commview must have the rva offsets corresponding to raw offsets, use pe-editor to add a new section 4000 length, here are the results :

for the sections :

Your dumped table consists of about 500 group of three members : module name, proc name or ordinal and address to copy the result.

I had to code a rebuilder at the dumped table's end :

He globally takes the first two members : module name and proc name / ordinal, uses getmodulenameA and getprocaddress to get the function's address in mem and copy this address back in commview, heres the listing fully explained.

00530AE7                 db  4Fh ; O  HERES THE LAST MEMBER OF YOUR DUMPED TABLE, 
you see openSCManagerA,
00530AE8                 db  70h ; p  advapi32.dll and 004e3994 is the last address 
to copy inside commview, 	
00530AE9                 db  65h ; e  4e3994 corresponds to the last thunk of 
commview's original IAT.
00530AEA                 db  6Eh ; n
00530AEB                 db  53h ; S
00530AEC                 db  43h ; C
00530AED                 db  4Dh ; M
00530AEE                 db  61h ; a
00530AEF                 db  6Eh ; n
00530AF0                 db  61h ; a
00530AF1                 db  67h ; g
00530AF2                 db  65h ; e
00530AF3                 db  72h ; r
00530AF4                 db  41h ; A
00530AF5                 db    0 ;  
00530AF6                 db  61h ; a
00530AF7                 db  64h ; d
00530AF8                 db  76h ; v
00530AF9                 db  61h ; a
00530AFA                 db  70h ; p
00530AFB                 db  69h ; i
00530AFC                 db  33h ; 3
00530AFD                 db  32h ; 2
00530AFE                 db  2Eh ; .
00530AFF                 db  64h ; d
00530B00                 db  6Ch ; l
00530B01                 db  6Ch ; l
00530B02                 db    0 ;  
00530B03                 db  94h ; 
00530B04                 db  39h ; 9
00530B05                 db  4Eh ; N
00530B06                 db    0 ;  
00530B07 unk_530B07      db    0 ;               ; DATA XREF: start+85o
00530B08                 db    0 ;  
00530B09                 db    0 ;  
00530B0A                 db    0 ;  
00530B0B                 db    0 ;  
00530B0C                 db    0 ;  
00530B0D                 db    0 ;  
00530B0E                 db    0 ;  
00530B0F                 db    0 ;  
00530B10                 db    0 ;  
00530B11                 db    0 ;  
00530B12                 db    0 ;  
00530B13                 db    0 ;  
00530B14                 db    0 ;  
00530B15                 db    0 ;  
00530B16                 db    0 ;  
00530B17                 db    0 ;  
00530B18                 db    0 ;  
00530B19                 db    0 ;  
00530B1A                 db    0 ;  
00530B1B                 db    0 ;  
00530B1C                 db    0 ;  
00530B1D                 db    0 ;  
00530B1E                 db    0 ;  
00530B1F                 db    0 ;  
00530B20 dword_530B20    dd 0                    ; DATA XREF: start+ACw
00530B20                                         ; start+B9r
00530B24                 db    0 ;  
00530B25                 db    0 ;  
00530B26                 db    0 ;  
00530B27                 db    0 ;  
00530B28 adr_lstrlen     dd 0                    ; DATA XREF: start+18w
00530B28                                         ; start+32r ...
00530B2C                 db    0 ;  
00530B2D                 db    0 ;  
00530B2E                 db    0 ;  
00530B2F                 db    0 ;  
00530B30                 db    0 ;  
00530B31 aLstrlen        db 'lstrlen',0          ; DATA XREF: start+Co ;Write lstrlen 
to retrieve this	 procedure's address in your rebuilder.
00530B39                 align 4
00530B3C lpProcName      dd 0                    ; DATA XREF: start+2Cw
00530B3C                                         ; start+51r ...
00530B40 current         dd 0                    ; DATA XREF: start+22w
00530B40                                         ; start+27r ...
00530B44                 db    0 ;  
00530B45 ;  S U B R O U T I N E 
00530B45 ; this prog uses a table pasted above :
00530B45 ; <procname>0<modulename/export ordinal >0<address to copy into 
thunk import table>
00530B45 ; it gets the real addresses to put into the app's import thunk table
00530B45                 public start
00530B45 start           proc near
00530B45                 mov     eax, offset aKernel32_dll ; get an offset to 
kernel.dll, at the start of the table
00530B4A                 push    eax             ; lpModuleName
00530B4B                 call    ds:GetModuleHandleA
00530B51                 push    offset aLstrlen ; get offset to lstrlen string
00530B56                 push    eax             ; hModule
00530B57                 call    ds:GetProcAddress
00530B5D                 mov     ds:adr_lstrlen, eax
00530B62                 mov     eax, offset aGetcurrentthre ; pos the offset at 
the table beginning
00530B67                 mov     ds:current, eax ; its a procname, we save it temporarly
00530B6C loc_530B6C:                             ; CODE XREF: start+8Fj
00530B6C                 mov     eax, ds:current
00530B71                 mov     ds:lpProcName, eax ; save this procname offset 
at the right place
00530B76                 push    eax
00530B77                 call    ds:adr_lstrlen  ; calculate procname string length
00530B7D                 cmp     eax, 1          ; is it an ordinal import ?
00530B80                 jz      short loc_530BDB ; go to ordinal treatment
00530B82                 inc     eax
00530B83                 add     ds:current, eax ; adjust the current offset to the next string
00530B89                 mov     ebx, ds:current ; its a modulename now, we get the address
00530B8F                 push    ebx             ; lpModuleName
00530B90                 call    ds:GetModuleHandleA ; calculate the modulename handle 
for getprocaddress
00530B96                 push    ds:lpProcName   ; get the previous procname to calculate 
the real address
00530B9C                 push    eax             ; hModule
00530B9D                 call    ds:GetProcAddress
00530BA3                 nop
00530BA4 loc_530BA4:                             ; CODE XREF: start+C7j
00530BA4                 mov     ebx, eax        ; save the procname address for the import 
table in ebx
00530BA6                 push    ds:current
00530BAC                 call    ds:adr_lstrlen  ; calculate the modulename length
00530BB2                 inc     eax
00530BB3                 add     ds:current, eax ; actualise the current offset, it points 
now to the apps thunk 
import table address
00530BB9                 mov     ecx, ds:current
00530BBF                 mov     eax, [ecx]      ; get the app's address
00530BC1                 mov     [eax], ebx      ; save the procname's address into import 
thunk table
00530BC3                 add     ds:current, 5   ; actualise the current offset to point to 
the next modulename
00530BCA                 cmp     ds:current, offset unk_530B07 ; are we at the table's end ?
00530BD4                 jl      short loc_530B6C ; repeat to the next import table address
00530BD6                 jmp     loc_4DE384      ; jump to app's entry point
00530BDB ; ---------------------------------------------------------------------------
00530BDB loc_530BDB:                             ; CODE XREF: start+3Bj
00530BDB                 xor     edx, edx
00530BDD                 mov     ecx, ds:lpProcName ; get the ordinal import offset
00530BE3                 mov     dl, [ecx]       ; get the export ordinal number
00530BE5                 inc     eax
00530BE6                 add     ds:current, eax ; actualise the current offset to point to 
00530BEC                 mov     eax, ds:current
00530BF1                 mov     ds:dword_530B20, edx ; save the ordinal
00530BF7                 push    eax             ; lpModuleName
00530BF8                 call    ds:GetModuleHandleA ; get the modulename's handle
00530BFE                 mov     edx, ds:dword_530B20 ; retrieve the procname's exported 
00530C04                 push    edx             ; lpProcName
00530C05                 push    eax             ; hModule
00530C06                 call    ds:GetProcAddress ; get the exported ordinal address, 
comparestringa is 25 for example
00530C0C                 jmp     short loc_530BA4 ; save the procname address for the 
import table in ebx
00530C0C start           endp

When you're finished, arm softice with a bpx getversion, launch commview (from the commview's original directory) at the third hit, do a bpx at 530b45 so you can check if the rebuilder works. If everything is fine, the rebuilder must generate valid api addresses until commview's last address at 4e3994.

It it works, congratulations, you've builded a fake import inside your dumped commview. 

When the rebuilder finish its work, it jumps to the commview's entry point 4de384.  

It will direct exit, because there is a crc check, we have to patch this code inside
the dumped commview :
004DE3B9                 call    sub_4524A0
004DE3BE                 mov     eax, [ebp+var_10]
004DE3C1                 call    sub_465118
004DE3C6                 cmp     eax, 6F200h
004DE3CB                 jz      short loc_4DE3D2 <- patch to jmp 4de3d2
004DE3CD                 call    sub_403BB4

Don't forget one thing, there is still an anti softice left. Reactivate the bpx createfilea do "d esp->4"; press F12 when it hits then invert the jz just after.

Launch again, it's now working and you're ready to continue the reversing of this crippled, time trial exe.

5) What's left to crack ?

Now the real work is finished, we can patch whatever we want inside. I will easily give you the patches, just because this section was not the main part of my essay, this will surely save you some work. To finish its agony, we dwelve with :

-Anti softice routine : typical one, just after the well known createfileA :

0046573E                 call    sub_406D0C (createfileA with softice driver as an argument)
00465743 crack5:
00465743                 cmp     eax, 0FFFFFFFFh is it loaded ?
00465746                 jz      short loc_465750 <- patch this to jump
00465748                 push    eax
00465749                 call    sub_406CEC
0046574E                 mov     bl, 1

-The time limit :You usually find those after a bpx to getlocaltime, and trace after.
004D8D5B                 call    sub_44EB74 ; this call contains a call to getlocaltime
004D8D60 loc_4D8D60:                             ; CODE XREF: sub_4D899C+386j
004D8D60                 mov     eax, ds:dword_4E051C
004D8D65                 cmp     byte ptr [eax], 0 ;is the trial finished ?
004D8D68                 jnz     short loc_4D8DB8 <- force this to jump
004D8D6A                 mov     eax, ds:dword_4E0378
another place :
004D8D60 loc_4D8D60:                             ; CODE XREF: sub_4D899C+386j
004D8D60                 mov     eax, ds:dword_4E051C
004D8D65                 cmp     byte ptr [eax], 0
004D8D68 crack4:                                 ; time limit, force to jump
004D8D68                 jmp     short loc_4D8DB8
and also :
00489688 crack6:                                 ; time trial fix patch to jump
00489688                 jmp     short loc_48968E
0048968A ; ---------------------------------------------------------------------------
0048968A                 mov     byte ptr [ebp-1], 1
0048968E loc_48968E:                             ; CODE XREF: sub_4894A0+72j
0048968E                                         ; sub_4894A0+7Cj ...
0048968E                 cmp     [ebp+var_1], 1
00489692                 jnz     short crack7    ; time trial fix
00489694                 mov     ds:byte_4E1C19, 1
0048969B crack7:                                 ; CODE XREF: sub_4894A0+1F2j
0048969B                 mov     eax, 120020h    ; time trial fix force this value and nop
004896A0                 nop
004896A1                 mov     ds:byte_4E1C1A, 1
another patches, otherwise random exits
004DA57C                 mov     eax, ds:dword_4E02EC
004DA581                 cmp     byte ptr [eax], 1
004DA584 crack9:
004DA584                 jmp     short loc_4DA5AB ;patch to jump
004DA586 ; ---------------------------------------------------------------------------
004DA586                 call    sub_4D03AC
004DA58B                 lea     ecx, [ebp-4]

004D8F3B loc_4D8F3B:                             ; CODE XREF: CODE:004D8F11j
004D8F3B                 call    sub_4894A0
004D8F40                 test    al, al
004D8F42 crack10:
004D8F42                 jmp     short loc_4D8F7D ;patch to jump
004D8F44 ; ---------------------------------------------------------------------------
004D8F44                 mov     eax, ds:dword_4E02EC
004D8F49                 cmp     byte ptr [eax], 1

call    sub_4894A0
004DA8D9                 test    al, al
004DA8DB crack11:                                ; patch to nop
004DA8DB                 nop
004DA8DC                 nop
004DA8DD                 call    sub_4D085C
004DA8E2                 retn

-half of the packets displayed : an easy one with ida, just find the reference to string :
0048B5A4                 push    offset loc_48BB1C
0048B5A9                 push    dword ptr fs:[eax]
0048B5AC                 mov     fs:[eax], esp
0048B5AF                 cmp     byte ptr [ebx+5Fh], 0
0048B5B3                 nop ; nop those so it never jumps to 48b5c2, you guessed why
0048B5B4                 nop
0048B5B5                 lea     edx, [ebp-14h]
0048B5B8                 mov     eax, [ebx+22h]
0048B5BB                 call    sub_48A7C0
0048B5C0                 jmp     short loc_48B5CF
0048B5C2 ; ---------------------------------------------------------------------------
0048B5C2                 lea     eax, [ebp-14h]
0048B5C5                 mov     edx, offset aDataThisEvalua ; "DATA:THIS EVALUATION VERSION 
                         DISPLAYS O"...
0048B5CA                 call    sub_403E08

you have two more places to do the same, find them and correct the *bug* .
-the annoying nag when you leave commview: I found it after a bpx to createwindowsexa, you 
have to press F12 a lot of times to find this routine :

00459718 loc_459718:                             ; CODE XREF: sub_45969C+6Cj
00459718                                         ; sub_45969C+70j
00459718                 mov     eax, [ebp+var_C]
0045971B                 mov     edx, [eax]
0045971D                 nop <- you have to nop this call to avoid the nag
0045971E                 nop
0045971F                 nop
00459720                 nop
00459721                 nop
00459722                 nop
00459723                 mov     [ebp-8], eax
00459726                 xor     eax, eax
00459728                 pop     edx
00459729                 pop     ecx
0045972A                 pop     ecx
0045972B                 mov     fs:[eax], edx
0045972E                 push    offset loc_459743
00459733 loc_459733:                             ; CODE XREF: CODE:00459741j
00459733                 mov     eax, [ebp+var_C]
00459736                 call    sub_403024
0045973B                 retn

Now you can enjoy your new portsniffer, auto rebuilded by itself, just like it always should be.

Final Notes

I need your feedback for this essay, so please write your comments after trying it at the msgboard :

You can join all the Fravia's forums at sandman's , where I had this idea :

Or on the Fravia msgboard, for intermediate and advanced ones :

Thanks to Eternal Bliss ,r!sc and SV for their preliminary work on that interesting target.


Ob Duh
I wont even bother explaining you that you should BUY this target program if you intend to use it for a longer period than the allowed one. Should you want to STEAL this software instead, you don't need to crack its protection scheme at all: you'll find it on most Warez sites, complete and already regged, farewell, don't come back.

You are deep inside Fravia's page of reverse engineering, choose your way out:

redhomepage redlinks redsearch_forms red+ORC redhow to protect redacademy database
redreality cracking redhow to search redjavascript wars
redtools redanonymity academy redcocktails redantismut CGI-scripts redmail_Fravia
redIs reverse engineering legal?