First, HellsHall checks whether the syscall address is hooked and tries to retrieve the syscall number by checking the presence of the following bytes:
0x4C, 0x8B, 0xD1, 0xB8 which represent mov r10,rcx && mov eax,SSn. This is how every syscall should start.
However, this logic fails when the function we are trying to obtain SSN number is hooked. Additional logic is added to check if the function is hooked:
If yes:
- Perform searching for low + index * UP ( 32)
- Perrform search for low - index * DOWN ( -32 )
Updated to indirect syscall by jmp RANDOM_RANGE_ADDRESS to execute syscall within ntdll.dll address
- Fetch syscall instruction from
win32u.dll - New function added:
FetchWin32uSyscallInstprovided:-
Syscall obfuscation - The global variable g_SYSCALL_OPCODE is derived from the syscall instruction's opcode (0x050F) XOR'd with 0x25. This operation obscures the original syscall instruction's opcode, making it less susceptible to detection by static scanners designed to identify direct syscall attempts. The use of the volatile keyword ensures that the XOR decryption operation is carried out at runtime rather than compile time, preventing the static exposure of the syscall instruction's opcode.
-
Returning different syscall instructions - To enhance evasion, the function tries to return a different syscall instruction each time it is invoked. This behavior is governed by the iSeed and iCounter variables. iSeed represents a randomly generated value during runtime, which the function utilizes to determine when to return. In other words, FetchWin32uSyscallInst will provide the address of the syscall instruction at the iSeed-th position, ensuring that it does not return the first encountered syscall instruction address on each call.
-
- Unhook hooked DLL
- Payload encryption