Eilam E.Reversing.Secrets of reverse engineering.2005
.pdf
Breaking Protections 371
Figure 11.10 Defender.EXE launched without any command-line options.
Defender takes a username and a 16-digit hexadecimal serial number. Just to see what happens, let’s try feeding it some bogus values. Figure 11.11 shows how Defender respond to John Doe as a username and 1234567890ABCDEF as the serial number.
Well, no real drama here—Defender simply reports that we have a bad serial number. One good reason to always go through this step when cracking is so that you at least know what the failure message looks like. You should be able to find this message somewhere in the executable.
Let’s load Defender.EXE into OllyDbg and take a first look at it. The first thing you should do is look at the Executable Modules window to see which DLLs are statically linked to Defender. Figure 11.12 shows the Executable Modules window for Defender.
Figure 11.11 Defender.EXE launched with John Doe as the username and 1234567890ABCDEF as the serial number.
372 Chapter 11
Figure 11.12 Executable modules statically linked with Defender (from OllyDbg).
Figure 11.13 Imports and Exports for Defender.EXE (from OllyDbg).
Very short list indeed—only NTDLL.DLL and KERNEL32.DLL. Remember that our GUI crackme, KeygenMe-3 had a much longer list, but then again Defender is a console-mode application. Let’s proceed to the Names window to determine which APIs are called by Defender. Figure 11.13 shows the Names window for Defender.EXE.
Very strange indeed. It would seem that the only API called by
Defender.EXE is IsDebuggerPresent from KERNEL32.DLL. It doesn’t take much reasoning to figure out that this is unlikely to be true. The program must be able to somehow communicate with the operating system, beyond just calling IsDebuggerPresent. For example, how would the program print out messages to the console window without calling into the operating system? That’s just not possible. Let’s run the program through DUMPBIN and see what it has to say about Defender’s imports. Listing 11.4 shows DUMPBIN’s output when it is launched with the /IMPORTS option.
Microsoft (R) COFF/PE Dumper Version 7.10.3077
Copyright (C) Microsoft Corporation. All rights reserved.
Dump of file defender.exe
Listing 11.4 Output from DUMPBIN when run on Defender.EXE with the /IMPORTS option.
Breaking Protections 373
File Type: EXECUTABLE IMAGE
Section contains the following imports:
KERNEL32.dll
405000 |
Import Address |
Table |
405030 |
Import Name Table |
|
0 |
time date stamp |
|
0 |
Index of first |
forwarder reference |
22F IsDebuggerPresent
Summary
1000 .data
4000 .h3mf85n
1000 .h477w81
1000 .rdata
Listing 11.4 (continued)
Not much news here. DUMPBIN is also claiming the Defender.EXE is only calling IsDebuggerPresent. One slightly interesting thing however is the Summary section, where DUMPBIN lists the module’s sections. It would appear that Defender doesn’t have a .text section (which is usually where the code is placed in PE executables). Instead it has two strange sections:
.h3mf85n and .h477w81. This doesn’t mean that the program doesn’t have any code, it simply means that the code is most likely tucked in one of those oddly named sections.
At this point it would be wise to run DUMPBIN with the /HEADERS option to get a better idea of how Defender is built (see Listing 11.5).
Microsoft (R) COFF/PE Dumper Version 7.10.3077
Copyright (C) Microsoft Corporation. All rights reserved.
Dump of file defender.exe
PE signature found
File Type: EXECUTABLE IMAGE
FILE HEADER VALUES
14C machine (x86)
Listing 11.5 Output from DUMPBIN when run on Defender.EXE with the /HEADERS option. (continued)
374 Chapter 11
4 |
number of sections |
|
4129382F |
time date stamp Mon Aug 23 03:19:59 2004 |
|
0 |
file pointer to symbol table |
|
0 |
number of symbols |
|
E0 |
size of optional header |
|
10F |
characteristics |
|
|
|
Relocations stripped |
|
|
Executable |
|
|
Line numbers stripped |
|
|
Symbols stripped |
|
|
32 bit word machine |
OPTIONAL HEADER VALUES |
||
10B |
magic # (PE32) |
|
7.10 |
linker version |
|
3400 |
size of code |
|
600 |
size of initialized data |
|
0 |
size of uninitialized data |
|
4232 |
entry point (00404232) |
|
1000 |
base of code |
|
5000 |
base of data |
|
400000 |
image base (00400000 to 00407FFF) |
|
1000 |
section alignment |
|
200 |
file alignment |
|
4.00 |
operating system version |
|
0.00 |
image version |
|
4.00 |
subsystem version |
|
0 |
Win32 version |
|
8000 |
size of image |
|
400 |
size of headers |
|
0 |
checksum |
|
3 |
subsystem (Windows CUI) |
|
400 |
DLL characteristics |
|
|
|
No safe exception handler |
100000 |
size of stack reserve |
|
1000 |
size of stack commit |
|
100000 |
size of heap reserve |
|
1000 |
size of heap commit |
|
0 |
loader flags |
|
10 |
number of directories |
|
5060 |
[ |
35] RVA [size] of Export Directory |
5008 |
[ |
28] RVA [size] of Import Directory |
0 |
[ |
0] RVA [size] of Resource Directory |
0 |
[ |
0] RVA [size] of Exception Directory |
0 |
[ |
0] RVA [size] of Certificates Directory |
0 |
[ |
0] RVA [size] of Base Relocation Directory |
0 |
[ |
0] RVA [size] of Debug Directory |
0 |
[ |
0] RVA [size] of Architecture Directory |
0 |
[ |
0] RVA [size] of Global Pointer Directory |
|
|
|
Listing 11.5 (continued)
|
|
|
|
Breaking Protections 375 |
|
|
|
|
|
|
|
|
|
0 |
[ |
0] RVA [size] of Thread Storage Directory |
|
|
|
0 |
[ |
0] RVA [size] of Load Configuration Directory |
|
|
|
0 |
[ |
0] RVA [size] of Bound Import Directory |
|
|
|
5000 |
[ |
8] RVA [size] of Import Address Table Directory |
|
|
|
0 |
[ |
0] RVA [size] of Delay Import Directory |
|
|
|
0 |
[ |
0] RVA [size] of COM Descriptor Directory |
|
|
|
0 |
[ |
0] RVA [size] of Reserved Directory |
|
|
SECTION HEADER #1 |
|
|
|
|
|
.h3mf85n |
name |
|
|
|
|
3300 |
virtual |
size |
|
|
|
1000 |
virtual |
address |
(00401000 to 004042FF) |
|
|
3400 |
size of |
raw data |
|
|
|
400 |
file pointer to |
raw data (00000400 to 000037FF) |
|
|
|
0 |
file pointer to |
relocation table |
|
|
|
0 |
file pointer to |
line numbers |
|
|
|
0 |
number of relocations |
|
||
|
0 |
number of line numbers |
|
||
|
E0000020 |
flags |
|
|
|
|
|
Code |
|
|
|
|
|
Execute |
Read Write |
|
|
|
SECTION HEADER #2 |
|
|
|
|
|
.rdata |
name |
|
|
|
|
95 |
virtual |
size |
|
|
|
5000 |
virtual |
address |
(00405000 to 00405094) |
|
|
200 |
size of |
raw data |
|
|
|
3800 |
file pointer to |
raw data (00003800 to 000039FF) |
|
|
|
0 |
file pointer to |
relocation table |
|
|
|
0 |
file pointer to |
line numbers |
|
|
|
0 |
number of relocations |
|
||
|
0 |
number of line numbers |
|
||
|
40000040 |
flags |
|
|
|
|
|
Initialized Data |
|
|
|
|
|
Read Only |
|
|
|
|
SECTION HEADER #3 |
|
|
|
|
|
.data |
name |
|
|
|
|
24 |
virtual |
size |
|
|
|
6000 |
virtual |
address |
(00406000 to 00406023) |
|
|
0 |
size of |
raw data |
|
|
|
0 |
file pointer to |
raw data |
|
|
|
0 |
file pointer to |
relocation table |
|
|
|
0 |
file pointer to |
line numbers |
|
|
|
0 |
number of relocations |
|
||
|
0 |
number of line numbers |
|
||
|
C0000040 |
flags |
|
|
|
|
|
Initialized Data |
|
|
|
|
|
|
|
|
|
Listing 11.5 (continued)
376 Chapter 11
|
Read Write |
SECTION HEADER #4 |
|
.h477w81 |
name |
8C |
virtual size |
7000 |
virtual address (00407000 to 0040708B) |
200 |
size of raw data |
3A00 |
file pointer to raw data (00003A00 to 00003BFF) |
0 |
file pointer to relocation table |
0 |
file pointer to line numbers |
0 |
number of relocations |
0 |
number of line numbers |
C0000040 |
flags |
|
Initialized Data |
|
Read Write |
Summary
1000 .data
4000 .h3mf85n
1000 .h477w81
1000 .rdata
Listing 11.5 (continued)
The /HEADERS options provides you with a lot more details on the program. For example, it is easy to see that section #1, .h3mf85n, is the code section. It is specified as Code, and the program’s entry point resides in it (the entry point is at 404232 and .h3mf85n starts at 401000 and ends at 4042FF, so the entry point is clearly inside this section). The other oddly named section, .h477w81 appears to be a small data section, probably containing some variables. It’s also worth mentioning that the subsystem flag equal 3. This identifies a Windows CUI (console user interface) program, and Windows will automatically create a console window for this program as soon as it is started.
All of those oddly named sections indicate that the program is possible packed in some way. Packers have a way of creating special sections that contain the packed code or the unpacking code. It is a good idea to run the program in PEiD to see if it is packed with a known packer. PEiD is a program that can identify popular executable signatures and show whether an executable has been packed by one of the popular executable packers or copy protection products. PEiD can be downloaded from http://peid.has.it/. Figure 11.14 shows PEiD’s output when it is fed with Defender.EXE.
Unfortunately, PEiD reports “Nothing found,” so you can safely assume that Defender is either not packed or that it is packed with an unknown packer. Let’s proceed to start disassembling the program and figuring out where that “Sorry . . . Bad key, try again.” message is coming from.
Breaking Protections 377
Figure 11.14 Running PEiD on Defender.EXE reports “Nothing found.”
Reversing Defender’s Initialization Routine
Because the program doesn’t appear to directly call any APIs, there doesn’t seem to be a specific API on which you could place a breakpoint to catch the place in the code where the program is printing this message. Thus you don’t really have a choice but to try your luck by examining the program’s entry point and trying to find some interesting code that might shed some light on this program. Let’s load the program in IDA and run a full analysis on it. You can now take a quick look at the program’s entry point.
.h3mf85n:00404232 start |
proc near |
|
.h3mf85n:00404232 |
|
|
.h3mf85n:00404232 var_8 |
= dword |
ptr -8 |
.h3mf85n:00404232 var_4 |
= dword |
ptr -4 |
.h3mf85n:00404232 |
|
|
.h3mf85n:00404232 |
push |
ebp |
.h3mf85n:00404233 |
mov |
ebp, esp |
.h3mf85n:00404235 |
push |
ecx |
.h3mf85n:00404236 |
push |
ecx |
.h3mf85n:00404237 |
push |
esi |
.h3mf85n:00404238 |
push |
edi |
.h3mf85n:00404239 |
call |
sub_402EA8 |
.h3mf85n:0040423E |
push |
eax |
.h3mf85n:0040423F |
call |
loc_4033D1 |
.h3mf85n:00404244 |
mov |
eax, dword_406000 |
.h3mf85n:00404249 |
pop |
ecx |
.h3mf85n:0040424A |
mov |
ecx, eax |
.h3mf85n:0040424C |
mov |
eax, [eax] |
.h3mf85n:0040424E |
mov |
edi, 6DEF20h |
.h3mf85n:00404253 |
xor |
esi, esi |
.h3mf85n:00404255 |
jmp |
short loc_404260 |
.h3mf85n:00404257 ; ---------------------------------------------------- |
|
|
|
|
|
Listing 11.6 A disassembly of Defender’s entry point function, generated by IDA.
(continued)
378 Chapter 11
.h3mf85n:00404257 |
|
|
.h3mf85n:00404257 loc_404257: |
|
; CODE XREF: start+30_j |
.h3mf85n:00404257 |
cmp |
eax, edi |
.h3mf85n:00404259 |
jz |
short loc_404283 |
.h3mf85n:0040425B |
add |
ecx, 8 |
.h3mf85n:0040425E |
mov |
eax, [ecx] |
.h3mf85n:00404260 |
|
|
.h3mf85n:00404260 loc_404260: |
|
; CODE XREF: start+23_j |
.h3mf85n:00404260 |
cmp |
eax, esi |
.h3mf85n:00404262 |
jnz |
short loc_404257 |
.h3mf85n:00404264 |
xor |
eax, eax |
.h3mf85n:00404266 |
|
|
.h3mf85n:00404266 loc_404266: |
|
; CODE XREF: start+5A_j |
.h3mf85n:00404266 |
lea |
ecx, [ebp+var_8] |
.h3mf85n:00404269 |
push |
ecx |
.h3mf85n:0040426A |
push |
esi |
.h3mf85n:0040426B |
mov |
[ebp+var_8], esi |
.h3mf85n:0040426E |
mov |
[ebp+var_4], esi |
.h3mf85n:00404271 |
call |
eax |
.h3mf85n:00404273 |
call |
loc_404202 |
.h3mf85n:00404278 |
mov |
eax, dword_406000 |
.h3mf85n:0040427D |
mov |
ecx, eax |
.h3mf85n:0040427F |
mov |
eax, [eax] |
.h3mf85n:00404281 |
jmp |
short loc_404297 |
.h3mf85n:00404283 ; ---------------------------------------------------- |
|
|
.h3mf85n:00404283 |
|
|
.h3mf85n:00404283 loc_404283: |
|
; CODE XREF: start+27_j |
.h3mf85n:00404283 |
mov |
eax, [ecx+4] |
.h3mf85n:00404286 |
add |
eax, dword_40601C |
.h3mf85n:0040428C |
jmp |
short loc_404266 |
.h3mf85n:0040428E ; ---------------------------------------------------- |
|
|
.h3mf85n:0040428E |
|
|
.h3mf85n:0040428E loc_40428E: |
|
; CODE XREF: start+67_j |
.h3mf85n:0040428E |
cmp |
eax, edi |
.h3mf85n:00404290 |
jz |
short loc_4042BA |
.h3mf85n:00404292 |
add |
ecx, 8 |
.h3mf85n:00404295 |
mov |
eax, [ecx] |
.h3mf85n:00404297 |
|
|
.h3mf85n:00404297 loc_404297: |
|
; CODE XREF: start+4F_j |
.h3mf85n:00404297 |
cmp |
eax, esi |
.h3mf85n:00404299 |
jnz |
short loc_40428E |
.h3mf85n:0040429B |
xor |
eax, eax |
.h3mf85n:0040429D |
|
|
.h3mf85n:0040429D loc_40429D: |
|
; CODE XREF: start+91_j |
.h3mf85n:0040429D |
lea |
ecx, [ebp+var_8] |
.h3mf85n:004042A0 |
push |
ecx |
.h3mf85n:004042A1 |
push |
esi |
.h3mf85n:004042A2 |
mov |
[ebp+var_8], esi |
|
|
|
Listing 11.6 (continued)
|
|
Breaking Protections 379 |
|
|
|
|
|
.h3mf85n:004042A5 |
mov |
[ebp+var_4], esi |
|
.h3mf85n:004042A8 |
call |
eax |
|
.h3mf85n:004042AA |
call |
loc_401746 |
|
.h3mf85n:004042AF |
mov |
eax, dword_406000 |
|
.h3mf85n:004042B4 |
mov |
ecx, eax |
|
.h3mf85n:004042B6 |
mov |
eax, [eax] |
|
.h3mf85n:004042B8 |
jmp |
short loc_4042CE |
|
.h3mf85n:004042BA ; ---------------------------------------------------- |
|
|
|
.h3mf85n:004042BA |
|
|
|
.h3mf85n:004042BA loc_4042BA: |
|
; CODE XREF: start+5E_j |
|
.h3mf85n:004042BA |
mov |
eax, [ecx+4] |
|
.h3mf85n:004042BD |
add |
eax, dword_40601C |
|
.h3mf85n:004042C3 |
jmp |
short loc_40429D |
|
.h3mf85n:004042C5 ; ---------------------------------------------------- |
|
|
|
.h3mf85n:004042C5 |
|
|
|
.h3mf85n:004042C5 loc_4042C5: |
|
; CODE XREF: start+9E_j |
|
.h3mf85n:004042C5 |
cmp |
eax, edi |
|
.h3mf85n:004042C7 |
jz |
short loc_4042F5 |
|
.h3mf85n:004042C9 |
add |
ecx, 8 |
|
.h3mf85n:004042CC |
mov |
eax, [ecx] |
|
.h3mf85n:004042CE |
|
|
|
.h3mf85n:004042CE loc_4042CE: |
|
; CODE XREF: start+86_j |
|
.h3mf85n:004042CE |
cmp |
eax, esi |
|
.h3mf85n:004042D0 |
jnz |
short loc_4042C5 |
|
.h3mf85n:004042D2 |
xor |
ecx, ecx |
|
.h3mf85n:004042D4 |
|
|
|
.h3mf85n:004042D4 loc_4042D4: |
|
; CODE XREF: start+CC_j |
|
.h3mf85n:004042D4 |
lea |
eax, [ebp+var_8] |
|
.h3mf85n:004042D7 |
push |
eax |
|
.h3mf85n:004042D8 |
push |
esi |
|
.h3mf85n:004042D9 |
mov |
[ebp+var_8], esi |
|
.h3mf85n:004042DC |
mov |
[ebp+var_4], esi |
|
.h3mf85n:004042DF |
call |
ecx |
|
.h3mf85n:004042E1 |
call |
loc_402082 |
|
.h3mf85n:004042E6 |
call |
ds:IsDebuggerPresent |
|
.h3mf85n:004042EC |
xor |
eax, eax |
|
.h3mf85n:004042EE |
pop |
edi |
|
.h3mf85n:004042EF |
inc |
eax |
|
.h3mf85n:004042F0 |
pop |
esi |
|
.h3mf85n:004042F1 |
leave |
|
|
.h3mf85n:004042F2 |
retn |
8 |
|
.h3mf85n:004042F5 ; ---------------------------------------------------- |
|
|
|
.h3mf85n:004042F5 |
|
|
|
.h3mf85n:004042F5 loc_4042F5: |
|
; CODE XREF: start+95_j |
|
.h3mf85n:004042F5 |
mov |
ecx, [ecx+4] |
|
.h3mf85n:004042F8 |
add |
ecx, dword_40601C |
|
.h3mf85n:004042FE |
jmp |
short loc_4042D4 |
|
.h3mf85n:004042FE start |
endp |
|
|
|
|
|
|
Listing 11.6 (continued)
380 Chapter 11
Listing 11.6 shows Defender’s entry point function. A quick scan of the function reveals one important property—the entry point is not a common runtime library initialization routine. Even if you’ve never seen a runtime library initialization routine before, you can be pretty sure that it doesn’t end with a call to IsDebuggerPresent. While we’re on that call, look at how EAX is being XORed against itself as soon as it returns—its return value is being ignored! A quick look in http://msdn.microsoft.com shows us that IsDebugger Present should return a Boolean specifying whether a debugger is present or not. XORing EAX right after this API returns means that the call is meaningless.
Anyway, let’s go back to the top of Listing 11.6 and learn something about Defender, starting with a call to 402EA8. Let’s take a look at what it does.
mf85n:00402EA8 sub_402EA8 |
proc near |
|
.h3mf85n:00402EA8 |
|
|
.h3mf85n:00402EA8 var_4 |
= dword |
ptr -4 |
.h3mf85n:00402EA8 |
|
|
.h3mf85n:00402EA8 |
push |
ecx |
.h3mf85n:00402EA9 |
mov |
eax, large fs:30h |
.h3mf85n:00402EAF |
mov |
[esp+4+var_4], eax |
.h3mf85n:00402EB2 |
mov |
eax, [esp+4+var_4] |
.h3mf85n:00402EB5 |
mov |
eax, [eax+0Ch] |
.h3mf85n:00402EB8 |
mov |
eax, [eax+0Ch] |
.h3mf85n:00402EBB |
mov |
eax, [eax] |
.h3mf85n:00402EBD |
mov |
eax, [eax+18h] |
.h3mf85n:00402EC0 |
pop |
ecx |
.h3mf85n:00402EC1 |
retn |
|
.h3mf85n:00402EC1 sub_402EA8 |
endp |
|
The preceding routine starts out with an interesting sequence that loads a value from fs:30h. Generally in NT-based operating systems the fs register is used for accessing thread local information. For any given thread, fs:0 points to the local TEB (Thread Environment Block) data structure, which contains a plethora of thread-private information required by the system during runtime. In this case, the function is accessing offset +30. Luckily, you have detailed symbolic information in Windows from which you can obtain information on what offset +30 is in the TEB. You can do that by loading symbols for NTDLL in WinDbg and using the DT command (for more information on WinDbg and the DT command go to the Microsoft Debugging Tools Web page at www.microsoft.com/whdc/devtools/debugging/default.mspx).
The structure listing for the TEB is quite long, so I’ll just list the first part of it, up to offset +30, which is the one being accessed by the program.
+0x000 |
NtTib |
: |
_NT_TIB |
+0x01c EnvironmentPointer |
: Ptr32 Void |
||
+0x020 |
ClientId |
: |
_CLIENT_ID |
+0x028 |
ActiveRpcHandle |
: |
Ptr32 Void |
