Monday 1 April 2013

An introduction to debugging with Linux

And reverse-engineering  


For this tutorial on how tu use gdb, I picked the first level on IO at smashthestack's wargame.

The vulnerable program to privilege escalation as this info on it:
"usage: %s "

So here, since its probably a program that looks for a specific string to grant you access to the next level, you have to think how the programmer coded the application since you cannot see it.

So in general, its probably an application along these lines:

if the command line argument == string
execute /bin/sh

First, lets get a general idea of what main() looks like with objdump:
when you see "intel" its because i want the intel syntax rather than AT&T, i find it easier to read through.

from the man page:
objdump displays information about one or more object files. The options control
what particular information to display. This information is mostly useful to
programmers who are working on the compilation tools, as opposed to programmers who
just want their program to compile and work.

objfile... are the object files to be examined. When you specify archives, objdump
shows information on each of the member object files.

-D flag --disassemble-all
Like -d, but disassemble the contents of all sections, not just those expected
to contain instructions.

If the target is an ARM architecture this switch also has the effect of forcing
the disassembler to decode pieces of data found in code sections as if they
were instructions.

grep -A20 main.:
grep searches the named input FILEs (or standard input if no files are named, or if
a single hyphen-minus (-) is given as file name) for lines containing a match to
the given PATTERN. By default, grep prints the matching lines.

-A NUM, --after-context=NUM
Print NUM lines of trailing context after matching lines. Places a line
containing a group separator (--) between contiguous groups of matches.
With the -o or --only-matching option, this has no effect and a warning is
given.

so basically i just want to grep the first lines of main()
-------------------------------------------------------------------------

so when i read these instructions here:
8048409:    c7 45 f4 c8 85 04 08 mov DWORD PTR [ebp-0xc],0x80485c8
8048410:    8b 45 e0 mov eax,DWORD PTR [ebp-0x20]
8048413:    83 38 02 cmp DWORD PTR [eax],0x2
8048416:    74 21 je 8048439

we are creating a *pointer than will contain the value located at the address 0x80485c8, which would have been given at the data declaration, which we will compare and if equal we will jump to the given address.

Since my assumptions of the code, i think the password (or string to compare) is located at the memory address 0x80485c8

so im going to run the debugger and check the value of that address, i could probably see that value before i have checked it, but i know that when we are to compare it, it has to contain the right value.
so btw, you can see i had not yet set the intel syntax in there and can see the difference between intel and AT&T (for those who didnt know about the different syntax).

so basically break main, will stop the program right before the _main_ function gets executed. from there, i r eip will show me what the EIP register is pointing to (the next instruction). x/5i will show me the next 5 instrucitons.

so i use 'nexti' to move to the next instruction, unjtil i get to where i want to be. like i said i could have probably stopped before that, but i know for sure that the value is written at the memory address i want to look at (because data can be changed, but the value we are comparing is the right one), as seen by objdump;. (you could also run disassemble main from gdb instead and when the program was compiled using the -g flag, you can even list the source code with the list function).

so to look at what is the value at the memory address i suspect the password to be, i use 'x' which is short for examine. thus x/s will show me the value in a string format.

so x/s will examine the value at the address specified and BINGO, we have the password.

there is an easier way, which is the strings function. since the password was in clear text, the string function will print out the strings out of the binary file:
Hope this helps to get you started debugging applications.

"take advantage of the enemy's unreadiness, make your way by unexpected routes, and attack unguarded spots." --Sun Tzu

No comments:

Post a Comment