I assume you mean you got a seggy when you tried to single step the code after the breakpoint you created.
Did you disassemble the code you created in memory? Did it look correct?
Also, in single stepping the code past your breakpoint, you need to single step the individual machine language instructions, not the C program lines!
This doesn't segfault (or give an illegal instruction or anything).
Code:
#include "stdio.h"
#include "string.h"
#include "stdlib.h"
#include "sys/mman.h"
#define null (void*)0
int main() {
void* code = mmap(null, 500, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANON, -1, 0);
char* code_byte = (char*)code;
// mov rax, 0x01 (code for sys_exit)
memcpy(code_byte, "\x48\xC7\xC0\x01\x00\x00\x00", 7);
// int 0x80 (execute system call)
memcpy(code_byte+7, "\xCD\x80", 2);
// Execute the code
((void(*)(void))code)();
return 0;
}
Disassembling the generated code looks correct.
On your original code, it shows a bad instruction after the one that loads the address.
Here's a new version of your program that might be easier to work with.
To show the disassembly of the code in memory:
gcc program.c -g
gdb a.out
l (to list the program, keep hitting return until you see the line that runs the code)
b 58 (assuming it is line 58)
r (to run up to the breakpoint)
x/i code (shows first disassembled line; hit enter for the next, etc.)
Code:
#include "stdio.h"
#include "string.h"
#include "stdlib.h"
#include "sys/mman.h"
#define null (void*)0
void putbytes(void *code, int *pos, const void *bytes, int len) {
memcpy((char*)code + *pos, (const char*)bytes, len);
*pos += len;
}
int main() {
char* data = mmap(null, 15, PROT_READ|PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
memset(data, 0x0, 15); // Default value
memcpy(data, "Hello world!", 12);
void* code = mmap(null, 500, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANON, -1, 0);
memset(code, 0xc3, 500); // Default value
int pos = 0;
// Call the "write" and "exit" system calls
// mov rax, 0x04 (sys_write)
putbytes(code, &pos, "\x48\xC7\xC0\x04\x00\x00\x00", 7);
// mov rbx, 0x01 (stdout)
putbytes(code, &pos, "\x48\xC7\xC3\x01\x00\x00\x00", 7);
// mov rdx, 12 (string length)
putbytes(code, &pos, "\x48\xC7\xC2\x0C\x00\x00\x00", 7);
// mov rcx, data (string address)
putbytes(code, &pos, "\x48\xC7\xC1", 3);
putbytes(code, &pos, &data, 8);
putbytes(code, &pos, "\x00", 1);
// int 0x80
putbytes(code, &pos, "\xCD\x80", 2);
// mov rax, 0x01
putbytes(code, &pos, "\x48\xC7\xC0\x01\x00\x00\x00", 7);
// int 0x80
putbytes(code, &pos, "\xCD\x80", 2);
// Execute the code
((void(*)(void))code)();
return 0;
}