Author Topic: GDB not copying desired string (For buffer overflow)  (Read 470 times)

0 Members and 1 Guest are viewing this topic.

Offline yasgur99

  • /dev/null
  • *
  • Posts: 10
  • Cookies: 2
    • View Profile
GDB not copying desired string (For buffer overflow)
« on: February 24, 2016, 11:55:48 pm »
Ok so I am trying to learn about buffer overflows and there is this simple program that is vulnerable of a BoF because it copies the first argument into a buffer of 5 characters. In the source code, there is a function called bar that never gets called by the program. My goal was to overflow the buffer and run that function.

So I loaded it up into gdb and I typed disass bar. the first few lines look like this:
Code: [Select]
(gdb) disas bar
Dump of assembler code for function bar:
   0x0000000000400988 <+0>: push   %rbp

So basically, all I have to do is put the address 0x00400988 into the end of the overflowed buffer. I calculated the return address to be 36 bytes past when I overflow the variable.

So in GDB i used the command set args $(perl -e 'print "A" x 36 . "\x88\x09\x40\x00"')

I set a breakpoint right after the strcpy was run and examined what 20 words of rsp looked like:
Code: [Select]
(gdb) x/40xw $rsp
0x7fffffffe240: 0xffffe358 0x00007fff 0x00000000 0x00000003
0x7fffffffe250: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffe260: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffe270: 0x41414141 0x00000088 0xf7a54b45 0x00007fff
0x7fffffffe280: 0x00000000 0x00000000 0xffffe358 0x00007fff

