@@ -198,45 +198,65 @@ bool FaultyFileDetector::scan_resource_process_parse_and_hook() {
198198 const int first_call_vtable_offset = 0x20 ;
199199 const int second_call_vtable_offset = 0x48 ;
200200 const int third_call_vtable_offset = 0x38 ;
201+ bool found[3 ]{false , false , false };
201202
202- const int max_instructions_search_range = 60 ;
203+ const int max_instructions_search_range = 100 ;
203204
204205 int current_calls_found = 0 ;
205206
206207 std::uint8_t *parse_call_ptr = nullptr ;
207208 std::uint8_t *parse_call_return_address = nullptr ;
208209 std::uint8_t *start_searching_resource_access_ptr = nullptr ;
209210
210- for (int i = 0 ; i < max_instructions_search_range; i++) {
211- auto instr = utility::decode_one (after_call_ptr);
212- if (!instr.has_value ()) {
213- break ;
211+ // for (int i = 0; i < max_instructions_search_range; i++) {
212+ // auto instr = utility::decode_one(after_call_ptr);
213+ // if (!instr.has_value()) {
214+ // break;
215+ // }
216+ // exhaustive_decode instead. seen to be using non contiguous control flow in some games.
217+ utility::exhaustive_decode ((uint8_t *)after_call_ptr, max_instructions_search_range, [&](utility::ExhaustionContext& ctx) -> utility::ExhaustionResult {
218+ if (current_calls_found >= 3 ) {
219+ return utility::ExhaustionResult::BREAK ;
214220 }
221+
222+ auto * instr = &ctx.instrux ;
215223
216224 if (instr->Instruction == ND_INS_CALLNI ) {
217225 if (instr->OperandsCount >= 1 && instr->Operands [0 ].Type == ND_OP_MEM ) {
218226 auto mem_operand = instr->Operands [0 ].Info .Memory ;
219227 if (mem_operand.Base == NDR_RAX ) {
220- if (current_calls_found == 0 && mem_operand.Disp == first_call_vtable_offset) {
228+ if (mem_operand.Disp == first_call_vtable_offset && !found[ 0 ] ) {
221229 // First call found
222230 current_calls_found++;
223231 start_searching_resource_access_ptr = after_call_ptr + instr->Length ;
224- } else if (current_calls_found == 1 && mem_operand.Disp == second_call_vtable_offset) {
232+ found[0 ] = true ;
233+ spdlog::info (" [FaultyFileDetector]: Found first call at 0x{:X}" , (uintptr_t )after_call_ptr);
234+ } else if (mem_operand.Disp == second_call_vtable_offset && !found[1 ]) {
225235 // Second call found
226236 current_calls_found++;
227237 parse_call_ptr = after_call_ptr;
228238 parse_call_return_address = after_call_ptr + instr->Length ;
229- } else if (current_calls_found == 2 && mem_operand.Disp == third_call_vtable_offset) {
239+ found[1 ] = true ;
240+ spdlog::info (" [FaultyFileDetector]: Found second call at 0x{:X}" , (uintptr_t )after_call_ptr);
241+ } else if (mem_operand.Disp == third_call_vtable_offset && !found[2 ]) {
230242 // Third call found
231243 current_calls_found++;
232- break ;
244+ found[2 ] = true ;
245+ spdlog::info (" [FaultyFileDetector]: Found third call at 0x{:X}" , (uintptr_t )after_call_ptr);
233246 }
234247 }
235248 }
236249 }
237250
238251 after_call_ptr += instr->Length ;
239- }
252+
253+ // step over calls.
254+ if (instr->Category == ND_CAT_CALL ) {
255+ return utility::ExhaustionResult::STEP_OVER ;
256+ }
257+
258+ return utility::ExhaustionResult::CONTINUE ;
259+ });
240260
241261 if (current_calls_found == 3 ) {
242262 // Definitively what we are looking for
@@ -249,13 +269,15 @@ bool FaultyFileDetector::scan_resource_process_parse_and_hook() {
249269 std::uint8_t *resource_argument_assigned_ptr = nullptr ;
250270
251271 // Very fragile way, but it works for now
252- for (int i = 0 ; i < resource_register_search_max_num_instructions && instr_ptr < parse_call_ptr ; i++) {
272+ for (int i = 0 ; i < resource_register_search_max_num_instructions; i++) {
253273 auto instrux = utility::decode_one (instr_ptr);
254- if (instrux && instrux->Instruction == ND_INS_MOV ) {
274+ if (instrux && std::string_view ( instrux->Mnemonic ). starts_with ( " MOV " ) ) {
255275 bool is_first_operator_first_arg = instrux->OperandsCount >= 1 && instrux->Operands [0 ].Type == ND_OP_REG && instrux->Operands [0 ].Info .Register .Reg == NDR_RCX ;
256276 bool is_second_operator_register = instrux->OperandsCount >= 2 && instrux->Operands [1 ].Type == ND_OP_REG ;
277+ // Seen in RE9
278+ bool is_second_operator_rsp_based = instrux->OperandsCount >= 2 && instrux->Operands [1 ].Type == ND_OP_MEM && instrux->Operands [1 ].Info .Memory .Base == NDR_RSP ;
257279
258- if (is_first_operator_first_arg && is_second_operator_register) {
280+ if (is_first_operator_first_arg && ( is_second_operator_register || is_second_operator_rsp_based) ) {
259281 resource_argument_assigned_ptr = instr_ptr + instrux->Length ;
260282 spdlog::info (" [FaultyFileDetector]: Found resource argument assign at 0x{:x}, hooking to extract it at: 0x{:x}" , (uintptr_t )instr_ptr, (uintptr_t )resource_argument_assigned_ptr);
261283
0 commit comments