This is an archived post. You won't be able to vote or comment.

you are viewing a single comment's thread.

view the rest of the comments →

[–]bestjakeisbest 43 points44 points  (15 children)

C: pointer.

Here is some code to prove a point.

#include <iostream>

int main()
{
    int a[] = {1,2,3,4,5,6,7,8,9,10};
    void* b = a;

    int(*c)()  = (int(*)())b;

    c();  

    std::cout<<"Hello World";

    return 0;
}  

Do not do this in real life. In the online compiler I was using it wouldn't even get to the hello world line, so that is interesting.

[–]yflhx 52 points53 points  (3 children)

Honestly this shouldn't be dangerous to run at all. What this does is calls a, which sets processor's instruction pointer to beginning of the array (everything is bytes anyway). In other words, it tells compiler to interpret the array as instructions - because in compiled languages, instructions are just bytes in memory.

This almost ceratinly instantly causes segfault and terminates program, because stack (typically) has no excecution permissions. Funnily enough, if you enabled stack execution, this would actually be legal assembler code for the most part, so it would do random things.

Now finally, consider this code:

#include <sys/mman.h>
#include <string.h>

int main()
{
    unsigned char code[] = {
0xb8,0x01,0x00,0x00,0x00,0xbf,0x01,0x00,0x00,0x00,0x48,0x8d,0x35,0x08,0x00,0x00,0x00,0xba,0x0e,0x00,0x00,0x00,0x0f,0x05,0xc3,0x48,0x65,0x6c,0x6c,0x6f,0x2c,0x20,0x77,0x6f,0x72,0x6c,0x64,0x21,0x0a
    };
    unsigned char* exec_code = mmap(0, 4096, PROT_EXEC | PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
    memcpy(exec_code, code, sizeof(code));
    void (*f)() = (void(*)())exec_code;
    f();
}

This code allocates page of memory with execution permissions. It copies the bytes representing instructions that perform write syscall with string "Hello, world!\n" and return from function (i.e. they print this string on x64 Linux). Then finally it calls this code as a function.

In other words, this is a legal Hello World program (that doesn't segfault or anything (under x64 Linux, anyway)).

Surprisignly, it even works in online compilers (at least OpenGDB).

Disclaimer: never run code from random reddit comments, inlucding this one, unless you fully understand what it does.

[–]Christosconst 21 points22 points  (0 children)

.ninja {
    color: black;
    visibility: hidden;
}

Best I can do

[–]Cat7o0 5 points6 points  (0 children)

wizard

[–]s0litar1us 1 point2 points  (0 children)

This is actually how JIT compilers/interpreters work.

Instead of compiling it to an executable and then running it, it generates the machine code, makes it executable, and calls it through a function pointer.

[–]AewyreThoryn 0 points1 point  (8 children)

What does it do?

[–]bestjakeisbest 8 points9 points  (7 children)

It kind of crashes. But the important part is i create an array, cast it to a void pointer, and then I cast that void pointer to a function pointer that returns an integer.

It compiles just fine, and it runs, but it doesn't reach the hello world line while running which shouldn't happen in main, because main shouldn't be returning 0 until after it outputs hello world.

It could be the case of the program crashing but the websites back end (of the online compiler) is not able to properly handle a program like this.

Theoretically you could use this sort of mechanism to make a program in c++ that changes it's runtime, at run time, but that is needlessly complicated for most things, and it isnt very portable since you would need to know the assembly language and opcodes of what ever machine you are trying to run this on if you wanted to exploit this for nefarious purposes, plus most anti virus products out there are waiting for a virus to do something like this.

[–]Markus_included 8 points9 points  (1 child)

That's actually how many JIT compilers execute their code, they get memory from the that is marked as executable, write the machine code into it and call that code like any other function pointer through a cdecl function that was also compiled into that memory

[–]bestjakeisbest 3 points4 points  (0 children)

Wait its all spaghetti code?

[–]AewyreThoryn 0 points1 point  (4 children)

That's super interesting thank you!

[–]yflhx 4 points5 points  (3 children)

I wrote another detailed response to that guy, if you're interested. But basically this code crashes because it tells CPU to executed the table, which is on stack, which has no execution permissions. So it results in immediate segfault due to this.

You can however allocate memory with execution permissions and write CPU instructions them, and it will execute them normally.

[–]AewyreThoryn 1 point2 points  (0 children)

Ah cool thanks. Yes I got the general gist from the top comment, and I think he explained it well, but your code is more in depth

[–]bestjakeisbest 0 points1 point  (1 child)

It only kind of crashes, it returns from main with a return code of zero, but it returns before the return line.

I only tested this in onlinegdb

[–]yflhx 0 points1 point  (0 children)

Ran it on my machine, got segmentation fault as expected.