Debug Fundamentals Exercise 4: The GAMEOVER exercise

Debug Fundamentals Exercise 4: The GAMEOVER exercise

  • Comments 8

 

We are back with another addition to the debugging fundamentals series here in 2009! Regardless of your debugging experience we hope you enjoy this one. Don’t worry too much if you can’t answer them all but give them your best shot.

 

The problem:

 

While debugging an application, a developer observes a crash and is puzzled. The developer saves a memory dump of the process using the command “.dump /ma dbgex4.dmp” and sends it to you for debug assistance.

 

0:000> r

eax=53454750 ebx=00000000 ecx=00000100 edx=000001b0 esi=001bfe20 edi=00ac36bc

eip=47414d45 esp=001bfe00 ebp=4f564552 iopl=0         nv up ei pl zr na pe nc

cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00010246

47414d45 ??              ???

 

The attached zip, dbgex4.zip, includes three files. The program itself, the program’s symbols file and the saved memory dump file. (NOTE: You do not need to execute the program for the exercise however you may want to in order to solve the bonus’. You will need to rename the file dbgex4.ex_ to dbgex4.exe in order to run it).

 

Using the accompanying files, answer the following questions:

 

Part One – Debugging

 

1.       What caused the access violation?

2.       Examine the registers at the time of the crash.  Is there anything interesting about the contents?

3.       How did the registers get into this state?

4.       Find the offending data structure which caused this state to occur. What are its contents?

5.       Are there security concerns with this access violation? Why?

6.        Why is this class of crashes not seen in the wild much anymore?

Part Two – Reverse Engineering

 

Examine the functions main(), snap(), crack(), pop(), and boom().

1.       Describe with a sentence or two what each one is doing.  (There is no need to comment on every assembly instruction or re-write the code in C here unless you really feel you need to.)

Bonus:

1.       If this access violation occurred while the program was running without a debugger present, would there be anything different about the crashing register state or the data structure which caused it? If so what is it and why? (HINT: If you would like to observe the crashing state like this, you can register windbg.exe to be the Just-In-Time debugger using the –I switch like so “windbg.exe -I”. When you run the dbgex4.exe program, it will crash and windbg.exe will launch automatically and attach to it.)

2.       The functions from “Part Two – Reverse Engineering” perform operations on a set of data. During this manipulation some data is lost. Find this data and decode its “secret” message.

 

