How it works...

 In step 1, we examine the stack, and this time, the last command we issue is the print command, which converts the hexadecimal value into a decimal value and stores it in a temporary variable. Remember that Little Endian matters here, so we need to reverse the byte order of the last command. Also note that esp contains the 0x080480f8 address, which is the address of our <portnum> label containing the bytes, 0x5c11. In JMP, CALL a series of instructions. The instruction immediately following the CALL instruction is automatically pushed onto the stack. As you can see here, esp is essentially pointing to the value 4444. Remember our static analysis phase and how poorly objdump handled these bytes? GDB is doing a better job, but if you review the disassembly window in the middle of our Terminal, you'll see even GDB disassembles those bytes poorly. Using the GDB commands during dynamic analysis is the only thing that really gave us valuable information about those bytes. Always take the extra step of manually interrogating the binary we're analyzing. The result of running the commands from step 1 is as follows:

In step 2, we use nexti to execute the pop esi command and then we review the general-purpose registers. We continue issuing the nexti command in step 3, stopping before the next interrupt procedure is executed. We should recognize that the general-purpose registers have been set up for the bind system call. We can confirm this by reviewing the stack, as instructed in step 4, where we notice the 0xbffff00c address:

Examining this address with the second command in step 4 shows us that it points to the location of 0x5c110002 on the stack:

So, why does this matter? Recall from the man page that bind takes three parameters. The first parameter it takes is socketfd, which, when we reexamine the stack, is 0x00000003. The second parameter is a structure containing the socket family (AF_INET (2)), the port, and IP address, while the third parameter is the size in bytes of the address structure.

We repeat this process of issuing the nexti command until right before the interrupt procedure is executed for each remaining block of code. For example, the disassembled instructions for the <listener> block of code are as follows:

Examining the general-purpose registers gives us the following output. Notice that ebx is set up for 0x4 (4), which is the listen system call for our socket:

ecx points to the stack, which contains the parameters for making the listen system call. The listen system call takes two parameters, which are socketfd (0x00000003) and backlog (0x00000001), as shown in the first two values of the output:

Continuing the nexti process for the next block of code, we can see the disassembled instructions, as follows:

The general-purpose registers have been set up for the accept system call, as we can see in the following screenshot. ebx contains the value 0x5eax is set up for the socketcall system call, and ecx contains an address that points to the top of the stack:

Examining the stack once again, we see the following output. The accept system call takes four parameters, of which the first one is the most important because it's the socketfd value that's was returned by creating the socket earlier:

We pause here to issue a netcat command in another Terminal session so that we can continue to dynamically analyze this binary. Return to GDB and continue execution with the nexti instruction until right before the next interrupt procedure is executed. The block of code that follows looks like this in the disassembly window:

If we review the general-purpose registers, they should resemble the following:

A quick lookup of the 0x11 value on the system call table shows us this is the value for execve. A quick review of execve tells us that it takes three parameters, all of which are pointers. The ebx and ecx registers all contain addresses. The third parameter is a null byte that's stored in edx because we're not passing any environment variables to execve. The man page specifically states that this last parameter must be terminated by a null pointer. A null byte works just fine in this case.

Then, we examine the stack to see whether it provides any useful information. We expand how deep into the stack we search to make sure to we get as much information as possible. We convert any hexadecimal we find into strings using the x/10s command and we see what we expected. The /bin////bash and -i values are both present on the stack:

At this point, the execve system call may fail and crash GDB and netcat, but that's is fine. We've seen enough. If GDB didn't crash, step 7 and step 8 provide us the path to quit and exit GDB. Excellent—if you've made it this far, you're doing well. If there are concepts we've covered that you still don't understand about GDB, go back through this recipe from the beginning.

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

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