desinner416 How do I cheat?
Reputation: 0
Joined: 09 Jan 2010 Posts: 1
|
Posted: Wed Nov 30, 2011 6:15 am Post subject: Anti-cheat bypass tutorial |
|
|
Anti-cheat bypass tutorial
by desinner
2011/11/30
Among all anti-cheat function, the most troubling one is SSDT hook.
Hackers usually try to edit game memory, as it is the most useful way of hacking.
However, due to that SSDT hook, some of the system API are being hooked.
When you tried to use some of the memory-editing-related API, say Openprocess, this API will enter Ring0 through using NtOpenProcess in SSDT.
Some anti cheat's don't hook Openprocess, but NtOpenProcess in SSDT table, by editing it in the start-up.
Here is the list of API being hooked:
NtOpenProcess
NtDeviceIoControlFile
NtWriteVirtualMemory
NtOpenSection
NtProtectVirtualMemory
NtTerminateProcess
So what we will do, is simply unhook the SSDT hook.
The programm code for SSDT unhook is attached in below, written in C++.
In case you don't understand the code, google SSDT unhook, many related codes and explaination can be found .
After unhook SSDT, then you can edit memory freely, by using OpenProcess , ReadProcessMemory, etc.
Code:
#include <ntddk.h>
#include "PE.h"
typedef struct _tagSSDT {
PVOID pvSSDTBase;
PVOID pvServiceCounterTable;
ULONG ulNumberOfServices;
PVOID pvParamTableBase;
} SSDT, *PSSDT;
extern PSSDT KeServiceDescriptorTable;
typedef struct _SYSTEM_MODULE
{
ULONG Reserved[2];
ULONG Base;
ULONG Size;
ULONG Flags;
USHORT Index;
USHORT Unknown;
USHORT LoadCount;
USHORT ModuleNameOffset;
CHAR ImageName[256];
} SYSTEM_MODULE_INFORMATION, *PSYSTEM_MODULE_INFORMATION;
typedef struct _SYSTEM_MODULE_INFORMATION
{
ULONG uCount;
SYSTEM_MODULE_INFORMATION aSM[];
}MODULE_LIST,*PMODULE_LIST;
NTSYSAPI
NTSTATUS
NTAPI
ZwQuerySystemInformation(
ULONG SystemInformationClass,
PVOID SystemInformation,
ULONG SystemInformationLength,
PULONG ReturnLength
);
ULONG GetKernelBaseAddress(char* lpszModule)
{
NTSTATUS nResult;
ULONG ulNeededSize, uLoop, uKernelAddr;
PMODULE_LIST pModuleList;
uKernelAddr = 0;
ZwQuerySystemInformation(11, &ulNeededSize, 0, &ulNeededSize);
pModuleList = ExAllocatePool(NonPagedPool, ulNeededSize);
nResult = ZwQuerySystemInformation(11, pModuleList, ulNeededSize, Null);
if (NT_SUCCESS(nResult))
{
//ntoskrnl is always first there
uKernelAddr = pModuleList->aSM[0].Base;
strcpy(lpszModule,"");
strcat(lpszModule,pModuleList->aSM[0].ModuleNameOffset+pModuleList->aSM[0].ImageName);
}
ExFreePool(pModuleList);
return uKernelAddr;
}
ULONG RVAToRaw(PVOID lpBase,ULONG VirtualAddress)
{
IMAGE_DOS_HEADER *pDosHeader;
IMAGE_NT_HEADERS *pNtHeader;
IMAGE_SECTION_HEADER *pSectionHeader;
ULONG NumOfSections,uLoop;
pDosHeader=(IMAGE_DOS_HEADER*)lpBase;
if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE)
return 0;
pNtHeader=(IMAGE_NT_HEADERS*)((unsigned char*)lpBase+pDosHeader->e_lfanew);
NumOfSections=pNtHeader->FileHeader.NumberOfSections;
pSectionHeader = (IMAGE_SECTION_HEADER*)((ULONG)pNtHeader + sizeof(ULONG) + sizeof(IMAGE_FILE_HEADER) + pNtHeader->FileHeader.SizeOfOptionalHeader);
VirtualAddress -= (ULONG)lpBase;
for (uLoop=0;uLoop<NumOfSections;uLoop++)
{
pSectionHeader = (IMAGE_SECTION_HEADER*)((ULONG)pSectionHeader + sizeof(IMAGE_SECTION_HEADER) * uLoop);
if(VirtualAddress>pSectionHeader->VirtualAddress&&VirtualAddress<pSectionHeader->VirtualAddress+pSectionHeader->SizeOfRawData)
{
ULONG Offset = VirtualAddress-pSectionHeader->VirtualAddress + pSectionHeader->PointerToRawData;
return Offset;
}
}
return 0;
}
void DriverUnload(PDRIVER_OBJECT pDriverObj)
{
DbgPrint("DriverUnload!");
}
NTSTATUS DriverEntry( IN PDRIVER_OBJECT theDriverObject, IN PUNICODE_STRING theRegistryPath )
{
NTSTATUS status=STATUS_SUCCESS;
ULONG uKernelMoule,uImageBase,uSSDTCount,uSSDTBase,uSSDTRaw,uLoop,uOldAddress,uNewAddress;
PULONG lpArraySSDT;
char szKernelPath[256];
ANSI_STRING aFileName;
UNICODE_STRING uFileName;
OBJECT_ATTRIBUTES ObjAttr;
IO_STATUS_BLOCK ioStatus;
FILE_POSITION_INFORMATION FilePos;
HANDLE hFile;
theDriverObject->DriverUnload=DriverUnload;
// get system modules
memset(szKernelPath,0,256);
uKernelMoule = GetKernelBaseAddress(szKernelPath);
uImageBase = ((IMAGE_NT_HEADERS*)(uKernelMoule + ((IMAGE_DOS_HEADER*)uKernelMoule)->e_lfanew))->OptionalHeader.ImageBase;
DbgPrint("Kernel ImageBase: 0x%.8X", uImageBase);
DbgPrint("Kernel Base: 0x%.8X", uKernelMoule);
DbgPrint("Kernel Module Path: %s", szKernelPath);
//
uSSDTCount = KeServiceDescriptorTable->ulNumberOfServices;
uSSDTBase = (ULONG)KeServiceDescriptorTable->pvSSDTBase;
DbgPrint("SSDT BaseAddress: 0x%8X, SSDT Count: 0x%X", uSSDTBase, uSSDTCount);
lpArraySSDT = ExAllocatePool(PagedPool, uSSDTCount * sizeof(ULONG));
if (lpArraySSDT == Null) return status;
uSSDTRaw = RVAToRaw(uKernelMoule, uSSDTBase);
DbgPrint("SSDT RAW: 0x%.8X", uSSDTRaw);
if (uSSDTRaw == 0)
{
DbgPrint("SSDT RAW Error");
ExFreePool(lpArraySSDT);
return status;
}
RtlInitAnsiString(&aFileName,szKernelPath);
status = RtlAnsiStringToUnicodeString(&uFileName, &aFileName, TRUE);
if(!NT_SUCCESS(status))
{
DbgPrint("RtlAnsiStringToUnicodeString Error");
ExFreePool(lpArraySSDT);
return status;
}
InitializeObjectAttributes(&ObjAttr, &uFileName, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, Null, NULL);
status = ZwOpenFile(&hFile, FILE_READ_DATA, &ObjAttr, &ioStatus, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_SYNCHRONOUS_IO_NONALERT);
if (NT_SUCCESS(status) && hFile)
{
FilePos.CurrentByteOffset.LowPart = uSSDTRaw;//1000;//uSSDTRaw;
FilePos.CurrentByteOffset.HighPart = 0;
status = ZwSetInformationFile(hFile, &ioStatus, &FilePos, sizeof(FILE_POSITION_INFORMATION), FilePositionInformation);
if (NT_SUCCESS(status))
{
status = ZwReadFile(hFile, NULL, NULL, NULL, &ioStatus, lpArraySSDT, uSSDTCount * sizeof(ULONG), NULL, NULL);
if (NT_SUCCESS(status))
{
for (uLoop=0; uLoop<uSSDTCount; uLoop++)
{
uOldAddress = *(lpArraySSDT + uLoop) - uImageBase + uKernelMoule;
uNewAddress = *((PULONG)uSSDTBase + uLoop);
if (uOldAddress != uNewAddress)
{
DbgPrint("SSDT No.%X, Old: 0x%.8X, New: 0x%.8X", uLoop, uOldAddress, uNewAddress);
__asm
cli
mov eax,cr0
and eax,~0x10000
mov cr0,eax
}
*((PULONG)uSSDTBase + uLoop) = uOldAddress;
//fast_InterlockedExchange(*(uSSDTBase + uLoop), uOldAddress);
__asm
mov eax,cr0
or eax,0x10000
mov cr0,eax
sti
}
}
}
DbgPrint("SSDT TheEnd...");
}
else
DbgPrint("Read File Error!");
}
// else
// DbgPrint("Set File Pos Error!");
if(hFile)
ZwClose(hFile);
}
else
DbgPrint("Open File Error!");
RtlFreeUnicodeString(&uFileName);
ExFreePool(lpArraySSDT);
return status;
}
/////////////////////////////////////////////////////////////////
//PE.H
#ifndef _PE_H_
#define _PE_H_
#define IMAGE_DOS_SIGNATURE 0x5A4D // MZ
#define IMAGE_SIZEOF_SHORT_NAME 8
#define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16
typedef unsigned char BYTE, *PBYTE;
typedef unsigned int UINT, *PUINT;
// headers PE
typedef struct _IMAGE_SECTION_HEADER {
BYTE Name[IMAGE_SIZEOF_SHORT_NAME];
union {
ULONG PhysicalAddress;
ULONG VirtualSize;
} Misc;
ULONG VirtualAddress;
ULONG SizeOfRawData;
ULONG PointerToRawData;
ULONG PointerToRelocations;
ULONG PointerToLinenumbers;
USHORT NumberOfRelocations;
USHORT NumberOfLinenumbers;
ULONG Characteristics;
} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;
#define IMAGE_FIRST_SECTION( ntheader ) ((PIMAGE_SECTION_HEADER) \
((ULONG)ntheader + \
FIELD_OFFSET( IMAGE_NT_HEADERS, OptionalHeader ) + \
((PIMAGE_NT_HEADERS)(ntheader))->FileHeader.SizeOfOptionalHeader \
))
typedef struct _IMAGE_DOS_HEADER {
USHORT e_magic;
USHORT e_cblp;
USHORT e_cp;
USHORT e_crlc;
USHORT e_cparhdr;
USHORT e_minalloc;
USHORT e_maxalloc;
USHORT e_ss;
USHORT e_sp;
USHORT e_csum;
USHORT e_ip;
USHORT e_cs;
USHORT e_lfarlc;
USHORT e_ovno;
USHORT e_res[4];
USHORT e_oemid;
USHORT e_oeminfo;
USHORT e_res2[10];
LONG e_lfanew;
} IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;
typedef struct _IMAGE_FILE_HEADER {
USHORT Machine;
USHORT NumberOfSections;
ULONG TimeDateStamp;
ULONG PointerToSymbolTable;
ULONG NumberOfSymbols;
USHORT SizeOfOptionalHeader;
USHORT Characteristics;
} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;
typedef struct _IMAGE_DATA_DIRECTORY {
ULONG VirtualAddress;
ULONG Size;
} IMAGE_DATA_DIRECTORY,
*PIMAGE_DATA_DIRECTORY;
typedef struct _IMAGE_OPTIONAL_HEADER {
USHORT Magic;
BYTE MajorLinkerVersion;
BYTE MinorLinkerVersion;
ULONG SizeOfCode;
ULONG SizeOfInitializedData;
ULONG SizeOfUninitializedData;
ULONG AddressOfEntryPoint;
ULONG BaseOfCode;
ULONG BaseOfData;
ULONG ImageBase;
ULONG SectionAlignment;
ULONG FileAlignment;
USHORT MajorOperatingSystemVersion;
USHORT MinorOperatingSystemVersion;
USHORT MajorImageVersion;
USHORT MinorImageVersion;
USHORT MajorSubsystemVersion;
USHORT MinorSubsystemVersion;
ULONG Win32VersionValue;
ULONG SizeOfImage;
ULONG SizeOfHeaders;
ULONG CheckSum;
USHORT Subsystem;
USHORT DllCharacteristics;
ULONG SizeOfStackReserve;
ULONG SizeOfStackCommit;
ULONG SizeOfHeapReserve;
ULONG SizeOfHeapCommit;
ULONG LoaderFlags;
ULONG NumberOfRvaAndSizes;
IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
} IMAGE_OPTIONAL_HEADER, *PIMAGE_OPTIONAL_HEADER;
typedef struct _IMAGE_NT_HEADERS {
ULONG Signature;
IMAGE_FILE_HEADER FileHeader;
IMAGE_OPTIONAL_HEADER OptionalHeader;
} IMAGE_NT_HEADERS, *PIMAGE_NT_HEADERS;
// PEB
#pragma pack(4)
typedef struct _PEB_LDR_DATA
{
ULONG Length;
BOOLEAN Initialized;
PVOID SsHandle;
LIST_ENTRY InLoadOrderModuleList;
LIST_ENTRY InMemoryOrderModuleList;
LIST_ENTRY InInitializationOrderModuleList;
} PEB_LDR_DATA, *PPEB_LDR_DATA;
#pragma pack()
typedef struct _PEB_ORIG {
BYTE Reserved1[2];
BYTE BeingDebugged;
BYTE Reserved2[229];
PVOID Reserved3[59];
ULONG SessionId;
} PEB_ORIG, *PPEB_ORIG;
typedef void (*PPEBLOCKROUTINE)(PVOID PebLock);
struct _PEB_FREE_BLOCK {
struct _PEB_FREE_BLOCK *Next;
ULONG Size;
};
typedef struct _PEB_FREE_BLOCK PEB_FREE_BLOCK;
typedef struct _PEB_FREE_BLOCK *PPEB_FREE_BLOCK;
typedef struct _RTL_DRIVE_LETTER_CURDIR {
USHORT Flags;
USHORT Length;
ULONG TimeStamp;
UNICODE_STRING DosPath;
} RTL_DRIVE_LETTER_CURDIR, *PRTL_DRIVE_LETTER_CURDIR;
typedef struct _RTL_USER_PROCESS_PARAMETERS {
ULONG MaximumLength;
ULONG Length;
ULONG Flags;
ULONG DebugFlags;
PVOID ConsoleHandle;
ULONG ConsoleFlags;
HANDLE StdInputHandle;
HANDLE StdOutputHandle;
HANDLE StdErrorHandle;
UNICODE_STRING CurrentDirectoryPath;
HANDLE CurrentDirectoryHandle;
UNICODE_STRING DllPath;
UNICODE_STRING ImagePathName;
UNICODE_STRING CommandLine;
PVOID Environment;
ULONG StartingPositionLeft;
ULONG StartingPositionTop;
ULONG Width;
ULONG Height;
ULONG CharWidth;
ULONG CharHeight;
ULONG ConsoleTextAttributes;
ULONG WindowFlags;
ULONG ShowWindowFlags;
UNICODE_STRING WindowTitle;
UNICODE_STRING DesktopName;
UNICODE_STRING ShellInfo;
UNICODE_STRING RuntimeData;
RTL_DRIVE_LETTER_CURDIR DLCurrentDirectory[0x20];
} RTL_USER_PROCESS_PARAMETERS, *PRTL_USER_PROCESS_PARAMETERS;
typedef struct _PEB {
BOOLEAN InheritedAddressSpace;
BOOLEAN ReadImageFileExecOptions;
BOOLEAN BeingDebugged;
BOOLEAN Spare;
HANDLE Mutant;
PVOID ImageBaseAddress;
PPEB_LDR_DATA LoaderData;
PRTL_USER_PROCESS_PARAMETERS ProcessParameters;
PVOID SubSystemData;
PVOID ProcessHeap;
PVOID FastPebLock;
PPEBLOCKROUTINE FastPebLockRoutine;
PPEBLOCKROUTINE FastPebUnlockRoutine;
ULONG EnvironmentUpdateCount;
PVOID *KernelCallbackTable;
PVOID EventLogSection;
PVOID EventLog;
PPEB_FREE_BLOCK FreeList;
ULONG TlsExpansionCounter;
PVOID TlsBitmap;
ULONG TlsBitmapBits[0x2];
PVOID ReadOnlySharedMemoryBase;
PVOID ReadOnlySharedMemoryHeap;
PVOID *ReadOnlyStaticServerData;
PVOID AnsiCodePageData;
PVOID OemCodePageData;
PVOID UnicodeCaseTableData;
ULONG NumberOfProcessors;
ULONG NtGlobalFlag;
BYTE Spare2[0x4];
LARGE_INTEGER CriticalSectionTimeout;
ULONG HeapSegmentReserve;
ULONG HeapSegmentCommit;
ULONG HeapDeCommitTotalFreeThreshold;
ULONG HeapDeCommitFreeBlockThreshold;
ULONG NumberOfHeaps;
ULONG MaximumNumberOfHeaps;
PVOID **ProcessHeaps;
PVOID GdiSharedHandleTable;
PVOID ProcessStarterHelper;
PVOID GdiDCAttributeList;
PVOID LoaderLock;
ULONG OSMajorVersion;
ULONG OSMinorVersion;
ULONG OSBuildNumber;
ULONG OSPlatformId;
ULONG ImageSubSystem;
ULONG ImageSubSystemMajorVersion;
ULONG ImageSubSystemMinorVersion;
ULONG GdiHandleBuffer[0x22];
ULONG PostProcessInitRoutine;
ULONG TlsExpansionBitmap;
BYTE TlsExpansionBitmapBits[0x80];
ULONG SessionId;
} PEB, *PPEB;
|
|