alexhude / uEmu

Tiny cute emulator plugin for IDA based on unicorn.
1.11k stars 177 forks source link

uEmu spawns a new thread on every instruction #15

Closed Vtec234 closed 5 years ago

Vtec234 commented 5 years ago

The code for step starts a new thread to do the step, probably to keep the simulation asynchronous, which is fair enough and useful. But the step function is only capable of executing one instruction at a time. The run functionality also uses step, just with a special constant kStepCount_Run which means "keep going". The issue is that step_thread_main will call step recursively, which will spawn a brand new thread.. on every instruction. Unicorn is slower than hardware, but not that slow, so this control flow makes emulation orders of magnitude slower than it needs to be. Proposed fix: call emu_start with an indefinite count in the step_thread_main thread and use Unicorn hooks (UC_HOOK_CODE) to do the tracing, breakpoint handling and IDAAPI_MakeCode.

alexhude commented 5 years ago

Thank you for your feedback.

However, I don't think there is an issue here, because step is NOT called recursively. According to IDA SDK

THREAD_SAFE int execute_sync ( exec_request_t & req, int reqf )
Execute code in the main thread.

Therefore, there is a new thread created for every instruction, but as soon as instruction is executed execute_sync(uEmuOnMainCallable(result_handler), MFF_WRITE) returns control back to main thread. Then result_handler creates new thread to execute next instruction.

It was intentionally designed that way with the idea of using some third party modules while control is back to IDA main thread (advanced manual fuzzing, monitoring, dynamic instrumentation etc). This means, even if we run with UC_HOOK_CODE we have to wait for the main thread to continue. For the purpose of running/tracing code quickly I strongly suggest using unicorn API directly because in this case you don't need to interact with CPU state in custom uEmu IDA views.

Also, as I remember, at the time of writing UC_HOOK_CODE was not working properly causing some odd issues during big block execution.

Vtec234 commented 5 years ago

Thank you for replying quickly. I should have been clearer in that what I considered to be the issue was that a new thread is spawned on every step, recursively or not, because doing so is generally a long operation. However if as you say, the purpose of uEmu is more to run heavy custom instrumentation in the main IDA thread, rather than execute blocks of code quickly, then maybe this is not so much of an issue. I'll go with your suggestion to use Unicorn directly.