Manually Unpacking - ASPack v1.083
by Volatily July 1999


Manually Unpacking... Volatily's essay (with a little too much code, maybe... hope that next version of this will have more explanations and less code :-) is well worth reading and experimenting on your own.
Read and enjoy!

Author: Volatility              
                     Date: 07/01/99                
        Topic: Manually Unpacking - ASPack v1.083  
               Level: Beginner/Intermediate        


I'm sure you've heard, by now, about packed programs. 
If you haven't, it
will be a topic worth learning about, because more and
more newer 
applications are being packed.  This essay deals
specifically with ASPack
v1.08.03, but may provide information on unpacking
some of the other many
packers out there.  I haven't tested my methods on
other versions of 
ASPack, or other packers, so it may work!

It will be extremely useful to print this essay if
you're going to follow
it step by step.  It would be rather difficult to
follow if you're just
referring to it on your computer.  Some word wrapping
problems will occur
but you should still have no problems understanding


1. NuMega Soft-Ice (any version for windows)
2. uCF's ProcDump
3. ASPack v1.08.03


A Bit About Packed Programs:  Software authors pack
their programs mainly
for two reasons, first, a packer dramatically reduces
the program's file
size, saving hard drive space.  Second, packers can
make the job of a
reverser a tough one, since you can't get an accurate
disassembly of the
file.  The original program is "wrapped" inside the
code of the packer,
which hides the original code.  When you execute the
program, you're 
actually executing the packer's code first.  The
packer, in turn, unpacks
the original application into memory, so that it can
execute.  This is 
where we will stop execution of the program - the
point where our program
is unpacked in memory.  We can then "dump" the program
to disk, and after
a little PE header editing (not discussed in great
detail in this essay),
we will have a copy of the original unpacked program!

Instead of searching all over for a program that has
been packed with
ASPack v1.08.03, we can simplify things by packing our
own program!  I'm
going to choose one that you're familiar with -
Windows 95/98's 
Calculator (calc.exe)!

The first thing we must do, is pack the program (make
sure this is a copy
of calc.exe, not the original!).  Open calc.exe with
ASPack, and it will
start packing the program.  Once finished, you can
"Test It" if you wish,
then exit ASPack.

Now that our program is packed, let's load it into
Soft-Ice's Symbol
Loader (File, Open Module).  Now let's run it (Module,
Load).  Soft-Ice
doesn't break!!! Why?  Here is a small explanation
from Miz's excellent

Ooops...SIce loader doesn't stop at the entrypoint
like we asked it to.  
Hmmmm...Why is that?

