diff --git a/Makefile_Windows b/Makefile_Windows new file mode 100644 index 0000000..69bbadf --- /dev/null +++ b/Makefile_Windows @@ -0,0 +1,32 @@ +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 = C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\Llvm\x64\bin\clang +CFLAGS = -Os -Iinclude -fno-asynchronous-unwind-tables -DUNICODE -D_UNICODE -m32 -fwritable-strings -DLAIKA -nostdlib -D_WIN32_WINNT=0x0501 + +all: $(NAME) + +lib: $(OBJ) + @if not exist bin (mkdir bin) + ar rc bin/$(NAME).lib $(OBJ) + ranlib bin/$(NAME).lib + +$(NAME): lib + $(CC) $(CFLAGS) -o bin/$(NAME) tests/interpreter.c -Lbin -lpasm + +interpreter: $(NAME) + +clean: + @if exist bin (del /q bin\*.*) + @if exist src\*.o (del /q src\*.o) + +fclean: clean + @if exist bin (rmdir bin) + +.PHONY: all $(NAME) interpreter lib clean fclean diff --git a/msvc/pasm.vcxproj b/msvc/pasm.vcxproj index 718a4fd..e24098e 100644 --- a/msvc/pasm.vcxproj +++ b/msvc/pasm.vcxproj @@ -29,26 +29,27 @@ StaticLibrary true - v143 + ClangCL Unicode + true StaticLibrary false - v143 + ClangCL true Unicode StaticLibrary true - v143 + ClangCL Unicode StaticLibrary false - v143 + ClangCL true Unicode @@ -100,20 +101,24 @@ Default false false + MultiThreadedDebug + true + false Console true - pasm_run_script + + - - /DLAIKA %(AdditionalOptions) - - + + /DLAIKA %(AdditionalOptions) + + Level3 @@ -137,7 +142,8 @@ true - pasm_run_script + + @@ -156,7 +162,8 @@ true - pasm_run_script + + @@ -182,7 +189,8 @@ true - pasm_run_script + + diff --git a/src/api.c b/src/api.c index 7171445..51f03ac 100644 --- a/src/api.c +++ b/src/api.c @@ -66,8 +66,7 @@ void api_callrawaddr() { #endif void api_VirtualAlloc(void) { #ifdef _WIN32 - char api[] = "[nwyzfqFqqth"; - fVirtualAlloc pVirtualAlloc = GetApi(L"kernel32.dll", PCAESAR_DECRYPT(api)); + fVirtualAlloc pVirtualAlloc = GetApi(L"kernel32.dll", "[nwyzfqFqqth"); if (pVirtualAlloc == NULL) { state->STACK_IDX -= 4; state->registers->eax = 1; @@ -90,8 +89,7 @@ void api_VirtualAlloc(void) { #endif void api_VirtualFree(void) { #ifdef _WIN32 - char api[] = "[nwyzfqKwjj"; - fVirtualFree pVirtualFree = GetApi(L"kernel32.dll", PCAESAR_DECRYPT(api)); + fVirtualFree pVirtualFree = GetApi(L"kernel32.dll", "[nwyzfqKwjj"); if (pVirtualFree == NULL) { state->STACK_IDX -= 3; state->registers->eax = 1; @@ -113,8 +111,7 @@ void api_VirtualFree(void) { #endif void api_GetAsyncKeyState(void) { #ifdef _WIN32 - char api[] = "LjyFx~shPj~Xyfyj"; - fGetAsyncKeyState pGetAsyncKeyState = GetApi(L"user32.dll", PCAESAR_DECRYPT(api)); + fGetAsyncKeyState pGetAsyncKeyState = GetApi(L"user32.dll", "LjyFx~shPj~Xyfyj"); if (pGetAsyncKeyState == NULL) { state->STACK_IDX -= 1; state->registers->eax = 1; diff --git a/src/debug.c b/src/debug.c index 1ee58ba..ddddfcf 100644 --- a/src/debug.c +++ b/src/debug.c @@ -109,8 +109,8 @@ int add_breakpoint(char *in, int *bp) { return 1; bp_add(bp, line - 1); printf("breakpoint added at line %d.\n", line); - return 0; #endif + return 0; } int rem_breakpoint(char *in, int *bp) { @@ -127,8 +127,8 @@ int rem_breakpoint(char *in, int *bp) { return 1; bp_rem(bp, line - 1); printf("breakpoint at line %d deleted.\n", line); - return 0; #endif + return 0; } void debug_input(char *line) { diff --git a/src/instructions.c b/src/instructions.c index 824ba13..e250703 100644 --- a/src/instructions.c +++ b/src/instructions.c @@ -19,11 +19,11 @@ bool is_reg(char* arg) { if (is_array(arg)) return true; return (strcmp__(arg, "eax") == 0) || (((arg[0] == 'a' && - ('1' <= arg[1] && arg[1] <= '9'))) && strlen(arg) == 2); + ('1' <= arg[1] && arg[1] <= '9'))) && strlen__(arg) == 2); } bool is_num(char* arg) { - return (strtol_(arg, NULL, 10) != 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) { @@ -91,7 +91,7 @@ long long get_value(char* arg) { } } else { - if (strlen(arg) > 2 && arg[0] == '0' && arg[1] == 'x') { + if (strlen__(arg) > 2 && arg[0] == '0' && arg[1] == 'x') { ret = strtol_(arg, NULL, 16); } ret = strtol_(arg, NULL, 10); @@ -160,9 +160,9 @@ void jmp() { state->registers->eax = 0; for (int i = 0; i < state->num_labels; i++) { if (state->labels[i] == NULL) break; - if (strlen(state->labels[i]) - 1 != strlen(state->args->arg1)) + 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; diff --git a/src/interpreter_states.c b/src/interpreter_states.c index ee59b46..70dc5b0 100644 --- a/src/interpreter_states.c +++ b/src/interpreter_states.c @@ -129,7 +129,7 @@ ARRAY_ERR add_array(char* line) { } char *ptr = strtok_(line_copy, " "); //set ptr = strtok_(NULL, " "); //array name - if (ptr == NULL || strlen(line) <= (4 + strlen(ptr))) { + if (ptr == NULL || strlen__(line) <= (4 + strlen__(ptr))) { free_(line_copy); return ARRAY_ERROR; } @@ -145,7 +145,7 @@ ARRAY_ERR add_array(char* line) { #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 + 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); return ARRAY_ERROR; @@ -212,13 +212,13 @@ ARRAY_ERR add_array(char* line) { 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 = line + 4 + strlen__(state->ARRAYS_NAME[state->num_arrays]) + 1; //leave me alone i'm tired 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') { + if (strlen__(ptr) > 2 && ptr[0] == '0' && ptr[1] == 'x') { arr[j++] = strtol_(ptr, NULL, 16); } else { @@ -265,8 +265,8 @@ void sanitize_arguments() { //removes trailing spaces } int parse_arguments(char *line) { - strcpy(state->args->arg1, ""); - strcpy(state->args->arg2, ""); + strcpy__(state->args->arg1, ""); + strcpy__(state->args->arg2, ""); #ifdef _WIN32 char *line_cpy = strdup_(line); @@ -283,12 +283,12 @@ int parse_arguments(char *line) { free_(line_cpy); return 0; } - strcpy(state->args->arg1, arg); + strcpy__(state->args->arg1, arg); if ((arg = extract_arg(ptr, 1)) == NULL) { free_(line_cpy); return 0; } - strcpy(state->args->arg2, arg); + strcpy__(state->args->arg2, arg); free_(line_cpy); return 0; } diff --git a/src/libc.c b/src/libc.c index fb80d45..1635664 100644 --- a/src/libc.c +++ b/src/libc.c @@ -3,11 +3,40 @@ #ifdef _WIN32 HANDLE _crt_heap_ = 0; -#include +_ACRTIMP int __cdecl __stdio_common_vsprintf( + _In_ unsigned __int64 _Options, + _Out_writes_opt_z_(_BufferCount) char* _Buffer, + _In_ size_t _BufferCount, + _In_z_ _Printf_format_string_params_(2) char const* _Format, + _In_opt_ _locale_t _Locale, + va_list _ArgList +) { + return 0; //clang linker errors +} + +//#include +#ifndef _MSC_VER #ifdef _M_X64 - #define GetTEB() ((PTEB)__readgsqword(FIELD_OFFSET(NT_TIB, Self))) +unsigned long long __readgsqword(unsigned long long offset) { + unsigned long long value; + __asm__ __volatile__( + "movq %%gs:%1, %0" + : "=r" (value) + : "m" (*(unsigned long long*)(offset)) + ); + return value; +} #else - #define GetTEB() ((PTEB)__readfsdword(FIELD_OFFSET(NT_TIB, Self))) +unsigned long __readfsdword(unsigned long offset) { + unsigned long value; + __asm__ __volatile__( + "movl %%fs:%1, %0" + : "=r" (value) + : "m" (*(unsigned long*)(offset)) + ); + return value; +} +#endif #endif typedef LPVOID(WINAPI* fHeapAlloc)(HANDLE, DWORD, SIZE_T); @@ -67,15 +96,13 @@ void* malloc_(size_t _Size) { #else if (_crt_heap_ == 0) { if (pHeapCreate == NULL) { - char api[] = "MjfuHwjfyj"; - pHeapCreate = GetApi(L"KERNEL32.DLL", PCAESAR_DECRYPT(api)); + pHeapCreate = GetApi(L"KERNEL32.DLL", PCAESAR_DECRYPT("MjfuHwjfyj")); } _crt_heap_ = pHeapCreate(0, 0, 0); } if (pHeapAlloc == NULL) { - char api[] = "MjfuFqqth"; - pHeapAlloc = GetApi(L"KERNEL32.DLL", PCAESAR_DECRYPT(api)); + pHeapAlloc = GetApi(L"KERNEL32.DLL", PCAESAR_DECRYPT("MjfuFqqth")); } return pHeapAlloc(_crt_heap_, HEAP_ZERO_MEMORY, _Size); #endif @@ -87,8 +114,7 @@ void free_(void* _Block) { return; #else if (pHeapFree == NULL) { - char api[] = "MjfuKwjj"; - pHeapFree = GetApi(L"KERNEL32.DLL", PCAESAR_DECRYPT(api)); + pHeapFree = GetApi(L"KERNEL32.DLL", PCAESAR_DECRYPT("MjfuKwjj")); } pHeapFree(_crt_heap_, 0, _Block); return; @@ -101,21 +127,18 @@ void* realloc_(void* _Block, size_t _Size) { #else if (_crt_heap_ == 0) { if (pHeapCreate == NULL) { - char api[] = "MjfuHwjfyj"; - pHeapCreate = GetApi(L"KERNEL32.DLL", PCAESAR_DECRYPT(api)); + pHeapCreate = GetApi(L"KERNEL32.DLL", PCAESAR_DECRYPT("MjfuHwjfyj")); } _crt_heap_ = pHeapCreate(0, 0, 0); } if (_Block == NULL) { if (pHeapAlloc == NULL) { - char api[] = "MjfuFqqth"; - pHeapAlloc = GetApi(L"KERNEL32.DLL", PCAESAR_DECRYPT(api)); + pHeapAlloc = GetApi(L"KERNEL32.DLL", PCAESAR_DECRYPT("MjfuFqqth")); } return pHeapAlloc(_crt_heap_, HEAP_ZERO_MEMORY, _Size); } if (pHeapReAlloc == NULL) { - char api[] = "MjfuWjFqqth"; - pHeapReAlloc = GetApi(L"KERNEL32.DLL", PCAESAR_DECRYPT(api)); + pHeapReAlloc = GetApi(L"KERNEL32.DLL", PCAESAR_DECRYPT("MjfuWjFqqth")); } return pHeapReAlloc(_crt_heap_, HEAP_ZERO_MEMORY, _Block, _Size); #endif @@ -340,10 +363,10 @@ cont: /* NOTREACHED */ } -#ifdef _WIN32 +#ifdef _MSC_VER #pragma optimize("", off) #endif -void* memset__(void* a, int val, size_t size) { +PASM_NOOPT void* memset__(void* a, int val, size_t size) { #ifndef _WIN32 return memset(a, val, size); #endif @@ -353,7 +376,7 @@ void* memset__(void* a, int val, size_t size) { ((char*)a)[i] = (char)val; return a; } -#ifdef _WIN32 +#ifdef _MSC_VER #pragma optimize("", on) #endif @@ -384,7 +407,7 @@ wchar_t* wcsstr__(const wchar_t* haystack, const wchar_t* needle) { } HMODULE get_module(const wchar_t* mod) { - PTEB tebPtr = GetTEB(); + PTEB_ tebPtr = GetTEB(); PPEB_LDR_DATA ldrData = tebPtr->ProcessEnvironmentBlock->Ldr; PLIST_ENTRY moduleList = &(ldrData->InMemoryOrderModuleList); @@ -419,7 +442,7 @@ void* GetProcAddress_(HMODULE hModule, LPCSTR lpProcName) { for (DWORD i = 0; i < exportDir->NumberOfNames; i++) { const char* functionName = (const char*)((BYTE*)hModule + nameRVAs[i]); - if (strcmp(functionName, lpProcName) == 0) { + if (strcmp__(functionName, lpProcName) == 0) { DWORD funcRVA = addrRVAs[ordinals[i]]; void* funcPtr = (void*)((BYTE*)hModule + funcRVA); return funcPtr; diff --git a/src/libc.h b/src/libc.h index 215a3a3..3d9fc86 100644 --- a/src/libc.h +++ b/src/libc.h @@ -1,10 +1,122 @@ #pragma once #include +#ifndef _MSC_VER +#ifdef _WIN32 +#define PASM_NOOPT __attribute__((optimize("O0"))) +#else +#define PASM_NOOPT +#endif +#else +#define PASM_NOOPT +#endif + #ifdef _WIN32 #include +//#include + extern HANDLE _crt_heap_; +typedef long NTSTATUS; + +#define FD_SET_(fd, set) do { \ + if (((fd_set FAR *)(set))->fd_count < FD_SETSIZE) \ + ((fd_set FAR *)(set))->fd_array[((fd_set FAR *)(set))->fd_count++]=(fd);\ +} while(0) + +typedef struct _UNICODE_STRING { + USHORT Length; + USHORT MaximumLength; + PWSTR Buffer; +} UNICODE_STRING; +typedef UNICODE_STRING* PUNICODE_STRING; +typedef const UNICODE_STRING* PCUNICODE_STRING; + +typedef struct _PEB_LDR_DATA { + BYTE Reserved1[8]; + PVOID Reserved2[3]; + LIST_ENTRY InMemoryOrderModuleList; +} PEB_LDR_DATA, * PPEB_LDR_DATA; + +typedef struct _LDR_DATA_TABLE_ENTRY { + PVOID Reserved1[2]; + LIST_ENTRY InMemoryOrderLinks; + PVOID Reserved2[2]; + PVOID DllBase; + PVOID Reserved3[2]; + UNICODE_STRING FullDllName; + BYTE Reserved4[8]; + PVOID Reserved5[3]; + union { + ULONG CheckSum; + PVOID Reserved6; + } DUMMYUNIONNAME; + ULONG TimeDateStamp; +} LDR_DATA_TABLE_ENTRY, * PLDR_DATA_TABLE_ENTRY; + +typedef struct _RTL_USER_PROCESS_PARAMETERS { + BYTE Reserved1[16]; + PVOID Reserved2[10]; + UNICODE_STRING ImagePathName; + UNICODE_STRING CommandLine; +} RTL_USER_PROCESS_PARAMETERS, * PRTL_USER_PROCESS_PARAMETERS; + +typedef +VOID +(NTAPI* PPS_POST_PROCESS_INIT_ROUTINE) ( + VOID + ); + +typedef struct _PEB { + BYTE Reserved1[2]; + BYTE BeingDebugged; + BYTE Reserved2[1]; + PVOID Reserved3[2]; + PPEB_LDR_DATA Ldr; + PRTL_USER_PROCESS_PARAMETERS ProcessParameters; + PVOID Reserved4[3]; + PVOID AtlThunkSListPtr; + PVOID Reserved5; + ULONG Reserved6; + PVOID Reserved7; + ULONG Reserved8; + ULONG AtlThunkSListPtr32; + PVOID Reserved9[45]; + BYTE Reserved10[96]; + PPS_POST_PROCESS_INIT_ROUTINE PostProcessInitRoutine; + BYTE Reserved11[128]; + PVOID Reserved12[1]; + ULONG SessionId; +} PEB, * PPEB; + +typedef struct __TEB { + PVOID Reserved1[12]; + PPEB ProcessEnvironmentBlock; + PVOID Reserved2[399]; + BYTE Reserved3[1952]; + PVOID TlsSlots[64]; + BYTE Reserved4[8]; + PVOID Reserved5[26]; + PVOID ReservedForOle; + PVOID Reserved6[4]; + PVOID TlsExpansionSlots; +} TEB_, * PTEB_; + +#ifndef _MSC_VER +#ifdef _M_X64 +unsigned long long __readgsqword(unsigned long long offset); +#else +unsigned long __readfsdword(unsigned long offset); +#endif +#endif + +#ifdef _M_X64 +#define GetTEB() ((PTEB_)__readgsqword(FIELD_OFFSET(NT_TIB, Self))) +#else +#define GetTEB() ((PTEB_)__readfsdword(FIELD_OFFSET(NT_TIB, Self))) +#endif + +//#define LAIKA #define KEY 5 char* PCAESAR_DECRYPT(char* in); @@ -15,8 +127,10 @@ 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 strlen__(char const* src); int strcmp__(char const* s1, char const* s2); char* strstr__(char* str, char const* to_find); +char* strcpy__(char* dest, char const* src); 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); diff --git a/src/pasm.c b/src/pasm.c index 71897a0..c9bb6b4 100644 --- a/src/pasm.c +++ b/src/pasm.c @@ -31,16 +31,13 @@ int dprintf(int stream, const char * format, ...) { HANDLE h; if (pGetStdHandle == NULL) { - char api[] = "LjyXyiMfsiqj"; - pGetStdHandle = (fGetStdHandle)GetApi(L"KERNEL32.DLL", PCAESAR_DECRYPT(api)); + pGetStdHandle = (fGetStdHandle)GetApi(L"KERNEL32.DLL", PCAESAR_DECRYPT("LjyXyiMfsiqj")); } if (pwvsprintfA == NULL) { - char api[] = "|{xuwnsykF"; - pwvsprintfA = (fwvsprintfA)GetApi(L"USER32.dll", PCAESAR_DECRYPT(api)); + pwvsprintfA = (fwvsprintfA)GetApi(L"USER32.dll", PCAESAR_DECRYPT("|{xuwnsykF")); } if (pWriteFile == NULL) { - char api[] = "\\wnyjKnqj"; - pWriteFile = (fWriteFile)GetApi(L"KERNEL32.DLL", PCAESAR_DECRYPT(api)); + pWriteFile = (fWriteFile)GetApi(L"KERNEL32.DLL", PCAESAR_DECRYPT("\\wnyjKnqj")); } switch (stream) { @@ -64,7 +61,8 @@ int dprintf(int stream, const char * format, ...) { } } else { - OVERLAPPED ov = {0}; + OVERLAPPED ov; + memset__(&ov, 0, sizeof(OVERLAPPED)); if (!pWriteFile(h, buffer, length, &written, &ov)) { state->should_exit = 1; //broken socket -> host disconnected return -1; @@ -161,9 +159,9 @@ int pasm_run_script(const char *filename, char **file, size_t lines, int _fstrea free_(line); continue; } - 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'; + 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, " ")); @@ -180,7 +178,7 @@ int pasm_run_script(const char *filename, char **file, size_t lines, int _fstrea free_(line); break; } - if (file[state->curr_line][strlen(line) - 1] != ':') { + 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], " ")); set_exit_state(-1);