Модератор форума
-
Автор темы
- #1
Всем привет и сегодня мы будем оптимизировать поиск паттернов в вашем чите
Оптимизация заключается в том, что мы будем сканировать только секции с кодом вместо всего модуля
Некоторые структуры:
Приколы для структуры CModule
Сам поиск паттерна:
Ради универсальности под разные игры секции выбираются по их характеристикам, а не названию
Плюсы или минусы хуй знает мне похуй:
Кто не знает как получать PEB:
Изначально делалось для x64, но на x86 проблем быть не должно
Оптимизация заключается в том, что мы будем сканировать только секции с кодом вместо всего модуля
Некоторые структуры:
C++:
struct CModule
{
DWORD64 m_dwBase = 0;
DWORD m_dwSize = 0;
void Initialize( const wchar_t* m_wszModuleName );
};
template< typename T, int m_iSize = 512 >
struct CVector
{
private:
int m_nSize;
T m_aData[ m_iSize ];
public:
CVector< T, m_iSize >( )
{
m_nSize = 0;
ZeroMemory( m_aData, sizeof( T ) * m_iSize );
}
void Push( T m_iValue )
{
m_aData[ m_nSize++ ] = m_iValue;
}
T* Data( )
{
return m_aData;
}
int Size( )
{
return m_nSize;
}
T& operator[]( int m_iIndex )
{
return m_aData[ m_iIndex ];
}
};
C++:
DWORD64 Utils::GetModuleBase( const wchar_t* m_wszModuleName )
{
for ( PLIST_ENTRY m_pListEntry = reinterpret_cast< PLIST_ENTRY64 >( m_pPEB->Ldr->InLoadOrderModuleList.Flink );
m_pListEntry != &m_pPEB->Ldr->InLoadOrderModuleList;
m_pListEntry = reinterpret_cast< PLIST_ENTRY >( m_pListEntry->Flink ) )
{
PLDR_DATA_TABLE_ENTRY m_pEntry = CONTAINING_RECORD( m_pListEntry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks );
if ( m_pEntry->BaseDllName.Buffer && !Utils::wcsicmp( m_wszModuleName, m_pEntry->BaseDllName.Buffer ) )
return m_pEntry->DllBase;
}
return 0;
}
DWORD Utils::GetModuleSize( DWORD64 m_dwImageBase )
{
if ( !m_dwImageBase )
return 0;
PIMAGE_DOS_HEADER m_pDos = reinterpret_cast< PIMAGE_DOS_HEADER >( m_dwImageBase );
return reinterpret_cast< PIMAGE_NT_HEADERS >( m_dwImageBase + m_pDos->e_lfanew )->OptionalHeader.SizeOfImage;
}
void Utils::CModule::Initialize( const wchar_t* m_wszModuleName )
{
m_dwBase = Utils::GetModuleBase( m_wszModuleName );
m_dwSize = Utils::GetModuleSize( m_dwBase );
Log( "[+] %ws info: 0x%llX \t0x%lX\n", m_wszModuleName, m_dwBase, m_dwSize );
}
C++:
void PatternToBytes( Utils::CVector< int >& m_aBytes, const char* m_szPattern )
{
char* m_pStart = const_cast< char* >( m_szPattern );
char* m_pEnd = const_cast< char* >( m_szPattern ) + Utils::strlen( m_szPattern );
for ( char* m_pCurrent = m_pStart; m_pCurrent < m_pEnd; ++m_pCurrent )
{
if ( *m_pCurrent == '?' )
{
++m_pCurrent;
if ( *m_pCurrent == '?' )
++m_pCurrent;
m_aBytes.Push( -1 );
}
else
{
m_aBytes.Push( Utils::strtoul( m_pCurrent, &m_pCurrent, 16 ) );
}
}
}
DWORD64 Utils::FindPattern( CModule m_Module, const char* m_szPattern )
{
DWORD m_dwSizeOfImage = m_Module.m_dwSize;
CVector< int > m_aBytes = CVector< int >( );
PatternToBytes( m_aBytes, m_szPattern );
int m_dwSize = m_aBytes.Size( );
IMAGE_NT_HEADERS* m_pNt = reinterpret_cast< IMAGE_NT_HEADERS* >( m_Module.m_dwBase +
reinterpret_cast< IMAGE_DOS_HEADER* >( m_Module.m_dwBase )->e_lfanew );
CVector< IMAGE_SECTION_HEADER*, 10 > m_aSections; // ну 10 и 10 че бухтеть то
IMAGE_SECTION_HEADER* m_pCurrentSection = IMAGE_FIRST_SECTION( m_pNt );
for ( int i = 0; i != m_pNt->FileHeader.NumberOfSections; ++i, ++m_pCurrentSection )
if ( m_pCurrentSection->Characteristics & IMAGE_SCN_CNT_CODE ||
m_pCurrentSection->Characteristics & IMAGE_SCN_MEM_EXECUTE )
m_aSections.Push( m_pCurrentSection );
for ( int c = 0; c < m_aSections.Size( ); ++c )
{
BYTE* m_pScanBytes = reinterpret_cast< BYTE* >( m_Module.m_dwBase + m_aSections[ c ]->VirtualAddress );
for ( DWORD i = 0; i < m_aSections[ c ]->SizeOfRawData - m_dwSize; ++i )
{
bool m_bFound = true;
for ( int j = 0; j < m_dwSize; ++j )
{
if ( m_pScanBytes[ i + j ] != m_aBytes[ j ] && m_aBytes[ j ] != -1 )
{
m_bFound = false;
break;
}
}
if ( m_bFound )
return ( DWORD64 )( &m_pScanBytes[ i ] );
}
}
return 0;
}
Плюсы или минусы хуй знает мне похуй:
- отсутствие CRT
- нет вызовов WinAPI
Кто не знает как получать PEB:
m_pPEB __readfsdword( 0x30 ); // x86
m_pPEB = __readgsqword( 0x60 ); // x64
Изначально делалось для x64, но на x86 проблем быть не должно