2010
03.04

Coding Unpackers for Fun and Profit: TitanEngine Training by
Tomislav Pericin and Nicolas Brulez

Learn how to analyze, unpack and code unpackers for software packers and protectors. Attendees will receive hands-on experience working with the ReversingLabs TitanEngine framework, designed for unpacker creation.

Instructors: Tomislav Pericin and Nicolas Brulez
Dates: 6-8 July 2010
Availability: 10 Seats

Day 1: Static file analysis and static unpacker coding

The focus of the first day is manual file unpacking and static file analysis. We go into deep format analysis to create both simple and more complex static unpackers.

We will focus on real-world protections you are likely to encounter on a day-to-day basis.

Day 2: Dynamic file analysis and dynamic unpacker coding

The second day will cover manual file unpacking and dynamic file analysis. We go into deep format analysis for creating simple and more complex dynamic unpackers. Special attention will be given to dynamic unpacker coding layout and the benefits of using TitanEngine to minimize the time it takes to create an unpacker.

Our focus will be on real world packers you are likely to encounter on a day-to-day basis. These packers top the charts in legitimate software compression, but are often used as malware envelopes.

Day 3: Advanced file analysis and coding complex unpackers

On day 3, we will cover the manual unpacking of complex file packing and protection systems. Special attention will be given to methods used to harden against format reverse engineering and prevent unpacking. We will describe common protection techniques utilized by both legitimate software protectors and those specifically designed for use in malware. We will then use information to show coding techniques needed for such complex dynamic unpackers and ways to counter all the tricks used to harden detection, analysis and unpacking.

Our focus will be on the real-world protections you are likely to encounter on a day-to-day basis.

More info here...

VN:F [1.8.4_1055]
Rating: +3 (from 3 votes)
  • Share/Bookmark
2010
03.01

Ask a developer Monday

This is the second "Ask a developer Monday," in which we answer the most common question we've received recently. The current No. 1 question is: "Why is the entry point after unpacking located in the section named UPX0?"

This is a more complex question than you might think, because it requires understanding the memory models used by software packers, which makes it a perfect question for "Ask a developer Monday"! To answer it we must explore the memory models used, and the possible results that an unpacker could produce.

The first memory model is the one  typically used by software packers. Its main characteristic is a greatly reduced number of portable executable sections - lowered to only two or three, depending on the packer solution itself. With this model, all sections in the file before packing are merged into a single section that is always the first section in the packed file. Most commonly this first section in the packed file holds no data and it is used just as a slot to reserve memory which will be filled after the packer stub finishes the decompression. The virtual size of this first packed file section is equal to the SizeOfImage of the file before it was packed. This gives the packers a powerful option for compressing all code and data in one pass as a single compressed data stream. It also speeds up the time needed to decompress the entire packed content and lowers the compressed file's size because it needs only a single decompression dictionary. The compressed data is commonly stored in the packer section which is either in the second or the third section of the packed file. Since resources must be aligned to SectionAlignment, they commonly get their own section - usually the last section of the file packed  using this memory model.

Although the first model brings faster decompression and smaller files to the table, it has the disadvantage of slightly increasing the memory usage for the packed file. Since memory usage is only increased by the size of the compressed content if that content is displaced from its original location and moved to the packer section, the problem can be avoided by  using a packer that uses a memory model in which the compressed data is stored at its original location. This kind of packer individually compresses the portable executable sections and stores the compressed data inside the same section. With this model, the packer preserves the  section layout the file had prior to packing. Commonly, only one section is added to the original file layout, and that section only contains the packer stub. Compression here is achieved by reducing the physical size of the individual sections. There is a hybrid approach which combines these two memory models, but there isn't a software compression solution that uses it.

Now how does this apply to dynamic unpackers? Since a dynamic unpacker executes the file until it reaches its original entry point and performs a memory dump once that point is reached, it has no impact whatsoever on the memory model used by the packer. That means that the file section layout before and after unpacking will remain the same, with exception of the sections added to the file by the unpacker. These new sections contain the import and relocation data, while the old sections hold the decompressed code, resources and data. There is no way to restore the memory model to its original layout if that kind of data isn't preserved in the packer stub. Since that data isn't commonly preserved by any software packers, a dynamic unpacker can't restore the original memory model layout. And since UPX uses the first memory model as its entry point after the file is unpacked, it will be moved from the section UPX1 to UPX0.  The thing to remember is that section names are not important, what is important is that the data and the code itself are decompressed and this is achieved by the dynamic unpackers.

  • Examples for the fist memory model are: UPX, FSG, RLPack, etc.
  • Examples for the second memory model are: PackMan, ASPack, AlexProtector, etc.

