diff --git a/hyperdbg/ScriptEngine/ScriptEngine.sln b/hyperdbg/ScriptEngine/ScriptEngine.sln new file mode 100644 index 00000000..8d5104f4 --- /dev/null +++ b/hyperdbg/ScriptEngine/ScriptEngine.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.30320.27 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ScriptEngine", "ScriptEngine.vcxproj", "{C2D44C60-3F23-4972-8F60-21083B9FB112}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {C2D44C60-3F23-4972-8F60-21083B9FB112}.Debug|x64.ActiveCfg = Debug|x64 + {C2D44C60-3F23-4972-8F60-21083B9FB112}.Debug|x64.Build.0 = Debug|x64 + {C2D44C60-3F23-4972-8F60-21083B9FB112}.Release|x64.ActiveCfg = Release|x64 + {C2D44C60-3F23-4972-8F60-21083B9FB112}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {63144D94-C02B-4949-9356-0CFE750E5558} + EndGlobalSection +EndGlobal diff --git a/hyperdbg/ScriptEngine/ScriptEngine.vcxproj b/hyperdbg/ScriptEngine/ScriptEngine.vcxproj new file mode 100644 index 00000000..b4f88601 --- /dev/null +++ b/hyperdbg/ScriptEngine/ScriptEngine.vcxproj @@ -0,0 +1,196 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 16.0 + Win32Proj + {c2d44c60-3f23-4972-8f60-21083b9fb112} + ScriptEngine + 10.0 + + + + DynamicLibrary + true + v142 + Unicode + + + DynamicLibrary + false + v142 + true + Unicode + + + DynamicLibrary + true + v142 + Unicode + + + DynamicLibrary + false + v142 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + $(SolutionDir)\build\Debug\ + + + false + $(ProjectDir)..\build\Debug + + + true + $(SolutionDir)\build\Debug\ + + + false + $(SolutionDir)\build\Release\ + + + + Level3 + true + _CRT_SECURE_NO_WARNINGS;SCRIPTENGINE_EXPORTS + true + NotUsing + pch.h + MultiThreadedDebug + + + Windows + true + false + + + xcopy /y /d "D:\worktable\ScriptEngine\ScriptEngine\build\Debug\ScriptEngine.dll" "D:\worktable\ScriptEngine\ScriptEngineEmulator\x64\Debug" + + + + + Level3 + true + true + true + _CRT_SECURE_NO_WARNINGS;SCRIPTENGINE_EXPORTS + true + NotUsing + pch.h + MultiThreaded + + + Windows + true + true + true + false + + + xcopy /y /d $(ProjectDir)\build\Debug\ScriptEngine.dll $(ProjectDir)\..\ScriptEngineEmulator\x64\Debug + + + + + Level3 + true + _CRT_SECURE_NO_WARNINGS;SCRIPTENGINE_EXPORTS + true + NotUsing + pch.h + MultiThreadedDebug + + + Windows + true + false + + + + + + + + + Level3 + true + true + true + _CRT_SECURE_NO_WARNINGS;SCRIPTENGINE_EXPORTS + true + NotUsing + pch.h + MultiThreaded + + + Windows + true + true + true + false + + + + + + + + + + + + + + + + + Create + Create + Create + Create + + + + + + + + \ No newline at end of file diff --git a/hyperdbg/ScriptEngine/ScriptEngine.vcxproj.filters b/hyperdbg/ScriptEngine/ScriptEngine.vcxproj.filters new file mode 100644 index 00000000..1528f8f2 --- /dev/null +++ b/hyperdbg/ScriptEngine/ScriptEngine.vcxproj.filters @@ -0,0 +1,48 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;c++;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + \ No newline at end of file diff --git a/hyperdbg/ScriptEngine/dllmain.cpp b/hyperdbg/ScriptEngine/dllmain.cpp new file mode 100644 index 00000000..ec23ae99 --- /dev/null +++ b/hyperdbg/ScriptEngine/dllmain.cpp @@ -0,0 +1,19 @@ +// dllmain.cpp : Defines the entry point for the DLL application. +#include "pch.h" + +BOOL APIENTRY DllMain( HMODULE hModule, + DWORD ul_reason_for_call, + LPVOID lpReserved + ) +{ + switch (ul_reason_for_call) + { + case DLL_PROCESS_ATTACH: + case DLL_THREAD_ATTACH: + case DLL_THREAD_DETACH: + case DLL_PROCESS_DETACH: + break; + } + return TRUE; +} + diff --git a/hyperdbg/ScriptEngine/framework.h b/hyperdbg/ScriptEngine/framework.h new file mode 100644 index 00000000..54b83e94 --- /dev/null +++ b/hyperdbg/ScriptEngine/framework.h @@ -0,0 +1,5 @@ +#pragma once + +#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers +// Windows Header Files +#include diff --git a/hyperdbg/ScriptEngine/input.txt b/hyperdbg/ScriptEngine/input.txt new file mode 100644 index 00000000..9f5dde05 --- /dev/null +++ b/hyperdbg/ScriptEngine/input.txt @@ -0,0 +1,27 @@ +//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); +//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 diff --git a/hyperdbg/ScriptEngine/pch.cpp b/hyperdbg/ScriptEngine/pch.cpp new file mode 100644 index 00000000..64b7eef6 --- /dev/null +++ b/hyperdbg/ScriptEngine/pch.cpp @@ -0,0 +1,5 @@ +// pch.cpp: source file corresponding to the pre-compiled header + +#include "pch.h" + +// When you are using pre-compiled headers, this source file is necessary for compilation to succeed. diff --git a/hyperdbg/ScriptEngine/pch.h b/hyperdbg/ScriptEngine/pch.h new file mode 100644 index 00000000..885d5d62 --- /dev/null +++ b/hyperdbg/ScriptEngine/pch.h @@ -0,0 +1,13 @@ +// 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" + +#endif //PCH_H diff --git a/hyperdbg/ScriptEngine/python/Grammer.txt b/hyperdbg/ScriptEngine/python/Grammer.txt new file mode 100644 index 00000000..2a124003 --- /dev/null +++ b/hyperdbg/ScriptEngine/python/Grammer.txt @@ -0,0 +1,75 @@ +S->C ; S' +S'->C ; S' +S'->eps +C->@PUSH _id = E0 @MOV C' +C'->eps +# +E0->E1 E0' +E0'->| E1 @OR E0' +E0'->eps + +E1->E2 E1' +E1'->^ E2 @XOR E1' +E1'->eps + +E2->E3 E2' +E2'->& E3 @AND E2' +E2'->eps + +E3->E4 E3' +E3'->>> E4 @ASR E3' +E3'->eps + +E4->E5 E4' +E4'-><< E5 @ASL E4' +E4'->eps + +E5->E6 E5' +E5'->+ E6 @ADD E5' +E5'->eps + +E6->E7 E6' +E6'->- E7 @SUB E6' +E6'->eps + +E7->E8 E7' +E7'->* E8 @MUL E7' +E7'->eps + +E8->E9 E8' +E8'->/ E9 @DIV E8' +E8'->eps + + +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->( E0 ) + +E10->@PUSH _register + +# numbers +E10->@PUSH _hex +E10->@PUSH _decimal +E10->@PUSH _octal +E10->@PUSH _binary + + +E10->@PUSH func +E10->@PUSH _pseudo_register + diff --git a/hyperdbg/ScriptEngine/python/parse_table_generator.py b/hyperdbg/ScriptEngine/python/parse_table_generator.py new file mode 100644 index 00000000..f1320be6 --- /dev/null +++ b/hyperdbg/ScriptEngine/python/parse_table_generator.py @@ -0,0 +1,593 @@ +import re + +# Util functions +def get_top(l): + return l[len(l)-1] + +def read(tokens): + x = tokens[0] + tokens = tokens[1:] + return tokens, x + + + + + + +class Parser: + def __init__(self): + self.grammer_file = open("Grammer.txt", "r") + self.output_file = open("..\src\parse_table.h", "w") + self.rhs_list = [] + self.lhs_list = [] + self.terminal_set = set() + self.nonterminal_set = set() + self.start = "" + self.maximum_rhs_len = 0 + + + self.SPECIAL_TOKENS = ['%', '++', '+=', '+', '--', '-=', '-', '*=', "*", "/=", "/", "=", ",", ";", "(", ")", "{", "}", "|", ">>", "<<", "&", "^"] + + self.first_dict = dict() + self.follow_dict = dict() + + self.INVALID = -1 + + def run(self): + self.read_grammer() + + self.find_all_firsts() + print("Firsts:") + self.print_firsts() + print("________________________________________________________________________________") + + self.find_all_follows() + print("Follows:") + self.print_follows() + print("________________________________________________________________________________") + + + self.find_all_perdicts() + print("Predicts:") + self.print_predicts() + print("________________________________________________________________________________") + + + self.fill_parse_table() + print("Parse Table:") + self.print_parse_table() + print() + + + self.output_file.write("#ifndef PARSE_TABLE_H\n") + self.output_file.write("#define PARSE_TABLE_H\n") + self.output_file.write("#include \"scanner.h\"\n") + self.output_file.write("#define RULES_COUNT " + str(len(self.lhs_list)) + "\n") + self.output_file.write("#define TERMINAL_COUNT " + str(len(list(self.terminal_set))) + "\n") + self.output_file.write("#define NONETERMINAL_COUNT " + str(len(list(self.nonterminal_list))) + "\n") + self.output_file.write("#define START_VARIABLE " + "\"" + self.start +"\"\n") + self.output_file.write("#define MAX_RHS_LEN " + str(self.maximum_rhs_len) +"\n") + + + self.write_lhs_list() + self.write_rhs_list() + self.write_rhs_size() + self.write_noneterminal_list() + self.write_terminal_list() + self.write_parse_table() + + + self.output_file.write("#endif\n") + + self.grammer_file.close() + self.output_file.close() + + + def parse(self, tokens): + stack = [] + matched_stack = [] + stack.append("$") + stack.append(self.start) + top = "" + tokens, current_in = read(tokens) + t_counter = 0 + + while top != "$": + top = get_top(stack) + + # print(stack) + + if self.isNoneTerminal(top): + id = self.parse_table[self.get_noneterminal_id(top)][self.get_terminal_id(current_in)] + + # Error Handling + if id == -1: + print("1)Error in input!") + exit() + + stack.pop() + + + rhs = self.rhs_list[id] + if rhs != ["eps"]: + for symbol in reversed(rhs): + stack.append(symbol) + + + elif self.isSemanticRule(top): + # TODO: Handle Semantic rules + if top == "@PUSH": + stack.pop() + top = get_top(stack) + if top == current_in: + matched_stack.append(top) + current_in = tokens[0] + tokens = tokens[1:] + else: + print("2)Error in input!") + exit() + + else: + + + + op0 = matched_stack.pop() + + op1 = matched_stack.pop() + + if top == "@MOV": + print(top,"\t", op1, ", ", op0 ) + else: + matched_stack.append("t" + str(t_counter)) + print(top, "\t", "t"+ str(t_counter), ", ", op1, ",", op0 ) + t_counter += 1 + + # print("matched stack :", end ="") + # print(matched_stack) + + stack.pop() + + else: # Terminal + # TODO: Handle Error + current_in = tokens[0] + if (len(tokens) > 1): + tokens = tokens[1:] + stack.pop() + # print(top) + + return matched_stack + + # def code_gen(self, input_stack): + # print("input stack:", input_stack) + # if len(input_stack) < 3: + # return input_stack + # top_idx = len(input_stack) - 1 + # first_op_idx = len(input_stack) - 2 + # second_op_idx = len(input_stack) - 3 + + # output_stack = [] + + # if not self.isSemanticRule(input_stack[top_idx]): + # print("Error!") + # exit() + # else: + # output_stack.append(input_stack.pop()) + # if not self.isSemanticRule(input_stack[first_op_idx]): # Operand + # output_stack.append(input_stack.pop()) + # else: # Operator + # output_stack.extend(self.code_gen(input_stack)) + + # if not self.isSemanticRule(input_stack[second_op_idx]): # Operand + # output_stack.append(input_stack.pop()) + # else: #Operator + # output_stack.extend(self.code_gen(input_stack)) + # print("output stack:", output_stack) + # return output_stack + + + + def read_grammer(self): + flag = 1 + counter = 0 + for line in self.grammer_file: + line = line.strip() + if line == "" or line[0] == "#": + continue + l = line.split("->") + lhs = l[0] + self.nonterminal_set.add(lhs) + self.lhs_list.append(lhs) + + + rhs = l[1].split(" ") + self.rhs_list.append(rhs) + for x in rhs: + if not self.isNoneTerminal(x) and not self.isSemanticRule(x) and not x=="eps": + self.terminal_set.add(x) + + + + + if flag: + flag = 0 + self.start = lhs + self.maximum_rhs_len = max(self.maximum_rhs_len, len(rhs)) + + counter += 1 + + self.terminal_set.add("$") + + self.nonterminal_list = list(self.nonterminal_set) + self.terminal_list = list(self.terminal_set) + + + + + + + def write_lhs_list(self): + + self.output_file.write("const struct _TOKEN Lhs[RULES_COUNT]= \n{\n") + counter = 0 + for lhs in self.lhs_list: + if counter == len(self.lhs_list)-1: + self.output_file.write("\t{NON_TERMINAL, " + "\"" + lhs + "\"}" + "\n") + else: + self.output_file.write("\t{NON_TERMINAL, " + "\"" + lhs + "\"}" + ",\n") + counter +=1 + self.output_file.write("};\n") + + def get_type(self,var): + if self.isNoneTerminal(var): + return "NON_TERMINAL" + elif self.isSemanticRule(var): + return "SEMANTIC_RULE" + + elif var == "eps": + return "EPSILON" + + elif var in self.SPECIAL_TOKENS: + return "SPECIAL_TOKEN" + elif var[0] == "_": + return var[1:].upper() + else: + return "KEYWORD" + + + def write_rhs_list(self): + self.output_file.write("const struct _TOKEN Rhs[RULES_COUNT][MAX_RHS_LEN]= \n{\n") + counter =0 + for rhs in self.rhs_list: + self.output_file.write("\t{") + + c = 0 + for var in rhs: + if c == len(rhs) -1: + self.output_file.write("{"+self.get_type(var) +", "+"\"" + var + "\"}" ) + else: + self.output_file.write("{"+self.get_type(var) +", "+"\"" + var + "\"}," ) + c += 1 + + if counter == len(self.rhs_list)-1: + self.output_file.write("}\n") + else: + self.output_file.write("},\n") + counter+= 1 + + self.output_file.write("};\n") + + def write_rhs_size(self): + self.output_file.write("const unsigned int RhsSize[RULES_COUNT]= \n{\n") + counter =0 + for rhs in self.rhs_list: + if counter == len(self.rhs_list)-1: + self.output_file.write( str(len(rhs)) + "\n" ) + else: + self.output_file.write( str(len(rhs)) + ",\n" ) + counter+= 1 + + self.output_file.write("};\n") + + def write_terminal_list(self): + self.output_file.write("const char* TerminalMap[TERMINAL_COUNT]= \n{\n") + counter = 0 + for x in self.terminal_list: + if counter == len(self.terminal_list)-1: + self.output_file.write("\"" + x + "\"" + "\n") + else: + self.output_file.write("\"" + x + "\"" + ",\n") + counter +=1 + self.output_file.write("};\n") + + def write_noneterminal_list(self): + self.output_file.write("const char* NoneTerminalMap[NONETERMINAL_COUNT]= \n{\n") + counter = 0 + for x in self.nonterminal_list: + if counter == len(self.nonterminal_list)-1: + self.output_file.write("\"" + x + "\"" + "\n") + else: + self.output_file.write("\"" + x + "\"" + ",\n") + counter +=1 + self.output_file.write("};\n") + + def write_parse_table(self): + self.output_file.write("const int ParseTable[NONETERMINAL_COUNT][TERMINAL_COUNT]= \n{\n") + i = 0 + for x in self.nonterminal_list: + j = 0 + self.output_file.write("\t{") + for y in self.terminal_list: + self.output_file.write(str(self.parse_table[i][j])) + if j != len(self.terminal_list)-1: + self.output_file.write("\t\t,") + j += 1 + + if i == len(self.nonterminal_list)-1: + self.output_file.write("\t}\n") + + else: + self.output_file.write("\t},\n") + i +=1 + self.output_file.write("};\n") + + + + def find_all_firsts(self): + + self.first_dict = {} + for symbol in self.nonterminal_list: + self.first_dict[symbol] = set() + + t = 0 + while True: + updated = False + i = 0 + for lhs in self.lhs_list: + rhs = self.rhs_list[i] + temp = set(self.first_dict[lhs]) + + + if rhs[0] == "eps": + pass + elif self.isNoneTerminal(rhs[0]): + self.first_dict[lhs] = self.first_dict[lhs].union(self.first_dict[rhs[0]]) + p = 0 + while self.isnullable(rhs[p]): + self.first_dict[lhs] = self.first_dict[lhs].union(self.first_dict[rhs[p+1]]) + p += 1 + elif self.isSemanticRule(rhs[0]): + if self.isNoneTerminal(rhs[0]): + self.first_dict[lhs] = self.first_dict[lhs].union(self.first_dict[rhs[1]]) + else: + self.first_dict[lhs].add(rhs[1]) + else: + self.first_dict[lhs].add(rhs[0]) + i += 1 + + if temp != self.first_dict[lhs]: + updated = True + p += 1 + if not updated: + break; + + + + def print_firsts(self): + for id in self.first_dict: + print(id, end=": ") + for x in self.first_dict[id]: + print(x,end = " ") + print() + + def get_noneterminal_id(self, nonterminal): + for i in range(len(self.nonterminal_list)): + if nonterminal == self.nonterminal_list[i]: + return i + + return -1 + def get_terminal_id(self, terminal): + for i in range(len(self.terminal_list)): + if terminal == self.terminal_list[i]: + return i + + return -1 + + + def fill_parse_table(self): + self.parse_table = [[self.INVALID for y in range(len(self.terminal_list))] for x in range(len(self.nonterminal_list))] + + rule_id = 0 + for lhs in self.lhs_list: + i = self.get_noneterminal_id(lhs) + + j = 0 + for terminal in self.terminal_list: + if terminal in self.predict_dict[rule_id]: + if self.parse_table[i][j] == self.INVALID: + self.parse_table[i][j] = rule_id + + else: + print("Error! Input grammer is not LL1.") + exit() + + j += 1 + + rule_id += 1 + + def print_parse_table(self): + print("\t", end = "") + for j in range(len(self.terminal_list)): + print(self.terminal_list[j], end= "\t ") + print() + for i in range(len(self.nonterminal_list)): + print(self.nonterminal_list[i], end= "\t") + for j in range(len(self.terminal_list)): + if self.parse_table[i][j] == self.INVALID: + print(".", end= "\t ") + else: + print(self.parse_table[i][j], end= "\t ") + print() + + + def find_all_perdicts(self): + self.predict_dict = {} + for i in range(len(self.lhs_list)): + self.predict_dict[i] = set() + + i = 0 + for lhs in self.lhs_list: + rhs = self.rhs_list[i] + is_right_nullable = True + # print(lhs, end= ": ") + # print(rhs) + + # if rhs[0] == "eps": + # pass + for symbol in rhs: + if self.isSemanticRule(symbol): + pass + + elif symbol == "eps": + is_right_nullable = True + break + elif self.isNoneTerminal(symbol): + self.predict_dict[i] |= self.first_dict[symbol] + if not self.isnullable(symbol): + is_right_nullable = False + break + else: + self.predict_dict[i].add(symbol) + is_right_nullable = False + break + + if is_right_nullable: + self.predict_dict[i] |= self.follow_dict[lhs] + i += 1 + + + def print_predicts(self): + for key in self.predict_dict: + print(key, end=": ") + for x in self.predict_dict[key]: + print(x,end = " ") + print() + + + + def find_all_follows(self): + self.follow_dict = {} + for symbol in self.nonterminal_list: + self.follow_dict[symbol] = set() + if symbol == self.start: + self.follow_dict[symbol].add('$') + + t = 0 + while True: + updated = False + + i = 0 + for lhs in self.lhs_list: + rhs = self.rhs_list[i] + + p = 0 + for symbol in rhs: + + if self.isNoneTerminal(symbol): + + temp = set(self.follow_dict[symbol]) + if p == len(rhs)-1: + self.follow_dict[symbol] = self.follow_dict[symbol].union(self.follow_dict[lhs]) + + + + else: + + next_var = self.get_next_var(rhs, p) + if self.isNoneTerminal(next_var): + self.follow_dict[symbol] = self.follow_dict[symbol].union(self.first_dict[next_var]) + if self.isnullable(next_var): + self.follow_dict[symbol] = self.follow_dict[symbol].union(self.follow_dict[next_var]) + elif self.isSemanticRule(next_var): + pass + else: + self.follow_dict[symbol].add(next_var) + + if p == len(rhs)-2: + next_var = self.get_next_var(rhs, p) + + if self.isnullable(next_var): + self.follow_dict[symbol] = self.follow_dict[symbol].union(self.follow_dict[lhs]) + self.follow_dict[lhs] = self.follow_dict[lhs].union(self.follow_dict[next_var]) + + + + if temp != self.follow_dict[symbol]: + updated = True + p += 1 + i += 1 + t += 1 + + if not updated: + break + def get_next_var(self, rhs, p): + if p == len(rhs)-1: + return None + + x = p +1 + while self.isSemanticRule(rhs[x]): + x+=1 + return rhs[x] + + def print_follows(self): + for key in self.follow_dict: + print(key, end=": ") + for x in self.follow_dict[key]: + print(x,end = " ") + print() + + def isNoneTerminal(self,x): + if x[0].isupper(): + return True + else: + return False + + def isSemanticRule(self, x): + if x[0] == '@': + return True + else: + return False + + def isnullable(self, s): + + if not s[0].isupper(): + return False + i = 0 + for lhs in self.lhs_list: + rhs = self.rhs_list[i] + + if lhs == s: + + if rhs[0] == "eps": + return True + + p = 0 + while True: + if self.isnullable(rhs[p]): + return True + else: + break + p += 1 + i +=1 + + return False + +parser = Parser() +parser.run() +tokens = ['_id', '=', '(', '_hex', '*', '_hex', ')', '*', '_hex', '*', '_decimal', '*', '_octal', ';', '$'] +stack = parser.parse(tokens) +print(stack) +# parser.code_gen(stack) + + + + diff --git a/hyperdbg/ScriptEngine/src/ScriptEngine.c b/hyperdbg/ScriptEngine/src/ScriptEngine.c new file mode 100644 index 00000000..cb53eee3 --- /dev/null +++ b/hyperdbg/ScriptEngine/src/ScriptEngine.c @@ -0,0 +1,798 @@ +#include +#include +#include +#include +#include "ScriptEngine.h" +#include "scanner.h" +#include "parse_table.h" + +/** +* +* +*/ +PSYMBOL_BUFFER ScriptEngineParse(char *str) +{ + TOKEN_LIST Stack = NewTokenList(); + TOKEN_LIST MatchedStack = NewTokenList(); + PSYMBOL_BUFFER CodeBuffer = NewSymbolBuffer(); + + TOKEN CurrentIn; + TOKEN TopToken; + + + int NonTerminalId; + int TerminalId; + int RuleId; + char c; + char t; + + + + // + // End of File Token + // + TOKEN EndToken = NewToken(); + EndToken->Type = END_OF_STACK; + strcpy(EndToken->Value, "$"); + + // + // Start Token + // + TOKEN StartToken = NewToken(); + strcpy(StartToken->Value, START_VARIABLE); + StartToken->Type = NON_TERMINAL; + + Push(Stack, EndToken); + Push(Stack, StartToken); + + c = sgetc(str); + CurrentIn = Scan(str, &c); + + do + { + + TopToken = Pop(Stack); + +#ifdef _SCRIPT_ENGINE_DBG_EN + printf("\nTop Token :\n"); + PrintToken(TopToken); + printf("\nCurrent Input :\n"); + PrintToken(CurrentIn); + printf("\n"); +#endif + + + if (TopToken->Type == NON_TERMINAL) + { + NonTerminalId = GetNonTerminalId(TopToken); + if (NonTerminalId == -1) + { + printf("Error in Nonterminal ID\n"); + return; + } + TerminalId = GetTerminalId(CurrentIn); + if (TerminalId == -1) + { + printf("Error in Terminal ID\n"); + return; + } + RuleId = ParseTable[NonTerminalId][TerminalId]; + if (RuleId == -1) + { + printf("Error in Parse Table\n"); + return; + } + + // printf("Rule ID = %d\n", RuleId); + + // Push RHS Reversely into stack + for (int i = RhsSize[RuleId] - 1; i >= 0; i--) + { + TOKEN Token = &Rhs[RuleId][i]; + + if (Token->Type == EPSILON) + break; + Push(Stack, Token); + } + } + else if (TopToken->Type == SEMANTIC_RULE) + { + if (!strcmp(TopToken->Value, "@PUSH")) + { + TopToken = Pop(Stack); + Push(MatchedStack, CurrentIn); + CurrentIn = Scan(str, &c); + + // char t = getchar(); + } + else + { + CodeGen(MatchedStack, CodeBuffer, TopToken); + + } + } + else + { + if (!IsEqual(TopToken, CurrentIn)) + { + printf("Error: Not Matched\n"); + return; + } + else + { + CurrentIn = Scan(str, &c); + /* printf("\nCurrent Input :\n"); + PrintToken(CurrentIn); + printf("\n");*/ + +#ifdef _SCRIPT_ENGINE_DBG_EN + printf("matched...\n"); +#endif + } + } +#ifdef _SCRIPT_ENGINE_DBG_EN + PrintTokenList(Stack); + printf("\n"); +#endif + + } while (TopToken->Type != END_OF_STACK); + + return CodeBuffer; +} + +TOKEN NewTemp(void) +{ + static unsigned int TempID = 0; + int i; + for (i = 0; i < MAX_TEMP_COUNT; i++) + { + if (TempMap[i] == 0) + { + TempID = i; + TempMap[i] = 1; + break; + } + } + if (i == MAX_TEMP_COUNT) + { + // TODO: Handle Error + printf("Error: Not enough tempporary variables to allocate. \n"); + } + TOKEN Temp = NewToken(); + char TempValue[8]; + sprintf(TempValue, "%d", TempID); + strcpy(Temp->Value, TempValue); + Temp->Type = TEMP; + return Temp; + +} +void FreeTemp(TOKEN Temp) +{ + int id = DecimalToInt(Temp->Value); + if (Temp->Type == TEMP) + { + TempMap[id] = 0; + } + free(Temp); + +} +void CodeGen(TOKEN_LIST MatchedStack, PSYMBOL_BUFFER CodeBuffer, TOKEN Operator) +{ + + TOKEN Op0; + TOKEN Op1; + TOKEN Temp; + + PSYMBOL OperatorSymbol; + PSYMBOL Op0Symbol; + PSYMBOL Op1Symbol; + PSYMBOL TempSymbol; + + OperatorSymbol = ToSymbol(Operator); + PushSymbol(CodeBuffer, OperatorSymbol); + + Op0 = Pop(MatchedStack); + Op0Symbol = ToSymbol(Op0); + PushSymbol(CodeBuffer, Op0Symbol); + + + + if (!strcmp(Operator->Value, "@MOV")) + { + Op1 = Pop(MatchedStack); + Op1Symbol = ToSymbol(Op1); + PushSymbol(CodeBuffer, Op1Symbol); + + + printf("%s\t%s,\t%s\n", Operator->Value, Op1->Value, Op0->Value); + PrintSymbol(OperatorSymbol); + PrintSymbol(Op1Symbol); + PrintSymbol(Op0Symbol); + printf("_____________\n"); + + // Free the operand if it is a temp value + FreeTemp(Op0); + FreeTemp(Op1); + } + else if (HasTwoOperand(Operator)) + { + + Op1 = Pop(MatchedStack); + Op1Symbol = ToSymbol(Op1); + PushSymbol(CodeBuffer, Op1Symbol); + + + + Temp = NewTemp(); + Push(MatchedStack, Temp); + TempSymbol = ToSymbol(Temp); + PushSymbol(CodeBuffer, TempSymbol); + + + + + + + printf("%s\t%s,\t%s,\t%s\n", Operator->Value, Temp->Value, Op0->Value, Op1->Value); + PrintSymbol(OperatorSymbol); + PrintSymbol(TempSymbol); + PrintSymbol(Op1Symbol); + PrintSymbol(Op0Symbol); + printf("_____________\n"); + + // Free the operand if it is a temp value + FreeTemp(Op0); + FreeTemp(Op1); + } + else + { + + Temp = NewTemp(); + Push(MatchedStack, Temp); + TempSymbol = ToSymbol(Temp); + PushSymbol(CodeBuffer, TempSymbol); + + + + + + printf("%s\t%s,\t%s\n", Operator->Value, Temp->Value, Op0->Value); + PrintSymbol(OperatorSymbol); + PrintSymbol(TempSymbol); + PrintSymbol(Op0Symbol); + printf("_____________\n"); + + // Free the operand if it is a temp value + FreeTemp(Op0); + } + + +} + + +char HasTwoOperand(TOKEN Operator) +{ + unsigned int n = sizeof(OneOperandSemanticRules) / sizeof(char*); + for (int i = 0; i < n; i++) + { + if (!strcmp(Operator->Value, OneOperandSemanticRules[i])) + { + return 0; + } + } + return 1; +} + +/** +* +* +* +*/ +char IsNoneTerminal(TOKEN Token) +{ + if (Token->Value[0] >= 'A' && Token->Value[0] <= 'Z') + return 1; + else + return 0; +} + +/** +* +* +* +*/ +char IsSemanticRule(TOKEN Token) +{ + if (Token->Value[0] == '@') + return 1; + else + return 0; +} + +/** +* +* +* +*/ +int GetNonTerminalId(TOKEN Token) +{ + for (int i = 0; i < NONETERMINAL_COUNT; i++) + { + if (!strcmp(Token->Value, NoneTerminalMap[i])) + return i; + } + return -1; +} + +/** +* +* +* +*/ +int GetTerminalId(TOKEN Token) +{ + + for (int i = 0; i < TERMINAL_COUNT; i++) + { + if (Token->Type == HEX) + { + if (!strcmp("_hex", TerminalMap[i])) + return i; + } + else if (Token->Type == ID) + { + if (!strcmp("_id", TerminalMap[i])) + { + return i; + } + } + else if (Token->Type == REGISTER) + { + if (!strcmp("_register", TerminalMap[i])) + { + return i; + } + } + else if (Token->Type == PSEUDO_REGISTER) + { + if (!strcmp("_pseudo_register", TerminalMap[i])) + { + return i; + } + } + else if (Token->Type == DECIMAL) + { + if (!strcmp("_decimal", TerminalMap[i])) + { + return i; + } + } + else if (Token->Type == BINARY) + { + if (!strcmp("_binary", TerminalMap[i])) + { + return i; + } + } + else if (Token->Type == OCTAL) + { + if (!strcmp("_octal", TerminalMap[i])) + { + return i; + } + } + + else // Keyword + { + if (!strcmp(Token->Value, TerminalMap[i])) + return i; + } + } + return -1; + +} + +/** +* +* +* +*/ +char IsEqual(const TOKEN Token1, const TOKEN Token2) +{ + if (Token1->Type == Token2->Type) + { + if (Token1->Type == SPECIAL_TOKEN) + { + if (!strcmp(Token1->Value, Token2->Value)) + { + return 1; + } + } + else + { + return 1; + } + } + return 0; +} + +/** +* +* +* +*/ +PSYMBOL NewSymbol(void) +{ + PSYMBOL Symbol; + Symbol = (PSYMBOL)malloc(sizeof(*Symbol)); + Symbol->Value = 0; + Symbol->Type = 0; + return Symbol; +} + +/** +* +* +* +*/ +void RemoveSymbol(PSYMBOL Symbol) +{ + free(Symbol); + return; +} + + +/** +* +* +* +*/ +void PrintSymbol(PSYMBOL Symbol) +{ + printf("Type:%llx, Value:0x%llx\n", Symbol->Type, Symbol->Value); +} + + +PSYMBOL ToSymbol(TOKEN Token) +{ + PSYMBOL Symbol = NewSymbol(); + switch (Token->Type) + { + case ID: + Symbol->Value = IdCounter++; + SetType(&Symbol->Type, SYMBOL_ID_TYPE); + return Symbol; + case DECIMAL: + Symbol->Value = DecimalToInt(Token->Value); + SetType(&Symbol->Type, SYMBOL_NUM_TYPE); + return Symbol; + case HEX: + Symbol->Value = HexToInt(Token->Value); + SetType(&Symbol->Type, SYMBOL_NUM_TYPE); + return Symbol; + case OCTAL: + Symbol->Value = OctalToInt(Token->Value); + SetType(&Symbol->Type, SYMBOL_NUM_TYPE); + return Symbol; + case BINARY: + Symbol->Value = BinaryToInt(Token->Value); + SetType(&Symbol->Type, SYMBOL_NUM_TYPE); + return Symbol; + + case REGISTER: + Symbol->Value = RegisterToInt(Token->Value); // TODO: Implement RegisterToInt(char* str) + SetType(&Symbol->Type, SYMBOL_REGISTER_TYPE); + return Symbol; + + case PSEUDO_REGISTER: + Symbol->Value = PseudoRegToInt(Token->Value); // TODO: Implement PseudoRegToInt(char* str) + SetType(&Symbol->Type, SYMBOL_PSEUDO_REG_TYPE); + return Symbol; + + case SEMANTIC_RULE: + Symbol->Value = SemanticRuleToInt(Token->Value); // TODO: Implement SemanticRuleToInt(char* str) + SetType(&Symbol->Type, SYMBOL_SEMANTIC_RULE_TYPE); + return Symbol; + case TEMP: + Symbol->Value = DecimalToInt(Token->Value); // TODO: Convert String to int + SetType(&Symbol->Type, SYMBOL_TEMP); + return Symbol; + + default: + // Raise Error + printf("Error in Converting Token with type %d to Symbol!\n",Token->Type); // TODO: Handle Error in a Error Handler Funtion + } +} +void SetType(unsigned long long *Val, unsigned char Type) +{ + *Val = (unsigned long long int)Type; +} + +unsigned long long int DecimalToInt(char *str) +{ + unsigned long long int acc = 0; + for (int i = 0; i < strlen(str); i++) + { + acc *= 10; + acc += (str[i] - '0'); + } + return acc; +} +unsigned long long int HexToInt(char *str) +{ + char temp; + unsigned long long int acc = 0; + for (int i = 0 ; i < strlen(str); i++) + { + acc <<= 4; + if (str[i] >= '0' && str[i] <= '9') + { + temp = str[i] - '0'; + } + else if (str[i] >= 'a' && str[i] <= 'f') + { + temp = str[i] - 'a' + 10; + } + else + { + temp = str[i] - 'A' + 10; + } + acc += temp; + } + + return acc; +} +unsigned long long int OctalToInt(char *str) +{ + unsigned long long int acc = 0; + for (int i = 0; i < strlen(str); i++) + { + acc <<= 3; + acc += (str[i] - '0'); + } + return acc; +} +unsigned long long int BinaryToInt(char *str) +{ + unsigned long long int acc = 0; + for (int i = 0; i < strlen(str); i++) + { + acc <<= 1; + acc += (str[i] - '0'); + } + return acc; +} + +unsigned long long int RegisterToInt(char *str) +{ + + if (!strcmp(str, "rcx")) + { + return RCX_MNEMONIC; + } + else if (!strcmp(str, "r10")) + { + return R10_MNEMONIC; + } + // ... + // TODO: Handle all Registers + return INVALID; +} +unsigned long long int PseudoRegToInt(char *str) +{ + // ... + // TODO: Handle all Pseudo Registers + return INVALID; +} +unsigned long long int SemanticRuleToInt(char *str) +{ + if (!strcmp(str, "@OR")) + { + return (unsigned long long int)FUNC_OR; + } + else if (!strcmp(str, "@XOR")) + { + return (unsigned long long int)FUNC_XOR; + } + else if (!strcmp(str, "@AND")) + { + return (unsigned long long int)FUNC_OR; + } + else if (!strcmp(str, "@ASR")) + { + return (unsigned long long int)FUNC_ASR; + } + else if (!strcmp(str, "@ASL")) + { + return (unsigned long long int)FUNC_ASR; + } + else if (!strcmp(str, "@ADD")) + { + return (unsigned long long int)FUNC_ADD; + } + else if (!strcmp(str, "@SUB")) + { + return (unsigned long long int)FUNC_SUB; + } + else if (!strcmp(str, "@MUL")) + { + return (unsigned long long int)FUNC_MUL; + } + else if (!strcmp(str, "@DIV")) + { + return (unsigned long long int)FUNC_DIV; + } + else if (!strcmp(str, "@MOD")) + { + return (unsigned long long int)FUNC_MOD; + } + else if (!strcmp(str, "@POI")) + { + return (unsigned long long int)FUNC_POI; + } + else if (!strcmp(str, "@DB")) + { + return (unsigned long long int)FUNC_DB; + } + else if (!strcmp(str, "@DD")) + { + return (unsigned long long int)FUNC_DD; + } + else if (!strcmp(str, "@DW")) + { + return (unsigned long long int)FUNC_DW; + } + else if (!strcmp(str, "@DQ")) + { + return (unsigned long long int)FUNC_DQ; + } + else if (!strcmp(str, "@STR")) + { + return (unsigned long long int)FUNC_STR; + } + else if (!strcmp(str, "@WSTR")) + { + return (unsigned long long int)FUNC_WSTR; + } + else if (!strcmp(str, "@SIZEOF")) + { + return (unsigned long long int)FUNC_SIZEOF; + } + else if (!strcmp(str, "@NOT")) + { + return (unsigned long long int)FUNC_NOT; + } + else if (!strcmp(str, "@NEG")) + { + return (unsigned long long int)FUNC_NEG; + } + else if (!strcmp(str, "@HI")) + { + return (unsigned long long int)FUNC_HI; + } + else if (!strcmp(str, "@LOW")) + { + return (unsigned long long int)FUNC_LOW; + } + else if (!strcmp(str, "@MOV")) + { + return (unsigned long long int)FUNC_MOV; + } + return -1; +} + +/** +* +* +* +*/ +PSYMBOL_BUFFER NewSymbolBuffer(void) +{ + PSYMBOL_BUFFER SymbolBuffer; + SymbolBuffer = (PSYMBOL_BUFFER)malloc(sizeof(*SymbolBuffer)); + SymbolBuffer->Pointer = 0; + SymbolBuffer->Size = SYMBOL_BUFFER_INIT_SIZE; + SymbolBuffer->Head = (PSYMBOL)malloc(SymbolBuffer->Size * sizeof(SYMBOL)); + return SymbolBuffer; +} + +/** +* +* +* +*/ +void RemoveSymbolBuffer(PSYMBOL_BUFFER SymbolBuffer) +{ + // TODO: When size of SymbolBuffer is more than 0, it must be freed + free(SymbolBuffer); + return; +} + +/** +* +* +* +*/ +PSYMBOL_BUFFER PushSymbol(PSYMBOL_BUFFER SymbolBuffer, const PSYMBOL Symbol) +{ + // + // Calculate address to write new token + // + uintptr_t Head = (uintptr_t)SymbolBuffer->Head; + uintptr_t Pointer = (uintptr_t)SymbolBuffer->Pointer; + PSYMBOL WriteAddr = (PSYMBOL)(Head + Pointer * sizeof(SYMBOL)); + + // + // Write input to the appropriate address in SymbolBuffer + // + *WriteAddr = *Symbol; + + // + // Update Pointer + // + SymbolBuffer->Pointer++; + + // + // Handle Overflow + // + if (Pointer == SymbolBuffer->Size - 1) + { + // + // Allocate a new buffer for string list with doubled length + // + PSYMBOL NewHead = (PSYMBOL)malloc(2 * SymbolBuffer->Size * sizeof(SYMBOL)); + + // + // Copy old Buffer to new buffer + // + memcpy(NewHead, SymbolBuffer->Head, SymbolBuffer->Size * sizeof(SYMBOL)); + + // + // Free Old buffer + // + free(SymbolBuffer->Head); + + // + // Upadate Head and size of SymbolBuffer + // + SymbolBuffer->Size *= 2; + SymbolBuffer->Head = NewHead; + } + + return SymbolBuffer; +} + +/** +* +* +* +*/ +PSYMBOL PopSymbol(PSYMBOL_BUFFER SymbolBuffer) +{ + if (SymbolBuffer->Pointer > 0) + { + SymbolBuffer->Pointer--; + } + uintptr_t Head = SymbolBuffer->Head; + uintptr_t Pointer = SymbolBuffer->Pointer; + PSYMBOL ReadAddr = (PSYMBOL)(Head + Pointer * sizeof(SYMBOL)); + + return ReadAddr; +} + + + +/** +* +* +* +*/ +void PrintSymbolBuffer(const PSYMBOL_BUFFER SymbolBuffer) +{ + PSYMBOL Symbol; + for (int i = 0; i < SymbolBuffer->Pointer; i++) + { + Symbol = SymbolBuffer->Head + i; + PrintSymbol(Symbol); + } +} \ No newline at end of file diff --git a/hyperdbg/ScriptEngine/src/ScriptEngine.h b/hyperdbg/ScriptEngine/src/ScriptEngine.h new file mode 100644 index 00000000..0e183dc4 --- /dev/null +++ b/hyperdbg/ScriptEngine/src/ScriptEngine.h @@ -0,0 +1,138 @@ +#ifndef SCRIPT_ENGINE_H +#define SCRIPT_ENGINE_H + + +#include +#include "scanner.h" + + //#define _SCRIPT_ENGINE_DBG_EN + +#define SYMBOL_ID_TYPE 0 +#define SYMBOL_NUM_TYPE 1 +#define SYMBOL_REGISTER_TYPE 2 +#define SYMBOL_PSEUDO_REG_TYPE 3 +#define SYMBOL_SEMANTIC_RULE_TYPE 4 +#define SYMBOL_TEMP 5 + + +#define R10_MNEMONIC 0 +#define RCX_MNEMONIC 16 + +#define INVALID -1 + + +#define FUNC_OR 0 +#define FUNC_XOR 1 +#define FUNC_AND 2 +#define FUNC_ASR 3 +#define FUNC_ASL 4 +#define FUNC_ADD 5 +#define FUNC_SUB 6 +#define FUNC_MUL 7 +#define FUNC_DIV 8 +#define FUNC_MOD 9 +#define FUNC_POI 10 +#define FUNC_DB 11 +#define FUNC_DD 12 +#define FUNC_DW 13 +#define FUNC_DQ 14 +#define FUNC_STR 15 +#define FUNC_WSTR 16 +#define FUNC_SIZEOF 17 +#define FUNC_NOT 18 +#define FUNC_NEG 19 +#define FUNC_HI 20 +#define FUNC_LOW 21 +#define FUNC_MOV 22 + + +#define SYMBOL_BUFFER_INIT_SIZE 1024 +#define MAX_TEMP_COUNT 32 + +// TODO : Automate generating this array +const char* OneOperandSemanticRules[] = +{ + "@POI", + "@DB", + "@DD", + "@DW", + "@DQ", + "@STR", + "@WSTR", + "@SIZEOF", + "@NOT", + "@NEG", + "@HI", + "@LOW" +}; + +typedef struct SYMBOL +{ + long long unsigned Type; + long long unsigned Value; +}SYMBOL, * PSYMBOL; + +typedef struct SYMBOL_BUFFER +{ + PSYMBOL Head; + unsigned int Pointer; + unsigned int Size; + unsigned int IdsCount; + +}SYMBOL_BUFFER, * PSYMBOL_BUFFER; + + +char TempMap[MAX_TEMP_COUNT] = { 0 }; +unsigned int IdCounter = 0; + + +char IsNoneTerminal(TOKEN Token); +char IsSemanticRule(TOKEN Token); +char IsEqual(const TOKEN Token1, const TOKEN Token2); + +int GetNonTerminalId(TOKEN Token); +int GetTerminalId(TOKEN Token); + + +PSYMBOL NewSymbol(void); +void RemoveSymbol(PSYMBOL Symbol); +__declspec(dllexport) void PrintSymbol(PSYMBOL Symbol); + +PSYMBOL_BUFFER NewSymbolBuffer(void); +void RemoveSymbolBuffer(PSYMBOL_BUFFER SymbolBuffer); +PSYMBOL_BUFFER PushSymbol(PSYMBOL_BUFFER SymbolBuffer, const PSYMBOL Symbol); +PSYMBOL PopSymbol(PSYMBOL_BUFFER SymbolBuffer); + +__declspec(dllexport) void PrintSymbolBuffer(const PSYMBOL_BUFFER SymbolBuffer); + +PSYMBOL ToSymbol(TOKEN Token); + + + + + + + +// Util Functions: +void SetType(unsigned long long* Val, unsigned char Type); +unsigned long long int DecimalToInt(char* str); +unsigned long long int HexToInt(char* str); +unsigned long long int OctalToInt(char* str); +unsigned long long int BinaryToInt(char* str); + +unsigned long long int RegisterToInt(char* str); +unsigned long long int PseudoRegToInt(char* str); +unsigned long long int SemanticRuleToInt(char* str); + +TOKEN NewTemp(void); +void FreeTemp(TOKEN Temp); + + + + +__declspec(dllexport) PSYMBOL_BUFFER ScriptEngineParse(char* str); + +void CodeGen(TOKEN_LIST MatchedStack, PSYMBOL_BUFFER CodeBuffer, TOKEN Operator); +char HasTwoOperand(TOKEN Operator); + +#endif // !SCRIPT_ENGINE_H \ No newline at end of file diff --git a/hyperdbg/ScriptEngine/src/input.txt b/hyperdbg/ScriptEngine/src/input.txt new file mode 100644 index 00000000..a171613e --- /dev/null +++ b/hyperdbg/ScriptEngine/src/input.txt @@ -0,0 +1,29 @@ + + +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 diff --git a/hyperdbg/ScriptEngine/src/parse_table.h b/hyperdbg/ScriptEngine/src/parse_table.h new file mode 100644 index 00000000..3975df6f --- /dev/null +++ b/hyperdbg/ScriptEngine/src/parse_table.h @@ -0,0 +1,277 @@ +#ifndef PARSE_TABLE_H +#define PARSE_TABLE_H +#include "scanner.h" +#define RULES_COUNT 55 +#define TERMINAL_COUNT 35 +#define NONETERMINAL_COUNT 25 +#define START_VARIABLE "S" +#define MAX_RHS_LEN 6 +const struct _TOKEN Lhs[RULES_COUNT]= +{ + {NON_TERMINAL, "S"}, + {NON_TERMINAL, "S'"}, + {NON_TERMINAL, "S'"}, + {NON_TERMINAL, "C"}, + {NON_TERMINAL, "C'"}, + {NON_TERMINAL, "E0"}, + {NON_TERMINAL, "E0'"}, + {NON_TERMINAL, "E0'"}, + {NON_TERMINAL, "E1"}, + {NON_TERMINAL, "E1'"}, + {NON_TERMINAL, "E1'"}, + {NON_TERMINAL, "E2"}, + {NON_TERMINAL, "E2'"}, + {NON_TERMINAL, "E2'"}, + {NON_TERMINAL, "E3"}, + {NON_TERMINAL, "E3'"}, + {NON_TERMINAL, "E3'"}, + {NON_TERMINAL, "E4"}, + {NON_TERMINAL, "E4'"}, + {NON_TERMINAL, "E4'"}, + {NON_TERMINAL, "E5"}, + {NON_TERMINAL, "E5'"}, + {NON_TERMINAL, "E5'"}, + {NON_TERMINAL, "E6"}, + {NON_TERMINAL, "E6'"}, + {NON_TERMINAL, "E6'"}, + {NON_TERMINAL, "E7"}, + {NON_TERMINAL, "E7'"}, + {NON_TERMINAL, "E7'"}, + {NON_TERMINAL, "E8"}, + {NON_TERMINAL, "E8'"}, + {NON_TERMINAL, "E8'"}, + {NON_TERMINAL, "E9"}, + {NON_TERMINAL, "E9'"}, + {NON_TERMINAL, "E9'"}, + {NON_TERMINAL, "E10"}, + {NON_TERMINAL, "E10"}, + {NON_TERMINAL, "E10"}, + {NON_TERMINAL, "E10"}, + {NON_TERMINAL, "E10"}, + {NON_TERMINAL, "E10"}, + {NON_TERMINAL, "E10"}, + {NON_TERMINAL, "E10"}, + {NON_TERMINAL, "E10"}, + {NON_TERMINAL, "E10"}, + {NON_TERMINAL, "E10"}, + {NON_TERMINAL, "E10"}, + {NON_TERMINAL, "E10"}, + {NON_TERMINAL, "E10"}, + {NON_TERMINAL, "E10"}, + {NON_TERMINAL, "E10"}, + {NON_TERMINAL, "E10"}, + {NON_TERMINAL, "E10"}, + {NON_TERMINAL, "E10"}, + {NON_TERMINAL, "E10"} +}; +const struct _TOKEN Rhs[RULES_COUNT][MAX_RHS_LEN]= +{ + {{NON_TERMINAL, "C"},{SPECIAL_TOKEN, ";"},{NON_TERMINAL, "S'"}}, + {{NON_TERMINAL, "C"},{SPECIAL_TOKEN, ";"},{NON_TERMINAL, "S'"}}, + {{EPSILON, "eps"}}, + {{SEMANTIC_RULE, "@PUSH"},{ID, "_id"},{SPECIAL_TOKEN, "="},{NON_TERMINAL, "E0"},{SEMANTIC_RULE, "@MOV"},{NON_TERMINAL, "C'"}}, + {{EPSILON, "eps"}}, + {{NON_TERMINAL, "E1"},{NON_TERMINAL, "E0'"}}, + {{SPECIAL_TOKEN, "|"},{NON_TERMINAL, "E1"},{SEMANTIC_RULE, "@OR"},{NON_TERMINAL, "E0'"}}, + {{EPSILON, "eps"}}, + {{NON_TERMINAL, "E2"},{NON_TERMINAL, "E1'"}}, + {{SPECIAL_TOKEN, "^"},{NON_TERMINAL, "E2"},{SEMANTIC_RULE, "@XOR"},{NON_TERMINAL, "E1'"}}, + {{EPSILON, "eps"}}, + {{NON_TERMINAL, "E3"},{NON_TERMINAL, "E2'"}}, + {{SPECIAL_TOKEN, "&"},{NON_TERMINAL, "E3"},{SEMANTIC_RULE, "@AND"},{NON_TERMINAL, "E2'"}}, + {{EPSILON, "eps"}}, + {{NON_TERMINAL, "E4"},{NON_TERMINAL, "E3'"}}, + {{SPECIAL_TOKEN, ">>"},{NON_TERMINAL, "E4"},{SEMANTIC_RULE, "@ASR"},{NON_TERMINAL, "E3'"}}, + {{EPSILON, "eps"}}, + {{NON_TERMINAL, "E5"},{NON_TERMINAL, "E4'"}}, + {{SPECIAL_TOKEN, "<<"},{NON_TERMINAL, "E5"},{SEMANTIC_RULE, "@ASL"},{NON_TERMINAL, "E4'"}}, + {{EPSILON, "eps"}}, + {{NON_TERMINAL, "E6"},{NON_TERMINAL, "E5'"}}, + {{SPECIAL_TOKEN, "+"},{NON_TERMINAL, "E6"},{SEMANTIC_RULE, "@ADD"},{NON_TERMINAL, "E5'"}}, + {{EPSILON, "eps"}}, + {{NON_TERMINAL, "E7"},{NON_TERMINAL, "E6'"}}, + {{SPECIAL_TOKEN, "-"},{NON_TERMINAL, "E7"},{SEMANTIC_RULE, "@SUB"},{NON_TERMINAL, "E6'"}}, + {{EPSILON, "eps"}}, + {{NON_TERMINAL, "E8"},{NON_TERMINAL, "E7'"}}, + {{SPECIAL_TOKEN, "*"},{NON_TERMINAL, "E8"},{SEMANTIC_RULE, "@MUL"},{NON_TERMINAL, "E7'"}}, + {{EPSILON, "eps"}}, + {{NON_TERMINAL, "E9"},{NON_TERMINAL, "E8'"}}, + {{SPECIAL_TOKEN, "/"},{NON_TERMINAL, "E9"},{SEMANTIC_RULE, "@DIV"},{NON_TERMINAL, "E8'"}}, + {{EPSILON, "eps"}}, + {{NON_TERMINAL, "E10"},{NON_TERMINAL, "E9'"}}, + {{SPECIAL_TOKEN, "%"},{NON_TERMINAL, "E10"},{SEMANTIC_RULE, "@MOD"},{NON_TERMINAL, "E9'"}}, + {{EPSILON, "eps"}}, + {{KEYWORD, "poi"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "E0"},{SEMANTIC_RULE, "@POI"},{SPECIAL_TOKEN, ")"}}, + {{KEYWORD, "db"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "E0"},{SEMANTIC_RULE, "@DB"},{SPECIAL_TOKEN, ")"}}, + {{KEYWORD, "dd"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "E0"},{SEMANTIC_RULE, "@DD"},{SPECIAL_TOKEN, ")"}}, + {{KEYWORD, "dw"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "E0"},{SEMANTIC_RULE, "@DW"},{SPECIAL_TOKEN, ")"}}, + {{KEYWORD, "dq"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "E0"},{SEMANTIC_RULE, "@DQ"},{SPECIAL_TOKEN, ")"}}, + {{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, ")"}}, + {{SPECIAL_TOKEN, "("},{NON_TERMINAL, "E0"},{SPECIAL_TOKEN, ")"}}, + {{SEMANTIC_RULE, "@PUSH"},{REGISTER, "_register"}}, + {{SEMANTIC_RULE, "@PUSH"},{HEX, "_hex"}}, + {{SEMANTIC_RULE, "@PUSH"},{DECIMAL, "_decimal"}}, + {{SEMANTIC_RULE, "@PUSH"},{OCTAL, "_octal"}}, + {{SEMANTIC_RULE, "@PUSH"},{BINARY, "_binary"}}, + {{SEMANTIC_RULE, "@PUSH"},{KEYWORD, "func"}}, + {{SEMANTIC_RULE, "@PUSH"},{PSEUDO_REGISTER, "_pseudo_register"}} +}; +const unsigned int RhsSize[RULES_COUNT]= +{ +3, +3, +1, +6, +1, +2, +4, +1, +2, +4, +1, +2, +4, +1, +2, +4, +1, +2, +4, +1, +2, +4, +1, +2, +4, +1, +2, +4, +1, +2, +4, +1, +2, +4, +1, +5, +5, +5, +5, +5, +5, +5, +5, +5, +5, +5, +5, +3, +2, +2, +2, +2, +2, +2, +2 +}; +const char* NoneTerminalMap[NONETERMINAL_COUNT]= +{ +"E8", +"E5'", +"E6'", +"S", +"E3", +"E3'", +"E1", +"E4'", +"E5", +"E2'", +"E6", +"E10", +"E9'", +"E1'", +"E0", +"E9", +"C'", +"E7'", +"C", +"E8'", +"E2", +"E7", +"S'", +"E0'", +"E4" +}; +const char* TerminalMap[TERMINAL_COUNT]= +{ +"_id", +";", +"str", +"&", +"/", +"low", +"_binary", +"_pseudo_register", +"poi", +"<<", +"db", +"_octal", +"dq", +"|", +"%", +"=", +"_decimal", +"*", +"(", +"dw", +"+", +">>", +"_hex", +"not", +"dd", +"^", +"-", +"func", +"wstr", +"sizeof", +"$", +"neg", +")", +"hi", +"_register" +}; +const int ParseTable[NONETERMINAL_COUNT][TERMINAL_COUNT]= +{ + {-1 ,-1 ,29 ,-1 ,-1 ,29 ,29 ,29 ,29 ,-1 ,29 ,29 ,29 ,-1 ,-1 ,-1 ,29 ,-1 ,29 ,29 ,-1 ,-1 ,29 ,29 ,29 ,-1 ,-1 ,29 ,29 ,29 ,-1 ,29 ,-1 ,29 ,29 }, + {-1 ,22 ,-1 ,22 ,-1 ,-1 ,-1 ,-1 ,-1 ,22 ,-1 ,-1 ,-1 ,22 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,21 ,22 ,-1 ,-1 ,-1 ,22 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,22 ,-1 ,-1 }, + {-1 ,25 ,-1 ,25 ,-1 ,-1 ,-1 ,-1 ,-1 ,25 ,-1 ,-1 ,-1 ,25 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,25 ,25 ,-1 ,-1 ,-1 ,25 ,24 ,-1 ,-1 ,-1 ,-1 ,-1 ,25 ,-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 ,14 ,-1 ,-1 ,14 ,14 ,14 ,14 ,-1 ,14 ,14 ,14 ,-1 ,-1 ,-1 ,14 ,-1 ,14 ,14 ,-1 ,-1 ,14 ,14 ,14 ,-1 ,-1 ,14 ,14 ,14 ,-1 ,14 ,-1 ,14 ,14 }, + {-1 ,16 ,-1 ,16 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,16 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,15 ,-1 ,-1 ,-1 ,16 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,16 ,-1 ,-1 }, + {-1 ,-1 ,8 ,-1 ,-1 ,8 ,8 ,8 ,8 ,-1 ,8 ,8 ,8 ,-1 ,-1 ,-1 ,8 ,-1 ,8 ,8 ,-1 ,-1 ,8 ,8 ,8 ,-1 ,-1 ,8 ,8 ,8 ,-1 ,8 ,-1 ,8 ,8 }, + {-1 ,19 ,-1 ,19 ,-1 ,-1 ,-1 ,-1 ,-1 ,18 ,-1 ,-1 ,-1 ,19 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,19 ,-1 ,-1 ,-1 ,19 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,19 ,-1 ,-1 }, + {-1 ,-1 ,20 ,-1 ,-1 ,20 ,20 ,20 ,20 ,-1 ,20 ,20 ,20 ,-1 ,-1 ,-1 ,20 ,-1 ,20 ,20 ,-1 ,-1 ,20 ,20 ,20 ,-1 ,-1 ,20 ,20 ,20 ,-1 ,20 ,-1 ,20 ,20 }, + {-1 ,13 ,-1 ,12 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,13 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,13 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,13 ,-1 ,-1 }, + {-1 ,-1 ,23 ,-1 ,-1 ,23 ,23 ,23 ,23 ,-1 ,23 ,23 ,23 ,-1 ,-1 ,-1 ,23 ,-1 ,23 ,23 ,-1 ,-1 ,23 ,23 ,23 ,-1 ,-1 ,23 ,23 ,23 ,-1 ,23 ,-1 ,23 ,23 }, + {-1 ,-1 ,40 ,-1 ,-1 ,46 ,52 ,54 ,35 ,-1 ,36 ,51 ,39 ,-1 ,-1 ,-1 ,50 ,-1 ,47 ,38 ,-1 ,-1 ,49 ,43 ,37 ,-1 ,-1 ,53 ,41 ,42 ,-1 ,44 ,-1 ,45 ,48 }, + {-1 ,34 ,-1 ,34 ,34 ,-1 ,-1 ,-1 ,-1 ,34 ,-1 ,-1 ,-1 ,34 ,33 ,-1 ,-1 ,34 ,-1 ,-1 ,34 ,34 ,-1 ,-1 ,-1 ,34 ,34 ,-1 ,-1 ,-1 ,-1 ,-1 ,34 ,-1 ,-1 }, + {-1 ,10 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,10 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,9 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,10 ,-1 ,-1 }, + {-1 ,-1 ,5 ,-1 ,-1 ,5 ,5 ,5 ,5 ,-1 ,5 ,5 ,5 ,-1 ,-1 ,-1 ,5 ,-1 ,5 ,5 ,-1 ,-1 ,5 ,5 ,5 ,-1 ,-1 ,5 ,5 ,5 ,-1 ,5 ,-1 ,5 ,5 }, + {-1 ,-1 ,32 ,-1 ,-1 ,32 ,32 ,32 ,32 ,-1 ,32 ,32 ,32 ,-1 ,-1 ,-1 ,32 ,-1 ,32 ,32 ,-1 ,-1 ,32 ,32 ,32 ,-1 ,-1 ,32 ,32 ,32 ,-1 ,32 ,-1 ,32 ,32 }, + {-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 ,28 ,-1 ,28 ,-1 ,-1 ,-1 ,-1 ,-1 ,28 ,-1 ,-1 ,-1 ,28 ,-1 ,-1 ,-1 ,27 ,-1 ,-1 ,28 ,28 ,-1 ,-1 ,-1 ,28 ,28 ,-1 ,-1 ,-1 ,-1 ,-1 ,28 ,-1 ,-1 }, + {3 ,-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 ,31 ,-1 ,31 ,30 ,-1 ,-1 ,-1 ,-1 ,31 ,-1 ,-1 ,-1 ,31 ,-1 ,-1 ,-1 ,31 ,-1 ,-1 ,31 ,31 ,-1 ,-1 ,-1 ,31 ,31 ,-1 ,-1 ,-1 ,-1 ,-1 ,31 ,-1 ,-1 }, + {-1 ,-1 ,11 ,-1 ,-1 ,11 ,11 ,11 ,11 ,-1 ,11 ,11 ,11 ,-1 ,-1 ,-1 ,11 ,-1 ,11 ,11 ,-1 ,-1 ,11 ,11 ,11 ,-1 ,-1 ,11 ,11 ,11 ,-1 ,11 ,-1 ,11 ,11 }, + {-1 ,-1 ,26 ,-1 ,-1 ,26 ,26 ,26 ,26 ,-1 ,26 ,26 ,26 ,-1 ,-1 ,-1 ,26 ,-1 ,26 ,26 ,-1 ,-1 ,26 ,26 ,26 ,-1 ,-1 ,26 ,26 ,26 ,-1 ,26 ,-1 ,26 ,26 }, + {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 ,7 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,6 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,7 ,-1 ,-1 }, + {-1 ,-1 ,17 ,-1 ,-1 ,17 ,17 ,17 ,17 ,-1 ,17 ,17 ,17 ,-1 ,-1 ,-1 ,17 ,-1 ,17 ,17 ,-1 ,-1 ,17 ,17 ,17 ,-1 ,-1 ,17 ,17 ,17 ,-1 ,17 ,-1 ,17 ,17 } +}; +#endif diff --git a/hyperdbg/ScriptEngine/src/scanner.c b/hyperdbg/ScriptEngine/src/scanner.c new file mode 100644 index 00000000..c5a5c868 --- /dev/null +++ b/hyperdbg/ScriptEngine/src/scanner.c @@ -0,0 +1,679 @@ +#include "scanner.h" +#include +#include +#include +#include + +const char* KeywordList[] = +{ + "str", + "low", + "poi", + "db", + "dq", + "dw", + "not", + "dd", + "func", + "wstr", + "sizeof", + "neg", + "hi" +}; + +/** + * + */ +TOKEN NewToken() +{ + TOKEN Token; + Token = (TOKEN)malloc(sizeof(*Token)); + Token->Value = (char *)calloc(TOKEN_VALUE_MAX_LEN, sizeof(char)); + strcpy(Token->Value, ""); + Token->Type = UNKNOWN; + return Token; +} + +/** + * + */ +TOKEN_LIST NewTokenList(void) +{ + TOKEN_LIST TokenList; + TokenList = (TOKEN_LIST)malloc(sizeof(*TokenList)); + TokenList->Pointer = 0; + TokenList->Size = TOKEN_LIST_INIT_SIZE; + TokenList->Head = (TOKEN *)malloc(TokenList->Size * sizeof(TOKEN)); + 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; +} +/** + * + */ + +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; +} + +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; +} +/** + * + */ +void PrintTokenList(TOKEN_LIST TokenList) +{ + TOKEN Token = NewToken(); + for (uintptr_t i = 0; i < TokenList->Pointer; i++) + { + Token = *(TokenList->Head + i); + PrintToken(Token); + } +} + +/** + * + * + */ +void PrintToken(TOKEN Token) +{ + if (Token->Type == WHITE_SPACE) + { + printf("< :"); + } + else + { + printf("<'%s' : ", Token->Value); + } + + 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; + } +} +/** + * + */ +void Append(TOKEN Token, char c) +{ + strncat(Token->Value, &c, 1); +} +/** + * + */ +TOKEN GetToken(char *c, char* str) +{ + static unsigned char WaitForID = 1; + TOKEN Token = NewToken(); + + switch (*c) + { + case '+': + *c = sgetc(str); + if (*c == '+') + { + strcpy(Token->Value, "++"); + Token->Type = SPECIAL_TOKEN; + *c = sgetc(str); + return Token; + } + else if (*c == '=') + { + strcpy(Token->Value, "+="); + Token->Type = SPECIAL_TOKEN; + *c = sgetc(str); + return Token; + } + else + { + strcpy(Token->Value, "+"); + Token->Type = SPECIAL_TOKEN; + return Token; + } + case '-': + *c = sgetc(str); + if (*c == '-') + { + strcpy(Token->Value, "--"); + Token->Type = SPECIAL_TOKEN; + *c = sgetc(str); + return Token; + } + else if (*c == '=') + { + strcpy(Token->Value, "-="); + Token->Type = SPECIAL_TOKEN; + *c = sgetc(str); + return Token; + } + else + { + strcpy(Token->Value, "-"); + Token->Type = SPECIAL_TOKEN; + return Token; + } + case '*': + *c = sgetc(str); + if (*c == '=') + { + strcpy(Token->Value, "*="); + Token->Type = SPECIAL_TOKEN; + *c = sgetc(str); + return Token; + } + else + { + strcpy(Token->Value, "*"); + Token->Type = SPECIAL_TOKEN; + return Token; + } + case '>': + *c = sgetc(str); + if (*c == '>') + { + strcpy(Token->Value, ">>"); + Token->Type = SPECIAL_TOKEN; + *c = sgetc(str); + return Token; + } + else + { + strcpy(Token->Value, ">"); + Token->Type = SPECIAL_TOKEN; + return Token; + } + case '<': + *c = sgetc(str); + if (*c == '<') + { + strcpy(Token->Value, "<<"); + Token->Type = SPECIAL_TOKEN; + *c = sgetc(str); + return Token; + } + else + { + strcpy(Token->Value, "<"); + Token->Type = SPECIAL_TOKEN; + return Token; + } + case '/': + *c = sgetc(str); + if (*c == '=') + { + strcpy(Token->Value, "/="); + Token->Type = SPECIAL_TOKEN; + *c = sgetc(str); + + return Token; + } + else if (*c == '/') + { + do + { + *c = sgetc(str); + } while (*c != '\n' && *c != EOF); + + Token->Type = COMMENT; + *c = sgetc(str); + return Token; + } + else if (*c == '*') + { + do + { + *c = sgetc(str); + if (*c == '*') + { + *c = sgetc(str); + if (*c == '/') + { + Token->Type = COMMENT; + *c = sgetc(str); + return Token; + } + } + if (*c == EOF) + break; + } while (1); + + Token->Type = UNKNOWN; + *c = sgetc(str); + return Token; + } + else + { + strcpy(Token->Value, "/"); + Token->Type = SPECIAL_TOKEN; + return Token; + } + + case '=': + strcpy(Token->Value, "="); + Token->Type = SPECIAL_TOKEN; + *c = sgetc(str); + return Token; + case '%': + strcpy(Token->Value, "%"); + Token->Type = SPECIAL_TOKEN; + *c = sgetc(str); + return Token; + + case ',': + strcpy(Token->Value, ","); + Token->Type = SPECIAL_TOKEN; + *c = sgetc(str); + return Token; + + case ';': + strcpy(Token->Value, ";"); + Token->Type = SPECIAL_TOKEN; + WaitForID = 1; + *c = sgetc(str); + return Token; + + case ':': + strcpy(Token->Value, ":"); + Token->Type = SPECIAL_TOKEN; + *c = sgetc(str); + return Token; + + case '(': + strcpy(Token->Value, "("); + Token->Type = SPECIAL_TOKEN; + *c = sgetc(str); + return Token; + case ')': + strcpy(Token->Value, ")"); + Token->Type = SPECIAL_TOKEN; + *c = sgetc(str); + return Token; + case '{': + strcpy(Token->Value, "{"); + Token->Type = SPECIAL_TOKEN; + *c = sgetc(str); + return Token; + case '}': + strcpy(Token->Value, "}"); + Token->Type = SPECIAL_TOKEN; + *c = sgetc(str); + return Token; + case '|': + strcpy(Token->Value, "|"); + Token->Type = SPECIAL_TOKEN; + *c = sgetc(str); + return Token; + case '&': + strcpy(Token->Value, "&"); + Token->Type = SPECIAL_TOKEN; + *c = sgetc(str); + return Token; + case '^': + strcpy(Token->Value, "^"); + Token->Type = SPECIAL_TOKEN; + *c = sgetc(str); + return Token; + case '@': + *c = sgetc(str); + if (IsLetter(*c)) + { + while (IsLetter(*c) || IsDecimal(*c)) + { + Append(Token, *c); + *c = sgetc(str); + } + Token->Type = REGISTER; + return Token; + } + + case '$': + *c = sgetc(str); + if (IsLetter(*c)) + { + while (IsLetter(*c) || IsDecimal(*c)) + { + Append(Token, *c); + *c = sgetc(str); + } + Token->Type = PSEUDO_REGISTER; + return Token; + } + + case '.': + *c = sgetc(str); + if (IsHex(*c)) + { + } + else + { + } + + case ' ': + case '\t': + strcpy(Token->Value, ""); + Token->Type = WHITE_SPACE; + *c = sgetc(str); + return Token; + case '\n': + strcpy(Token->Value, ""); + Token->Type = WHITE_SPACE; + *c = sgetc(str); + WaitForID = 1; + return Token; + + case '0': + *c = sgetc(str); + if (*c == 'x') + { + *c = sgetc(str); + while (IsHex(*c) || *c == '`') + { + if (*c != '`') + Append(Token, *c); + *c = sgetc(str); + } + Token->Type = HEX; + return Token; + } + else if (*c == 'o') + { + *c = sgetc(str); + while (IsOctal(*c) || *c == '`') + { + if (*c != '`') + Append(Token, *c); + *c = sgetc(str); + } + Token->Type = OCTAL; + return Token; + } + else if (*c == 'n') + { + *c = sgetc(str); + while (IsDecimal(*c) || *c == '`') + { + if (*c != '`') + Append(Token, *c); + *c = sgetc(str); + } + Token->Type = DECIMAL; + return Token; + } + else if (*c == 'y') + { + *c = sgetc(str); + while (IsBinary(*c) || *c == '`') + { + if (*c != '`') + Append(Token, *c); + *c = sgetc(str); + } + Token->Type = BINARY; + return Token; + } + + else if (IsHex(*c)) + { + do + { + if (*c != '`') + Append(Token, *c); + *c = sgetc(str); + } while (IsHex(*c) || *c == '`'); + Token->Type = HEX; + return Token; + } + else + { + strcpy(Token->Value, "0"); + Token->Type = HEX; + return Token; + } + + default: + if (IsHex(*c)) + { + do + { + if (*c != '`') + Append(Token, *c); + *c = sgetc(str); + } while (IsHex(*c) || *c == '`'); + int n = sizeof(KeywordList) / sizeof(char*); + for (int i = 0; i < n; i++) + { + if (!strcmp(Token->Value, KeywordList[i])) + { + Token->Type = KEYWORD; + return Token; + } + } + Token->Type = HEX; + return Token; + } + else if (IsLetter(*c) || *c == '_') + { + while (IsLetter(*c) || *c == '_' || IsDecimal(*c)) + { + Append(Token, *c); + *c = sgetc(str); + } + + if (WaitForID) + { + Token->Type = ID; + WaitForID = 0; + } + else + { + Token->Type = KEYWORD; + } + + return Token; + } + + + Token->Type = UNKNOWN; + *c = sgetc(str); + return Token; + } + return Token; +} +/** + * + */ +TOKEN Scan(char* str, char* c) +{ + TOKEN Token = NewToken(); + + while (1) + { + + Token = GetToken(c, str); + if (*c == EOF) + { + Token->Type = END_OF_STACK; + strcpy(Token->Value,"$"); + return Token; + } + + else if (Token->Type == WHITE_SPACE || Token->Type == COMMENT) + { + continue; + } + return Token; + } +} + +char IsHex(char c) +{ + if ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')) + return 1; + else + return 0; +} +char IsDecimal(char c) +{ + if (c >= '0' && c <= '9') + return 1; + else + return 0; +} +char IsLetter(char c) +{ + if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')) + return 1; + else + { + return 0; + } +} +char IsBinary(char c) +{ + if (c == '0' || c == '1') + return 1; + else + { + return 0; + } +} +char IsOctal(char c) +{ + if (c >= '0' && c <= '7') + return 1; + else + return 0; +} + +char sgetc(char* str) +{ + static int idx = 0; + char c = str[idx]; + if (c) + { + idx++; + return c; + } + else + { + return EOF; + } +} \ No newline at end of file diff --git a/hyperdbg/ScriptEngine/src/scanner.h b/hyperdbg/ScriptEngine/src/scanner.h new file mode 100644 index 00000000..061a03d9 --- /dev/null +++ b/hyperdbg/ScriptEngine/src/scanner.h @@ -0,0 +1,64 @@ +#ifndef SCANNER_H +#define SCANNER_H +#include + +//#define SCRIPTENGINE_EXPORTS +#define TOKEN_VALUE_MAX_LEN 100 +#define TOKEN_LIST_INIT_SIZE 16 +typedef enum TOKEN_TYPE +{ + ID, + DECIMAL, + HEX, + OCTAL, + BINARY, + SPECIAL_TOKEN, + KEYWORD, + WHITE_SPACE, + COMMENT, + REGISTER, + PSEUDO_REGISTER, + NON_TERMINAL, + SEMANTIC_RULE, + END_OF_STACK, + EPSILON, + TEMP, + UNKNOWN +} TOKEN_TYPE; + + + +struct _TOKEN +{ + TOKEN_TYPE Type; + char *Value; +}; + +typedef struct _TOKEN *TOKEN; + +typedef struct _TOKEN_LIST +{ + TOKEN *Head; + unsigned int Pointer; + unsigned int Size; +} * TOKEN_LIST; + +TOKEN NewToken(void); +TOKEN_LIST NewTokenList(void); +void PrintTokenList(TOKEN_LIST TokenList); +void PrintToken(TOKEN Token); +TOKEN_LIST Push(TOKEN_LIST TokenList, TOKEN Token); +TOKEN Pop(TOKEN_LIST TokenList); +TOKEN Top(TOKEN_LIST TokenList); +void Append(TOKEN Token, char c); +TOKEN GetToken(char *c, char* str); +TOKEN Scan(char* str, char* c); +char IsHex(char c); +char IsDecimal(char c); +char IsLetter(char c); +char IsBinary(char c); +char IsOctal(char c); + +char sgetc(char* str); + +#endif \ No newline at end of file diff --git a/hyperdbg/hprdbghv/hprdbghv.vcxproj b/hyperdbg/hprdbghv/hprdbghv.vcxproj index 0de985e0..8c2d1c0e 100644 --- a/hyperdbg/hprdbghv/hprdbghv.vcxproj +++ b/hyperdbg/hprdbghv/hprdbghv.vcxproj @@ -30,6 +30,7 @@ KMDF Universal false + false Windows10 diff --git a/hyperdbg/hyperdbg.sln b/hyperdbg/hyperdbg.sln index 3faef099..34349a8d 100644 --- a/hyperdbg/hyperdbg.sln +++ b/hyperdbg/hyperdbg.sln @@ -20,9 +20,14 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "include", "include", "{1997 EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "hprdbgctrl", "hprdbgctrl\hprdbgctrl.vcxproj", "{809C3AD5-3211-4992-A472-9D81D124C5FA}" + ProjectSection(ProjectDependencies) = postProject + {C2D44C60-3F23-4972-8F60-21083B9FB112} = {C2D44C60-3F23-4972-8F60-21083B9FB112} + EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "hyperdbg-test", "hyperdbg-test\hyperdbg-test.vcxproj", "{C3DC85E1-0559-4B58-9792-DE421472DFE9}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ScriptEngine", "ScriptEngine\ScriptEngine.vcxproj", "{C2D44C60-3F23-4972-8F60-21083B9FB112}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|x64 = Debug|x64 @@ -57,6 +62,14 @@ Global {C3DC85E1-0559-4B58-9792-DE421472DFE9}.Release|x64.Build.0 = Release|x64 {C3DC85E1-0559-4B58-9792-DE421472DFE9}.Release|x86.ActiveCfg = Release|Win32 {C3DC85E1-0559-4B58-9792-DE421472DFE9}.Release|x86.Build.0 = Release|Win32 + {C2D44C60-3F23-4972-8F60-21083B9FB112}.Debug|x64.ActiveCfg = Debug|x64 + {C2D44C60-3F23-4972-8F60-21083B9FB112}.Debug|x64.Build.0 = Debug|x64 + {C2D44C60-3F23-4972-8F60-21083B9FB112}.Debug|x86.ActiveCfg = Debug|Win32 + {C2D44C60-3F23-4972-8F60-21083B9FB112}.Debug|x86.Build.0 = Debug|Win32 + {C2D44C60-3F23-4972-8F60-21083B9FB112}.Release|x64.ActiveCfg = Release|x64 + {C2D44C60-3F23-4972-8F60-21083B9FB112}.Release|x64.Build.0 = Release|x64 + {C2D44C60-3F23-4972-8F60-21083B9FB112}.Release|x86.ActiveCfg = Release|Win32 + {C2D44C60-3F23-4972-8F60-21083B9FB112}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE