Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Eilam E.Reversing.Secrets of reverse engineering.2005

.pdf
Скачиваний:
69
Добавлен:
23.08.2013
Размер:
8.78 Mб
Скачать

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