Salut à toi visiteur !
Inscris toi en moins de 10 secondes pour profitez pleinement du site et partager avec la communauté ! S'inscrire


Source Thread Hijacking (x86/x64 support)


#1
Hello,

Si vous surveillez CSGO en ce moment vous avez certainement vu l'implémentation de routines de détections d’exécution de code, que ce soit le grand classique LoadLibrary mais aussi une technique utilisée depuis déjà un long moment, le manual mapping, en checkant les nouveaux threads & en vérifiant s'ils sont legit au sein du module Smile 

[Image: ep48Hny.png]

Du coup je vous partage le code qui était encore utilisé récemment sur Royal Hack afin d'hijack un thread pour faire nos magouilles Smile
 
Code :
 
InjectionResult CRemoteAccess::HijackThread(LPCVOID lpAddress, DWORD dwEipOffset, CEvent& event) const
{
InjectionResult result = { InjectionCode::HijackFailure, 0 };

// open the target thread
NTSTATUS ntStatus = 0;
HANDLE hThread = OpenThreadById(
m_dwThreadId,
THREAD_SUSPEND_RESUME | THREAD_GET_CONTEXT | THREAD_SET_CONTEXT | THREAD_QUERY_INFORMATION,
&ntStatus);
if(hThread != NULL)
{
ULONG previousSuspendCount;

// suspend the target thread
ntStatus = Syscall_NtSuspendThread(hThread, &previousSuspendCount);
if(NT_SUCCESS(ntStatus))
{
CONTEXT context;
context.ContextFlags = CONTEXT_CONTROL;

// get the target thread context
ntStatus = Syscall_NtGetContextThread(
hThread,
&context);
if(NT_SUCCESS(ntStatus))
{
// save the old eip
#ifdef _X86_
DWORD_PTR dwOldEip = context.Eip;
#elif defined _AMD64_
DWORD_PTR dwOldEip = context.Rip;
#endif

// write the old eip
ntStatus = Syscall_NtWriteVirtualMemory(
m_hProcess,
MakePtr(PVOID, lpAddress, dwEipOffset),
&dwOldEip,
sizeof(dwOldEip),
NULL);
if(NT_SUCCESS(ntStatus))
{
// redirect the EIP
context.ContextFlags = CONTEXT_CONTROL;
#ifdef _X86_
context.Eip = (DWORD)lpAddress;
#elif defined _AMD64_
context.Rip = (DWORD64)lpAddress;
#endif

// set our modified thread context
ntStatus = Syscall_NtSetContextThread(
hThread,
&context);
if(NT_SUCCESS(ntStatus))
{
result.code = InjectionCode::Injected;
result.error = 0;
}
else
{
result.code = InjectionCode::SetContextFailure;
result.error = ntStatus;
}
}
else
{
result.code = InjectionCode::WriteFailure;
result.error = ntStatus;
}
}
else
{
result.code = InjectionCode::GetContextFailure;
result.error = ntStatus;
}

// resume the target thread
ntStatus = Syscall_NtResumeThread(hThread, &previousSuspendCount);
if(result.code == InjectionCode::Injected && !NT_SUCCESS(ntStatus))
{
result.code = InjectionCode::ResumeFailure;
result.error = ntStatus;
}
}
else
{
result.code = InjectionCode::SuspendFailure;
result.error = ntStatus;
}

// close the target thread
Syscall_NtClose(hThread);
}
else
{
result.code = InjectionCode::OpenFailure;
result.error = ntStatus;
}

if(result.code == InjectionCode::Injected)
{
// wait for the hijack to be done
if(!event.WaitMultiple(m_hProcess))
{
result.code = InjectionCode::WaitEventError;

// read the exit code
g_imports.Modules.Kernel32.GetExitCodeProcess(m_hProcess, &result.error);
}
}

return result;
}

Du coup c'est plutôt straightfoward, & compatible 32/64bit automatiquement.

Le concept est ultra simple & facile à implémenter comme vous le voyez.
[+] 1 utilisateur dit Merci à UnstucK pour ce message

