mirror of
https://github.com/HyperDbg/HyperDbg.git
synced 2026-07-30 03:15:51 +00:00
698 lines
16 KiB
C
698 lines
16 KiB
C
/**
|
|
* @file ScriptEngine.c
|
|
* @author M.H. Gholamrezei (gholamrezaei.mh@gmail.com)
|
|
* @brief Script engine parser and codegen
|
|
* @details
|
|
* @version 0.1
|
|
* @date 2020-10-22
|
|
*
|
|
* @copyright This project is released under the GNU Public License v3.
|
|
*
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <stdint.h>
|
|
#include "globals.h"
|
|
#include "common.h"
|
|
#include "parse_table.h"
|
|
#include "ScriptEngine.h"
|
|
#include "ScriptEngineCommon.h"
|
|
|
|
|
|
|
|
#include "string.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;
|
|
|
|
//
|
|
// 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);
|
|
|
|
InputIdx = 0;
|
|
|
|
|
|
c = sgetc(str);
|
|
|
|
CurrentIn = Scan(str, &c);
|
|
if (CurrentIn->Type == UNKNOWN)
|
|
{
|
|
char* Message = "Invalid Token!";
|
|
CodeBuffer->Message = (char*)malloc(strlen(Message) + 1);
|
|
strcpy(CodeBuffer->Message, Message);
|
|
|
|
RemoveTokenList(Stack);
|
|
RemoveTokenList(MatchedStack);
|
|
RemoveToken(StartToken);
|
|
RemoveToken(EndToken);
|
|
RemoveToken(CurrentIn);
|
|
return CodeBuffer;
|
|
}
|
|
|
|
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)
|
|
{
|
|
char* Message = "Invalid Syntax!";
|
|
CodeBuffer->Message = (char*)malloc(strlen(Message) + 1);
|
|
strcpy(CodeBuffer->Message, Message);
|
|
|
|
RemoveToken(StartToken);
|
|
RemoveToken(EndToken);
|
|
RemoveTokenList(MatchedStack);
|
|
RemoveToken(CurrentIn);
|
|
return CodeBuffer;
|
|
}
|
|
TerminalId = GetTerminalId(CurrentIn);
|
|
if (TerminalId == -1)
|
|
{
|
|
char* Message = "Invalid Syntax!";
|
|
CodeBuffer->Message = (char*)malloc(strlen(Message) + 1);
|
|
strcpy(CodeBuffer->Message, Message);
|
|
|
|
RemoveToken(StartToken);
|
|
RemoveToken(EndToken);
|
|
RemoveTokenList(MatchedStack);
|
|
RemoveToken(CurrentIn);
|
|
return CodeBuffer;
|
|
}
|
|
RuleId = ParseTable[NonTerminalId][TerminalId];
|
|
if (RuleId == -1)
|
|
{
|
|
char* Message = "Invalid Syntax!";
|
|
CodeBuffer->Message = (char*)malloc(strlen(Message) + 1);
|
|
strcpy(CodeBuffer->Message, Message);
|
|
|
|
RemoveToken(StartToken);
|
|
RemoveToken(EndToken);
|
|
RemoveTokenList(MatchedStack);
|
|
RemoveToken(CurrentIn);
|
|
return CodeBuffer;
|
|
}
|
|
|
|
//
|
|
// 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);
|
|
|
|
if (CurrentIn->Type == UNKNOWN)
|
|
{
|
|
char* Message = "Invalid Token!";
|
|
CodeBuffer->Message = (char*)malloc(strlen(Message) + 1);
|
|
strcpy(CodeBuffer->Message, Message);
|
|
|
|
RemoveToken(StartToken);
|
|
RemoveToken(EndToken);
|
|
RemoveTokenList(MatchedStack);
|
|
RemoveToken(CurrentIn);
|
|
return CodeBuffer;
|
|
}
|
|
|
|
// char t = getchar();
|
|
}
|
|
else
|
|
{
|
|
CodeGen(MatchedStack, CodeBuffer, TopToken);
|
|
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (!IsEqual(TopToken, CurrentIn))
|
|
{
|
|
char* Message = "Invalid Syntax!";
|
|
CodeBuffer->Message = (char*)malloc(strlen(Message) + 1);
|
|
strcpy(CodeBuffer->Message, Message);
|
|
|
|
RemoveToken(StartToken);
|
|
RemoveToken(EndToken);
|
|
RemoveTokenList(MatchedStack);
|
|
RemoveToken(CurrentIn);
|
|
return CodeBuffer;
|
|
}
|
|
else
|
|
{
|
|
|
|
|
|
RemoveToken(CurrentIn);
|
|
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);
|
|
|
|
|
|
RemoveTokenList(Stack);
|
|
RemoveTokenList(MatchedStack);
|
|
RemoveToken(StartToken);
|
|
RemoveToken(EndToken);
|
|
RemoveToken(CurrentIn);
|
|
return CodeBuffer;
|
|
}
|
|
|
|
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);
|
|
printf("_____________\n");
|
|
|
|
//
|
|
// Free the operand if it is a temp value
|
|
//
|
|
FreeTemp(Op0);
|
|
FreeTemp(Op1);
|
|
}
|
|
else if (IsType2Func(Operator))
|
|
{
|
|
printf("%s\t%s\n", Operator->Value, Op0->Value);
|
|
printf("_____________\n");
|
|
|
|
}
|
|
else if (IsType1Func(Operator))
|
|
{
|
|
Temp = NewTemp();
|
|
Push(MatchedStack, Temp);
|
|
TempSymbol = ToSymbol(Temp);
|
|
PushSymbol(CodeBuffer, TempSymbol);
|
|
printf("%s\t%s,\t%s\n", Operator->Value, Temp->Value, Op0->Value);
|
|
printf("_____________\n");
|
|
// Free the operand if it is a temp value
|
|
FreeTemp(Op0);
|
|
}
|
|
else
|
|
{
|
|
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);
|
|
printf("_____________\n");
|
|
|
|
// Free the operand if it is a temp value
|
|
FreeTemp(Op0);
|
|
FreeTemp(Op1);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
/**
|
|
*
|
|
*
|
|
*
|
|
*/
|
|
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
|
|
}
|
|
}
|
|
|
|
/**
|
|
*
|
|
*
|
|
*
|
|
*/
|
|
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));
|
|
SymbolBuffer->Message = NULL;
|
|
return SymbolBuffer;
|
|
}
|
|
|
|
/**
|
|
*
|
|
*
|
|
*
|
|
*/
|
|
void RemoveSymbolBuffer(PSYMBOL_BUFFER SymbolBuffer)
|
|
{
|
|
free(SymbolBuffer->Message);
|
|
free(SymbolBuffer->Head);
|
|
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;
|
|
RemoveSymbol(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);
|
|
}
|
|
}
|
|
|
|
|
|
unsigned long long int RegisterToInt(char* str)
|
|
{
|
|
|
|
if (!strcmp(str, "rax"))
|
|
{
|
|
return RAX_MNEMONIC;
|
|
}
|
|
else if (!strcmp(str, "rcx"))
|
|
{
|
|
return RCX_MNEMONIC;
|
|
}
|
|
else if (!strcmp(str, "rdx"))
|
|
{
|
|
return RDX_MNEMONIC;
|
|
}
|
|
else if (!strcmp(str, "rbx"))
|
|
{
|
|
return RBX_MNEMONIC;
|
|
}
|
|
else if (!strcmp(str, "rsp"))
|
|
{
|
|
return RSP_MNEMONIC;
|
|
}
|
|
else if (!strcmp(str, "rsi"))
|
|
{
|
|
return RSI_MNEMONIC;
|
|
}
|
|
else if (!strcmp(str, "rdi"))
|
|
{
|
|
return RDI_MNEMONIC;
|
|
}
|
|
else if (!strcmp(str, "r8"))
|
|
{
|
|
return R8_MNEMONIC;
|
|
}
|
|
else if (!strcmp(str, "r9"))
|
|
{
|
|
return R9_MNEMONIC;
|
|
}
|
|
else if (!strcmp(str, "r10"))
|
|
{
|
|
return R10_MNEMONIC;
|
|
}
|
|
else if (!strcmp(str, "r11"))
|
|
{
|
|
return R11_MNEMONIC;
|
|
}
|
|
else if (!strcmp(str, "r12"))
|
|
{
|
|
return R12_MNEMONIC;
|
|
}
|
|
else if (!strcmp(str, "r13"))
|
|
{
|
|
return R13_MNEMONIC;
|
|
}
|
|
else if (!strcmp(str, "r14"))
|
|
{
|
|
return R14_MNEMONIC;
|
|
}
|
|
else if (!strcmp(str, "r15"))
|
|
{
|
|
return R15_MNEMONIC;
|
|
}
|
|
|
|
return INVALID;
|
|
}
|
|
unsigned long long int PseudoRegToInt(char* str)
|
|
{
|
|
if (!strcmp(str, "tid"))
|
|
{
|
|
return TID_MNEMONIC;
|
|
}
|
|
if (!strcmp(str, "pid"))
|
|
{
|
|
return PID_MNEMONIC;
|
|
}
|
|
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_ASL;
|
|
}
|
|
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;
|
|
}
|
|
else if (!strcmp(str, "@PRINT"))
|
|
{
|
|
return (unsigned long long int)FUNC_PRINT;
|
|
}
|
|
return -1;
|
|
}
|