diff --git a/hyperdbg/script-engine/src/ScriptEngine.c b/hyperdbg/script-engine/ScriptEngine.c similarity index 98% rename from hyperdbg/script-engine/src/ScriptEngine.c rename to hyperdbg/script-engine/ScriptEngine.c index 599be33f..3f84dfdd 100644 --- a/hyperdbg/script-engine/src/ScriptEngine.c +++ b/hyperdbg/script-engine/ScriptEngine.c @@ -14,8 +14,8 @@ #include #include #include +#include "common.h" #include "parse_table.h" -#include "scanner.h" #include "ScriptEngine.h" @@ -69,7 +69,7 @@ PSYMBOL_BUFFER ScriptEngineParse(char *str) CurrentIn = Scan(str, &c); if (CurrentIn->Type == UNKNOWN) { - char* Message = "Invalid Syntax!"; + char* Message = "Invalid Token!"; CodeBuffer->Message = (char*)malloc(strlen(Message) + 1); strcpy(CodeBuffer->Message, Message); @@ -104,10 +104,9 @@ PSYMBOL_BUFFER ScriptEngineParse(char *str) CodeBuffer->Message = (char*)malloc(strlen(Message) + 1); strcpy(CodeBuffer->Message, Message); - RemoveTokenList(Stack); - RemoveTokenList(MatchedStack); RemoveToken(StartToken); RemoveToken(EndToken); + RemoveTokenList(MatchedStack); RemoveToken(CurrentIn); return CodeBuffer; } @@ -118,10 +117,9 @@ PSYMBOL_BUFFER ScriptEngineParse(char *str) CodeBuffer->Message = (char*)malloc(strlen(Message) + 1); strcpy(CodeBuffer->Message, Message); - RemoveTokenList(Stack); - RemoveTokenList(MatchedStack); RemoveToken(StartToken); RemoveToken(EndToken); + RemoveTokenList(MatchedStack); RemoveToken(CurrentIn); return CodeBuffer; } @@ -132,11 +130,9 @@ PSYMBOL_BUFFER ScriptEngineParse(char *str) CodeBuffer->Message = (char*)malloc(strlen(Message) + 1); strcpy(CodeBuffer->Message, Message); - - RemoveTokenList(Stack); - RemoveTokenList(MatchedStack); RemoveToken(StartToken); RemoveToken(EndToken); + RemoveTokenList(MatchedStack); RemoveToken(CurrentIn); return CodeBuffer; } @@ -164,14 +160,13 @@ PSYMBOL_BUFFER ScriptEngineParse(char *str) if (CurrentIn->Type == UNKNOWN) { - char* Message = "Invalid Syntax!"; + char* Message = "Invalid Token!"; CodeBuffer->Message = (char*)malloc(strlen(Message) + 1); strcpy(CodeBuffer->Message, Message); - RemoveTokenList(Stack); - RemoveTokenList(MatchedStack); RemoveToken(StartToken); RemoveToken(EndToken); + RemoveTokenList(MatchedStack); RemoveToken(CurrentIn); return CodeBuffer; } @@ -192,10 +187,9 @@ PSYMBOL_BUFFER ScriptEngineParse(char *str) CodeBuffer->Message = (char*)malloc(strlen(Message) + 1); strcpy(CodeBuffer->Message, Message); - RemoveTokenList(Stack); - RemoveTokenList(MatchedStack); RemoveToken(StartToken); RemoveToken(EndToken); + RemoveTokenList(MatchedStack); RemoveToken(CurrentIn); return CodeBuffer; } @@ -357,7 +351,7 @@ void CodeGen(TOKEN_LIST MatchedStack, PSYMBOL_BUFFER CodeBuffer, TOKEN Operator) char HasTwoOperand(TOKEN Operator) { - unsigned int n = sizeof(OneOperandSemanticRules) / sizeof(char*); + unsigned int n = 13;//sizeof(OneOperandSemanticRules) / sizeof(char*); for (int i = 0; i < n; i++) { if (!strcmp(Operator->Value, OneOperandSemanticRules[i])) diff --git a/hyperdbg/script-engine/src/ScriptEngine.h b/hyperdbg/script-engine/ScriptEngine.h similarity index 89% rename from hyperdbg/script-engine/src/ScriptEngine.h rename to hyperdbg/script-engine/ScriptEngine.h index 9737129e..2b9b3adc 100644 --- a/hyperdbg/script-engine/src/ScriptEngine.h +++ b/hyperdbg/script-engine/ScriptEngine.h @@ -11,29 +11,16 @@ */ #pragma once -#include "scanner.h" + + #include #include "ScriptEngineCommon.h" +#include "scanner.h" +#include "common.h" + -// TODO : Automate generating this array -const char* OneOperandSemanticRules[] = -{ - "@POI", - "@DB", - "@DD", - "@DW", - "@DQ", - "@STR", - "@WSTR", - "@SIZEOF", - "@NOT", - "@NEG", - "@HI", - "@LOW", - "@PRINT" -}; char TempMap[MAX_TEMP_COUNT] = { 0 }; unsigned int IdCounter = 0; diff --git a/hyperdbg/script-engine/common.c b/hyperdbg/script-engine/common.c new file mode 100644 index 00000000..41abdcbe --- /dev/null +++ b/hyperdbg/script-engine/common.c @@ -0,0 +1,419 @@ + +#include +#include +#include +#include +#include "common.h" + + + +/** + * @brief allocates a new token + * + * @return Token + */ +TOKEN NewToken() +{ + TOKEN Token; + + // + // Allocates memory for token and its value + // + Token = (TOKEN)malloc(sizeof(*Token)); + Token->Value = (char*)calloc(TOKEN_VALUE_MAX_LEN, sizeof(char)); + + // + // Init fields + // + strcpy(Token->Value, ""); + Token->Type = UNKNOWN; + Token->len = 0; + Token->max_len = TOKEN_VALUE_MAX_LEN; + + return Token; +} + +/** + * @brief removes allocated memory of a token + * + * @param Token + */ +void RemoveToken(TOKEN Token) +{ + free(Token->Value); + free(Token); + + return; +} + +/** + * @brief prints token + * @detail prints value and type of token + * + * @param Token + */ +void PrintToken(TOKEN Token) +{ + + // + // Prints vlaue of the Token + // + if (Token->Type == WHITE_SPACE) + { + printf("< :"); + } + else + { + printf("<'%s' : ", Token->Value); + } + + // + // Prints type of the Token + // + switch (Token->Type) + { + case ID: + printf(" ID>\n"); + break; + case DECIMAL: + printf(" DECIMAL>\n"); + break; + case HEX: + printf(" HEX>\n"); + break; + case OCTAL: + printf(" OCTAL>\n"); + break; + case BINARY: + printf(" BINARY>\n"); + break; + case SPECIAL_TOKEN: + printf(" SPECIAL_TOKEN>\n"); + break; + case KEYWORD: + printf(" KEYWORD>\n"); + break; + case WHITE_SPACE: + printf(" WHITE_SPACE>\n"); + break; + case COMMENT: + printf(" COMMENT>\n"); + break; + case REGISTER: + printf(" REGISTER>\n"); + break; + case PSEUDO_REGISTER: + printf(" PSEUDO_REGISTER>\n"); + break; + case SEMANTIC_RULE: + printf(" SEMANTIC_RULE>\n"); + break; + case NON_TERMINAL: + printf(" NON_TERMINAL>\n"); + break; + case END_OF_STACK: + printf(" END_OF_STACK>\n"); + break; + case UNKNOWN: + printf(" UNKNOWN>\n"); + break; + + default: + printf(" ERROR>\n"); + break; + } +} + +/** + * @brief appends char to the token value + * + * @param Token + * @param char + */ +void Append(TOKEN Token, char c) +{ + // + // Check overflow of the string + // + if (Token->len >= Token->max_len - 1) + { + // + // Double the length of the allocated space for the string + // + Token->max_len *= 2; + char* NewValue = (char*)calloc(Token->max_len, sizeof(char)); + + + // + // Free Old buffer and update the pointer + // + strncpy(NewValue, Token->Value, Token->len); + free(Token->Value); + Token->Value = NewValue; + } + + + // + // Append the new charcter to the string + // + strncat(Token->Value, &c, 1); + Token->len++; + + + +} + +/** + * @brief allocates a new TOKEN_LIST + * + * @return TOKEN_LIST + */ +TOKEN_LIST NewTokenList(void) +{ + TOKEN_LIST TokenList; + + // + // Allocation of memory for TOKEN_LIST structure + // + TokenList = (TOKEN_LIST)malloc(sizeof(*TokenList)); + + + // + // Initialize fields of TOKEN_LIST + // + TokenList->Pointer = 0; + TokenList->Size = TOKEN_LIST_INIT_SIZE; + + // + // Allocation of memory for TOKEN_LIST buffer + // + TokenList->Head = (TOKEN*)malloc(TokenList->Size * sizeof(TOKEN)); + + return TokenList; +} + +/** + * @brief removes allocated memory of a TOKEN_LIST + * + * @param TokenList + */ +void RemoveTokenList(TOKEN_LIST TokenList) +{ + TOKEN Token; + for (uintptr_t i = 0; i < TokenList->Pointer; i++) + { + Token = *(TokenList->Head + i); + RemoveToken(Token); + } + free(TokenList->Head); + free(TokenList); + + return; +} + + +/** + * @brief prints each Token inside a TokenList + * + * @param TokenList + */ +void PrintTokenList(TOKEN_LIST TokenList) +{ + TOKEN Token; + for (uintptr_t i = 0; i < TokenList->Pointer; i++) + { + Token = *(TokenList->Head + i); + PrintToken(Token); + } + +} + +/** + * @brief adds Token to the last empty position of TokenList + * + * @param Token + * @param TokenList + * @return TokenList + */ +TOKEN_LIST Push(TOKEN_LIST TokenList, TOKEN Token) +{ + // + // Calculate address to write new token + // + uintptr_t Head = (uintptr_t)TokenList->Head; + uintptr_t Pointer = (uintptr_t)TokenList->Pointer; + TOKEN* WriteAddr = (TOKEN*)(Head + Pointer * sizeof(TOKEN)); + + // + // Write Token to appropriate address in TokenList + // + *WriteAddr = Token; + + // + // Update Pointer + // + TokenList->Pointer++; + + // + // Handle overflow + // + if (Pointer == TokenList->Size - 1) + { + // + // Allocate a new buffer for string list with doubled length + // + TOKEN* NewHead = (TOKEN*)malloc(2 * TokenList->Size * sizeof(TOKEN)); + + // + // Copy old buffer to new buffer + // + memcpy(NewHead, TokenList->Head, TokenList->Size * sizeof(TOKEN)); + + // + // Free old buffer + // + free(TokenList->Head); + + // + // Update Head and size of TokenList + // + TokenList->Size = TokenList->Size * 2; + TokenList->Head = NewHead; + } + + return TokenList; +} +/** + * @brief removes last Token of a TokenList and returns it + * + * @param TokenList + @ @return Token + */ +TOKEN Pop(TOKEN_LIST TokenList) +{ + // + // Calculate address to read most recent token + // + if (TokenList->Pointer > 0) + TokenList->Pointer--; + uintptr_t Head = (uintptr_t)TokenList->Head; + uintptr_t Pointer = (uintptr_t)TokenList->Pointer; + TOKEN* ReadAddr = (TOKEN*)(Head + Pointer * sizeof(TOKEN)); + + + return *ReadAddr; +} + + +/** + * @brief returns last Token of a TokenList + * + * @param TokenList + * @return Token + */ +TOKEN Top(TOKEN_LIST TokenList) +{ + // + // Calculate address to read most recent token + // + uintptr_t Head = (uintptr_t)TokenList->Head; + uintptr_t Pointer = (uintptr_t)TokenList->Pointer - 1; + TOKEN* ReadAddr = (TOKEN*)(Head + Pointer * sizeof(TOKEN)); + + return *ReadAddr; +} + +/** +* @brief cheks whether input char belongs to hexadecimal digit-set or not +* +* @param char +* @return bool +*/ +char IsHex(char c) +{ + if ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')) + return 1; + else + return 0; +} + +/** +* @brief cheks whether input char belongs to decimal digit-set or not +* +* @param char +* @return bool +*/ +char IsDecimal(char c) +{ + if (c >= '0' && c <= '9') + return 1; + else + return 0; +} + +/** +* @brief cheks whether input char belongs to alphabet set or not +* +* @param char +* @return bool +*/ +char IsLetter(char c) +{ + if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')) + return 1; + else + { + return 0; + } +} + +/** +* @brief cheks whether input char belongs to binary digit-set or not +* +* @param char +* @return bool +*/ +char IsBinary(char c) +{ + if (c == '0' || c == '1') + return 1; + else + { + return 0; + } +} + +/** +* @brief cheks whether input char belongs to octal digit-set or not +* +* @param char +* @return bool +*/ +char IsOctal(char c) +{ + if (c >= '0' && c <= '7') + return 1; + else + return 0; +} + + + + +// TODO : Automate generating this array +const char* OneOperandSemanticRules[] = +{ + "@POI", + "@DB", + "@DD", + "@DW", + "@DQ", + "@STR", + "@WSTR", + "@SIZEOF", + "@NOT", + "@NEG", + "@HI", + "@LOW", + "@PRINT" +}; diff --git a/hyperdbg/script-engine/src/scanner.h b/hyperdbg/script-engine/common.h similarity index 83% rename from hyperdbg/script-engine/src/scanner.h rename to hyperdbg/script-engine/common.h index 33ec6676..f631da14 100644 --- a/hyperdbg/script-engine/src/scanner.h +++ b/hyperdbg/script-engine/common.h @@ -1,7 +1,10 @@ -#pragma once -#include +#pragma once + +#ifndef COMMON_H +#define COMMON_H + #define SYMBOL_BUFFER_INIT_SIZE 128 #define MAX_TEMP_COUNT 32 @@ -15,6 +18,9 @@ */ #define TOKEN_LIST_INIT_SIZE 1024 +extern const char* KeywordList[]; +extern const char* OneOperandSemanticRules[]; + /** * @brief enumerates possible types for token */ @@ -66,10 +72,8 @@ typedef struct _TOKEN_LIST unsigned int Size; } *TOKEN_LIST; -/** -* @brief number of read characters from input -*/ -unsigned int InputIdx; +// TODO: automate generation of KeyWordList + //////////////////////////////////////////////////// @@ -99,7 +103,6 @@ TOKEN Pop(TOKEN_LIST TokenList); TOKEN Top(TOKEN_LIST TokenList); - //////////////////////////////////////////////////// // Util Functions // //////////////////////////////////////////////////// @@ -114,13 +117,6 @@ char IsBinary(char c); char IsOctal(char c); -//////////////////////////////////////////////////// -// Interfacing functions // -//////////////////////////////////////////////////// -TOKEN GetToken(char* c, char* str); -TOKEN Scan(char* str, char* c); +#endif // !COMMON_H -char sgetc(char* str); - -char IsKeyword(char* str); diff --git a/hyperdbg/script-engine/input.txt b/hyperdbg/script-engine/input.txt index 9f5dde05..a171613e 100644 --- a/hyperdbg/script-engine/input.txt +++ b/hyperdbg/script-engine/input.txt @@ -1,5 +1,7 @@ -//x1 = poi(poi((poi(($proc&neg(1000`0000))+10)^poi(poi(poi(poi(poi(poi(poi(poi($prcb+18)+220)+648)+8)-240)+2a0)))^neg(0n6708588087252463955)^($proc&neg(100000)))-8)-1080); -test= poi(2 + 5 * 1); + + +x1 = poi(poi((poi(($proc&neg(1000`0000))+10)^poi(poi(poi(poi(poi(poi(poi(poi($prcb+18)+220)+648)+8)-240)+2a0)))^neg(0n6708588087252463955)^($proc&neg(100000)))-8)-1080); +//test= poi(2); //a2= poi((01)+ 2 * 3) * poi(2); // Binary //test=dw(@rcx+($proc|3+poi(poi(@rax)))); /* diff --git a/hyperdbg/script-engine/src/parse_table.h b/hyperdbg/script-engine/parse_table.c similarity index 54% rename from hyperdbg/script-engine/src/parse_table.h rename to hyperdbg/script-engine/parse_table.c index dcbbd1dd..696dc858 100644 --- a/hyperdbg/script-engine/src/parse_table.h +++ b/hyperdbg/script-engine/parse_table.c @@ -1,11 +1,5 @@ -#ifndef PARSE_TABLE_H -#define PARSE_TABLE_H -#include "scanner.h" -#define RULES_COUNT 56 -#define TERMINAL_COUNT 36 -#define NONETERMINAL_COUNT 25 -#define START_VARIABLE "S" -#define MAX_RHS_LEN 6 +#include "parse_table.h" +#include "common.h" const struct _TOKEN Lhs[RULES_COUNT]= { {NON_TERMINAL, "S"}, @@ -62,7 +56,6 @@ const struct _TOKEN Lhs[RULES_COUNT]= {NON_TERMINAL, "E10"}, {NON_TERMINAL, "E10"}, {NON_TERMINAL, "E10"}, - {NON_TERMINAL, "E10"}, {NON_TERMINAL, "E10"} }; const struct _TOKEN Rhs[RULES_COUNT][MAX_RHS_LEN]= @@ -111,7 +104,6 @@ const struct _TOKEN Rhs[RULES_COUNT][MAX_RHS_LEN]= {{KEYWORD, "str"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "E0"},{SEMANTIC_RULE, "@STR"},{SPECIAL_TOKEN, ")"}}, {{KEYWORD, "wstr"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "E0"},{SEMANTIC_RULE, "@WSTR"},{SPECIAL_TOKEN, ")"}}, {{KEYWORD, "sizeof"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "E0"},{SEMANTIC_RULE, "@SIZEOF"},{SPECIAL_TOKEN, ")"}}, - {{KEYWORD, "not"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "E0"},{SEMANTIC_RULE, "@NOT"},{SPECIAL_TOKEN, ")"}}, {{KEYWORD, "neg"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "E0"},{SEMANTIC_RULE, "@NEG"},{SPECIAL_TOKEN, ")"}}, {{KEYWORD, "hi"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "E0"},{SEMANTIC_RULE, "@HI"},{SPECIAL_TOKEN, ")"}}, {{KEYWORD, "low"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "E0"},{SEMANTIC_RULE, "@LOW"},{SPECIAL_TOKEN, ")"}}, @@ -173,7 +165,6 @@ const unsigned int RhsSize[RULES_COUNT]= 5, 5, 5, -5, 3, 2, 2, @@ -185,97 +176,109 @@ const unsigned int RhsSize[RULES_COUNT]= }; const char* NoneTerminalMap[NONETERMINAL_COUNT]= { -"S", -"E6", "E10", -"E7'", -"E5", "E8'", -"S'", -"E2'", -"E9'", -"E9", -"E2", -"E4", "E8", -"E0'", -"E3'", -"E7", -"E5'", -"E3", -"C", -"E6'", -"E4'", "E1", +"E9'", +"E2", +"E7", +"E2'", +"E3", +"E5'", +"E9", +"E0'", +"S", "C'", +"E5", +"C", +"S'", +"E6", +"E4'", +"E4", +"E6'", +"E0", +"E3'", "E1'", -"E0" +"E7'" }; const char* TerminalMap[TERMINAL_COUNT]= { -"&", -"neg", -"<<", +"-", +"=", +"_id", "|", "_octal", -"dq", -"*", -"_hex", -")", -"sizeof", -"_pseudo_register", -"wstr", -"hi", -"not", -"_register", -"str", -"_id", -"-", -"/", -"func", -"%", -"print", -"(", -"low", -";", -"_binary", -">>", "db", -"$", -"_decimal", +"dq", +"hi", +"_pseudo_register", +"*", "dw", -"=", -"^", "poi", +"print", "dd", -"+" +"wstr", +"sizeof", +"(", +"/", +"_binary", +"%", +"+", +">>", +";", +"^", +"$", +")", +"neg", +"_decimal", +"<<", +"_register", +"_hex", +"func", +"str", +"&", +"low" }; const int ParseTable[NONETERMINAL_COUNT][TERMINAL_COUNT]= { - {-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,0 ,-1 ,-1 ,-1 ,-1 ,0 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 }, - {-1 ,24 ,-1 ,-1 ,24 ,24 ,-1 ,24 ,-1 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,-1 ,-1 ,-1 ,24 ,-1 ,-1 ,24 ,24 ,-1 ,24 ,-1 ,24 ,-1 ,24 ,24 ,-1 ,-1 ,24 ,24 ,-1 }, - {-1 ,45 ,-1 ,-1 ,52 ,40 ,-1 ,50 ,-1 ,43 ,55 ,42 ,46 ,44 ,49 ,41 ,-1 ,-1 ,-1 ,54 ,-1 ,-1 ,48 ,47 ,-1 ,53 ,-1 ,37 ,-1 ,51 ,39 ,-1 ,-1 ,36 ,38 ,-1 }, - {29 ,-1 ,29 ,29 ,-1 ,-1 ,28 ,-1 ,29 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,29 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,29 ,-1 ,29 ,-1 ,-1 ,-1 ,-1 ,-1 ,29 ,-1 ,-1 ,29 }, - {-1 ,21 ,-1 ,-1 ,21 ,21 ,-1 ,21 ,-1 ,21 ,21 ,21 ,21 ,21 ,21 ,21 ,-1 ,-1 ,-1 ,21 ,-1 ,-1 ,21 ,21 ,-1 ,21 ,-1 ,21 ,-1 ,21 ,21 ,-1 ,-1 ,21 ,21 ,-1 }, - {32 ,-1 ,32 ,32 ,-1 ,-1 ,32 ,-1 ,32 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,32 ,31 ,-1 ,-1 ,-1 ,-1 ,-1 ,32 ,-1 ,32 ,-1 ,-1 ,-1 ,-1 ,-1 ,32 ,-1 ,-1 ,32 }, - {-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,1 ,-1 ,-1 ,-1 ,-1 ,1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,2 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 }, - {13 ,-1 ,-1 ,14 ,-1 ,-1 ,-1 ,-1 ,14 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,14 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,14 ,-1 ,-1 ,-1 }, - {35 ,-1 ,35 ,35 ,-1 ,-1 ,35 ,-1 ,35 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,35 ,35 ,-1 ,34 ,-1 ,-1 ,-1 ,35 ,-1 ,35 ,-1 ,-1 ,-1 ,-1 ,-1 ,35 ,-1 ,-1 ,35 }, - {-1 ,33 ,-1 ,-1 ,33 ,33 ,-1 ,33 ,-1 ,33 ,33 ,33 ,33 ,33 ,33 ,33 ,-1 ,-1 ,-1 ,33 ,-1 ,-1 ,33 ,33 ,-1 ,33 ,-1 ,33 ,-1 ,33 ,33 ,-1 ,-1 ,33 ,33 ,-1 }, - {-1 ,12 ,-1 ,-1 ,12 ,12 ,-1 ,12 ,-1 ,12 ,12 ,12 ,12 ,12 ,12 ,12 ,-1 ,-1 ,-1 ,12 ,-1 ,-1 ,12 ,12 ,-1 ,12 ,-1 ,12 ,-1 ,12 ,12 ,-1 ,-1 ,12 ,12 ,-1 }, - {-1 ,18 ,-1 ,-1 ,18 ,18 ,-1 ,18 ,-1 ,18 ,18 ,18 ,18 ,18 ,18 ,18 ,-1 ,-1 ,-1 ,18 ,-1 ,-1 ,18 ,18 ,-1 ,18 ,-1 ,18 ,-1 ,18 ,18 ,-1 ,-1 ,18 ,18 ,-1 }, - {-1 ,30 ,-1 ,-1 ,30 ,30 ,-1 ,30 ,-1 ,30 ,30 ,30 ,30 ,30 ,30 ,30 ,-1 ,-1 ,-1 ,30 ,-1 ,-1 ,30 ,30 ,-1 ,30 ,-1 ,30 ,-1 ,30 ,30 ,-1 ,-1 ,30 ,30 ,-1 }, - {-1 ,-1 ,-1 ,7 ,-1 ,-1 ,-1 ,-1 ,8 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,8 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 }, - {17 ,-1 ,-1 ,17 ,-1 ,-1 ,-1 ,-1 ,17 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,17 ,-1 ,16 ,-1 ,-1 ,-1 ,-1 ,-1 ,17 ,-1 ,-1 ,-1 }, - {-1 ,27 ,-1 ,-1 ,27 ,27 ,-1 ,27 ,-1 ,27 ,27 ,27 ,27 ,27 ,27 ,27 ,-1 ,-1 ,-1 ,27 ,-1 ,-1 ,27 ,27 ,-1 ,27 ,-1 ,27 ,-1 ,27 ,27 ,-1 ,-1 ,27 ,27 ,-1 }, - {23 ,-1 ,23 ,23 ,-1 ,-1 ,-1 ,-1 ,23 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,23 ,-1 ,23 ,-1 ,-1 ,-1 ,-1 ,-1 ,23 ,-1 ,-1 ,22 }, - {-1 ,15 ,-1 ,-1 ,15 ,15 ,-1 ,15 ,-1 ,15 ,15 ,15 ,15 ,15 ,15 ,15 ,-1 ,-1 ,-1 ,15 ,-1 ,-1 ,15 ,15 ,-1 ,15 ,-1 ,15 ,-1 ,15 ,15 ,-1 ,-1 ,15 ,15 ,-1 }, - {-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,3 ,-1 ,-1 ,-1 ,-1 ,4 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 }, - {26 ,-1 ,26 ,26 ,-1 ,-1 ,-1 ,-1 ,26 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,25 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,26 ,-1 ,26 ,-1 ,-1 ,-1 ,-1 ,-1 ,26 ,-1 ,-1 ,26 }, - {20 ,-1 ,19 ,20 ,-1 ,-1 ,-1 ,-1 ,20 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,20 ,-1 ,20 ,-1 ,-1 ,-1 ,-1 ,-1 ,20 ,-1 ,-1 ,-1 }, - {-1 ,9 ,-1 ,-1 ,9 ,9 ,-1 ,9 ,-1 ,9 ,9 ,9 ,9 ,9 ,9 ,9 ,-1 ,-1 ,-1 ,9 ,-1 ,-1 ,9 ,9 ,-1 ,9 ,-1 ,9 ,-1 ,9 ,9 ,-1 ,-1 ,9 ,9 ,-1 }, - {-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,5 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 }, - {-1 ,-1 ,-1 ,11 ,-1 ,-1 ,-1 ,-1 ,11 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,11 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,10 ,-1 ,-1 ,-1 }, - {-1 ,6 ,-1 ,-1 ,6 ,6 ,-1 ,6 ,-1 ,6 ,6 ,6 ,6 ,6 ,6 ,6 ,-1 ,-1 ,-1 ,6 ,-1 ,-1 ,6 ,6 ,-1 ,6 ,-1 ,6 ,-1 ,6 ,6 ,-1 ,-1 ,6 ,6 ,-1 } + {-1 ,-1 ,-1 ,-1 ,51 ,37 ,40 ,45 ,54 ,-1 ,39 ,36 ,-1 ,38 ,42 ,43 ,47 ,-1 ,52 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,44 ,50 ,-1 ,48 ,49 ,53 ,41 ,-1 ,46 }, + {32 ,-1 ,-1 ,32 ,-1 ,-1 ,-1 ,-1 ,-1 ,32 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,31 ,-1 ,-1 ,32 ,32 ,32 ,32 ,-1 ,32 ,-1 ,-1 ,32 ,-1 ,-1 ,-1 ,-1 ,32 ,-1 }, + {-1 ,-1 ,-1 ,-1 ,30 ,30 ,30 ,30 ,30 ,-1 ,30 ,30 ,-1 ,30 ,30 ,30 ,30 ,-1 ,30 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,30 ,30 ,-1 ,30 ,30 ,30 ,30 ,-1 ,30 }, + {-1 ,-1 ,-1 ,-1 ,9 ,9 ,9 ,9 ,9 ,-1 ,9 ,9 ,-1 ,9 ,9 ,9 ,9 ,-1 ,9 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,9 ,9 ,-1 ,9 ,9 ,9 ,9 ,-1 ,9 }, + {35 ,-1 ,-1 ,35 ,-1 ,-1 ,-1 ,-1 ,-1 ,35 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,35 ,-1 ,34 ,35 ,35 ,35 ,35 ,-1 ,35 ,-1 ,-1 ,35 ,-1 ,-1 ,-1 ,-1 ,35 ,-1 }, + {-1 ,-1 ,-1 ,-1 ,12 ,12 ,12 ,12 ,12 ,-1 ,12 ,12 ,-1 ,12 ,12 ,12 ,12 ,-1 ,12 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,12 ,12 ,-1 ,12 ,12 ,12 ,12 ,-1 ,12 }, + {-1 ,-1 ,-1 ,-1 ,27 ,27 ,27 ,27 ,27 ,-1 ,27 ,27 ,-1 ,27 ,27 ,27 ,27 ,-1 ,27 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,27 ,27 ,-1 ,27 ,27 ,27 ,27 ,-1 ,27 }, + {-1 ,-1 ,-1 ,14 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,14 ,14 ,-1 ,14 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,13 ,-1 }, + {-1 ,-1 ,-1 ,-1 ,15 ,15 ,15 ,15 ,15 ,-1 ,15 ,15 ,-1 ,15 ,15 ,15 ,15 ,-1 ,15 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,15 ,15 ,-1 ,15 ,15 ,15 ,15 ,-1 ,15 }, + {-1 ,-1 ,-1 ,23 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,22 ,23 ,23 ,23 ,-1 ,23 ,-1 ,-1 ,23 ,-1 ,-1 ,-1 ,-1 ,23 ,-1 }, + {-1 ,-1 ,-1 ,-1 ,33 ,33 ,33 ,33 ,33 ,-1 ,33 ,33 ,-1 ,33 ,33 ,33 ,33 ,-1 ,33 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,33 ,33 ,-1 ,33 ,33 ,33 ,33 ,-1 ,33 }, + {-1 ,-1 ,-1 ,7 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,8 ,-1 ,-1 ,8 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 }, + {-1 ,-1 ,0 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,0 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 }, + {-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,5 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 }, + {-1 ,-1 ,-1 ,-1 ,21 ,21 ,21 ,21 ,21 ,-1 ,21 ,21 ,-1 ,21 ,21 ,21 ,21 ,-1 ,21 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,21 ,21 ,-1 ,21 ,21 ,21 ,21 ,-1 ,21 }, + {-1 ,-1 ,3 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,4 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 }, + {-1 ,-1 ,1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,2 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 }, + {-1 ,-1 ,-1 ,-1 ,24 ,24 ,24 ,24 ,24 ,-1 ,24 ,24 ,-1 ,24 ,24 ,24 ,24 ,-1 ,24 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,24 ,24 ,-1 ,24 ,24 ,24 ,24 ,-1 ,24 }, + {-1 ,-1 ,-1 ,20 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,20 ,20 ,20 ,-1 ,20 ,-1 ,-1 ,19 ,-1 ,-1 ,-1 ,-1 ,20 ,-1 }, + {-1 ,-1 ,-1 ,-1 ,18 ,18 ,18 ,18 ,18 ,-1 ,18 ,18 ,-1 ,18 ,18 ,18 ,18 ,-1 ,18 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,18 ,18 ,-1 ,18 ,18 ,18 ,18 ,-1 ,18 }, + {25 ,-1 ,-1 ,26 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,26 ,26 ,26 ,26 ,-1 ,26 ,-1 ,-1 ,26 ,-1 ,-1 ,-1 ,-1 ,26 ,-1 }, + {-1 ,-1 ,-1 ,-1 ,6 ,6 ,6 ,6 ,6 ,-1 ,6 ,6 ,-1 ,6 ,6 ,6 ,6 ,-1 ,6 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,6 ,6 ,-1 ,6 ,6 ,6 ,6 ,-1 ,6 }, + {-1 ,-1 ,-1 ,17 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,16 ,17 ,17 ,-1 ,17 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,17 ,-1 }, + {-1 ,-1 ,-1 ,11 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,11 ,10 ,-1 ,11 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 }, + {29 ,-1 ,-1 ,29 ,-1 ,-1 ,-1 ,-1 ,-1 ,28 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,29 ,29 ,29 ,29 ,-1 ,29 ,-1 ,-1 ,29 ,-1 ,-1 ,-1 ,-1 ,29 ,-1 } +}; +const char* KeywordList[]= { +"print", +"poi", +"db", +"dd", +"dw", +"dq", +"str", +"wstr", +"sizeof", +"neg", +"hi", +"low" }; -#endif diff --git a/hyperdbg/script-engine/parse_table.h b/hyperdbg/script-engine/parse_table.h new file mode 100644 index 00000000..368f48d1 --- /dev/null +++ b/hyperdbg/script-engine/parse_table.h @@ -0,0 +1,16 @@ +#ifndef PARSE_TABLE_H +#define PARSE_TABLE_H +#define RULES_COUNT 55 +#define TERMINAL_COUNT 35 +#define NONETERMINAL_COUNT 25 +#define START_VARIABLE "S" +#define MAX_RHS_LEN 6 +#define KEYWORD_LIST_LENGTH 12 +extern const struct _TOKEN Lhs[RULES_COUNT]; +extern const struct _TOKEN Rhs[RULES_COUNT][MAX_RHS_LEN]; +extern const unsigned int RhsSize[RULES_COUNT]; +const char* NoneTerminalMap[NONETERMINAL_COUNT]; +const char* TerminalMap[TERMINAL_COUNT]; +const int ParseTable[NONETERMINAL_COUNT][TERMINAL_COUNT]; +extern const char* KeywordList[]; +#endif diff --git a/hyperdbg/script-engine/pch.h b/hyperdbg/script-engine/pch.h index 885d5d62..fbd07e40 100644 --- a/hyperdbg/script-engine/pch.h +++ b/hyperdbg/script-engine/pch.h @@ -1,13 +1,16 @@ + +#pragma once // pch.h: This is a precompiled header file. // Files listed below are compiled only once, improving build performance for future builds. // This also affects IntelliSense performance, including code completion and many code browsing features. // However, files listed here are ALL re-compiled if any one of them is updated between builds. // Do not add files here that you will be updating frequently as this negates the performance advantage. + + #ifndef PCH_H #define PCH_H -// add headers that you want to pre-compile here #include "framework.h" - +//#include "common.h" #endif //PCH_H diff --git a/hyperdbg/script-engine/python/Grammer.txt b/hyperdbg/script-engine/python/Grammar.txt similarity index 69% rename from hyperdbg/script-engine/python/Grammer.txt rename to hyperdbg/script-engine/python/Grammar.txt index e63badb0..b0b1dd75 100644 --- a/hyperdbg/script-engine/python/Grammer.txt +++ b/hyperdbg/script-engine/python/Grammar.txt @@ -1,10 +1,13 @@ +.oneOpfunc1->poi db dd dw dq str wstr sizeof neg hi low +.oneOpfunc2->print S->C ; S' S'->C ; S' S'->eps C->@PUSH _id = E0 @MOV C' -C->print ( E0 @PRINT ) +C->.oneOpfunc2 ( E0 @.oneOpfunc2 ) C'->eps + E0->E1 E0' E0'->| E1 @OR E0' E0'->eps @@ -46,22 +49,14 @@ E9->E10 E9' E9'->% E10 @MOD E9' E9'->eps -E10->poi ( E0 @POI ) -E10->db ( E0 @DB ) -E10->dd ( E0 @DD ) -E10->dw ( E0 @DW ) -E10->dq ( E0 @DQ ) -E10->str ( E0 @STR ) -E10->wstr ( E0 @WSTR ) -E10->sizeof ( E0 @SIZEOF ) -E10->not ( E0 @NOT ) -E10->neg ( E0 @NEG ) -E10->hi ( E0 @HI ) -E10->low ( E0 @LOW ) +E10->.oneOpfunc1 ( E0 @.oneOpfunc1 ) + E10->( E0 ) + +# Types must have '_' at the first E10->@PUSH _register # numbers diff --git a/hyperdbg/script-engine/python/parse_table_generator.py b/hyperdbg/script-engine/python/parse_table_generator.py index 549c2438..905cbe9b 100644 --- a/hyperdbg/script-engine/python/parse_table_generator.py +++ b/hyperdbg/script-engine/python/parse_table_generator.py @@ -2,10 +2,10 @@ * @file parse_table_generator.py * @author M.H. Gholamrezei (gholamrezaei.mh@gmail.com) * @brief Script engine Parse table generator - * @details This program reads grammer from Greammer.txt file + * @details This program reads grammar from Greammer.txt file * placed in the same directory of the program - * and creates ParseTable.h which is used by the - * parser of script engine. + * and creates parse_table.h and parse_table.c which is + * used by the parser of script engine. * @version 0.1 * @date 2020-10-24 * @@ -26,15 +26,18 @@ def Read(Tokens): class Parser: def __init__(self): - # The file which contains the grammer of the language - self.GrammerFile = open("Grammer.txt", "r") + # The file which contains the grammar of the language + self.GrammarFile = open("Grammar.txt", "r") # The file which is used by parser for parsing the input - self.OutputFile = open("..\src\parse_table.h", "w") + self.SourceFile = open("..\\parse_table.c", "w") + self.HeaderFile = open("..\\parse_table.h", "w") + # Lists which used for storing the rules: # Right Hand Side(Rhs) self.RhsList = [] + # Left Hand Side(Lhs) self.LhsList = [] @@ -55,6 +58,9 @@ class Parser: # INVALID rule indicator self.INVALID = -1 + self.MapsList = dict() + self.keywordList = [] + # Dictionaries used for storing first and follow sets self.FirstDict = dict() self.FollowDict = dict() @@ -62,66 +68,75 @@ class Parser: def Run(self): - # Read grammer from input file and intialize grammer related variables - self.ReadGrammer() + # Read grammar from input file and intialize grammar related variables + self.ReadGrammar() # Calculate "First Set" for all nonterminals and print it self.FindAllFirsts() - print("Firsts:") - self.PrintFirsts() - print("________________________________________________________________________________") + # print("Firsts:") + # self.PrintFirsts() + # print("________________________________________________________________________________") # Calculate "Follow Set" for all nonterminals and print it self.FindAllFollows() - print("Follows:") - self.PrintFollows() - print("________________________________________________________________________________") + # print("Follows:") + # self.PrintFollows() + # print("________________________________________________________________________________") # Calculate "Prdicted Set" for each rule and print it self.FindAllPredicts() - print("Predicts:") - self.print_predicts() - print("________________________________________________________________________________") + # print("Predicts:") + # self.print_predicts() + # print("________________________________________________________________________________") # Fills "Parse Table" according to calculted "Predicted Set" and print "Parse Table" self.FillParseTable() - print("Parse Table:") - self.PrintParseTable() - print() + # print("Parse Table:") + # self.PrintParseTable() + # print() # Prints variables that is needed for parser for parsing into the output file - self.OutputFile.write("#ifndef PARSE_TABLE_H\n") - self.OutputFile.write("#define PARSE_TABLE_H\n") - self.OutputFile.write("#include \"scanner.h\"\n") - self.OutputFile.write("#define RULES_COUNT " + str(len(self.LhsList)) + "\n") - self.OutputFile.write("#define TERMINAL_COUNT " + str(len(list(self.TerminalSet))) + "\n") - self.OutputFile.write("#define NONETERMINAL_COUNT " + str(len(list(self.NonTerminalList))) + "\n") - self.OutputFile.write("#define START_VARIABLE " + "\"" + self.Start +"\"\n") - self.OutputFile.write("#define MAX_RHS_LEN " + str(self.MAXIMUM_RHS_LEN) +"\n") + self.HeaderFile.write("#ifndef PARSE_TABLE_H\n") + self.HeaderFile.write("#define PARSE_TABLE_H\n") + + self.HeaderFile.write("#define RULES_COUNT " + str(len(self.LhsList)) + "\n") + self.HeaderFile.write("#define TERMINAL_COUNT " + str(len(list(self.TerminalSet))) + "\n") + self.HeaderFile.write("#define NONETERMINAL_COUNT " + str(len(list(self.NonTerminalList))) + "\n") + self.HeaderFile.write("#define START_VARIABLE " + "\"" + self.Start +"\"\n") + self.HeaderFile.write("#define MAX_RHS_LEN " + str(self.MAXIMUM_RHS_LEN) +"\n") + self.HeaderFile.write("#define KEYWORD_LIST_LENGTH " + str(len(self.keywordList)) +"\n") - # Prints Rules into output file + + self.SourceFile.write("#include \"parse_table.h\"\n") + self.SourceFile.write("#include \"common.h\"\n") + + + # Prints Rules into output files self.WriteLhsList() self.WriteRhsList() - # Prints size of each Rhs into output file + # Prints size of each Rhs into output files self.WriteRhsSize() - # Prints noneterminals and Terminal into output file + # Prints noneterminals and Terminal into output files self.WriteNoneTermianlList() self.WriteTerminalList() - # Prints "Parse Table" into output file + # Prints "Parse Table" into output files self.WriteParseTable() + # Prints Keywords list into output files + self.WriteKeywordList() - self.OutputFile.write("#endif\n") + self.HeaderFile.write("#endif\n") - # Closes Grammer Input File - self.GrammerFile.close() + # Closes Grammar Input File + self.GrammarFile.close() - # Closes Output File - self.OutputFile.close() + # Closes Output Files + self.SourceFile.close() + self.HeaderFile.close() # This function simulates of script engine parser in ScriptEngine.C in @@ -209,56 +224,105 @@ class Parser: - def ReadGrammer(self): + def ReadGrammar(self): Flag = 1 - Counter = 0 - for Line in self.GrammerFile: + Counter = -1 + for Line in self.GrammarFile: + Counter += 1 Line = Line.strip() if Line == "" or Line[0] == "#": continue + elif Line[0] == ".": + L = Line.split("->") + Elements = L[1].split(" ") + self.MapsList[L[0]] = Elements + continue + L = Line.split("->") Lhs = L[0] - self.NonTerminalSet.add(Lhs) - self.LhsList.append(Lhs) - - Rhs = L[1].split(" ") - self.RhsList.append(Rhs) + + HasMapKeyword = False + MapKeywordIdx1 = 0 + MapKeywordIdx2 = 0 + Idx = 0 for X in Rhs: - if not self.IsNoneTerminal(X) and not self.IsSemanticRule(X) and not X=="eps": - self.TerminalSet.add(X) + if X[0] == ".": + HasMapKeyword = True + MapKeywordIdx1 = Idx + elif X[0] == "@": + if X[1] == ".": + MapKeywordIdx2 = Idx + Idx += 1 + + if not HasMapKeyword: + self.NonTerminalSet.add(Lhs) + self.LhsList.append(Lhs) + self.RhsList.append(Rhs) + for X in Rhs: + if not self.IsNoneTerminal(X) and not self.IsSemanticRule(X) and not X=="eps": + self.TerminalSet.add(X) - + else: + + for value in self.MapsList[Rhs[MapKeywordIdx1]]: + RhsTemp =list(Rhs) + RhsTemp[MapKeywordIdx1] = value + RhsTemp[MapKeywordIdx2] = "@" + value.upper() + self.keywordList.append(value) + self.NonTerminalSet.add(Lhs) + self.LhsList.append(Lhs) + self.RhsList.append(RhsTemp) + + for X in RhsTemp: + if not self.IsNoneTerminal(X) and not self.IsSemanticRule(X) and not X=="eps": + self.TerminalSet.add(X) + if Flag: Flag = 0 self.Start = Lhs self.MAXIMUM_RHS_LEN = max(self.MAXIMUM_RHS_LEN, len(Rhs)) - Counter += 1 + self.TerminalSet.add("$") self.NonTerminalList = list(self.NonTerminalSet) + self.TerminalList = list(self.TerminalSet) + + def WriteKeywordList(self): + self.SourceFile.write("const char* KeywordList[]= {\n") + self.HeaderFile.write("extern const char* KeywordList[];\n") + + Counter = 0 + for X in self.keywordList: + if Counter == len(self.keywordList)-1: + self.SourceFile.write("\"" + X + "\"" + "\n") + else: + self.SourceFile.write("\"" + X + "\"" + ",\n") + Counter +=1 + self.SourceFile.write("};\n") def WriteLhsList(self): - self.OutputFile.write("const struct _TOKEN Lhs[RULES_COUNT]= \n{\n") + self.SourceFile.write("const struct _TOKEN Lhs[RULES_COUNT]= \n{\n") + self.HeaderFile.write("extern const struct _TOKEN Lhs[RULES_COUNT];\n") Counter = 0 for Lhs in self.LhsList: if Counter == len(self.LhsList)-1: - self.OutputFile.write("\t{NON_TERMINAL, " + "\"" + Lhs + "\"}" + "\n") + self.SourceFile.write("\t{NON_TERMINAL, " + "\"" + Lhs + "\"}" + "\n") else: - self.OutputFile.write("\t{NON_TERMINAL, " + "\"" + Lhs + "\"}" + ",\n") + self.SourceFile.write("\t{NON_TERMINAL, " + "\"" + Lhs + "\"}" + ",\n") Counter +=1 - self.OutputFile.write("};\n") + self.SourceFile.write("};\n") def GetType(self,Var): if self.IsNoneTerminal(Var): @@ -278,80 +342,85 @@ class Parser: def WriteRhsList(self): - self.OutputFile.write("const struct _TOKEN Rhs[RULES_COUNT][MAX_RHS_LEN]= \n{\n") + self.SourceFile.write("const struct _TOKEN Rhs[RULES_COUNT][MAX_RHS_LEN]= \n{\n") + self.HeaderFile.write("extern const struct _TOKEN Rhs[RULES_COUNT][MAX_RHS_LEN];\n") Counter =0 for Rhs in self.RhsList: - self.OutputFile.write("\t{") + self.SourceFile.write("\t{") C = 0 for Var in Rhs: if C == len(Rhs) -1: - self.OutputFile.write("{"+self.GetType(Var) +", "+"\"" + Var + "\"}" ) + self.SourceFile.write("{"+self.GetType(Var) +", "+"\"" + Var + "\"}" ) else: - self.OutputFile.write("{"+self.GetType(Var) +", "+"\"" + Var + "\"}," ) + self.SourceFile.write("{"+self.GetType(Var) +", "+"\"" + Var + "\"}," ) C += 1 if Counter == len(self.RhsList)-1: - self.OutputFile.write("}\n") + self.SourceFile.write("}\n") else: - self.OutputFile.write("},\n") + self.SourceFile.write("},\n") Counter+= 1 - self.OutputFile.write("};\n") + self.SourceFile.write("};\n") def WriteRhsSize(self): - self.OutputFile.write("const unsigned int RhsSize[RULES_COUNT]= \n{\n") + self.SourceFile.write("const unsigned int RhsSize[RULES_COUNT]= \n{\n") + self.HeaderFile.write("extern const unsigned int RhsSize[RULES_COUNT];\n") Counter =0 for Rhs in self.RhsList: if Counter == len(self.RhsList)-1: - self.OutputFile.write( str(len(Rhs)) + "\n" ) + self.SourceFile.write( str(len(Rhs)) + "\n" ) else: - self.OutputFile.write( str(len(Rhs)) + ",\n" ) + self.SourceFile.write( str(len(Rhs)) + ",\n" ) Counter+= 1 - self.OutputFile.write("};\n") + self.SourceFile.write("};\n") def WriteTerminalList(self): - self.OutputFile.write("const char* TerminalMap[TERMINAL_COUNT]= \n{\n") + self.SourceFile.write("const char* TerminalMap[TERMINAL_COUNT]= \n{\n") + self.HeaderFile.write("const char* TerminalMap[TERMINAL_COUNT];\n") Counter = 0 for X in self.TerminalList: if Counter == len(self.TerminalList)-1: - self.OutputFile.write("\"" + X + "\"" + "\n") + self.SourceFile.write("\"" + X + "\"" + "\n") else: - self.OutputFile.write("\"" + X + "\"" + ",\n") + self.SourceFile.write("\"" + X + "\"" + ",\n") Counter +=1 - self.OutputFile.write("};\n") + self.SourceFile.write("};\n") def WriteNoneTermianlList(self): - self.OutputFile.write("const char* NoneTerminalMap[NONETERMINAL_COUNT]= \n{\n") + self.SourceFile.write("const char* NoneTerminalMap[NONETERMINAL_COUNT]= \n{\n") + self.HeaderFile.write("const char* NoneTerminalMap[NONETERMINAL_COUNT];\n") Counter = 0 for X in self.NonTerminalList: if Counter == len(self.NonTerminalList)-1: - self.OutputFile.write("\"" + X + "\"" + "\n") + self.SourceFile.write("\"" + X + "\"" + "\n") else: - self.OutputFile.write("\"" + X + "\"" + ",\n") + self.SourceFile.write("\"" + X + "\"" + ",\n") Counter +=1 - self.OutputFile.write("};\n") + self.SourceFile.write("};\n") def WriteParseTable(self): - self.OutputFile.write("const int ParseTable[NONETERMINAL_COUNT][TERMINAL_COUNT]= \n{\n") + self.SourceFile.write("const int ParseTable[NONETERMINAL_COUNT][TERMINAL_COUNT]= \n{\n") + self.HeaderFile.write("const int ParseTable[NONETERMINAL_COUNT][TERMINAL_COUNT];\n") i = 0 for X in self.NonTerminalList: j = 0 - self.OutputFile.write("\t{") + self.SourceFile.write("\t{") for y in self.TerminalList: - self.OutputFile.write(str(self.ParseTable[i][j])) + self.SourceFile.write(str(self.ParseTable[i][j])) if j != len(self.TerminalList)-1: - self.OutputFile.write("\t\t,") + self.SourceFile.write("\t\t,") j += 1 if i == len(self.NonTerminalList)-1: - self.OutputFile.write("\t}\n") + self.SourceFile.write("\t}\n") else: - self.OutputFile.write("\t},\n") + self.SourceFile.write("\t},\n") i +=1 - self.OutputFile.write("};\n") + self.SourceFile.write("};\n") @@ -430,7 +499,7 @@ class Parser: self.ParseTable[i][j] = RuleId else: - print("Error! Input grammer is not LL1.") + print("Error! Input grammar is not LL1.") exit() j += 1 diff --git a/hyperdbg/script-engine/src/scanner.c b/hyperdbg/script-engine/scanner.c similarity index 52% rename from hyperdbg/script-engine/src/scanner.c rename to hyperdbg/script-engine/scanner.c index aa815013..3e60ebc9 100644 --- a/hyperdbg/script-engine/src/scanner.c +++ b/hyperdbg/script-engine/scanner.c @@ -16,420 +16,10 @@ #include #include #include "scanner.h" +#include "common.h" +#include "pasre_table.h" -// TODO: automate generation of KeyWordList - -/** -* @brief list of keywords -*/ -const char* KeywordList[] = -{ - "str", - "low", - "poi", - "db", - "dq", - "dw", - "not", - "dd", - "func", - "wstr", - "sizeof", - "neg", - "hi", - "print" -}; - -/** - * @brief allocates a new token - * - * @return Token - */ -TOKEN NewToken() -{ - TOKEN Token; - - // - // Allocates memory for token and its value - // - Token = (TOKEN)malloc(sizeof(*Token)); - Token->Value = (char*)calloc(TOKEN_VALUE_MAX_LEN, sizeof(char)); - - // - // Init fields - // - strcpy(Token->Value, ""); - Token->Type = UNKNOWN; - Token->len = 0; - Token->max_len = TOKEN_VALUE_MAX_LEN; - - return Token; -} - -/** - * @brief removes allocated memory of a token - * - * @param Token - */ -void RemoveToken(TOKEN Token) -{ - free(Token->Value); - free(Token); - - return; -} - -/** - * @brief prints token - * @detail prints value and type of token - * - * @param Token - */ -void PrintToken(TOKEN Token) -{ - - // - // Prints vlaue of the Token - // - if (Token->Type == WHITE_SPACE) - { - printf("< :"); - } - else - { - printf("<'%s' : ", Token->Value); - } - - // - // Prints type of the Token - // - switch (Token->Type) - { - case ID: - printf(" ID>\n"); - break; - case DECIMAL: - printf(" DECIMAL>\n"); - break; - case HEX: - printf(" HEX>\n"); - break; - case OCTAL: - printf(" OCTAL>\n"); - break; - case BINARY: - printf(" BINARY>\n"); - break; - case SPECIAL_TOKEN: - printf(" SPECIAL_TOKEN>\n"); - break; - case KEYWORD: - printf(" KEYWORD>\n"); - break; - case WHITE_SPACE: - printf(" WHITE_SPACE>\n"); - break; - case COMMENT: - printf(" COMMENT>\n"); - break; - case REGISTER: - printf(" REGISTER>\n"); - break; - case PSEUDO_REGISTER: - printf(" PSEUDO_REGISTER>\n"); - break; - case SEMANTIC_RULE: - printf(" SEMANTIC_RULE>\n"); - break; - case NON_TERMINAL: - printf(" NON_TERMINAL>\n"); - break; - case END_OF_STACK: - printf(" END_OF_STACK>\n"); - break; - case UNKNOWN: - printf(" UNKNOWN>\n"); - break; - - default: - printf(" ERROR>\n"); - break; - } -} - -/** - * @brief appends char to the token value - * - * @param Token - * @param char - */ -void Append(TOKEN Token, char c) -{ - // - // Check overflow of the string - // - if (Token->len >= Token->max_len-1) - { - // - // Double the length of the allocated space for the string - // - Token->max_len *= 2; - char* NewValue = (char*)calloc(Token->max_len, sizeof(char)); - - - // - // Free Old buffer and update the pointer - // - strncpy(NewValue, Token->Value, Token->len); - free(Token->Value); - Token->Value = NewValue; - } - - - // - // Append the new charcter to the string - // - strncat(Token->Value, &c, 1); - Token->len++; - - - -} - -/** - * @brief allocates a new TOKEN_LIST - * - * @return TOKEN_LIST - */ -TOKEN_LIST NewTokenList(void) -{ - TOKEN_LIST TokenList; - - // - // Allocation of memory for TOKEN_LIST structure - // - TokenList = (TOKEN_LIST)malloc(sizeof(*TokenList)); - - - // - // Initialize fields of TOKEN_LIST - // - TokenList->Pointer = 0; - TokenList->Size = TOKEN_LIST_INIT_SIZE; - - // - // Allocation of memory for TOKEN_LIST buffer - // - TokenList->Head = (TOKEN*)malloc(TokenList->Size * sizeof(TOKEN)); - - return TokenList; -} - -/** - * @brief removes allocated memory of a TOKEN_LIST - * - * @param TokenList - */ -void RemoveTokenList(TOKEN_LIST TokenList) -{ - TOKEN Token; - for (uintptr_t i = 0; i < TokenList->Pointer; i++) - { - Token = *(TokenList->Head + i); - RemoveToken(Token); - } - free(TokenList->Head); - free(TokenList); - - return; -} - - -/** - * @brief prints each Token inside a TokenList - * - * @param TokenList - */ -void PrintTokenList(TOKEN_LIST TokenList) -{ - TOKEN Token; - for (uintptr_t i = 0; i < TokenList->Pointer; i++) - { - Token = *(TokenList->Head + i); - PrintToken(Token); - } - -} - -/** - * @brief adds Token to the last empty position of TokenList - * - * @param Token - * @param TokenList - * @return TokenList - */ -TOKEN_LIST Push(TOKEN_LIST TokenList, TOKEN Token) -{ - // - // Calculate address to write new token - // - uintptr_t Head = (uintptr_t)TokenList->Head; - uintptr_t Pointer = (uintptr_t)TokenList->Pointer; - TOKEN* WriteAddr = (TOKEN*)(Head + Pointer * sizeof(TOKEN)); - - // - // Write Token to appropriate address in TokenList - // - *WriteAddr = Token; - - // - // Update Pointer - // - TokenList->Pointer++; - - // - // Handle overflow - // - if (Pointer == TokenList->Size - 1) - { - // - // Allocate a new buffer for string list with doubled length - // - TOKEN* NewHead = (TOKEN*)malloc(2 * TokenList->Size * sizeof(TOKEN)); - - // - // Copy old buffer to new buffer - // - memcpy(NewHead, TokenList->Head, TokenList->Size * sizeof(TOKEN)); - - // - // Free old buffer - // - free(TokenList->Head); - - // - // Update Head and size of TokenList - // - TokenList->Size = TokenList->Size * 2; - TokenList->Head = NewHead; - } - - return TokenList; -} -/** - * @brief removes last Token of a TokenList and returns it - * - * @param TokenList - @ @return Token - */ -TOKEN Pop(TOKEN_LIST TokenList) -{ - // - // Calculate address to read most recent token - // - if (TokenList->Pointer > 0) - TokenList->Pointer--; - uintptr_t Head = (uintptr_t)TokenList->Head; - uintptr_t Pointer = (uintptr_t)TokenList->Pointer; - TOKEN* ReadAddr = (TOKEN*)(Head + Pointer * sizeof(TOKEN)); - - - return *ReadAddr; -} - - -/** - * @brief returns last Token of a TokenList - * - * @param TokenList - * @return Token - */ -TOKEN Top(TOKEN_LIST TokenList) -{ - // - // Calculate address to read most recent token - // - uintptr_t Head = (uintptr_t)TokenList->Head; - uintptr_t Pointer = (uintptr_t)TokenList->Pointer - 1; - TOKEN* ReadAddr = (TOKEN*)(Head + Pointer * sizeof(TOKEN)); - - return *ReadAddr; -} - -/** -* @brief cheks whether input char belongs to hexadecimal digit-set or not -* -* @param char -* @return bool -*/ -char IsHex(char c) -{ - if ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')) - return 1; - else - return 0; -} - -/** -* @brief cheks whether input char belongs to decimal digit-set or not -* -* @param char -* @return bool -*/ -char IsDecimal(char c) -{ - if (c >= '0' && c <= '9') - return 1; - else - return 0; -} - -/** -* @brief cheks whether input char belongs to alphabet set or not -* -* @param char -* @return bool -*/ -char IsLetter(char c) -{ - if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')) - return 1; - else - { - return 0; - } -} - -/** -* @brief cheks whether input char belongs to binary digit-set or not -* -* @param char -* @return bool -*/ -char IsBinary(char c) -{ - if (c == '0' || c == '1') - return 1; - else - { - return 0; - } -} - -/** -* @brief cheks whether input char belongs to octal digit-set or not -* -* @param char -* @return bool -*/ -char IsOctal(char c) -{ - if (c >= '0' && c <= '7') - return 1; - else - return 0; -} /** @@ -870,10 +460,9 @@ char sgetc(char* str) char IsKeyword(char* str) { - int n = sizeof(KeywordList) / sizeof(KeywordList[0]); + int n = KEYWORD_LIST_LENGTH; for (int i = 0; i < n; i++) - { - if (!strcmp(str, KeywordList[i])) + {if (!strcmp(str, KeywordList[i])) { return 1; } diff --git a/hyperdbg/script-engine/scanner.h b/hyperdbg/script-engine/scanner.h new file mode 100644 index 00000000..9cd947c3 --- /dev/null +++ b/hyperdbg/script-engine/scanner.h @@ -0,0 +1,24 @@ +#pragma once + +#ifndef SCANNER_H +#define SCANNER_H +#include "common.h" +/** +* @brief number of read characters from input +*/ +unsigned int InputIdx; + +//////////////////////////////////////////////////// +// Interfacing functions // +//////////////////////////////////////////////////// +TOKEN GetToken(char* c, char* str); + +TOKEN Scan(char* str, char* c); + +char sgetc(char* str); + +char IsKeyword(char* str); + +#endif // !SCANNER_H + + diff --git a/hyperdbg/script-engine/script-engine.vcxproj b/hyperdbg/script-engine/script-engine.vcxproj index d5967b3d..f23d4b62 100644 --- a/hyperdbg/script-engine/script-engine.vcxproj +++ b/hyperdbg/script-engine/script-engine.vcxproj @@ -81,10 +81,10 @@ true _CRT_SECURE_NO_WARNINGS;SCRIPTENGINE_EXPORTS true - NotUsing + Use pch.h MultiThreaded - $(SolutionDir)\include;%(AdditionalIncludeDirectories) + %(AdditionalIncludeDirectories) Windows @@ -99,20 +99,23 @@ + + - - - + + + Create Create - - + + + diff --git a/hyperdbg/script-engine/script-engine.vcxproj.filters b/hyperdbg/script-engine/script-engine.vcxproj.filters index 544aa42e..145c0d0f 100644 --- a/hyperdbg/script-engine/script-engine.vcxproj.filters +++ b/hyperdbg/script-engine/script-engine.vcxproj.filters @@ -21,13 +21,16 @@ Header Files - + Header Files - + Header Files - + + Header Files + + Header Files @@ -38,10 +41,16 @@ Source Files - + Source Files - + + Source Files + + + Source Files + + Source Files diff --git a/hyperdbg/script-engine/src/input.txt b/hyperdbg/script-engine/src/input.txt deleted file mode 100644 index a171613e..00000000 --- a/hyperdbg/script-engine/src/input.txt +++ /dev/null @@ -1,29 +0,0 @@ - - -x1 = poi(poi((poi(($proc&neg(1000`0000))+10)^poi(poi(poi(poi(poi(poi(poi(poi($prcb+18)+220)+648)+8)-240)+2a0)))^neg(0n6708588087252463955)^($proc&neg(100000)))-8)-1080); -//test= poi(2); -//a2= poi((01)+ 2 * 3) * poi(2); // Binary -//test=dw(@rcx+($proc|3+poi(poi(@rax)))); -/* - //test=dq(@rcx) - //test=$proc+@rdx - //ad1= b2;A - //a3 = $rsc34; - //a2= 0y0101`1010`1; // Binary - //a10 = 0n34331; // - Decimal - //a10 = 0o770; // Octal - //test=poi(@rax+a0); - //test1=str(poi($proc+10));mytest=str(poi($proc+10));test3=str(poi($proc+10)); - //test=dw(NtCreateFile+10) - //test=dw(NtCreateFile+@rcx+($proc|3+poi(poi(@rax)))) - // - // - //$proc = 0xfffff801`42600000 - // - // - //csc=0y101010`010101*934; - //tsc = 10.032; - // - //test = 343 -*/ \ No newline at end of file