That is it for this weeks Q&A, until next time...

VN:F [1.8.4_1055]
Rating: +2 (from 2 votes)
  • Share/Bookmark
2010
02.23

Today we finish our AlexProtector unpacker whose creation was started last week with file format analysis. When the analysis was conducted we were intending to create a dynamic unpacker for this protection but since it is just as "easy" to create a static one we went for that option. That exact idea is the reason why we are a day late with our blog and we are glad we are since we noticed some bugs in the Importer module that were resolved. But we did more then just bug fixing we did some tweaks to existing function for even better import elimination protection support.

Since we already did the analysis part we will go straight to coding an unpacker and describe everything that needs to be done to complete it. We are going to start by reserving enough space for section data which needs to be decompressed. This action can be a complex task if we try to manually re-size the file and move all data to their appropriate location. However the TitanEngine comes with two functions which can do the hard work for us even though they are not meant to do this exact task. But before we go into that lets explain what is really needed. The problem lays in the fact that some sections are compressed by aPLib which means that the protected file size is most likely smaller then the original one. To accommodate the need for extra space in which this decompressed data will be written we have to re-size the sections so they can hold this physical data. How much space is needed? That part is simple only because AlexProtector stores compressed section data inside their original sections. Which means that if the first PE section is compressed its compressed data will still be in the first section. After decompression that data will still need to be written there, but there its going to be a lack of physical space because the size of compressed data is up to ~70% smaller then the original data size. Because the original data was still in the section which we need to decompress we know that the maximum physical size of that data is equal to the virtual size of that section. And that means that we need to re-size all section so that their physical size is equal to rounded up virtual size. Doing this is equal to dumping the memory of the running process with the TitanEngine's DumpProcess function but since we don't want to start the process while making a static unpacker we will do this differently. We will use StaticFileLoad to simulate the file load which is equal to running the process after which we will dump that memory to disk with DumpMemory. But that doesn't complete our task since dumped image needs to have its PE section values corrected so that the file is a valid PE image. This is done by setting the raw size of each section to rounded up virtual one and by setting the raw offset of each section to its virtual offset. Once that is done all virtual locations in the file are equal to their physical counterparts, and so the virtual address 0x1000 is on the 0x1000 byte from the start of the file.

Once we have the file re-sized to near to original size we can start decompressing data. However we don't want to be guessing which section is compressed and which isn't so we will directly read the protector data to reverse the compression. To find out where this data is stored we monitor calls to aPLib decompression code and we find a call to it from the second protection layer which is exactly what we need:

;Layer base: 0x00220000
;--------------------------------------------------------------------
/*2202D1*/  LEA ESI,DWORD PTR SS:[EBP+4023C1]  ;Internal section data
/*2202D7*/  MOV EAX,DWORD PTR DS:[ESI+4]
/*2202DA*/  PUSH 4
/*2202DC*/  PUSH 1000
/*2202E1*/  PUSH EAX
... Junk removed with DeJunk ...
/*220387*/  PUSH 0
/*220389*/  CALL NEAR DWORD PTR SS:[EBP+402411] ;VirtualAlloc
/*22038F*/  MOV DWORD PTR SS:[EBP+40239D],EAX
/*220395*/  PUSH ESI
/*220396*/  MOV EBX,DWORD PTR DS:[ESI]
/*220398*/  ADD EBX,DWORD PTR SS:[EBP+402399]
/*22039E*/  PUSH EAX
... Junk removed with DeJunk ...
/*220444*/  PUSH EBX
/*220445*/  LEA ECX,DWORD PTR SS:[EBP+401108]
/*22044B*/  CALL NEAR ECX                       ;aPLib decompress
/*22044D*/  ADD ESP,8
/*220450*/  MOV ECX,EAX
/*220452*/  MOV EDI,DWORD PTR DS:[ESI]
... Junk removed with DeJunk ...
/*2204F9*/  ADD EDI,DWORD PTR SS:[EBP+402399]
/*2204FF*/  MOV ESI,DWORD PTR SS:[EBP+40239D]
/*220505*/  REP MOVS BYTE PTR ES:[EDI],BYTE PTR DS:[ESI]
/*220507*/  POP ESI
/*220508*/  MOV EAX,DWORD PTR SS:[EBP+40239D]
/*22050E*/  PUSH 8000
/*220513*/  PUSH 0
/*220515*/  PUSH EAX
/*220516*/  CALL NEAR DWORD PTR SS:[EBP+402415] ;VirtualFree
... Junk removed with DeJunk ...
/*2205C1*/  ADD ESI,8
/*2205C4*/  CMP DWORD PTR DS:[ESI],0
/*2205C7*/  JNZ 002202D7
 

