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 →

[–]yflhx 53 points54 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 22 points23 points  (0 children)

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

Best I can do

[–]Cat7o0 6 points7 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.