I wonder how is that possible.
I found debugger detection in TLS Callback function - there is conditional jump after some check.
When I step over it with debugger and modify ZF flag to bypass detection everything works fine. But when I try to patch this jump to the opposite (jne to je) application freezes and bombards me with OutputDebugString.
I don't save patch to the file, I patch it while process is in memory.
I was interested how this patch is detected, so I set Hardware Access Breakpoints on bytes that I patched, and then run it. Breakpoints weren't hit, and yet application changed it behavior just like it always do when I patch.
Notice that difference in code flow have nothing to do with this detection since when I modify ZF flag application works fine.
So I am very baffled, how does this application detects that patch, when it doesn't apparently access memory that I patched? Or is Hardware Access Breakpoint imperfect? I am interested in general ideas, how would you go about detecting whether your code was patched or not, without hitting hardware breakpoints.