|
7 | 7 | #include "debugger.h"
|
8 | 8 | #include "filehelper.h"
|
9 | 9 | #include "label.h"
|
10 |
| -#include "yara/yara.h" |
11 | 10 | #include "stringformat.h"
|
12 | 11 | #include "disasm_helper.h"
|
13 | 12 | #include "symbolinfo.h"
|
@@ -947,299 +946,6 @@ bool cbInstrGUIDFind(int argc, char* argv[])
|
947 | 946 | return true;
|
948 | 947 | }
|
949 | 948 |
|
950 |
| -static void yaraCompilerCallback(int error_level, const char* file_name, int line_number, const char* message, void* user_data) |
951 |
| -{ |
952 |
| - switch(error_level) |
953 |
| - { |
954 |
| - case YARA_ERROR_LEVEL_ERROR: |
955 |
| - dprintf(QT_TRANSLATE_NOOP("DBG", "[YARA ERROR] ")); |
956 |
| - break; |
957 |
| - case YARA_ERROR_LEVEL_WARNING: |
958 |
| - dprintf(QT_TRANSLATE_NOOP("DBG", "[YARA WARNING] ")); |
959 |
| - break; |
960 |
| - } |
961 |
| - dprintf(QT_TRANSLATE_NOOP("DBG", "File: \"%s\", Line: %d, Message: \"%s\"\n"), file_name, line_number, message); |
962 |
| -} |
963 |
| - |
964 |
| -static String yara_print_string(const uint8_t* data, int length) |
965 |
| -{ |
966 |
| - String result = "\""; |
967 |
| - const char* str = (const char*)data; |
968 |
| - for(int i = 0; i < length; i++) |
969 |
| - { |
970 |
| - char cur[16] = ""; |
971 |
| - if(str[i] >= 32 && str[i] <= 126) |
972 |
| - sprintf_s(cur, "%c", str[i]); |
973 |
| - else |
974 |
| - sprintf_s(cur, "\\x%02X", (uint8_t)str[i]); |
975 |
| - result += cur; |
976 |
| - } |
977 |
| - result += "\""; |
978 |
| - return result; |
979 |
| -} |
980 |
| - |
981 |
| -static String yara_print_hex_string(const uint8_t* data, int length) |
982 |
| -{ |
983 |
| - String result = ""; |
984 |
| - for(int i = 0; i < length; i++) |
985 |
| - { |
986 |
| - if(i) |
987 |
| - result += " "; |
988 |
| - char cur[16] = ""; |
989 |
| - sprintf_s(cur, "%02X", (uint8_t)data[i]); |
990 |
| - result += cur; |
991 |
| - } |
992 |
| - return result; |
993 |
| -} |
994 |
| - |
995 |
| -struct YaraScanInfo |
996 |
| -{ |
997 |
| - duint base; |
998 |
| - int index; |
999 |
| - bool rawFile; |
1000 |
| - const char* modname; |
1001 |
| - bool debug; |
1002 |
| - |
1003 |
| - YaraScanInfo(duint base, bool rawFile, const char* modname, bool debug) |
1004 |
| - : base(base), index(0), rawFile(rawFile), modname(modname), debug(debug) |
1005 |
| - { |
1006 |
| - } |
1007 |
| -}; |
1008 |
| - |
1009 |
| -static int yaraScanCallback(int message, void* message_data, void* user_data) |
1010 |
| -{ |
1011 |
| - YaraScanInfo* scanInfo = (YaraScanInfo*)user_data; |
1012 |
| - bool debug = scanInfo->debug; |
1013 |
| - switch(message) |
1014 |
| - { |
1015 |
| - case CALLBACK_MSG_RULE_MATCHING: |
1016 |
| - { |
1017 |
| - duint base = scanInfo->base; |
1018 |
| - YR_RULE* yrRule = (YR_RULE*)message_data; |
1019 |
| - auto addReference = [scanInfo, yrRule](duint addr, const char* identifier, const std::string & pattern) |
1020 |
| - { |
1021 |
| - auto index = scanInfo->index; |
1022 |
| - GuiReferenceSetRowCount(index + 1); |
1023 |
| - scanInfo->index++; |
1024 |
| - |
1025 |
| - char addr_text[deflen] = ""; |
1026 |
| - sprintf_s(addr_text, "%p", addr); |
1027 |
| - GuiReferenceSetCellContent(index, 0, addr_text); //Address |
1028 |
| - String ruleFullName = ""; |
1029 |
| - ruleFullName += yrRule->identifier; |
1030 |
| - if(identifier) |
1031 |
| - { |
1032 |
| - ruleFullName += "."; |
1033 |
| - ruleFullName += identifier; |
1034 |
| - } |
1035 |
| - GuiReferenceSetCellContent(index, 1, ruleFullName.c_str()); //Rule |
1036 |
| - GuiReferenceSetCellContent(index, 2, pattern.c_str()); //Data |
1037 |
| - }; |
1038 |
| - |
1039 |
| - if(STRING_IS_NULL(yrRule->strings)) |
1040 |
| - { |
1041 |
| - if(debug) |
1042 |
| - dprintf(QT_TRANSLATE_NOOP("DBG", "[YARA] Global rule \"%s\" matched!\n"), yrRule->identifier); |
1043 |
| - addReference(base, nullptr, ""); |
1044 |
| - } |
1045 |
| - else |
1046 |
| - { |
1047 |
| - if(debug) |
1048 |
| - dprintf(QT_TRANSLATE_NOOP("DBG", "[YARA] Rule \"%s\" matched:\n"), yrRule->identifier); |
1049 |
| - YR_STRING* string; |
1050 |
| - yr_rule_strings_foreach(yrRule, string) |
1051 |
| - { |
1052 |
| - YR_MATCH* match; |
1053 |
| - yr_string_matches_foreach(string, match) |
1054 |
| - { |
1055 |
| - String pattern; |
1056 |
| - if(STRING_IS_HEX(string)) |
1057 |
| - pattern = yara_print_hex_string(match->data, match->match_length); |
1058 |
| - else |
1059 |
| - pattern = yara_print_string(match->data, match->match_length); |
1060 |
| - auto offset = duint(match->base + match->offset); |
1061 |
| - duint addr; |
1062 |
| - if(scanInfo->rawFile) //convert raw offset to virtual offset |
1063 |
| - addr = valfileoffsettova(scanInfo->modname, offset); |
1064 |
| - else |
1065 |
| - addr = base + offset; |
1066 |
| - |
1067 |
| - if(debug) |
1068 |
| - dprintf(QT_TRANSLATE_NOOP("DBG", "[YARA] String \"%s\" : %s on %p\n"), string->identifier, pattern.c_str(), addr); |
1069 |
| - |
1070 |
| - addReference(addr, string->identifier, pattern); |
1071 |
| - } |
1072 |
| - } |
1073 |
| - } |
1074 |
| - } |
1075 |
| - break; |
1076 |
| - |
1077 |
| - case CALLBACK_MSG_RULE_NOT_MATCHING: |
1078 |
| - { |
1079 |
| - YR_RULE* yrRule = (YR_RULE*)message_data; |
1080 |
| - if(debug) |
1081 |
| - dprintf(QT_TRANSLATE_NOOP("DBG", "[YARA] Rule \"%s\" did not match!\n"), yrRule->identifier); |
1082 |
| - } |
1083 |
| - break; |
1084 |
| - |
1085 |
| - case CALLBACK_MSG_SCAN_FINISHED: |
1086 |
| - { |
1087 |
| - if(debug) |
1088 |
| - dputs(QT_TRANSLATE_NOOP("DBG", "[YARA] Scan finished!")); |
1089 |
| - } |
1090 |
| - break; |
1091 |
| - |
1092 |
| - case CALLBACK_MSG_IMPORT_MODULE: |
1093 |
| - { |
1094 |
| - YR_MODULE_IMPORT* yrModuleImport = (YR_MODULE_IMPORT*)message_data; |
1095 |
| - if(debug) |
1096 |
| - dprintf(QT_TRANSLATE_NOOP("DBG", "[YARA] Imported module \"%s\"!\n"), yrModuleImport->module_name); |
1097 |
| - } |
1098 |
| - break; |
1099 |
| - } |
1100 |
| - return ERROR_SUCCESS; //nicely undocumented what this should be |
1101 |
| -} |
1102 |
| - |
1103 |
| -bool cbInstrYara(int argc, char* argv[]) |
1104 |
| -{ |
1105 |
| - if(IsArgumentsLessThan(argc, 2)) |
1106 |
| - return false; |
1107 |
| - duint addr = 0; |
1108 |
| - SELECTIONDATA sel; |
1109 |
| - GuiSelectionGet(GUI_DISASSEMBLY, &sel); |
1110 |
| - addr = sel.start; |
1111 |
| - |
1112 |
| - duint base = 0; |
1113 |
| - duint size = 0; |
1114 |
| - duint mod = argc > 2 ? ModBaseFromName(argv[2]) : 0; |
1115 |
| - bool rawFile = false; |
1116 |
| - if(mod) |
1117 |
| - { |
1118 |
| - base = mod; |
1119 |
| - size = ModSizeFromAddr(base); |
1120 |
| - rawFile = argc > 3 && *argv[3] == '1'; |
1121 |
| - } |
1122 |
| - else |
1123 |
| - { |
1124 |
| - if(argc > 2 && !valfromstring(argv[2], &addr)) |
1125 |
| - { |
1126 |
| - dprintf(QT_TRANSLATE_NOOP("DBG", "Invalid value \"%s\"!\n"), argv[2]); |
1127 |
| - return false; |
1128 |
| - } |
1129 |
| - |
1130 |
| - size = 0; |
1131 |
| - if(argc > 3) |
1132 |
| - if(!valfromstring(argv[3], &size)) |
1133 |
| - size = 0; |
1134 |
| - if(!size) |
1135 |
| - addr = MemFindBaseAddr(addr, &size); |
1136 |
| - base = addr; |
1137 |
| - } |
1138 |
| - std::vector<unsigned char> rawFileData; |
1139 |
| - if(rawFile) //read the file from disk |
1140 |
| - { |
1141 |
| - char modPath[MAX_PATH] = ""; |
1142 |
| - if(!ModPathFromAddr(base, modPath, MAX_PATH)) |
1143 |
| - { |
1144 |
| - dprintf(QT_TRANSLATE_NOOP("DBG", "Failed to get module path for %p!\n"), base); |
1145 |
| - return false; |
1146 |
| - } |
1147 |
| - if(!FileHelper::ReadAllData(modPath, rawFileData)) |
1148 |
| - { |
1149 |
| - dprintf(QT_TRANSLATE_NOOP("DBG", "Failed to read file \"%s\"!\n"), modPath); |
1150 |
| - return false; |
1151 |
| - } |
1152 |
| - size = rawFileData.size(); |
1153 |
| - } |
1154 |
| - Memory<uint8_t*> data(size); |
1155 |
| - if(rawFile) |
1156 |
| - memcpy(data(), rawFileData.data(), size); |
1157 |
| - else |
1158 |
| - { |
1159 |
| - memset(data(), 0xCC, data.size()); |
1160 |
| - MemReadDumb(base, data(), size); |
1161 |
| - } |
1162 |
| - |
1163 |
| - String rulesContent; |
1164 |
| - if(!FileHelper::ReadAllText(argv[1], rulesContent)) |
1165 |
| - { |
1166 |
| - dprintf(QT_TRANSLATE_NOOP("DBG", "Failed to read the rules file \"%s\"\n"), argv[1]); |
1167 |
| - return false; |
1168 |
| - } |
1169 |
| - |
1170 |
| - bool bSuccess = false; |
1171 |
| - YR_COMPILER* yrCompiler; |
1172 |
| - if(yr_compiler_create(&yrCompiler) == ERROR_SUCCESS) |
1173 |
| - { |
1174 |
| - yr_compiler_set_callback(yrCompiler, yaraCompilerCallback, 0); |
1175 |
| - if(yr_compiler_add_string(yrCompiler, rulesContent.c_str(), nullptr) == 0) //no errors found |
1176 |
| - { |
1177 |
| - YR_RULES* yrRules; |
1178 |
| - if(yr_compiler_get_rules(yrCompiler, &yrRules) == ERROR_SUCCESS) |
1179 |
| - { |
1180 |
| - //initialize new reference tab |
1181 |
| - char modname[MAX_MODULE_SIZE] = ""; |
1182 |
| - if(!ModNameFromAddr(base, modname, true)) |
1183 |
| - sprintf_s(modname, "%p", base); |
1184 |
| - String fullName; |
1185 |
| - const char* fileName = strrchr(argv[1], '\\'); |
1186 |
| - if(fileName) |
1187 |
| - fullName = fileName + 1; |
1188 |
| - else |
1189 |
| - fullName = argv[1]; |
1190 |
| - fullName += " ("; |
1191 |
| - fullName += modname; |
1192 |
| - fullName += ")"; //nanana, very ugly code (long live open source) |
1193 |
| - GuiReferenceInitialize(fullName.c_str()); |
1194 |
| - GuiReferenceAddColumn(sizeof(duint) * 2, GuiTranslateText(QT_TRANSLATE_NOOP("DBG", "Address"))); |
1195 |
| - GuiReferenceAddColumn(48, GuiTranslateText(QT_TRANSLATE_NOOP("DBG", "Rule"))); |
1196 |
| - GuiReferenceAddColumn(10, GuiTranslateText(QT_TRANSLATE_NOOP("DBG", "Data"))); |
1197 |
| - GuiReferenceSetRowCount(0); |
1198 |
| - GuiReferenceReloadData(); |
1199 |
| - YaraScanInfo scanInfo(base, rawFile, argc > 2 ? argv[2] : modname, settingboolget("Engine", "YaraDebug")); |
1200 |
| - duint ticks = GetTickCount(); |
1201 |
| - dputs(QT_TRANSLATE_NOOP("DBG", "[YARA] Scan started...")); |
1202 |
| - int err = yr_rules_scan_mem(yrRules, data(), size, 0, yaraScanCallback, &scanInfo, 0); |
1203 |
| - GuiReferenceReloadData(); |
1204 |
| - switch(err) |
1205 |
| - { |
1206 |
| - case ERROR_SUCCESS: |
1207 |
| - dprintf(QT_TRANSLATE_NOOP("DBG", "%u scan results in %ums...\n"), DWORD(scanInfo.index), GetTickCount() - DWORD(ticks)); |
1208 |
| - bSuccess = true; |
1209 |
| - break; |
1210 |
| - case ERROR_TOO_MANY_MATCHES: |
1211 |
| - dputs(QT_TRANSLATE_NOOP("DBG", "Too many matches!")); |
1212 |
| - break; |
1213 |
| - default: |
1214 |
| - dputs(QT_TRANSLATE_NOOP("DBG", "Error while scanning memory!")); |
1215 |
| - break; |
1216 |
| - } |
1217 |
| - yr_rules_destroy(yrRules); |
1218 |
| - } |
1219 |
| - else |
1220 |
| - dputs(QT_TRANSLATE_NOOP("DBG", "Error while getting the rules!")); |
1221 |
| - } |
1222 |
| - else |
1223 |
| - dputs(QT_TRANSLATE_NOOP("DBG", "Errors in the rules file!")); |
1224 |
| - yr_compiler_destroy(yrCompiler); |
1225 |
| - } |
1226 |
| - else |
1227 |
| - dputs(QT_TRANSLATE_NOOP("DBG", "yr_compiler_create failed!")); |
1228 |
| - return bSuccess; |
1229 |
| -} |
1230 |
| - |
1231 |
| -bool cbInstrYaramod(int argc, char* argv[]) |
1232 |
| -{ |
1233 |
| - if(IsArgumentsLessThan(argc, 3)) |
1234 |
| - return false; |
1235 |
| - if(!ModBaseFromName(argv[2])) |
1236 |
| - { |
1237 |
| - dprintf(QT_TRANSLATE_NOOP("DBG", "Invalid module \"%s\"!\n"), argv[2]); |
1238 |
| - return false; |
1239 |
| - } |
1240 |
| - return cmddirectexec(StringUtils::sprintf("yara \"%s\",\"%s\",%s", argv[1], argv[2], argc > 3 && *argv[3] == '1' ? "1" : "0").c_str()); |
1241 |
| -} |
1242 |
| - |
1243 | 949 | bool cbInstrSetMaxFindResult(int argc, char* argv[])
|
1244 | 950 | {
|
1245 | 951 | if(IsArgumentsLessThan(argc, 2))
|
|
0 commit comments