As we can see from this code snippet protector is reading data located at EBP+0x004023c1. Here both numbers are constants with EBP being calculated at the start of the protector code and referred to as "protector delta". It is determined here:

  PUSHAD
  CALL L002
L002:
  POP EBP
  SUB EBP,00401006
 

Most protections use this kind of coding which is popularly called offset independent coding. By using this coding method protection authors don't need to know the exact offset on which their protection will be written on. Now since we are only coding an unpacker for this one protection version we will use the same internal constants that the protector uses. So, at the location Delta+0x004023c1 we will find and read the internal AlexProtector data about compressed sections. That data is a two dimensional array with the following structure:

typedef struct AlexProt_SectionData{
	DWORD SectionVirtualOffset;
	DWORD SectionVirtualSize;
}AlexProt_SectionData, *PAlexProt_SectionData;
 

After we decompress that data all the sections are restored to their original state. With a small exception of the code section which still need original entry point and import elimination protection removing. First thing out of that two that we will fix is the import protection because removing that protection will correct the code section data.

When we were analyzing the file format we have determined the internal format that AlexProtector uses for storing import data. Now that we are creating an unpacker we need that data so we need to determine where it is stored and if it is encrypted at any point. With some tracing we determine that this code does the decryption of the compressed import data.

;Layer base: 0x00220000
;--------------------------------------------------------------------
/*22080F*/  LEA EDI,DWORD PTR SS:[EBP+402531] ;Pointer to import data
/*220815*/  ADD EDI,DWORD PTR SS:[EBP+4023B5]
/*22081B*/  XOR EDX,EDX
/*22081D*/  MOV ECX,100
/*220822*/  DIV ECX
/*220824*/  MOV EBX,EDX
/*220826*/  DIV ECX
/*220828*/  ADD EBX,EDX
/*22082A*/  DIV ECX
/*22082C*/  ADD EBX,EDX
/*22082E*/  DIV ECX
/*220830*/  ADD EBX,EDX
/*220832*/  POP ECX
/*220833*/  MOV EAX,EBX
/*220835*/  MOV ECX,DWORD PTR SS:[EBP+4023B9] ;Size of the import data
/*22083B*/  XOR BYTE PTR DS:[EDI],AL          ;Decryption loop
/*22083D*/  INC EDI
/*22083E*/  DEC ECX
/*22083F*/  JNZ 0022083B
 

Internal import data is compressed and then encrypted. To be able to use it we must reverse this process by decrypting the memory content and then decompressing it. For decryption part we need the decryption key and the decryption algorithm. Since the algorithm is known, and it is a simple XOR one, we must determine the key for decryption before continuing. Here is where the protection author made a mistake because he used a decryption key which is CRC hash of the selected memory part. Now this is a conditional "mistake" since it does prevent us from using software breakpoints in some areas but it makes the decryption key calculation unnecessary because that key can't change for this particular protector version. Since the EAX value at the start of this code snippet is 0xD0340178 we can calculate that decryption key is 0x7D.

Once this memory is decrypted it can be decompressed and then processed in order to correct both the import table and the code section. If we remember our analysis from the last time, here is how internal import data is packed:

typedef struct ALEX_IAT_DLL{
       BYTE DLLSignature; //0xC3
       BYTE DLLNameLength;
       // DLLName[DLLNameLength] followed by 0x00
}ALEX_IAT_DLL, *PALEX_IAT_DLL;
 
typedef struct ALEX_IAT_APIENTRY{
       // 0xC4 indicates Ordinal import
       BYTE APINameLength;
       // APIName[APINameLength] followed by 0x00
       BYTE RedirectionNumber; //Number of redirections
       DWORD RedirectionAddress[RedirectionNumber];
}ALEX_IAT_APIENTRY, *PALEX_IAT_APIENTRY;

