Code:
;it's pseudo-code
;void KillMainThread
KillMainThread:
PUSH 0BB8h ;3000 dec
CALL DWORD PTR DS:[Sleep] ;Sleep is pointer to Kernel32.Sleep
PUSH 1
CALL DWORD PTR DS:[ExitProcess] ;same as sleep
MOV EAX, DWORD PTR DS:[RandomValue] ;EAX = random value, generated while creating code
CALL EAX ;crash thread
RETN
;void CheatDetected
CheatDetected:
PUSH ESP
PUSH 0
PUSH 0
PUSH KillMainThread
PUSH 0
PUSH 0
CALL DWORD PTR DS:[CreateThread]
PUSH 10h ;MB_ICONERROR
PUSH msgTitle
PUSH msgText
PUSH strMU
PUSH 0
CALL DWORD PTR DS:[FindWindowA]
PUSH EAX
CALL DWORD PTR DS:[MessageBoxA]
MOV EAX, DWORD PTR DS:[RandomValue] ;same as KillMainThread
CALL EAX ;and also crash
RETN
;void ScanWindowThread
ScanWindowThread:
PUSH EBX
PUSH ESI
ThreadLoop:
MOV ESI, NumberOfAllCaptions
MOV EBX, FirstCaption ;beginning of caption table
@Loop:
MOV EAX, DWORD PTR DS:[EBX]
PUSH EAX
PUSH 0
CALL DWORD PTR DS:[FindWindowA]
TEST EAX, EAX
JE SHORT Continue
CALL CheatDetected
Continue:
ADD EBX, 4
DEC ESI
JNZ SHORT @Loop
PUSH ScanWindowThreadDelay
CALL DWORD PTR DS:[Sleep]
JMP SHORT ThreadLoop
POP ESI
POP EBX
RETN
;bool ScanProcessMemory(DWORD hHandle)
;Dump in table: 4 bytes for address, 32 bytes for dump data = 36 bytes total
ScanProcessMemory:
PUSH EBP
MOV EBP, ESP
ADD ESP, -8 ;3 dwords on stack to use
PUSH EBX
PUSH ESI
PUSH EDI
XOR EBX, EBX
MOV DWORD PTR SS:[EBP-4], NumberOfDumps
MOV ESI, FirstDump ;table beginning
DumpCheck:
LEA EAX, DWORD PTR SS:[EBP-8]
PUSH EAX ;dwRead
PUSH 20h ;32 dec = buf size
PUSH WorkBuf ;allocated 32 bytes
MOV EAX, DWORD PTR DS:[ESI]
PUSH EAX ;current dump address
MOV EAX, DWORD PTR SS:[EBP+8]
PUSH EAX ;hHandle
CALL DWORD PTR DS:[ReadProessMemory]
MOV DWORD PTR SS:[EBP-8], 20h ;dwRead = 32, it's used to decrease len if compared byte is same
MOV EDI, 20h ;loop- for (i = 32;...)
LEA EAX, DWORD PTR DS:[ESI+4] ;current dump bytes
MOV EDX, WorkBuf ;begining of buf (WorkBuf[j], EDX = j
Compare:
MOV CL, BYTE PTR DS:[EAX] ;CL = Dump[i]->DumpBytes[j]
CMP CL, BYTE PTR DS:[EDX] ;if (Dump[i]->DumpBytes[j] == WorkBuf[j])
JNZ SHORT NotEqual
DEC DWORD PTR SS:[EBP-8] ;--dwRead
NotEqual:
INC EDX
INC EAX
DEC EDI
JNZ SHORT Compare
CMP DWORD PTR SS:[EBP-8], 0 ;if (dwRead = 0) { return true }
JNZ SHORT CheckNext
MOV BL, 1 ;result = true
JMP SHORT ScanProcessMemoryEnd
ADD ESI, 24h ;increase ESI size by 36 bytes
DEC DWORD PTR SS:[EBP-4] ;--i
JNZ SHORT DumpCheck
MOV EAX, EBX ;return result
POP EDI
POP ESI
POP EBX
POP ECX
POP ECX
POP EBP
RETN 4 ;one dword as argument on stack
;void ScanProcessThread
ScanProcessThread:
PUSH EBX
PUSH ESI
PUSH EDI
ADD ESP, -128 ;PROCESSENTRY32 pe
MOV EDI, ESP
SPThreadLoop:
PUSH 0
PUSH 2
CALL DWORD PTR DS:[CreateToolhelp32Snapshot]
MOV EBX, EAX ;hHandle = CreateToolhelp32Snapshot
CMP EAX, -1
JE SHORT InvalidSnapshot ;if (hHandle == INVALID_HANDLE_VALUE) goto InvalidSnapshot
MOV DWORD PTR DS:[EDI], 128 ;pe->dwSize = sizeof(PROCESSENTRY32)
PUSH EDI ;pe
PUSH EBX ;hHandle
CALL DWORD PTR DS:[Process32First]
TEST AL, AL
JE NoMoreProcesses
SnapLoop:
MOV EAX, DWORD PTR DS:[EDI+8] ;EAX = pe->th32ProcessID
PUSH EAX ;pe->th32ProcessID
PUSH 0 ;false
PUSH 1F0FFF ;PROCESS_ALL_ACCESS
CALL DWORD PTR DS:[OpenProcess]
MOV ESI, EAX ;hProcess = OpenProcess
TEST ESI, ESI
JE SHORT OpenProcessFail
PUSH ESI
CALL ScanProcessMemory
TEST AL, AL
JE SHORT ProcessClear
CALL CheatDetected
ProcessClear:
PUSH EDI ;pe
PUSH EBX ;hHandle
CALL DWORD PTR DS:[Process32Next]
TEST AL, AL
JNZ SHORT SnapLoop
InvalidSnapshot:
PUSH EBX ;hHandle
CALL DWORD PTR DS:[CloseHandle]
PUSH ScanProcessThreadDelay
CALL DWORD PTR DS:[Sleep]
JMP SHORT SPThreadLoop
ADD ESP, 128
POP EDI
POP ESI
POP EBX
RETN
;void PlayerBMDCheck
PlayerBMDCheck:
PUSH EBX ;hHandle
PUSH ESI ;fSize
PUSH 0 ;0
PUSH 80h ;NORMAL
PUSH 3 ;OPEN_EXISTING
PUSH 0 ;0
PUSH 11h ;FILE_SHARE_READ
PUSH 80000000h ;GENERIC_READ
PUSH PlayerBMDPath ;Data\Player\player.bmd
CALL DWORD PTR DS:[CreateFileA]
MOV EBX, EAX ;hHandle = CreateFileA
PUSH 0 ;0
PUSH EBX ;hHandle
CALL DWORD PTR DS:[GetFileSize]
MOV ESI, EAX ;fSize = GetFileSize
PUSH EBX ;hHandle
CALL DWORD PTR DS:[CloseHandle]
CMP ESI, DWORD PTR DS:[PlayerBMDSize] ;PlayerBMDSize const
JE PlayerCheckSuccess
PUSH 10h ;MB_ICONERROR
PUSH playermsgTitle
PUSH playermsgText
PUSH strMU
PUSH 0
CALL DWORD PTR DS:[FindWindowA]
PUSH EAX
CALL DWORD PTR DS:[MessageBoxA]
PUSH 1
CALL DWORD PTR DS:[ExitProcess]
POP ESI
POP EBX
RETN
;void AntiCheatStartup
AntiCheatStartup:
PUSH ECX
PUSH strKernel32
CALL DWORD PTR DS:[LoadLibraryA] ;LoadLibraryA address is get from IAT during analyze in creator
MOV DWORD PTR SS:[ESP], EAX ;hModule = LoadLibrary
PUSH strExitProcess
MOV EAX, DWORD PTR SS:[ESP+4]
PUSH EAX ;hModule
CAlL DWORD PTR DS:[GetProcAddress]
MOV DWORD PTR DS:[IAT[0]], EAX ;IAT[0] = GetProcAddress
PUSH strSleep
MOV EAX, DWORD PTR SS:[ESP+4]
PUSH EAX ;hModule
CAlL DWORD PTR DS:[GetProcAddress]
MOV DWORD PTR DS:[IAT[1]], EAX ;IAT[1] = GetProcAddress
... ;it's frequently, I won't write all of this :P
;loaded modules: 2- kernel32.dll and user32.dll, I know I should use loop :P
PUSH ESP
PUSH 0
PUSH 0
PUSH ScanWindowThread
PUSH 0
PUSH 0
CALL DWORD PTR DS:[CreateTrhead]
PUSH ESP
PUSH 0
PUSH 0
PUSH ScanProcessThread
PUSH 0
PUSH 0
CALL DWORD PTR DS:[CreateThread]
CALL PlayerBMDCheck
PUSH OEP ;Original Entry Point
RETN ;JMP OEP by PUSH+RET method
POP EDX
RETN