Well the answer lies in the PE format! (Told you this
stuff was 

Lets take a look at it in ProcDump, via the 'PE Editor

First thing we spot is that the packer entry point
(PEP) is 0x00006046.

Lets look at the section containing the PEP:-
Well we can see it's the .text section and the
characteristics are 

What does this mean? Well, lets take alook at winnt.h
to see......

[Excerpt from WinNT.h]
// Section characteristics.
#define IMAGE_SCN_TYPE_NO_PAD 0x00000008 // Reserved.
#define IMAGE_SCN_CNT_CODE 0x00000020 // Section contains code.
#define IMAGE_SCN_CNT_INITIALIZED_DATA 0x00000040 //Section contains initialized data.
#define IMAGE_SCN_CNT_UNINITIALIZED_DATA 0x00000080 //Section contains uninitialized data.
#define IMAGE_SCN_LNK_OTHER 0x00000100 // Reserved.
#define IMAGE_SCN_LNK_INFO 0x00000200 // Section contains comments or some other type of information.
#define IMAGE_SCN_LNK_REMOVE 0x00000800 // Section contents will not become part of image.
#define IMAGE_SCN_LNK_COMDAT 0x00001000 // Section contents comdat.
#define IMAGE_SCN_NO_DEFER_SPEC_EXC 0x00004000 // Reset speculative exceptions handling 
						bits in the TLB entries for this section.
#define IMAGE_SCN_GPREL 0x00008000 // Section content can be accessed relative to GP
#define IMAGE_SCN_MEM_FARDATA 0x00008000
#define IMAGE_SCN_MEM_PURGEABLE 0x00020000
#define IMAGE_SCN_MEM_16BIT 0x00020000
#define IMAGE_SCN_MEM_LOCKED 0x00040000
#define IMAGE_SCN_MEM_PRELOAD 0x00080000
#define IMAGE_SCN_ALIGN_1BYTES 0x00100000 //
#define IMAGE_SCN_ALIGN_2BYTES 0x00200000 //
#define IMAGE_SCN_ALIGN_4BYTES 0x00300000 //
#define IMAGE_SCN_ALIGN_8BYTES 0x00400000 //
#define IMAGE_SCN_ALIGN_16BYTES 0x00500000 // Default alignment if no others are specified.
#define IMAGE_SCN_ALIGN_32BYTES 0x00600000 //
#define IMAGE_SCN_ALIGN_64BYTES 0x00700000 //
#define IMAGE_SCN_ALIGN_128BYTES 0x00800000 //
#define IMAGE_SCN_ALIGN_256BYTES 0x00900000 //
#define IMAGE_SCN_ALIGN_512BYTES 0x00A00000 //
#define IMAGE_SCN_ALIGN_1024BYTES 0x00B00000 //
#define IMAGE_SCN_ALIGN_2048BYTES 0x00C00000 //
#define IMAGE_SCN_ALIGN_4096BYTES 0x00D00000 //
#define IMAGE_SCN_ALIGN_8192BYTES 0x00E00000 //
#define IMAGE_SCN_LNK_NRELOC_OVFL 0x01000000 // Section contains extended relocations.
#define IMAGE_SCN_MEM_DISCARDABLE 0x02000000 // Section can be discarded.
#define IMAGE_SCN_MEM_NOT_CACHED 0x04000000 // Section is not cachable.
#define IMAGE_SCN_MEM_NOT_PAGED 0x08000000 // Section is not pageable.
#define IMAGE_SCN_MEM_SHARED 0x10000000 // Section is shareable.
#define IMAGE_SCN_MEM_EXECUTE 0x20000000 // Section is executable.
#define IMAGE_SCN_MEM_READ 0x40000000 // Section is readable.
#define IMAGE_SCN_MEM_WRITE 0x80000000 // Section is writeable.

From this we can see that our 0xC0000040 actually means:-

^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Read Write Initialized Data

Hmmm - but we know that SIce loader won't break on
entry unless we specify that
this section contains *CODE*, and we should also
specify that it is executable.

So (Using ProcDump) change the Section Characteristics
for the .text section to 0xE0000020.

^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^
Executable Read Write Contains Code

Does SIce loader break in now? Yes it does!

If you don't completely understand this, don't worry. 
You can read more
about PE information later.  What we need to know from
this info, is how
to make Soft-Ice break via Symbol Loader, to do this,
perform the 
following steps:

1. Run Procdump, and click on the "PE Editor" button.
2. Choose your packed calc.exe file.
3. Click on the "Sections" button.
4. Right click on the first line (.text) and choose
"Edit Section".
5. Change the "Section Characteristics" from C0000040
to E0000020.
6. Click "OK", and exit Procdump.

With these steps completed, open, and load the program
in Symbol Loader
again.  Now Soft-Ice breaks!

Now we're in the packer's code.  The key to getting to
the end of this
code, and the place we need to unpack the original
program, is by 
setting several BPX's to get through the loops.  If
you try to do this
manually, without setting breakpoints, it could take
hours (or days? I
never tried it).

Below is all the code from my Symbol Loader log file. 
I've commented on
where to set the breakpoints, and on important lines. 
My comments are
precedeed by "***".

NOTE: The address numbers may be different on your PC,
but the last three
will be the same (XXX:XXXXX712).

015F:01017000  PUSHAD
015F:01017001  CALL    01017006
015F:01017006  POP     EBP
015F:01017007  SUB     EBP,00444A0A
015F:0101700D  MOV     EBX,00444A04
015F:01017012  ADD     EBX,EBP
015F:01017014  SUB     EBX,[EBP+004450B1]
015F:0101701A  CMP     DWORD PTR [EBP+004450AC],00
015F:01017021  MOV     [EBP+00444EBB],EBX
015F:01017027  JNZ     01017544                 (NO JUMP)
015F:0101702D  LEA     EAX,[EBP+004450D1]
015F:01017033  PUSH    EAX
015F:01017034  CALL    [EBP+00445194]
015F:0101703A  MOV     [EBP+004450CD],EAX
015F:01017040  MOV     EDI,EAX
015F:01017042  LEA     EBX,[EBP+004450DE]
015F:01017048  PUSH    EBX
015F:01017049  PUSH    EAX
015F:0101704A  CALL    [EBP+00445190]
015F:01017050  MOV     [EBP+004450B9],EAX
015F:01017056  LEA     EBX,[EBP+004450EB]
015F:0101705C  PUSH    EBX
015F:0101705D  PUSH    EDI
015F:0101705E  CALL    [EBP+00445190]
015F:01017064  MOV     [EBP+004450BD],EAX
015F:0101706A  MOV     EAX,[EBP+00444EBB]
015F:01017070  MOV     [EBP+004450AC],EAX
015F:01017076  PUSH    04
015F:01017078  PUSH    00001000
015F:0101707D  PUSH    0000049A
015F:01017082  PUSH    00
015F:01017084  CALL    [EBP+004450B9]
015F:0101708A  MOV     [EBP+004450B5],EAX
015F:01017090  LEA     EBX,[EBP+00444ACF]
015F:01017096  PUSH    EAX
015F:01017097  PUSH    EBX
015F:01017098  CALL    01017565
015F:0101709D  MOV     ECX,EAX
015F:0101709F  LEA     EDI,[EBP+00444ACF]
015F:010170A5  MOV     ESI,[EBP+004450B5]
015F:010170AB  SAR     ECX,02
015F:010170AE  REPZ MOVSD
015F:010170B0  MOV     ECX,EAX
015F:010170B2  AND     ECX,03
015F:010170B5  REPZ MOVSB
015F:010170B7  MOV     EAX,[EBP+004450B5]
015F:010170BD  PUSH    00008000
015F:010170C2  PUSH    00
015F:010170C4  PUSH    EAX
015F:010170C5  CALL    [EBP+004450BD]
015F:010170CB  LEA     EAX,[EBP+00444C37]
015F:010170D1  PUSH    EAX
015F:010170D2  RET
015F:01017233  MOV     EBX,[EBP+00444ADF]
015F:01017239  OR      EBX,EBX
015F:0101723B  JZ      01017247                               (JUMP )
015F:01017247  LEA     ESI,[EBP+00444AF7]
015F:0101724D  CMP     DWORD PTR [ESI],00
015F:01017250  JZ      01017365                              (NO JUMP)
015F:01017256  LEA     EAX,[EBP+004450D1]
015F:0101725C  PUSH    EAX
015F:0101725D  CALL    [EBP+00445194]
015F:01017263  MOV     [EBP+004450CD],EAX
015F:01017269  MOV     EDI,EAX
015F:0101726B  LEA     EBX,[EBP+004450DE]
015F:01017271  PUSH    EBX
015F:01017272  PUSH    EAX
015F:01017273  CALL    [EBP+00445190]
015F:01017279  MOV     [EBP+004450B9],EAX
015F:0101727F  LEA     EBX,[EBP+004450EB]
015F:01017285  PUSH    EBX
015F:01017286  PUSH    EDI
015F:01017287  CALL    [EBP+00445190]
015F:0101728D  MOV     [EBP+004450BD],EAX
015F:01017293  LEA     ESI,[EBP+00444AF7]
015F:01017299  MOV     EAX,[ESI+04]
015F:0101729C  PUSH    04
015F:0101729E  PUSH    00001000
015F:010172A3  PUSH    EAX
015F:010172A4  PUSH    00
015F:010172A6  CALL    [EBP+004450B9]
015F:010172AC  MOV     [EBP+004450B5],EAX
015F:010172B2  PUSH    ESI
015F:010172B3  MOV     EBX,[ESI]
015F:010172B5  ADD     EBX,[EBP+004450AC]
015F:010172BB  PUSH    EAX
015F:010172BC  PUSH    EBX
015F:010172BD  CALL    01017565
015F:010172C2  CMP     EAX,[ESI+04]
015F:010172C5  JZ      010172D2                           (JUMP )
015F:010172D2  CMP     BYTE PTR [EBP+004450B0],00
015F:010172D9  JNZ     01017316                           (NO JUMP)
015F:010172DB  INC     BYTE PTR [EBP+004450B0]
015F:010172E1  PUSH    EAX
015F:010172E2  PUSH    ECX
015F:010172E3  PUSH    ESI
015F:010172E4  PUSH    EBX
015F:010172E5  MOV     ECX,EAX
015F:010172E7  SUB     ECX,06
015F:010172EA  MOV     ESI,[EBP+004450B5]
015F:010172F0  XOR     EBX,EBX
015F:010172F2  OR      ECX,ECX
015F:010172F4  JZ      01017312                           (NO JUMP)
015F:010172F6  JS      01017312                                (NO JUMP)
015F:010172F8  LODSB
015F:010172F9  CMP     AL,E8
015F:010172FB  JZ      01017305                                (NO JUMP)
015F:010172FD  CMP     AL,E9
015F:010172FF  JZ      01017305                                (NO JUMP)
015F:01017301  INC     EBX
015F:01017302  DEC     ECX
015F:01017303  JMP     010172F2                                (JUMP )
015F:010172F2  OR      ECX,ECX
015F:010172F4  JZ      01017312                                (NO JUMP)
015F:010172F6  JS      01017312                                (NO JUMP)
015F:010172F8  LODSB
015F:010172F9  CMP     AL,E8

*** Set BPX here to jump to next line (BPX
    Press F5

Break due to BPX #015F:01017312  (ET=8.40 milliseconds)
015F:01017312  POP     EBX
015F:01017313  POP     ESI
015F:01017314  POP     ECX
015F:01017315  POP     EAX
015F:01017316  MOV     ECX,EAX
015F:01017318  MOV     EDI,[ESI]
015F:0101731A  ADD     EDI,[EBP+004450AC]
015F:01017320  MOV     ESI,[EBP+004450B5]
015F:01017326  SAR     ECX,02
015F:01017329  REPZ MOVSD
015F:0101732B  MOV     ECX,EAX
015F:0101732D  AND     ECX,03
015F:01017330  REPZ MOVSB
015F:01017332  POP     ESI
015F:01017333  MOV     EAX,[EBP+004450B5]
015F:01017339  PUSH    00008000
015F:0101733E  PUSH    00
015F:01017340  PUSH    EAX
015F:01017341  CALL    [EBP+004450BD]
015F:01017347  ADD     ESI,08
015F:0101734A  CMP     DWORD PTR [ESI],00
015F:0101734D  JNZ     01017299                       (JUMP )

*** Set BPX here to jump to next line (BPX
    Press F5

Break due to BPX #015F:01017353  (ET=35.08
015F:01017353  MOV     EBX,[EBP+00444ADF]
015F:01017359  OR      EBX,EBX
015F:0101735B  JZ      01017365                                     (JUMP )
015F:01017365  MOV     EDX,[EBP+004450AC]
015F:0101736B  MOV     EAX,[EBP+00444ADB]
015F:01017371  SUB     EDX,EAX
015F:01017373  JZ      010173EE                                     (JUMP )
015F:010173EE  MOV     ESI,[EBP+00444AEB]
015F:010173F4  MOV     EDX,[EBP+004450AC]
015F:010173FA  ADD     ESI,EDX
015F:010173FC  MOV     EAX,[ESI+0C]
015F:010173FF  TEST    EAX,EAX
015F:01017401  JZ      01017544                                     (NO JUMP)
015F:01017407  ADD     EAX,EDX
015F:01017409  MOV     EBX,EAX
015F:0101740B  PUSH    EAX
015F:0101740C  CALL    [EBP+00445194]
015F:01017412  TEST    EAX,EAX
015F:01017414  JNZ     0101747D                                     (JUMP )
015F:0101747D  MOV     DWORD PTR [EBX],00000000
015F:01017483  MOV     [EBP+0044516E],EAX
015F:01017489  MOV     DWORD PTR [EBP+00445172],00000000
015F:01017493  MOV     EDX,[EBP+004450AC]
015F:01017499  MOV     EAX,[ESI]
015F:0101749B  TEST    EAX,EAX
015F:0101749D  JNZ     010174A2                       (JUMP )
015F:010174A2  ADD     EAX,EDX
015F:010174A4  ADD     EAX,[EBP+00445172]
015F:010174AA  MOV     EBX,[EAX]
015F:010174AC  MOV     EDI,[ESI+10]
015F:010174AF  ADD     EDI,EDX
015F:010174B1  ADD     EDI,[EBP+00445172]
015F:010174B7  TEST    EBX,EBX
015F:010174B9  JZ      0101752C                                     (NO JUMP)
015F:010174BB  TEST    EBX,80000000
015F:010174C1  JNZ     010174C7                                     (NO JUMP)
015F:010174C3  ADD     EBX,EDX
015F:010174C5  INC     EBX
015F:010174C6  INC     EBX
015F:010174C7  PUSH    EBX
015F:010174C8  AND     EBX,7FFFFFFF
015F:010174CE  PUSH    EBX
015F:010174CF  PUSH    DWORD PTR [EBP+0044516E]
015F:010174D5  CALL    [EBP+00445190]
015F:010174DB  TEST    EAX,EAX
015F:010174DD  POP     EBX
015F:010174DE  JNZ     0101751E                                     (JUMP )
015F:0101751E  MOV     [EDI],EAX
015F:01017520  ADD     DWORD PTR [EBP+00445172],04
015F:01017527  JMP     01017493                                     (JUMP )

*** Set BPX here to jump to next line (BPX 015F:0101752C)
    Press F5

Break due to BPX #015F:0101752C  (ET=33.17 milliseconds)
015F:0101752C  XOR     EAX,EAX
015F:0101752E  MOV     [ESI],EAX
015F:01017530  MOV     [ESI+0C],EAX
015F:01017533  MOV     [ESI+10],EAX
015F:01017536  ADD     ESI,14
015F:01017539  MOV     EDX,[EBP+004450AC]
015F:0101753F  JMP     010173FC                                     (JUMP )

*** Set BPX here to jump to next line (BPX 015F:01017544)
    Press F5

Break due to BPX #015F:01017544  (ET=2.62 milliseconds)
015F:01017544  MOV     EAX,[EBP+00444AEF]
015F:0101754A  PUSH    EAX
015F:0101754B  ADD     EAX,[EBP+004450AC]
015F:01017551  POP     EBX
015F:01017552  OR      EBX,EBX
015F:01017554  MOV     [ESP+1C],EAX
015F:01017558  POPAD
015F:01017559  JNZ     01017563                                     (JUMP )
015F:01017563  PUSH    EAX  *** Take note of the value
of EAX!
015F:01017564  RET          *** Stop here!!!

Lengthy code, but straight to the point!  We've set several breakpoints
as you can see from the above code, so we don't get stuck in the loops.

Make sure you took note of the value of EAX (should be 010119E0).

The final RET above, is the end of the packer code. 
In order to be able to dump our full program code, we need to put the
unpacking code in an infinite loop.  To do this, type the following:

a eip      (hit enter)
jmp eip    (hit enter)
(hit enter again)

Now, press F5 to leave Soft-Ice.  The program is now unpacked in memory,
due to the infinite loop we set.  We can now dump it, by performing the
following steps:

1. Run Procdump.
2. Find calc.exe in the list of "Tasks".
3. Right-click on the calc.exe task, and choose "Dump (Full)".
4. Save the program under a new filename.

You can now compare file sizes of the packed program, and the dumped 
program.  Quite a difference!

If you try to run the dumped program though, it won't work.  Why?
Remember the value of EAX you noted?  This is referred to as the OEP
(Original Entry Point).  Run Procdump again, and click on the "PE Editor"
button.  Open the dumped program.  We need to change the "Entry Point"
from 00017000 to our new entry point, which is OEP minus Image Base
(010119E0 - 01000000 = 000119E0).  When you've changed the Entry Point,
exit Procdump, and try to run the dumped program again.  It works!

NOTE: As I stated earlier, I'm not going into great
detail about PE
header functions, and editing.  You should study it
though to gain a
complete understanding of unpacking.

Congratulations, you've successfully unpacked a
program packed with 
ASPack v1.08.03!!!

If you have any questions, feel free to e-mail me at
GREETINGS (in no order of importance):

Eternal Bliss (for showing me the EASY way to get out of those damned loops!)
Miz           (for his EXCELLENT essay that got me interested in packing)
Reverser+       (For THE site that got me interesting in reversing)

Torn@do, Lucifer48, Jeff, BJanes, MisterZ-, +Sandman, Lord Soth, alpine.

Copyright (c) 1999 Volatility And The Immortal Descendants
All Rights Reserved

You'r deep inside reverser's pages of reverse engineering



redhomepage red links red anonymity red+ORC redstudents' essays redacademy database redbots wars
redantismut redtools redcocktails redjavascript wars redsearch_forms redmail_reverser
redIs reverse engineering illegal?