Above is the pseudo C code that describes the internal import data structure. Here, redirection data refers to addresses in code section which need to be corrected so that they point to correct API pointers. That is why in a way we can observe this table as a sort of a relocation table because the data which needs to be written at that location corresponds to random location in memory where import redirection is allocated on. Since that memory allocation is outside the PE image file memory we call that kind of import protection import eliminations. To repair it we need to estimate the location where we will reconstruct the import table and create a table aligned to that location on the fly. There are two ways to do this and we decided to go with the more complex one. Its logic goes like this:

  • Initialize importer and say that import table will be moved
  • Create a relative virtual import table with no point of reference
  • Relocate virtual import table to reserved spot
  • Write the new import table

Now the relative virtual import table must be a confusing term but it can be simply described as an import table whose references start with zero and increment by four. That would look something like this:

  1. New DLL: Kernel32.dll
  2. TrunkValue: 0x00000000; GetProcAddress (e.g.)
  3. TrunkValue: 0x00000004; LoadLibraryA (e.g.)
  4. TrunkValue: 0x00000008; FreeLibrary (e.g.); Remember its +8 for the last item
  5. New DLL: User32.dll
  6. TrunkValue: 0x00000010; MessageBoxA (e.g.)
  7. TrunkValue: 0x00000014; MessageBoxW (e.g.)

Once we compile this kind of table we simply relocate it by adding a correct value to their trunk relative addresses. That value is virtual address of the section we will add to the file in order to store the import table there. At the time of unpacking that address will be a SectionAlignment aligned value of NtSizeOfImage. We could have build our table like this from the start with no need for relocating it but we wanted to show a more general approach. Since that is done we just need to write correct pointers to redirection addresses found in AlexProtector internal data so that the code section and the new import table are connected.

With imports sorted we move on the last item on our list, the entry point protection. It is processed by this code here:

;Layer base: 0x00220000
;--------------------------------------------------------------------
/*220D0B*/  LEA EBX,DWORD PTR SS:[EBP+402531] ;Pointer to EP data
... Junk removed with DeJunk ...
/*220DB6*/  ADD EBX,DWORD PTR SS:[EBP+4023B5]
/*220DBC*/  ADD EBX,DWORD PTR SS:[EBP+4023B9] ;Pointer correction
... Junk removed with DeJunk ...
/*220E67*/  MOV ECX,DWORD PTR SS:[EBP+402395]
... Junk removed with DeJunk ...
/*220F12*/  MOV EAX,DWORD PTR SS:[EBP+4023AD]
/*220F18*/  PUSH EAX
/*220F19*/  PUSH EBX
/*220F1A*/  LEA EDX,DWORD PTR SS:[EBP+401108]
/*220F20*/  CALL NEAR EDX                     ;aPLib
... Junk removed with DeJunk ...
/*220FC7*/  ADD ESP,8
/*220FCA*/  MOV EAX,DWORD PTR SS:[EBP+4023AD]
/*220FD0*/  MOV EBX,DWORD PTR SS:[EBP+402391]
... Junk removed with DeJunk ...
/*22107B*/  MOV ESI,DWORD PTR SS:[EBP+402385] ;EP resumes here
/*221081*/  ADD EAX,EBX
/*221083*/  MOV BYTE PTR DS:[EAX],0E9         ;Write OEP jump
/*221086*/  INC EAX
/*221087*/  MOV ECX,ESI
... Junk removed with DeJunk ...
/*22112E*/  SUB ECX,EAX
/*221130*/  SUB ECX,4
/*221133*/  MOV DWORD PTR DS:[EAX],ECX
... Junk removed with DeJunk ...
/*2211DA*/  MOV EAX,DWORD PTR SS:[EBP+4023AD]
/*2211E0*/  MOV DWORD PTR SS:[ESP+1C],EAX
/*2211E4*/  POPAD
/*2211E5*/  JMP NEAR EAX                      ;Jump to stolen EP
 

As we can see the stolen entry point data is decompressed and a new jump to the first non stolen instruction is written. To reverse this we must decompress the buffer with EP jump correction after which we need to write it to a new section. It is possible to extract the correct the entry point to its original state but that would mean that we would have to disassemble and analyze the decompressed buffer which contains those original functions riddled with junk code. There is a high margin of error if this is performed and therefore keeping the junk is the simplest option.

Writing an unpacker for AlexProtector should be a nice exercise for any reverser. We have shown in detail how it can be done statically. If you have any questions about any of the steps in writing this unpacker feel free to contact us. Until next week....

Samples and Protector / RL!deAlexProtector
(package contains protector binary, unpacker with source and the samples used)

VN:F [1.8.4_1055]
Rating: +2 (from 2 votes)
  • Share/Bookmark
2010
02.18