Share this post :
Attachment: dbgex4.zip
Leave a Comment
  • Please add 6 and 4 and type the answer here:
  • Post
  • 1 - Stack is overwritten, so ret in boom causes return to a bad address which isn't valid

    2 - EAX has some custom value, EBP still looks good showing some previous function calls

    3 - Executed up through boom function

    4 - Not copying here =)

    5 - It's a buffer overflow, a common way to gain execution if a bug is around

    6 - cookies are usually on the stack where static buffers are used in order to detect this problem

    Part 2

    - snap - copy struct from memory into reserved area on stack to perform later operations

    - crack - swap all the values in the structure (last byte now first byte, etc.), then find offset to in struct to first instance of 0xC3

    - pop - move everything up by the offset found in crack

    - boom - copy from struct to local buffer until zero is found, a little too much

    Part 3

    1 - Didn't try this

    2- GAMEOVER Happy debugging courtesy of Platforms GES!<DBGNINJA>

  • so where do we find the answers, and better yet, the step through to solve this?

    Thanks!

    [We'll post the answers next week after everyone has a chance to work through the quiz. Thanks, Ron]
  • Part One – Debugging

    1) What causes the AV?

    Buffer overrun which damages the return address (among other things)

    2)  Examine the registers at the time of the crash.  Is there anything interesting about the contents?

    The EIP and EBP contain "funny" values. These are, in fact, hints to solving the problem.

    3) How did the registers get into this state?

    As part of function cleanup code, EBP is restored to a previous value (0x4f564552 in this case, the actual value (0x001bfe04) has been overwritten)

    EIP will be automatically loaded with the return address saved on stack prior to function invocation (0x47414d45 in this case, actual value (0x00ac123b) has been overwritten)

    4) Find the offending data structure which caused this state to occur. What are its contents?

    The offending data structure is a null-terminated character buffer. It is a literal 'GAMEOVER Happy debugging courtesy of Platforms GES!' written backwards. The length of the buffer is 8 bytes longer than the allotted stack space - hence the overrun.

    5) Are there security concerns with this access violation? Why?

    Well, altering the return address could lead to execution of injected hostile code

    6) Why is this class of crashes not seen in the wild much anymore?

    Recent compilers have built-in support against buffer overruns (Stack Guard on GCC, '/GS' flag on Visual Studio). <a href="http://en.wikipedia.org/wiki/Stack-smashing_protection">Link for more info</a>.

    Part Two – Reverse Engineering

    1) Describe with a sentence or two what each one is doing.  (There is no need to comment on every assembly instruction or re-write the code in C here unless you really feel you need to.)

    a) main() allocates 76 (0x4c) bytes of stack space and invokes snap with the address to the buffer

    b) snap(0x001bfe20)

    > makes a copy of global buffer named 'string', size of 61 (0x3d) bytes (counted to the null-terminator)

    > invokes crack (by jumping directly to it)

    c) crack(0x001bfe20)

    > reverses the buffer

    > locates the 0xc3 byte in the string and invokes pop() providing it with initial buffer's address and position to the byte next to 0xc3

    d) pop(0x001bfe20, 0xc)

    > copies the bytes following 0xc3 until the null-terminator to the original buffer starting from the beginning (0x001bfe20)

    > invokes boom with the address of the buffer

    e) boom(0x001bfe20)

    > allocates stack for buffer of size 0x2c (0x34-0x2c=8 bytes offending difference)

    > makes a copy of the buffer (to the null-terminator)

    > decodes the string by ORing source byte divided by 16 with source byte multipled by 16

    Bonus

    1) The decoded buffer (which caused the overrun) is not present on stack

    [Buffer comparison]

    0:000> db 001bfe20 l34

    001bfe20  12 35 54 74 02 37 d6 27-f6 66 47 16 c6 05 02 66  .5Tt.7.'.fG....f

    001bfe30  f6 02 97 37 56 47 27 57-f6 36 02 76 e6 96 76 76  ...7VG'W.6.v..vv

    001bfe40  57 26 56 46 02 97 07 07-16 84 02 25 54 65 f4 54  W&VF.......%Te.T

    001bfe50  d4 14 74 00                                      ..t.

    0:000> db dbgex4!string l3e

    00ac3000  74 14 d4 54 f4 65 54 25-02 84 16 07 07 97 02 46  t..T.eT%.......F

    00ac3010  56 26 57 76 76 96 e6 76-02 36 f6 57 27 47 56 37  V&Wvv..v.6.W'GV7

    00ac3020  97 02 f6 66 02 05 c6 16-47 66 f6 27 d6 37 02 74  ...f....Gf.'.7.t

    00ac3030  54 35 12 c3 44 24 74 e4-94 e4 a4 14 e3 00        T5..D$t.......

    Part of stack with trashed EBP and EIP:

    ...

    001bfdf4  4f564552 ; EBP

    001bfdf8  47414d45 ; EIP

    001bfdfc  00b1ef02

    001bfe00  00000001

    001bfe04  001bfe14

    001bfe08  00ac1289 dbgex4!crack+0x44 [c:\tmp\dbgex4.cpp @ 94] ; call to pop()

    ...

  • I have not had a chance to download the attachment but based on a quick look and having seen a lot of things like this in the past, I think I can offer a few answers shooting from the hip.

    1.       What caused the access violation?

    Not having looked at the dump, I would say that some sort of stack destruction was the culprit.

    2.       Examine the registers at the time of the crash.  Is there anything interesting about the contents?

    Absolutely - EIP and EBP (as well as EAX) all appear to have some sort of ASCII text (4 bytes) stored in them.

    3.       How did the registers get into this state?

    My guess is some sort of data overrun.  A temporary stack location used to hold a string and a sprintf() or similar call overran that buffer on the stack.

    4.       Find the offending data structure which caused this state to occur. What are its contents?

    Have not had a chance to look deeply into that.

    5.       Are there security concerns with this access violation? Why?

    Yes.  Malware can take advantage of this overrun and have valid instructions written instead of just text (ASCII).  Carefully crafted destruction can wreak all kinds of havoc and compromise security on a node (or worse).

    6.        Why is this class of crashes not seen in the wild much anymore?

    Hopefully, because developers are using Visual Studio 2005 (or newer) and have taken heed of the warnings about using unsafe functions such as sprintf(), strcat(), etc.  Best practices would be to modify existing code to use the secure C run time functions (like sprintf_s()) to help prevent buffer overruns and data corruption.

    Just my 2 cents from looking at only the register dump.  Here's hoping that many years of seeing this type of footprint has served me well.

    Mike

  • Hi GES team.

    Nice day and thanks for the “Happy debugging”.

    The secret message is the following:

    GAMEOVER Happy debugging courtesy of Platforms GES!

    Anyway, the access violation is caused by a corruption of stack, the edp is corrupted and move the eip to an incorrect memory area. This  memory area cannot read/write. Code resides only in a read memory area.

    The data structure used to corrupt the stack is the following:

    char buf[] = {0x74, 0x11, 0xD4, 0x54};

    This crash is a protection introduced by the DEP. This feature provides the ability to sign a memory area that can be read or read/write. This protection try to avoid a runtime injection of malicious code.

    Is very difficult to introduce this kind of error in the day by day programming work.

  • the number of things done wrong in this program, are hard to count,

    lets see, procedures without returns, procedure that doesn't rebalance the stack (cause of crash), no string sanitization, string coping onto the buffer, the list is long and bad.

    Cause of access violation, I didn't look too hard, but simply, setup stack frame and then returns without disassembling the stack from, but from what I could see, you might overright the proper return address to boot.

    return caused eip, eax was set, the others I didn't look at, not sure if SEH changed ebp or if it was overwritten, didn't check too hard, the program is rather one big mess.

  • The EIP and EBP value really suggested that this is a stack overridden problem. The value itself suggest it looks like the stack is overridden by a string. use command 'dda esp-100 esp' and search the EBP value from the result I can see that the EBP is actually be overridden by the string "!SEG smroftalP fo ysetruoc gniggubed yppaH REVOEMAG"

    1.       What caused the access violation?

    Stack is got overridden. The program is try to write a string into an array on the stack, whose size is however less than the string length thus the stack content is got overridded by the rest of the string. And unfortunately the data that is got overridden is the return address. Thus when the RET instructment is called a wrong address is put into EIP, which causes the access violation.

    2.       Examine the registers at the time of the crash.  Is there anything interesting about the contents?

    EIP=47414d45, EBP=4f564552. The content of the hex numbers looks really like an array of chars if we read it as (47-41-4d-45) and (4f-56-45-52), all groups is actually a ASCII reprentation of an letter.

    3.       How did the registers get into this state?

    Explained in the 1st question

    4.       Find the offending data structure which caused this state to occur. What are its contents?

    "!SEG smroftalP fo ysetruoc gniggubed yppaH REVOEMAG"

    5.       Are there security concerns with this access violation? Why?

    Yes. By override the return address by some well designed data (say, an address of a function which is injected by the hacker) a hacker can hijack the program to do whatever he wants

    6.        Why is this class of crashes not seen in the wild much anymore?

    1. Use the new _s family can avoid stack overriden

    2. Use static code analysis can find the suspecious places

    3. use STL-like well deisgned C++ data structure rather than the raw C data structures can avoid the problem.

  • We’re posting the answers to Debug Fundamentals #4 in this blog. Additionally we posted all of your answers

Page 1 of 1 (8 items)