HyperDbg Debugger
Loading...
Searching...
No Matches
disassembler.cpp File Reference

Demonstrates basic hooking functionality of the ZydisFormatter class by implementing a custom symbol-resolver. More...

#include "pch.h"
#include "Zycore/Format.h"
#include "Zycore/LibC.h"
#include "Zydis/Zydis.h"

Classes

struct  ZydisSymbol_
 Defines the ZydisSymbol struct. More...
 

Macros

#define PaddingLength   12
 

Typedefs

typedef struct ZydisSymbol_ ZydisSymbol
 Defines the ZydisSymbol struct.
 

Functions

VOID DisassembleBuffer (ZydisDecoder *decoder, ZyanU64 runtime_address, ZyanU8 *data, ZyanUSize length, uint32_t maximum_instr, BOOLEAN is_x86_64, BOOLEAN show_of_branch_is_taken, PRFLAGS rflags)
 Disassemble a user-mode buffer.
 
int ZydisTest ()
 Zydis test.
 
int HyperDbgDisassembler64 (unsigned char *BufferToDisassemble, UINT64 BaseAddress, UINT64 Size, UINT32 MaximumInstrDecoded, BOOLEAN ShowBranchIsTakenOrNot, PRFLAGS Rflags)
 Disassemble x64 assemblies.
 
int HyperDbgDisassembler32 (unsigned char *BufferToDisassemble, UINT64 BaseAddress, UINT64 Size, UINT32 MaximumInstrDecoded, BOOLEAN ShowBranchIsTakenOrNot, PRFLAGS Rflags)
 Disassemble 32 bit assemblies.
 
DEBUGGER_CONDITIONAL_JUMP_STATUS HyperDbgIsConditionalJumpTaken (unsigned char *BufferToDisassemble, UINT64 BuffLength, RFLAGS Rflags, BOOLEAN Isx86_64)
 Check whether the jump is taken or not taken (in debugger)
 
BOOLEAN HyperDbgCheckWhetherTheCurrentInstructionIsCall (unsigned char *BufferToDisassemble, UINT64 BuffLength, BOOLEAN Isx86_64, PUINT32 CallLength)
 Check whether the current instruction is a 'call' or not.
 
UINT32 HyperDbgLengthDisassemblerEngine (unsigned char *BufferToDisassemble, UINT64 BuffLength, BOOLEAN Isx86_64)
 Length Disassembler engine based on Zydis.
 
BOOLEAN HyperDbgCheckWhetherTheCurrentInstructionIsCallOrRet (unsigned char *BufferToDisassemble, UINT64 CurrentRip, UINT32 BuffLength, BOOLEAN Isx86_64, PBOOLEAN IsRet)
 Check whether the current instruction is a 'call' or 'ret' or not.
 
BOOLEAN HyperDbgCheckWhetherTheCurrentInstructionIsRet (unsigned char *BufferToDisassemble, UINT64 BuffLength, BOOLEAN Isx86_64)
 Check whether the current instruction is a 'ret' or not.
 

Variables

UINT32 g_DisassemblerSyntax
 Shows the syntax used in !u !u2 u u2 commands.
 
std::map< UINT64, LOCAL_FUNCTION_DESCRIPTIONg_DisassemblerSymbolMap
 Symbol table for disassembler.
 
BOOLEAN g_AddressConversion
 Whether converting addresses to object names or not.
 
ZydisFormatterFunc default_print_address_absolute
 

Detailed Description

Demonstrates basic hooking functionality of the ZydisFormatter class by implementing a custom symbol-resolver.

Macro Definition Documentation

◆ PaddingLength

#define PaddingLength   12

Typedef Documentation

◆ ZydisSymbol

typedef struct ZydisSymbol_ ZydisSymbol

Defines the ZydisSymbol struct.

Function Documentation

◆ DisassembleBuffer()

VOID DisassembleBuffer ( ZydisDecoder * decoder,
ZyanU64 runtime_address,
ZyanU8 * data,
ZyanUSize length,
uint32_t maximum_instr,
BOOLEAN is_x86_64,
BOOLEAN show_of_branch_is_taken,
PRFLAGS rflags )

Disassemble a user-mode buffer.