ReversingLabs are giving a presentation on Barcelona BlackHat in April. Here is the short description of our presentation:

"Exploiting archive formats can lead to steganographic data hiding and to processing errors with serious forensic consequences. These formats are very interesting as they are commonly found on every PC, Apple or Linux machine, and it is popularly believed that they are well understood and trusted. Can exploits ever be present in file formats that have been in use for over ten or even twenty years?

Through deep format analysis, beyond fuzzing, we look at what goes wrong when the format specifications are interpreted differently. Can you trust programs that work with archives? Can you even trust your antivirus? We will answer these questions and disclose for the first time 15 newly discovered vulnerabilities in ZIP, 7ZIP, RAR, CAB and GZIP file formats revealing the impact they have on anti-malware scanners, digital forensic, security gateways and IPS appliances.

This talk will include demo of ArchiveInsider, a new forensics tool that detects and extracts hidden data and fully validates vulnerable file formats. We will demonstrate file format steganography, file malformation, and even data "self destruction," all with tools that you use and trust."

See you there...

VN:F [1.8.4_1055]
Rating: +2 (from 2 votes)
  • Share/Bookmark
2010
02.18

With over 385 functions TitanEngine is surely overwhelming at first sight. To help you get over this initial barrier we have included many sample applications with the TitanEngine SDK. However that still involves learning the use of 20 - 30 functions and the general layout we envisioned for our dynamic unpackers. And even this can be a lot for someone who wants to perform simple tasks such as creating an unpacker for FSG packer. Having that in mind we designed a basic set of 5 functions that are simple to use because they automate most of the steps needed in creating simple dynamic unpackers. These 5 new functions create the debugging process, search for patterns, set breakpoints and handle memory dumping and file fixing steps.

To demonstrate what is coming in the next TitanEngine 2.0.3 release we asked one of our reverse engineers to show us how he would create an unpacker for FSG using these new functions. Single breath video capture which only took 16 minutes shows how to create a simple FSG 2.0 unpacker from scratch, for the first time showing the entire unpacker coding process. We have speedup this video four times for your viewing pleasure. Final result of this exercise is a fully functional FSG 2.0 unpacker done in only 40 lines of code.

This is just one of the features that you can expect to see in the next TitanEngine major version upgrade. Stay tuned for more...

VN:F [1.8.4_1055]
Rating: +3 (from 3 votes)
  • Share/Bookmark
2010
02.15

There is hardly a software protection now days that has just a single layer of code which contains whole stub code. Even some software packers such as PeCompact implement multiple layers in process of software decompression. It is common that these higher layers do most interesting protection operations such as memory decompression, import table processing and entry point protection and redirection. Therefore in order to fully dynamically unpack these kinds of protection we need to move trough these layers and collect the needed data along the way. Protection we have chosen to analyze is AlexProtector because it features use of just such multiple layer protection model along with other interesting protection features. During analysis of this protection we will encounter: obfuscations, antidebugging, antitracing, antiemulation, checksum checks, import elimination and stolen bytes at the entry point. Quite an impressive list of protections found in software protection from 2004 which is why we at the ReversingLabs commonly use it as introduction to more complex protection solutions.

Entry point of the packed file gives us a vague clue on how interesting this analysis will be. It looks like this:

  PUSHAD
  CALL L002
L002:
  POP EBP
  SUB EBP,00401006
  CALL 00407036
  JMP L007
  DB E9
L007:
  MOV EAX,DWORD PTR SS:[ESP+C]
  JMP SHORT 0040701E

Usual method of getting code offset delta via CALL/POP followed by simple obfuscations and first packer controlled exception. Luckily for us the whole first protection layer is unprotected so basic stub functions are accessible from start. They include antidebugging functions and more importantly decompression of main protection layer and control transfer to it. Therefore this first layer is only interesting in sense of catching the layer control transfer. To locate that part of the code we scroll a bit down and spot the aplib decompression code. That recognizable code:

  PUSHAD
  MOV ESI,DWORD PTR SS:[ESP+24]
  MOV EDI,DWORD PTR SS:[ESP+28]
  CLD
  MOV DL,80
  XOR EBX,EBX
  MOVS BYTE PTR ES:[EDI],BYTE PTR DS:[ESI]
...
  SUB EDI,DWORD PTR SS:[ESP+28]
  MOV DWORD PTR SS:[ESP+1C],EDI
  POPAD
  RET

