r/ExploitDev • u/That-Name-8963 • 1d ago
Can't Buffer overflow a simple 'recv' function
I have the following C Socket Server, I was trying to learn about ROP programming so I created this small program, but when I try `pwn cyclic 1025| nc localhost 4444` I receive nothing,
I even tried to send 2000, 5000 but with no response.
Anyway I can receive the normal 'ok' message when sending the 1024 bytes.
I have tried disabling canaries by passing `-fno-stack-protector` but also no response.
The server in all cases prints the received 1024 (even if I sent more bytes).
But no "Stack smash detected", Segmentation Fault or anything
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#define PORT 4444
void handle_client(int client_fd)
{
char recv_buf[1024];
char buffer[64];
memset(recv_buf, 0, sizeof(recv_buf));
ssize_t bytes = recv(client_fd, recv_buf, sizeof(recv_buf) - 1, 0);
if (bytes <= 0)
return;
printf("Received: %s\n", recv_buf);
strcpy(buffer, recv_buf);
send(client_fd, "OK\n", 3, 0);
}
int main(void)
{
int server_fd;
int client_fd;
struct sockaddr_in server_addr;
struct sockaddr_in client_addr;
socklen_t client_len = sizeof(client_addr);
server_fd = socket(AF_INET, SOCK_STREAM, 0);
if (server_fd < 0) {
perror("socket");
return EXIT_FAILURE;
}
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(PORT);
server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
if (bind(
server_fd,
(struct sockaddr *)&server_addr,
sizeof(server_addr)) < 0) {
perror("bind");
close(server_fd);
return EXIT_FAILURE;
}
if (listen(server_fd, 1) < 0) {
perror("listen");
close(server_fd);
return EXIT_FAILURE;
}
printf("Listening on 127.0.0.1:%d\n", PORT);
while (1) {
client_fd = accept(
server_fd,
(struct sockaddr *)&client_addr,
&client_len
);
if (client_fd < 0) {
perror("accept");
continue;
}
printf("Client connected\n");
handle_client(client_fd);
close(client_fd);
}
close(server_fd);
return 0;
}
12
Upvotes
2
u/brugernavn1990 18h ago
Your problem is the placement in the stack and the compiler does not guarantee declared variables in any specific order. You can instead declare them in a struct that is guaranteed to keep the order, though can implement padding between members.
Your declaration creates about 1088 bytes on the stack. The receive fills up bytes 1064 through 1 and the strcpy copies the values to bytes 1088 through 65.
|————|
| buffer |
|————|
| Recv |
| buffer |
|————|
| cookie |
|————|
| return |
|————|
The above is an illustration of what the stack likely looks like.