#2
tapez sur google le nom du jeu plus tcheat et le premier resultat est valide

#3
[quote = "UnstucK" pid = '44791' dateline = '1597756051']
Hello,

Si vous surveillez CSGO en ce moment vous avez certainement vu l'implémentation de routines de détections d’exécution de code, que ce soit le grand classique LoadLibrary mais aussi une technique utilisée depuis déjà un long moment, le manual mapping, en checkant les nouveaux threads & en vérifiant s'ils sont legit au sein du module Smile 

[Image: ep48Hny.png]

Du coup je vous partage le code qui était encore utilisé récemment sur Royal Hack afin d'hijack un thread pour faire nos magouilles Smile
 
[code]
 
InjectionResult CRemoteAccess::HijackThread(LPCVOID lpAddress, DWORD dwEipOffset, CEvent& event) const
{
InjectionResult result = { InjectionCode::HijackFailure, 0 };

// open the target thread
NTSTATUS ntStatus = 0;
HANDLE hThread = OpenThreadById(
m_dwThreadId,
THREAD_SUSPEND_RESUME | THREAD_GET_CONTEXT | THREAD_SET_CONTEXT | THREAD_QUERY_INFORMATION,
&ntStatus);
if(hThread != NULL)
{
ULONG previousSuspendCount;

// suspend the target thread
ntStatus = Syscall_NtSuspendThread(hThread, &previousSuspendCount);
if(NT_SUCCESS(ntStatus))
{
CONTEXT context;
context.ContextFlags = CONTEXT_CONTROL;

// get the target thread context
ntStatus = Syscall_NtGetContextThread(
hThread,
&context);
if(NT_SUCCESS(ntStatus))
{
// save the old eip
#ifdef _X86_
DWORD_PTR dwOldEip = context.Eip;
#elif defined _AMD64_
DWORD_PTR dwOldEip = context.Rip;
#endif

// write the old eip
ntStatus = Syscall_NtWriteVirtualMemory(
m_hProcess,
MakePtr(PVOID, lpAddress, dwEipOffset),
&dwOldEip,
sizeof(dwOldEip),
NULL);
if(NT_SUCCESS(ntStatus))
{
// redirect the EIP
context.ContextFlags = CONTEXT_CONTROL;
#ifdef _X86_
context.Eip = (DWORD)lpAddress;
#elif defined _AMD64_
context.Rip = (DWORD64)lpAddress;
#endif

// set our modified thread context
ntStatus = Syscall_NtSetContextThread(
hThread,
&context);
if(NT_SUCCESS(ntStatus))
{
result.code = InjectionCode :: Injected;
result.error = 0;
}
else
{
result.code = InjectionCode :: SetContextFailure;
result.error = ntStatus;
}
}
else
{
result.code = InjectionCode :: WriteFailure;
result.error = ntStatus;
}
}
else
{
result.code = InjectionCode :: GetContextFailure;
result.error = ntStatus;
}

// resume the target thread
ntStatus = Syscall_NtResumeThread (hThread, & previousSuspendCount);
if (result.code == InjectionCode :: Injected &&! NT_SUCCESS (ntStatus))
{
result.code = InjectionCode :: ResumeFailure;
result.error = ntStatus;
}
}
else
{
result.code = InjectionCode :: SuspendFailure;
result.error = ntStatus;
}

// close the target thread
Syscall_NtClose (hThread);
}
else
{
result.code = InjectionCode :: OpenFailure;
result.error = ntStatus;
}

if (result.code == InjectionCode :: Injected)
{
// wait for the hijack to be done
if (! event.WaitMultiple (m_hProcess))
{
result.code = InjectionCode :: WaitEventError;

// read the exit code
g_imports.Modules.Kernel32.GetExitCodeProcess (m_hProcess, & result.error);
}
}

return result;
}
[/coded]

So it's rather straightfoward, & 32 / 64bit compatible automatically.

The concept is ultra simple & easy to implement as you can see.
[/ quote]

very nice


Atteindre :