And it is located at offset +0x108 relative to the entry point. Since it is common for protectors to compress and/or encrypt their layers setting a hardware breakpoint here seems like a good place to start. After a few exceptions it is finally hit and we can collect the needed data from this functions input parameters. If we take a look at the stack we can see these numbers:

0012FF50   00407AB9  RETURN to 00407AB9 from 00407108 ;Called from
0012FF54   00408531  00408531 ;Packed layer content
0012FF58   00330000           ;Allocated layer buffe

If we look at the address layer decompression was called from we can see this:

  CALL 00407108 ;aPLib decompression
  ADD ESP,8
  PUSHAD ;AntiTracing via RDTSC
 ...
  ADD ESP,4
  RDTSC
  MOV EBX,EAX
...
  ADD ESP,4
  MOV ECX,EDX
...
  ADD ESP,4
  RDTSC
  SUB EAX,EBX
...
  ADD ESP,4
  SBB EDX,ECX
  RDTSC
  ADD EAX,EBX
...
  ADD ESP,4
  ADC EDX,ECX
  RDTSC
  SUB EAX,EBX
...
  ADD ESP,4
...
  ADD ESP,4
  SBB EDX,ECX
...
  ADD ESP,4
  TEST EDX,EDX
  JNZ SHORT 00407B36 ;Executed if code is traced
  POPAD

This antitrace code is repeated throughout the code many times, and it is also present in all API redirections. Following this is a single exception that is executed just before the control transfer to second protection layer. Instruction JMP EDI which is located just above the custom memory checksum algorithm transfers the control to next layer. That next layer starts like this:

  JMP L003
L001:
  JMP L004
  ???
L003:
  JMP L001
L004:
  CALL L036
  TEST AL,83
  LES EAX,FWORD PTR DS:[EAX+EDX*4]
  NOP
  NOP
  NOP
  NOP
 

This protection layer holds all information necessary for unpacker coding in this layer. Import are handled at these locations:

+0x9A5:  PUSH EBX
  LEA EDX,DWORD PTR SS:[EBP+401108]
  CALL NEAR EDX                       ;decompress IAT data
  ADD ESP,8
  MOV EDI,DWORD PTR SS:[EBP+4023A9]
+0x9B7:  CMP BYTE PTR DS:[EDI],0C3
  JNZ 00330A8C
  ADD EDI,2
  PUSH EDI
  CALL NEAR DWORD PTR SS:[EBP+4024C8] ;GetModuleHandleA
  TEST EAX,EAX
...
+0xA95:  INC EDI
  PUSH EDI
  PUSH DWORD PTR SS:[EBP+40247C]
  CALL NEAR DWORD PTR SS:[EBP+4024C4] ;GetProcAddress
  XOR EBX,EBX
  PUSHAD
 

And this is where we have a choice to either place breakpoints at these locations or analyze a memory buffer holding IAT data. That buffer is decompressed just before it is processed. If we take a look at how it looks like we can see the following pattern:

typedef struct ALEX_IAT_DLL{
       BYTE DLLSignature; //0xC3
       BYTE DLLNameLength;
       // DLLName[DLLNameLength] followed by 0x00
}ALEX_IAT_DLL, *PALEX_IAT_DLL;
 
typedef struct ALEX_IAT_APIENTRY{
       BYTE APINameLength;
       // APIName[APINameLength] followed by 0x00
       BYTE RedirectionNumber; //Number of redirections
       DWORD RedirectionAddress[RedirectionNumber];
}ALEX_IAT_APIENTRY, *PALEX_IAT_APIENTRY;

Any of the two choices is a good one. However AlexProtector uses protection technique called import elimination which means that parts of the code section which are used as call gates to Windows API are damaged and must be fixed. This data is stored in the import structure we just analyzed. However there is a problem with this since we don't know the original location of the import table and we must reserve some space for it. Solution to this problem is to reserve space in the new section but a detailed description on how to do this will be done next week in the part two of this blog when we create the unpacker for AlexProtector.

Solving the problem of imports leaves us with just one more problem, the entry point. After some quick tracing we find this code part:

+0x107B:  MOV ESI,DWORD PTR SS:[EBP+402385] ;SS:[00408385]=004012E6
  ADD EAX,EBX
  MOV BYTE PTR DS:[EAX],0E9 ;Write jump to EP
  INC EAX
  MOV ECX,ESI
...
+0x11E5:  MOV DWORD PTR SS:[ESP+1C],EAX
  POPAD
  JMP NEAR EAX              ;Jump to stolen EP code
