1

Assuming we have a vulnerable c program and we found a buffer overflow vulnerability on the program and created an exploit on that. Can the same exploit be executed if the vulnerable c program runs on a different machine? Will memory addresses be the same?

I think the answer is no they probably won´t even be the same when running only in the same environment and on the same machine. There is nothing like a guarantee that it will have the same address.

A modern-day OS assigns the memory arbitrarily (within certain sections of course). This technique is called Address Space Layout Randomization

Hence, my final question that can't explain based on this video is how geohot manage to exploit a buffer overflow attack remotely if addresses would not the same. He first did it locally and then remotely. How does he manage to achieve it?

Here is an example of a server that executes strcpy(buffer2, buffer); and i expect to give a segmentation fault.

    #include <netinet/in.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <sys/socket.h>
    #include <unistd.h>
    #define PORT 1337
   int main(int argc, char const* argv[])
{
       int server_fd, new_socket, valread;
       struct sockaddr_in address;
       int opt = 1;
       int addrlen = sizeof(address);
       static char buffer[1024] = { 0 };
       char buffer2[8] = { 0 };
       char* hello = "Hello from server";

       // Creating socket file descriptor
       if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
               perror("socket failed");
               exit(EXIT_FAILURE);
       }

       // Forcefully attaching socket to port 8080
       if (setsockopt(server_fd, SOL_SOCKET,
                               SO_REUSEADDR | SO_REUSEPORT, &opt,
                               sizeof(opt))) {
               perror("setsockopt");
               exit(EXIT_FAILURE);
       }
       address.sin_family = AF_INET;
       address.sin_addr.s_addr = INADDR_ANY;
       address.sin_port = htons(PORT);

       // Forcefully attaching socket to port 8080
       if (bind(server_fd, (struct sockaddr*)&address,
                       sizeof(address))
               < 0) {
               perror("bind failed");
               exit(EXIT_FAILURE);
       }
    while (1){
       if (listen(server_fd, 3) < 0) {
               perror("listen");
               exit(EXIT_FAILURE);
       }
       if ((new_socket
               = accept(server_fd, (struct sockaddr*)&address,
                               (socklen_t*)&addrlen))
               < 0) {
               perror("accept");
               exit(EXIT_FAILURE);
       }
       valread = read(new_socket, buffer, 1024);
       fprintf(stderr,"%d\n",valread);
       strcpy(buffer2, buffer);
       printf("%s\n", buffer);
       send(new_socket, buffer2, strlen(buffer2), 0);
       printf("Hello message sent\n");
       close(new_socket);
       }
}

i send this

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

And the output is this:

