内存泄漏演示问题

时间:2015-01-25 21:47:23

标签: c sockets security memory demo

我正在尝试创建一个程序来演示如何发生像heartbleed这样的问题。这就是我到目前为止所做的:

#include <stdio.h>
#include <sys/socket.h>
#include <strings.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <signal.h>
#include <string.h>
#include <stdlib.h>

#define LPORT 5555
#define ACCEPT_QUEUE_SIZE 10

typedef struct sockaddr_in sockaddr_in;
typedef struct sockaddr sockaddr;

const char *login_msg = "=== Welcome to super secure admin control panel! ===\nPlease enter the password:";
const char *login_len_msg = "\nPlease enter the length of the password you entered: ";
const char *incorrect_password_msg = "\nACCESS DENIED USING PASSWORD: ";
const char *correct_password_msg = "\nACCESS GRANTED.\n";


int sockfd = 0;
sockaddr_in serv_addr;
void connection_handler(int connfd, const char *secret_password, char *client_address) {
    pid_t my_pid = fork();
    if (my_pid < 0) {
        fprintf(stderr, "[!] Failed to fork a new process for connection handler\n");
        exit(EXIT_FAILURE);
    }
    if (my_pid == 0) {
    if (1) {
        send(connfd, login_msg, strlen(login_msg), 0);
        char user_resp[51], secret_key[10];
        char user_resp_len_msg[6];
        int user_resp_len = 0;
        bzero(&user_resp, sizeof(user_resp));
        bzero(&user_resp_len_msg, sizeof(user_resp_len_msg));
        recv(connfd, &user_resp, 50, 0);
        fprintf(stderr, "[*] Client %s sent password %s\n", client_address, user_resp);
        send(connfd, login_len_msg, strlen(login_len_msg), 0);
        recv(connfd, &user_resp_len_msg, 5, 0);
        fprintf(stderr, "[*] Client %s sent password length string %s\n", client_address, user_resp_len_msg);
        sscanf(user_resp_len_msg, "%d\n", &user_resp_len);
        if (strncmp(secret_password, user_resp, strlen(secret_password)) == 0) {
            fprintf(stderr, "[+] %s successfully completed the challenge\n", client_address);
            send(connfd, correct_password_msg, strlen(correct_password_msg), 0);
        }
        else {
            send(connfd, incorrect_password_msg, strlen(incorrect_password_msg), 0);
            send(connfd, user_resp, user_resp_len, 0);
        }
        close(connfd);
        exit(EXIT_SUCCESS);
    }
}

void interrupt_handler(int signum) {
    fprintf(stderr, "[*] Caught interrupt signal, dying\n");
    close(sockfd);
    exit(EXIT_SUCCESS);
}

int main(int argc, const char * argv[]) {
    if (argc != 2) {
        fprintf(stderr, "[!] Usage: %s [server password]\n", argv[0]);
        exit(EXIT_FAILURE);
    }

    setpgrp();
    signal(SIGHUP, SIG_IGN);
    signal(SIGINT, interrupt_handler);

    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
        fprintf(stderr, "[!] Failed fo create socket\n");
        exit(EXIT_FAILURE);
    }

    int optval = 1;
    if( setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) != 0) {
        fprintf(stderr, "[!] Failed to set SO_REUSEADDR option on socket\n");
        exit(EXIT_FAILURE);
    }

    bzero(&serv_addr, sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_addr.s_addr = INADDR_ANY;
    serv_addr.sin_port = htons(LPORT);

    if (bind(sockfd, (sockaddr*)&serv_addr, sizeof(serv_addr)) != 0) {
        fprintf(stderr, "[!] Failed to bind to port %d\n", LPORT);
        exit(EXIT_FAILURE);
    }

    if (listen(sockfd, ACCEPT_QUEUE_SIZE) != 0) {
        fprintf(stderr, "[!] Failed to listen on port %d with queue size %d\n", LPORT, ACCEPT_QUEUE_SIZE);
        exit(EXIT_FAILURE);
    }

    sockaddr_in client_addr;
    socklen_t client_addr_len = sizeof(client_addr);
    char client_addr_str[INET_ADDRSTRLEN];
    while (1) {
        bzero(&client_addr, sizeof(client_addr));
        bzero(&client_addr_str, sizeof(client_addr_str));
        int connfd = accept(sockfd, (sockaddr*)&client_addr, &client_addr_len);
        inet_ntop(AF_INET, &client_addr.sin_addr.s_addr, client_addr_str, client_addr_len);
        fprintf(stderr, "[*] Got new connection from %s\n", client_addr_str);
        connection_handler(connfd, argv[1], client_addr_str);
    }

    return 0;
}

它以./program [password]运行。在OSX上,我注意到argv泄露了,所以我决定密码应该去的地方。但是,当我在ubuntu上测试时,情况并非如此。有没有一种简单的方法可以确保内存的相邻部分中存在两个缓冲区?

我认识到预测未定义的行为非常困难,并且可能没有简单的答案。

0 个答案:

没有答案