...
  MOV EDI,DFB4AF72
  LEA EDI,DWORD PTR DS:[1A58BA5F]
  DEC EDI
  SHRD EDI,ESI,0F2
  BSR EDI,ESI
  TEST EDI,2730DC5C
  TEST EDI,874CDC1C
  AND EDI,9378C643
  JMP 004012E6              ;True jump to EP
 

First part of this code at +0x107B writes the jump to entry point, more exactly the first instruction after few instruction that have been stolen. Since those stolen instructions must be executed protector creates yet another layer which is executed just before the jump to entry point. That layer contains the stolen instructions and the jump at the end of that code leads to protected file code section. Stolen instructions are mixed with the junk instructions so its easiest to dump this layer to new sections and fix jump to entry point. This was the last piece of information needed to create unpacker for this protection, which is a topic for next week when we continue working on AlexProtector.

If you only want to unpack AlexProtect protected files you can see how it is done in our video tutorial which shows ImportStudio usage:

Writing an unpacker for AlexProtector should be a nice exercise for any reverser. However we will do that next week, until then...

Samples and Protector
(package contains protector binary and samples used)

VN:F [1.8.4_1055]
Rating: +4 (from 4 votes)
  • Share/Bookmark
2010
02.08

TitanEngine and Python SDK

As we said in the blog dedicated to our latest TitanEngine release we are continuously working on expanding our SDK to support as much programming languages as possible. That is why the next major version update for TitanEngine will feature a support for Python scripting language. We are looking forward to seeing multiple unpacking scripts appearing with the next TitanEngine major release.  Until next week...

VN:F [1.8.4_1055]
Rating: +3 (from 3 votes)
  • Share/Bookmark
2010
02.01

Minor inconvenience

During our every day work as reverse engineers we encounter problems that affect the tools we use. Most commonly to try to detect their presence and/or crash them. Whatever is their purpose we must work our way around them. One of such problems we encountered recently is a theoretical scenario in which OllyDBG can't resolve data about the loaded modules. This scenario is possible do the fact that OllyDBG doesn't use unicode APIs to access files on the disk. However question remains, how can you load a DLL file with non English characters? That isn't possible via import table since all DLL names in that table are ASCII. In fact only way to do this is to use the unicode version of LoadLibrary API, which seems odd because it isn't really clear why this is even possible. Simply put there is no need for such a feature because files with names that consist of non English characters can't be statically loaded because PECOFF documentation specifies that those strings are ASCII. But this is just a minor inconvenience we can work around since that memory can still be accessed. One of the available solutions is to rename the file and correct the LoadLibrary calls to load the new file. Until next week...

VN:F [1.8.4_1055]
Rating: +2 (from 2 votes)
  • Share/Bookmark
2010
01.27

ReversingLabs first birthday

The time has proven itself irrelevant once more with ReversingLabs celebrating its first birthday after seven long years of existence. Today is a very special day for us here at the ReversingLabs because today we turn one, officially. That means that just a year ago roller-coaster we call ReversingLabs Corporation stared its journey racing us to future. So far it has been a hell of a ride with the best twist and turns yet to happen, we promise you that. This year, even though its January, looks extremely promising with interesting works already done and releases pending, so keep an eye out open for us since you never know where we might show up.

Our thanks goes to everyone who supported us during all those years, we promise to keep surprising you with our projects on (more) regular basics.

VN:F [1.8.4_1055]
Rating: +5 (from 5 votes)
  • Share/Bookmark
2010
01.18

If it ain’t broke…

If it ain't broke, don't fix it. But what if it is? What if the file you are trying to unpack with your unpacker is broken, then what? Do you just chuck it marking it as crapware or do you try to fix it? This raises many many question in file handling. Its foolish to assume that every file your unpacker receives is a valid portable executable. So, how does TitanEngine cope with this?

As you may know TitanEngine has two built in functions to identify and fix damaged PE32/PE32+ files. Those two functions are: IsPE32FileValidExW and FixBrokenPE32FileExW in their UNICODE implementation. If you remember, not too long ago we published a PE validation tool built around our validation function which is available here. Today we pay attention on how to use these two functions.

Ideally before initializing the dynamic unpacking process you would validate the file you are unpacking to see if it will actually execute on the system. Windows loader can also show error messages about the broken file but since we are building our own application which might batch files its best to handle these cases statically before the application runs. And TitanEngine's validation function works in just such a way. It statically inspects the file making sure that it is valid or providing as much information about the errors found as possible. If we take a look at the FILE_STATUS_INFO structure we see all aspects of PE file being inspected.

