-
Notifications
You must be signed in to change notification settings - Fork 411
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
Detecting x64dbg with SetWinEventHook #48
Comments
Just adding more info.
NTSTATUS __stdcall __ClientCallWinEventProc(int (__stdcall **a1)(int, int, int, int, int, int, int))
{
int (__stdcall *v1)(int, int, int, int, int, int, int); // ST18_4@1
int (__stdcall *v2)(int, int, int, int, int, int, int); // ST14_4@1
int (__stdcall *v3)(int, int, int, int, int, int, int); // ST10_4@1
int (__stdcall *v4)(int, int, int, int, int, int, int); // ST0C_4@1
int (__stdcall *v5)(int, int, int, int, int, int, int); // ST08_4@1
int (__stdcall *v6)(int, int, int, int, int, int, int); // ST04_4@1
int (__stdcall *v7)(int, int, int, int, int, int, int); // ST00_4@1
int (__stdcall *v8)(int, int, int, int, int, int, int); // esi@1
int Result; // [sp+8h] [bp-1Ch]@1
int v11; // [sp+10h] [bp-14h]@1
int v12; // [sp+18h] [bp-Ch]@1
int v13; // [sp+1Ch] [bp-8h]@1
v11 = 0;
v12 = 0;
v13 = 0;
v1 = a1[7];
v2 = a1[6];
v3 = a1[5];
v4 = a1[4];
v5 = a1[3]; // this is the HWND
v6 = a1[2];
v7 = a1[1];
v8 = *a1;
__guard_check_icall_fptr(*a1);
Result = v8(v7, v6, v5, v4, v3, v2, v1);
return NtCallbackReturn(&Result, 0x18u, 0);
} Since typedef
VOID
(NTAPI
*t_KiUserCallbackDispatcher)(
IN ULONG ApiNumber,
IN PVOID InputBuffer,
IN ULONG InputLength
);
t_KiUserCallbackDispatcher KiUserCallbackDispatcher_Trampoline;
VOID NTAPI KiUserCallbackDispatcher_Hook(ULONG ApiNumber, PVOID InputBuffer, ULONG InputLength) {
if (ApiNumber == 0x58 && InputBuffer) {
HWND &hwnd = *(HWND*)((UINT_PTR)InputBuffer + 0xC);
if (hwnd) {
HANDLE hHandle = NtUserQueryWindow(hwnd, WindowProcess);
if (isProtectedPid(hHandle)) {
hwnd = NULL;
}
}
}
return KiUserCallbackDispatcher_Trampoline(ApiNumber, InputBuffer, InputLength);
} I'm not sure if this |
I see some ways to approach this, but I'm not a great fan of any of them:
I have some other musings w.r.t. the above that relate to ScyllaHide in general. For example, hooking Similarly I noticed that the index of |
Personally I never actually run PDBReader because nobody uses unreliable methods like this to detect x64dbg, but adding the disassembly in the ScyllaHide plugin sounds like a good alternative approach. Also you can just rename |
Yeah, likewise. The only commercial protector I know of that (I think) uses this kind of functionality is Obsidium. Not that I studied in great detail, I only noticed that my paid-for copy of NTLite wouldn't start if IDA was running. I sent the author an email to kindly tell him to go fuck himself and that was that. |
Interestingly (or maybe not so), using Scyllahide with OllyDbg, the debugger window title is changed to match the profile being used by the plugin. And so when editing the code above to test for "OllyDbg", the debugger is not detected by the SetWinEventHook executable if the debugger is already running. ;) |
Could you try if it detects x64dbg if you rename the executable to something random? |
With the specific code used above (edited to check for "Ollydbg" as well), the detection "does not" occur if the debugger executable is is renamed to something random (123.exe as the example). I tested x64dbg and Ollydbg yielding identical results. |
Heh. Yeah, checks like these are very frail and not that many protectors actually use them (because they are so easy to circumvent) unless you run the protector with the "paranoid" setting enabled. The issue is though that there are very many ways to query things about windows, desktops, the mouse, anything GUI related really, from win32k.sys (through user32.dll or win32u.dll nowadays in Win 10). The OP already listed several, but a more exhaustive list would be good. Also I'm not sure about how to go about adding this to SH since it could be some 10 or more hooks. I looked at the various user32.dlls "through the ages" (from XP x86 to Win 10 x64) and unfortunately there are too many small differences to make a heuristic approach with a disassembler (like I talked about above) work I think. There is also the problem that if you want to add a new win32k syscall hook, you have to find a new heuristic and make it work on all OSes. I still want to get rid of PDBReader and NtApiCollection eventually though, so I currently have a WIP project that uses a table of hardcoded syscall numbers (based on SyscallTables). This sounds like it is impossible to maintain, and it would be, except on builds >= 14393 of Win 10 we can get the syscall numbers from exported names in win32u.dll the same way you can already do it with ntdll. The remaining syscall numbers are fixed since the OSes have already been released. So in pseudocode the function to get an RVA looks something like this:
I have a prototype app of this and it works on all OS/bitness combinations I've tested, but integrating it into ScyllaHide will take some time since there is a lot of code to replace. |
Sample source code using SetWinEventHook to detect x64dbg:
The detection happens as soon as you move the mouse over other windows. This sends events to the application with the
HWND
and you can check if its title is flagged or not.You could counter this by hooking:
You could also hook
NtUserSetWinEventHook
to get the address of the WinEventProc callback and then hook it to erase the passed HWND. According to the documentation, it should be safe to erase it:Type: HWND
Handle to the window that generates the event, or NULL if no window is associated with the event. For example, the mouse pointer is not associated with a window.
The text was updated successfully, but these errors were encountered: