Last active
January 30, 2018 00:39
-
-
Save totem3/adb287040e04f7f3e7902490f03d8307 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <stdint.h> | |
#include <sys/mman.h> | |
#include <sys/stat.h> | |
#include "osfmk/mach/machine.h" | |
#include "EXTERNAL_HEADERS/mach-o/loader.h" | |
#include <string.h> | |
#include <assert.h> | |
int main() | |
{ | |
unsigned int code_bytes = 640 * 1024; | |
uint8_t* mem = (uint8_t*) mmap( | |
NULL, | |
code_bytes, | |
PROT_READ | PROT_WRITE | PROT_EXEC, | |
MAP_ANONYMOUS | MAP_PRIVATE, | |
0, | |
0); | |
uint64_t offset = 0; | |
uint64_t data_offset = 0; | |
uint64_t ncmds = 0; | |
uint64_t vmaddr = 0x0000000100000000; | |
uint64_t vmsize = 0x0000000000001000; | |
struct mach_header_64 *header = (struct mach_header_64*)mem; | |
header->magic = MH_MAGIC_64; | |
header->cputype = (CPU_ARCH_ABI64 | CPU_TYPE_X86); | |
header->cpusubtype = CPU_SUBTYPE_LIB64 | CPU_SUBTYPE_X86_64_ALL; | |
header->ncmds = 0; | |
header->sizeofcmds = 0; | |
header->filetype = MH_EXECUTE; | |
header->flags = MH_PIE | MH_TWOLEVEL | MH_PRELOAD; | |
offset += sizeof(struct mach_header_64); | |
printf("sizeof segment %lu\n", sizeof(struct segment_command_64)); | |
printf("sizeof section %lu\n", sizeof(struct section_64)); | |
printf("offset %llu\n", offset); | |
struct segment_command_64 *zero = (struct segment_command_64*)(mem + offset); | |
zero->cmd = LC_SEGMENT_64; | |
zero->cmdsize = sizeof(struct segment_command_64); | |
zero->vmsize = vmaddr; | |
strcpy(zero->segname, SEG_PAGEZERO); | |
offset += sizeof(struct segment_command_64); | |
ncmds += 1; | |
printf("offset %llu\n", offset); | |
struct segment_command_64 *text = (struct segment_command_64*)(mem + offset); | |
text->cmd = LC_SEGMENT_64; | |
text->cmdsize = sizeof(struct segment_command_64); | |
strncpy(text->segname, SEG_TEXT, 16); | |
text->vmaddr = vmaddr; | |
text->vmsize = vmsize; | |
text->fileoff = 0; | |
text->filesize = 4096; | |
text->maxprot = 0x7; | |
text->initprot = 0x5; | |
uint32_t nsects = 0; | |
text->nsects = nsects; | |
text->flags = 0; | |
offset += sizeof(struct segment_command_64); | |
ncmds += 1; | |
// section 0 | |
/* uint8_t prg[] = {0x48,0xc7,0xc0,0x00,0x00,0x00,0x00,0xc3}; */ | |
// 0x0000000100000fc8 | |
uint8_t prg[] = { | |
0x48, 0xc7, 0xc0, 0x04, 0x00, 0x00, 0x02, | |
0x48, 0xc7, 0xc7, 0x01, 0x00, 0x00, 0x00, | |
0x48, 0x8d, 0x35, 0x19, 0x00, 0x00, 0x00, | |
0x48, 0xc7, 0xc2, 0x0d, 0x00, 0x00, 0x00, | |
0x0f, 0x05, | |
0x48, 0xc7, 0xc0, 0x01, 0x00, 0x00, 0x02, | |
0x48, 0xc7, 0xc7, 0x00, 0x00, 0x00, 0x00, | |
0x0f, 0x05, | |
0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x2c, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x0a, 0x00, | |
}; | |
size_t prgsize = sizeof(prg); | |
printf("offset %llu\n", offset); | |
struct section_64 *text_sect = (struct section_64*)(mem + offset); | |
strncpy(text_sect->sectname, SECT_TEXT, 16); | |
strncpy(text_sect->segname, SEG_TEXT, 16); | |
text_sect->addr = 0; //vmaddr + offset | |
text_sect->size = prgsize; | |
text_sect->offset = 0; | |
text_sect->align = 0; | |
text_sect->flags = 0x80000400; | |
offset += sizeof(struct section_64); | |
data_offset += text_sect->size; | |
nsects += 1; | |
text->nsects = nsects; | |
text->cmdsize += (sizeof(struct section_64) * nsects); | |
printf("text->nsects %d\n", text->nsects); | |
printf("sizeof segment %lu\n", sizeof(struct segment_command_64)); | |
printf("sizeof section %lu\n", sizeof(struct section_64)); | |
printf("text->cmdsize %d\n", text->cmdsize); | |
printf("offset %llu\n", offset); | |
struct segment_command_64 *seg_data = (struct segment_command_64*)(mem + offset); | |
seg_data->cmd = LC_SEGMENT_64; | |
seg_data->cmdsize = sizeof(struct segment_command_64); | |
strncpy(seg_data->segname, SEG_DATA, 16); | |
seg_data->vmaddr = vmaddr+0x1000; | |
seg_data->vmsize = vmsize; | |
seg_data->fileoff = 0x1000; | |
seg_data->filesize = 4096; | |
seg_data->maxprot = 0x7; | |
seg_data->initprot = 0x3; | |
uint32_t ndata_sects = 1; | |
seg_data->nsects = ndata_sects; | |
seg_data->cmdsize = sizeof(struct segment_command_64) + sizeof(struct section_64); | |
seg_data->flags = 0; | |
offset += sizeof(struct segment_command_64); | |
ncmds += 1; | |
printf("offset %llu\n", offset); | |
struct section_64 *cstr_sect = (struct section_64*)(mem + offset); | |
strncpy(cstr_sect->sectname, "__cstring", 16); | |
strncpy(cstr_sect->segname, SEG_DATA, 16); | |
cstr_sect->addr = vmaddr + 0x1000; //vmaddr + offset | |
cstr_sect->size = 0x10; | |
cstr_sect->offset = 0x1000; | |
cstr_sect->align = 1; | |
cstr_sect->flags = 0x80000400; | |
offset += sizeof(struct section_64); | |
memcpy(mem+0x1000, "hello, world!\n", 0x10); | |
printf("linkedit offset %llu\n", offset); | |
struct segment_command_64 *linkedit = (struct segment_command_64*)(mem+offset); | |
linkedit->cmd = LC_SEGMENT_64; | |
linkedit->cmdsize = sizeof(struct segment_command_64); | |
strncpy(linkedit->segname, SEG_LINKEDIT, 16); | |
linkedit->vmaddr = 0; // vmdadr + offset | |
linkedit->vmsize = 4096; | |
linkedit->fileoff = 4096; | |
linkedit->filesize = 152; | |
linkedit->maxprot = 7; | |
linkedit->initprot = 1; | |
offset += sizeof(struct segment_command_64); | |
data_offset += 152; | |
ncmds += 1; | |
struct dyld_info_command *dyld_info_only = (struct dyld_info_command*)(mem+offset); | |
dyld_info_only->cmd = LC_DYLD_INFO_ONLY; | |
dyld_info_only->cmdsize = sizeof(struct dyld_info_command); | |
dyld_info_only->export_off = 0x2000; | |
dyld_info_only->export_size = 0x30; | |
offset += sizeof(struct dyld_info_command); | |
ncmds += 1; | |
struct symtab_command *symtab = (struct symtab_command*)(mem + offset); | |
symtab->cmd = LC_SYMTAB; | |
symtab->cmdsize = sizeof(struct symtab_command); | |
symtab->symoff = 0x2030; // 0x1038 | |
symtab->nsyms = 0; | |
symtab->stroff = 0x2030; // 0x1068 | |
symtab->strsize = 0; | |
offset += sizeof(struct symtab_command); | |
ncmds += 1; | |
struct dysymtab_command *dysymtab = (struct dysymtab_command*)(mem + offset); | |
dysymtab->cmd = LC_DYSYMTAB; | |
dysymtab->cmdsize = sizeof(struct dysymtab_command); | |
dysymtab->nextdefsym = 0; | |
dysymtab->iundefsym = 0; | |
dysymtab->nundefsym = 0; | |
offset += sizeof(struct dysymtab_command); | |
ncmds += 1; | |
struct dylinker_command* dylinker = (struct dylinker_command*)(mem + offset); | |
dylinker->cmd = LC_LOAD_DYLINKER; | |
dylinker->cmdsize = sizeof(struct dylinker_command) + 20; | |
union lc_str name = {0x0c}; | |
dylinker->name = name; | |
offset += sizeof(struct dylinker_command); | |
strncpy((char*)(mem+offset), "/usr/lib/dyld", 20); | |
offset += 20; | |
ncmds += 1; | |
struct entry_point_command *entry = (struct entry_point_command*)(mem + offset); | |
entry->cmd = LC_MAIN; | |
entry->cmdsize = sizeof(struct entry_point_command); | |
entry->entryoff = 4016; | |
entry->stacksize = 0; | |
offset += sizeof(struct entry_point_command); | |
ncmds += 1; | |
struct dylib_command *dylib = (struct dylib_command*)(mem + offset); | |
dylib->cmd = LC_LOAD_DYLIB; | |
dylib->cmdsize = 56;// sizeof(struct dylib_command) + 0; | |
union lc_str libname = {24}; | |
struct dylib lib = { | |
.name = libname, | |
.timestamp = 2, | |
.current_version = 81148930, | |
.compatibility_version = 65536 | |
}; | |
dylib->dylib = lib; | |
offset += sizeof(struct dylib_command); | |
strncpy((char*)mem+offset, "/usr/lib/libSystem.B.dylib", 32); | |
offset += 32; | |
ncmds += 1; | |
header->ncmds = ncmds; | |
header->sizeofcmds = offset - sizeof(struct mach_header_64); | |
/* assert(header->sizeofcmds == 728); */ | |
printf("offset %llx\n", offset); | |
if (offset < 0xfb0) { | |
offset += (0xfb0 - offset); | |
} | |
printf("offset %llx\n", offset); | |
printf("header %lx\n", sizeof(struct mach_header_64)); | |
text_sect->addr = vmaddr + offset; | |
text_sect->offset = offset; | |
memcpy((mem+offset), prg, sizeof(prg)); | |
offset += text_sect->size; | |
linkedit->fileoff = 0x2000; //offset; | |
linkedit->vmaddr = vmaddr + linkedit->fileoff; | |
char* filename = "foo"; | |
FILE *fp = fopen(filename, "wb"); | |
fwrite(mem, 1, code_bytes, fp); | |
fclose(fp); | |
chmod(filename, 0777); | |
return 0; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <stdint.h> | |
#include <sys/mman.h> | |
#include <sys/stat.h> | |
#include "osfmk/mach/machine.h" | |
#include "EXTERNAL_HEADERS/mach-o/loader.h" | |
#include <string.h> | |
int main() | |
{ | |
unsigned int code_bytes = 8192; | |
uint8_t* mem = (uint8_t*) mmap( | |
NULL, | |
code_bytes, | |
PROT_READ | PROT_WRITE | PROT_EXEC, | |
MAP_ANONYMOUS | MAP_PRIVATE, | |
0, | |
0); | |
uint64_t offset = 0; | |
uint64_t data_offset = 0; | |
uint64_t ncmds = 0; | |
uint64_t vmaddr = 0x0000000100000000; | |
uint64_t vmsize = 0x0000000000001000; | |
struct mach_header_64 *header = (struct mach_header_64*)mem; | |
header->magic = MH_MAGIC_64; | |
header->cputype = (CPU_ARCH_ABI64 | CPU_TYPE_X86); | |
header->cpusubtype = CPU_SUBTYPE_LIB64 | CPU_SUBTYPE_X86_64_ALL; | |
header->ncmds = 0; | |
header->sizeofcmds = 0; | |
header->filetype = MH_EXECUTE; | |
header->flags = MH_PIE | MH_TWOLEVEL | MH_PRELOAD; | |
offset += sizeof(struct mach_header_64); | |
struct segment_command_64 *zero = (struct segment_command_64*)(mem + offset); | |
zero->cmd = LC_SEGMENT_64; | |
zero->cmdsize = sizeof(struct segment_command_64); | |
zero->vmsize = vmaddr; | |
strcpy(zero->segname, SEG_PAGEZERO); | |
offset += sizeof(struct segment_command_64); | |
ncmds += 1; | |
struct segment_command_64 *text = (struct segment_command_64*)(mem + offset); | |
text->cmd = LC_SEGMENT_64; | |
text->cmdsize = sizeof(struct segment_command_64); | |
strncpy(text->segname, SEG_TEXT, 16); | |
text->vmaddr = vmaddr; | |
text->vmsize = vmsize; | |
text->fileoff = 0; | |
text->filesize = 4096; | |
text->maxprot = 0x7; | |
text->initprot = 0x5; | |
uint32_t nsects = 0; | |
text->nsects = nsects; | |
text->flags = 0; | |
offset += sizeof(struct segment_command_64); | |
ncmds += 1; | |
uint8_t prg[] = { | |
0x48, 0xc7, 0xc0, 0x04, 0x00, 0x00, 0x02, | |
0x48, 0xc7, 0xc7, 0x01, 0x00, 0x00, 0x00, | |
0x48, 0x8d, 0x35, 0x19, 0x00, 0x00, 0x00, | |
0x48, 0xc7, 0xc2, 0x0d, 0x00, 0x00, 0x00, | |
0x0f, 0x05, | |
0x48, 0xc7, 0xc0, 0x01, 0x00, 0x00, 0x02, | |
0x48, 0xc7, 0xc7, 0x00, 0x00, 0x00, 0x00, | |
0x0f, 0x05, | |
0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x2c, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x0a, 0x00, | |
}; | |
size_t prgsize = sizeof(prg); | |
struct section_64 *text_sect = (struct section_64*)(mem + offset); | |
strncpy(text_sect->sectname, SECT_TEXT, 16); | |
strncpy(text_sect->segname, SEG_TEXT, 16); | |
text_sect->addr = 0; | |
text_sect->size = prgsize; | |
text_sect->offset = 0; | |
text_sect->align = 0; | |
text_sect->flags = 0x80000400; | |
offset += sizeof(struct section_64); | |
data_offset += text_sect->size; | |
nsects += 1; | |
text->nsects = nsects; | |
text->cmdsize += (sizeof(struct section_64) * nsects); | |
uint8_t entry[] = { | |
0x05, 0x00, 0x00, 0x00, | |
0xb8, 0x00, 0x00, 0x00, | |
0x04, 0x00, 0x00, 0x00, | |
0x2a, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0xb0, 0x0f, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
}; | |
memcpy(mem + offset, entry, 184); | |
offset += 184; | |
ncmds += 1; | |
header->ncmds = ncmds; | |
header->sizeofcmds = offset - sizeof(struct mach_header_64); | |
if (offset < 0xfb0) { | |
offset += (0xfb0 - offset); | |
} | |
text_sect->addr = vmaddr + offset; | |
text_sect->offset = offset; | |
memcpy((mem+offset), prg, sizeof(prg)); | |
offset += text_sect->size; | |
char* filename = "foo"; | |
FILE *fp = fopen(filename, "wb"); | |
fwrite(mem, 1, code_bytes, fp); | |
fclose(fp); | |
chmod(filename, 0777); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment