DynamoRIO / dynamorio

Dynamic Instrumentation Tool Platform
Other
2.61k stars 554 forks source link

CRASH (themida-hostname.exe) multi threaded self modification #2294

Open Simorfo opened 7 years ago

Simorfo commented 7 years ago

With version 6.2.0-2 of DynamoRio The latest build does not solve the problem

On Windows 7, with a 32 bit application, themida-hostname.exe the classic hostname software packed with themida

I run it with (no client) C:\rio\bin32\drrun.exe -debug -- themida-hostname.exe

The expected output is a line with the hostname. Instead we get a crash with ASSERT(!info.overlap || (f != NULL && TEST(FRAG_IS_TRACE, f->flags)));

The problem seems to come from two threads doing self modifications on the same memory page. With a race condition, we have two exceptions EXCEPTION_ACCESS_VIOLATION.

Both threads end up in function handle_modified_code First one goes normally, ending removing the interval from the exec list to continue write. But second one logs Region for 0x101a1f3 not exec, probably data on same page WARNING: region now writable: assuming another thread already flushed it going to flush again just to make sure ASSERT(!info.overlap || (f != NULL && TEST(FRAG_IS_TRACE, f->flags)));

Condition base_pc < (bb_pend + PAGE_SIZE) && (base_pc + size) > bb_pstart was not true for the second thread because size was not expanded after get_memory_info to the exec area size.

Returning NULL from handle_modified_code to re-execute the faulting write instead of asserting provides a correct behavior in this case.

Simorfo commented 7 years ago

Sorry, this happens only in debug mode. In non-debug mode, dynamorio works fine.

With debug mode, I get a few other failed asserts

derekbruening commented 7 years ago

Sorry, this happens only in debug mode. In non-debug mode, dynamorio works fine.

You mean there's no possibility of a race in non-debug? Or it's just less likely due to spending less time processing exceptions and you just didn't observe it? What if you run the app in a loop 1000 iters?

Simorfo commented 7 years ago

In non-debug mode, I just run it 10 times and did not observe a race condition

With debug mode, I got a race every time.

Also, I tried to run it with option safe_translate_flushed I tried it because I managed to get test security-win32.selfmod-threads running fine with this option (and not fine without) But I get another bug with this sample before getting to the threads creation (one mutex gets locked twice)