My issue is that the return address is not copying correctly. As you can see, it only copies the hex value 88 (and i guess the 00 in the beginning of the buffer.

This is what I have tried so far:

I have tried to recompile and check if it was an issue with the address being returned to.

I have tried to change the hex values of the address to random values and that seems to copy. For example, I tried to copy in the values 0x85af4709 into that location and it worked. In fact, I found out that the 09 in the original address is what is causing the issue. For example, I am able to make the address 0x00400788 but it cant be 0x00400988. (Another example is that I can't copy in the values 0xaaaa09aa because the 09 is in it)

That being said, I found out that 09 in ascii is a tab, which can be written as \t. Even if I did that, i got the original issue.

After that, I tried adjusting the amount of "A"s I would copy into the buffer to see if that did anyhting. it didnt.

I even tried to write the string out when typing run in gdb

Then, I googled this issue and found a really good example of exactly what i was trying to do. I used the sample program on page 32 of this article:
https://engineering.purdue.edu/kak/compsec/NewLectures/Lecture21.pdf

To my suprise, exactly what I was doing in my program worked exactly as I intended it to work in the authors sample program.

As a conclusion,
I was wondering if someone would be able to explain why that one position in the address can contain any hex value except the one I want to copy into it. In addition to that, I wan't to know how I can fix this.


If you would like any additional info id be more than happy to give it to you

« Last Edit: February 25, 2016, 12:48:45 am by yasgur99 »

Offline TheWormKill

  • EZ's Scripting Whore
  • Global Moderator
  • Knight
  • *
  • Posts: 257
  • Cookies: 66
  • The Grim Reaper of Worms
    • View Profile
Re: GDB not copying desired string (For buffer overflow)
« Reply #1 on: February 25, 2016, 12:26:40 am »
This is indeed very interesting. What I initially thought of is that your address contains null-bytes that make strcpy() break from the loop, but this doesn't seem the case. your program's source might be useful here, as it maybe contains some other details that interfere with this?

Also:
For example, I am able to make the address 0x00400788 but it cant be 0x00400788.
Those two are the same two addresses.

So, please post the source, look for typos in your adresses and maybe I will find sth and explain the issue to you (or you'll find it yourself :)).
Stuff I did: How to think like a superuser, Iridium

He should make that "Haskell"
Quote
<m0rph-is-gay> fuck you thewormkill you python coding mother fucker

Offline yasgur99

  • /dev/null
  • *
  • Posts: 10
  • Cookies: 2
    • View Profile
Re: GDB not copying desired string (For buffer overflow)
« Reply #2 on: February 25, 2016, 12:35:06 am »
This is indeed very interesting. What I initially thought of is that your address contains null-bytes that make strcpy() break from the loop, but this doesn't seem the case. your program's source might be useful here, as it maybe contains some other details that interfere with this?

Also:Those two are the same two addresses.

So, please post the source, look for typos in your adresses and maybe I will find sth and explain the issue to you (or you'll find it yourself :)).

My bad with those two addresses, I editd the orginal to say what I meant to say which is:
Code: [Select]
I am able to make the address 0x00400788 but it cant be 0x00400988.
The source code is: (This program is from the book Hacking: The Art of Exploitation and I added in the bar function from the link in my original post)

Code: [Select]
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
#include "hacking.h" //An Error Checked Malloc

#define FILENAME "/var/notes"

void fatal(char *);
int print_notes(int, int, char *);
int find_user_note(int, int);
int search_note(char *, char *);

void bar() {
printf("\n\nWhat? I was not supposed to be called!\n\n");
fflush(stdout);
}

int main(int argc, char *argv[]) {
int fd, userid, printing = 1;
char searchstring[5];

if (argc > 1)
strcpy(searchstring, argv[1]);
else
searchstring[0] = 0;

userid = getuid();

fd = open(FILENAME, O_RDONLY);
if(fd == -1) {
fatal("in main opening file");
}

while(printing)
printing = print_notes(fd, userid, searchstring);

printf("-------[ end of note data ]-------\n");
close(fd);
}


// A function to print the notes for a given uid that match an optional searchstring
// Returns 0 at end of file, 1 if still more notes
int print_notes(int fd, int uid, char *searchstring){

int note_length;
char byte = 0;
char note_buffer[100];

note_length = find_user_note(fd, uid);
if(note_length == -1) //If end of file reached
return 0;       // Return 0;

read(fd, note_buffer, note_length); // Read More Data
note_buffer[note_length] = 0;     // Terminate the String

if(search_note(note_buffer, searchstring)) //If searchstring found
printf(note_buffer); //Print the note
else

return 1;
}


// A function to find the next note for a given userID
// Returns -1 if the end of the file is reached
// Otherwise, it returns the length of the found note
int find_user_note(int fd, int user_uid) {

int note_uid = -1;
unsigned char byte;
int length;

while(note_uid != user_uid) { // Loop unitl a note for user_uid is found

if(read(fd, &note_uid, 4) != 4) // Read the uid data
return -1; // If 4 bytes arent read, return end of file code

if(read(fd, &byte, 1) != 1) //Read the newline separtor
return -1;

byte = length = 0;
while(byte != '\n') { // Figure out how many bytes to the end of line
if(read(fd, &byte, 1) != 1) // Read Single byte
return -1; // If byte isn't read, return end of file code
length++;
}
}

lseek(fd, length * -1, SEEK_CUR); // Rewind file by reading length bytes

printf("[DEBUG] found a %i byte note for user id %i\n", length, note_uid);
return length;
}

//A function to search a note for a given keyword
// Returns 1 if a match is found, 0 if there is no match
int search_note(char *note, char *keyword){

int i, keyword_length, match=0;

keyword_length = strlen(keyword);
if(keyword_length == 0) // If there is no searchstring
return 1; //Always match

for(i=0; i < strlen(note); i++){ // Iterate over bytes in note
if(note[i] == keyword[match]) // If byte matches keyword
match++; // Get ready to check next byte
else {
if(note[i] == keyword[match]) // If byte matches keyword
match = 1; // Start the match count at 1
else
match = 0; // Otherwise its zero
}

if(match == keyword_length) // If there is a full match
return 1; // return match
}
return 0; // return not matched

}


Offline TheWormKill

  • EZ's Scripting Whore
  • Global Moderator
  • Knight
  • *
  • Posts: 257
  • Cookies: 66
  • The Grim Reaper of Worms
    • View Profile
Re: GDB not copying desired string (For buffer overflow)
« Reply #3 on: February 25, 2016, 12:49:17 am »
Hm. I'm lost here, and I currently don't have time to try it myself. So I will enumerate some options you have:
1. investigate the source code of that particular version of strcpy(), and, if necessary, step through it in your debugger to find out what happens.
2. there is also a possible workaround: if there are nop's before the function you try to jump to, you might be able to decrease the address and jump before the function, alhough this would require fairly much space before the function in question, as we aren't talking of the LSB here, but a byte with higher significance.

So, Option 1 is your best bet. If you can't figure it out, I'll look into it myself tomorrow.
Stuff I did: How to think like a superuser, Iridium

He should make that "Haskell"
Quote
<m0rph-is-gay> fuck you thewormkill you python coding mother fucker

Offline yasgur99

  • /dev/null
  • *
  • Posts: 10
  • Cookies: 2
    • View Profile
Re: GDB not copying desired string (For buffer overflow)
« Reply #4 on: February 25, 2016, 01:14:28 am »
Hm. I'm lost here, and I currently don't have time to try it myself. So I will enumerate some options you have:
1. investigate the source code of that particular version of strcpy(), and, if necessary, step through it in your debugger to find out what happens.
2. there is also a possible workaround: if there are nop's before the function you try to jump to, you might be able to decrease the address and jump before the function, alhough this would require fairly much space before the function in question, as we aren't talking of the LSB here, but a byte with higher significance.

So, Option 1 is your best bet. If you can't figure it out, I'll look into it myself tomorrow.

I will definetly try and see what I can figure out. Thanks for the tips. I'm new to hacking so this should be a good challange.

One thing i did notice is that when i have the 09 in there, gdb sees the argc as 3 (even though it should be two). When it isn't 09 it sees the argc as two (which it should be.)  Taking that into consideration, my plan was to make that byte something that didn't trick the compiler into thinking there were three arguments.

I also tried running the program on a different computer and in this case 0a is in the same position and is causing the same issue (and causes gdb to see the argc as 3) ( this is becaus 0a is a line feed)

In order to make that byte non-detrimental, i went into the source code and moved the bar function to the bottom to see if i could get a much different memory address when i re-comiled. I did and it worked. I am now able to copy that memory address right where I want it.

but now i have a new issue:
So because I am on a 64 bit machine, memory address are double as long. that means that the actual memory address that needs to be in buffer is 0x0000000000400988. That means that I need to have 0x00000000 follow in memory. The issue is that I don't know how to add that because there was already a null byte in the previous memory address 0x00400988. Also, they are all null bytes. The next address in memory that needs to be the 0x00000000 is 0x00007fff.

 How can I make 0x00007fff 0x00000000 is my new issue
« Last Edit: February 25, 2016, 02:08:59 am by yasgur99 »