Parameters
decoder
runtime_address
data
length
maximum_instr
is_x86_64
show_of_branch_is_taken
rflagsjust used in the case show_of_branch_is_taken is true
127{
128 ZydisFormatter formatter;
129 int instr_decoded = 0;
130 UINT64 UsedBaseAddress = NULL;
131
132 if (g_DisassemblerSyntax == 1)
133 {
134 ZydisFormatterInit(&formatter, ZYDIS_FORMATTER_STYLE_INTEL);
135 }
136 else if (g_DisassemblerSyntax == 2)
137 {
138 ZydisFormatterInit(&formatter, ZYDIS_FORMATTER_STYLE_ATT);
139 }
140 else if (g_DisassemblerSyntax == 3)
141 {
142 ZydisFormatterInit(&formatter, ZYDIS_FORMATTER_STYLE_INTEL_MASM);
143 }
144 else
145 {
146 ShowMessages("err, in selecting disassembler syntax\n");
147 return;
148 }
149
150 ZydisFormatterSetProperty(&formatter, ZYDIS_FORMATTER_PROP_FORCE_SEGMENT, ZYAN_TRUE);
151 ZydisFormatterSetProperty(&formatter, ZYDIS_FORMATTER_PROP_FORCE_SIZE, ZYAN_TRUE);
152
153 //
154 // Replace the `ZYDIS_FORMATTER_FUNC_PRINT_ADDRESS_ABS` function that formats
155 // the absolute addresses
156 //
158 (ZydisFormatterFunc)&ZydisFormatterPrintAddressAbsolute;
159 ZydisFormatterSetHook(&formatter, ZYDIS_FORMATTER_FUNC_PRINT_ADDRESS_ABS, (const void **)&default_print_address_absolute);
160
161 ZydisDecodedOperand operands[ZYDIS_MAX_OPERAND_COUNT];
162 ZydisDecodedInstruction instruction;
163 char buffer[256];
164
165 while (ZYAN_SUCCESS(ZydisDecoderDecodeFull(decoder, data, length, &instruction, operands)))
166 {
167 //
168 // Apply addressconversion of settings here
169 //
171 {
172 //
173 // Showing function names here
174 //
175 if (SymbolShowFunctionNameBasedOnAddress(runtime_address, &UsedBaseAddress))
176 {
177 //
178 // The symbol address is showed
179 //
180 ShowMessages(":\n");
181 }
182 }
183
184 // ZYAN_PRINTF("%016" PRIX64 " ", runtime_address);
185 ShowMessages("%s ", SeparateTo64BitValue(runtime_address).c_str());
186 //
187 // We have to pass a `runtime_address` different to
188 // `ZYDIS_RUNTIME_ADDRESS_NONE` to enable printing of absolute addresses
189 //
190 ZydisFormatterFormatInstruction(&formatter, &instruction, operands, instruction.operand_count_visible, &buffer[0], sizeof(buffer), runtime_address, ZYAN_NULL);
191
192 //
193 // Show the memory for this instruction
194 //
195 for (size_t i = 0; i < instruction.length; i++)
196 {
197 ZyanU8 MemoryContent = data[i];
198 ShowMessages(" %02X", MemoryContent);
199 }
200 //
201 // Add padding (we assume that each instruction should be at least 10 bytes)
202 //
203#define PaddingLength 12
204 if (instruction.length < PaddingLength)
205 {
206 for (size_t i = 0; i < PaddingLength - instruction.length; i++)
207 {
208 ShowMessages(" ");
209 }
210 }
211
212 //
213 // Check whether we should show the result of conditional branches or not
214 //
215 if (show_of_branch_is_taken)
216 {
217 //
218 // Get the result of conditional jump, we re-format the instruction
219 // here because the user might have changed the configuration of Zydis
220 // using the "settings" command so it's better to re-format with default
221 // configuration
222 //
223 RFLAGS TempRflags = {0};
224 TempRflags.AsUInt = rflags->AsUInt;
225 DEBUGGER_CONDITIONAL_JUMP_STATUS ResultOfCondJmp =
226 HyperDbgIsConditionalJumpTaken(data, length, TempRflags, is_x86_64);
227
229 {
230 ShowMessages(" %s [taken]\n", &buffer[0]);
231 }
232 else if (ResultOfCondJmp ==
234 {
235 ShowMessages(" %s [not taken]\n", &buffer[0]);
236 }
237 else
238 {
239 //
240 // It's either not a conditional jump or an error occurred
241 //
242 ShowMessages(" %s\n", &buffer[0]);
243 }
244 }
245 else
246 {
247 //
248 // Show regular instruction
249 //
250 ShowMessages(" %s\n", &buffer[0]);
251 }
252
253 data += instruction.length;
254 length -= instruction.length;
255 runtime_address += instruction.length;
256 instr_decoded++;
257
258 if (instr_decoded == maximum_instr)
259 {
260 return;
261 }
262 }
263}
unsigned __int64 UINT64
Definition BasicTypes.h:21
enum _DEBUGGER_CONDITIONAL_JUMP_STATUS DEBUGGER_CONDITIONAL_JUMP_STATUS
Whether a jump is taken or not taken.
@ DEBUGGER_CONDITIONAL_JUMP_STATUS_JUMP_IS_NOT_TAKEN
Definition RequestStructures.h:1110
@ DEBUGGER_CONDITIONAL_JUMP_STATUS_JUMP_IS_TAKEN
Definition RequestStructures.h:1109
string SeparateTo64BitValue(UINT64 Value)
add ` between 64 bit values and convert them to string
Definition common.cpp:27
DEBUGGER_CONDITIONAL_JUMP_STATUS HyperDbgIsConditionalJumpTaken(unsigned char *BufferToDisassemble, UINT64 BuffLength, RFLAGS Rflags, BOOLEAN Isx86_64)
Check whether the jump is taken or not taken (in debugger)
Definition disassembler.cpp:410
BOOLEAN g_AddressConversion
Whether converting addresses to object names or not.
Definition globals.h:584
ZydisFormatterFunc default_print_address_absolute
Definition disassembler.cpp:61
#define PaddingLength
UINT32 g_DisassemblerSyntax
Shows the syntax used in !u !u2 u u2 commands.
Definition globals.h:598
VOID ShowMessages(const char *Fmt,...)
Show messages.
Definition libhyperdbg.cpp:96
NULL()
Definition test-case-generator.py:530
BOOLEAN SymbolShowFunctionNameBasedOnAddress(UINT64 Address, PUINT64 UsedBaseAddress)
shows the functions' name for the disassembler
Definition symbol.cpp:162

◆ HyperDbgCheckWhetherTheCurrentInstructionIsCall()

BOOLEAN HyperDbgCheckWhetherTheCurrentInstructionIsCall ( unsigned char * BufferToDisassemble,
UINT64 BuffLength,
BOOLEAN Isx86_64,
PUINT32 CallLength )

Check whether the current instruction is a 'call' or not.

Parameters
BufferToDisassembleCurrent Bytes of assembly
BuffLengthLength of buffer
Isx86_64Whether it's an x86 or x64
CallLengthLength of call (if return value is TRUE)
Returns
BOOLEAN
760{
761 ZydisDecoder decoder;
762 ZydisFormatter formatter;
763 ZydisDecodedOperand operands[ZYDIS_MAX_OPERAND_COUNT];
764 UINT64 CurrentRip = 0;
765 int instr_decoded = 0;
766 ZydisDecodedInstruction instruction;
767 char buffer[256];
768 UINT32 MaximumInstrDecoded = 1;
769
770 //
771 // Default length
772 //
773 *CallLength = 0;
774
775 if (ZydisGetVersion() != ZYDIS_VERSION)
776 {
777 ShowMessages("invalid zydis version\n");
779 }
780
781 if (Isx86_64)
782 {
783 ZydisDecoderInit(&decoder, ZYDIS_MACHINE_MODE_LONG_64, ZYDIS_STACK_WIDTH_64);
784 }
785 else
786 {
787 ZydisDecoderInit(&decoder, ZYDIS_MACHINE_MODE_LONG_COMPAT_32, ZYDIS_STACK_WIDTH_32);
788 }
789
790 ZydisFormatterInit(&formatter, ZYDIS_FORMATTER_STYLE_INTEL);
791
792 ZydisFormatterSetProperty(&formatter, ZYDIS_FORMATTER_PROP_FORCE_SEGMENT, ZYAN_TRUE);
793 ZydisFormatterSetProperty(&formatter, ZYDIS_FORMATTER_PROP_FORCE_SIZE, ZYAN_TRUE);
794
795 //
796 // Replace the `ZYDIS_FORMATTER_FUNC_PRINT_ADDRESS_ABS` function that
797 // formats the absolute addresses
798 //
800 (ZydisFormatterFunc)&ZydisFormatterPrintAddressAbsolute;
801 ZydisFormatterSetHook(&formatter, ZYDIS_FORMATTER_FUNC_PRINT_ADDRESS_ABS, (const void **)&default_print_address_absolute);
802
803 while (ZYAN_SUCCESS(ZydisDecoderDecodeFull(&decoder, BufferToDisassemble, BuffLength, &instruction, operands)))
804 {
805 //
806 // We have to pass a `runtime_address` different to
807 // `ZYDIS_RUNTIME_ADDRESS_NONE` to enable printing of absolute addresses
808 //
809
810 ZydisFormatterFormatInstruction(&formatter, &instruction, operands, instruction.operand_count_visible, &buffer[0], sizeof(buffer), (ZyanU64)CurrentRip, ZYAN_NULL);
811
812 if (instruction.mnemonic == ZydisMnemonic::ZYDIS_MNEMONIC_CALL)
813 {
814 //
815 // It's a call
816 //
817
818 //
819 // Log call
820 //
821 // ShowMessages("call length : 0x%x\n", instruction.length);
822
823 //
824 // Set the length
825 //
826 *CallLength = instruction.length;
827
828 return TRUE;
829 }
830 else
831 {
832 //
833 // It's not call
834 //
835 return FALSE;
836 }
837 }
838
839 //
840 // Should not reach here
841 //
842 return FALSE;
843}
#define TRUE
Definition BasicTypes.h:55
#define FALSE
Definition BasicTypes.h:54
unsigned int UINT32
Definition BasicTypes.h:48
@ DEBUGGER_CONDITIONAL_JUMP_STATUS_ERROR
Definition RequestStructures.h:1107

◆ HyperDbgCheckWhetherTheCurrentInstructionIsCallOrRet()

BOOLEAN HyperDbgCheckWhetherTheCurrentInstructionIsCallOrRet ( unsigned char * BufferToDisassemble,
UINT64 CurrentRip,
UINT32 BuffLength,
BOOLEAN Isx86_64,
PBOOLEAN IsRet )

Check whether the current instruction is a 'call' or 'ret' or not.

Parameters
BufferToDisassembleCurrent Bytes of assembly
CurrentRipAddress of current RIP
BuffLengthLength of buffer
Isx86_64Whether it's an x86 or x64
IsRetWhether it's a 'ret' or not
Returns
BOOLEAN
989{
990 ZydisDecoder decoder;
991 ZydisFormatter formatter;
992 ZydisDecodedOperand operands[ZYDIS_MAX_OPERAND_COUNT];
993 int instr_decoded = 0;
994 ZydisDecodedInstruction instruction;
995 char buffer[256];
996 UINT32 MaximumInstrDecoded = 1;
997
998 if (ZydisGetVersion() != ZYDIS_VERSION)
999 {
1000 ShowMessages("invalid zydis version\n");
1002 }
1003
1004 if (!Isx86_64)
1005 {
1006 ZydisDecoderInit(&decoder, ZYDIS_MACHINE_MODE_LONG_64, ZYDIS_STACK_WIDTH_64);
1007 }
1008 else
1009 {
1010 ZydisDecoderInit(&decoder, ZYDIS_MACHINE_MODE_LONG_COMPAT_32, ZYDIS_STACK_WIDTH_32);
1011 }
1012
1013 ZydisFormatterInit(&formatter, ZYDIS_FORMATTER_STYLE_INTEL);
1014
1015 ZydisFormatterSetProperty(&formatter, ZYDIS_FORMATTER_PROP_FORCE_SEGMENT, ZYAN_TRUE);
1016 ZydisFormatterSetProperty(&formatter, ZYDIS_FORMATTER_PROP_FORCE_SIZE, ZYAN_TRUE);
1017
1018 //
1019 // Replace the `ZYDIS_FORMATTER_FUNC_PRINT_ADDRESS_ABS` function that
1020 // formats the absolute addresses
1021 //
1023 (ZydisFormatterFunc)&ZydisFormatterPrintAddressAbsoluteForTrackingInstructions;
1024 ZydisFormatterSetHook(&formatter, ZYDIS_FORMATTER_FUNC_PRINT_ADDRESS_ABS, (const void **)&default_print_address_absolute);
1025
1026 while (ZYAN_SUCCESS(ZydisDecoderDecodeFull(&decoder, BufferToDisassemble, BuffLength, &instruction, operands)))
1027 {
1028 if (instruction.mnemonic == ZydisMnemonic::ZYDIS_MNEMONIC_CALL)
1029 {
1030 //
1031 // It's a 'call' instruction
1032 //
1033
1034 //
1035 // Log call
1036 //
1037 // ShowMessages("call length : 0x%x\n", instruction.length);
1038
1039 //
1040 // We have to pass a `runtime_address` different to
1041 // `ZYDIS_RUNTIME_ADDRESS_NONE` to enable printing of absolute addresses
1042 //
1043
1044 ZydisFormatterFormatInstruction(&formatter, &instruction, operands, instruction.operand_count_visible, &buffer[0], sizeof(buffer), (ZyanU64)CurrentRip, ZYAN_NULL);
1045
1046 *IsRet = FALSE;
1047
1048 return TRUE;
1049 }
1050 else if (instruction.mnemonic == ZydisMnemonic::ZYDIS_MNEMONIC_RET)
1051 {
1052 //
1053 // It's a 'ret' instruction
1054 //
1055
1056 //
1057 // Log ret
1058 //
1059 // ShowMessages("ret length : 0x%x\n", instruction.length);
1060
1061 //
1062 // Call the tracker callback
1063 //
1065
1066 *IsRet = TRUE;
1067
1068 return TRUE;
1069 }
1070 else
1071 {
1072 //
1073 // It's not call
1074 //
1075 return FALSE;
1076 }
1077 }
1078
1079 //
1080 // Should not reach here
1081 //
1082 return FALSE;
1083}
VOID CommandTrackHandleReceivedRetInstructions(UINT64 CurrentRip)
Handle received 'ret'.
Definition track.cpp:281

◆ HyperDbgCheckWhetherTheCurrentInstructionIsRet()

BOOLEAN HyperDbgCheckWhetherTheCurrentInstructionIsRet ( unsigned char * BufferToDisassemble,
UINT64 BuffLength,
BOOLEAN Isx86_64 )

Check whether the current instruction is a 'ret' or not.

Parameters
BufferToDisassembleCurrent Bytes of assembly
BuffLengthLength of buffer
Isx86_64Whether it's an x86 or x64
RetLengthLength of ret (if return value is TRUE)
Returns
BOOLEAN
1100{
1101 ZydisDecoder decoder;
1102 ZydisFormatter formatter;
1103 ZydisDecodedOperand operands[ZYDIS_MAX_OPERAND_COUNT];
1104 UINT64 CurrentRip = 0;
1105 int instr_decoded = 0;
1106 ZydisDecodedInstruction instruction;
1107 char buffer[256];
1108 UINT32 MaximumInstrDecoded = 1;
1109
1110 if (ZydisGetVersion() != ZYDIS_VERSION)
1111 {
1112 ShowMessages("invalid zydis version\n");
1114 }
1115
1116 if (Isx86_64)
1117 {
1118 ZydisDecoderInit(&decoder, ZYDIS_MACHINE_MODE_LONG_64, ZYDIS_STACK_WIDTH_64);
1119 }
1120 else
1121 {
1122 ZydisDecoderInit(&decoder, ZYDIS_MACHINE_MODE_LONG_COMPAT_32, ZYDIS_STACK_WIDTH_32);
1123 }
1124
1125 ZydisFormatterInit(&formatter, ZYDIS_FORMATTER_STYLE_INTEL);
1126
1127 ZydisFormatterSetProperty(&formatter, ZYDIS_FORMATTER_PROP_FORCE_SEGMENT, ZYAN_TRUE);
1128 ZydisFormatterSetProperty(&formatter, ZYDIS_FORMATTER_PROP_FORCE_SIZE, ZYAN_TRUE);
1129
1130 //
1131 // Replace the `ZYDIS_FORMATTER_FUNC_PRINT_ADDRESS_ABS` function that
1132 // formats the absolute addresses
1133 //
1135 (ZydisFormatterFunc)&ZydisFormatterPrintAddressAbsolute;
1136 ZydisFormatterSetHook(&formatter, ZYDIS_FORMATTER_FUNC_PRINT_ADDRESS_ABS, (const void **)&default_print_address_absolute);
1137
1138 while (ZYAN_SUCCESS(ZydisDecoderDecodeFull(&decoder, BufferToDisassemble, BuffLength, &instruction, operands)))
1139 {
1140 //
1141 // We have to pass a `runtime_address` different to
1142 // `ZYDIS_RUNTIME_ADDRESS_NONE` to enable printing of absolute addresses
1143 //
1144
1145 ZydisFormatterFormatInstruction(&formatter, &instruction, operands, instruction.operand_count_visible, &buffer[0], sizeof(buffer), (ZyanU64)CurrentRip, ZYAN_NULL);
1146
1147 if (instruction.mnemonic == ZydisMnemonic::ZYDIS_MNEMONIC_RET)
1148 {
1149 //
1150 // It's a ret
1151 //
1152
1153 //
1154 // Log ret
1155 //
1156 // ShowMessages("ret length : 0x%x\n", instruction.length);
1157
1158 return TRUE;
1159 }
1160 else
1161 {
1162 //
1163 // It's not ret
1164 //
1165 return FALSE;
1166 }
1167 }
1168
1169 //
1170 // Should not reach here
1171 //
1172 return FALSE;
1173}

◆ HyperDbgDisassembler32()

int HyperDbgDisassembler32 ( unsigned char * BufferToDisassemble,
UINT64 BaseAddress,
UINT64 Size,
UINT32 MaximumInstrDecoded,
BOOLEAN ShowBranchIsTakenOrNot,
PRFLAGS Rflags )

Disassemble 32 bit assemblies.

Parameters
BufferToDisassemblebuffer to disassemble
BaseAddressthe base address of assembly
Sizesize of buffer
MaximumInstrDecodedmaximum instructions to decode, 0 means all possible
ShowBranchIsTakenOrNoton conditional jumps shows whether jumps is taken or not
Rflagsin the case ShowBranchIsTakenOrNot is true, we use this variable to show the result of jump
Returns
int
379{
380 if (ZydisGetVersion() != ZYDIS_VERSION)
381 {
382 fputs("Invalid Zydis version\n", ZYAN_STDERR);
383 return EXIT_FAILURE;
384 }
385
386 ZydisDecoder decoder;
387 ZydisDecoderInit(&decoder, ZYDIS_MACHINE_MODE_LONG_COMPAT_32, ZYDIS_STACK_WIDTH_32);
388
389 //
390 // Disassembling buffer
391 //
392 DisassembleBuffer(&decoder, (UINT32)BaseAddress, &BufferToDisassemble[0], Size, MaximumInstrDecoded, FALSE, ShowBranchIsTakenOrNot, Rflags);
393
394 return 0;
395}
VOID DisassembleBuffer(ZydisDecoder *decoder, ZyanU64 runtime_address, ZyanU8 *data, ZyanUSize length, uint32_t maximum_instr, BOOLEAN is_x86_64, BOOLEAN show_of_branch_is_taken, PRFLAGS rflags)
Disassemble a user-mode buffer.
Definition disassembler.cpp:119

◆ HyperDbgDisassembler64()

int HyperDbgDisassembler64 ( unsigned char * BufferToDisassemble,
UINT64 BaseAddress,
UINT64 Size,
UINT32 MaximumInstrDecoded,
BOOLEAN ShowBranchIsTakenOrNot,
PRFLAGS Rflags )

Disassemble x64 assemblies.

Parameters
BufferToDisassemblebuffer to disassemble
BaseAddressthe base address of assembly
Sizesize of buffer
MaximumInstrDecodedmaximum instructions to decode, 0 means all possible
ShowBranchIsTakenOrNoton conditional jumps shows whether jumps is taken or not
Rflagsin the case ShowBranchIsTakenOrNot is true, we use this variable to show the result of jump
Returns
int
339{
340 if (ZydisGetVersion() != ZYDIS_VERSION)
341 {
342 fputs("Invalid Zydis version\n", ZYAN_STDERR);
343 return EXIT_FAILURE;
344 }
345
346 ZydisDecoder decoder;
347 ZydisDecoderInit(&decoder, ZYDIS_MACHINE_MODE_LONG_64, ZYDIS_STACK_WIDTH_64);
348
349 //
350 // Disassembling buffer
351 //
352 DisassembleBuffer(&decoder, BaseAddress, &BufferToDisassemble[0], Size, MaximumInstrDecoded, TRUE, ShowBranchIsTakenOrNot, Rflags);
353
354 return 0;
355}

◆ HyperDbgIsConditionalJumpTaken()

DEBUGGER_CONDITIONAL_JUMP_STATUS HyperDbgIsConditionalJumpTaken ( unsigned char * BufferToDisassemble,
UINT64 BuffLength,
RFLAGS Rflags,
BOOLEAN Isx86_64 )

Check whether the jump is taken or not taken (in debugger)

the implementation of this function derived from the table in this site : http://www.unixwiz.net/techtips/x86-jumps.html

Parameters
BufferToDisassembleCurrent Bytes of assembly
BuffLengthLength of buffer
RflagsThe kernel's current RFLAG
Isx86_64Whether it's an x86 or x64
Returns
DEBUGGER_NEXT_INSTRUCTION_FINDER_STATUS
414{
415 ZydisDecoder decoder;
416 ZydisFormatter formatter;
417 ZydisDecodedOperand operands[ZYDIS_MAX_OPERAND_COUNT];
418 UINT64 CurrentRip = 0;
419 int instr_decoded = 0;
420 ZydisDecodedInstruction instruction;
421 UINT32 MaximumInstrDecoded = 1;
422
423 if (ZydisGetVersion() != ZYDIS_VERSION)
424 {
425 ShowMessages("invalid Zydis version\n");
427 }
428
429 if (Isx86_64)
430 {
431 ZydisDecoderInit(&decoder, ZYDIS_MACHINE_MODE_LONG_64, ZYDIS_STACK_WIDTH_64);
432 }
433 else
434 {
435 ZydisDecoderInit(&decoder, ZYDIS_MACHINE_MODE_LONG_COMPAT_32, ZYDIS_STACK_WIDTH_32);
436 }
437
438 ZydisFormatterInit(&formatter, ZYDIS_FORMATTER_STYLE_INTEL);
439
440 ZydisFormatterSetProperty(&formatter, ZYDIS_FORMATTER_PROP_FORCE_SEGMENT, ZYAN_TRUE);
441 ZydisFormatterSetProperty(&formatter, ZYDIS_FORMATTER_PROP_FORCE_SIZE, ZYAN_TRUE);
442
443 //
444 // Replace the `ZYDIS_FORMATTER_FUNC_PRINT_ADDRESS_ABS` function that
445 // formats the absolute addresses
446 //
447 default_print_address_absolute = (ZydisFormatterFunc)&ZydisFormatterPrintAddressAbsolute;
448 ZydisFormatterSetHook(&formatter, ZYDIS_FORMATTER_FUNC_PRINT_ADDRESS_ABS, (const void **)&default_print_address_absolute);
449
450 while (ZYAN_SUCCESS(ZydisDecoderDecodeFull(&decoder, BufferToDisassemble, BuffLength, &instruction, operands)))
451 {
452 //
453 // We have to pass a `runtime_address` different to
454 // `ZYDIS_RUNTIME_ADDRESS_NONE` to enable printing of absolute addresses
455 //
456
457 // ZydisFormatterFormatInstruction(&formatter, &instruction, operands, instruction.operand_count_visible, &buffer[0], sizeof(buffer), (ZyanU64)CurrentRip, ZYAN_NULL);
458
459 switch (instruction.mnemonic)
460 {
461 case ZydisMnemonic::ZYDIS_MNEMONIC_JO:
462
463 //
464 // Jump if overflow (jo)
465 //
466 if (Rflags.OverflowFlag)
468 else
470
471 break;
472
473 case ZydisMnemonic::ZYDIS_MNEMONIC_JNO:
474
475 //
476 // Jump if not overflow (jno)
477 //
478 if (!Rflags.OverflowFlag)
480 else
482
483 break;
484
485 case ZydisMnemonic::ZYDIS_MNEMONIC_JS:
486
487 //
488 // Jump if sign
489 //
490 if (Rflags.SignFlag)
492 else
494
495 break;
496
497 case ZydisMnemonic::ZYDIS_MNEMONIC_JNS:
498
499 //
500 // Jump if not sign
501 //
502 if (!Rflags.SignFlag)
504 else
506
507 break;
508
509 case ZydisMnemonic::ZYDIS_MNEMONIC_JZ:
510
511 //
512 // Jump if equal (je),
513 // Jump if zero (jz)
514 //
515 if (Rflags.ZeroFlag)
517 else
519
520 break;
521
522 case ZydisMnemonic::ZYDIS_MNEMONIC_JNZ:
523
524 //
525 // Jump if not equal (jne),
526 // Jump if not zero (jnz)
527 //
528 if (!Rflags.ZeroFlag)
530 else
532
533 break;
534
535 case ZydisMnemonic::ZYDIS_MNEMONIC_JB:
536
537 //
538 // Jump if below (jb),
539 // Jump if not above or equal (jnae),
540 // Jump if carry (jc)
541 //
542
543 //
544 // This jump is unsigned
545 //
546
547 if (Rflags.CarryFlag)
549 else
551
552 break;
553
554 case ZydisMnemonic::ZYDIS_MNEMONIC_JNB:
555
556 //
557 // Jump if not below (jnb),
558 // Jump if above or equal (jae),
559 // Jump if not carry (jnc)
560 //
561
562 //
563 // This jump is unsigned
564 //
565
566 if (!Rflags.CarryFlag)
568 else
570
571 break;
572
573 case ZydisMnemonic::ZYDIS_MNEMONIC_JBE:
574
575 //
576 // Jump if below or equal (jbe),
577 // Jump if not above (jna)
578 //
579
580 //
581 // This jump is unsigned
582 //
583
584 if (Rflags.CarryFlag || Rflags.ZeroFlag)
586 else
588
589 break;
590
591 case ZydisMnemonic::ZYDIS_MNEMONIC_JNBE:
592
593 //
594 // Jump if above (ja),
595 // Jump if not below or equal (jnbe)
596 //
597
598 //
599 // This jump is unsigned
600 //
601
602 if (!Rflags.CarryFlag && !Rflags.ZeroFlag)
604 else
606
607 break;
608
609 case ZydisMnemonic::ZYDIS_MNEMONIC_JL:
610
611 //
612 // Jump if less (jl),
613 // Jump if not greater or equal (jnge)
614 //
615
616 //
617 // This jump is signed
618 //
619
620 if (Rflags.SignFlag != Rflags.OverflowFlag)
622 else
624
625 break;
626
627 case ZydisMnemonic::ZYDIS_MNEMONIC_JNL:
628
629 //
630 // Jump if greater or equal (jge),
631 // Jump if not less (jnl)
632 //
633
634 //
635 // This jump is signed
636 //
637
638 if (Rflags.SignFlag == Rflags.OverflowFlag)
640 else
642
643 break;
644
645 case ZydisMnemonic::ZYDIS_MNEMONIC_JLE:
646
647 //
648 // Jump if less or equal (jle),
649 // Jump if not greater (jng)
650 //
651
652 //
653 // This jump is signed
654 //
655
656 if (Rflags.ZeroFlag || Rflags.SignFlag != Rflags.OverflowFlag)
658 else
660
661 break;
662
663 case ZydisMnemonic::ZYDIS_MNEMONIC_JNLE:
664
665 //
666 // Jump if greater (jg),
667 // Jump if not less or equal (jnle)
668 //
669
670 //
671 // This jump is signed
672 //
673
674 if (!Rflags.ZeroFlag && Rflags.SignFlag == Rflags.OverflowFlag)
676 else
678
679 break;
680
681 case ZydisMnemonic::ZYDIS_MNEMONIC_JP:
682
683 //
684 // Jump if parity (jp),
685 // Jump if parity even (jpe)
686 //
687
688 if (Rflags.ParityFlag)
690 else
692
693 break;
694
695 case ZydisMnemonic::ZYDIS_MNEMONIC_JNP:
696
697 //
698 // Jump if not parity (jnp),
699 // Jump if parity odd (jpo)
700 //
701
702 if (!Rflags.ParityFlag)
704 else
706
707 break;
708
709 case ZydisMnemonic::ZYDIS_MNEMONIC_JCXZ:
710 case ZydisMnemonic::ZYDIS_MNEMONIC_JECXZ:
711
712 //
713 // Jump if %CX register is 0 (jcxz),
714 // Jump if% ECX register is 0 (jecxz)
715 //
716
717 //
718 // Actually this instruction are rarely used
719 // but if we want to support these instructions then we
720 // should read ecx and cx each time in the debuggee,
721 // so it's better to just ignore it as a non-conditional
722 // jump
723 //
725
726 default:
727
728 //
729 // It's not a jump
730 //
732 break;
733 }
734
736 }
737
738 //
739 // Should not reach here
740 //
742}
@ DEBUGGER_CONDITIONAL_JUMP_STATUS_NOT_CONDITIONAL_JUMP
Definition RequestStructures.h:1108

◆ HyperDbgLengthDisassemblerEngine()

UINT32 HyperDbgLengthDisassemblerEngine ( unsigned char * BufferToDisassemble,
UINT64 BuffLength,
BOOLEAN Isx86_64 )

Length Disassembler engine based on Zydis.

Parameters
BufferToDisassembleCurrent Bytes of assembly
BuffLengthLength of buffer
Isx86_64Whether it's an x86 or x64
Lengthof call (if return value is TRUE)
Returns
UINT32
860{
861 ZydisDecoder decoder;
862 ZydisFormatter formatter;
863 ZydisDecodedOperand operands[ZYDIS_MAX_OPERAND_COUNT];
864 UINT64 CurrentRip = 0;
865 int instr_decoded = 0;
866 ZydisDecodedInstruction instruction;
867 UINT32 MaximumInstrDecoded = 1;
868
869 if (ZydisGetVersion() != ZYDIS_VERSION)
870 {
871 ShowMessages("invalid Zydis version\n");
873 }
874
875 if (Isx86_64)
876 {
877 ZydisDecoderInit(&decoder, ZYDIS_MACHINE_MODE_LONG_64, ZYDIS_STACK_WIDTH_64);
878 }
879 else
880 {
881 ZydisDecoderInit(&decoder, ZYDIS_MACHINE_MODE_LONG_COMPAT_32, ZYDIS_STACK_WIDTH_32);
882 }
883
884 ZydisFormatterInit(&formatter, ZYDIS_FORMATTER_STYLE_INTEL);
885
886 ZydisFormatterSetProperty(&formatter, ZYDIS_FORMATTER_PROP_FORCE_SEGMENT, ZYAN_TRUE);
887 ZydisFormatterSetProperty(&formatter, ZYDIS_FORMATTER_PROP_FORCE_SIZE, ZYAN_TRUE);
888
889 //
890 // Replace the `ZYDIS_FORMATTER_FUNC_PRINT_ADDRESS_ABS` function that
891 // formats the absolute addresses
892 //
894 (ZydisFormatterFunc)&ZydisFormatterPrintAddressAbsolute;
895 ZydisFormatterSetHook(&formatter, ZYDIS_FORMATTER_FUNC_PRINT_ADDRESS_ABS, (const void **)&default_print_address_absolute);
896
897 while (ZYAN_SUCCESS(ZydisDecoderDecodeFull(&decoder, BufferToDisassemble, BuffLength, &instruction, operands)))
898 {
899 //
900 // We have to pass a `runtime_address` different to
901 // `ZYDIS_RUNTIME_ADDRESS_NONE` to enable printing of absolute addresses
902 //
903 // ZydisFormatterFormatInstruction(&formatter, &instruction, operands, instruction.operand_count_visible, &buffer[0], sizeof(buffer), (ZyanU64)CurrentRip, ZYAN_NULL);
904
905 //
906 // Return len of buffer
907 //
908 return instruction.length;
909 }
910
911 //
912 // Error in disassembling buffer
913 //
914 return 0;
915}

◆ ZydisTest()

int ZydisTest ( )

Zydis test.

Returns
int
272{
273 if (ZydisGetVersion() != ZYDIS_VERSION)
274 {
275 fputs("Invalid Zydis version\n", ZYAN_STDERR);
276 return EXIT_FAILURE;
277 }
278
279 ZyanU8 data[] = {
280 0x48,
281 0x8B,
282 0x05,
283 0x39,
284 0x00,
285 0x13,
286 0x00, // mov rax, qword ptr ds:[<SomeModule.SomeData>]
287 0x50, // push rax
288 0xFF,
289 0x15,
290 0xF2,
291 0x10,
292 0x00,
293 0x00, // call qword ptr ds:[<SomeModule.SomeFunction>]
294 0x85,
295 0xC0, // test eax, eax
296 0x0F,
297 0x84,
298 0x00,
299 0x00,
300 0x00,
301 0x00, // jz 0x007FFFFFFF400016
302 0xE9,
303 0xE5,
304 0x0F,
305 0x00,
306 0x00 // jmp <SomeModule.EntryPoint>
307 };
308
309 ZydisDecoder decoder;
310 ZydisDecoderInit(&decoder, ZYDIS_MACHINE_MODE_LONG_64, ZYDIS_STACK_WIDTH_64);
311
312 DisassembleBuffer(&decoder, 0x007FFFFFFF400000, &data[0], sizeof(data), 0xffffffff, TRUE, FALSE, NULL);
313
314 return 0;
315}

Variable Documentation

◆ default_print_address_absolute

ZydisFormatterFunc default_print_address_absolute

◆ g_AddressConversion

BOOLEAN g_AddressConversion
extern

Whether converting addresses to object names or not.

it is enabled by default

◆ g_DisassemblerSymbolMap

std::map<UINT64, LOCAL_FUNCTION_DESCRIPTION> g_DisassemblerSymbolMap
extern

Symbol table for disassembler.

◆ g_DisassemblerSyntax

UINT32 g_DisassemblerSyntax
extern

Shows the syntax used in !u !u2 u u2 commands.

INTEL = 1, ATT = 2, MASM = 3