flat assembler
Message board for the users of flat assembler.

Index > Windows > Interesting Time Problem

Goto page Previous  1, 2, 3
Author
Thread Post new topic Reply to topic
r22



Joined: 27 Dec 2004
Posts: 805
r22
asmcoder wrote:
and btw:
mov edi,edi was done specyficly for hotfixes, right?
so why instead ms didnt put there 2 nops?


If they only used NOPs it would be more difficult to tell where a function starts. So MOV EDI,EDI was used for clarity, so it's easier to look at dumps where you might not have PE import info to know where the functions begin.

Code:
;;padding nops
NOP
NOP
NOP
patching nops
NOP
NOP
NOP
NOP
NOP
MOV EDI,EDI ;;<--where the function begins
    


Code:
;;padding nops
NOP
NOP
NOP
;;patching nops
NOP
NOP
NOP
NOP
NOP
NOP ;; <-this is where it really starts
NOP
PUSH EBP ;; <-does it start here???? Looks like it, but "NOPe" :D
MOV EBP,ESP
    
Post 21 Jun 2009, 22:13
View user's profile Send private message AIM Address Yahoo Messenger Reply with quote
asmcoder



Joined: 02 Jun 2008
Posts: 784
asmcoder
[content deleted]


Last edited by asmcoder on 14 Aug 2009, 14:50; edited 1 time in total
Post 21 Jun 2009, 22:50
View user's profile Send private message Reply with quote
arigity



Joined: 22 Dec 2008
Posts: 45
arigity
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
Post 21 Jun 2009, 23:07
View user's profile Send private message Reply with quote
asmcoder



Joined: 02 Jun 2008
Posts: 784
asmcoder
[content deleted]


Last edited by asmcoder on 14 Aug 2009, 14:50; edited 1 time in total
Post 21 Jun 2009, 23:10
View user's profile Send private message Reply with quote
LocoDelAssembly
Your code has a bug


Joined: 06 May 2005
Posts: 4633
Location: Argentina
LocoDelAssembly
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
Post 22 Jun 2009, 14:52
View user's profile Send private message Reply with quote
windwakr



Joined: 30 Jun 2004
Posts: 827
Location: Michigan, USA
windwakr
For the lazy people,
Detours is here
Guide on detours
lol, trampoline functions....where do they come up with this stuff....

_________________
----> * <---- My star, won HERE
Post 22 Jun 2009, 15:09
View user's profile Send private message Reply with quote
asmcoder



Joined: 02 Jun 2008
Posts: 784
asmcoder
[content deleted]


Last edited by asmcoder on 14 Aug 2009, 14:50; edited 1 time in total
Post 23 Jun 2009, 00:03
View user's profile Send private message Reply with quote
LocoDelAssembly
Your code has a bug


Joined: 06 May 2005
Posts: 4633
Location: Argentina
LocoDelAssembly
Quote:

i did and its done wrong. overwriting 5 (not 2) bytes on active memory.

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:

BUT you can make breakpoint exception and check where it occured.

What? Confused

Quote:

oh well, it also wont solve 1 prolem.

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.
Post 23 Jun 2009, 00:38
View user's profile Send private message Reply with quote
arigity



Joined: 22 Dec 2008
Posts: 45
arigity
asmcoder wrote:
Quote:
Anyone had checked Microsoft Detours to see how this is done?

i did and its done wrong. overwriting 5 (not 2) bytes on active memory.


microsoft detours is meant to be able to detour anywhere, not just api functions.

asmcoder wrote:

api hooking cant be done.


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
Post 23 Jun 2009, 02:13
View user's profile Send private message Reply with quote
LocoDelAssembly
Your code has a bug


Joined: 06 May 2005
Posts: 4633
Location: Argentina
LocoDelAssembly
Quote:

if your truly worried about multi-threading issues you can simply suspend all other threads while yours is hooking and resume afterwards.

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).
Post 23 Jun 2009, 03:21
View user's profile Send private message Reply with quote
arigity



Joined: 22 Dec 2008
Posts: 45
arigity
LocoDelAssembly wrote:
Quote:

if your truly worried about multi-threading issues you can simply suspend all other threads while yours is hooking and resume afterwards.

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).


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.
Post 23 Jun 2009, 15:25
View user's profile Send private message Reply with quote
asmcoder



Joined: 02 Jun 2008
Posts: 784
asmcoder
[content deleted]


Last edited by asmcoder on 14 Aug 2009, 14:50; edited 1 time in total
Post 23 Jun 2009, 17:30
View user's profile Send private message Reply with quote
arigity



Joined: 22 Dec 2008
Posts: 45
arigity
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.
Post 23 Jun 2009, 17:41
View user's profile Send private message Reply with quote
asmcoder



Joined: 02 Jun 2008
Posts: 784
asmcoder
[content deleted]


Last edited by asmcoder on 14 Aug 2009, 14:50; edited 1 time in total
Post 23 Jun 2009, 17:49
View user's profile Send private message Reply with quote
LocoDelAssembly
Your code has a bug


Joined: 06 May 2005
Posts: 4633
Location: Argentina
LocoDelAssembly
Quote:

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.

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:

EOT, there is NO way of safe hooking. Editing shared memory without exclusive access is BAD.

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]
Post 23 Jun 2009, 18:40
View user's profile Send private message Reply with quote
r22



Joined: 27 Dec 2004
Posts: 805
r22
Back On Topic.
The hack does NOT work on Windows Server 2003.

I assume this is the cause...
Quote:

Terminal Services isolates each terminal session by design. Therefore, CreateRemoteThread fails if the target process is in a different session than the calling process.

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?
Post 04 Aug 2009, 17:59
View user's profile Send private message AIM Address Yahoo Messenger Reply with quote
r22



Joined: 27 Dec 2004
Posts: 805
r22
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.
Post 04 Aug 2009, 18:49
View user's profile Send private message AIM Address Yahoo Messenger Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  
Goto page Previous  1, 2, 3

< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2020, Tomasz Grysztar. Also on YouTube, Twitter.

Website powered by rwasa.