typedef struct{
	BYTE OveralEvaluation;
	bool EvaluationTerminatedByException;
	bool FileIs64Bit;
	bool FileIsDLL;
	bool FileIsConsole;
	bool MissingDependencies;
	bool MissingDeclaredAPIs;
	BYTE SignatureMZ;
	BYTE SignaturePE;
	BYTE EntryPoint;
	BYTE ImageBase;
	BYTE SizeOfImage;
	BYTE FileAlignment;
	BYTE SectionAlignment;
	BYTE ExportTable;
	BYTE RelocationTable;
	BYTE ImportTable;
	BYTE ImportTableSection;
	BYTE ImportTableData;
	BYTE IATTable;
	BYTE TLSTable;
	BYTE LoadConfigTable;
	BYTE BoundImportTable;
	BYTE COMHeaderTable;
	BYTE ResourceTable;
	BYTE ResourceData;
	BYTE SectionTable;
}FILE_STATUS_INFO, *PFILE_STATUS_INFO;

Most important field for file validation purposes is the OveralEvaluation field which can have the following values:

  • UE_RESULT_FILE_OK
  • UE_RESULT_FILE_INVALID_FORMAT
  • UE_RESULT_FILE_INVALID_AND_NON_FIXABLE
  • UE_RESULT_FILE_INVALID_BUT_FIXABLE

No matter if the file is fixable or not the rest of the structure will be filled with information about defects found in the file. File is considered invalid and non fixable if the file OveralEvaluation says so, but that doesn't mean that the file will execute. If there are missing dependencies in the file it might not execute but that can be easily fixed by installing the Nexus plugin. If however OveralEvaluation claims that file can be fixed we can call FixBrokenPE32FileExW function to try to repair the file. While file is being repaired  following structure will be filled:

typedef struct{
	BYTE OveralEvaluation;
	bool FixingTerminatedByException;
	bool FileFixPerformed;
	bool StrippedRelocation;
	bool DontFixRelocations;
	DWORD OriginalRelocationTableAddress;
	DWORD OriginalRelocationTableSize;
	bool StrippedExports;
	bool DontFixExports;
	DWORD OriginalExportTableAddress;
	DWORD OriginalExportTableSize;
	bool StrippedResources;
	bool DontFixResources;
	DWORD OriginalResourceTableAddress;
	DWORD OriginalResourceTableSize;
	bool StrippedTLS;
	bool DontFixTLS;
	DWORD OriginalTLSTableAddress;
	DWORD OriginalTLSTableSize;
	bool StrippedLoadConfig;
	bool DontFixLoadConfig;
	DWORD OriginalLoadConfigTableAddress;
	DWORD OriginalLoadConfigTableSize;
	bool StrippedBoundImports;
	bool DontFixBoundImports;
	DWORD OriginalBoundImportTableAddress;
	DWORD OriginalBoundImportTableSize;
	bool StrippedIAT;
	bool DontFixIAT;
	DWORD OriginalImportAddressTableAddress;
	DWORD OriginalImportAddressTableSize;
	bool StrippedCOM;
	bool DontFixCOM;
	DWORD OriginalCOMTableAddress;
	DWORD OriginalCOMTableSize;
}FILE_FIX_INFO, *PFILE_FIX_INFO;

This structure is input/output one. It can be used to set options to what will be fixed in and what will be left as it is. This is totally optional and this structure can be left zeroed before calling the file fixing function. Field OveralEvaluation can have the same values like in the FILE_STATUS_INFO structure and its used the same way. Additionally the value of variable FileFixPerformed indicates if the the file has been fixed. However not all field can be fixed, some can only be temporarily stripped. These fields are saved in the FILE_FIX_INFO structure and must be restored once the file has been dumped to disk. Most commonly this refers to resources which can be corrupted on disk but valid once the file has been decompressed in memory. Currently there isn't a function to automatically restore these fields so it must be done by the unpacker code. This will change for next major release.

To make this blog a little more then just a documentation clarification we have modified our existing UPX unpacker sample to support basic file fixing. Sample which is included in the package has damaged SizeOfImage field and incorrect code section attributes. This is fixed by the unpacked and saved in a new file which is then used for unpacking. As always binary, source code and the samples are included with the blog. Until next week...

RL!deUPX
(package contains unpacker binary, source and samples used)

VN:F [1.8.4_1055]
Rating: +3 (from 3 votes)
  • Share/Bookmark