Dynamic analysis

The theme of the day was dynamic analysis of programs, and some tools to use.

Software tools used today

file
determine the file type from its contents.
strings
print the strings of printable characters in files.
gdb
the GNU debugger.
ltrace
Run a program and print used library calls and their arguments.
xxd
make a hexdump of a file.

Hexdumps

A hexdump is a printable representation of data, it typically looks like this:

$ xxd a.out
00000000: 7f45 4c46 0201 0100 0000 0000 0000 0000  .ELF............
00000010: 0300 3e00 0100 0000 7006 0000 0000 0000  ..>.....p.......
00000020: 4000 0000 0000 0000 e019 0000 0000 0000  @...............
...

Every line displays 16 bytes. To the left is the address (or file offset), in the middle is the data in hexadecimal, and the rightmost column shows the same data but as printable characters. In this case, the second, third and fourth bytes (offset 1 to 3) are 0x45, 0x4c, 0x4f or “ELF”. Non-printable characters are show as dots.

A note of caution, do NOT use xxd to dump multiple files at once, like $ xxd * as it will assume the second argument is a destination to write the dump to. This destroys the file in the second argument. (Lars has done this, on important files…)

Debugging

The debugger gdb is a very powerful tool, but it can take some time to get used to. It has a command line interface.

Here are some common gdb commands:

  • help - get inline help about commands
  • run (r) - run program from beginning
  • continue (c) - continue from current location
  • x - examine memory (requires a format and an address)
  • backtrace (bt) - print the call stack from current position (What series of function calls made the program end up at this point?)
  • info - information about program structure (takes extra argument)
    • info proc map - information about memory areas in the running process (Where are the stack, heap, executable, libraries etc located in memory?)
    • info register - list registsrs and their contents
  • disassemble - list the assembler instructions of a function.

Sometimes the disassemble command does not work, especially if you execute code where you are not supposed to… It is possible to use the x command with the instruction format.

(gdb) disassemble  $rsp
No function contains specified address.
(gdb) x/5i $rsp
   0x7fffffffdd60:	add    %cl,0x55(%rdx)
   0x7fffffffdd63:	push   %rbp
   0x7fffffffdd64:	push   %rbp
   0x7fffffffdd65:	push   %rbp
   0x7fffffffdd66:	add    %al,(%rax)
(gdb)

Using ltrace can almost feel like cheating sometimes, in a good way.

Practical session

As an exercise, we wrote small programs that checked for a password and then took them apart.

Analyzing Lars' binary

Lars had written a small program, and the task was to find out what it did.

Analyzing binary 2

We made an assembler listing with objdump -d and commented it. Together we examined the instructions to find out what it did and what input it expected.

We also tried dynamic analysis:

$ ltrace ./easy  <<< asdfasdfasdf
read(0, "asdfas", 6)                                                = 6
strncat(0x7fffe1749030, 0x7fffe17490ca, 5, 0x7fffe17490ca)          = 0x7fffe1749030
popen("echo -n asdfa | md5sum", "r")                                = 0x5628600d9260
fgets("aa41efe0a1b3eeb9bf303e4561ff8392"..., 256, 0x5628600d9260)   = 0x7fffe17490d0
--- SIGCHLD (Child exited) ---
pclose(0x5628600d9260)                                              = 0
strncmp("aa41efe0a1b3eeb9bf303e4561ff8392"..., "8b1a9953c4611296a827abf8c47804d7"..., 32) = 41
puts("Fuck off!"Fuck off!
)                                                   = 10
+++ exited (status 0) +++

This gave the same result as the static analysis, just a bit quicker.

The program reads six bytes, calls popen() to compute the md5 checksum of the bytes and then compares the checksum to “8b1a9953c4611296a827abf8c47804d7”. This can be brute-forced, but even easier is to search for the hash and see that it is “Hello”.

There was also an uninteded solution. The binary used popen(), and it was possible to get the correct output by supplying a bogus version of md5sum:

$ ./easy <<< asdfasdfasdf
Fuck off!
$ ls -l md5sum
-rwxrwxr-x 1 larsh larsh 53 Sep  9 19:52 md5sum
$ cat md5sum
#!/bin/sh
echo "8b1a9953c4611296a827abf8c47804d7  -"
$ PATH=. ./easy <<< asdfasdfasdf
Access granted!
$

But this is a more advanced technique that we might cover more at another meeting.

Visual debuggers

We briefly looked at alternative debuggers.

For windows there is Ollydbg, there is also EDB but noone had used it. A visual debugger makes some patterns easier to spot, such as ASCII string pointer in registers.