Merge pull request #10 from cbsirb/master

Small enhancements to the disamtool_lix
pull/15/head
vlutas 4 years ago committed by GitHub
commit 02b7177b99
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -56,6 +56,8 @@ typedef size_t SIZE_T;
std::string enc_mode_to_str(const uint8_t enc_mode); std::string enc_mode_to_str(const uint8_t enc_mode);
std::string op_type_to_str(const ND_OPERAND_TYPE type);
std::string op_enc_to_str(const ND_OPERAND_ENCODING Encoding);
std::string ins_class_to_str(const ND_INS_CLASS cls); std::string ins_class_to_str(const ND_INS_CLASS cls);
std::string ins_cat_to_str(ND_INS_CATEGORY category); std::string ins_cat_to_str(ND_INS_CATEGORY category);
std::string ins_set_to_str(ND_INS_SET ins_set); std::string ins_set_to_str(ND_INS_SET ins_set);

@ -6,6 +6,7 @@
#include <fstream> #include <fstream>
#include <memory> #include <memory>
#include <limits> #include <limits>
#include <cmath>
#include "external/argparse.h" #include "external/argparse.h"
@ -49,6 +50,7 @@ struct options {
bool interactive; bool interactive;
bool comm; bool comm;
bool json_output; bool json_output;
bool extended;
std::string in_file; std::string in_file;
std::string hex_string; std::string hex_string;
@ -57,6 +59,7 @@ struct options {
// From here on, these are set internally // From here on, these are set internally
std::unique_ptr<uint8_t[]> bytes; std::unique_ptr<uint8_t[]> bytes;
size_t actual_size; size_t actual_size;
int address_size;
bool output_redirected; bool output_redirected;
}; };
@ -223,11 +226,11 @@ void print_instruction(const size_t rip, INSTRUX *instrux, const options &opts)
char instruxText[ND_MIN_BUF_SIZE]; char instruxText[ND_MIN_BUF_SIZE];
uint32_t k = 0; uint32_t k = 0;
printf("%zx ", rip); printf("%*zx ", opts.address_size, rip);
if (!opts.no_color) if (!opts.no_color)
{ {
_set_text_color(White); _set_text_color(Magenta);
for (uint32_t idx = 0; idx < instrux->PrefLength; idx++, k++) for (uint32_t idx = 0; idx < instrux->PrefLength; idx++, k++)
{ {
printf("%02x", instrux->InstructionBytes[k]); printf("%02x", instrux->InstructionBytes[k]);
@ -282,187 +285,155 @@ void print_instruction(const size_t rip, INSTRUX *instrux, const options &opts)
std::cout << instruxText << std::endl; std::cout << instruxText << std::endl;
// if (Options->ExtendedInfo) if (opts.extended) {
// { const uint8_t opsize[3] = { 2, 4, 8 };
// const BYTE opsize[3] = { 2, 4, 8 }; const uint8_t adsize[3] = { 2, 4, 8 };
// const BYTE adsize[3] = { 2, 4, 8 }; const uint8_t veclen[3] = { 16, 32, 64 };
// const BYTE veclen[3] = { 16, 32, 64 };
printf(" DSIZE: %2d, ASIZE: %2d, VLEN: ",
// printf(" DSIZE: %2d, ASIZE: %2d, VLEN: ", opsize[instrux->EfOpMode] * 8, adsize[instrux->AddrMode] * 8);
// opsize[instrux->EfOpMode] * 8, adsize[instrux->AddrMode] * 8);
if (ND_HAS_VECTOR(instrux)) {
// if (ND_HAS_VECTOR(instrux)) printf("%2d\n", veclen[instrux->VecMode] * 8);
// { } else {
// printf("%2d\n", veclen[instrux->VecMode] * 8); printf("-\n");
// } }
// else
// { printf(" ISA Set: %s, Ins cat: %s, Ins class: %d, CET tracked: %s\n",
// printf("-\n"); ins_set_to_str(instrux->IsaSet).c_str(), ins_cat_to_str(instrux->Category).c_str(), instrux->Instruction,
// } instrux->IsCetTracked ? "yes" : "no");
// printf(" ISA Set: %s, Ins cat: %s, Ins class: %d, CET tracked: %s\n", if (0 != instrux->CpuidFlag.Flag) {
// set_to_string(instrux->IsaSet), category_to_string(instrux->Category), instrux->Instruction, const char *regs[4] = { "eax", "ecx", "edx", "ebx" };
// instrux->IsCetTracked ? "yes" : "no");
printf(" CPUID leaf: 0x%08x", instrux->CpuidFlag.Leaf);
// if (0 != instrux->CpuidFlag.Flag)
// { if (instrux->CpuidFlag.SubLeaf != ND_CFF_NO_SUBLEAF)
// char *regs[4] = { "eax", "ecx", "edx", "ebx" }; {
printf(", sub-leaf: 0x%08x", instrux->CpuidFlag.SubLeaf);
// printf(" CPUID leaf: 0x%08x", instrux->CpuidFlag.Leaf); }
// if (instrux->CpuidFlag.SubLeaf != ND_CFF_NO_SUBLEAF) printf(", reg: %s, bit %d\n", regs[instrux->CpuidFlag.Reg], instrux->CpuidFlag.Bit);
// { }
// printf(", sub-leaf: 0x%08x", instrux->CpuidFlag.SubLeaf);
// } printf(" FLAGS access: ");
// printf(", reg: %s, bit %d\n", regs[instrux->CpuidFlag.Reg], instrux->CpuidFlag.Bit); uint32_t all = instrux->FlagsAccess.Tested.Raw | instrux->FlagsAccess.Modified.Raw | instrux->FlagsAccess.Set.Raw
// } | instrux->FlagsAccess.Cleared.Raw | instrux->FlagsAccess.Undefined.Raw;
const char *flags[22] = { "CF", nullptr, "PF", nullptr, "AF", nullptr, "ZF", "SF", "TF", "IF", "DF", "OF", "IOPL", nullptr, "NT", nullptr, "RF", "VM", "AC", "VIF", "VIP", "ID" };
// {
// DWORD fidx, all; for (uint32_t fidx = 0; fidx < 21; fidx++) {
// char *flags[22] = { "CF", NULL, "PF", NULL, "AF", NULL, "ZF", "SF", "TF", "IF", "DF", "OF", "IOPL", NULL, "NT", NULL, "RF", "VM", "AC", "VIF", "VIP", "ID" }; if (flags[fidx] != nullptr) {
if (0 == (all & (1ULL << fidx))) {
// all = instrux->FlagsAccess.Tested.Raw | instrux->FlagsAccess.Modified.Raw | instrux->FlagsAccess.Set.Raw | continue;
// instrux->FlagsAccess.Cleared.Raw | instrux->FlagsAccess.Undefined.Raw; }
// printf(" FLAGS access: ");
printf("%s: ", flags[fidx]);
// for (fidx = 0; fidx < 21; fidx++)
// { if (instrux->FlagsAccess.Tested.Raw & (1ULL << fidx)) {
// if (flags[fidx] != NULL) printf("t");
// { }
// if (0 == (all & (1ULL << fidx)))
// { if (instrux->FlagsAccess.Modified.Raw & (1ULL << fidx)) {
// continue; printf("m");
// } }
// printf("%s: ", flags[fidx]); if (instrux->FlagsAccess.Set.Raw & (1ULL << fidx)) {
printf("1");
// if (instrux->FlagsAccess.Tested.Raw & (1ULL << fidx)) }
// {
// printf("t"); if (instrux->FlagsAccess.Cleared.Raw & (1ULL << fidx)) {
// } printf("0");
}
// if (instrux->FlagsAccess.Modified.Raw & (1ULL << fidx))
// { if (instrux->FlagsAccess.Undefined.Raw & (1ULL << fidx)) {
// printf("m"); printf("u");
// } }
// if (instrux->FlagsAccess.Set.Raw & (1ULL << fidx)) printf("; ");
// { }
// printf("1"); }
// }
printf("\n");
// if (instrux->FlagsAccess.Cleared.Raw & (1ULL << fidx))
// { printf(" Valid modes: R0: %s, R1: %s, R2: %s, R3: %s, Real: %s, V8086: %s, Prot: %s, Compat: %s, Long: %s, SMM: %s, SGX: %s, TSX: %s, VMXRoot: %s, VMXNonRoot: %s\n",
// printf("0"); instrux->ValidModes.Ring0 ? "yes" : "no",
// } instrux->ValidModes.Ring1 ? "yes" : "no",
instrux->ValidModes.Ring2 ? "yes" : "no",
// if (instrux->FlagsAccess.Undefined.Raw & (1ULL << fidx)) instrux->ValidModes.Ring3 ? "yes" : "no",
// { instrux->ValidModes.Real ? "yes" : "no",
// printf("u"); instrux->ValidModes.V8086 ? "yes" : "no",
// } instrux->ValidModes.Protected ? "yes" : "no",
instrux->ValidModes.Compat ? "yes" : "no",
// printf("; "); instrux->ValidModes.Long ? "yes" : "no",
// } instrux->ValidModes.Smm ? "yes" : "no",
// } instrux->ValidModes.Sgx ? "yes" : "no",
instrux->ValidModes.Tsx ? "yes" : "no",
// printf("\n"); instrux->ValidModes.VmxRoot ? "yes" : "no",
// } instrux->ValidModes.VmxNonRoot ? "yes" : "no");
// printf(" Valid modes: R0: %s, R1: %s, R2: %s, R3: %s, Real: %s, V8086: %s, Prot: %s, Compat: %s, Long: %s, SMM: %s, SGX: %s, TSX: %s, VMXRoot: %s, VMXNonRoot: %s\n", for (uint8_t i = 0; i < instrux->OperandsCount; i++) {
// instrux->ValidModes.Ring0 ? "yes" : "no", printf(" Operand %d %s Type: %10s, Size: %2d, RawSize: %2d, Encoding: %s", i,
// instrux->ValidModes.Ring1 ? "yes" : "no", instrux->Operands[i].Access.Read && instrux->Operands[i].Access.Write ? "RW" :
// instrux->ValidModes.Ring2 ? "yes" : "no", instrux->Operands[i].Access.Write ? "-W" : instrux->Operands[i].Access.Read ? "R-" : "--",
// instrux->ValidModes.Ring3 ? "yes" : "no", op_type_to_str(instrux->Operands[i].Type).c_str(), instrux->Operands[i].Size,
// instrux->ValidModes.Real ? "yes" : "no", instrux->Operands[i].RawSize, op_enc_to_str(instrux->Operands[i].Encoding).c_str());
// instrux->ValidModes.V8086 ? "yes" : "no",
// instrux->ValidModes.Protected ? "yes" : "no", if (ND_OP_MEM == instrux->Operands[i].Type) {
// instrux->ValidModes.Compatibility ? "yes" : "no", printf(", ");
// instrux->ValidModes.Long ? "yes" : "no",
// instrux->ValidModes.Smm ? "yes" : "no", if (instrux->Operands[i].Info.Memory.IsAG) {
// instrux->ValidModes.Sgx ? "yes" : "no", printf("Address Generator, ");
// instrux->ValidModes.Tsx ? "yes" : "no", }
// instrux->ValidModes.VmxRoot ? "yes" : "no",
// instrux->ValidModes.VmxNonRoot ? "yes" : "no" if (instrux->Operands[i].Info.Memory.IsBitbase) {
// ); printf("Bitbase Addressing, ");
}
// for (i = 0; i < instrux->OperandsCount; i++)
// { if (instrux->Operands[i].Info.Memory.IsMib) {
// printf(" Operand %d %s Type: %10s, Size: %2d, RawSize: %2d, Encoding: %s", i, printf("MIB Addressing, ");
// instrux->Operands[i].Access.Read && instrux->Operands[i].Access.Write ? "RW" : }
// instrux->Operands[i].Access.Write ? "-W" : instrux->Operands[i].Access.Read ? "R-" : "--",
// optype_to_string(instrux->Operands[i].Type), instrux->Operands[i].Size, if (instrux->Operands[i].Info.Memory.IsVsib) {
// instrux->Operands[i].RawSize, encoding_to_string(instrux->Operands[i].Encoding) printf("VSIB Addressing, ");
// ); }
// if (ND_OP_MEM == instrux->Operands[i].Type) if (instrux->Operands[i].Info.Memory.IsStack) {
// { printf("Stack, ");
// printf(", "); }
// if (instrux->Operands[i].Info.Memory.IsAG) if (instrux->Operands[i].Info.Memory.IsShadowStack) {
// { printf("Shadow Stack, ");
// printf("Address Generator, "); }
// } }
// if (instrux->Operands[i].Info.Memory.IsBitbase) if (ND_OP_REG == instrux->Operands[i].Type) {
// { printf(", Type: %16s, Size: %2d, Reg: %d, Count: %d",
// printf("Bitbase Addressing, "); reg_type_to_str(instrux->Operands[i].Info.Register.Type).c_str(),
// } instrux->Operands[i].Info.Register.Size,
instrux->Operands[i].Info.Register.Reg,
// if (instrux->Operands[i].Info.Memory.IsMib) instrux->Operands[i].Info.Register.Count);
// { }
// printf("MIB Addressing, ");
// } printf("\n");
// if (instrux->Operands[i].Info.Memory.IsVsib) if (instrux->Operands[i].Decorator.HasBroadcast) {
// { printf(" Decorator: Broadcast %d bytes element %d times\n",
// printf("VSIB Addressing, "); instrux->Operands[i].Decorator.Broadcast.Size,
// } instrux->Operands[i].Decorator.Broadcast.Count);
}
// if (instrux->Operands[i].Info.Memory.IsStack)
// { if (instrux->Operands[i].Decorator.HasMask) {
// printf("Stack, "); printf(" Decorator: Mask k%d\n", instrux->Operands[i].Decorator.Mask.Msk);
// } }
// if (instrux->Operands[i].Info.Memory.IsShadowStack) if (instrux->Operands[i].Decorator.HasZero) {
// { printf(" Decorator: Zero (no merging)\n");
// printf("Shadow Stack, "); }
// } }
// }
printf("\n");
// if (ND_OP_REG == instrux->Operands[i].Type) }
// {
// printf(", Type: %16s, Size: %2d, Reg: %d, Count: %d\n",
// regtype_to_string(instrux->Operands[i].Info.Register.Type),
// instrux->Operands[i].Info.Register.Size,
// instrux->Operands[i].Info.Register.Reg,
// instrux->Operands[i].Info.Register.Count);
// }
// else
// {
// printf("\n");
// }
// if (instrux->Operands[i].Decorator.HasBroadcast)
// {
// printf(" Decorator: Broadcast %d bytes element %d times\n",
// instrux->Operands[i].Decorator.Broadcast.Size,
// instrux->Operands[i].Decorator.Broadcast.Count);
// }
// if (instrux->Operands[i].Decorator.HasMask)
// {
// printf(" Decorator: Mask k%d\n", instrux->Operands[i].Decorator.Mask.Msk);
// }
// if (instrux->Operands[i].Decorator.HasZero)
// {
// printf(" Decorator: Zero (no merging)\n");
// }
// }
// printf("\n");
// }
} }
@ -489,6 +460,8 @@ size_t disassemble(options &opts)
auto bytes = opts.bytes.get(); auto bytes = opts.bytes.get();
auto disasm_size = std::min(opts.actual_size - opts.offset, opts.size); auto disasm_size = std::min(opts.actual_size - opts.offset, opts.size);
opts.address_size = int(std::ceil(((8 * sizeof(opts.actual_size)) - __builtin_clzll(opts.actual_size)) / 4.0));
while ((total_disasm < disasm_size) && (icount < opts.count)) { while ((total_disasm < disasm_size) && (icount < opts.count)) {
INSTRUX instrux; INSTRUX instrux;
@ -507,9 +480,9 @@ size_t disassemble(options &opts)
auto j = byte_to_json(bytes[rel_rip], rel_rip + opts.rip); auto j = byte_to_json(bytes[rel_rip], rel_rip + opts.rip);
std::cout << j.GetString() << std::endl; std::cout << j.GetString() << std::endl;
} else { } else {
printf("%zx ", rel_rip + opts.rip); printf("%*zx ", opts.address_size, rel_rip + opts.rip);
printf("%02x", bytes[rel_rip]); printf("%02x", bytes[rel_rip]);
printf("%s", gSpaces[16 - 1]); printf("%s", gSpaces[16 - opts.address_size]);
printf("db 0x%02x\n", bytes[rel_rip]); printf("db 0x%02x\n", bytes[rel_rip]);
} }
} }
@ -649,6 +622,7 @@ int main(int argc, char **argv)
parser.add_argument("-b", "--bits", "Use the arch [16, 32, 64]", false); parser.add_argument("-b", "--bits", "Use the arch [16, 32, 64]", false);
parser.add_argument("--verbose", "Verbose mode", false); parser.add_argument("--verbose", "Verbose mode", false);
parser.add_argument("--json", "Output to json", false); parser.add_argument("--json", "Output to json", false);
parser.add_argument("--extended", "Extended instruction info", false);
try { try {
parser.parse(argc, argv); parser.parse(argc, argv);
@ -657,7 +631,7 @@ int main(int argc, char **argv)
return 1; return 1;
} }
opts.bits = parser.get<uint8_t>("bits"); opts.bits = parser.get<uint64_t>("bits");
opts.interactive = parser.get<bool>("interactive"); opts.interactive = parser.get<bool>("interactive");
opts.comm = parser.get<bool>("comm"); opts.comm = parser.get<bool>("comm");
opts.offset = _get_hex_opt(parser, "offset"); opts.offset = _get_hex_opt(parser, "offset");
@ -671,6 +645,7 @@ int main(int argc, char **argv)
opts.dump_stats = parser.get<bool>("stats"); opts.dump_stats = parser.get<bool>("stats");
opts.verbose = parser.get<bool>("verbose"); opts.verbose = parser.get<bool>("verbose");
opts.json_output = parser.get<bool>("json"); opts.json_output = parser.get<bool>("json");
opts.extended = parser.get<bool>("extended");
if (opts.verbose) { if (opts.verbose) {
std::cout << "interactive: " << opts.interactive << std::endl; std::cout << "interactive: " << opts.interactive << std::endl;
@ -685,6 +660,7 @@ int main(int argc, char **argv)
std::cout << "stats: " << opts.dump_stats << std::endl; std::cout << "stats: " << opts.dump_stats << std::endl;
std::cout << "hex: " << opts.hex_string << std::endl; std::cout << "hex: " << opts.hex_string << std::endl;
std::cout << "json: " << opts.json_output << std::endl; std::cout << "json: " << opts.json_output << std::endl;
std::cout << "extended: " << opts.extended << std::endl;
} }
if (!_validate_and_fix_args(opts)) { if (!_validate_and_fix_args(opts)) {

@ -18,6 +18,52 @@ std::string enc_mode_to_str(const uint8_t enc_mode)
} }
std::string op_enc_to_str(const ND_OPERAND_ENCODING Encoding)
{
switch (Encoding) {
case ND_OPE_NP: return "NP";
case ND_OPE_R: return "R";
case ND_OPE_M: return "M";
case ND_OPE_V: return "V";
case ND_OPE_O: return "O";
case ND_OPE_I: return "I";
case ND_OPE_D: return "D";
case ND_OPE_C: return "C";
case ND_OPE_1: return "1";
case ND_OPE_A: return "A";
case ND_OPE_L: return "L";
case ND_OPE_E: return "E";
case ND_OPE_S: return "S";
default: return "";
}
}
std::string op_type_to_str(const ND_OPERAND_TYPE type)
{
switch(type) {
case ND_OP_NOT_PRESENT:
return "not_present";
case ND_OP_REG:
return "register";
case ND_OP_MEM:
return "memory";
case ND_OP_IMM:
return "immediate";
case ND_OP_OFFS:
return "offset";
case ND_OP_ADDR:
return "address";
case ND_OP_CONST:
return "const";
case ND_OP_BANK:
return "bank";
}
return "<unknown>";
}
std::string ins_class_to_str(const ND_INS_CLASS cls) std::string ins_class_to_str(const ND_INS_CLASS cls)
{ {
switch (cls) { switch (cls) {

Loading…
Cancel
Save