trailofbits / sienna-locomotive

A user-friendly fuzzing and crash triage tool for Windows
https://blog.trailofbits.com/user-friendly-fuzzing-with-sienna-locomotive
GNU Affero General Public License v3.0
131 stars 24 forks source link

Non executable memory faults in DynamoRIO #11

Open TACIXAT opened 7 years ago

TACIXAT commented 7 years ago

Whether memory is executable or not relies on the GNU_STACK header in ELF files. If it is not present, the default behavior is that READ_IMPLIES_EXECUTE. Pin, probably since it JITs stuff, has memory marked as executable. This behavior translates down to the binary it is instrumenting.

The issue is that if we see a crash on an access violation when attempting to branch to nx memory, we won't see that same crash in Pin. Instead, it will branch to the memory and crash in some other way.

Did somewhat of a workaround for this in Pin. Tracking memory allocations (mmap hook) and using Pin's IMG_FindByAddress. This isn't bulletproof though, as the IMG_FindByAddress has some false negative that is valid executable code. When a branch is found that goes to what should be NX memory, the instruction is marked with a DEP flag (see: instruction.h).

  1. Is this a problem on Windows?

  2. Is there a better way to detect NX memory (e.g. platform specific /proc/<pid>/maps and VirtualQuery)?

  3. Quick fixes to resolve the false negative.

TACIXAT commented 6 years ago

It looks like DynamoRIO might also have permissive memory. We should try to reproduce a crash caused by jumping to NX memory. If all memory is marked as executable in DR, then we should find a way to track this and implement our own memory permission checker.

woodruffw commented 6 years ago

We should probably de-icebox this: the fact that all memory in DR is executable means that we'll probably find crashes that won't happen when DEP is enabled.

ehennenfent commented 6 years ago

Perhaps we can save the memory maps from the fuzzer/tracer and check after the crash occurs whether the instruction pointer was in a region that should not have been executable.

woodruffw commented 6 years ago

I think dr_virtual_alloc + MEMORY_BASIC_INFORMATION.Protect will allow us to accomplish this.

woodruffw commented 6 years ago

Based on https://github.com/DynamoRIO/dynamorio/blob/f1713ec4a9a856d1038c6095da67a5bd95b6a1c7/core/win32/ntdll.c#L2016 and https://github.com/DynamoRIO/dynamorio/blob/f1713ec4a9a856d1038c6095da67a5bd95b6a1c7/core/win32/drwinapi/kernel32_mem.c#L460, I don't think DynamoRIO uses permissive memory. I also haven't been able to cause a ROP exploit under a DEP-protected binary run under drrun, so I think this is probably not going to be a concern.

woodruffw commented 6 years ago

(Marking it as a candidate just in case I'm wrong).