-
Notifications
You must be signed in to change notification settings - Fork 1.4k
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
Execution depends on whether UC_HOOK_MEM_READ/_WRITE is registered #2041
Comments
I assume this is #2031 , could you have a check? |
Unfortunately no. In my case, #2031 fails (differs) even with mem hooks registered. Also, it min 2 times slower. I gonna try to figure out when (i.e which commit) it went wrong. It did work in september. |
Can you provide a sample? |
It is not trivial to extract a shellcode size sample. What I see with #2031 is that the phenomenon is consistent with a correct execution flow with missing write mem hook. (i.e it is different from what I saw without #2031: there I experienced a change in execution flow when I enabled an empty read or write hook. Here the execution flow is correct with or without hook registered but when it is registered, some callbacks are missing) This is my current understanding, I keep looking. |
Can you check what happend when you apply following patch:
There is not much I can do about this. The problem is by using |
What happens to self modifying code? Does the optimization break it?
From: PhilippTakacs ***@***.***>
Date: Friday, 25 October 2024 at 4:39 PM
To: unicorn-engine/unicorn ***@***.***>
Cc: lazymio ***@***.***>, Comment ***@***.***>
Subject: Re: [unicorn-engine/unicorn] Execution depends on whether UC_HOOK_MEM_READ/_WRITE is registered (Issue #2041)
Can you check what happend when you apply following patch:
diff --git a/qemu/accel/tcg/cputlb.c b/qemu/accel/tcg/cputlb.c
index 211d0ec1..3de68e67 100644
…--- a/qemu/accel/tcg/cputlb.c
+++ b/qemu/accel/tcg/cputlb.c
@@ -1188,23 +1188,23 @@ tb_page_addr_t get_page_addr_code(CPUArchState *env, target_ulong addr)
static bool uc_mem_hook_installed(struct uc_struct *uc, target_ulong paddr)
{
- if (HOOK_EXISTS_BOUNDED(uc, UC_HOOK_MEM_FETCH_UNMAPPED, paddr))
+ if (HOOK_EXISTS(uc, UC_HOOK_MEM_FETCH_UNMAPPED))
return true;
- if (HOOK_EXISTS_BOUNDED(uc, UC_HOOK_MEM_READ_UNMAPPED, paddr))
+ if (HOOK_EXISTS(uc, UC_HOOK_MEM_READ_UNMAPPED))
return true;
- if (HOOK_EXISTS_BOUNDED(uc, UC_HOOK_MEM_READ, paddr))
+ if (HOOK_EXISTS(uc, UC_HOOK_MEM_READ))
return true;
- if (HOOK_EXISTS_BOUNDED(uc, UC_HOOK_MEM_READ_PROT, paddr))
+ if (HOOK_EXISTS(uc, UC_HOOK_MEM_READ_PROT))
return true;
- if (HOOK_EXISTS_BOUNDED(uc, UC_HOOK_MEM_FETCH_PROT, paddr))
+ if (HOOK_EXISTS(uc, UC_HOOK_MEM_FETCH_PROT))
return true;
- if (HOOK_EXISTS_BOUNDED(uc, UC_HOOK_MEM_READ_AFTER, paddr))
+ if (HOOK_EXISTS(uc, UC_HOOK_MEM_READ_AFTER))
return true;
- if (HOOK_EXISTS_BOUNDED(uc, UC_HOOK_MEM_WRITE, paddr))
+ if (HOOK_EXISTS(uc, UC_HOOK_MEM_WRITE))
return true;
- if (HOOK_EXISTS_BOUNDED(uc, UC_HOOK_MEM_WRITE_UNMAPPED, paddr))
+ if (HOOK_EXISTS(uc, UC_HOOK_MEM_WRITE_UNMAPPED))
return true;
- if (HOOK_EXISTS_BOUNDED(uc, UC_HOOK_MEM_WRITE_PROT, paddr))
+ if (HOOK_EXISTS(uc, UC_HOOK_MEM_WRITE_PROT))
return true;
return false;
}
Also, it min 2 times slower
There is not much I can do about this. The problem is by using tlb_set_dirty most of the unicorn code will be skipped for mem access. This allows faster execution but prevents self modifying code and memory hooks.
—
Reply to this email directly, view it on GitHub<#2041 (comment)>, or unsubscribe<https://github.com/notifications/unsubscribe-auth/AHJULO26TSEQSI4AD2MKGODZ5H7UJAVCNFSM6AAAAABQM7NDKSVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDIMZXGIZDCNJYGU>.
You are receiving this because you commented.Message ID: ***@***.***>
|
As far as I see yes. I assume the problem is when one tb writes two times itself for the first one the tb-cache is cleared and not dirty is set, but for the second write the fast path is taken so no rebuild of the tb. I'm currently still at debugging this to understand what exactly happen and to enable the optimization whenever possible. |
Taking the slow path always gets rid of the dependency of mem hooks being registered.
|
Can you install your memhook in a version before d010357 and check if all mem hooks get called? It confuses me, because tlb_set_dirty() is not called like before but now some mem hooks are missing. |
It seems that the mem callbacks are missing because uc->size_recur_mem is not zero in store_helper(). The stores do happen, as i said, execution flow seems ok. |
before d010357 , mem hooks do happen and executing does not depend on hooks being installed. I made this check under 1) above. so
|
Can you try following patch:
|
|
This makes it fine. (it is "cpu->uc->size_recur_mem = 0;" in fact, I just want to make sure we see the same sourcetree. ?) |
Cool, this seems the root cause. I will check if this hack is really necessary. Btw, does this change fail any unit test? |
Not now, but I can check if I can adjust the test of #2031 for this issue. |
Yes, my bad. |
Thanks. Please go ahead. |
So now I could reproduce the missing hooks, but I have now double hooks for each write which modifies the current tb. This is the asm:
I have debugged this a bit and found that the cpu_loop_exec_tb() is called with the old value of rip. For example after the second mov the execution is restarted with rip as 0x1007 (code starts at 0x1000). This causes the self modifying code to be executed twice. Is this expected behavior? |
I confirm I experience two hooks per hit too. I wonder if it's connected to d010357 as well. |
No, the double execution (with smc) also happens before d010357. |
Using the dev branch head, I am facing an issue where I see that an execution flow that has been recorded in the past differs from it's recorded value. This binary snipplet includes self modifying code. I can get the old behavior only if I register an empty UC_HOOK_MEM_READ or WRITE hook (parameters do not matter, they can be zero). I checked the code and it seems branches regarding the existance of these hooks have been added in 8816883 and 6cc7e1d. And all these seem to be in connection with d010357.
(I made a check: If I remove the appropriate calls to tlb_set_dirty(), it works ok without hooks.)
I do not really understand the connection between tlb_set_dirty() and read/write hooks.
Unfortunately I do not have an example that easily fits here.
The text was updated successfully, but these errors were encountered: