mirror of
https://github.com/HyperDbg/HyperDbg.git
synced 2026-07-12 18:49:32 +00:00
414 lines
13 KiB
C++
414 lines
13 KiB
C++
/**
|
|
* @file casting.cpp
|
|
* @author Sina Karvandi (sina@hyperdbg.org)
|
|
* @brief casting functions queries for script engine
|
|
* @details
|
|
* @version 0.1
|
|
* @date 2022-02-04
|
|
*
|
|
* @copyright This project is released under the GNU Public License v3.
|
|
*
|
|
*/
|
|
#include "pch.h"
|
|
|
|
/*
|
|
Grammar :
|
|
|
|
EXPRSSION-> cast < STRING0 > ( EXPRESSION ) STRING_SEQUENCE
|
|
STRING_SEQUENCE->.STRING[1 - N] STRING_SEQUENCE
|
|
STRING_SEQUENCE->'->' STRING STRING_SEQUENCE
|
|
STRING_SEQUENCE->eps
|
|
|
|
*/
|
|
|
|
typedef struct _UNICODE_STRING
|
|
{
|
|
USHORT Length; // +0x000
|
|
USHORT MaximumLength; // +0x002
|
|
PWSTR Buffer; // +0x004
|
|
} UNICODE_STRING, *PUNICODE_STRING;
|
|
|
|
typedef struct _STUPID_STRUCT1
|
|
{
|
|
UINT32 Flag32; // +0x000
|
|
UINT64 Flag64; // +0x004
|
|
PVOID Context; // +0x00c
|
|
PUNICODE_STRING StringValue; // +0x014
|
|
} STUPID_STRUCT1, *PSTUPID_STRUCT1;
|
|
|
|
typedef struct _STUPID_STRUCT2
|
|
{
|
|
UINT32 Sina32; // +0x000
|
|
UINT64 Sina64; // +0x004
|
|
PVOID AghaaSina; // +0x00c
|
|
PUNICODE_STRING UnicodeStr; // +0x014
|
|
PSTUPID_STRUCT1 StupidStruct1; // +0x01c
|
|
|
|
} STUPID_STRUCT2, *PSTUPID_STRUCT2;
|
|
|
|
/**
|
|
* @brief This function returns the needed details for making support
|
|
* for the casting in the script engine
|
|
*
|
|
* @param StructName Top-level name of struct to perform the look up on this
|
|
* struct
|
|
* @param FiledOfStructName The field name (a field of struct)
|
|
* @param IsStructNamePointerOrNot Shows whether the field specified in
|
|
* FiledOfStructName is a pointer or not
|
|
* @param IsFiledOfStructNamePointerOrNot Shows whether the field specified in
|
|
* FiledOfStructName is a pointer or not
|
|
* @param NewStructOrTypeName Returns the type (structure name) of the
|
|
* FiledOfStructName for future (next '->' or '.' )
|
|
* @param OffsetOfFieldFromTop The start position of this field from the top of
|
|
* structure
|
|
* @param SizeOfField The exact size of the target field
|
|
*
|
|
* @return BOOLEAN if the StructName or the FiledOfStructName not found or there
|
|
* was any error it returns FALSE (in that case script engine should throw an
|
|
* error to the user) otherwise return TRUE which means the script engine can
|
|
* safely use the details
|
|
*/
|
|
BOOLEAN
|
|
SymCastingQueryForFiledsAndTypes(const char * StructName,
|
|
const char * FiledOfStructName,
|
|
PBOOLEAN IsStructNamePointerOrNot,
|
|
PBOOLEAN IsFiledOfStructNamePointerOrNot,
|
|
char ** NewStructOrTypeName,
|
|
UINT32 * OffsetOfFieldFromTop,
|
|
UINT32 * SizeOfField)
|
|
{
|
|
BOOLEAN IsPointer = FALSE;
|
|
BOOLEAN IsTheStructItselfAPointer = FALSE;
|
|
UINT32 TempOffsetOfFieldFromTop = 0;
|
|
UINT32 TempSizeOfField = 0;
|
|
|
|
if (strcmp(StructName, "STUPID_STRUCT1") == 0 ||
|
|
strcmp(StructName, "PSTUPID_STRUCT1") == 0)
|
|
{
|
|
if (strcmp(StructName, "PSTUPID_STRUCT1") == 0)
|
|
{
|
|
IsTheStructItselfAPointer = TRUE;
|
|
}
|
|
|
|
if (strcmp(FiledOfStructName, "Flag32") == 0)
|
|
{
|
|
IsPointer = FALSE;
|
|
TempOffsetOfFieldFromTop = 0x0;
|
|
TempSizeOfField = 0x4;
|
|
strcpy(*NewStructOrTypeName, "UINT32");
|
|
}
|
|
else if (strcmp(FiledOfStructName, "Flag64") == 0)
|
|
{
|
|
IsPointer = FALSE;
|
|
TempOffsetOfFieldFromTop = 0x4;
|
|
TempSizeOfField = 0x8;
|
|
strcpy(*NewStructOrTypeName, "UINT64");
|
|
}
|
|
else if (strcmp(FiledOfStructName, "Context") == 0)
|
|
{
|
|
IsPointer = TRUE;
|
|
TempOffsetOfFieldFromTop = 0xc;
|
|
TempSizeOfField = 0x8;
|
|
strcpy(*NewStructOrTypeName, "PVOID");
|
|
}
|
|
else if (strcmp(FiledOfStructName, "StringValue") == 0)
|
|
{
|
|
IsPointer = TRUE;
|
|
TempOffsetOfFieldFromTop = 0x14;
|
|
TempSizeOfField = 0x8;
|
|
strcpy(*NewStructOrTypeName, "PUNICODE_STRING");
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Unknown Field
|
|
//
|
|
return FALSE;
|
|
}
|
|
}
|
|
else if (strcmp(StructName, "STUPID_STRUCT2") == 0 ||
|
|
strcmp(StructName, "PSTUPID_STRUCT2") == 0)
|
|
{
|
|
if (strcmp(StructName, "PSTUPID_STRUCT2") == 0)
|
|
{
|
|
IsTheStructItselfAPointer = TRUE;
|
|
}
|
|
|
|
if (strcmp(FiledOfStructName, "Sina32") == 0)
|
|
{
|
|
IsPointer = FALSE;
|
|
TempOffsetOfFieldFromTop = 0x0;
|
|
TempSizeOfField = 0x4;
|
|
strcpy(*NewStructOrTypeName, "UINT32");
|
|
}
|
|
else if (strcmp(FiledOfStructName, "Sina64") == 0)
|
|
{
|
|
IsPointer = FALSE;
|
|
TempOffsetOfFieldFromTop = 0x4;
|
|
TempSizeOfField = 0x8;
|
|
strcpy(*NewStructOrTypeName, "UINT64");
|
|
}
|
|
else if (strcmp(FiledOfStructName, "AghaaSina") == 0)
|
|
{
|
|
IsPointer = TRUE;
|
|
TempOffsetOfFieldFromTop = 0xc;
|
|
TempSizeOfField = 0x8;
|
|
strcpy(*NewStructOrTypeName, "PVOID");
|
|
}
|
|
else if (strcmp(FiledOfStructName, "UnicodeStr") == 0)
|
|
{
|
|
IsPointer = TRUE;
|
|
TempOffsetOfFieldFromTop = 0x14;
|
|
TempSizeOfField = 0x8;
|
|
strcpy(*NewStructOrTypeName, "PUNICODE_STRING");
|
|
}
|
|
else if (strcmp(FiledOfStructName, "StupidStruct1") == 0)
|
|
{
|
|
IsPointer = TRUE;
|
|
TempOffsetOfFieldFromTop = 0x1c;
|
|
TempSizeOfField = 0x8;
|
|
strcpy(*NewStructOrTypeName, "PSTUPID_STRUCT1");
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Unknown Field
|
|
//
|
|
return FALSE;
|
|
}
|
|
}
|
|
else if (strcmp(StructName, "UNICODE_STRING") == 0 ||
|
|
strcmp(StructName, "PUNICODE_STRING") == 0)
|
|
{
|
|
if (strcmp(StructName, "PUNICODE_STRING") == 0)
|
|
{
|
|
IsTheStructItselfAPointer = TRUE;
|
|
}
|
|
|
|
if (strcmp(FiledOfStructName, "Length") == 0)
|
|
{
|
|
IsPointer = FALSE;
|
|
TempOffsetOfFieldFromTop = 0x0;
|
|
TempSizeOfField = 0x2;
|
|
strcpy(*NewStructOrTypeName, "USHORT");
|
|
}
|
|
else if (strcmp(FiledOfStructName, "MaximumLength") == 0)
|
|
{
|
|
IsPointer = FALSE;
|
|
TempOffsetOfFieldFromTop = 0x2;
|
|
TempSizeOfField = 0x2;
|
|
strcpy(*NewStructOrTypeName, "USHORT");
|
|
}
|
|
else if (strcmp(FiledOfStructName, "Buffer") == 0)
|
|
{
|
|
IsPointer = TRUE;
|
|
TempOffsetOfFieldFromTop = 0x4;
|
|
TempSizeOfField = 0x8;
|
|
strcpy(*NewStructOrTypeName, "PWSTR");
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Unknown Field
|
|
//
|
|
return FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Unknown Structure
|
|
//
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Apply the needed information
|
|
//
|
|
*OffsetOfFieldFromTop = TempOffsetOfFieldFromTop;
|
|
*SizeOfField = TempSizeOfField;
|
|
*IsFiledOfStructNamePointerOrNot = IsPointer;
|
|
*IsStructNamePointerOrNot = IsTheStructItselfAPointer;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/**
|
|
* @brief This function returns the sizeof of the structure
|
|
*
|
|
* @param StructNameOrTypeName Top-level name of struct
|
|
* @param SizeOfField Result of the sizeof
|
|
*
|
|
* @return BOOLEAN if the StructNameOrTypeName not found or there was any error
|
|
* it returns FALSE (in that case script engine should throw an error to the
|
|
* user) otherwise return TRUE which means the script engine can safely use the
|
|
* details
|
|
*/
|
|
BOOLEAN
|
|
SymQuerySizeof(const char * StructNameOrTypeName, UINT32 * SizeOfField)
|
|
{
|
|
if (strcmp(StructNameOrTypeName, "STUPID_STRUCT1") == 0)
|
|
{
|
|
*SizeOfField = sizeof(STUPID_STRUCT1);
|
|
}
|
|
else if (strcmp(StructNameOrTypeName, "STUPID_STRUCT2") == 0)
|
|
{
|
|
*SizeOfField = sizeof(STUPID_STRUCT2);
|
|
}
|
|
else if (strcmp(StructNameOrTypeName, "UNICODE_STRING") == 0)
|
|
{
|
|
*SizeOfField = sizeof(UNICODE_STRING);
|
|
}
|
|
else if (strcmp(StructNameOrTypeName, "PSTUPID_STRUCT1") == 0)
|
|
{
|
|
*SizeOfField = sizeof(PSTUPID_STRUCT1);
|
|
}
|
|
else if (strcmp(StructNameOrTypeName, "PSTUPID_STRUCT2") == 0)
|
|
{
|
|
*SizeOfField = sizeof(PSTUPID_STRUCT2);
|
|
}
|
|
else if (strcmp(StructNameOrTypeName, "PUNICODE_STRING") == 0)
|
|
{
|
|
*SizeOfField = sizeof(PUNICODE_STRING);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Unknown Structure
|
|
//
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
int
|
|
main()
|
|
{
|
|
UINT32 SizeofResult = 0;
|
|
|
|
//
|
|
// Test sizeof operator
|
|
//
|
|
|
|
if (SymQuerySizeof("PUNICODE_STRING", &SizeofResult))
|
|
{
|
|
printf("result of sizeof(PUNICODE_STRING) is : 0x%x\n", SizeofResult);
|
|
}
|
|
|
|
if (SymQuerySizeof("SOME_UNKNOWN_STRUCT", &SizeofResult))
|
|
{
|
|
printf("result of sizeof(SOME_UNKNOWN_STRUCT) is : 0x%x\n", SizeofResult);
|
|
}
|
|
else
|
|
{
|
|
printf("SOME_UNKNOWN_STRUCT is not found\n");
|
|
}
|
|
|
|
printf("\n\n\n");
|
|
|
|
//
|
|
// ********* Test casting *********
|
|
//
|
|
|
|
/*
|
|
|
|
|
|
Local var @ 0x95fa18df58 Type AllocateStructForCasting::__l2::_STUPID_STRUCT2*
|
|
0x00000260`d065ee30
|
|
|
|
+0x000 Sina32 : 0x32
|
|
+0x008 Sina64 : 0x64
|
|
+0x010 AghaaSina : 0x00000000`00000055 Void
|
|
+0x018 UnicodeStr : 0x00000260`d065ec70 AllocateStructForCasting::__l2::_UNICODE_STRING
|
|
+0x000 Length : 0x40
|
|
+0x002 MaximumLength : 0x40
|
|
+0x008 Buffer : 0x00000260`d065ecf0 "Goodbye I'm at stupid struct 2!"
|
|
+0x020 StupidStruct1 : 0x00000260`d065eda0 AllocateStructForCasting::__l2::_STUPID_STRUCT1
|
|
+0x000 Flag32 : 0x3232
|
|
+0x008 Flag64 : 0x6464
|
|
+0x010 Context : 0x00000000`00000085 Void
|
|
+0x018 StringValue : 0x00000260`d065eb50 AllocateStructForCasting::__l2::_UNICODE_STRING
|
|
+0x000 Length : 0x3c
|
|
+0x002 MaximumLength : 0x3c
|
|
+0x008 Buffer : 0x00000260`d065ebd0 "Hi come from stupid struct 1!"
|
|
|
|
|
|
my_var = cast<PSTUPID_STRUCT2>(@rcx)->Sina32;
|
|
// my_var = 0x32
|
|
|
|
my_var = cast<PSTUPID_STRUCT2>(@rcx)->Sina64;
|
|
// my_var = 0x64
|
|
|
|
my_var = cast<PSTUPID_STRUCT2>(@rcx)->AghaaSina;
|
|
// my_var = 0x55
|
|
|
|
my_var = cast<PSTUPID_STRUCT2>(@rcx).Unknownnnnnn;
|
|
// Error because Unknownnnnnn not found
|
|
|
|
my_var = cast<PSTUPID_STRUCT2>(@rcx)->Unknownnnnnn;
|
|
// Error because Unknownnnnnn not found
|
|
|
|
my_var = cast<PSTUPID_STRUCT2>(@rcx).Sina32;
|
|
// Error because PSTUPID_STRUCT2 is pointer, should use '->'
|
|
|
|
my_var = cast<PSTUPID_STRUCT2>(*@rcx).Sina32;
|
|
// Error because PSTUPID_STRUCT2 is pointer, should use '->'
|
|
|
|
my_var = cast<STUPID_STRUCT2>(*@rcx).Sina32;
|
|
// my_var = 0x32
|
|
|
|
my_var = cast<STUPID_STRUCT2>(*@rcx).Sina64;
|
|
// my_var = 0x64
|
|
|
|
my_var = cast<STUPID_STRUCT2>(*@rcx).AghaaSina;
|
|
// my_var = 0x55
|
|
|
|
my_var = cast<STUPID_STRUCT2>(*@rcx).UnicodeStr->MaximumLength;
|
|
// my_var = 0x40
|
|
|
|
my_var = cast<PSTUPID_STRUCT2>(@rcx)->UnicodeStr->MaximumLength;
|
|
// my_var = 0x40
|
|
|
|
my_var = cast<PSTUPID_STRUCT2>(@rcx)->StupidStruct1->Flag32;
|
|
// my_var = 0x3232
|
|
|
|
my_var = cast<PSTUPID_STRUCT2>(@rcx)->StupidStruct1->Flag64;
|
|
// my_var = 0x6464
|
|
|
|
my_var = cast<STUPID_STRUCT2>(*@rcx).StupidStruct1->StringValue->MaximumLength;
|
|
// my_var = 0x3c
|
|
|
|
printf("Result is : %ws\n", cast<PSTUPID_STRUCT2>(@rcx)->UnicodeStr->Buffer );
|
|
// Result is : Goodbye I'm at stupid struct 2!"
|
|
|
|
printf("Result is : %ws\n", cast<PSTUPID_STRUCT2>(@rcx)->StupidStruct1->StringValue->Buffer );
|
|
// Result is : Goodbye I'm at stupid struct 2!"
|
|
|
|
*/
|
|
|
|
BOOLEAN IsStructPointerOrNot = FALSE;
|
|
BOOLEAN IsFieldPointerOrNot = FALSE;
|
|
UINT32 OffsetOfFieldFromTop = NULL;
|
|
UINT32 SizeOfField = NULL;
|
|
CHAR * NewStructOrTypeName = (CHAR *)malloc(100);
|
|
|
|
if (SymCastingQueryForFiledsAndTypes(
|
|
"STUPID_STRUCT2",
|
|
"UnicodeStr",
|
|
&IsStructPointerOrNot,
|
|
&IsFieldPointerOrNot,
|
|
&NewStructOrTypeName,
|
|
&OffsetOfFieldFromTop,
|
|
&SizeOfField))
|
|
{
|
|
printf("is the structure itself pointer or not: %s\n",
|
|
IsStructPointerOrNot ? "yes" : "no");
|
|
printf("is the field of structure itself pointer or not: %s\n",
|
|
IsFieldPointerOrNot ? "yes" : "no");
|
|
printf("offset of field from top : %x\n", OffsetOfFieldFromTop);
|
|
printf("size of field : %x\n", SizeOfField);
|
|
}
|
|
|
|
free(NewStructOrTypeName);
|
|
}
|