***** ***** by crUsAdEr ***** ****
TOOLS used :
IDA 4.15
Soft Ice on Win2k
LordPE
Revirgin (for unpacking only)
WinHex (for unpacking only)
Targets : ReGet Deluxe 3.0 beta (build 117) (but I think
any program protected with the same version of AsProtect will do)
Included :
asprotect.dll
1. Unpacking AsProtect
This is boring after a while,
here I summarise some steps you should take when unpacking AsProtected program
(please read Spl/\j's tutorial on commview, not much has changed
since!)
- Run the program
- Run WinHex and open the program memory space, search for
AsProtect signature byte "61 FF E0"
- If you are on win 98, run super bpm. (for win2k user, use
Solomon's trick of "bpx 80464C50" to prevent AsProtect from clearing your
bpm).
- Close the program, put a bpx on GetVersion and run the
program again, sice should break, press F12 and you should be in the
AsProtected code, trace with F8 and take note of where the results of this
GetVersion is stored in memory. AsProtect store this results and used it later
to emulate the API. Other emulated API are GetModuleHandleA,
GetCurrentProcess, GetCurrentProcessId and GetCommandLineA. So trace and watch
where they are stored. Write down these memory addresses. Tips : trace with
F8
- Do a bpm on the address of "61 FF E0" you found earlier
- Let the program runs and sice will break again at "popad ;
jmp eax " where eax is you OEP. Dump here.
- Run revirgin and let it resolve IAT (read the revirgin
manual on how to do this)
- There are a few missing APIs which are either emulated
(remember the address we wrote down earlier?) or redirected. You need to fix
these manually and they should be dealt with case by case. (again, read
Spl/\j's tutorial)
- Sometimes AsProtect dips inside the program code before hitting OEP to trick /tracex and set various flags, encrypt/decrypt some codes but these should be dealt with individually.
Phew, done with the boring part, now if you are interested in how AsProtect really works and willing to work on your own to learn the art of reverse engineering then read on. The next few sections aims to discuss how AsProtect decrypts the program, how APIs are really emulated, how API is mangled, how dippings are done etc... and of course how your bpm are cleared!
2. AsProtect library
Yep, you are right! AsProtect
has a dll that is used to perform all of its tasks of decrypting and loading the
target. This dll is decrypted at runtime so this section will discuss how to
obtain this dll from memory, rebuild it and use it to study AsProtect. Use IDA
to disassemble the program, you should be able to over come most of the
obfuscation code (grab IDA tutorials or read the IDA manual). My approach is
disassemble and debug bit by bit in parallel.
Trace with softice from the beginning of the protected program, you will soon be brought AsProtect code in the last section of the program, F8 a few step and then you will be in the first decryption loop :
0067B083 ; ---------------------------------------------------------------- 0067B083 0067B083 loc_67B083: ; CODE XREF: 0067B06Fp 0067B083 8A DD mov bl, ch 0067B085 5E pop esi ; esi := 67B074 0067B086 8A C3 mov al, bl 0067B088 81 C6 C2 07 00 00 add esi, 7C2h ; esi := 67B836 0067B08E 56 push esi 0067B08F 8A E2 mov ah, dl 0067B091 5B pop ebx ; ebx := 67B836 0067B092 68 B5 01 00 00 push 1B5h 0067B097 59 pop ecx ; ecx := 1B5 0067B097 ; Number of time loop perform 0067B097 ; or number of dwords to be decrypted 0067B098 0067B098 loop1: ; CODE XREF: 0067B154j 0067B098 FF 36 push dword ptr [esi] 0067B09A 66 B8 8B 7F mov ax, 7F8Bh 0067B09E 5A pop edx ; edx := [esi] 0067B09F 0F 89 0C 00 00 00 jns loc_67B0B1 0067B09F ; ---------------------------------------------------------------- 0067B0A5 0F db 0Fh ; <----useless code---->
0067B0B0 00 db 0 ; 0067B0B1 ; ---------------------------------------------------------------- 0067B0B1 0067B0B1 loc_67B0B1: ; CODE XREF: 0067B09Fj 0067B0B1 81 C2 51 CF 9C 42 add edx, 429CCF51h ; add edx 0067B0B7 66 BF 0A 05 mov di, 50Ah 0067B0BB 81 F2 B6 23 95 0D xor edx, 0D9523B6h ; xor edx 0067B0C1 80 CB 2D or bl, 2Dh 0067B0C4 81 EA B7 D8 25 0E sub edx, 0E25D8B7h ; sub edx 0067B0CA 68 B0 D5 A1 60 push 60A1D5B0h 0067B0CF E8 14 00 00 00 call sub_67B0E8 0067B0CF ; ---------------------------------------------------------------- 0067B0D4 DC db 0DCh ; _ <----useless code---->
0067B0E7 5B db 5Bh ; [ 0067B0E8 0067B0E8 ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ 0067B0E8 0067B0E8 0067B0E8 sub_67B0E8 proc near ; CODE XREF: 0067B0CFp 0067B0E8 66 BF A4 D9 mov di, 0D9A4h 0067B0EC 58 pop eax ; eax := 67B0D4 0067B0ED 5F pop edi 0067B0EE 89 16 mov [esi], edx ; store back edx into [esi] 0067B0F0 80 F7 27 xor bh, 27h 0067B0F3 81 EE 7D 99 CB 4F sub esi, 4FCB997Dh 0067B0F9 66 8B D9 mov bx, cx 0067B0FC 81 C6 79 99 CB 4F add esi, 4FCB9979h ; sub esi, 4 0067B102 66 B8 35 7B mov ax, 7B35h 0067B106 49 dec ecx ; decrease counter 0067B107 0F 85 22 00 00 00 jnz continue_decrypt 0067B10D 0F 8A 06 00 00 00 jp loc_67B119 0067B10D ; -------------------------------------------------------------- 0067B113 81 db 81h ; ü <----useless code---->
0067B118 74 db 74h ; t 0067B119 ; -------------------------------------------------------------- 0067B119 0067B119 loc_67B119: ; CODE XREF: sub_67B0E8+25j 0067B119 E9 48 00 00 00 ; 0067B190j 0067B119 jmp loc_67B166 0067B119 ; -------------------------------------------------------------- 0067B11E A5 db 0A5h ; Ñ <----useless code---->
0067B12E 15 db 15h ; 0067B12F ; -------------------------------------------------------------- 0067B12F 0067B12F continue_decrypt: ; CODE XREF: sub_67B0E8+1Fj 0067B12F E8 0D 00 00 00 call loc_67B141 0067B12F ; -------------------------------------------------------------- 0067B134 91 db 91h ; æ <----useless code---->
0067B140 85 db 85h ; à 0067B140 sub_67B0E8 endp 0067B140 0067B141 ; -------------------------------------------------------------- 0067B141 0067B141 loc_67B141: ; CODE XREF: sub_67B0E8+47p 0067B141 E9 0D 00 00 00 jmp loc_67B153 0067B141 ; -------------------------------------------------------------- 0067B146 01 db 1 ; <----useless code---->
0067B152 F5 db 0F5h ; ) 0067B153 ; -------------------------------------------------------------- 0067B153 0067B153 loc_67B153: ; CODE XREF: 0067B141j 0067B153 5F pop edi ; edi := 67D134 0067B154 E9 3F FF FF FF jmp loop1
Lots of obfuscation code but I list here once so that hopefully you will get accustomed to them. There are more to come!
I hope the dead listing with comments are good enough to understand, but as you can see AsProtect is decrypting something and that some thing happen to be the VERY next block of codes. Do trace through it once or twice and you will get the hang of it. This is important as it will help you to understand AsProtect structure better as you go on. As you can see, the key is to use IDA to disassemble at the right place and ignore obfuscation code. Also, just a personal opinion, comment like mad, I commented everything I see eventhouugh sometimes I don't know what they are, I simply rename those offset "some_shit", the next time you see "some_shit" you'll know that this variable has been accessed before and it helps....
Once you have understand how this loop works, bpx on the exit of the loop and you will soon see the next loop with the same algorithm but different key and size used to decrypt the block after itself. This decryption is repeated a few times, (I think 4) and then a block of data is copy to high memory and decrypt there (our dll). It is also quite interesting to watch how AsProtect search for its import; namely GetProcAddress, GetModuleHandleA, LoadLibraryA, VirtualAlloc and VirtualFree by scanning the export directory of kernel32.dll instead of using the pre-loaded import IAT.
Once, the dll is loaded into some high memory, I made a dump,
attach it to the end of the program, adjust the sections header so that the
virtual address is the same. At the first glance, it looks like just a data
block with some code on it but once I start tracing this code I see something
fishy. Here comes the OS loader :
(I remove the relocation codes as they
are too long to list here. Only Import loading and OEP calculation is
listed)
00A4A488 loc_A4A488: 00A4A488 mov esi, dword ptr ss:unk_442A61[ebp] ; esi = [A4A11D] 00A4A48E 8B 95 D8 30 44 00 mov edx, dword ptr ss:unk_4430D8[ebp] ; add image base 00A4A494 03 F2 add esi, edx ; esi now points to Import Directory 00A4A496 00A4A496 load_next_dl_import: 00A4A496 8B 46 0C mov eax, [esi+0Ch] ; get dll name offset 00A4A499 85 C0 test eax, eax 00A4A49B 0F 84 0A 01 00 00 jz finish_import_loading ; eax := [A4A121] 00A4A4A1 03 C2 add eax, edx ; add image base 00A4A4A3 8B D8 mov ebx, eax 00A4A4A5 50 push eax 00A4A4A6 FF 95 EC 31 44 00 call dword ptr ss:unk_4431EC[ebp] ; GetModuleHandleA 00A4A4AC 85 C0 test eax, eax 00A4A4AE 75 07 jnz short library_loaded 00A4A4B0 53 push ebx 00A4A4B1 FF 95 F0 31 44 00 call dword ptr ss:unk_4431F0[ebp] ; LoadLibraryA 00A4A4B7 00A4A4B7 library_loaded: 00A4A4B7 89 85 4D 29 44 00 mov dword ptr ss:unk_44294D[ebp], eax 00A4A4BD C7 85 51 29 44 00+ mov dword ptr ss:unk_442951[ebp], 0 ; initialise Import Counter 00A4A4C7 00A4A4C7 next_first_thunk_entry: 00A4A4C7 8B 95 D8 30 44 00 mov edx, dword ptr ss:unk_4430D8[ebp] ; get image base 00A4A4CD 8B 06 mov eax, [esi] ; check Original_First_Thunk 00A4A4CF 85 C0 test eax, eax 00A4A4D1 75 03 jnz short original_first_thunk_found ; 00A4A4D3 8B 46 10 mov eax, [esi+10h] ; get first thunk offset 00A4A4D6 00A4A4D6 original_first_thunk_found: ; CODE XREF: 00A4A4D1j 00A4A4D6 03 C2 add eax, edx ; add image base 00A4A4D8 03 85 51 29 44 00 add eax, dword ptr ss:unk_442951[ebp] ; add counter 00A4A4DE 8B 18 mov ebx, [eax] ; get Import ASCII 00A4A4E0 8B 7E 10 mov edi, [esi+10h] 00A4A4E3 03 FA add edi, edx ; edi => first thunk 00A4A4E5 03 BD 51 29 44 00 add edi, dword ptr ss:unk_442951[ebp] ; add counter 00A4A4EB 85 DB test ebx, ebx 00A4A4ED 0F 84 A2 00 00 00 jz dll_done 00A4A4F3 F7 C3 00 00 00 80 test ebx, 80000000h ; import by ordinal? 00A4A4F9 75 04 jnz short loc_A4A4FF 00A4A4FB 03 DA add ebx, edx ; add image base 00A4A4FD 43 inc ebx 00A4A4FE 43 inc ebx ; add 2 to point to API ASCII 00A4A4FF 00A4A4FF loc_A4A4FF: ; CODE XREF: 00A4A4F9j 00A4A4FF 53 push ebx 00A4A500 81 E3 FF FF FF 7F and ebx, 7FFFFFFFh 00A4A506 53 push ebx 00A4A507 FF B5 4D 29 44 00 push dword ptr ss:unk_44294D[ebp] ; modulehandle 00A4A50D FF 95 E8 31 44 00 call dword ptr ss:unk_4431E8[ebp] ; get Proc address 00A4A513 85 C0 test eax, eax 00A4A515 5B pop ebx 00A4A516 75 6F jnz short API_add_found 00A4A518 F7 C3 00 00 00 80 test ebx, 80000000h ; import by ordinal ? 00A4A51E 75 19 jnz short loc_A4A539 00A4A520 57 push edi 00A4A521 8B 46 0C mov eax, [esi+0Ch] 00A4A524 03 85 D8 30 44 00 add eax, dword ptr ss:unk_4430D8[ebp] 00A4A52A 50 push eax 00A4A52B 53 push ebx 00A4A52C 8D 85 53 31 44 00 lea eax, unk_443153[ebp] 00A4A532 50 push eax 00A4A533 57 push edi 00A4A534 E9 99 00 00 00 jmp loc_A4A5D2 00A4A539 ; ------------------------------------------------------------- 00A4A539 00A4A539 loc_A4A539: ; CODE XREF: 00A4A51Ej 00A4A539 81 E3 FF FF FF 7F and ebx, 7FFFFFFFh 00A4A53F 8B 85 DC 30 44 00 mov eax, dword ptr ss:unk_4430DC[ebp] 00A4A545 39 85 4D 29 44 00 cmp dword ptr ss:unk_44294D[ebp], eax 00A4A54B 75 24 jnz short loc_A4A571 00A4A54D 57 push edi 00A4A54E 8B D3 mov edx, ebx 00A4A550 4A dec edx 00A4A551 C1 E2 02 shl edx, 2 00A4A554 8B 9D 4D 29 44 00 mov ebx, dword ptr ss:unk_44294D[ebp] 00A4A55A 8B 7B 3C mov edi, [ebx+3Ch] 00A4A55D 8B 7C 3B 78 mov edi, [ebx+edi+78h] 00A4A561 03 5C 3B 1C add ebx, [ebx+edi+1Ch] 00A4A565 8B 04 13 mov eax, [ebx+edx] 00A4A568 03 85 4D 29 44 00 add eax, dword ptr ss:unk_44294D[ebp] 00A4A56E 5F pop edi 00A4A56F EB 16 jmp short API_add_found 00A4A571 ;-------------------------------------------------------------- 00A4A571 00A4A571 loc_A4A571: ; CODE XREF: 00A4A54Bj 00A4A571 57 push edi 00A4A572 8B 46 0C mov eax, [esi+0Ch] 00A4A575 03 85 D8 30 44 00 add eax, dword ptr ss:unk_4430D8[ebp] 00A4A57B 50 push eax 00A4A57C 53 push ebx 00A4A57D 8D 85 A4 31 44 00 lea eax, unk_4431A4[ebp] 00A4A583 50 push eax 00A4A584 57 push edi 00A4A585 EB 4B jmp short loc_A4A5D2 00A4A587 ; ----------------------------------------------------------------- 00A4A587 00A4A587 API_add_found: ; CODE XREF: 00A4A516j 00A4A587 89 07 ; 00A4A56Fj 00A4A587 mov [edi], eax ; update first thunk 00A4A589 83 85 51 29 44 00+ add dword ptr ss:unk_442951[ebp], 4 00A4A590 E9 32 FF FF FF jmp next_first_thunk_entry ; get image base 00A4A595 ; ------------------------------------------------------------------ 00A4A595 00A4A595 dll_done: ; CODE XREF: 00A4A4EDj 00A4A595 89 06 mov [esi], eax ; clear Import Directory Entry 00A4A597 89 46 0C mov [esi+0Ch], eax 00A4A59A 89 46 10 mov [esi+10h], eax 00A4A59D 83 C6 14 add esi, 14h ; next Import Directories Entry 00A4A5A0 8B 95 D8 30 44 00 mov edx, dword ptr ss:unk_4430D8[ebp] 00A4A5A6 E9 EB FE FF FF jmp load_next_dl_import ; get dll name offset 00A4A5AB ; ------------------------------------------------------------------ 00A4A5AB 00A4A5AB finish_import_loading: ; CODE XREF: 00A4A49Bj 00A4A5AB 8B 85 65 2A 44 00 mov eax, dword ptr ss:unk_442A65[ebp] ; eax := [A4A121] 00A4A5B1 50 push eax 00A4A5B2 03 85 D8 30 44 00 add eax, dword ptr ss:unk_4430D8[ebp] ; add image base 00A4A5B8 5B pop ebx 00A4A5B9 0B DB or ebx, ebx 00A4A5BB 89 85 11 2F 44 00 mov dword ptr ss:unk_442F11[ebp], eax ; update instruction at A4A5CC 00A4A5C1 61 popa 00A4A5C2 75 08 jnz short OEP_OK 00A4A5C4 B8 01 00 00 00 mov eax, 1 00A4A5C9 C2 0C 00 retn 0Ch 00A4A5CC ; ------------------------------------------------------------------ 00A4A5CC OEP_OK: ; CODE XREF: 00A4A5C2j 00A4A5CC 68 00 00 00 00 push 0 ; this will be changed to push OEP 00A4A5D1 C3 retn ; go to OEP of the Delphi prog 00A4A5D2 ; -------------------------------------------------------------------
I know it is long dead listing, but do read through it, at least the comments as I think I wrote sufficient comments for readers to have an idea on what is happening. I have removed most of the codes (the decompression and relocation codes). Basically, it decompresses the main block and then perform what seems to me a relocation of image file, then import loading and finally getting OEP to jump to it. Hence I suspect this was either a dll or exe file (packed with AsPack?) or something. Hence I decided to dump this image (before all this reloc and IAT loading is done), it was hard to build the file as the header is completely ripped off and I took some time before getting it right so that IDA will disassemble them. First I notice that it has 6 sections (most if not all Delphi app has 6 sections) and then I remember AsProtect likes Delphi very much! Thus I open some Delphi exe and ripped the header completely, paste into this dump, fix the section info, fix the reloc and import info. (If you are not familiar with PE header, read some excellent PE tutorials by Iczellion and others at krobar's site).
Finally, I got IDA to disassemble the file nicely and hence discover it was a console dll written in Delphi and IDA (great tool!! Really helpful here) actually can apply its FLIRT feature to detect lots of Delphi function and that saves me lots of time. I must say if IDA has not been able to disassemble the dll properly, this tutorial would not have been done so easily. here I attach the dll here so you can disassemble and study them yourself. You should also try to dump and rebuild on from any AsProtect program as a practice.
Yep, once you obtain the dll, you will realise that all of AsProtect mysteries are inside that dll... its seh clearing debug registers, its crc check, IAT mangling etc... Here come the fun!!!
3. AsProtect.dll seh tricks
Here is how a typical seh is set up in AsProtect and you will know that seh is used not less than 30 times in this dll. It used to stop newbies like me from tracing AsProtect code but not anymore once you understand what is going on. Before you read this, please read some essential information about seh (I suggest Jeremy Gordon's excellent paper on seh).
004106B2 E8 49 C6 FF FF call Clear_API_emu_code ; upper limit 004106B7 E8 25 00 00 00 call set_seh_3 004106BC 004106BC seh_3_handler: ; 004106BC 8B 44 24 0C mov eax, [esp+0Ch] ; get context to eax 004106C0 83 80 B8 00 00 00+ add dword ptr [eax+0B8h], 2 ; add context.eip by 2 004106C7 51 push ecx 004106C8 31 C9 xor ecx, ecx 004106CA 89 48 04 mov [eax+4], ecx ; clear debug register 0 004106CD 89 48 08 mov [eax+8], ecx ; clear debug register 1 004106D0 89 48 0C mov [eax+0Ch], ecx ; clear debug register 2 004106D3 89 48 10 mov [eax+10h], ecx ; clear debug register 3 004106D6 C7 40 18 55 01 00+ mov dword ptr [eax+18h], 155h ; context.dr7 := 155 004106DD 59 pop ecx 004106DE 31 C0 xor eax, eax ; exception handled, continue 004106E0 C3 retn 004106E0 set_seh_1 endp ; sp = 4 004106E1 004106E1 ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ 004106E1 004106E1 set_seh_3 proc near ; CODE XREF: set_seh_1+25p 004106E1 31 C0 xor eax, eax 004106E3 64 FF 30 push dword ptr fs:[eax] ; set up seh 3 004106E6 64 89 20 mov fs:[eax], esp 004106E9 31 00 xor [eax], eax ; cause seh 3 004106E9 ; this seh clear debug register 004106EB 64 8F 05 00 00 00+ pop large dword ptr fs:0 ; remove seh struc 004106F2 58 pop eax 004106F3 E8 CC 1F FF FF call @System@Randomize$qqrv ; System::Randomize(void)
The seh is set up in a slightly different way which makes it harder to detect but with IDA everything becomes very clear!
004106B7 call set_seh_3 ; this is equivalent to push handler and move eip to 4106E1 same as
; push 4106BC (our seh handler)
004106E1
xor eax,
eax
004106E3
push dword ptr
fs:[eax] ; set up seh
3
004106E6
mov fs:[eax],
esp
004106E9
xor [eax],
eax
; cause seh
3
004106E9
; this seh clear debug
register
004106EB
pop large dword ptr fs:0 ; remove seh
struc
004106F2
pop eax
Thus when we trace over 4106E9, the seh is
triggered and our context is retrieved to eax, where eip is adjusted by
increasing it by 2 to point to the next working instruction, also debug
registers are cleared the same way. (this is posted by R!sc before)
This is interesting indeed! For example when you are tracing and you are at 4106B7, if you trace into with F8 you will meet the faulty instruction at 4106E9 and be lost in kernel seh code! if you trace over with F10, sice will place a break point at the next instruction which happen to be the seh handler and then you will soon meet the "ret" at 4106E0 and again you will be lost in seh kernel code! Now that we know how this whole seh scheme works, we can trace anywhere we want, simply do a "r eip eip+2" at the faulty instruction and seh handler will be skipped altogether!
Analysing the dll is slightly harder as it is a long, full-blown dll with a hell lot of seh and Delphi bloated codes but IDA eases the jobs quite a bit. You should try to analyse this slowly, always trace over a call and guess what it does first before actually stepping inside it.
4. AsProtect.dll internal
OK, I am not going to discuss the whole dll here, that would take too long and is pointless to paste long Delphi codes. I will just roughly describe its structure. Here is the skeleton of the dll
00410C32 68 4C E7 40 00 push offset self_hash 00410C37 68 5C 0D 41 00 push offset Dips_DriveHash_Date_Registry_CodeDecrypt 00410C3C 68 90 02 41 00 push offset nothing_important ; notthing really important here 00410C3C ; just some file header checking 00410C41 68 44 FF 40 00 push offset complete_API_mangling 00410C46 68 1C F9 40 00 push offset Fully_decrypt_file ; decrypt the file fully, 00410C46 ; IAT is untouched.. virgin!!!!! 00410C46 ; import ASCII stripped but 00410C46 ; hint are still there 00410C4B 68 10 F3 40 00 push offset Decrypt_file_first_time 00410C50 68 2C 06 41 00 push offset emu_API_n_file_hash 00410C55 C3 retn
Yep, so AsProtect will execute the API_emulation routine and then on return, it will jump to the next routine Decrypt_file_first_time and then so on and so on. API emulation is pretty easy to understand, especially if you have unpack a few AsProtected programs. Also AsProtect use open the exe and hash the whole file to check for CRC. Also, you should read the thread by me, Mike and Dakien at Fravia's Board (crypto forum, "stream cipher??" and "Tutorial: finding encryption code") on encryption routines used. You will find that in fact all the main decryption routines are similar to that one throughout this dll with MD5 heavily used!
The third routine decrypt the exe fully and perform relocation on the code section if required. Here you will see how the mysterious "ret" at 401014 call (that appears in all AsProtect programs) is made, I guess to test if the code section is executable.
It should be noted that after the 3rd routine, we can actually dump the file and obtain a nice clean dump with IAT first thunk intact, import ASCII are stripped together with dll names but the hints are still there so we can actually rebuild the program from there!
Disassembling the API mangling routine we'll see exactly how decrypt import information, classify imports into different categories (6 if I am not wrong) and have different treatment for each of them. Again, you have unpacked AsProtect then you will know these routines or at least have an ideas of how Imports are treated differently by AsProtect. I will not post the full code here as the offset given above should be enough for you to find where the routines are.
00410033 A1 A4 49 41 00 mov eax, ds:Encrypted_data_offset 00410038 8B 55 F0 mov edx, [ebp-10h] 0041003B 89 42 04 mov [edx+4], eax 0041003E 8B 15 94 32 41 00 mov edx, ds:sign_13_import_data 00410044 8B 45 F0 mov eax, [ebp-10h] 00410047 E8 A4 D0 FF FF call Decrypt_n_Find ; eax points to mem_struc 00410047 ; mem_struc+4 : original data 00410047 ; mem_struc+8 : decrypted data 00410047 ; it also traverse the decrypted data 00410047 ; block to search for data block with 00410047 ; signature in edx 0041004C 8B D8 mov ebx, eax 0041004E 85 DB test ebx, ebx 00410050 74 1B jz short import_data_not_found 00410052 8B 43 04 mov eax, [ebx+4] 00410055 E8 3A 25 FF FF call @System@@GetMem$qqrv ; size in eax 0041005A 89 45 FC mov [ebp-4], eax ; [ebp-4] points to import data
The call at 410047 decrypt a block data in the exe containing all the information about the protected program, like import data, dips to be performed, various hash results, decryption keys and assign each of these data with a signature tag. In this case the signature tag is named "sign_13_import_data" by me. The procedure search for this signature in edx and output eax pointing to the desire