DynamoRIO / DynamoRIO/dynamorio
Document that instr_get_app_pc() may point to a hook: should encode instead of using the bits there
- Dominant language
- C
- Stars
- 3.2k
- Forks
- 629
- Avg merge
- 2d 15h
- Merged PRs (30d)
- 31
Description
**Instruction raw bits are wrong **
On Windows 10, I need to print the raw bits of every instruction to a trace file.
I have successfully done it, but when I check the correctness, I find that after decoding the raw bits into instr_t, the decoded content is not same as the original instr_t. I just decode the raw bits in analysis funciton of instrumentation phase 3 and do not insert any instrumentation when reproducing this error.
I used DynamoRIO for 2 years, I am not a novice. I do not encode, just decode from original app_pc without any instrumentation happened, I am sure there is no problem about the re-relativization problem happened in encode.
This error happens from official release version DynamoRIO-Windows-9.0.1 to nightly build DynamoRIO-Windows-9.93.19503, the newer versions after DynamoRIO-Windows-9.93.19503 are not tested yet.
Note that the correctness checking code is in the analysis function in instrumentation phase 3, meaning that the analysis function is the first argument of drmgr_register_bb_instrumentation_event.
I disassemble the error happen original block into a file, the content is as follows:
TAG 0x00007ffd34a2d500
+0 L3 @0x000002b0eacd9420 4c 8b d1 mov %rcx -> %r10
+3 L3 @0x000002b0eac8ad80 b8 23 00 00 00 mov $0x00000023 -> %eax
+8 L3 @0x000002b0eac89928 f6 04 25 08 03 fe 7f test 0x7ffe0308[1byte] $0x01
01
+16 L3 @0x000002b0eac8b7a0 75 03 jnz $0x00007ffd34a2d515
END 0x00007ffd34a2d500
This is in ntdll.dll and the offset to the start of ntdll.dll is 0x9d500.
The error is that, in original app_pc for the second instruction, the binary content is 'e9 c1 2c 16 80' which is different from 'b8 23 00 00 00'. This binary content is actually decoded as a jmp instruction instead of a mov instruction.
I test this error in many files, and that error will definitely happen in all tested files.
I have quick fixed this error for myself by checking the mov instruction and re-encoding mov instruction into somewhere for myself.
Only mov instructions in some special blocks in ntdll.dll have this kind of error.
**To Reproduce**
Write an exe file which is a simple Hello World with simple file read operations.
```c
int main()
{
std::string filename = "C:/HomeSpace/file_with_5bytes.bin";
std::ifstream t;
t.open(filename.c_str()); // open input file
t.seekg(0, std::ios::end); // go to the end
int length = t.tellg(); // report location (this is the length)
t.seekg(0, std::ios::beg); // go back to the beginning
char* buffer = new char[length]; // allocate memory for a buffer of appropriate dimension
printf("read buffer start address:%p\n", buffer);
t.read(buffer, length); // read the whole file into the buffer
t.close(); // close file handle
if (*(buffer + 0) < 15) {
std::cout << "run 0th < 15 branch!\n";
}
return 0;
}
```
Write client only with the analysis function (first argument of drmgr_register_bb_instrumentation_event) in instrumentation phase 3, the DR_ASSERT in the following code will fail.
```c
dr_emit_flags_t
app_instruction_analysis_reproduce_bug(void* drcontext, void* tag, instrlist_t* bb, bool for_trace,
bool translating, void** user_data)
{
instr_t* first = instrlist_first(bb);
instr_t* last = instrlist_last(bb);
// iterate instr
instr_t* itr = first;
while (1) {
app_pc itr_app_pc = instr_get_app_pc(itr);
app_pc itr_next_app_pc = decode_next_pc(drcontext, itr_app_pc);
instr_t inst_data{};
instr_t* inst = &inst_data;
instr_init(drcontext, inst);
byte* next_pc = decode(drcontext, itr_app_pc, inst);
// this assert will fail for some blocks (no more than 20) in ntdll.dll.
DR_ASSERT(instr_same(inst, itr));
instr_free(drcontext, inst);
if (itr == last) {
break;
}
itr = instr_get_next(itr);
}
return DR_EMIT_DEFAULT;
}
```
In dr_client_main function, register above code into drmgr_register_bb_instrumentation_event, the error will happen.
```
drmgr_register_bb_instrumentation_event(app_instruction_analysis_reproduce_bug, NULL_Function, NULL);
```
Although I have a simple fix (check the mov instruction in ntdll.dll and re-encode mov instruction into somewhere else by myself, note that mov instruction has no re-relativization problems, so the fix is easy to implement), but I hope this error can be fixed on the official side. This small error may cause serious consequents as the execution results will be inconsistency between the binary level trace and the original exe execution.
Contributor guide
Assessment
This issue has not been assessed yet.