1

I've been working on the bufbomb lab from CSAPPS and I've gotten stuck on one of the phases.

I won't get into the gore-y details of the project since I just need a nudge in the right direction. I'm having a hard time finding the starting address of the array called "buf" in the given assembly.

We're given a function called getbuf:

#define NORMAL_BUFFER_SIZE 32

int getbuf()
{
   char buf[NORMAL_BUFFER_SIZE];
   Gets(buf);
   return 1;
}

And the assembly dumps:

Dump of assembler code for function getbuf:
0x08048d92 <+0>:    sub    $0x3c,%esp
0x08048d95 <+3>:    lea    0x10(%esp),%eax
0x08048d99 <+7>:    mov    %eax,(%esp)
0x08048d9c <+10>:    call   0x8048c66 <Gets>
0x08048da1 <+15>:    mov    $0x1,%eax
0x08048da6 <+20>:    add    $0x3c,%esp
0x08048da9 <+23>:    ret   
End of assembler dump.


Dump of assembler code for function Gets:
0x08048c66 <+0>:    push   %ebp
0x08048c67 <+1>:    push   %edi
0x08048c68 <+2>:    push   %esi
0x08048c69 <+3>:    push   %ebx
0x08048c6a <+4>:    sub    $0x1c,%esp
0x08048c6d <+7>:    mov    0x30(%esp),%esi
0x08048c71 <+11>:    movl   $0x0,0x804e100
0x08048c7b <+21>:    mov    %esi,%ebx
0x08048c7d <+23>:    jmp    0x8048ccf <Gets+105>
0x08048c7f <+25>:    mov    %eax,%ebp
0x08048c81 <+27>:    mov    %al,(%ebx)
0x08048c83 <+29>:    add    $0x1,%ebx
0x08048c86 <+32>:    mov    0x804e100,%eax
0x08048c8b <+37>:    cmp    $0x3ff,%eax
0x08048c90 <+42>:    jg     0x8048ccf <Gets+105>
0x08048c92 <+44>:    lea    (%eax,%eax,2),%edx
0x08048c95 <+47>:    mov    %ebp,%ecx
0x08048c97 <+49>:    sar    $0x4,%cl
0x08048c9a <+52>:    mov    %ecx,%edi
0x08048c9c <+54>:    and    $0xf,%edi
0x08048c9f <+57>:    movzbl 0x804a478(%edi),%edi
0x08048ca6 <+64>:    mov    %edi,%ecx
---Type <return> to continue, or q <return> to quit---
0x08048ca8 <+66>:    mov    %cl,0x804e140(%edx)
0x08048cae <+72>:    mov    %ebp,%ecx
0x08048cb0 <+74>:    and    $0xf,%ecx
0x08048cb3 <+77>:    movzbl 0x804a478(%ecx),%ecx
0x08048cba <+84>:    mov    %cl,0x804e141(%edx)
0x08048cc0 <+90>:    movb   $0x20,0x804e142(%edx)
0x08048cc7 <+97>:    add    $0x1,%eax
0x08048cca <+100>:    mov    %eax,0x804e100
0x08048ccf <+105>:    mov    0x804e110,%eax
0x08048cd4 <+110>:    mov    %eax,(%esp)
0x08048cd7 <+113>:    call   0x8048820 <_IO_getc@plt>
0x08048cdc <+118>:    cmp    $0xffffffff,%eax
0x08048cdf <+121>:    je     0x8048ce6 <Gets+128>
0x08048ce1 <+123>:    cmp    $0xa,%eax
0x08048ce4 <+126>:    jne    0x8048c7f <Gets+25>
0x08048ce6 <+128>:    movb   $0x0,(%ebx)
0x08048ce9 <+131>:    mov    0x804e100,%eax
0x08048cee <+136>:    movb   $0x0,0x804e140(%eax,%eax,2)
0x08048cf6 <+144>:    mov    %esi,%eax
0x08048cf8 <+146>:    add    $0x1c,%esp
0x08048cfb <+149>:    pop    %ebx
0x08048cfc <+150>:    pop    %esi
0x08048cfd <+151>:    pop    %edi
---Type <return> to continue, or q <return> to quit---
0x08048cfe <+152>:    pop    %ebp
0x08048cff <+153>:    ret   
End of assembler dump.

I'm having a difficult time locating where the starting address of buf is (or where buf is at all in this mess!). If someone could point that out to me, I'd greatly appreciate it.

Attempt at a solution

Reading symbols from /home/user/CS247/buflab/buflab-handout/bufbomb...(no debugging symbols found)...done.
(gdb) break getbuf
Breakpoint 1 at 0x8048d92
(gdb) run -u user < firecracker-exploit.bin
Starting program: /home/user/CS247/buflab/buflab-handout/bufbomb -u user < firecracker-exploit.bin
Userid: ...
Cookie: ...

Breakpoint 1, 0x08048d92 in getbuf ()
(gdb) print buf
No symbol table is loaded.  Use the "file" command.
(gdb) 

4 Answers 4

2

As has been pointed out by some other people, buf is allocated on the stack at run time. See these lines in the getbuf() function:

0x08048d92 <+0>:    sub    $0x3c,%esp
0x08048d95 <+3>:    lea    0x10(%esp),%eax
0x08048d99 <+7>:    mov    %eax,(%esp)

