|
Reversing Packed Targets
An Excersize in reversing for reversing's sake
|
Packers
|
19 May 1998
|
by
The RudeBoy [PC]
|
|
|
Courtesy of Fravia's page of
reverse engineering
|
|
fra_00xx 980519 RudeBoy 0100 PU PC
|
Simple, yet interesting little essay about basic DOS-type unpacking skills.
|
|
|
There is a crack, a crack in everything
That's how the light gets in
| |
Rating
|
( )Beginner (X)Intermediate ( )Advanced ( )Expert
|
|
An essay discussing simple .com file packing and unpacking
Reversing Packed Targets
An Excersize in reversing for reversing's sake
Written by
The RudeBoy [PC]
This essay is meant to explain .com file packing and unpacking.
Not much else to say...
TRacer 1.98
IDA 3.7x
C Compiler (optional)
Hex Editor (optional)
PKLite
rb15fcrk.com - f's crack for ReBirth 1.5
Not Important
A friend of mine downloaded this crack off the web so that he could better evaluate
ReBirth. He sent it to me as well, and when I ran it I noticed that it had a "nag".
In order to run the patch, you had to hit the "Page Up" key. I decided that I would
remove the nag from this program.
To do this, i started up IDA and loaded the .com file. What I saw was interesting.
The program started off with a jmp, followed by a bunch of data that seemed to make
no sense. Generally this is a good sign that the file is packed. I now had a few
options: i could try a generic unpacker (and learn nothing in the process), i could
use TR or debug to unpack the prog (and learn nothing), or, i could reverse the
unpacking routine and write my own unpacker for this kind of file. I decided to go
for the third option.
To reverse the unpacking routine, I followed the jump at the entry point. The first
thing it does is check the DOS version, then jumps to the next part of the code regardless
of what version of DOS is running. This is where we want to start paying attention:
loc_0_3576:
mov bx, 10h ;
add bx, 0F0h ; 10h + F0h = 100h*
push bx
mov al, 0AAh ; Encryption key into al
add al, 7 ; change the key by adding 7
push cx
mov cx, 3465h ; # of bytes to decrypt into cx
loc_0_3586:
jmp loc_0_358A ; jmp to decryption loop
; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ? db 0EAh ; ?; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ?
loc_0_358A:
xor cs:[bx], al ; xor the byte at cs:[bx] with our encryption key
push si ; random code
mov si, 64h ; ??
sub si, 27DBh ; ??
pop bp ; ??
inc al ; increment the encryption key
inc bx ; look at the next byte in the program
loop loc_0_3586 ; loop until all bytes have been processed
* 100h is the starting location in memory of a .com file
So this code is pretty simple, get the encryption key, xor a byte by it, increment
the encryption key, and use it tdecryptpt the next byte in the file.
If thencryptionon routine ended here there would be a problem. When the program is
packed, The first 3 bytes are changed to a jmp to this section of code. Xor'ing this
jump by the encryption key will still leave us with 3 odd bytes at the start of the file.
So we go to the next section of the code:
mov bx, 100h
mov word ptr [bx], 0F0B8h
mov byte ptr [bx+2], 80h
Simple enough, the packer stores the first 3 bytes directly in the decryption routine.
Now, to write our own unpacker for these files. I used C to do this, but you can use
whatever language is comfortable to you. You can take at a look at the source to my
unpacker here.
Now, on to removing that nag...
Wait, this file is packed again...this time with PKLite. Reversing PKLite is beyond
the scope of this essay, but PKLite has an option built into it to decompress packed
files. Just run pklite -x [filename] and the file is now unpacked.
Again, on to removing the nag...but wait, the file is packed yet again...
This time the file is compressed with the same packer used the first time, so, if you
wrote your unpacker properly you can make short work of this final layer of packing.
Now time to *finally* remove the nag. IDA does not produce a very usable listing for
this prog, so fire up TR, and step through this prog. You will find a few sections
of code dedicated to printing characters and strings to the screen, then a few
memory allocation calls then:
mov ds, cs:word_0_2B9 ; setting up a far call
push ds ;
pop es ;
assume es:seg000 ;
call dword ptr cs:unk_0_2B7 ; NagUser();
Trace into the NagUser() function and here is what you will see:
or ax, ax ;Test value in ax
jz loc_0_BA4 ;jump
clc
retf
loc_0_BA4:
xor ax, ax
int 16h ; KEYBOARD - READ CHAR FROM BUFFER, WAIT IF EMPTY
; Return: AH = scan code, AL = character
cmp ah, 49h ; compare the key pressed to "Page Up"
jz loc_0_BAF ; jump if equal
Bingo! That's the code we're looking for. In order to kill the nag, we have to do
two things. First, stop the int 16h, because it waits for a keypress. Second, force
the jz after the compare to always jump. There are many ways to do these things, I
will let you figure them out for yourself.
/*********************************************************************************
funp.cpp
Unpacker for "f" encrypted .com files
This code is not very neat...i threw it together pretty quickly, so please
excuse the sloppyness.
*********************************************************************************/
#include
#include
void main (int argc, char *argv[]) {
FILE *packed, *unpacked;
int codeloc, count, i, curbyte;
char key;
printf("f-Unpacker by The RudeBoy [PC]\n");
if (argc <3)
{
printf("USAGE: funp [packed file] [unpacked file]\n");
exit(-1);
}
// Open the files
if((packed = fopen(argv[1], "rb")) == NULL){
printf("Error: cannot locate %s\n", argv[1]);
exit(-1);
}
if ((unpacked = fopen(argv[2], "wb")) == NULL)
{
printf("Error: cannot open %s\n", argv[2]);
exit(-1);
}
//Seek in one byte, to get the location of the decryption code
"if(fseek(packed,1.class" tppabs="http://fravia.org/if(fseek(packed,1.class" , SEEK_SET)){
printf("Error in %s: cannot seek to 0x1\n", argv[1]);
exit(-1);
}
codeloc = 0;
//Get the location of the decryption code (relative to the current location in the file)
if( fread(&codeloc, sizeof(short), 1, packed) != 1)
{
printf("Error in %s: could not read data\n", argv[1]);
exit(-1);
}
codeloc += 3; //So we have the total length from the start of the file to the code
if(fseek(packed,codeloc + 0x17 , SEEK_SET)){
printf("Error in %s: cannot seek to 0x%X\n", argv[1], codeloc);
exit(-1);
}
//Get the initial decryption key
if( fread(&key, sizeof(char), 1, packed) != 1)
{
printf("Error in %s: could not read data\n", argv[1]);
exit(-1);
}
//add 7
key += 7;
count = 0;
if(fseek(packed,codeloc + 0x1C , SEEK_SET)){
printf("Error in %s: cannot seek to 0x%X\n", argv[1], codeloc);
exit(-1);
}
//Get the number of encrypted bytes
if( fread(&count, sizeof(short), 1, packed) != 1)
{
printf("Error in %s: could not read data\n", argv[1]);
exit(-1);
}
//Go to the beginning of the file to start the decryption
fseek(packed,0 , SEEK_SET);
//Decryption loop
for(i = 1;i<=count;i++)
{
//Get the next byte from the packed file
curbyte = fgetc(packed);
//xor it by the key
curbyte ^= key;
//and write it to the decrypted file
fputc( curbyte, unpacked);
//increment the key, or make it 0 if it equals 0xFF
if(key == 0xFF)
key = 0;
else
key++;
}
//Go to the location in the packed file where the "real" first 3 bytes are found
if(fseek(packed,codeloc + 0x38 , SEEK_SET)){
printf("Error in %s: cannot seek to 0x%X\n", argv[1], codeloc);
exit(-1);
}
fseek(unpacked,0 , SEEK_SET);
//Get each of those bytes and write them to the unpacked file
curbyte = fgetc(packed);
fputc( curbyte, unpacked);
curbyte = fgetc(packed);
fputc( curbyte, unpacked);
fseek(packed,3 , SEEK_CUR);
curbyte = fgetc(packed);
fputc( curbyte, unpacked);
//close the files
fclose(packed);
fclose(unpacked);
printf("Done.\n");
}
//----------------------------------------------------------------------------------
Ob duh doesn't apply, it's reversing for reversing sake , here
You are deep inside fravia's page of reverse engineering,
choose your way out:
Back to the packers' section
homepage
links
search_forms
+ORC
students' essays
academy database
reality cracking
how to search
javascript wars
tools
anonymity academy
cocktails
antismut CGI-scripts
mail_fravia+
Is reverse engineering legal?