You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Linux缓冲区溢出测试中无法覆盖EIP寄存器的问题

背景

我正在Linux环境下创建一个带缓冲区溢出漏洞的应用程序,用于练习漏洞的创建与利用,但目前遇到了瓶颈。

问题描述

尽管输入了约1000个"A"字符,我仍无法覆盖EIP寄存器,程序超出缓冲区限制后也不会崩溃。
代码逻辑是先输入验证码(非易受攻击字段),再请求用户输入邮箱(无验证,为易受攻击字段)。

目标

能够对上述代码进行缓冲区溢出利用,尽可能少地修改其验证合法用户的逻辑(先验证码后邮箱)。

代码

源代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>

#define PORT 6000
#define BUFFER_SIZE 256
#define CODE "xxxxxxxxxxx"

void handle_client(int client_socket) {
    char buffer[BUFFER_SIZE];
    char email[64];

    send(client_socket, "Ingrese el código: ", 19, 0);
    recv(client_socket, buffer, BUFFER_SIZE, 0);

    if (strncmp(buffer, CODE, strlen(CODE)) == 0) {
        send(client_socket, "Código correcto. Ingrese su correo: ", 36, 0);
        recv(client_socket, email, 256, 0);
        scanf("%s", email);
        printf("Correo recibido: %s\n", email);
    } else {
        send(client_socket, "Código incorrecto.\n", 19, 0);
    }

    close(client_socket);
}

