flat assembler
Message board for the users of flat assembler.
Index
> Windows > Interesting Time Problem Goto page Previous 1, 2, 3 |
Author |
|
asmcoder 21 Jun 2009, 22:50
[content deleted]
Last edited by asmcoder on 14 Aug 2009, 14:50; edited 1 time in total |
|||
21 Jun 2009, 22:50 |
|
arigity 21 Jun 2009, 23:07
asmcoder wrote: and i belive 2x nop is better that 1 mov. no asmcoder wrote: and why edi nit mov eax,eax, eax operations are faster. no asmcoder wrote: and they sould make some hook chain. no |
|||
21 Jun 2009, 23:07 |
|
asmcoder 21 Jun 2009, 23:10
[content deleted]
Last edited by asmcoder on 14 Aug 2009, 14:50; edited 1 time in total |
|||
21 Jun 2009, 23:10 |
|
LocoDelAssembly 22 Jun 2009, 14:52
r22, asmcoder, all: I think I have an SMP safe implementation this time. The problem that remains unsolved is the scenario in which multiple threads attempt to patch the same API simultaneously (really expectable considering how improbable is having even one doing this?). Anyway, if you don't restore protection the problem is gone (no other patcher thread will make another doing the same crash). Another possibility could be using SEH and catch the page fault exception, however I'm not sure if the exception triggering will be transparently enough to the target process in any situation, that must be investigated.
Code: proc hook_GetSystemTimeAsFileTime uses ebx esi local oldProtect: DWORD PATCH_SIZE = 7 mov ebx, [GetSystemTimeAsFileTime] cmp word [ebx], $FF8B ; "mov edi, edi" but not encoded as FASM do jne .unhookable ; (Trivially) lea esi, [ebx-5] invoke VirtualProtect, esi, PATCH_SIZE, PAGE_EXECUTE_READWRITE, addr oldProtect test eax, eax jz .protFail mov byte [ebx-5], $E9 mov eax, hook sub eax, ebx mov [ebx-4], eax mov byte [ebx], $84 ; TEST opcode ("mov edi, edi" is transformed into "test BH, BH") ; This is done to avoid issues on cores that already fetched half of "mov edi, edi" ; (in that case the instruction crossed a 16-byte boundary) invoke GetCurrentProcess invoke FlushInstructionCache, eax, esi, PATCH_SIZE test eax, eax jz .flushFail ; At this point the five NOPs cannot be incorrectly cached by any processor and also no processor should still have ; "mov edi, edi" half fetched. mov byte [ebx+1], $F9 ; $-5 but also transforms "test BH, BH" into "test CL, BH" mov byte [ebx], $EB ; JMP rel8 opcode ; JMP $-5 Fully assembled at this point. Some cores may still execute "test CL, BH" so we call FlushInstructionCache again invoke FlushInstructionCache, eax, esi, PATCH_SIZE ; Comment if you don't need to make the hook effective as soon as possible. call .protect mov eax, TRUE ; In case VirtualProtect failed .return: ret .flushFail: call .protect .unhookable: .protFail: mov eax, FALSE jmp .return .protect: invoke VirtualProtect, esi, PATCH_SIZE, [oldProtect], addr oldProtect ret endp In case of attempting to implement a code to be safe with multiple patchers then .protect should be changed to this: Code: .protect: cmp [oldProtect], PAGE_EXECUTE_READWRITE je .leftUnprotected invoke VirtualProtect, esi, PATCH_SIZE, [oldProtect], addr oldProtect .leftUnprotected: ret Anyone had checked Microsoft Detours to see how this is done? [edit]The multiple patchers scenario can't be solved by just leaving the pages with write access as mentioned above. Another patcher may update half of the rel32 of the JMP that replaces the five NOPs. This situation should happen only if the operand is at an unaligned address crossing a cache line boundary (or perhaps just by crossing a 16-byte boundary).[/edit] Last edited by LocoDelAssembly on 23 Jun 2009, 21:03; edited 1 time in total |
|||
22 Jun 2009, 14:52 |
|
windwakr 22 Jun 2009, 15:09
For the lazy people,
Detours is here Guide on detours lol, trampoline functions....where do they come up with this stuff.... |
|||
22 Jun 2009, 15:09 |
|
asmcoder 23 Jun 2009, 00:03
[content deleted]
Last edited by asmcoder on 14 Aug 2009, 14:50; edited 1 time in total |
|||
23 Jun 2009, 00:03 |
|
LocoDelAssembly 23 Jun 2009, 00:38
Quote:
But according to the documentation, when you commit the changes it claims to take care of the threads' instruction pointers (I don't know how, I haven't compiled anything yet). Note however that Detours can hook functions not starting with "mov edi, edi" nor having the five NOPs on top, so clearly it must control the threads somehow because an incomplete update will obviously provide room for crashing. Quote: exception on memory access - i dont think its good idea. Well, it happens all the time with pages currently swapped. The difference is that the exception will be forwarded into the process' thread doing this fault. Not an issue if this is all that Windows will do about it. What I don't know is whether another thread in the process will be able to know about this somehow or not, if that could happen then it is not transparent. Quote:
What? Quote:
Which one? PS: Just one extra technique I forgot to mention, assuming that the other potential patchers perform the update like us AND we are going to patch a function residing in a non-writable page then we could use VirtualProtect as a semaphore. If oldProtect returns write access then it means there is someone else trying to patch (or the page was writable from the beginning), in that case we just leave without doing anything else. |
|||
23 Jun 2009, 00:38 |
|
arigity 23 Jun 2009, 02:13
asmcoder wrote:
microsoft detours is meant to be able to detour anywhere, not just api functions. asmcoder wrote:
and your basing this on.....? i do not see how multiple threads attempting to hook the same function at the same time is very likely but should it occur i see no reason why it should cause a crash. if your truly worried about multi-threading issues you can simply suspend all other threads while yours is hooking and resume afterwards. incidentally for additional hooking reference, there is also apihooks.com |
|||
23 Jun 2009, 02:13 |
|
LocoDelAssembly 23 Jun 2009, 03:21
Quote:
This idea could be problematic (that's the reason I've avoided commenting it). If for some reason your patcher thread takes too long to get CPU-time you will keep the target process suspended for too long. If you are ready to face the possible consequences of doing this then I think you could also just assume that you will be the only one patching the API. Also, catching the exceptions in the patcher thread perhaps is better (and thinking about it perhaps a SEH handler should always be installed as if the patcher crash it should try to avoid by all means to make the crash process-wide). |
|||
23 Jun 2009, 03:21 |
|
arigity 23 Jun 2009, 15:25
LocoDelAssembly wrote:
you don't need to suspend them for the entire duration of your threads existence, only while hooking, and specifically only while writing the hook. at most it might be a few milliseconds. |
|||
23 Jun 2009, 15:25 |
|
asmcoder 23 Jun 2009, 17:30
[content deleted]
Last edited by asmcoder on 14 Aug 2009, 14:50; edited 1 time in total |
|||
23 Jun 2009, 17:30 |
|
arigity 23 Jun 2009, 17:41
your hopeless, dozens of applications from anti-virus software to network monitoring tools and firewalls use hooking frequently, its only unsafe when you don't know what your doing.
|
|||
23 Jun 2009, 17:41 |
|
asmcoder 23 Jun 2009, 17:49
[content deleted]
Last edited by asmcoder on 14 Aug 2009, 14:50; edited 1 time in total |
|||
23 Jun 2009, 17:49 |
|
LocoDelAssembly 23 Jun 2009, 18:40
Quote:
Yes, I considered stopping all the others threads at exactly that point but I still sustain the idea. You need few milliseconds, but you can't be sure the OS will give them to you quickly. (I have simulated a similar situation in the concurrent queue thread started by r22). I'm supposing a very extreme situation of course, but since we are supposedly searching for a all-times safe solution this one is too invasive. Quote:
For sure "mov edi, edi" was placed for hot patching, so the fact you don't know how to safely patch is no evidence that this can't be done. I have been noting you are worried about multiple writes or writing when someone else is reading. Do you know that LOCK prefix is there for the read-modify-write instructions? If n cores execute simultaneously "mov [globalVar], eax" the final result will be that [globarVar] will have the contents of the EAX register of some of the processors (but not a mixture nor the write aborted, whatever, you just can't tell in advance which final value you will have but you know that it will be exactly the contents of the EAX register of some core). The situation is different in the case of "add [globalCounter], eax", in this case multiple outcomes are possible, you could have the result of the last core that finally completed the execution, the sum of 2 cores, etc, while with "lock add [globalCounter], eax" you will get for sure globarVar equal to the summation of the EAX register of all the cores that executed the instruction. BTW, reading in between of writings does not impose any problem either, at worst we read an out of date value but not trash. [edit]The paragraph above assumed globarVar and globalCounter dword aligned. If that is not the case then a mixture of the last two memory write cycles perhaps occur (e.g., one part of the dword has the contents of EAX[31:24] and the rest of the bytes from EAX[23:0] but both parts comes from different processors). However, as far as I can recall, using LOCK would not solve this problem. (Using XCHG since LOCK MOV is invalid)[/edit] |
|||
23 Jun 2009, 18:40 |
|
r22 04 Aug 2009, 17:59
Back On Topic.
The hack does NOT work on Windows Server 2003. I assume this is the cause... Quote:
The TermServ running on XP doesn't seem to care but Windows Server failed on CreateRemoteThread. So, impersonating a session? Or is there a "Startup" folder for service accounts? Other ideas? |
|||
04 Aug 2009, 17:59 |
|
r22 04 Aug 2009, 18:49
UPDATE The hack works on the test server (Windows Server 2003).
I just created an ASPX page that runs the EXE using System.Diagnostics so it runs in the same Windows session. |
|||
04 Aug 2009, 18:49 |
|
Goto page Previous 1, 2, 3 < Last Thread | Next Thread > |
Forum Rules:
|
Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.
Website powered by rwasa.