DLL_THREAD_ATTACH monitoring in the protection DLL is only good for remote thread creation style injections into your process, not things like APC injection etc. Bypassing DLL_THREAD_ATTACH would be easy too, like calling DisableThreadLibraryCalls on this "protection DLL" prior to creating your injection thread, since there is no such API available to work with foreign processes I have written a small example below which extends DisableThreadLibraryCalls to work with any process, not just your own. After calling this example the DLL_THREAD_ATTACH injection detection method is useless, one could easily use standard CRT method for injection again without any alerts. I think some stupid game protection uses this method to detect injections, very weak :lol:
Code: Select allconst
LDR_DISABLE_THREAD_CALLS = $00040000;
function DisableThreadLibraryCallsEx(const hProcess: ULONG; bDisable: BOOL; hMod: HMODULE = $FFFF): BOOL;
var
bRet: ULONG;
PebAddr: ULONG;
Peb: TPeb;
Ldr: TPebLdrData;
LdrMod: TLdrModule;
pFlink: Pointer;
pHead: Pointer;
dwFlags: ULONG;
dwModule: ULONG;
dwPatch: ULONG;
begin
dwModule := 0;
dwPatch := 0;
if (hProcess > 0) then
begin
PebAddr := PebBaseAddress(hProcess);
if NtReadVirtualMemory(hProcess, Ptr(PebAddr), @Peb, sizeof(Peb), @bRet) = 0 then
begin
if (Peb.Ldr <> nil) and (Peb.LoaderLock <> nil) and
(NtReadVirtualMemory(hProcess, Peb.Ldr, @Ldr, sizeof(Ldr), @bRet) = 0) then
begin
pFlink := Ldr.InLoadOrderModuleList.Flink;
pHead := pFlink;
while (NtReadVirtualMemory(hProcess, pFlink, @LdrMod, sizeof(LdrMod), @bRet) = 0) do
begin
if LdrMod.InLoadOrderModuleList.Flink = pHead then
Break;
if (hMod = $FFFF) or (hMod = LdrMod.BaseAddress) then
begin
if NtReadVirtualMemory(hProcess, Ptr(DWORD(pFlink) + $34), @dwFlags, sizeof(dwFlags), @bRet) = 0 then
begin
if (bDisable) then
dwFlags := (dwFlags or LDR_DISABLE_THREAD_CALLS)
else
dwFlags := (dwFlags xor LDR_DISABLE_THREAD_CALLS);
if WriteProcessMemory(hProcess, Ptr(DWORD(pFlink) + $34), @dwFlags, sizeof(dwFlags), bRet) then
inc(dwPatch);
inc(dwModule);
end;
if (hMod <> $FFFF) then
Break;
end;
pFlink := LdrMod.InLoadOrderModuleList.Flink;
end;
end;
end;
end;
result := (dwModule > 0) and (dwModule = dwPatch);
end;