add include file in script engine

This commit is contained in:
xmaple21215 2026-01-06 16:38:22 +08:00
parent c2e2fe5c4b
commit 8bd8950514
16 changed files with 1037 additions and 753 deletions

View file

@ -357,7 +357,7 @@ ScriptEngineEvalWrapper(PGUEST_REGS GuestRegs,
//
// Run Parser
//
PSYMBOL_BUFFER CodeBuffer = (PSYMBOL_BUFFER)ScriptEngineParse((char *)Expr.c_str());
PSYMBOL_BUFFER CodeBuffer = (PSYMBOL_BUFFER)ScriptEngineParse((char*)Expr.c_str());
#ifdef _SCRIPT_ENGINE_IR_PRINT_EN
//

File diff suppressed because it is too large Load diff

View file

@ -535,6 +535,23 @@ GetToken(char * c, char * str)
}
return Token;
case '#':
do
{
if (*c != '`')
AppendByte(Token, *c);
*c = sgetc(str);
} while (IsLetter(*c) || IsHex(*c) || (*c == '_') || (*c == '!'));
if (IsKeyword(Token->Value))
{
Token->Type = KEYWORD;
}
else
{
Token->Type = UNKNOWN;
}
return Token;
case ' ':
case '\t':
strcpy(Token->Value, "");

View file