int main() {
    int server_socket, client_socket;
    struct sockaddr_in server_addr, client_addr;
    socklen_t addr_size;

    server_socket = socket(AF_INET, SOCK_STREAM, 0);
    if (server_socket < 0) {
        perror("Error al crear el socket");
        exit(1);
    }

    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(PORT);
    server_addr.sin_addr.s_addr = INADDR_ANY;

    if (bind(server_socket, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) {
        perror("Error al enlazar el socket");
        close(server_socket);
        exit(1);
    }

    if (listen(server_socket, 5) < 0) {
        perror("Error al escuchar en el socket");
        close(server_socket);
        exit(1);
    }
    printf("Servidor escuchando en el puerto %d\n", PORT);

    while (1) {
        addr_size = sizeof(client_addr);
        client_socket = accept(server_socket, (struct sockaddr*)&client_addr, &addr_size);
        if (client_socket < 0) {
            perror("Error al aceptar la conexión");
            continue;
        }
        printf("Conexión recibida de %s:%d\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
        handle_client(client_socket);
    }

    close(server_socket);
    return 0;
}

编译命令

gcc -m32 -fno-stack-protector source.c -o server -z execstack
实际表现

目前我用GDB调试,输入payload后的寄存器输出如下:

gdb-peda$ info registers
eax            0x100               0x100
ecx            0xffffcd20          0xffffcd20
edx            0x100               0x100
ebx            0x4                 0x4
esp            0xffffccb8          0xffffccb8
ebp            0x0                 0x0
esi            0x0                 0x0
edi            0x0                 0x0
eip            0xf7fc657b          0xf7fc657b <__kernel_vsyscall+11>
eflags         0x246               [ PF ZF IF ]
cs             0x23                0x23
ss             0x2b                0x2b
ds             0x2b                0x2b
es             0x2b                0x2b
fs             0x0                 0x0
gs             0x63                0x63

我认为EIP寄存器应该变为0x41414141,但实际并非如此。

排查过程

我尝试了多种方法,大部分代码由ChatGPT生成(手动编写耗时太长)。
我尝试过以下函数,均无效:

  • gets(编译报错)
  • strcpy
  • scanf(当前使用的函数)
  • strcmp

我还试过编写Windows环境下的代码,用Wine运行,但无法为程序禁用DEP(数据执行保护),导致无法调试。
目前我认为问题出在代码逻辑,而非所用函数或执行方式。

额外疑问

能否通过哈希验证码并对比输入哈希值来进行验证?这种方式会被Ghidra等逆向工具破解吗?

补充信息

2024年10月7日 欧洲中部夏令时 20:35:56

我添加ESP寄存器结果以及提交payload时的GDB输出。
能看到payload,但EIP未被修改。

GDB断点输出

[----------------------------------registers-----------------------------------]
EAX: 0x100 
EBX: 0x56558ff4 --> 0x3ef0 
ECX: 0xffffcd20 ('A' <repeats 200 times>...)
EDX: 0x0 
ESI: 0xd8fe 
EDI: 0xf7ffcb60 --> 0x0 
EBP: 0xffffce68 --> 0xffffcec8 --> 0x0 
ESP: 0xffffcd20 ('A' <repeats 200 times>...)
EIP: 0x565562ef (<handle_client+146>:   sub    esp,0x8)
EFLAGS: 0x282 (carry parity adjust zero SIGN trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
   0x565562e4 <handle_client+135>:  push   DWORD PTR [ebp+0x8]
   0x565562e7 <handle_client+138>:  call   0x56556100 <recv@plt>
   0x565562ec <handle_client+143>:  add    esp,0x10
=> 0x565562ef <handle_client+146>:  sub    esp,0x8
   0x565562f2 <handle_client+149>:  lea    eax,[ebp-0x148]
   0x565562f8 <handle_client+155>:  push   eax
   0x565562f9 <handle_client+156>:  lea    eax,[ebx-0x1f9a]
   0x565562ff <handle_client+162>:  push   eax
[------------------------------------stack-------------------------------------]
0000| 0xffffcd20 ('A' <repeats 200 times>...)
0004| 0xffffcd24 ('A' <repeats 200 times>...)
0008| 0xffffcd28 ('A' <repeats 200 times>...)
0012| 0xffffcd2c ('A' <repeats 200 times>...)
0016| 0xffffcd30 ('A' <repeats 200 times>...)
0020| 0xffffcd34 ('A' <repeats 200 times>...)
0024| 0xffffcd38 ('A' <repeats 200 times>...)
0028| 0xffffcd3c ('A' <repeats 200 times>...)
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
0x565562ef in handle_client ()

ESP寄存器输出(命令:x/100x $esp)

0xffffcd20: 0x41    0x41    0x41    0x41    0x41    0x41    0x41    0x41
0xffffcd28: 0x41    0x41    0x41    0x41    0x41    0x41    0x41    0x41
0xffffcd30: 0x41    0x41    0x41    0x41    0x41    0x41    0x41    0x41
0xffffcd38: 0x41    0x41    0x41    0x41    0x41    0x41    0x41    0x41
0xffffcd40: 0x41    0x41    0x41    0x41    0x41    0x41    0x41    0x41
0xffffcd48: 0x41    0x41    0x41    0x41    0x41    0x41    0x41    0x41
0xffffcd50: 0x41    0x41    0x41    0x41    0x41    0x41    0x41    0x41
0xffffcd58: 0x41    0x41    0x41    0x41    0x41    0x41    0x41    0x41
0xffffcd60: 0x41    0x41    0x41    0x41    0x41    0x41    0x41    0x41
0xffffcd68: 0x41    0x41    0x41    0x41    0x41    0x41    0x41    0x41
0xffffcd70: 0x41    0x41    0x41    0x41    0x41    0x41    0x41    0x41
0xffffcd78: 0x41    0x41    0x41    0x41    0x41    0x41    0x41    0x41
0xffffcd80: 0x41    0x41    0x41    0x41

2024年10月7日 欧洲中部夏令时 22:11:21

正如dbush所说,buffer可能在栈上位于email之后,验证后确实如此。

编译命令

gcc -g -m32 -fno-stack-protector testlin.c -o server -z execstack

变量内存地址

gdb-peda$ print &buffer
$1 = (char (*)[256]) 0xffffcd50
gdb-peda$ print &email
$2 = (char (*)[64]) 0xffffcd10

栈视图

gdb-peda$ x/100xb 0xffffcd10
0xffffcd10: 0x61    0x73    0x64    0x61    0x73    0x64    0x0a    0x35
0xffffcd18: 0x39    0x34    0x33    0x38    0x80    0xcd    0xff    0xff
0xffffcd20: 0x1b    0x71    0x55    0x56    0x2c    0xce    0xf8    0xf7
0xffffcd28: 0xb8    0xce    0xff    0xff    0xac    0x6c    0xdb    0xf7
0xffffcd30: 0x26    0x00    0x00    0x00    0x00    0x00    0x00    0x00
0xffffcd38: 0xb8    0xce    0xff    0xff    0x80    0xcd    0xff    0xff
0xffffcd40: 0x1b    0x71    0x55    0x56    0x2c    0xce    0xf8    0xf7
0xffffcd48: 0xb8    0xce    0xff    0xff    0x42    0x1b    0xdc    0xf7
0xffffcd50: 0x62    0x70    0x68    0x79    0x73    0x75    0x75    0x78
0xffffcd58: 0x73    0x72    0x6e    0x6b    0x71    0x74    0x75    0x70
0xffffcd60: 0x66    0x77    0x63    0x79    0x0a    0x00    0x00    0x00
0xffffcd68: 0x64    0xce    0xff    0xff    0x98    0xcd    0xff    0xff
0xffffcd70: 0xe4    0xcf    0xff    0xf7

内容的提问来源于stack exchange,提问作者jefrey hernandez rodriguez

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 14:04:52