How it works...

Step 1 begins by displaying the help menu for ltrace, followed by step 2, which opens a new Terminal tab and displays the man page within that new tab. In step 3, we open a third Terminal tab and run the ltrace tool with its default options against our example binary. The output doesn't give us much information because we didn't submit any command-line arguments to the example binary. The following is the result of running the command on the 64-bit Ubuntu virtual machine:

The only thing we see is the call to __libc_start_main() and the printf() function call. Next, in step 4, we run ltrace against the example binary again, only this time, we issue two command-line arguments, that is, the blah and blah strings, since we're unsure of the correct arguments to pass. As you may recall from the Using strings recipe earlier in this chapter, we saw possible values in the output from that tool. Here's the output for step 4 when it is ran on the 64-bit Ubuntu virtual machine:

One important piece of information to notice is that, since we've provided two arguments to this example program, we've bypassed the initial logic checking to see if the program was run with two command-line arguments. Since it was, we can see many more function calls taking place. One of particular interest is the line that reads strcmp("blah", "rot13"). This tells us that the string comparison function is used, and clearly it will fail since we didn't provide the correct string for one or both of the arguments. In step 5, we issue the -T argument, which tells ltrace to show us the amount of time that passed inside each call, and the -x main argument, which tells ltrace to trace specific static functions. In our case, we tell it to trace the main function. We also pass rot13 as the first command-line argument to our binary, which produces the following results on the 64-bit Ubuntu virtual machine:

Can you see a difference in this output compared to the last? It appears that by changing the first command-line argument to rot13, we've passed the first strcmp() check and see a second check along with a call to puts(), indicating that we've failed the second strcmp() check. We also see the expected value to this second check and can run ltrace again using this value as the second argument to the binary. In step 6, we do just that, but with some added arguments to ltrace. We're already familiar with the -T argument. The -r argument tells ltrace to use relative timestamps in its output, and the -c argument displays a nice summary of how many times functions or libraries are called and the amount of time spent on each. We also pass the correct two strings as arguments to our program to get the full functionality from our example binary:

Another useful set of arguments are highlighted in step 7. Instead of printing out a summary of the time and number of calls that were made within our binary, we issue the -f and -i arguments, which trace any child processes that were created and displays the instruction pointer address at the time of the call, respectively. The -i argument is especially useful if we wish to see the address of RIP/EIP at the time of the call. We'll perform similar functionality using a debugger during dynamic analysis.

In step 8, we move on to the strace tool, open up a new Terminal tab, and issue a command to provide us with the help menu. Step 9 opens a new Terminal tab, and then we issue a command to display the man page for strace, which gives us in-depth explanations for each of the arguments that's available for this tool, along with explanations for the meaning of some of the output. Step 10 begins by opening a new Terminal tab and running strace against our binary using the default output, which resembles the following on the 64-bit Ubuntu virtual machine:

This output, though not formatted as cleanly as some of us would like it, provides a great amount of information about the system calls that are used by the example program. We can see a call to execve() at the start, and several calls to mmap()open(), and read() within the output. We can always refer to the man page for the specific system call if we are unsure about its purpose or functionality. In step 11, we issue the strace command using the -r, -i, -T, -C arguments, which tell strace to show us a relative timestamp (-r), the address of the instruction pointer when the system call is made (-i), and how much time is spent on each system call (-T). We tell strace to print out a summary of the system calls, along with the typical output that's expected when using the other arguments we passed on the command line. Notice that we run this twice: once with arguments to the example program we know won't work, and once with the proper arguments to the example program. It's a good idea to identify any differences between the two. The final command we issue in step 12 uses the -f argument in addition to the -i argument, which tells strace we want to see, follow, and fork from the parent process (-f), and still want to see the instruction pointer for each system call. If a binary we're analyzing ever spawns child processes, the -f argument will help us follow those new child processes as they are created by system calls with that functionality.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.189.14.219