@ -309,8 +309,9 @@ ScriptEngineConvertFileToPdbFileAndGuidAndAgeDetails(const char * LocalFilePath,
PVOID
ScriptEngineParse(char * str)
{
PSCRIPT_ENGINE_TOKEN_LIST Stack = NewTokenList();
char * ScriptSource = _strdup(str);
PSCRIPT_ENGINE_TOKEN_LIST Stack = NewTokenList();
PSCRIPT_ENGINE_TOKEN_LIST MatchedStack = NewTokenList();
PSYMBOL_BUFFER CodeBuffer = NewSymbolBuffer();
@ -362,13 +363,13 @@ ScriptEngineParse(char * str)
Push(Stack, EndToken);
Push(Stack, StartToken);
c = sgetc(str);
c = sgetc(ScriptSource);
PSCRIPT_ENGINE_TOKEN CurrentIn = Scan(str, &c);
PSCRIPT_ENGINE_TOKEN CurrentIn = Scan(ScriptSource, &c);
if (CurrentIn->Type == UNKNOWN)
{
Error = SCRIPT_ENGINE_ERROR_SYNTAX;
ErrorMessage = HandleError(&Error, str);
ErrorMessage = HandleError(&Error, ScriptSource);
CodeBuffer->Message = ErrorMessage;
RemoveTokenList(Stack);
@ -421,16 +422,16 @@ ScriptEngineParse(char * str)
{
if (!strcmp(TopToken->Value, "BOOLEAN_EXPRESSION"))
{
UINT64 BooleanExpressionSize = BooleanExpressionExtractEnd(str, &WaitForWaitStatementBooleanExpression, CurrentIn);
UINT64 BooleanExpressionSize = BooleanExpressionExtractEnd(ScriptSource, &WaitForWaitStatementBooleanExpression, CurrentIn);
ScriptEngineBooleanExpresssionParse(BooleanExpressionSize, CurrentIn, MatchedStack, CodeBuffer, str, &c, &Error);
ScriptEngineBooleanExpresssionParse(BooleanExpressionSize, CurrentIn, MatchedStack, CodeBuffer, ScriptSource, &c, &Error);
if (Error != SCRIPT_ENGINE_ERROR_FREE)
{
break;
}
RemoveToken(&CurrentIn);
CurrentIn = Scan(str, &c);
CurrentIn = Scan(ScriptSource, &c);
if (CurrentIn->Type == UNKNOWN)
{
Error = SCRIPT_ENGINE_ERROR_UNKNOWN_TOKEN;
@ -438,7 +439,7 @@ ScriptEngineParse(char * str)
}
RemoveToken(&CurrentIn);
CurrentIn = Scan(str, &c);
CurrentIn = Scan(ScriptSource, &c);
if (CurrentIn->Type == UNKNOWN)
{
Error = SCRIPT_ENGINE_ERROR_UNKNOWN_TOKEN;
@ -494,7 +495,7 @@ ScriptEngineParse(char * str)
Push(MatchedStack, CurrentIn);
CurrentIn = Scan(str, &c);
CurrentIn = Scan(ScriptSource, &c);
if (CurrentIn->Type == UNKNOWN)
{
Error = SCRIPT_ENGINE_ERROR_SYNTAX;
@ -508,7 +509,7 @@ ScriptEngineParse(char * str)
{
WaitForWaitStatementBooleanExpression = TRUE;
}
CodeGen(MatchedStack, CodeBuffer, TopToken, &Error);
CodeGen(MatchedStack, CodeBuffer, TopToken, &Error, &ScriptSource);
if (Error != SCRIPT_ENGINE_ERROR_FREE)
{
break;
@ -525,7 +526,7 @@ ScriptEngineParse(char * str)
else
{
RemoveToken(&CurrentIn);
CurrentIn = Scan(str, &c);
CurrentIn = Scan(ScriptSource, &c);
if (CurrentIn->Type == UNKNOWN)
{
@ -543,7 +544,7 @@ ScriptEngineParse(char * str)
if (Error != SCRIPT_ENGINE_ERROR_FREE)
{
ErrorMessage = HandleError(&Error, str);
ErrorMessage = HandleError(&Error, ScriptSource);
}
else
{
@ -635,12 +636,29 @@ ScriptEngineParse(char * str)
UserDefinedFunctionHead = 0;
}
if (IncludeHead)
{
PINCLUDE_NODE Node = IncludeHead;
while (Node)
{
if (Node->FilePath)
free(Node->FilePath);
PINCLUDE_NODE Temp = Node;
Node = Node->NextNode;
free(Temp);
}
IncludeHead = 0;
}
if (CurrentIn)
RemoveToken(&CurrentIn);
if (TopToken)
RemoveToken(&TopToken);
free(ScriptSource);
return (PVOID)CodeBuffer;
}
@ -653,7 +671,7 @@ ScriptEngineParse(char * str)
* @param Error
*/
void
CodeGen(PSCRIPT_ENGINE_TOKEN_LIST MatchedStack, PSYMBOL_BUFFER CodeBuffer, PSCRIPT_ENGINE_TOKEN Operator, PSCRIPT_ENGINE_ERROR_TYPE Error)
CodeGen(PSCRIPT_ENGINE_TOKEN_LIST MatchedStack, PSYMBOL_BUFFER CodeBuffer, PSCRIPT_ENGINE_TOKEN Operator, PSCRIPT_ENGINE_ERROR_TYPE Error, char ** ScriptSource)
{
PSCRIPT_ENGINE_TOKEN Op0 = NULL;
PSCRIPT_ENGINE_TOKEN Op1 = NULL;
@ -692,7 +710,62 @@ CodeGen(PSCRIPT_ENGINE_TOKEN_LIST MatchedStack, PSYMBOL_BUFFER CodeBuffer, PSCRI
while (TRUE)
{
if (!strcmp(Operator->Value, "@START_OF_USER_DEFINED_FUNCTION"))
if (!strcmp(Operator->Value, "@INCLUDE"))
{
char * IncludeFilePath;
char FullPath[MAX_PATH_LEN];
char * IncludeFileBuffer;
BOOLEAN IncludedPath = FALSE;
Temp = Pop(MatchedStack);
IncludeFilePath = Temp->Value;
ResolveIncludePath(IncludeFilePath, FullPath);
if (!FileExists(FullPath))
{
*Error = SCRIPT_ENGINE_ERROR_SYNTAX;
break;
}
if (!ParseIncludeFile(FullPath, &IncludeFileBuffer))
{
*Error = SCRIPT_ENGINE_ERROR_SYNTAX;
break;
}
if (!IncludeHead)
{
IncludeHead = calloc(sizeof(INCLUDE_NODE), 1);
IncludeHead->FilePath = _strdup(FullPath);
}
else
{
PINCLUDE_NODE Node, PrevNode = NULL;
for (Node = IncludeHead; Node; PrevNode = Node, Node = Node->NextNode)
{
if (!strcmp(Node->FilePath, FullPath))
{
IncludedPath = TRUE;
break;
}
}
if (!IncludedPath && PrevNode)
{
PrevNode->NextNode = calloc(sizeof(INCLUDE_NODE), 1);
PrevNode->NextNode->FilePath = _strdup(FullPath);
}
}
if (!IncludedPath)
{
*ScriptSource = InsertStrNew(*ScriptSource, InputIdx, IncludeFileBuffer);
}
}
else if (!strcmp(Operator->Value, "@START_OF_USER_DEFINED_FUNCTION"))
{
Op0 = Pop(MatchedStack);
VariableType = HandleType(MatchedStack);
@ -3514,7 +3587,7 @@ ScriptEngineBooleanExpresssionParse(
}
else
{
CodeGen(MatchedStack, CodeBuffer, SemanticRule, Error);
CodeGen(MatchedStack, CodeBuffer, SemanticRule, Error, &str);
if (*Error != SCRIPT_ENGINE_ERROR_FREE)
{
break;

View file

@ -273,18 +273,27 @@ IsOneOperandOperator(PSCRIPT_ENGINE_TOKEN Operator);
/**
*
*/
typedef struct USER_DEFINED_FUNCTION_NODE
typedef struct _USER_DEFINED_FUNCTION_NODE
{
char * Name;
long long unsigned Address;
long long unsigned VariableType;
long long unsigned ParameterNumber;
long long unsigned MaxTempNumber;
long long unsigned LocalVariableNumber;
long long unsigned IdTable;
long long unsigned FunctionParameterIdTable;
char * TempMap;
struct USER_DEFINED_FUNCTION_NODE * NextNode;
char * Name;
long long unsigned Address;
long long unsigned VariableType;
long long unsigned ParameterNumber;
long long unsigned MaxTempNumber;
long long unsigned LocalVariableNumber;
long long unsigned IdTable;
long long unsigned FunctionParameterIdTable;
char * TempMap;
struct _USER_DEFINED_FUNCTION_NODE * NextNode;
} USER_DEFINED_FUNCTION_NODE, *PUSER_DEFINED_FUNCTION_NODE;
/**
*
*/
typedef struct _INCLUDE_NODE
{
char * FilePath;
struct _INCLUDE_NODE * NextNode;
} INCLUDE_NODE, *PINCLUDE_NODE;
#endif // !COMMON_H

View file

@ -1,8 +1,8 @@
#pragma once
#ifndef PARSE_TABLE_H
#define PARSE_TABLE_H
#define RULES_COUNT 271
#define TERMINAL_COUNT 121
#define RULES_COUNT 272
#define TERMINAL_COUNT 122
#define NONETERMINAL_COUNT 63
#define START_VARIABLE "S"
#define MAX_RHS_LEN 15

View file

@ -39,6 +39,7 @@
#include "SDK/imports/user/HyperDbgSymImports.h"
#include "SDK/headers/HardwareDebugger.h"
#include "type.h"
#include "script_include.h"
#include "common.h"
#include "scanner.h"
#include "globals.h"

View file

@ -26,6 +26,8 @@ PUSER_DEFINED_FUNCTION_NODE UserDefinedFunctionHead;
PUSER_DEFINED_FUNCTION_NODE CurrentUserDefinedFunction;
PINCLUDE_NODE IncludeHead;
/**
* @brief number of read characters from input
*/

View file

@ -76,7 +76,9 @@ CodeGen(
PSCRIPT_ENGINE_TOKEN_LIST MatchedStack,
PSYMBOL_BUFFER CodeBuffer,
PSCRIPT_ENGINE_TOKEN Operator,
PSCRIPT_ENGINE_ERROR_TYPE Error);
PSCRIPT_ENGINE_ERROR_TYPE Error,
char** ScriptSource
);
unsigned long long int
RegisterToInt(char * str);

View file

@ -67,6 +67,8 @@ STATEMENT->CALL_FUNC_STATEMENT ;
STATEMENT->break @BREAK ;
STATEMENT->continue @CONTINUE ;
STATEMENT->VARIABLE_TYPE3
STATEMENT->#include STRING @INCLUDE ;
S2->STATEMENT2 S2
S2->{ STATEMENT2 S2 }

View file

@ -75,8 +75,7 @@
<TreatLinkerWarningAsErrors>true</TreatLinkerWarningAsErrors>
</Link>
<PostBuildEvent>
<Command>
</Command>
<Command>robocopy "$(ProjectDir)script" "$(TargetDir)script" /E</Command>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='release|x64'">
@ -105,8 +104,7 @@
<TreatLinkerWarningAsErrors>true</TreatLinkerWarningAsErrors>
</Link>
<PostBuildEvent>
<Command>
</Command>
<Command>robocopy "$(ProjectDir)script" "$(TargetDir)script" /E</Command>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemGroup>
@ -119,6 +117,7 @@
<ClInclude Include="header\scanner.h" />
<ClInclude Include="header\script-engine.h" />
<ClInclude Include="header\type.h" />
<ClInclude Include="script_include.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="code\common.c" />
@ -132,6 +131,7 @@
<ClCompile Include="code\scanner.c" />
<ClCompile Include="code\script-engine.c" />
<ClCompile Include="code\type.c" />
<ClCompile Include="script_include.c" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">

View file

@ -41,6 +41,9 @@
<ClInclude Include="header\pch.h">
<Filter>header</Filter>
</ClInclude>
<ClInclude Include="script_include.h">
<Filter>header</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="code\common.c">
@ -67,5 +70,8 @@
<ClCompile Include="code\pch.c">
<Filter>code</Filter>
</ClCompile>
<ClCompile Include="script_include.c">
<Filter>code</Filter>
</ClCompile>
</ItemGroup>
</Project>

View file

@ -0,0 +1,12 @@
? {
int myfibonacci(int var1) {
if (var1 == 0) {
return 0;
}
if (var1 == 1) {
return 1;
}
return myfibonacci(var1 - 1) + myfibonacci(var1 - 2);
}
}

View file

@ -0,0 +1,8 @@
? {
void my_func(int var, int var2) {
printf("var = %d, var2 = %d\n", var, var2);
return;
printf("this statement is never shown!\n");
}
}

View file

@ -0,0 +1,135 @@
#include "pch.h"
#include "script_include.h"
static void
Ltrim(char * s)
{
char * p = s;
while (*p && isspace((unsigned char)*p))
p++;
if (p != s)
memmove(s, p, strlen(p) + 1);
}
static void
Rtrim(char * s)
{
char * end = s + strlen(s);
while (end > s && isspace((unsigned char)end[-1]))
end--;
*end = '\0';
}
static void
Trim(char * s)
{
Ltrim(s);
Rtrim(s);
}
char *
InsertStrNew(char * str, int InputIdx, const char * buf)
{
size_t len_str = strlen(str);
size_t len_buf = strlen(buf);
if (InputIdx < 0 || InputIdx > len_str)
return str;
char * newstr = realloc(str, len_str + len_buf + 1);
if (!newstr)
return str;
memmove(newstr + InputIdx + len_buf,
newstr + InputIdx,
len_str - InputIdx + 1);
memcpy(newstr + InputIdx, buf, len_buf);
return newstr;
}
BOOLEAN
IsAbsolutePath(const char * path)
{
if (!path || !path[0])
return FALSE;
if (strlen(path) >= 3 &&
((path[1] == ':' && (path[2] == '\\' || path[2] == '/'))))
return TRUE;
return FALSE;
}
void
ResolveIncludePath(const char * IncludeFilePath, char * OutPath)
{
if (IsAbsolutePath(IncludeFilePath))
{
strncpy(OutPath, IncludeFilePath, MAX_PATH_LEN - 1);
OutPath[MAX_PATH_LEN - 1] = '\0';
return;
}
char ExeDir[MAX_PATH_LEN];
GetModuleFileNameA(NULL, ExeDir, MAX_PATH_LEN);
char * p = strrchr(ExeDir, '\\');
if (p)
*p = '\0';
snprintf(
OutPath,
MAX_PATH_LEN,
"%s\\%s",
ExeDir,
IncludeFilePath);
}
BOOLEAN
FileExists(const char * path)
{
DWORD attr = GetFileAttributesA(path);
if (attr == INVALID_FILE_ATTRIBUTES)
return FALSE;
if (attr & FILE_ATTRIBUTE_DIRECTORY)
return FALSE;
return TRUE;
}
BOOLEAN
ParseIncludeFile(char * IncludeFile, char ** Buffer)
{
FILE * fp = fopen(IncludeFile, "r");
fseek(fp, 0, SEEK_END);
long size = ftell(fp);
rewind(fp);
*Buffer = calloc(size + 1, 1);
fread(*Buffer, 1, size, fp);
(*Buffer)[size] = '\0';
Trim(*Buffer);
size_t len = strlen(*Buffer);
if ((*Buffer)[0] == '?' &&
(*Buffer)[1] == ' ' &&
(*Buffer)[2] == '{' &&
(*Buffer)[len - 1] == '}')
{
memmove(
*Buffer,
*Buffer + 3,
len - 3 + 1);
(*Buffer)[strlen(*Buffer) - 1] = '\0';
return TRUE;
}
return FALSE;
}

View file

@ -0,0 +1,13 @@
#define MAX_PATH_LEN 1024
void
ResolveIncludePath(const char * IncludeFilePath, char * OutPath);
BOOLEAN
FileExists(const char * path);
BOOLEAN
ParseIncludeFile(char * IncludeFile, char ** Buffer);
char*
InsertStrNew(char* str, int InputIdx, const char* buf);