8
AAAAAAAA
Hello message sent
Mixalis Navridis
  • 181
  • 2
  • 15
  • I won't watch the video (and you might want to phrase your question without referencing a video). What makes you think that the attack is done twice on different machines with the same address? – Yunnosch Jun 09 '23 at 08:51
  • There is no standard way to do a "buffer overflow attack". Perhaps you can post some example? In general the naive school book examples as how these were carried out back in the 1990s aren't relevant for any purpose. – Lundin Jun 09 '23 at 09:04
  • 1
    Not all applications running on Microsoft Windows use Address Space Layout Randomization (ASLR). For example, [ASLR can be disabled](https://stackoverflow.com/q/9560993/12149471). – Andreas Wenzel Jun 09 '23 at 09:05
  • Another major obstacle to most buffer-overflow attacks is that modern CPUs usually have a [no-execute bit](https://en.wikipedia.org/wiki/NX_bit). However, the operating system and/or the program must set that bit appropriately, for it to be of any use. – Andreas Wenzel Jun 09 '23 at 09:10
  • @Yunnosch i am not sure that the attack is done twice on the same addresses thats why i said cant explain please watch the video if possible and tell me how is done – Mixalis Navridis Jun 09 '23 at 10:59
  • Sorry, but I do not consider "Please watch this video and tell me how to do that." to be a question for StackOverflow. If you cannot ask a specific question(see [ask]) then my answer is "It is a fake video, maybe one which just lacks necessary details." - and that answer does not require to follow a link.... – Yunnosch Jun 09 '23 at 11:05
  • 2
    I have now watched the video. It does not provide many details. In particular, it does not specify whether the target process is using ASLR and the no-execute bit. Therefore, my guess is that both are disabled. – Andreas Wenzel Jun 09 '23 at 11:16
  • @Lundin Example is added – Mixalis Navridis Jun 09 '23 at 11:16
  • @Andreas Wenzel so if i understand correctly if we assume that ASLR is disabled and no-execute bit is not set, the attack should be possible remotely correct? – Mixalis Navridis Jun 09 '23 at 11:20
  • @MixalisNavridis: I don't have much experience with security exploits, but I guess that whether an attack is possible may also depend on some other factors. For example, the attacker would probably need to know (or guess) the exact version of the vulnerable software installed on the target computer, because the memory layout may be different in different versions. Also, depending on what exactly the attacker wants to do, the attacker may also need to know (or guess) which version of a particular system DLL is installed on the target computer, if the attacker intends to use that DLL. – Andreas Wenzel Jun 09 '23 at 11:57
  • @Andreas Wenzel Don't make it too complex take for example the above illustration which simulates a simple buffer flow attack. Can this piece of software be injected remotely if ASLR and no-execute bit is not setted? – Mixalis Navridis Jun 09 '23 at 12:12
  • 1
    @MixalisNavridis: Apart from ASLR and the no-execute bit, there exist additional security features. For example, I don't think that such an exploit would work on software compiled by the Microsoft compiler if [GuardStack](https://learn.microsoft.com/en-us/archive/msdn-magazine/2017/december/c-visual-c-support-for-stack-based-buffer-protection#guardstack-gs) is active. I'm not sure if the compiler you are using has a similar feature. However, if all of these security features are disabled, then I believe that the buffer overflow should be exploitable. – Andreas Wenzel Jun 09 '23 at 12:35
  • 1
    If you are using the compilers gcc or clang, then those compilers have a feature similar to [GuardStack](https://learn.microsoft.com/en-us/archive/msdn-magazine/2017/december/c-visual-c-support-for-stack-based-buffer-protection#guardstack-gs) on the Microsoft compiler. See the command-line option [`-fstack-protector`](https://gcc.gnu.org/onlinedocs/gcc/Instrumentation-Options.html#index-fstack-protector) for further information. – Andreas Wenzel Jun 09 '23 at 12:53
  • @Andreas Wenzel Do you know if additional security features like -fstack-protector exist on Linux by default because i am running the above code on the question and i expect the strcpy to produce a segmentation fault but this didn't happen – Mixalis Navridis Jun 10 '23 at 11:18
  • 1
    @MixalisNavridis: What happened instead of a segmentation fault? Did you get an error message stating that stack corruption was detected? Or did your program behave as intended? How big was the data that you sent to the program? – Andreas Wenzel Jun 11 '23 at 19:56
  • 1
    @MixalisNavridis: Note that the line `valread = read(new_socket, buffer, 1024);` will not necessarily read 1024 bytes of data in the first call to that function, even if the client sends more than 1024 bytes of data. What is the value of `valread`? – Andreas Wenzel Jun 11 '23 at 20:16
  • 1
    In your question, you stated that the posted code causes a segmentation fault. However, in your last comment, you stated that the posted code does **not** cause a segmentation fault. This appears contradictory to me. Please clarify this contradiction. – Andreas Wenzel Jun 11 '23 at 20:51
  • @Andreas Wenzel My mistake not causes segmentation fault i expect to give a fault but it didnt. Lets focus only in the sctrcpy because there strcpy is not safe and i expect this func produce the error – Mixalis Navridis Jun 12 '23 at 19:53
  • 1
    @MixalisNavridis: In your last comment, you responded to my last comment. But you did not respond to the two comments that I made before my last comment. In those two comments, I asked you some questions, which you still have not answered. – Andreas Wenzel Jun 12 '23 at 20:14
  • @Andreas Wenzel i sent for example this string "%p,%p,%p" and at least i manage to get some addresses in the printf. This is how far i manage to achieve. i've also tried to send a large string with random letters and numbers but the program worked well – Mixalis Navridis Jun 12 '23 at 20:56
  • 1
    @MixalisNavridis: The string `"%p,%p,%p"` has a length of 9 bytes, so you are only overflowing the 8-byte buffer `buffer2` by one byte. This is probably not sufficient to cause a segmentation fault. I suggest that you try sending 1024 bytes. Also, as stated above, you should verify that `read` actually read all 1024 bytes, by checking the return value of `read`, which is stored in the variable `valread`. It is possible that the function `read` doesn't read everything at once. – Andreas Wenzel Jun 13 '23 at 15:31
  • @Andreas Wenzel I tried to send more than 1024 bytes and i verify that the read save only the 1024 bytes and ignore the rest so no error is thrown any suggestions? – Mixalis Navridis Jun 14 '23 at 11:19
  • 1
    @MixalisNavridis: If `buffer` is stored after `buffer2` in memory, then overflowing `buffer2` with `1024` bytes will only overwrite `buffer` and maybe some other local variables, but it will not reach the return address of the function `main`. That is possibly why you are not getting a segmentation fault. I suggest that you change `char buffer[1024] = { 0 };` to `static char buffer[1024] = { 0 };`, so that it does not get stored on the stack. This may then cause the segmentation fault to occur. – Andreas Wenzel Jun 14 '23 at 11:31
  • @Andreas Wenzel unfortunately no further luck the rest bytes still ignored – Mixalis Navridis Jun 14 '23 at 14:28
  • 1
    @MixalisNavridis: And the value of the variable `valread` is `1024` after the function `read` returns? I suggest that you add a `fprintf(stderr,"%d\n",valread);` statement after the function call to verify this. – Andreas Wenzel Jun 14 '23 at 14:37
  • 1
    Could you please update the code in your question with the latest code, so that I can see if you applied the changes correctly. Generally, you should not change the question in such a way that it may invalidate existing answers. However, since your question does not have any answers yet, this should not be an issue. – Andreas Wenzel Jun 14 '23 at 14:38
  • Please also specify the exact output of the program as well as exactly how you are compiling the program. With what command-line are you invoking the compiler? – Andreas Wenzel Jun 14 '23 at 14:52
  • @Andreas Wenzel i updated the code and also update the input and output of the program please check – Mixalis Navridis Jun 15 '23 at 13:33
  • 1
    Why did you change the size of `buffer` from `1024` to `8`? Due to this change, you have less control on how much `buffer2` is being overflowed. – Andreas Wenzel Jun 15 '23 at 13:59
  • Please also update the output when you change your code, unless the output remained the same. – Andreas Wenzel Jun 15 '23 at 19:35
  • @Andreas Wenze i have a questions first i changed again to 1024 but what input to give to get error. Can you test it locally and tell me – Mixalis Navridis Jun 15 '23 at 19:36
  • @MixalisNavridis: I believe your posted input should be ok. – Andreas Wenzel Jun 15 '23 at 19:37
  • 1
    If you still don't get a segmentation fault, then my guess is that the reason is that the function `main` never returns, so that your program never attempts to read the return address of the function call to `main` (which should have been overwritten by the buffer overflow). In that case, I suggest that you add the line `return 0;` after the line `close(new_socket);`, in order to escape your infinite `while (1){` loop. – Andreas Wenzel Jun 15 '23 at 19:45
  • @Andreas Wenzel Brilliant i think it works i got this "*** stack smashing detected ***: terminated" when adding the return 0 am i right does it worked? but i dont get segmentation fault – Mixalis Navridis Jun 16 '23 at 13:57
  • 1
    @MixalisNavridis: Yes, that is not a segmentation fault. But it is code emitted by the compiler detecting that a buffer overflow has occurred and that the information on the stack is therefore corrupt. For this reason, the program is refusing to use the stored return address of the function, because it assumes that this information is invalid and that it would pose a security risk to use that address. If you want an actual segmentation fault to occur, you will have to disable this check. In order to tell you how, you would have to specify exactly how you are compiling the program. – Andreas Wenzel Jun 16 '23 at 14:04
  • @Andreas Wenzel, i am using Ubuntu with Clion and gcc 11.3.0 – Mixalis Navridis Jun 16 '23 at 19:53
  • 1
    @MixalisNavridis: I have never used CLion. All I know is that it is an IDE. Can you tell me with what command line arguments CLion is invoking the compiler gcc? Is it maybe using [`-fstack-protector`](https://gcc.gnu.org/onlinedocs/gcc/Instrumentation-Options.html#index-fstack-protector) (which I already mentioned above)? If that is the case, then you should remove it (only in this case, though). – Andreas Wenzel Jun 16 '23 at 20:13
  • @Andreas Wenzel i think i need to do this one and i will be ok. Do you agree?https://stackoverflow.com/questions/2340259/how-to-turn-off-gcc-compiler-optimization-to-enable-buffer-overflow – Mixalis Navridis Jun 16 '23 at 20:41
  • 1
    @MixalisNavridis: It depends on what your intent is. If your intent is merely to get the buffer overflow to trigger a segmentation fault, I guess it should be sufficient to make sure that CLion does not invoke your compiler with `-fstack-protector` or any similar compiler options. However, if you want to use the buffer overflow to take control of your server program, then additional steps will probably be necessary, such as disabling ASLR and maybe also the [no-execute bit](https://en.wikipedia.org/wiki/NX_bit). – Andreas Wenzel Jun 17 '23 at 19:03
  • 1
    It may be worth noting that some Linux distributions may have modified the compiler in such a way that [`-fstack-protector`](https://gcc.gnu.org/onlinedocs/gcc/Instrumentation-Options.html#index-fstack-protector) is enabled by default. In that case, you will have to invoke the compiler with `-fno-stack-protector` to disable it. See [this answer](https://stackoverflow.com/a/10713028/12149471) for further information. – Andreas Wenzel Jun 17 '23 at 19:12
  • 1
    If you are unsure how to change the command-line options of the compiler in CLion, then I suggest that you try compiling the program directly, without CLion. – Andreas Wenzel Jun 17 '23 at 19:17
  • @Andreas Wenzel i decide not use clion and run it from terminal and base on the link that sent earlier i will disable ASLR and fstack-protector but i dont find a way to prevent also the no execute bit. can you guide me on this – Mixalis Navridis Jun 18 '23 at 17:06
  • 1
    @MixalisNavridis: Unfortunately, I have no experience with the [no-execute bit](https://en.wikipedia.org/wiki/NX_bit) in Linux. However, [this question](https://unix.stackexchange.com/questions/274591/how-to-verify-nx-cpu-bit-usage-by-linux-kernel) may be helpful. – Andreas Wenzel Jun 18 '23 at 21:43

0 Answers0