The first line subtracts 0x3c (60) bytes from the stack pointer, effectively allocating that much space. The extra bytes beyond 32 are probably for parameters for Gets (Its hard to tell what the calling convention is for Gets is precisely, so its hard to say) The second line gets the address of the 16 bytes up. This leaves 44 bytes above it that are unallocated. The third line puts that address onto the stack for probably for the gets function call. (remember the stack grows down, so the stack pointer will be pointing at the last item on the stack). I am not sure why the compiler generated such strange offsets (60 bytes and then 44) but there is probably a good reason. If I figure it out I will update here.

Inside the gets function we have the following lines:

0x08048c66 <+0>:    push   %ebp
0x08048c67 <+1>:    push   %edi
0x08048c68 <+2>:    push   %esi
0x08048c69 <+3>:    push   %ebx
0x08048c6a <+4>:    sub    $0x1c,%esp
0x08048c6d <+7>:    mov    0x30(%esp),%esi

Here we see that we save the state of some of the registers, which add up to 16-bytes, and then Gets reserves 28 (0x1c) bytes on the stack. The last line is key: It grabs the value at 0x30 bytes up the stack and loads it into %esi. This value is the address of buf put on the stack by getbuf. Why? 4 for the return addres plus 16 for the registers+28 reserved = 48. 0x30 = 48, so it is grabbing the last item placed on the stack by getbuf() before calling gets.

To get the address of buf you have to actually run the program in the debugger because the address will probably be different everytime you run the program, or even call the function for that matter. You can set a break point at any of these lines above and either dump the %eax register when the it contains the address to be placed on the stack on the second line of getbuf, or dump the %esi register when it is pulled off of the stack. This will be the pointer to your buffer.

Sign up to request clarification or add additional context in comments.

2 Comments

Thank you so much! I really appreciate you going through the logic of how you came to your conclusion -- it'll help me out a lot when working the next two phases of the assignment.
Not a problem. Comment if you have further questions.
0

to be able to see debugging info while using gdb,you must use the -g3 switch with gcc when you compile.see man gcc for more details on the -g switch. Only then, gcc will add debugging info (symbol table) into the executable.

Comments

0
0x08048cd4 <+110>:    mov    %eax,(%esp)
0x08048cd7 <+113>:    **call   0x8048820 <_IO_getc@plt>**
0x08048cdc <+118>:    cmp    $0xffffffff,%eax
0x0848cdf <+121>:    je     0x8048ce6 <Gets+128>
0x08048ce1 <+123>:    cmp    $0xa,%eax
0x08048ce4 <+126>:    jne    0x8048c7f <Gets+25>
0x08048ce6 <+128>:    movb   $0x0,(%ebx)
0x08048ce9 <+131>:    mov    0x804e100,%eax
0x08048cee <+136>:    movb   $0x0,0x804e140(%eax,%eax,2)
0x08048cf6 <+144>:    mov    %esi,%eax
0x08048cf8 <+146>:    add    $0x1c,%esp
0x08048cfb <+149>:    **pop    %ebx**
0x08048cfc <+150>:    **pop    %esi**
0x08048cfd <+151>:    **pop    %edi**
---Type <return> to continue, or q <return> to quit---
0x08048cfe <+152>:    **pop    %ebp**
0x08048cff <+153>:    ret   
End of assembler dump.

I Don't know your flavour of asm but there's a call in there which may use the start address

The end of the program pops various pointers

That's where I'd start looking

If you can tweak the asm for these functions you can input your own routines to dump data as the function runs and before those pointers get popped

Comments

0

buf is allocated on the stack. Therefore, you will not be able to spot its address from an assembly listing. In other words, buf is allocated (and its address therefore known) only when you enter the function getbuf() at runtime.

If you must know the address, one option would be to use gbd (but make sure you compile with the -g flag to enable debugging support) and then:

gdb a.out    # I'm assuming your binary is a.out
break getbuf # Set a breakpoint where you want gdb to stop
run          # Run the program. Supply args if you need to
             # WAIT FOR your program to reach getbuf and stop    
print buf

If you want to go this route, a good gdb tutorial (example) is essential. You could also place a printf inside getbuf and debug that way - it depends on what you are trying to do.

One other point leaps out from your code. Upon return from getbuf, the result of Gets will be trashed. This is because Gets is presumably writing its results into the stack-allocated buf. When you return from getbuf, your stack is blown and you cannot reliably access buf.

5 Comments

I've tried this, and I got "No symbol table loaded. Use the "file" command" from GDB (and yes, the file is open and running in GDB when I do this). *Sidenote: That weird behavior you mentioned is intentional. The whole point of the assignment is to inject exploit code to make the program jump around a bit to get past those redundant lines of code.
Did exactly that, but I'm still getting that message. I updated my original post to show my attempt.
You haven't compiled your program with debugging symbols. If you are compiling using gcc, make sure you are using the -g option. How do you compile the code?
We are given the complied program. The whole point of the assignment, again, is to mess around with the program without actually having much information. I'm not new to GDB, I'm just lost at how to find the array. I'm not sure what registers to look in to trace down where the array starts.
Ahh - I wish you'd said in the original post that you were given the compiled program. This looks like homework or some other assignment ... Look at the excellent answer given by @Dougvj and you should be able to figure it out.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.