nooc

Unnamed repository; edit this file 'description' to name the repository.
git clone git://git.nihaljere.xyz/nooc
Log | Files | Refs | LICENSE

commit 2637645b18ff9ca6c87f1f2c33771014dac50483
parent dacb5b542397620ba34790d08a3975ad3561a3a9
Author: Nihal Jere <nihal@nihaljere.xyz>
Date:   Wed,  3 Nov 2021 14:39:23 -0500

can do arbitrary syscalls

Diffstat:
Aarray.c | 21+++++++++++++++++++++
Aarray.h | 4++++
Mmain.c | 76+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------
Mprog.nc | 4++--
4 files changed, 90 insertions(+), 15 deletions(-)

diff --git a/array.c b/array.c @@ -0,0 +1,21 @@ +#include <stddef.h> +#include <stdlib.h> +#include <string.h> + +#include "array.h" + +int +_array_add(void **data, size_t size, size_t *len, size_t *cap, void *new) +{ + if (*len == *cap) { + *cap = *cap ? 2*(*cap)*size : 1; + *data = realloc(*data, size*(*cap)); + if (*data == NULL) + return -1; + } + + memcpy(*data + size*(*len), new, size); + *len += 1; + + return *len; +} diff --git a/array.h b/array.h @@ -0,0 +1,4 @@ +#define array_add(arr, new) \ + _array_add((void **) &(arr->data), sizeof(new), &(arr->len), &(arr->cap), &new); + +int _array_add(void **data, size_t size, size_t *len, size_t *cap, void *new); diff --git a/main.c b/main.c @@ -8,6 +8,8 @@ #include <sys/mman.h> #include <unistd.h> +#include "array.h" + char code[] = {0xb8, 0, 0x00, 0x00, 0x00, 0xbf, 0x00, 0x00, 0x00, 0x00, 0xf, 0x5}; int @@ -156,9 +158,15 @@ enum func { FUNC_EXIT }; +struct fparams { + size_t cap; + size_t len; + int *data; +}; + struct fcall { enum func func; - int val; + struct fparams params; }; void @@ -180,27 +188,62 @@ expect(struct token *tok, enum tokentype type) struct fcall parse(struct token *tok) { - struct fcall fcall; + struct fcall fcall = { 0 }; expect(tok, TOK_SYSCALL); tok = tok->next; expect(tok, TOK_LPAREN); tok = tok->next; - expect(tok, TOK_EXIT); - fcall.func = FUNC_EXIT; - tok = tok->next; - expect(tok, TOK_COMMA); - tok = tok->next; - expect(tok, TOK_NUM); + int val; + while (1) { + expect(tok, TOK_NUM); + val = strtol(tok->slice.ptr, NULL, 10); + array_add((&fcall.params), val); + tok = tok->next; + + if (tok->type == TOK_RPAREN) + break; + expect(tok, TOK_COMMA); + tok = tok->next; + } // FIXME: error check - fcall.val = strtol(tok->slice.ptr, NULL, 10); - tok = tok->next; expect(tok, TOK_RPAREN); tok = tok->next; return fcall; } +size_t +gensyscall(char *buf, struct fparams *params) +{ + if (params->len > 7) + error("syscall can take at most 7 parameters"); + + if (buf) { + char *ptr = buf; + char mov[] = {0x48, 0xc7}; + char padding[] = {0, 0, 0}; + + // encoding for argument registers in ABI order + char regs[] = {0, 7, 6, 2, 10, 8, 9}; + for (int i = 0; i < params->len; i++) { + memcpy(ptr, mov, 2); + ptr += 2; + char op1 = 0xc0 | regs[i]; + *(ptr++) = op1; + *(ptr++) = params->data[i]; + memset(ptr, 0, 3); + ptr += 3; + } + + char syscall[] = {0x0f, 0x05}; + memcpy(ptr, syscall, 2); + } + + // for now, we assume each mov is 7 bytes encoded, and 2 bytes for syscall + return 7*params->len + 2; +} + struct stat statbuf; int @@ -232,7 +275,7 @@ main(int argc, char *argv[]) switch (fcall.func) { case FUNC_EXIT: code[1] = 60; - code[6] = fcall.val; + code[6] = fcall.params.data[0]; } FILE *out = fopen(argv[2], "w"); @@ -242,8 +285,15 @@ main(int argc, char *argv[]) return 1; } - elf(code, sizeof(code), out); - fprintf(stderr, "size: %d\n", sizeof(code)); + size_t len = gensyscall(NULL, &(fcall.params)); + char *fcode = malloc(len); + if (!fcode) + error("gensyscall malloc failed"); + + gensyscall(fcode, &(fcall.params)); + + elf(fcode, len, out); + fprintf(stderr, "size: %d\n", len); fclose(out); } diff --git a/prog.nc b/prog.nc @@ -1 +1 @@ -syscall(exit, 12)- \ No newline at end of file +syscall(60, 12)+ \ No newline at end of file