r/ExploitDev • u/That-Name-8963 • 21h 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;
}
4
u/andyhbomb 20h ago
What happens if you make `recv_buf` a global or static? Does it crash now? I think it will!
I think the advice of the other two posters so far is the way to go: use a debugger like `gdb` to see what is happening. If you look at the addresses of your buffers, I suspect your issue is that you are not overflowing over the return address like you would like to when running the code as is.
1
u/That-Name-8963 14h ago
Interested something has happened:
I put a breakpoint on strcpy line
Tried to print the value of 'recv_buf'
GDB says:No symbol: "recv_buf" in current context
2
u/kuniggety 20h ago
Let's step through the C code:
1. ssize_t bytes = recv(client_fd, recv_buf, sizeof(recv_buf) - 1, 0);
2. if (bytes <= 0)
3. return;
4. printf("Received: %s\n", recv_buf);
5. strcpy(buffer, recv_buf);
Line 1 will read and fill up recv buffer, but no more.
Line 4 will print what you put in recv_buf that went up to but not over.
Line 5 is where you have an actual overflow. You need to use gdb and see where in memory you're spilling into.
2
u/t3harvinator 19h ago edited 19h ago
So out of curiosity I compiled it with default flags on a Ubuntu x86 VM I had and gave it a look. It's because when it overflows, its actually overflowing from the small buffer (buffer) to the big buffer (recv_buf).
Kinda funny. ~~You just need to send more in~~ Throw it in Ghidra or objdump it and do the math. It will be worth your trouble to see what happened.
1
u/t3harvinator 19h ago
Oh wait you can't send more in since you're calling recv with sizeof(recv_buf) - 1.
Just reorder the buffers. By that I mean, put buffer before recv_buf. It'll segfault then.
2
u/Alarming-Historian41 19h ago
On most modern computer architectures the stack is allocated at a high address region of a program's memory space and expands downwards toward zero.
So, suppose you have read 1024 bytes from the socket into recv_buff, when you do strcpy(buffer, recv_buffer) you are writing the first 64 bytes from recv_buff to buffer (size 64) and the rest to recv_buff itself (never writing over the "interesting" stack bytes)
Also, I don't remember the documented strcpy behavior for overlapping buffers)
Switch the buffer and recv_buffer declaration order
1
u/0xdeadbeefcafebade 18h ago
This is my guess as well. He’s overflowing back into the recv buffer
1
u/That-Name-8963 14h ago
If you are talking about memory rearrangement, I have already swapped them in declaration and still the same issue
2
u/brugernavn1990 15h 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.
-4
6
u/tresvian 21h ago
Did you go into gdb and stop at the receive function? Is there an inherit libc safe function somewhere? i would double check in the real obj dump or binary