Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Changing PC from within an UC_HOOK_CODE doesn't work #210

Closed
hugoreinaldo opened this issue Oct 21, 2015 · 14 comments
Closed

Changing PC from within an UC_HOOK_CODE doesn't work #210

hugoreinaldo opened this issue Oct 21, 2015 · 14 comments

Comments

@hugoreinaldo
Copy link

Is there a way to change the program counter from within an UC_HOOK_CODE ? None of the following examples seem to work:

def hook_code(uc, address, size, userdata):
    uc.reg_write(arm_const.UC_ARM_REG_PC, 0x00)

def hook_code(uc, address, size, userdata):
    uc.mem_write(address+size, 0x00)
@hugoreinaldo hugoreinaldo changed the title Changing PC during from within an UC_HOOK_CODE doesn't work Changing PC from within an UC_HOOK_CODE doesn't work Oct 21, 2015
@lunixbochs
Copy link
Contributor

Try stopping emulation and doing an emu_start() at the new address once the hook_code callback returns.

@aquynh
Copy link
Member

aquynh commented Oct 21, 2015

Can you send a pull request to put your testcase under tests/regress/, so it is possible to test and confirm this issue? Thanks

@gaffe23
Copy link
Contributor

gaffe23 commented Oct 21, 2015

There are test cases for this in tests/regress/callback-pc.py using both UC_HOOK_CODE and UC_HOOK_BLOCK.

@hugoreinaldo
Copy link
Author

@lunixbochs I'm trying your solution as a workaround for the issue.

@gaffe23 The test case tests/regress/callback-pc.py covers this issue, however there is no assertion validating the PC change in this test.

@aquynh
Copy link
Member

aquynh commented Oct 22, 2015

this issue was already discussed at #4

@gaffe23
Copy link
Contributor

gaffe23 commented Oct 23, 2015

@hugoreinaldo Yep, I wrote that before we actually had a test suite. I'm about to submit a pull request to add assertions, just to make it clear that we'd like this to work at some point.

aquynh added a commit that referenced this issue Oct 24, 2015
add assertion to callback-PC test to make it clear what the correct behavior should be (issue #210)
@farmdve
Copy link
Contributor

farmdve commented Nov 12, 2015

@aquynh

Have you found a way to change EIP from hooked code? I've been studying Unicorn and the QEMU internals(thank god they are mostly stripped), it's difficult, there is lots of code, but I am making progress.

I do have some ideas, but they are incomplete.

@aquynh
Copy link
Member

aquynh commented Nov 12, 2015

yes, a rough idea is to quit the current basic block immediately, flush the JIT translation cache, then tell the engine to change the EIP, so next time JIT will start from the new place.

that is the approach, but i dont have time to work on the implementation yet. this is a bit tricky to code. if you can, just go ahead doing it.

@aquynh
Copy link
Member

aquynh commented Nov 13, 2015

you guys should send in a testcase about changing PC from the callback. i can fix that if i have time.

@farmdve
Copy link
Contributor

farmdve commented Jan 5, 2016

I am feeling in the mood to try and tackle this.

So, you said you had something in mind, what is it? What I have in mind is, after setting EIP to a new location, we set the tcg_exit_req to true and some other variable to indicate we are not exiting, but merely changing eip. Then when the hook exits, check_exit_request is immediately called and sees we are requesting exit. Then once it is done, we find a suitable place and flush the translation blocks. Then when tb_find_fast is called it will start translating the new address.

That is for manually changing EIP. For emulating something like SEH, we need to have hooks for exceptions(all exceptions).

EDIT: I think we may need a special function for this. If we use uc_reg_write(UC_X86_REG_EIP) then how can we differentiate between setting EIP before calling uc_emu_start and doing the same from a hook?
EDIT2:With minimal changes I managed to implement changing EIP/PC from callback.

@aquynh
Copy link
Member

aquynh commented Jan 6, 2016

yes in general the way to go when PC is modified from inside a callback (using uc_reg_write()) is:

  • signal to quit the current BB immediately
  • upon exit, flush a page in the JIT cache where the new PC belongs to
  • let the execution continue

this is not really hard to implement, and i think you can do it :-)

@farmdve
Copy link
Contributor

farmdve commented Jan 6, 2016

@aquynh

Experimentally, just for myself, I have. farmdve@bd2f111 this is my dev branch, wanted to test all features at once. Don't mind the indentation :D

@aquynh
Copy link
Member

aquynh commented Jan 6, 2016

can you have a testcase for this new feature?

do you really want to flush all the cache? how about flushing only a related cache page (that contains the new PC)?

@aquynh
Copy link
Member

aquynh commented Jan 28, 2016

this feature is now implemented for all architectures in the commit 5a04bcb.

check out https://github.com/unicorn-engine/unicorn/blob/master/tests/unit/test_pc_change.c to see how this works.

if you find any issues, please report.

@aquynh aquynh closed this as completed Jul 10, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants