![Page 1: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/1.jpg)
![Page 2: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/2.jpg)
GAMEHACKINGDevelopingAutonomousBotsforOnlineGames
NickCano
SanFrancisco
![Page 3: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/3.jpg)
GAMEHACKING.Copyright©2016byNickCano.
Allrightsreserved.Nopartofthisworkmaybereproducedortransmittedinanyformorbyanymeans,electronicormechanical,includingphotocopying,recording,orbyanyinformationstorageorretrievalsystem,withoutthepriorwrittenpermissionofthecopyrightownerandthepublisher.
PrintedinUSA
Firstprinting
2019181716123456789
ISBN-10:1-59327-669-9ISBN-13:978-1-59327-669-0
Publisher:WilliamPollockProductionEditor:LaurelChunCoverIllustration:RyanMilnerInteriorDesign:OctopodStudiosDevelopmentalEditor:JenniferGriffith-DelgadoTechnicalReviewer:StephenLawlerCopyeditor:RachelMonaghanCompositor:LaurelChunProofreader:PaulaL.FlemingIndexer:BIMCreatives,LLC
Forinformationondistribution,translations,orbulksales,pleasecontactNoStarchPress,Inc.directly:NoStarchPress,Inc.2458thStreet,SanFrancisco,CA94103phone:415.863.9900;[email protected]
LibraryofCongressCataloging-in-PublicationData
Cano,Nick,author.Gamehacking:developingautonomousbotsforonlinegames/byNickCano.pagescmIncludesindex.Summary:"Ahands-onguidetohackingcomputergames.Showsprogrammershowtodissectcomputergamesandcreatebotstoaltertheirgamingenvironment.Coversthebasicsofgamehacking,includingreverseengineering,assemblycodeanalysis,programmaticmemorymanipulation,persistenthacks,responsivehacks,andcodeinjection."--Providedbypublisher.ISBN978-1-59327-669-0--ISBN1-59327-669-91.Intelligentagents(Computersoftware)2.Internetprogramming.3.Internetgames--Programming.4.Hacking.I.Title.QA76.76.I58C362016
![Page 4: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/4.jpg)
005.8--dc23
2015036294
NoStarchPressandtheNoStarchPresslogoareregisteredtrademarksofNoStarchPress,Inc.Otherproductandcompanynamesmentionedhereinmaybethetrademarksoftheirrespectiveowners.Ratherthanuseatrademarksymbolwitheveryoccurrenceofatrademarkedname,weareusingthenamesonlyinaneditorialfashionandtothebenefitofthetrademarkowner,withnointentionofinfringementofthetrademark.
Theinformationinthisbookisdistributedonan“AsIs”basis,withoutwarranty.Whileeveryprecautionhasbeentakeninthepreparationofthiswork,neithertheauthornorNoStarchPress,Inc.shallhaveanyliabilitytoanypersonorentitywithrespecttoanylossordamagecausedorallegedtobecauseddirectlyorindirectlybytheinformationcontainedinit.
![Page 5: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/5.jpg)
AbouttheAuthorNickCanowrotehisfirstscriptsforopensourcegameserverswhenhewas12andstartedabusinesssellinghisbotswhenhewas16.Hehasbeenapartofthegame-hackingcommunityeversinceandadvisesgamedevelopersanddesignersonbestpracticestoprotecttheirgamesagainstbots.Nickalsohasyearsofexperienceindetectinganddefendingagainstmalware,andhehasspokenatmanyconferencesabouthisresearchandtools.
![Page 6: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/6.jpg)
AbouttheTechnicalReviewerStephenLawleristhefounderandpresidentofasmallcomputersoftwareandsecurityconsultingfirm.Hehasbeenactivelyworkingininformationsecurityforover10years,primarilyinreverseengineering,malwareanalysis,andvulnerabilityresearch.HewasamemberoftheMandiantmalwareanalysisteamandassistedwithhigh-profilecomputerintrusionsaffectingseveralFortune100companies.StephenalsodevelopedandteachesthePracticalARMExploitationclass,whichhasbeenofferedatBlackHatandseveralothersecurityconferencesforthepastfiveyears.
![Page 7: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/7.jpg)
BRIEFCONTENTS
ForewordbyDr.JaredDeMott
Acknowledgments
Introduction
PART1:TOOLSOFTHETRADEChapter1:ScanningMemoryUsingCheatEngine
Chapter2:DebuggingGameswithOllyDbg
Chapter3:ReconnaissancewithProcessMonitorandProcessExplorer
PART2:GAMEDISSECTIONChapter4:FromCodetoMemory:AGeneralPrimer
Chapter5:AdvancedMemoryForensics
Chapter6:ReadingfromandWritingtoGameMemory
PART3:PROCESSPUPPETEERINGChapter7:CodeInjection
Chapter8:ManipulatingControlFlowinaGame
PART4:CREATINGBOTSChapter9:UsingExtrasensoryPerceptiontoWardOffFogofWar
Chapter10:ResponsiveHacks
Chapter11:PuttingItAllTogether:WritingAutonomousBots
![Page 8: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/8.jpg)
Chapter12:StayingHidden
Index
![Page 9: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/9.jpg)
CONTENTSINDETAIL
FOREWORDbyDr.JaredDeMott
ACKNOWLEDGMENTS
INTRODUCTIONPrerequisitesfortheReaderABriefGameHackingHistoryWhyHackGames?HowThisBookIsOrganizedAbouttheOnlineResourcesHowtoUseThisBook
PART1TOOLSOFTHETRADE
1SCANNINGMEMORYUSINGCHEATENGINEWhyMemoryScannersAreImportantBasicMemoryScanningCheatEngine’sMemoryScanner
ScanTypesRunningYourFirstScanNextScansWhenYouCan’tGetaSingleResultCheatTables
MemoryModificationinGamesManualModificationwithCheatEngine
![Page 10: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/10.jpg)
TrainerGeneratorPointerScanning
PointerChainsPointerScanningBasicsPointerScanningwithCheatEnginePointerRescanning
LuaScriptingEnvironmentSearchingforAssemblyPatternsSearchingforStrings
ClosingThoughts
2DEBUGGINGGAMESWITHOLLYDBGABriefLookatOllyDbg’sUserInterfaceOllyDbg’sCPUWindow
ViewingandNavigatingaGame’sAssemblyCodeViewingandEditingRegisterContentsViewingandSearchingaGame’sMemoryViewingaGame’sCallStack
CreatingCodePatchesTracingThroughAssemblyCodeOllyDbg’sExpressionEngine
UsingExpressionsinBreakpointsUsingOperatorsintheExpressionEngineWorkingwithBasicExpressionElementsAccessingMemoryContentswithExpressions
OllyDbgExpressionsinActionPausingExecutionWhenaSpecificPlayer’sNameIsPrintedPausingExecutionWhenYourCharacter’sHealthDrops
OllyDbgPlug-insforGameHackersCopyingAssemblyCodewithAsm2ClipboardAddingCheatEnginetoOllyDbgwithCheatUtilityControllingOllyDbgThroughtheCommandLineVisualizingControlFlowwithOllyFlow
![Page 11: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/11.jpg)
ClosingThoughts
3RECONNAISSANCEWITHPROCESSMONITORANDPROCESSEXPLORERProcessMonitor
LoggingIn-GameEventsInspectingEventsintheProcessMonitorLogDebuggingaGametoCollectMoreData
ProcessExplorerProcessExplorer’sUserInterfaceandControlsExaminingProcessPropertiesHandleManipulationOptions
ClosingThoughts
PART2GAMEDISSECTION
4FROMCODETOMEMORY:AGENERALPRIMERHowVariablesandOtherDataManifestinMemory
NumericDataStringDataDataStructuresUnionsClassesandVFTables
x86AssemblyCrashCourseCommandSyntaxProcessorRegistersTheCallStackImportantx86InstructionsforGameHacking
![Page 12: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/12.jpg)
ClosingThoughts
5ADVANCEDMEMORYFORENSICSAdvancedMemoryScanning
DeducingPurposeFindingthePlayer’sHealthwithOllyDbgDeterminingNewAddressesAfterGameUpdates
IdentifyingComplexStructuresinGameDataThestd::stringClassThestd::vectorClassThestd::listClassThestd::mapClass
ClosingThoughts
6READINGFROMANDWRITINGTOGAMEMEMORYObtainingtheGame’sProcessIdentifier
ObtainingProcessHandlesWorkingwithOpenProcess()
AccessingMemoryWorkingwithReadProcessMemory()andWriteProcessMemory()AccessingaValueinMemorywithReadProcessMemory()andWriteProcessMemory()WritingTemplatedMemoryAccessFunctions
MemoryProtectionDifferentiatingx86WindowsMemoryProtectionAttributesChangingMemoryProtection
AddressSpaceLayoutRandomizationDisablingASLRtoSimplifyBotDevelopmentBypassingASLRinProduction
ClosingThoughts
![Page 13: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/13.jpg)
PART3PROCESSPUPPETEERING
7CODEINJECTIONInjectingCodeCaveswithThreadInjection
CreatinganAssemblyCodeCaveTranslatingtheAssemblytoShellcodeWritingtheCodeCavetoMemoryUsingThreadInjectiontoExecutetheCodeCave
HijackingaGame’sMainThreadtoExecuteCodeCavesBuildingtheAssemblyCodeCaveGeneratingSkeletonShellcodeandAllocatingMemoryFindingandFreezingtheMainThread
InjectingDLLsforFullControlTrickingaProcessintoLoadingYourDLLAccessingMemoryinanInjectedDLLBypassingASLRinanInjectedDLL
ClosingThoughts
8MANIPULATINGCONTROLFLOWINAGAMENOPingtoRemoveUnwantedCode
WhentoNOPHowtoNOP
HookingtoRedirectGameExecutionCallHookingVFTableHookingIATHookingJumpHooking
ApplyingCallHookstoAdobeAIR
![Page 14: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/14.jpg)
AccessingtheRTMPGoldmineHookingtheRTMPSencode()FunctionHookingtheRTMPSdecode()FunctionPlacingtheHooks
ApplyingJumpHooksandVFHookstoDirect3DTheDrawingLoopFindingtheDirect3DDeviceWritingaHookforEndScene()WritingaHookforReset()What’sNext?
ClosingThoughts
PART4CREATINGBOTS
9USINGEXTRASENSORYPERCEPTIONTOWARDOFFFOGOFWARBackgroundKnowledgeRevealingHiddenDetailswithLighthacks
AddingaCentralAmbientLightSourceIncreasingtheAbsoluteAmbientLightCreatingOtherTypesofLighthacks
RevealingSneakyEnemieswithWallhacksRenderingwithZ-BufferingCreatingaDirect3DWallhackFingerprintingtheModelYouWanttoReveal
GettingaWiderFieldofVisionwithZoomhacksUsingNOPingZoomhacksScratchingtheSurfaceofHookingZoomhacks
DisplayingHiddenDatawithHUDsCreatinganExperienceHUD
![Page 15: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/15.jpg)
UsingHookstoLocateDataAnOverviewofOtherESPHacksClosingThoughts
10RESPONSIVEHACKSObservingGameEvents
MonitoringMemoryDetectingVisualCuesInterceptingNetworkTraffic
PerformingIn-GameActionsEmulatingtheKeyboardSendingPackets
TyingthePiecesTogetherMakingthePerfectHealerResistingEnemyCrowd-ControlAttacksAvoidingWastedMana
ClosingThoughts
11PUTTINGITALLTOGETHER:WRITINGAUTONOMOUSBOTSControlTheoryandGameHackingStateMachinesCombiningControlTheoryandStateMachines
ABasicHealerStateMachineAComplexHypotheticalStateMachineErrorCorrection
PathfindingwithSearchAlgorithmsTwoCommonSearchTechniquesHowObstaclesDisruptSearchesAnA*SearchAlgorithmWhenA*SearchesAreParticularlyUseful
![Page 16: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/16.jpg)
CommonandCoolAutomatedHacksLootingwithCavebotsAutomatingCombatwithWarbots
ClosingThoughts
12STAYINGHIDDENProminentAnti-CheatSoftwareThePunkBusterToolkit
Signature-BasedDetectionScreenshotsHashValidation
TheESEAAnti-CheatToolkitTheVACToolkit
DNSCacheScansBinaryValidationFalsePositives
TheGameGuardToolkitUser-ModeRootkitKernel-ModeRootkit
TheWardenToolkitCarefullyManagingaBot’sFootprint
MinimizingaBot’sFootprintMaskingYourFootprintTeachingaBottoDetectDebuggersAnti-DebuggingTechniques
DefeatingSignature-BasedDetectionDefeatingScreenshotsDefeatingBinaryValidationDefeatinganAnti-CheatRootkitDefeatingHeuristicsClosingThoughts
![Page 17: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/17.jpg)
INDEX
![Page 18: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/18.jpg)
FOREWORD
Nickisgreat.Wefirsthititoffinalltherightandwrongways,asyoucanimagine.I’vebeeninthesecurityfieldawhile;he’salittleyounger.I’vehadtheschooling,whereashe’snotmuchforcollege.I’mafaithguy,andhe’snot.Theinterestingthingisthatnoneofthatmatters;we’vehadablastanyway.Age,race,gender,degrees—whenitcomestogaming,hacking,andcoding,noonecares!
Nickgetsitdone.He’sfun.He’sbrilliant.He’shardworking.Andprobablymostpertinent:he’soneoftherarefewwhounderstandtheintersectionofgaming,hacking,andcoding.He’sworkedinthisnicheandcreatedprofitablebots.
Inthisfirst-of-its-kindbook,Nickwalksyouthroughwhatitmeanstopullapartgames.Heteachesyouthesoftwareinvestigationtoolsandtricksofthetrade.You’lllearnaboutgameinternals,howtopullthemapart,andhowtomodifyplay.Forexample,Nickteacheshowtoavoidanti-cheatsothatyoucanautomateplay.Wouldn’titbecooltohaveyourownbotthatcollectsexperience,gold,items,andmore—allwhileyou’reaway?
Everwonderhowthecheaterscheat?Everwantedtopatchorprotectyourgame?Grabacoffee,crackopenyourlaptop,andenjoy.
Blessingstoyouandyours,
Dr.JaredDeMottSecurityExpert&SoftwareBuilder
![Page 19: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/19.jpg)
ACKNOWLEDGMENTS
Writingthisbookwasanamazingjourney,andIcouldn’thavedoneitalone.NoStarchPresshasbeenextremelysupportiveandworkedcloselywithmetotakethisbookfromconcepttoreality.Inparticular,I’dliketothankmydevelopmentaleditor,JenniferGriffith-Delgado,andmyproductioneditor,LaurelChun.BillPollock,TylerOrtman,AlisonLaw,andtherestoftheteamatNoStarcharewonderfulpeople,andI’mpleasedtohaveworkedwiththem.
ThankstocopyeditorRachelMonaghan,proofreaderPaulaL.Fleming,andtechnicalreviewerStephenLawler.ThanksalsotomyfriendsCavitt“synt4x”GloverandVadimKotov,whotookthetimetoskimsomechaptersbeforesubmission,andtoJaredDeMottforwritingthebook’sforeword.
I’dliketothankallofthepeopleonTPForumswhotookmeinwhenIwasjustanaivekidandhelpedmelearnhowtohackgames.Inparticular,IowemythankstoJoseph“jo3bingham”Bingham,IanObermiller,andjeremic,whoallhadasignificantinfluenceonmyprogressionasahacker,andtoTPForumsfounderJosh“Zyphrus”Hartzell,whohelpedmefindmyconfidenceandskillswhenmyfuturelookeditsbleakest.
Thanksalsotomyentireforumstaffandeverycustomerwhohaseverusedmybots.Andfinally,thankstomyfamily,friends,andcolleagues,whohavebeenfunandsupportiveandhelpedshapemeintothemanIamtoday.
![Page 20: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/20.jpg)
INTRODUCTION
Acommonmisconceptionintheworldofonlinegamingistheideathattheonlygameyoucanplayistheoneinthetitle.Infact,gamehackersenjoyplayingthegamethathidesbehindthecurtain:acat-and-mousegameofwitsbetweenthemandthegamedevelopers.Whilegamehackersworktoreverseengineergamebinaries,automateaspectsofgameplay,andmodifygamingenvironments,gamedeveloperscombatthehacker-designedtools(normallyreferredtoasbots)usinganti-reversingtechniques,botdetectionalgorithms,andheuristicdatamining.
Asthebattlebetweengamehackersanddevelopershasprogressed,thetechnicalmethodsimplementedbybothparties—manyofwhichresembletechniquesutilizedbymalwaredevelopersandantivirusvendors—haveevolved,becomingmorecomplex.Thisbookhighlightsthefightputupbygamehackers,andtheadvancedmethodstheyhaveengineeredtomanipulategameswhilesimultaneouslyeludinggamedevelopersinthedarkcornersoftheirownsoftware.
Althoughthebookfocusesonteachingyoutodeveloptoolsthatwouldlikelybeconsideredanuisanceorevenmaliciousbygamingcompanies,you’llfindthatmanyofthetechniquesareusefulfordevelopmentoftoolsthatareperfectlybenignandneutral.Furthermore,theknowledgeofhowthesetechniquesareimplementediskeyforthegamedevelopersworkingtopreventtheiruse.
![Page 21: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/21.jpg)
PrerequisitesfortheReaderThisbookdoesnotaimtoteachyousoftwaredevelopment,andthereforeassumesthatyouhave,atminimum,asolidsoftwaredevelopmentbackground.ThisbackgroundshouldincludefamiliaritywithnativeWindows-baseddevelopment,aswellaslightexperiencewithgamedevelopmentandmemorymanagement.Whiletheseskillswillbeenoughforyoutofollowthisbook,experiencewithx86assemblyandWindowsinternalswillensurethatdetailsofmoreadvancedimplementationsarenotlostonyou.
Furthermore,sincealltheadvancedhacksdiscussedinthisbookrelyoncodeinjection,anabilitytowritecodeinanativelanguagelikeCorC++isamust.AlloftheexamplecodeinthisbookiswritteninC++andcanbecompiledwithMicrosoftVisualC++ExpressEdition.(YoucandownloadMSVC++ExpressEditionfromhttp://www.visualstudio.com/en-US/products/visual-studio-express-vs.)
NOTE
Otherlanguagesthatcompiletonativecode,suchasDelphi,arealsocapableofinjection,butIwillnotdiscusstheminthisbook.
ABriefGameHackingHistorySincethedawnofonlinePCgamingintheearly1980s,anongoingwarofwitsbetweengamehackersandgamedevelopershasbeentakingplace.Thisseeminglyendlessstrugglehaspromptedgamedeveloperstodevotecountlesshourstowardpreventinghackersfromtakingtheirgamesapartandgreasingbetweenthegears.Thesehackers,whofightbackwiththeirsophisticatedstealthimplementations,havemanymotivations:customizedgraphics,betterperformance,easeofuse,autonomousplay,in-gameassetacquisition,and,ofcourse,real-lifeprofit.
Thelate1990sandearly2000swerethegoldenageofgamehacking,whenonlinePCgamesbecameadvancedenoughtodrawlargecrowdsbutwerestillsimpleenoughtoeasilyreverseengineerandmanipulate.Online
![Page 22: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/22.jpg)
gamesthatcameoutduringthistime,suchasTibia(January1997),Runescape(January2001),andUltimaOnline(September1997),wereheavilytargetedbybotdevelopers.Thedevelopersofthesegamesandotherslikethemstillstruggletodaytocontrolthemassivecommunitiesofbotdevelopersandbotusers.Thegamedevelopers’lackofactionandthehackers’tenacityhavenotonlycompletelyshatteredtheeconomieswithinthegames,buthavealsoproducedathrivingfor-profitindustryfocusedaroundbotdevelopmentandbotdefense.
Intheyearssincethegoldenage,morematuregamecompaniesstartedtakingbotdefenseveryseriously.Thesecompaniesnowhavededicatedteamsfocusedondevelopingbotpreventionsystems,andmanyalsoviewbotsasalegalmatterandwillnothesitatetobanishplayerswhousebotsandsuethebotdeveloperswhoprovidedthem.Asaresult,manygamehackershavebeenforcedtodevelopadvancedstealthtechniquestokeeptheiruserssafe.
Thiswarwageson,andthenumbersonbothsidesofthefightwillcontinuetogrowasonlinegamingbecomesmoreprevalentoverthecomingyears.Majorgamedevelopersarepursuinghackerswithendlessdetermination,evenslammingsomegamehackinggiantswithmultimillion-dollarlawsuits.Thismeansthatgamehackerswhoareseriousabouttheirbusinessmusteithertargetsmallergamingcompanies,oranonymouslymarkettheirproductsfromtheshadowsinordertoescapeprosecution.Fortheforeseeablefuture,gamehackingandbotdevelopmentwillcontinuetogrowintoalargerandmorelucrativeindustryforthosegamehackersboldenoughtotaketherisks.
WhyHackGames?Asidefromitsobviousallureandchallengingnature,gamehackinghassomepracticalandprofitablepurposes.Everyday,thousandsofnoviceprogrammersexperimentwithsmall-scalegamehackingasawaytoautomatemonotonoustasksorperformmenialactions.ThesescriptkiddieswilluseautomationtoolslikeAutoItfortheirsmall,relativelyharmlesshacks.Ontheotherhand,professionalgamehackers,backedbytheirlargetoolkitsandyearsofprogrammingexperience,willdevotehundredsofhourstothedevelopmentofadvancedgamehacks.Thesetypesofgamehacks,whicharethefocusofthisbook,areoftencreatedwiththeintentofmaking
![Page 23: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/23.jpg)
whicharethefocusofthisbook,areoftencreatedwiththeintentofmakinglargeamountsofmoney.
Gamingisahugeindustrythatgenerated$22.4billioninsalesin2014,accordingtotheEntertainmentSoftwareAssociation.Ofthetensofmillionsofplayerswhoplaygamesdaily,20percentplaymassivelymultiplayeronlinerole-playinggames(MMORPGs).TheseMMORPGsoftenhavethousandsofplayerswhotradevirtualgoodswithinthrivingin-gameeconomies.Playersoftenhaveaneedforin-gameassetsandarewillingtobuytheseassetswithreal-worldmoney.Consequently,MMORPGplayersendupdevelopinglargecommunitiesthatprovidegold-for-cashservices.Theseservicesoftengoasfarasenforcingexchangeratesfromin-gamegoldtoreal-worldcurrencies.
Totakeadvantageofthis,gamehackerswillcreatebotsthatarecapableofautomaticallyfarminggoldandlevelingcharacters.Then,dependingontheirgoal,hackerswilleithersetupmassivegoldfarmsandselltheirin-gameprofits,orperfectandselltheirsoftwaretoplayerswhowishtoseamlesslyobtainlevelsandgoldwithminimalinterference.DuetothemassivecommunitiessurroundingpopularMMORPGs,thesegamehackerscanmakebetweensixandsevenfiguresannually.
WhileMMORPGsprovidethelargestattacksurfaceforhackers,theyhavearelativelysmallaudienceoverall.About38percentofgamersfavorreal-timestrategy(RTS)andmassiveonlinebattlearena(MOBA)games,andanother6percentplayprimarilyfirst-personshooter(FPS)games.Thesecompetitiveplayerversusplayer(PvP)gamescollectivelyrepresent44percentofthegamingmarketandprovidegreatrewardstodeterminedgamehackers.
PvPgamesareoftenepisodicinnature;eachmatchisanisolatedgame,andthere’stypicallynotmuchprofitableprogressionforbottingawayfromkeyboard(AFK).Thismeansthat,insteadofrunninggoldfarmsorcreatingautonomousbotstolevelupcharacters,hackerswillcreatereactivebotsthatassistplayersincombat.
Thesehighlycompetitivegamesareaboutskillandtactics,andmostplayersparticipatetoprovetheirabilitytothemselvesandothers.Asaconsequence,thenumberofpeopleseekingbotsforPvP-typegamesissubstantiallylowerthanyou’dfindinthegrind-heavyworldofMMORPGs.Nevertheless,hackerscanstillmakeaprettypennysellingtheirPvPbots,whichareoftenmucheasiertodevelopthanfull-fledgedautonomousbots.
![Page 24: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/24.jpg)
HowThisBookIsOrganizedThisbookissplitintofourparts,eachofwhichfocusesonadifferentcoreaspectofgamehacking.InPart1:ToolsoftheTrade,you’llgetaboxfulloftoolstohelpyouhackgames.
•Chapter1:ScanningMemoryUsingCheatEnginewillteachyouhowtoscanagame’smemoryforimportantvaluesusingCheatEngine.
•InChapter2:DebuggingGameswithOllyDbg,you’llgetacrashcourseindebuggingandreverseengineeringwithOllyDbg.Theskillsyoulearnherewillbeextremelyusefulwhenyoustartmakingadvancedbotsandinjectingcode.
•Towrapup,Chapter3:ReconnaissancewithProcessMonitorandProcessExplorer,willteachyouhowtousetworeconnaissancetoolstoinspecthowgamesinteractwithfiles,otherprocesses,thenetwork,andtheoperatingsystem.
TheonlineresourcesforeachchapterinPart1includecustombinariesIcreatedtogiveyouasafeplacetotestandhoneyournewlydiscoveredskills.
Onceyou’recomfortablewitheverywrenchandhammer,Part2:GameDissection,willteachyouhowtogetunderthehoodandfigureouthowgameswork.
•InChapter4:FromCodetoMemory:AGeneralPrimer,you’lllearnwhatagame’ssourcecodeanddatalooklikeoncecompiledintoagamebinary.
•Chapter5:AdvancedMemoryForensicsbuildsontheknowledgeyou’llgainfromChapter4.You’lllearnhowtoscanmemoryandusedebuggingtoseamlesslylocatetrickymemoryvaluesanddissectcomplexclassesandstructures.
•Finally,Chapter6:ReadingfromandWritingtoGameMemoryshowsyouhowtoreadandmodifydatawithinarunninggame.
Thesechaptersprovidelotsofin-depthproof-of-conceptexamplecodethatyoucanusetoverifyeverythingyouread.
![Page 25: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/25.jpg)
InPart3:ProcessPuppeteering,you’llbecomeapuppeteerasyoulearnhowtoturnanygameintoamarionette.
•BuildingontheskillsfromParts1and2,Chapter7:CodeInjectiondescribeshowtoinjectandexecuteyourowncodeintheaddressspaceofagame.
•Onceyou’vemasteredinjection,Chapter8:ManipulatingControlFlowinaGamewillteachyouhowtouseinjectiontointercept,modify,ordisableanyfunctioncallmadebyagame,andwillwrapupwithsomeusefulreal-worldexamplesforthecommonlibrariesAdobeAIRandDirect3D.
Tocomplementyourpuppeteeringclasses,thesechaptersareaccompaniedbythousandsoflinesofproduction-readycodethatyoucanuseasaboilerplatelibraryforafuturebot.
InPart4:CreatingBots,you’llseehowtocombineyourtoolbox,dissectionabilities,puppeteeringskills,andsoftwareengineeringbackgroundtocreatepowerfulbots.
•Chapter9:UsingExtrasensoryPerceptiontoWardOffFogofWarexploreswaystomakeagamedisplayusefulinformationthatisn’texposedbydefault,suchasthelocationsofhiddenenemiesandtheamountofexperienceyouearnperhour.
•Chapter10:ResponsiveHacksshowscodepatternsyoucanusetodetectin-gameevents,likedecreasesinhealth,andtomakebotsthatreacttothoseeventsfasterthanhumanplayers.
•Chapter11:PuttingItAllTogether:WritingAutonomousBotsrevealshowbotsthatplaygameswithouthumaninteractionwork.Automatedbotscombinecontroltheory,statemachines,searchalgorithms,andmathematicalmodels,andthischapterisacrashcourseinthosetopics.
•InChapter12:StayingHidden,you’lllearnaboutsomeofthehigh-leveltechniquesyoucanusetoescapeandevadeanysystemthatwouldinterferewithyourbots.
Asyou’veprobablycometoexpect,thesechaptershavelotsofexamplecode.Someofthehacksshowninthispartarebuiltonexamplecodefrom
![Page 26: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/26.jpg)
previouschapters.Othersexploresuccinct,straightforwarddesignpatternsyoucanusetocreateyourownbots.Onceyou’vefinishedallfourpartsofthisbook,you’llbesentoffintothevirtualworldwithyournewsuperpower.
AbouttheOnlineResourcesYou’llfindmanyadditionalresourcesforthisbookathttps://www.nostarch.com/gamehacking/.Theseresourcesincludecompiledbinariestotestyourskills,aconsiderableamountofexamplecode,andquiteafewsnippetsofproduction-readygamehackingcode.Theseresourcesgohand-in-handwiththebook,anditreallyisn’tcompletewithoutthem,somakesuretodownloadthembeforeyoucontinue.
HowtoUseThisBookThisbookshouldbeusedfirstandforemostasaguidetogetyoustartedingamehacking.Theprogressionissuchthatthecontentofeachchapterintroducesnewskillsandabilitiesthatbuildonallpreviouschapters.Asyoucompletechapters,Iencourageyoutoplaywiththeexamplecodeandtestyourskillsonarealgamebeforecontinuingyourreading.Thisisimportant,assomecoveredtopicswillhaveusecasesthatdon’tbecomeevidentuntilyou’re10feetdeepinthemud.
Onceyou’vefinishedthebook,Ihopeitcanstillbeusefultoyouasafieldmanual.Ifyoucomeacrosssomedatastructureyou’reunsureof,maybethedetailsinChapter5canhelp.Ifyoureverseengineeragame’smapformatandarereadytocreateapathfinder,youcanalwaysfliptoChapter11,studythecontent,andusesomeoftheexamplecodeasastartingpoint.Althoughit’simpossibletoanticipatealltheproblemsyoumightfacewhenyou’rehackingaway,I’vetriedtoensureyou’llfindsomeanswerswithinthesepages.
ANOTEFROMTHEPUBLISHERThisbookdoesnotcondonepiracy,violatingtheDMCA,infringingcopyright,orbreakingin-gameTermsofService.Gamehackershave
![Page 27: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/27.jpg)
copyright,orbreakingin-gameTermsofService.Gamehackershavebeenbannedfromgamesforlife,suedformillionsofdollars,andevenjailedfortheirwork.
![Page 28: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/28.jpg)
PART1TOOLSOFTHETRADE
![Page 29: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/29.jpg)
1SCANNINGMEMORYUSINGCHEATENGINE
Thebestgamehackersintheworldspendyearspersonalizingexpansivearsenalswithcustom-builttools.Suchpotenttoolkitsenablethesehackerstoseamlesslyanalyzegames,effortlesslyprototypehacks,andeffectivelydevelopbots.Atthecore,however,eachuniquekitisbuiltfromthesamefour-piecepowerhouse:amemoryscanner,anassembler-leveldebugger,aprocessmonitor,andahexeditor.
Memoryscanningisthegatewaytogamehacking,andthischapterwillteachyouaboutCheatEngine,apowerfulmemoryscannerthatsearchesagame’soperatingmemory(whichlivesinRAM)forvaluesliketheplayer’slevel,health,orin-gamemoney.First,I’llfocusonbasicmemoryscanning,memorymodification,andpointerscanning.Followingthat,we’lldiveintoCheatEngine’spowerfulembeddedLuascriptingengine.
NOTE
YoucangrabCheatEnginefromhttp://www.cheatengine.org/.Payattentionwhenrunningtheinstallerbecauseitwilltrytoinstallsometoolbarsandotherbloatware.Youcandisablethoseoptionsifyouwish.
WhyMemoryScannersAreImportantKnowingagame’sstateisparamounttointeractingwiththegame
![Page 30: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/30.jpg)
Knowingagame’sstateisparamounttointeractingwiththegameintelligently,butunlikehumans,softwarecan’tdeterminethestateofagamesimplybylookingatwhat’sonthescreen.Fortunately,underneathallofthestimuliproducedbyagame,acomputer’smemorycontainsapurelynumericrepresentationofthatgame’sstate—andprogramscanunderstandnumberseasily.Hackersusememoryscannerstofindthosevaluesinmemory,andthenintheirprograms,theyreadthememoryintheselocationstounderstandthegame’sstate.
Forexample,aprogramthathealsplayerswhentheyfallbelow500healthneedstoknowhowtodotwothings:trackaplayer’scurrenthealthandcastahealingspell.Theformerrequiresaccesstothegame’sstate,whilethelattermightonlyrequireabuttontobepressed.Giventhelocationwhereaplayer’shealthisstoredandthewaytoreadagame’smemory,theprogramwouldlooksomethinglikethispseudocode:
//dothisinsomeloophealth=readMemory(game,HEALTH_LOCATION)if(health<500)pressButton(HEAL_BUTTON)
AmemoryscannerallowsyoutofindHEALTH_LOCATIONsothatyoursoftwarecanqueryitforyoulater.
BasicMemoryScanningThememoryscanneristhemostbasic,yetmostimportant,toolfortheaspiringgamehacker.Asinanyprogram,alldatainthememoryofagameresidesatanabsolutelocationcalledamemoryaddress.Ifyouthinkofthememoryasaverylargebytearray,amemoryaddressisanindexpointingtoavalueinthatarray.Whenamemoryscanneristoldtofindsomevaluex(calledascanvalue,becauseit’sthevalueyou’rescanningfor)inagame’smemory,thescannerloopsthroughthebytearraylookingforanyvalueequaltox.Everytimeitfindsamatchingvalue,itaddstheindexofthematchtoaresultlist.
Duetothesheersizeofagame’smemory,however,thevalueofxcanappearinhundredsoflocations.Imaginethatxistheplayer’shealth,whichiscurrently500.Ourxuniquelyholds500,but500isnotuniquelyheldbyx,
![Page 31: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/31.jpg)
soascanforxreturnsallvariableswithavalueof500.Anyaddressesnotrelatedtoxareultimatelyclutter;theyshareavalueof500withxonlybychance.Tofilterouttheseunwantedvalues,thememoryscannerallowsyoutorescantheresultlist,removingaddressesthatnolongerholdthesamevalueasx,whetherxisstill500orhaschanged.
Fortheserescanstobeeffective,theoverallstateofthegamemusthavesignificantentropy—ameasureofdisorder.Youincreaseentropybychangingthein-gameenvironment,oftenbymovingaround,killingcreatures,orswitchingcharacters.Asentropyincreases,unrelatedaddressesarelesslikelytocontinuetoarbitrarilyholdthesamevalue,andgivenenoughentropy,afewrescansshouldfilteroutallfalsepositivesandleaveyouwiththetrueaddressofx.
CheatEngine’sMemoryScannerThissectiongivesyouatourofCheatEngine’smemory-scanningoptions,whichwillhelpyoutrackdowntheaddressesofgamestatevaluesinmemory.I’llgiveyouachancetotrythescanneroutin“BasicMemoryEditing”onpage11;fornow,openCheatEngineandhavealookaround.Thememoryscanneristightlyencapsulatedinitsmainwindow,asshowninFigure1-1.
![Page 32: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/32.jpg)
Figure1-1:CheatEnginemainscreen
Tobeginscanningagame’smemory,clicktheAttachicon➊toattachtoaprocessandthenenterthescanvalue(referredtoasxinourconceptualscanner)youwanttolocate➌.Byattachingtoaprocess,we’retellingCheatEnginetopreparetooperateonit;inthiscase,thatoperationisascan.IthelpstoalsotellCheatEnginewhatkindofscantorun,asI’lldiscussnext.
ScanTypesCheatEngineallowsyoutoselecttwodifferentscandirectives,calledScanTypeandValueType➍.ScanTypetellsthescannerhowtocompareyourscanvaluewiththememorybeingscannedusingoneofthefollowingscantypes:
![Page 33: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/33.jpg)
ExactValueReturnsaddressespointingtovaluesequaltothescanvalue.Choosethisoptionifthevalueyouarelookingforwon’tchangeduringthescan;health,mana,andleveltypicallyfallintothiscategory.
BiggerThanReturnsaddressespointingtovaluesgreaterthanthescanvalue.Thisoptionisusefulwhenthevalueyou’researchingforissteadilyincreasing,whichoftenhappenswithtimers.
SmallerThanReturnsaddressespointingtovaluessmallerthanthescanvalue.LikeBiggerThan,thisoptionisusefulforfindingtimers(inthiscase,onesthatcountdownratherthanup).
ValueBetweenReturnsaddressespointingtovalueswithinascanvaluerange.ThisoptioncombinesBiggerThanandSmallerThan,displayingasecondaryscanvalueboxthatallowsyoutoinputamuchsmallerrangeofvalues.
UnknownInitialValueReturnsalladdressesinaprogram’smemory,allowingrescanstoexaminetheentireaddressrangerelativetotheirinitialvalues.Thisoptionisusefulforfindingitemorcreaturetypes,sinceyouwon’talwaysknowtheinternalvaluesthegamedevelopersusedtorepresenttheseobjects.
TheValueTypedirectivetellstheCheatEnginescannerwhattypeofvariableit’ssearchingfor.
RunningYourFirstScanOncethetwoscandirectivesareset,clickFirstScan➋torunaninitialscanforvalues,andthescannerwillpopulatetheresultslist➎.Anygreenaddressesinthislistarestatic,meaningthattheyshouldremainpersistentacrossprogramrestarts.Addresseslistedinblackresideindynamicallyallocatedmemory,memorythatisallocatedatruntime.
Whentheresultslistisfirstpopulated,itshowstheaddressandreal-timevalueofeachresult.Eachrescanwillalsoshowthevalueofeachresultduringthepreviousscan.(Anyreal-timevaluesdisplayedareupdatedatanintervalthatyoucansetinEdit▸Settings▸GeneralSettings▸Updateinterval.)
![Page 34: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/34.jpg)
NextScansOncetheresultslistispopulated,thescannerenablestheNextScan➋button,whichofferssixnewscantypes.Theseadditionalscantypesallowyoutocomparetheaddressesintheresultslisttotheirvaluesinthepreviousscan,whichwillhelpyounarrowdownwhichaddressholdsthegamestatevalueyou’rescanningfor.Theyareasfollows:
IncreasedValueReturnsaddressespointingtovaluesthathaveincreased.ThiscomplementstheBiggerThanscantypebykeepingthesameminimumvalueandremovinganyaddresswhosevaluehasdecreased.
IncreasedValueByReturnsaddressespointingtovaluesthathaveincreasedbyadefinedamount.Thisscantypeusuallyreturnsfarfewerfalsepositives,butyoucanuseitonlywhenyouknowexactlyhowmuchavaluehasincreased.
DecreasedValueThisoptionistheoppositeofIncreasedValue.
DecreasedValueByThisoptionistheoppositeofIncreasedValueBy.
ChangedValueReturnsaddressespointingtovaluesthathavechanged.Thistypeisusefulwhenyouknowavaluewillmutate,butyou’reunsurehow.
UnchangedValueReturnsaddressespointingtovaluesthathaven’tchanged.Thiscanhelpyoueliminatefalsepositives,sinceyoucaneasilycreatealargeamountofentropywhileensuringthedesiredvaluestaysthesame.
You’llusuallyneedtousemultiplescantypesinordertonarrowdownalargeresultlistandfindthecorrectaddress.Eliminatingfalsepositivesisoftenamatterofproperlycreatingentropy(asdescribedin“BasicMemoryScanning”onpage4),tacticallychangingyourscandirectives,bravelypressingNextScan,andthenrepeatingtheprocessuntilyouhaveasingleremainingaddress.
WhenYouCan’tGetaSingleResultSometimesitisimpossibletopinpointasingleresultinCheatEngine,in
![Page 35: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/35.jpg)
whichcaseyoumustdeterminethecorrectaddressthroughexperimentation.Forexample,ifyou’relookingforyourcharacter’shealthandcan’tnarrowitdowntofewerthanfiveaddresses,youcouldtrymodifyingthevalueofeachaddress(asdiscussedin“ManualModificationwithCheatEngine”onpage8)untilyouseethehealthdisplaychangeortheothervaluesautomaticallychangetotheoneyouset.
CheatTablesOnceyou’vefoundthecorrectaddress,youcandouble-clickittoaddittothecheattablepane➏;addressesinthecheattablepanecanbemodified,watched,andsavedtocheattablefilesforfutureuse.
Foreachaddressinthecheattablepane,youcanaddadescriptionbydouble-clickingtheDescriptioncolumn,andyoucanaddacolorbyright-clickingandselectingChangeColor.Youcanalsodisplaythevaluesofeachaddressinhexadecimalordecimalformatbyright-clickingandselectingShowashexadecimalorShowasdecimal,respectively.Lastly,youcanchangethedatatypeofeachvaluebydouble-clickingtheTypecolumn,oryoucanchangethevalueitselfbydouble-clickingtheValuecolumn.
Sincethemainpurposeofthecheattablepaneistoallowagamehackertoneatlytrackaddresses,itcanbedynamicallysavedandloaded.GotoFile▸SaveorFile▸SaveAstosavethecurrentcheattablepanetoa.ctdocumentfilecontainingeachaddresswithitsvaluetype,description,displaycolor,anddisplayformat.Toloadthesaved.ctdocuments,gotoFile▸Load.(You’llfindmanyready-madecheattablesforpopulargamesathttp://cheatengine.org/tables.php.)
NowthatI’vedescribedhowtoscanforagamestatevalue,I’lldiscusshowyoucanchangethatvaluewhenyouknowwhereitlivesinmemory.
MemoryModificationinGamesBotscheatagamesystembymodifyingmemoryvaluesinthegame’sstateinordertogiveyoulotsofin-gamemoney,modifyyourcharacter’shealth,changeyourcharacter’sposition,andsoon.Inmostonlinegames,acharacter’svitals(suchashealth,mana,skills,andposition)areheldinmemorybutarecontrolledbythegameserverandrelayedtoyourlocal
![Page 36: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/36.jpg)
memorybutarecontrolledbythegameserverandrelayedtoyourlocalgameclientovertheInternet,somodifyingsuchvaluesduringonlineplayismerelycosmeticanddoesn’taffecttheactualvalues.(Anyusefulmemorymodificationtoanonlinegamerequiresamuchmoreadvancedhackthat’sbeyondCheatEngine’scapabilities.)Inlocalgameswithnoremoteserver,however,youcanmanipulateallofthesevaluesatwill.
ManualModificationwithCheatEngineWe’lluseCheatEnginetounderstandhowthememorymodificationmagicworks.
Tomodifymemorymanually,dothefollowing:
1. AttachCheatEnginetoagame.2. Eitherscanfortheaddressyouwishtomodifyorloadacheattablethat
containsit.3. Double-clickontheValuecolumnfortheaddresstoopenaninput
promptwhereyoucanenteranewvalue.4. Ifyouwanttomakesurethenewvaluecan’tbeoverwritten,selectthe
boxundertheActivecolumntofreezetheaddress,whichwillmakeCheatEnginekeepwritingthesamevaluebacktoiteverytimeitchanges.
Thismethodworkswondersforquick-and-dirtyhacks,butconstantlychangingvaluesbyhandiscumbersome;anautomatedsolutionwouldbemuchmoreappealing.
TrainerGeneratorCheatEngine’strainergeneratorallowsyoutoautomatethewholememorymodificationprocesswithoutwritinganycode.
Tocreateatrainer(asimplebotthatbindsmemorymodificationactionstokeyboardhotkeys),gotoFile▸CreategenerictrainerLuascriptfromtable.ThisopensaTrainergeneratordialogsimilartotheoneshowninFigure1-2.
![Page 37: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/37.jpg)
Figure1-2:CheatEngineTrainergeneratordialog
Thereareanumberoffieldstomodifyhere:
ProcessnameThenameoftheexecutablethetrainershouldattachto.ThisisthenameshownintheprocesslistwhenyouattachwithCheatEngine,anditshouldbeautofilledwiththenameoftheprocessCheatEngineisattachedto.
PopuptraineronkeypressOptionallyenablesahotkey—whichyousetbyenteringakeycombinationintheboxbelowthecheckbox—todisplaythetrainer’smainwindow.
TitleThenameofyourtrainer,whichwillbedisplayedonitsinterface.Thisisoptional.
AbouttextThedescriptionofyourtrainer,tobedisplayedontheinterface;thisisalsooptional.
Freezeinterval(inmilliseconds)Theintervalduringwhichafreezeoperationoverwritesthevalue.Youshouldgenerallyleavethisat250,aslowerintervalscansapresourcesandhighervaluesmaybetooslow.
Oncethesevaluesareconfigured,clickAddHotkeytosetupakeysequencetoactivateyourtrainer.Youwillbepromptedtoselectavalue
![Page 38: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/38.jpg)
fromyourcheattable.Enteravalue,andyouwillbetakentoaSet/ChangehotkeyscreensimilartoFigure1-3.
Figure1-3:CheatEngineSet/Changehotkeyscreen
Onthisscreen,placeyourcursorintheboxlabeledTypethekeysyouwanttosetthehotkeyto➊andenterthedesiredkeycombination.Next,choosethedesiredactionfromthedrop-downmenu➋;youroptionsshouldappearinthefollowingorder:
TogglefreezeTogglesthefreezestateoftheaddress.
TogglefreezeandallowincreaseTogglesthefreezestateoftheaddressbutallowsthevaluetoincrease.Anytimethevaluedecreases,thetraineroverwritesitwithitspreviousvalue.Increasedvalueswillnotbeoverwritten.
TogglefreezeandallowdecreaseDoestheoppositeofTogglefreezeandallowincrease.
FreezeSetstheaddresstofrozenifit’snotfrozenalready.
UnfreezeUnfreezestheaddressifit’sfrozen.
![Page 39: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/39.jpg)
SetvaluetoSetsthevaluetowhateveryouspecifyinthevaluebox➌.
DecreasevaluewithDecreasesthevaluebytheamountyouspecifyinthevaluebox➌.
IncreasevaluewithDoestheoppositeofDecreasevaluewith.
Finally,youcansetadescriptionfortheaction➍.ClickApply,thenOK,andyouractionwillappearinthelistontheTrainergeneratorscreen.Atthispoint,CheatEnginerunsthetrainerinthebackground,andyoucansimplypressthehotkeysyouconfiguredtoexecutethememoryactions.
Tosaveyourtrainertoaportableexecutable,clickGeneratetrainer.RunningthisexecutableafterthegameislaunchedwillattachyourtrainertothegamesoyoucanuseitwithoutstartingCheatEngine.
NowthatyouknowyourwayaroundCheatEngine’smemoryscannerandtrainergenerator,trymodifyingsomememoryyourself.
BASICMEMORYEDITINGDownloadthefilesforthisbookfromhttps://www.nostarch.com/gamehacking/,andrunthefileBasicMemory.exe.Next,startupCheatEngineandattachtothebinary.Then,usingonlyCheatEngine,findtheaddressesforthex-andy-coordinatesofthegrayball.(Hint:Usethe4Bytesvaluetype.)
Onceyou’vefoundthevalues,modifythemtoplacetheballontopoftheblacksquare.Thegamewillletyouknowonceyou’vesucceededbydisplayingthetext“Goodjob!”(Hint:Eachtimetheballismoved,itsposition—storedasa4-byteinteger—inthatplaneischangedby1.Also,trytolookonlyforstatic[green]results.)
PointerScanningAsI’vementioned,onlinegamesoftenstorevaluesindynamicallyallocatedmemory.Whileaddressesthatreferencedynamicmemoryareuselesstous
![Page 40: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/40.jpg)
inandofthemselves,somestaticaddresswillalwayspointtoanotheraddress,whichinturnpointstoanother,andsoon,untilthetailofthechainpointstothedynamicmemorywe’reinterestedin.CheatEnginecanlocatethesechainsusingamethodcalledpointerscanning.
Inthissection,I’llintroduceyoutopointerchainsandthendescribehowpointerscanningworksinCheatEngine.Whenyouhaveagoodgraspoftheuserinterface,youcangetsomehands-onexperiencein“PointerScanning”onpage18.
PointerChainsThechainofoffsetsI’vejustdescribediscalledapointerchainandlookslikethis:
list<int>chain={start,offset1,offset2[,...]}
Thefirstvalueinthispointerchain(start)iscalledamemorypointer.It’sanaddressthatstartsthechain.Theremainingvalues(offset1,offset2,andsoon)makeuptheroutetothedesiredvalue,calledapointerpath.
Thispseudocodeshowshowapointerchainmightberead:
intreadPointerChain(chain){➊ret=read(chain[0])fori=1,chain.len-1,1{offset=chain[i]ret=read(ret+offset)}returnret}
ThiscodecreatesthefunctionreadPointerPath(),whichtakesapointerchaincalledchainasaparameter.ThefunctionreadPointerPath()treatsthepointerpathinchainasalistofmemoryoffsetsfromtheaddressret,whichisinitiallysettothememorypointerat➊.Itthenloopsthroughtheseoffsets,updatingthevalueofrettotheresultofread(ret+offset)oneachiterationandreturningretonceit’sfinished.ThispseudocodeshowswhatreadPointerPath()lookslikewhentheloopisunrolled:
list<int>chain={0xDEADBEEF,0xAB,0x10,0xCC}value=readPointerPath(chain)//thefunctioncallunrollstothisret=read(0xDEADBEEF)//chain[0]
![Page 41: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/41.jpg)
ret=read(0xDEADBEEF)//chain[0]ret=read(ret+0xAB)ret=read(ret+0x10)ret=read(ret+0xCC)intvalue=ret
Thefunctionultimatelycallsreadfourtimes,onfourdifferentaddresses—oneforeachelementinchain.
NOTE
Manygamehackersprefertocodetheirchainreadsinplace,insteadofencapsulatingtheminfunctionslikereadPointerPath().
PointerScanningBasicsPointerchainsexistbecauseeverychunkofdynamicallyallocatedmemorymusthaveacorrespondingstaticaddressthatthegame’scodecanusetoreferenceit.Gamehackerscanaccessthesechunksbylocatingthepointerchainsthatreferencethem.Becauseoftheirmultitierstructure,however,pointerchainscannotbelocatedthroughthelinearapproachthatmemoryscannersuse,sogamehackershavedevisednewwaystofindthem.
Fromareverseengineeringperspective,youcouldlocateandanalyzetheassemblycodeinordertodeducewhatpointerpathitusedtoaccessthevalue,butdoingsoisverytime-consumingandrequiresadvancedtools.Pointerscannerssolvethisproblembyusingbrute-forcetorecursivelyiterateovereverypossiblepointerchainuntiltheyfindonethatresolvestothetargetmemoryaddress.
TheListing1-1pseudocodeshouldgiveyouageneralideaofhowapointerscannerworks.
list<int>pointerScan(target,maxAdd,maxDepth){➊foraddress=BASE,0x7FFFFFF,4{ret=rScan(address,target,maxAdd,maxDepth,1)if(ret.len>0){ret.pushFront(address)returnret}}return{}}
![Page 42: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/42.jpg)
list<int>rScan(address,target,maxAdd,maxDepth,curDepth){➋foroffset=0,maxAdd,4{value=read(address+offset)➌if(value==target)returnlist<int>(offset)}➍if(curDepth<maxDepth){curDepth++➎foroffset=0,maxAdd,4{ret=rScan(address+offset,target,maxAdd,maxDepth,curDepth)➏if(ret.len>0){ret.pushFront(offset)➐returnret}}}return{}}
Listing1-1:Pseudocodeforapointerscanner
ThiscodecreatesthefunctionspointerScan()andrScan().
pointerScan()ThepointerScan()functionistheentrypointtothescan.Ittakestheparameterstarget(thedynamicmemoryaddresstofind),maxAdd(themaximumvalueofanyoffset),andmaxDepth(themaximumlengthofthepointerpath).Itthenloopsthroughevery4-bytealignedaddress➊inthegame,callingrScan()withtheparametersaddress(theaddressinthecurrentiteration),target,maxAdd,maxDepth,andcurDepth(thedepthofthepath,whichisalways1inthiscase).
rScan()TherScan()functionreadsmemoryfromevery4-bytealignedoffsetbetween0andmaxAdd➋,andreturnsifaresultisequaltotarget➌.IfrScan()doesn’treturninthefirstloopandtherecursionisnottoodeep➍,itincrementscurDepthandagainloopsovereachoffset➎,callingitselfforeachiteration.
Ifaselfcallreturnsapartialpointerpath➏,rScan()willprependthe
![Page 43: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/43.jpg)
currentoffsettothepathandreturnuptherecursionchain➐untilitreachespointerScan().WhenacalltorScan()frompointerScan()returnsapointerpath,pointerScan()pushesthecurrentaddresstothefrontofthepathandreturnsitasacompletechain.
PointerScanningwithCheatEngineThepreviousexampleshowedthebasicprocessofpointerscanning,buttheimplementationI’veshownisprimitive.Asidefrombeinginsanelyslowtoexecute,itwouldgeneratecountlessfalsepositives.CheatEngine’spointerscannerusesanumberofadvancedinterpolationstospeedupthescanandmakeitmoreaccurate,andinthissection,I’llintroduceyoutothesmorgasbordofavailablescanningoptions.
ToinitiateapointerscaninCheatEngine,right-clickonadynamicmemoryaddressinyourcheattableandclickPointerscanforthisaddress.Whenyouinitiateapointerscan,CheatEnginewillaskyouwheretostorethescanresultsasa.ptrfile.Onceyouenteralocation,aPointerscannerscanoptionsdialogsimilartotheoneshowninFigure1-4willappear.
![Page 44: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/44.jpg)
Figure1-4:CheatEnginePointerscannerscanoptionsdialog
TheAddresstofindinputfieldatthetopdisplaysyourdynamicmemoryaddress.NowcarefullyselectfromamongCheatEngine’smanyscanoptions.
KeyOptionsSeveralofCheatEngine’sscanoptionstypicallyretaintheirdefaultvalues.Thoseoptionsareasfollows:
Addressesmustbe32-bitsalignedTellsCheatEnginetoscanonlyaddressesthataremultiplesof4,whichgreatlyincreasesthescanspeed.
![Page 45: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/45.jpg)
Asyou’lllearninChapter4,compilersaligndatasothatmostaddresseswillbemultiplesof4anywaybydefault.You’llrarelyneedtodisablethisoption.
OnlyfindpathswithastaticaddressSpeedsupthescanbypreventingCheatEnginefromsearchingpathswithadynamicstartpointer.Thisoptionshouldalwaysbeenabledbecausescanningforapathstartingatanotherdynamicaddresscanbecounterproductive.
Don’tincludepointerswithread-onlynodesShouldalsoalwaysbeenabled.Dynamicallyallocatedmemorythatstoresvolatiledatashouldneverberead-only.
StoptraversingapathwhenastatichasbeenfoundTerminatesthescanwhenitfindsapointerpathwithastaticstartaddress.Thisshouldbeenabledtoreducefalsepositivesandspeedupthescan.
PointerpathmayonlybeinsidethisregionCantypicallybeleftasis.Theotheroptionsavailabletoyoucompensateforthislargerangebyintelligentlynarrowingthescopeofthescan.
FirstelementofpointerstructmustpointtomoduleTellsCheatEnginenottosearchheapchunksinwhichvirtualfunctiontablesarenotfound,undertheassumptionthatthegamewascodedusingobjectorientation.Whilethissettingcanimmenselyspeedupscans,it’shighlyunreliableandyoushouldalmostalwaysleaveitdisabled.
NoloopingpointersInvalidatesanypathsthatpointtothemselves,weedingoutinefficientpathsbutslightlyslowingdownthescan.Thisshouldusuallybeenabled.
MaxlevelDeterminesthemaximumlengthofthepointerpath.(RememberthemaxDepthvariableintheexamplecodeinListing1-1?)Thisshouldbekeptaround6or7.Ofcourse,therewillbetimeswhenyou’llneedtochangetheseoptions
fromthesettingsdescribed.Forexample,failingtoobtainreliableresultswiththeNoloopingpointersorMaxlevelsettingstypicallymeansthatthevalueyou’relookingforexistsinadynamicdatastructure,likealinkedlist,binarytree,orvector.AnotherexampleistheStoptraversingapathwhenastatichasbeenfoundoption,whichinrarecasescanpreventyoufromgettingreliableresults.
![Page 46: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/46.jpg)
SituationalOptionsUnlikethepreviousoptions,yoursettingsfortheremainingoneswilldependonyoursituation.Here’showtodeterminethebestconfigurationforeach:
ImprovepointerscanwithgatheredheapdataAllowsCheatEnginetousetheheapallocationrecordtodetermineoffsetlimits,effectivelyspeedingupthescanbyweedingoutmanyfalsepositives.Ifyourunintoagameusingacustommemoryallocator(whichisbecomingincreasinglycommon),thisoptioncanactuallydotheexactoppositeofwhatit’smeanttodo.Youcanleavethissettingenabledininitialscans,butitshouldbethefirsttogowhenyou’reunabletofindreliablepaths.
OnlyallowstaticandheapaddressesinthepathInvalidatesallpathsthatcan’tbeoptimizedwithheapdata,makingthisapproachevenmoreaggressive.
MaxdifferentoffsetspernodeLimitsthenumberofsame-valuepointersthescannerchecks.Thatis,ifndifferentaddressespointto0x0BADF00D,thisoptiontellsCheatEnginetoconsideronlythefirstmaddresses.Thiscanbeextremelyhelpfulwhenyou’reunabletonarrowdownyourresultset.Inothercases,youmaywanttodisableit,asitwillmissmanyvalidpaths.
Allowstackaddressesofthefirstthread(s)tobehandledasstaticScansthecallstacksofoldestmthreadsinthegame,consideringthefirstnbytesineachone.ThisallowsCheatEnginetoscantheparametersandlocalvariablesoffunctionsinthegame’scallchain(thegoalbeingtofindvariablesusedbythegame’smainloop).Thepathsfoundwiththisoptioncanbebothhighlyvolatileandextremelyuseful;IuseitonlywhenIfailtofindheapaddresses.
StackaddressesasonlystaticaddressTakesthepreviousoptionevenfurtherbyallowingonlystackaddressesinpointerpaths.
PointersmustendwithspecificoffsetsCanbeusefulifyouknowtheoffset(s)attheendofavalidpath.Thisoptionwillallowyoutospecifythoseoffsets(startingwiththelastoffsetatthetop),greatlyreducingthescopeofthescan.
NrofthreadsscanningDetermineshowmanythreadsthescannerwill
![Page 47: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/47.jpg)
use.Anumberequaltothenumberofcoresinyourprocessoroftenworksbest.Adrop-downmenuwithoptionsallowsyoutospecifythepriorityforeachthread.Idleisbestifyouwantyourscantogoveryslowly,Normaliswhatyoushoulduseformostscans,andTimecriticalisusefulforlengthyscansbutwillrenderyourcomputeruselessforthescanduration.
MaximumoffsetvalueDeterminesthemaximumvalueofeachoffsetinthepath.(RememberthemaxAddvariableinListing1-1?)Itypicallystartwithalowvalue,increasingitonlyifmyscanfails;128isagoodstartingvalue.Keepinmindthatthisvalueismostlyignoredifyou’reusingtheheapoptimizationoptions.
NOTE
WhatifbothOnlyallowstaticandheapaddressesinthepathandStackaddressesasonlystaticaddressareenabled?Willthescancomeupempty?Seemslikeafun,albeituseless,experiment.
Onceyouhavedefinedyourscanoptions,clickOKtostartapointerscan.Whenthescancompletes,aresultswindowwillappearwiththelistofpointerchainsfound.Thislistoftenhasthousandsofresults,containingbothrealchainsandfalsepositives.
PointerRescanningThepointerscannerhasarescanfeaturethatcanhelpyoueliminatefalsepositives.Tobegin,pressCTRL-RfromtheresultswindowtoopentheRescanpointerlistdialog,asshowninFigure1-5.
![Page 48: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/48.jpg)
Figure1-5:CheatEngineRescanpointerlistdialog
TherearetwomainoptionstoconsiderwhenyoutellCheatEnginetorescan:
OnlyfilteroutinvalidpointersIfyoucheckthisbox➊,therescanwilldiscardonlypointerchainsthatpointtoinvalidmemory,whichhelpsifyourinitialresultsetisverylarge.Disablethistofilteroutpathsthatdon’tresolvetoaspecificaddressorvalue(asshowninthefigure).
RepeatrescanuntilstoppedIfyoucheckthisbox➋,therescanwillexecuteinacontinuousloop.Ideally,youshouldenablethissettingandletrescanrunwhileyoucreatealargeamountofmemoryentropy.
Fortheinitialrescan,enablebothOnlyfilteroutinvalidpointersandRepeatrescanuntilstopped,andthenpressOKtoinitiatetherescan.Therescanwindowwillgoaway,andaStoprescanloopbuttonwillappearintheresultswindow.TheresultlistwillbeconstantlyrescanneduntilyouclickStoprescanloop,butspendafewminutescreatingmemoryentropybeforedoingso.
Inrarecases,rescanningusingarescanloopmaystillleaveyouwithalargelistofpossiblepaths.Whenthishappens,youmayneedtorestartthegame,findtheaddressthatholdsyourvalue(itmayhavechanged!),andusetherescanfeatureonthisaddresstofurthernarrowresults.Inthisscan,leaveOnlyfilteroutinvalidpointersuncheckedandenterthenewaddress
![Page 49: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/49.jpg)
intheAddresstofindfield.
NOTE
Ifyouhadtoclosetheresultswindow,youcanreopenitandloadtheresultlistbygoingtothemainCheatEnginewindowandpressingtheMemoryViewbuttonbelowtheresultspane.Thisshouldbringupamemorydumpwindow.Whenthewindowappears,pressCTRL-Ptoopenthepointerscanresultslist.ThenpressCTRL-Otoopenthe.ptrfilewhereyousavedthepointerscan.
Ifyourresultsstillaren’tnarrowenough,tryrunningthesamescanacrosssystemrestartsorevenondifferentsystems.Ifthisstillyieldsalargeresultset,eachresultcansafelybeconsideredstaticbecausemorethanonepointerchaincanresolvetothesameaddress.
Onceyou’venarroweddownyourresultset,double-clickonausablepointerchaintoaddittoyourcheattable.Ifyouhaveahandfulofseeminglyusablechains,grabtheonewiththefewestoffsets.Ifyoufindmultiplechainswithidenticaloffsetsthatstartwiththesamepointerbutdivergeafteracertainpoint,yourdatamaybestoredinadynamicdatastructure.
That’sallthereistopointerscanninginCheatEngine.Tryityourself!
POINTERSCANNINGGotohttps://www.nostarch.com/gamehacking/anddownloadMemoryPointers.exe.Unlikethelasttask,whichrequiredyoutowinonlyonce,thisonerequiresthatyouwin50timesin10seconds.Uponeachwin,thememoryaddressesforthex-andy-coordinateswillchange,meaningyouwillbeabletofreezethevalueonlyifyouhavefoundaproperpointerpath.Startthisexercisethesamewayasthepreviousone,butonceyou’vefoundtheaddresses,usethePointerscanfeaturetolocatepointerpathstothem.Then,placetheballontopoftheblacksquare,freezethevalueinplace,andpressTABtobeginthetest.Justasbefore,thegamewillletyouknowonceyou’vewon.(Hint:Trysettingthemaximumlevelto5andthe
![Page 50: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/50.jpg)
maximumoffsetvalueto512.Also,playwiththeoptionstoallowstackaddresses,terminatethescanwhenastaticisfound,andimprovethepointerscanwithheapdata.Seewhichcombinationofoptionsgivesthebestresults.)
LuaScriptingEnvironmentHistorically,botdevelopersrarelyusedCheatEnginetoupdatetheiraddresseswhenagamereleasedapatchbecauseitwasmucheasiertodosoinOllyDbg.ThismadeCheatEngineuselesstogamehackersotherthanforinitialresearchanddevelopment—thatis,untilapowerfulLua-basedembeddedscriptingenginewasimplementedaroundCheatEngine’srobustscanningenvironment.WhilethisenginewascreatedtoenablethedevelopmentofsimplebotswithinCheatEngine,professionalgamehackersfoundtheycouldalsouseittoeasilywritecomplexscriptstoautomaticallylocateaddressesacrossdifferentversionsofagame’sbinary—ataskthatmightotherwisetakehours.
NOTE
You’llfindmoredetailabouttheCheatEngineLuascriptingengineonthewikiathttp://wiki.cheatengine.org/.
TostartusingtheLuaengine,pressCTRL-ALT-LfromthemainCheatEnginewindow.Oncethewindowopens,writeyourscriptinthetextareaandclickExecutescripttorunit.SaveascriptwithCTRL-SandopenasavedscriptwithCTRL-O.
Thescriptingenginehashundredsoffunctionsandinfiniteusecases,soI’llgiveyoujustaglimpseofitsabilitiesbybreakingdowntwoscripts.Everygameisdifferentandeverygamehackerwritesscriptstoaccomplishuniquegoals,sothesescriptsareonlyusefulfordemonstratingconcepts.
SearchingforAssemblyPatternsThisfirstscriptlocatesfunctionsthatcomposeoutgoingpacketsandsendsthemtothegameserver.Itworksbysearchingagame’sassemblycodefor
![Page 51: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/51.jpg)
themtothegameserver.Itworksbysearchingagame’sassemblycodeforfunctionsthatcontainacertaincodesequence.
➊BASEADDRESS=getAddress("Game.exe")➋functionLocatePacketCreation(packetType)➌foraddress=BASEADDRESS,(BASEADDRESS+0x2ffffff)dolocalpush=readBytes(address,1,false)localtype=readInteger(address+1)localcall=readInteger(address+5)➍if(push==0x68andtype==packetTypeandcall==0xE8)thenreturnaddressendendreturn0endFUNCTIONHEADER={0xCC,0x55,0x8B,0xEC,0x6A}➎functionLocateFunctionHead(checkAddress)if(checkAddress==0)thenreturn0end➏foraddress=checkAddress,(checkAddress-0x1fff),-1dolocalmatch=truelocalcheckheader=readBytes(address,#FUNCTIONHEADER,true)➐fori,vinipairs(FUNCTIONHEADER)doif(v~=checkheader[i])thenmatch=falsebreakendend➑if(match)thenreturnaddress+1endendreturn0end
➒localfuncAddress=LocateFunctionHead(LocatePacketCreation(0x64))if(funcAddress~=0)thenprint(string.format("0x%x",funcAddress))elseprint("Notfound!")end
ThecodebeginsbygettingthebaseaddressofthemodulethatCheatEngineisattachedto➊.Onceithasthebaseaddress,thefunctionLocatePacketCreation()isdefined➋.Thisfunctionloopsthroughthefirst0x2FFFFFFbytesofmemoryinthegame➌,searchingforasequencethatrepresentsthisx86assemblercode:
![Page 52: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/52.jpg)
PUSHtype;Datais:0x68[4bytetype]CALLoffset;Datais:0xE8[4byteoffset]
ThefunctionchecksthatthetypeisequaltopacketType,butitdoesn’tcarewhatthefunctionoffsetis➍.Oncethissequenceisfound,thefunctionreturns.
Next,theLocateFunctionHead()functionisdefined➎.Thefunctionbacktracksupto0x1FFFbytesfromagivenaddress➏,andateachaddress,itchecksforastubofassemblercode➐thatlookssomethinglikethis:
INT3;0xCCPUSHEBP;0x55MOVEBP,ESP;0x8B0xECPUSH[-1];0x6A0xFF
Thisstubwillbepresentatthebeginningofeveryfunction,becauseit’spartofthefunctionprologuethatsetsupthefunction’sstackframe.Onceitfindsthecode,thefunctionwillreturntheaddressofthestubplus1➑(thefirstbyte,0xCC,ispadding).
Totiethesestepstogether,theLocatePacketCreation()functioniscalledwiththepacketTypethatI’mlookingfor(arbitrarily0x64)andtheresultingaddressispassedintotheLocateFunctionHead()function➒.ThiseffectivelylocatesthefirstfunctionthatpushespacketTypeintoafunctioncallandstoresitsaddressinfuncAddress.Thisstubshowstheresult:
INT3;LocateFunctionHeadback-trackedtoherePUSHEBP;andreturnedthisaddressMOVEBP,ESPPUSH[-1]--snip--PUSH[0x64];LocatePacketCreationreturnedthisaddressCALL[something]
This35-linescriptcanautomaticallylocate15differentfunctionsinunderaminute.
SearchingforStringsThisnextLuascriptscansagame’smemoryfortextstrings.ItworksmuchastheCheatEngine’smemoryscannerdoeswhenyouusethestringvaluetype.
![Page 53: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/53.jpg)
type.
BASEADDRESS=getAddress("Game.exe")➊functionfindString(str)locallen=string.len(str)➋localchunkSize=4096➌localchunkStep=chunkSize-lenprint("Found'"..str.."'at:")➍foraddress=BASEADDRESS,(BASEADDRESS+0x2ffffff),chunkStepdolocalchunk=readBytes(address,chunkSize,true)if(notchunk)thenbreakend➎forc=0,chunkSize-lendo➏checkForString(address,chunk,c,str,len)endendendfunctioncheckForString(address,chunk,start,str,len)fori=1,lendoif(chunk[start+i]~=string.byte(str,i))thenreturnfalseendend➐print(string.format("\t0x%x",address+start))end
➑findString("hello")➒findString("world")
Aftergettingthebaseaddress,thefindString()functionisdefined➊,whichtakesastring,str,asaparameter.Thisfunctionloopsthroughthegame’smemory➍in4,096-byte-longchunks➋.Thechunksarescannedsequentially,eachonestartinglen(thelengthofstr)bytesbeforetheendofthepreviousone➌topreventmissingastringthatbeginsononechunkandendsonanother.
AsfindString()readseachchunk,ititeratesovereverybyteuntiltheoverlappointinthechunk➎,passingeachsubchunkintothecheckForString()function➏.IfcheckForString()matchesthesubchunktostr,itprintstheaddressofthatsubchunktotheconsole➐.
Lastly,tofindalladdressesthatreferencethestrings"hello"and"world",thefunctionsfindString("hello")➑andfindString("world")➒arecalled.
![Page 54: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/54.jpg)
Byusingthiscodetosearchforembeddeddebugstringsandpairingitwiththepreviouscodetolocatefunctionheaders,I’mabletofindalargenumberofinternalfunctionswithinagameinmereseconds.
OPTIMIZINGMEMORYCODEDuetothehighoverheadofmemoryreading,optimizationisextremelyimportantwhenyou’rewritingcodethatperformsmemoryreads.Inthepreviouscodesnippet,noticethatthefunctionfindString()doesnotusetheLuaengine’sbuiltinreadString()function.Instead,itreadsbigchunksofmemoryandsearchesthemforthedesiredstring.Let’sbreakdownthenumbers.
AscanusingreadString()wouldtrytoreadastringoflenbytesateverypossiblememoryaddress.Thismeansitwouldread,atmost,(0x2FFFFFF*len+len)bytes.However,findString()readschunksof4,096bytesandscansthemlocallyformatchingstrings.Thismeansitwouldread,atmost,(0x2FFFFFF+4096+(0x2FFFFFF/(4096-10))*len)bytes.Whensearchingforastringwithalengthof10,thenumberofbytesthateachmethodwouldreadis503,316,480and50,458,923,respectively.
NotonlydoesfindString()readanorderofmagnitudelessdata,italsoinvokesfarfewermemoryreads.Readinginchunksof4,096byteswouldrequireatotalof(0x2FFFFFF/(4096-len))reads.ComparethattoascanusingreadString(),whichwouldneed0x2FFFFFFreads.ThescanthatusesfindString()isahugeimprovementbecauseinvokingareadismuchmoreexpensivethanincreasingthesizeofdatabeingread.(NotethatIchose4,096arbitrarily.Ikeepthechunkrelativelysmallbecausereadingmemorycanbetime-consuming,anditmightbewastefultoreadfourpagesatatimejusttofindthestringinthefirst.)
ClosingThoughts
![Page 55: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/55.jpg)
Bythispoint,youshouldhaveabasicunderstandingofCheatEngineandhowitworks.CheatEngineisaveryimportanttoolinyourkit,andIencourageyoutogetsomehands-onexperiencewithitbyfollowing“BasicMemoryEditing”onpage11and“PointerScanning”onpage18andplayingaroundwithitonyourown.
![Page 56: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/56.jpg)
2DEBUGGINGGAMESWITHOLLYDBG
YoucanscratchthesurfaceofwhathappensasagamerunswithCheatEngine,butwithagooddebugger,youcandigdeeperuntilyouunderstandthegame’sstructureandexecutionflow.ThatmakesOllyDbgessentialtoyourgame-hackingarsenal.It’spackedwithamyriadofpowerfultoolslikeconditionalbreakpoints,referencedstringsearch,assemblypatternsearch,andexecutiontracing,makingitarobustassembler-leveldebuggerfor32-bitWindowsapplications.
I’llcoverlow-levelcodestructureindetailinChapter4,butforthischapter,Iassumeyou’reatleastfamiliarwithmoderncode-leveldebuggers,suchastheonepackagedwithMicrosoftVisualStudio.OllyDbgisfunctionallysimilartothose,withonemajordifference:itinterfaceswiththeassemblycodeofanapplication,workingevenintheabsenceofsourcecodeand/ordebugsymbols,makingitidealwhenyouneedtodigintotheinternalsofagame.Afterall,gamecompaniesarerarelynice(ordumb)enoughtoshiptheirgameswithdebugsymbols!
Inthischapter,I’llgooverOllyDbg’suserinterface,showyouhowtouseitsmostcommondebuggingfeatures,breakdownitsexpressionengine,andprovidesomereal-worldexamplesofhowyoucantieitintoyourgamehackingendeavors.Asawrap-up,I’llteachyouaboutsomeusefulplug-insandsendyouoffwithatestgamedesignedtogetyoustartedinOllyDbg.
![Page 57: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/57.jpg)
NOTE
ThischapterfocusesonOllyDbg1.10andmaynotbeentirelyaccurateforlaterversions.Iusethisversionbecause,atthetimeofwriting,theplug-ininterfaceforOllyDbg2isstillfarlessrobustthantheoneforOllyDbg1.
WhenyoufeellikeyouhaveahandleonOllyDbg’sinterfaceandfeatures,youcantryitonagameyourselfwith“Patchinganif()Statement”onpage46.
ABriefLookatOllyDbg’sUserInterfaceGototheOllyDbgwebsite(http://www.ollydbg.de/),downloadandinstallOllyDbg,andopentheprogram.YoushouldseethetoolbarshowninFigure2-1aboveamultiplewindowinterfacearea.
Figure2-1:OllyDbgmainwindow
Thistoolbarcontainstheprogramcontrols➊,thedebugbuttons➋,theGotobutton➌,thecontrolwindowbuttons➍,andtheSettingsbutton➎.
Thethreeprogramcontrolsallowyoutoopenanexecutableandattachtotheprocessitcreates,restartthecurrentprocess,orterminateexecutionofthecurrentprocess,respectively.YoucanalsocompletethesefunctionswiththehotkeysF3,CTRL-F2,andALT-F2,respectively.Toattachtoaprocessthatisalreadyrunning,clickFile▸Attach.
Thedebugbuttonscontrolthedebuggeractions.Table2-1describeswhatthesebuttonsdo,alongwiththeirhotkeysandfunctions.Thistablealsoliststhreeusefuldebuggeractionsthatdon’thavebuttonsonthedebug
![Page 58: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/58.jpg)
toolbar.
Table2-1:DebugButtonsandOtherDebuggerFunctions
Button Hotkey Function
Play F9 Resumesnormalexecutionoftheprocess.
Pause F12 PausesexecutionofallthreadswithintheprocessandbringsuptheCPUwindowattheinstructioncurrentlybeingexecuted.
Stepinto
F7 Single-stepstothenextoperationtobeexecuted(willdivedownintofunctioncalls).
Stepover
F8 Stepstothenextoperationtobeexecutedwithincurrentscope(willskipoverfunctioncalls).
Traceinto
CTRL-F11
Runsadeeptrace,tracingeveryoperationthatisexecuted.
Traceover
CTRL-F12
Runsapassivetracethattracesonlyoperationswithinthecurrentscope.
Executeuntilreturn
CTRL-F9
Executesuntilareturnoperationishitwithinthecurrentscope.
CTRL-F7
Automaticallysingle-stepsoneveryoperation,followingexecutioninthedisassemblywindow.Thismakesexecutionappeartobeanimated.
CTRL-F8
Alsoanimatesexecution,butstepsoverfunctionsinsteadofsteppingintothem.
ESC Stopsanimation,pausingexecutiononthecurrentoperation.
TheGotobuttonopensadialogaskingforahexadecimaladdress.Onceyouentertheaddress,OllyDbgopenstheCPUwindowandshowsthedisassemblyatthespecifiedaddress.WhentheCPUwindowisinfocus,youcanalsoshowthatinformationwiththehotkeyCTRL-G.
Thecontrolwindowbuttonsopendifferentcontrolwindows,whichdisplay
![Page 59: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/59.jpg)
usefulinformationabouttheprocessyou’redebuggingandexposemoredebuggingfunctions,liketheabilitytosetbreakpoints.OllyDbghasatotalof13controlwindows,whichcanallbeopensimultaneouslywithinthemultiplewindowinterface.Table2-2describesthesewindows,listedintheorderinwhichtheyappearonthewindowbuttonstoolbar.
Table2-2:OllyDbg’sControlWindows
Window HotkeyFunction
Log ALT-L
Displaysalistoflogmessages,includingdebugprints,threadevents,debuggerevents,moduleloads,andmuchmore.
Modules ALT-E Displaysalistofallexecutablemodulesloadedintotheprocess.Double-clickamoduletoopenitintheCPUwindow.
Memorymap
ALT-M
Displaysalistofallblocksofmemoryallocatedbytheprocess.Double-clickablockinthelisttobringupadumpwindowofthatmemoryblock.
Threads Displaysalistofthreadsrunningintheprocess.Foreachthreadinthislist,theprocesshasastructurecalledaThreadInformationBlock(TIB).OllyDbgallowsyoutovieweachthread’sTIB;simplyright-clickathreadandselectDumpthreaddatablock.
Windows Displaysalistofwindowhandlesheldbytheprocess.Right-clickawindowinthislisttojumptoorsetabreakpointonitsclassprocedure(thefunctionthatgetscalledwhenamessageissenttothewindow).
Handles Displaysalistofhandlesheldbytheprocess.(NotethatProcessExplorerhasamuchbetterhandlelistthanOllyDbg,asIwilldiscussinChapter3.)
CPU ALT-C
Displaysthemaindisassemblerinterfaceandcontrolsamajorityofthedebuggerfunctionality.
Patches CTRL-P
Displaysalistofanyassemblycodemodificationsyouhavemadetomoduleswithintheprocess.
![Page 60: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/60.jpg)
Callstack ALT-K
Displaysthecallstackfortheactivethread.Thewindowupdateswhentheprocesshalts.
BreakpointsALT-B Displaysalistofactivedebuggerbreakpointsandallowsyoutotogglethemonandoff.
References Displaysthereferencelist,whichtypicallyholdsthesearchresultsformanydifferenttypesofsearches.Itpopsuponitsownwhenyourunasearch.
Runtrace Displaysalistofoperationsloggedbyadebuggertrace.
Source Displaysthesourcecodeofthedisassembledmoduleifaprogramdebugdatabaseispresent.
Finally,theSettingsbuttonopenstheOllyDbgsettingswindow.Keepthedefaultsettingsfornow.
Nowthatyou’vehadatourofthemainOllyDbgwindow,let’sexploretheCPU,Patches,andRuntracewindowsmoreclosely.You’llusethosewindowsextensivelyasagamehacker,andknowingyourwayaroundthemiskey.
OllyDbg’sCPUWindowTheCPUwindowinFigure2-2iswheregamehackersspendmostoftheirtimeinOllyDbgbecauseitisthemaincontrolwindowforthedebuggingfeatures.
![Page 61: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/61.jpg)
Figure2-2:OllyDbgCPUwindow
Thiswindowhousesfourdistinctcontrolpanes:thedisassemblerpane➊,theregisterspane➋,thedumppane➌,andthestackpane➍.ThesefourpanesencapsulateOllyDbg’smaindebuggerfunctions,soit’simportanttoknowtheminsideandout.
ViewingandNavigatingaGame’sAssemblyCodeYou’llnavigategamecodeandcontrolmostaspectsofdebuggingfromOllyDbg’sdisassemblerpane.Thispanedisplaystheassemblycodeforthecurrentmodule,anditsdataisneatlydisplayedinatablecomposedoffourdistinctcolumns:Address,Hexdump,Disassembly,andComment.
TheAddresscolumndisplaysthememoryaddressesofeachoperationinthegameprocessyou’reattachedto.Youcandouble-clickanaddressinthis
![Page 62: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/62.jpg)
columntotogglewhetherit’sthedisplaybase.Whenanaddressissetasthedisplaybase,theAddresscolumndisplaysallotheraddressesasoffsetsrelativetoit.
TheHexdumpcolumndisplaysthebytecodeforeachoperation,groupingoperationcodesandparametersaccordingly.Blackbracesspanningmultiplelinesontheleftsideofthiscolumnmarkknownfunctionboundaries.Operationsthathavejumpsgoingtothemareshownwitharight-facingarrowontheinsideofthesebraces.Operationsthatperformjumpsareshownwitheitherup-facingordown-facingarrows,dependingonthedirectioninwhichtheyjump,ontheinsideofthesebraces.Forexample,inFigure2-2,theinstructionataddress0x779916B1(highlightedingray)hasanup-facingarrow,indicatingit’sanupwardjump.Youcanthinkofajumpasagotooperator.
TheDisassemblycolumndisplaystheassemblycodeofeachoperationthegameperforms.So,forexample,youcanconfirmthattheinstructionat0x779916B1inFigure2-2isajumpbylookingattheassembly,whichshowsaJNZ(jumpifnonzero)instruction.Blackbracesinthiscolumnmarktheboundariesofloops.Right-facingarrowsattachedtothesebracespointtotheconditionalstatementsthatcontrolwhethertheloopscontinueorexit.Thethreeright-facingarrowsinthiscolumninFigure2-2pointtoCMP(compare)andTESTinstructions,whichareusedbyassemblycodetocomparevalues.
TheCommentcolumndisplayshuman-readablecommentsabouteachoperationthegameperforms.IfOllyDbgencountersknownAPIfunctionnames,itwillautomaticallyinsertacommentwiththenameofthefunction.Similarly,ifitsuccessfullydetectsargumentsbeingpassedtoafunction,itwilllabelthem(forexample,Arg1,Arg2,...,ArgN).Youcandouble-clickinthiscolumntoaddacustomizedcomment.Blackbracesinthiscolumnmarktheassumedboundariesoffunctioncallparameters.
NOTE
OllyDbginfersfunctionboundaries,jumpdirections,loopstructures,andfunctionparametersduringcodeanalysis,soifthesecolumnslackboundarylinesorjumparrows,justpressCTRL-Atorunacodeanalysisonthebinary.
![Page 63: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/63.jpg)
Whenthedisassemblerpaneisinfocus,thereareafewhotkeysyoucanusetoquicklynavigatecodeandcontrolthedebugger.UseF2forTogglebreakpoint,SHIFT-F12forPlaceconditionalbreakpoint,-(hyphen)forGobackand+(plus)forGoforward(thesetwoworkasyou’dexpectinawebbrowser),*(asterisk)forGotoEIP(whichistheexecutionpointerinthex86architecture),CTRL--(hyphen)forGotopreviousfunction,andCTRL-+
forGotonextfunction.ThedisassemblercanalsopopulatetheReferenceswindowwithdifferent
typesofsearchresults.WhenyouwanttochangetheReferenceswindow’scontents,right-clickinthedisassemblerpane,mouseovertheSearchformenutoexpandit,andselectoneofthefollowingoptions:
AllintermodularcallsSearchesforallcallstofunctionsinremotemodules.Thiscan,forexample,allowyoutoseeeverywherethatagamecallsSleep(),PeekMessage(),oranyotherWindowsAPIfunction,enablingyoutoinspectorsetbreakpointsonthecalls.
AllcommandsSearchesforalloccurrencesofagivenoperationwritteninassembly,wheretheaddedoperatorsCONSTandR32willmatchaconstantvalueoraregistervalue,respectively.OneuseforthisoptionmightbesearchingforcommandslikeMOV[0xDEADBEEF],CONST;MOV[0xDEADBEEF],R32;andMOV[0xDEADBEEF],[R32+CONST]tolistalloperationsthatmodifymemoryattheaddress0xDEADBEEF,whichcouldbeanything,includingtheaddressofyourplayer’shealth.
AllsequencesSearchesforalloccurrencesofagivensequenceofoperations.Thisissimilartothepreviousoptions,butitallowsyoutospecifymultiplecommands.
AllconstantsSearchesforallinstancesofagivenhexadecimalconstant.Forinstance,ifyouentertheaddressofyourcharacter’shealth,thiswilllistallofthecommandsthatdirectlyaccessit.
AllswitchesSearchesforallswitch-caseblocks.
AllreferencedtextstringsSearchesforallstringsreferencedincode.Youcanusethisoptiontosearchthroughallreferencedstringsandseewhatcodeaccessesthem,whichcanbeusefulforcorrelatingin-gametextdisplayswiththecodethatdisplaysthem.Thisoptionisalsoveryusefulforlocatinganydebugassertionorloggingstrings,whichcanbea
![Page 64: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/64.jpg)
tremendoushelpindeterminingthepurposeofcodeparts.
ThedisassemblercanalsopopulatetheNameswindowwithalllabelsinthecurrentmodule(CTRL-N)orallknownlabelsinallmodules(Searchfor▸Nameinallmodules).KnownAPIfunctionswillbeautomaticallylabeledwiththeirnames,andyoucanaddalabeltoacommandbyhighlightingit,pressingSHIFT-;andenteringthelabelwhenprompted.Whenalabeledcommandisreferencedincode,thelabelwillbeshowninplaceoftheaddress.Onewaytousethisfeatureistonamefunctionsthatyou’veanalyzed(justsetalabelonthefirstcommandinafunction)soyoucanseetheirnameswhenotherfunctionscallthem.
ViewingandEditingRegisterContentsTheregisterspanedisplaysthecontentsoftheeightprocessorregisters,alleightflagbits,thesixsegmentregisters,thelastWindowserrorcode,andEIP.Underneaththesevalues,thispanecandisplayeitherFloating-PointUnit(FPU)registersordebugregisters;clickonthepane’sheadertochangewhichregistersaredisplayed.Thevaluesinthispanearepopulatedonlyifyoufreezeyourprocess.Valuesthataredisplayedinredhavebeenchangedsincethepreviouspause.Double-clickonvaluesinthispanetoeditthem.
ViewingandSearchingaGame’sMemoryThedumppanedisplaysadumpofthememoryataspecificaddress.Tojumptoanaddressanddisplaythememorycontents,pressCTRL-Gandentertheaddressintheboxthatappears.YoucanalsojumptotheaddressofanentryintheotherCPUwindowpanesbyright-clickingontheAddresscolumnandselectingFollowindump.
Whiletherearealwaysthreecolumnsinthedumppane,theonlyoneyoushouldalwaysseeistheAddresscolumn,whichbehavesmuchlikeitscousinwithinthedisassemblerpane.Thedatadisplaytypeyouchoosedeterminestheothertwocolumnsshown.Right-clickthedumppanetochangethedisplaytype;fortheoneshowninFigure2-2,you’dright-clickandselectHex▸Hex/ASCII(8bytes).
Youcansetamemorybreakpointonanaddressshowninthedumppanebyright-clickingthataddressandexpandingtheBreakpointsubmenu.Select
![Page 65: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/65.jpg)
Memory▸Onaccessfromthismenutobreakonanycodethatusestheaddressatall,orselectMemory▸Onwritetobreakonlyoncodethatwritestothatspaceinmemory.Toremoveamemorybreakpoint,selectRemovememorybreakpointinthesamemenu;thisoptionappearsonlywhentheaddressyouright-clickhasabreakpoint.
Withoneormorevaluesselectedinthedump,youcanpressCTRL-Rtosearchthecurrentmodule’scodeforreferencestoaddressesoftheselectedvalues;resultsofthissearchappearintheReferenceswindow.YoucanalsosearchforvaluesinthispaneusingCTRL-BforbinarystringsandCTRL-Nforlabels.Afteryouinitiateasearch,pressCTRL-Ltojumptothenextmatch.CTRL-Eallowsyoutoeditanyvaluesyouhaveselected.
NOTE
ThedumpwindowsthatyoucanopenfromtheMemorywindowworkinthesamewayasthedumppane.
ViewingaGame’sCallStackThefinalCPUpaneisthestackpane,andasthenamesuggests,itshowsthecallstack.Likethedumpanddisassemblerpanes,thestackpanehasanAddresscolumn.ThestackpanealsohasaValuecolumn,whichshowsthestackasanarrayof32-bitintegers,andaCommentcolumn,whichshowsreturnaddresses,knownfunctionnames,andotherinformativelabels.Thestackpanesupportsallthesamehotkeysasthedumppane,withtheexceptionofCTRL-N.
MULTICLIENTPATCHINGOnetypeofhack,calledamulticlientpatch,overwritesthesingle-instancelimitationcodewithinagame’sbinarywithno-operationcode,allowingtheusertorunmultiplegameclients,evenwhendoingsoisnormallyforbidden.Becausethecodethatperformsinstancelimitationmustbeexecutedveryearlyafteragameclientislaunched,itcanbenearlyimpossibleforabottoinjectitspatchontime.The
![Page 66: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/66.jpg)
easiestworkaroundforthisistomakemulticlientpatchespersistbyapplyingthemwithinOllyDbgandsavingthemdirectlytothegamebinary.
CreatingCodePatchesOllyDbg’scodepatchesletyoumakeassemblycodemodificationsforagameyouwanttohack,removingtheneedtoengineeratooltailoredtothatspecificgame.Thismakesprototypingcontrolflowhacks—whichmanipulategamebehaviorthroughamixofgamedesignflaws,x86assemblyprotocols,andcommonbinaryconstructs—mucheasier.
Gamehackerstypicallyincludeperfectedpatchesasoptionalfeaturesinabot’stoolsuite,butinsomecases,makingthosefeaturespersistentisactuallymoreconvenientforyourenduser.Luckily,OllyDbgpatchesprovidethecompletefunctionalityyouneedtodesign,test,andpermanentlysavecodemodificationstoanexecutablebinaryusingonlyOllyDbg.
Toplaceapatch,navigatetothelineofassemblycodeyouwanttopatchintheCPUwindow,double-clicktheinstructionyouwishtomodify,placeanewassemblyinstructioninthepop-upprompt,andclickAssemble,asshowninFigure2-3.
Figure2-3:PlacingapatchwithOllyDbg
![Page 67: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/67.jpg)
Alwayspayattentiontothesizeofyourpatch—youcan’tjustresizeandmovearoundassembledcodehoweveryou’dlike.Patcheslargerthanthecodeyouintendtoreplacewilloverflowintosubsequentoperations,potentiallyremovingcriticalfunctionality.Patchessmallerthantheoperationsyouintendtoreplacearesafe,aslongasFillwithNOPsischecked.Thisoptionfillsanyabandonedbyteswithno-operation(NOP)commands,whicharesingle-byteoperationsthatdonothingwhenexecuted.
Allpatchesyouplacearelisted,alongwiththeaddress,size,state,oldcode,newcode,andcomment,inthePatcheswindow.Selectapatchinthislisttoaccessasmallbutpowerfulsetofhotkeys,showninTable2-3.
Table2-3:PatchesWindowHotkeys
OperatorFunction
ENTER Jumpstothepatchinthedisassembler.
spacebar Togglesthepatchonoroff.
F2 Placesabreakpointonthepatch.
SHIFT-F2 Placesaconditionalbreakpointonthepatch.
SHIFT-F4 Placesaconditionallogbreakpointonthepatch.DEL Removesthepatchentryfromthelistonly.
InOllyDbg,youcanalsosaveyourpatchesdirectlytothebinary.First,right-clickinthedisassemblerandclickCopytoexecutable▸Allmodifications.Ifyouwanttocopyonlycertainpatches,highlighttheminthedisassemblypaneandpressCopytoexecutable▸Selectioninstead.
DETERMININGPATCHSIZEThereareafewwaystodeterminewhetheryourpatchwillbeadifferentsizethantheoriginalcode.Forexample,inFigure2-3,youcanseethecommandat0x7790ED2EbeingchangedfromSHRAL,6toSHRAL,7.Ifyoulookatthebytestotheleftofthecommand,yousee3bytesthatrepresentthememoryofthecommand.Thismeansour
![Page 68: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/68.jpg)
newcommandmusteitherbe3bytesorpaddedwithNOPsifit’slessthan3bytes.Furthermore,thesebytesarearrangedintwocolumns.Thefirstcolumncontains0xC0and0x08,whichrepresentthecommandSHRandthefirstoperand,AL.Thesecondcolumncontains0x06,whichrepresentstheoriginaloperand.Becausethesecondcolumnshowsasinglebyte,anyreplacementoperandmustalsobe1byte(between0x00and0xFF).Ifthiscolumnhadshown0x00000006instead,areplacementoperandcouldbeupto4bytesinlength.
TypicalcodepatcheswilleitheruseallNOPstocompletelyremoveacommand(byleavingtheboxemptyandlettingitfilltheentirecommandwithNOPs)orjustreplaceasingleoperand,sothismethodofcheckingpatchsizeisalmostalwayseffective.
TracingThroughAssemblyCodeWhenyourunatraceonanyprogram,OllyDbgsingle-stepsovereveryexecutedoperationandstoresdataabouteachone.Whenthetraceiscomplete,theloggeddataisdisplayedintheRuntracewindow,showninFigure2-4.
Figure2-4:TheRuntracewindow
TheRuntracewindowisorganizedintothefollowingsixcolumns:
![Page 69: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/69.jpg)
BackThenumberofoperationsloggedbetweenanoperationandthecurrentexecutionstate
ThreadThethreadthatexecutedtheoperation
ModuleThemodulewheretheoperationresides
AddressTheaddressoftheoperation
CommandTheoperationthatwasexecuted
ModifiedregistersTheregisterschangedbytheoperationandtheirnewvalues
Whenhackinggames,IfindOllyDbg’stracefeatureveryeffectiveathelpingmefindpointerpathstodynamicmemorywhenCheatEnginescansproveinconclusive.ThisworksbecauseyoucanfollowthelogintheRuntracewindowbackwardfromthepointwhenthememoryisusedtothepointwhereitisresolvedfromastaticaddress.
Thispotentfeature’susefulnessislimitedonlybythecreativityofthehackerusingit.ThoughItypicallyuseitonlytofindpointerpaths,I’vecomeacrossafewothersituationswhereithasproveninvaluable.Theanecdotesin“OllyDbgExpressionsinAction”onpage36willhelptoilluminatethefunctionalityandpoweroftracing.
OllyDbg’sExpressionEngineOllyDbgishometoacustomexpressionenginethatcancompileandevaluateadvancedexpressionswithasimplesyntax.Theexpressionengineissurprisinglypowerfuland,whenutilizedproperly,canbethedifferencebetweenanaverageOllyDbguserandanOllyDbgwizard.Youcanusethisenginetospecifyexpressionsformanyfeatures,suchasconditionalbreakpoints,conditionaltraces,andthecommandlineplug-in.Thissectionintroducestheexpressionengineandtheoptionsitprovides.
NOTE
Partsofthissectionarebasedontheofficialexpressionsdocumentation(http://www.ollydbg.de/Help/i_Expressions.htm).Ihavefound,however,thatafewofthecomponentsdefinedinthedocumentationdon’tseemtowork,
![Page 70: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/70.jpg)
atleastnotinOllyDbgv1.10.TwoexamplesaretheINTandASCIIdatatypes,whichmustbesubstitutedwiththealiasesLONGandSTRING.Forthisreason,hereIincludeonlycomponentsthatI’vepersonallytestedandfullyunderstand.
UsingExpressionsinBreakpointsWhenaconditionalbreakpointistoggledon,OllyDbgpromptsyoutoenteranexpressionforthecondition;thisiswheremostexpressionsareused.Whenthatbreakpointisexecuted,OllyDbgsilentlypausesexecutionandevaluatestheexpression.Iftheresultoftheevaluationisnonzero,executionremainspausedandyouwillseethebreakpointgettriggered.Butiftheresultoftheevaluationis0,OllyDbgsilentlyresumesexecutionasifnothinghappened.
Withthehugenumberofexecutionsthathappenwithinagameeverysecond,you’lloftenfindthatapieceofcodeisexecutedinfartoomanycontextsforabreakpointtobeaneffectivewayofgettingthedatayouarelookingfor.Aconditionalbreakpointpairedwithagoodunderstandingofthecodesurroundingitisafoolproofwaytoavoidthesesituations.
UsingOperatorsintheExpressionEngineFornumericdatatypes,OllyDbgexpressionssupportgeneralC-styleoperators,asseeninTable2-4.Whilethereisnocleardocumentationontheoperatorprecedence,OllyDbgseemstofollowC-styleprecedenceandcanuseparenthesizedscoping.
Table2-4:OllyDbgNumericOperators
OperatorFunction
a==b Returns1ifaisequaltob,elsereturns0.a!=b Returns1ifaisnotequaltob,elsereturns0.a>b Returns1ifaisgreaterthanb,elsereturns0.a<b Returns1ifaislessthanb,elsereturns0.a>=b Returns1ifaisgreaterthanorequaltob,elsereturns0.a<=b Returns1ifaislessthanorequaltob,elsereturns0.
![Page 71: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/71.jpg)
a<=b Returns1ifaislessthanorequaltob,elsereturns0.a&&b
Returns1ifaandbarebothnonzero,elsereturns0.a||b Returns1ifeitheraorbarenonzero,elsereturns0.a^b ReturnstheresultofXOR(a,b).a%b ReturnstheresultofMODULUS(a,b).a&b ReturntheresultofAND(a,b).a|b ReturntheresultofOR(a,b).a<<b Returnstheresultofashiftedbbitstotheleft.a>>b Returnstheresultofashiftedbbitstotheright.a+b Returnsthesumofaplusb.a-b Returnsthedifferenceofaminusb.a/b Returnsthequotientofadividedbyb.a*b Returnstheproductofatimesb.+a Returnsthesignedrepresentationofa.-a Returnsa*-1.!a Returns1ifais0,elsereturns0.
Forstrings,ontheotherhand,theonlyavailableoperatorsare==and!=,whichbothadheretothefollowingsetofrules:
•Stringcomparisonsarecaseinsensitive.
•Ifonlyoneoftheoperandsisastringliteral,thecomparisonwillterminateafteritreachesthelengthoftheliteral.Asaresult,theexpression[STRINGEAX]=="ABC123",whereEAXisapointertothestringABC123XYZ,willevaluateto1insteadof0.
•Ifnotypeisspecifiedforanoperandinastringcomparisonandtheotheroperandisastringliteral(forexample,"MyString"!=EAX),thecomparisonwillfirstassumethenonliteraloperandisanASCIIstring,and,ifthatcomparewouldreturn0,itwilltryasecondcompareassumingthe
![Page 72: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/72.jpg)
operandisaUnicodestring.
Ofcourse,operatorsaren’tmuchusewithoutoperands.Let’slookatsomeofthedatayoucanevaluateinexpressions.
WorkingwithBasicExpressionElementsExpressionsareabletoevaluatemanydifferentelements,including:
CPUregistersEAX,EBX,ECX,EDX,ESP,EBP,ESI,andEDI.Youcanalsousethe1-byteand2-byteregisters(forexample,ALforthelowbyteandAXforthelowwordofEAX).EIPcanalsobeused.
SegmentregistersCS,DS,ES,SS,FS,andGS.
FPUregistersST0,ST1,ST2,ST3,ST4,ST5,ST6,andST7.
SimplelabelsCanbeAPIfunctionnames,suchasGetModuleHandle,oruser-definedlabels.
WindowsconstantsSuchasERROR_SUCCESS.
IntegersArewritteninhexadecimalformatordecimalformatiffollowedbyatrailingdecimalpoint(forexample,FFFFor65535.).
Floating-pointnumbersAllowexponentsindecimalformat(forexample,654.123e-5).
StringliteralsArewrappedinquotationmarks(forexample,"mystring").
Theexpressionsenginelooksfortheseelementsintheorderthey’relistedhere.Forexample,ifyouhavealabelthatmatchesthenameofaWindowsconstant,theengineusestheaddressofthelabelinsteadoftheconstant’svalue.Butifyouhavealabelnamedafteraregister,suchasEAX,theengineusestheregistervalue,notthelabelvalue.
AccessingMemoryContentswithExpressionsOllyDbgexpressionsarealsopowerfulenoughtoincorporatememoryreading,whichyoucandobywrappingamemoryaddress,oranexpressionthatevaluatestoone,insquarebrackets.Forexample,[EAX+C]and[401000]
![Page 73: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/73.jpg)
representthecontentsattheaddressesEAX+Cand401000.ToreadthememoryasatypeotherthanDWORD,youcanspecifythedesiredtypeeitherbeforethebrackets,asinBYTE[EAX],orasthefirsttokenwithinthem,asin[STRINGESP+C].SupportedtypesarelistedinTable2-5.
Table2-5:OllyDbgDataTypes
DatatypeInterpretationBYTE 8-bitinteger(unsigned)CHAR 8-bitinteger(signed)WORD 16-bitinteger(unsigned)SHORT 16-bitinteger(signed)DWORD 32-bitinteger(unsigned)LONG 32-bitinteger(signed)FLOAT 32-bitfloating-pointnumberDOUBLE 64-bitfloating-pointnumberSTRING PointertoanASCIIstring(null-terminated)UNICODE PointertoaUnicodestring(null-terminated)
PluggingmemorycontentsdirectlyintoyourOllyDbgexpressionsisincrediblyusefulingamehacking,inpartbecauseyoucantellthedebuggertocheckacharacter’shealth,name,gold,andsooninmemorybeforebreaking.You’llseeanexampleofthisin“PausingExecutionWhenaSpecificPlayer’sNameIsPrinted”onpage37.
OllyDbgExpressionsinActionExpressionsinOllyDbguseasyntaxsimilartothatofmostprogramminglanguages;youcanevencombinemultipleexpressionsandnestoneexpressionwithinanother.Gamehackers(really,allhackers)commonlyusethemtocreateconditionalbreakpoints,asIdescribedin“UsingExpressionsinBreakpoints”onpage34,butyoucanusetheminmanydifferentplacesinOllyDbg.Forinstance,OllyDbg’scommandlineplug-incanevaluate
![Page 74: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/74.jpg)
expressionsinplaceanddisplaytheirresults,allowingyoutoeasilyreadarbitrarymemory,inspectvaluesthatarebeingcalculatedbyassemblycode,orquicklygettheresultsofmathematicalequations.Furthermore,hackerscanevencreateintelligent,position-agnosticbreakpointsbycouplingexpressionswiththetracefeature.
Inthissection,I’llsharesomeanecdoteswheretheexpressionenginehascomeinhandyduringmywork.Iwillexplainmythoughtprocess,walkthroughmyentiredebuggingsession,andbreakeachexpressiondownintoitscomponentpartssoyoucanseesomewaystouseOllyDbgexpressionsingamehacking.
NOTE
Theseexamplescontainsomeassemblycode,butifyoudon’thavemuchexperiencewithassembly,don’tworry.JustignorethefinedetailsandknowthatvalueslikeECX,EAX,andESPareprocessregistersliketheonesdiscussedin“ViewingandEditingRegisterContents”onpage29.Fromthere,I’llexplaineverythingelse.
Ifyougetconfusedaboutanoperator,element,ordatatypeinanexpressionasIwalkthroughtheseanecdotes,justreferto“OllyDbg’sExpressionEngine”onpage33.
PausingExecutionWhenaSpecificPlayer’sNameIsPrintedDuringoneparticulardebuggingsession,Ineededtofigureoutexactlywhatwashappeningwhenagamewasdrawingthenamesofplayersonscreen.Specifically,Ineededtoinvokeabreakpointbeforethegamedrewthename“Player1,”ignoringallothernamesthatweredrawn.
FiguringOutWheretoPauseAsastartingpoint,IusedCheatEnginetofindtheaddressofPlayer1’snameinmemory.OnceIhadtheaddress,IusedOllyDbgtosetamemorybreakpointonthefirstbyteofthestring.Everytimethisbreakpointgothit,IquicklyinspectedtheassemblycodetodeterminehowitwasusingPlayer
![Page 75: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/75.jpg)
1’sname.Eventually,IfoundthenamebeingaccesseddirectlyaboveacalltoafunctionthatIhadpreviouslygiventhenameprintText().Ihadfoundthecodethatwasdrawingthename.
IremovedmymemorybreakpointandreplaceditwithacodebreakpointonthecalltoprintText().Therewasaproblem,however:becausethecalltoprintText()wasinsidealoopthatiteratedovereveryplayerinthegame,mynewbreakpointwasgettinghiteverytimeanamewasdrawn—andthatwasmuchtoooften.Ineededtofixittohitonlyonaspecificplayer.
Inspectingtheassemblycodeatmypreviousmemorybreakpointtoldmethateachplayer’snamewasaccessedusingthefollowingassemblycode:
PUSHDWORDPTRDS:[EAX+ECX*90+50]
TheEAXregistercontainedtheaddressofanarrayofplayerdata;I’llcallitplayerStruct.ThesizeofplayerStructwas0x90bytes,theECXregistercontainedtheiterationindex(thefamousvariablei),andeachplayer’snamewasstored0x50bytesafterthestartofitsrespectiveplayerStruct.ThismeantthatthisPUSHinstructionessentiallyputEAX[ECX].name(thenameoftheplayeratindexi)onthestacktobepassedasanargumenttotheprintText()functioncall.Theloop,then,brokedowntosomethinglikethefollowingpsuedocode:
playerStructEAX[MAX_PLAYERS];//thisisfilledelsewherefor(int➊ECX=0;ECX<MAX_PLAYERS;ECX++){char*name=➋EAX[ECX].name;breakpoint();//mycodebreakpointwasbasicallyrighthereprintText(name);}
Purelythroughanalysis,IdeterminedthattheplayerStruct()functioncontaineddataforallplayers,andtheloopiteratedoverthetotalnumberofplayers(countingupwithECX➊),fetchedthecharactername➋foreachindex,andprintedthename.
CraftingtheConditionalBreakpointKnowingthat,topauseexecutiononlywhenprinting“Player1”allIhadtodowascheckthecurrentplayernamebeforeexecutingmybreakpoint.Inpseudocode,thenewbreakpointwouldlooklikethis:
![Page 76: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/76.jpg)
if(EAX[ECX].name=="Player1")breakpoint();
OnceIfiguredouttheformofmynewbreakpoint,IneededtoaccessEAX[ECX].namefromwithintheloop.That’swhereOllyDbg’sexpressionenginecamein:Icouldachievemygoalbymakingslightmodificationstotheexpressionthattheassemblycodeused,leavingmewiththisexpression:
[STRINGEAX+ECX*0x90+0x50]=="Player1"
IremovedthecodebreakpointonprintText()andreplaceditwithaconditionalbreakpointthatusedthisexpression,whichtoldOllyDbgtobreakonlyifthestringvaluestoredatEAX+ECX*0x90+0x50matchedPlayer1’sname.Thisbreakpointhitonlywhen"Player1"wasbeingdrawn,allowingmetocontinuemyanalysis.
Theamountofworkittooktoengineerthisbreakpointmightseemextensive,butwithpractice,theentireprocessbecomesasintuitiveaswritingcode.Experiencedhackerscandothisinamatterofseconds.
Inpractice,thisbreakpointenabledmetoinspectcertainvaluesintheplayerStruct()functionfor"Player1"assoonasheappearedonscreen.Doingitthiswaywasimportant,asthestatesofthesevalueswererelevanttomyanalysisonlyinthefirstfewframesaftertheplayerenteredthescreen.Creativelyusingbreakpointslikethiscanenableyoutoanalyzeallsortsofcomplexgamebehavior.
PausingExecutionWhenYourCharacter’sHealthDropsDuringanotherdebuggingsession,Ineededtofindthefirstfunctioncalledaftermycharacter’shealthdroppedbelowthemaximum.Iknewtwowaystoapproachthisproblem:
•Findeverypieceofcodethataccessesthehealthvalueandplaceaconditionalbreakpointthatchecksthehealthoneachone.Then,onceoneofthesebreakpointsishit,single-stepthroughthecodeuntilthenextfunctioncall.
•UseOllyDbg’stracefunctiontocreateadynamicbreakpointthatcanstopexactlywhereIneed.
Thefirstmethodrequiredmoresetupandwasnoteasilyrepeatable,mostlyduetothesheernumberofbreakpointsneededandthefactthatI’d
![Page 77: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/77.jpg)
mostlyduetothesheernumberofbreakpointsneededandthefactthatI’dhavetosingle-stepbyhand.Incontrast,thelattermethodhadaquicksetup,andsinceitdideverythingautomatically,itwaseasilyrepeatable.Thoughusingthetracefunctionwouldslowthegamedownconsiderably(everysingleoperationwascapturedbythetrace),Ichosethelattermethod.
WritinganExpressiontoCheckHealthOnceagain,IstartedbyusingCheatEnginetofindtheaddressthatstoredmyhealth.Usingthemethoddescribedin“CheatEngine’sMemoryScanner”onpage5,Ideterminedtheaddresstobe0x40A000.
Next,IneededanexpressionthattoldOllyDbgtoreturn1whenmyhealthwasbelowmaximumandreturn0otherwise.Knowingthatmyhealthwasstoredat0x40A000andthatthemaximumvaluewas500,Iinitiallydevisedthisexpression:
[0x40A000]<500.
Thisexpressionwouldinvokeabreakwhenmyhealthwasbelow500(remember,decimalnumbersmustbesuffixedwithaperiodintheexpressionengine),butinsteadofwaitingforafunctiontobecalled,thebreakwouldhappenimmediately.Toensurethatitwaiteduntilafunctionwascalled,Iappendedanotherexpressionwiththe&&operator:
[0x40A000]<500.&&[➊BYTEEIP]==0xE8
Onx86processors,theEIPregisterstorestheaddressoftheoperationbeingexecuted,soIdecidedtocheckthefirstbyteatEIP➊toseeifitwasequalto0xE8.Thisvaluetellstheprocessortoexecuteanearfunctioncall,whichisthetypeofcallIwaslookingfor.
Beforestartingmytrace,Ihadtodoonelastthing.Becausethetracefeaturerepeatedlysingle-steps(TraceintousesstepintoandTraceoverusesstepover,asdescribedin“ABriefLookatOllyDbg’sUserInterface”onpage24),Ineededtostartthetraceatalocationscopedatorabovethelevelofanycodethatcouldpossiblyupdatethehealthvalue.
FiguringOutWheretoStarttheTraceTofindagoodlocation,Iopenedthegame’smainmoduleinOllyDbg’s
![Page 78: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/78.jpg)
CPUwindow,right-clickedinthedisassemblerpane,andselectedSearchfor▸Allintermodularcalls.TheReferenceswindowpoppedupanddisplayedalistofexternalAPIfunctionsthatwerecalledbythegame.NearlyallgamingsoftwarepollsfornewmessagesusingtheWindowsUSER32.PeekMessage()function,soIsortedthelistusingtheDestinationcolumnandtypedPEEK(youcansearchthelistbysimplytypinganamewiththewindowinfocus)tolocatethefirstcalltoUSER32.PeekMessage().
ThankstotheDestinationsorting,everycalltothisfunctionwaslistedinacontiguouschunkfollowingthefirst,asshowninFigure2-5.IsetabreakpointoneachbyselectingitandpressingF2.
Figure2-5:OllyDbg’sFoundintermodularcallswindow
ThoughtherewerearoundadozencallstoUSER32.PeekMessage(),onlytwoofthemweresettingoffmybreakpoints.Evenbetter,theactivecallswerebesideoneanotherinanunconditionalloop.Atthebottomofthisloopwereanumberofinternalfunctioncalls.Thislookedexactlylikeamaingameloop.
ActivatingtheTrace
![Page 79: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/79.jpg)
Tofinallysetmytrace,Iremovedallofmypreviousbreakpointsandplacedoneatthetopofthesuspectedmainloop.Iremovedthebreakpointassoonasitwashit.IthenpressedCTRL-TfromtheCPUwindow,whichbroughtupadialogcalledConditiontopauseruntrace,showninFigure2-6.Withinthisnewdialog,IenabledtheConditionisTRUEoption,placedmyexpressionintheboxbesideit,andpressedOK.Then,IwentbacktotheCPUwindowandpressedCTRL-F11tobeginaTraceIntosession.
Figure2-6:Conditiontopauseruntracedialog
Oncethetracebegan,thegameransoslowlyitwasnearlyunplayable.Todecreasemytestcharacter’shealth,Iopenedasecondinstanceofthegame,loggedintoadifferentcharacter,andattackedmytestcharacter.Whentheexecutionofthetracecaughtuptorealtime,OllyDbgsawmyhealthchangeandtriggeredthebreakpointonthefollowingfunctioncall—justasexpected.
Inthisgame,themainpiecesofcodethatwouldmodifythehealthvalueweredirectlyinvokedfromthenetworkcode.Usingthistrace,Iwasabletofindthefunctionthatthenetworkmodulecalleddirectlyafteranetworkpackettoldthegametochangetheplayer’shealth.Here’sthepsuedocodeofwhatthegamewasdoing:
![Page 80: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/80.jpg)
voidnetwork::check(){while(this->hasPacket()){packet=this->getPacket();if(packet.type==UPDATE_HEALTH){oldHealth=player->health;player->health=packet.getInteger();➊observe(HEALTH_CHANGE,oldHealth,player->health);}}}
Iknewthegamehadcodethatneededtoexecuteonlywhentheplayer’shealthwaschanged,andIneededtoaddcodethatcouldalsorespondtosuchchanges.Withoutknowingtheoverallcodestructure,Iguessedthatthehealth-dependentcodewouldbeexecutedfromsomefunctioncalldirectlyafterhealthwasupdated.Mytraceconditionalbreakpointconfirmedthishunch,asitbrokedirectlyontheobserve()function➊.Fromthere,Iwasabletoplaceahookonthefunction(hooking,awaytointerceptfunctioncalls,isdescribedin“HookingtoRedirectGameExecution”onpage153)andexecutemyowncodewhentheplayer’shealthchanged.
OllyDbgPlug-insforGameHackersOllyDbg’shighlyversatileplug-insystemisperhapsoneofitsmostpowerfulfeatures.ExperiencedgamehackersoftenconfiguretheirOllyDbgenvironmentswithdozensofusefulplug-ins,bothpubliclyavailableandcustom-made.
Youcandownloadpopularplug-insfromtheOpenRCE(http://www.openrce.org/downloads/browse/OllyDbg_Plugins)andtuts4you(http://www.tuts4you.com/download.php?list.9/)plug-inrepositories.Installingthemiseasy:justunziptheplug-infilesandplacetheminsideOllyDbg’sinstallationfolder.
Onceinstalled,someplug-inscanbeaccessedfromtheOllyDbg’sPluginmenuitem.Otherplug-ins,however,mightbefoundonlyinspecificplacesthroughouttheOllyDbginterface.
Youcanfindhundredsofpotentplug-insusingtheseonlinerepositories,butyoushouldbecarefulwhenconstructingyourarsenal.Workinginanenvironmentbloatedbyunusedplug-inscanactuallyimpedeproductivity.Inthissection,I’vecarefullyselectedfourplug-insthatIbelievearenotonly
![Page 81: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/81.jpg)
thissection,I’vecarefullyselectedfourplug-insthatIbelievearenotonlyintegraltoagamehacker’stoolkitbutalsononinvasivetotheenvironment.
CopyingAssemblyCodewithAsm2ClipboardAsm2Clipboardisaminimalisticplug-infromtheOpenRCErepositorythatallowsyoutocopychunksofassemblycodefromthedisassemblerpanetotheclipboard.Thiscanbeusefulforupdatingaddressoffsetsanddevisingcodecaves,twogame-hackingessentialsIcoverdeeplyinChapters5and7.
WithAsm2Clipboardinstalled,youcanhighlightablockofassemblycodeinthedisassembler,right-clickthehighlightedcode,expandtheAsm2Clipboardsubmenu,andselecteitherCopyfixedAsmcodetoclipboardorCopyAsmcodetoclipboard.Thelatterprependsthecodeaddressofeachinstructionasacomment,whiletheformercopiesonlythepurecode.
AddingCheatEnginetoOllyDbgwithCheatUtilityTheCheatUtilityplug-infromtuts4youprovidesahighlyslimmed-downversionofCheatEnginewithinOllyDbg.WhileCheatUtilityonlyallowsyoutodoexact-valuescanswithaverylimitednumberofdatatypes,itcanmakesimplescansmucheasierwhenyoudon’tneedthefullfunctionalityofCheatEnginetofindwhatyou’relookingfor.AfterinstallingCheatUtility,toopenitsinterface(showninFigure2-7),selectPlugins▸Cheatutility▸Start.
![Page 82: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/82.jpg)
Figure2-7:CheatUtilityinterface
CheatUtility’suserinterfaceandoperationmimicCheatEngineclosely,soreviewChapter1ifyouneedarefresher.
NOTE
GamesInvader,anupdatedversionofCheatUtilityalsofromtuts4you,wascreatedtoprovidemorefunctionality.I’vefounditbuggy,however,andIpreferCheatUtilitysinceIcanalwaysuseCheatEngineforadvancedscans.
ControllingOllyDbgThroughtheCommandLineThecommandlineplug-inenablesyoutocontrolOllyDbgthroughasmallcommandlineinterface.Toaccesstheplug-in,eitherpressALT-F1orselectPlugins▸Commandline▸Commandline.Youshouldthenseeawindow,showninFigure2-8,whichactsasthecommandlineinterface.
Figure2-8:Commandlineinterface
![Page 83: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/83.jpg)
Toexecuteacommand,typeitintotheinputbox➊andpressENTER.Youwillseeasession-levelcommandhistoryinthecenterlist➋,andthebottomlabeldisplaysthecommand’sreturnvalue➌(ifany).
Thoughtherearemanycommandsavailable,Ifindamajorityofthemuseless.Iprimarilyusethistoolasawaytotestthatexpressionsareparsingasexpectedandasahandycalculator,butthereareafewadditionalusecasesthatarealsoworthmentioning.I’vedescribedtheseinTable2-6.
Table2-6:CommandLinePlug-inCommands
Command Function
BCidentifier
Removesanybreakpointspresentonidentifier,whichcanbeacodeaddressorAPIfunctionname.
BPidentifier[,condition]
Placesadebuggerbreakpointonidentifier,whichcanbeacodeaddressorAPIfunctionname.WhenidentifierisanAPIfunctionname,thebreakpointwillbeplacedonthefunctionentrypoint.Theconditionparameterisanoptionalexpressionthat,ifpresent,willbesetasthebreakpointcondition.
BPXlabel Placesadebuggerbreakpointoneveryinstanceoflabelwithinthemodulecurrentlybeingdisassembled.ThislabelwilltypicallybeanAPIfunctionname.
CALCexpression?expression
Evaluatesexpressionanddisplaystheresult.
HDaddress Removesanyhardwarebreakpointspresentonaddress.HEaddress Placesahardwareon-executebreakpointonaddress.HRaddress Placesahardwareon-accessbreakpointonaddress.Onlyfour
hardwarebreakpointscanexistatatime.HWaddress Placesahardwareon-writebreakpointonaddress.MD Removesanyexistingmemorybreakpoint,ifpresent.MRaddress1,address2
Placesamemoryon-accessbreakpointstartingataddress1andspanninguntiladdress2.Willreplaceanyexistingmemorybreakpoint.
![Page 84: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/84.jpg)
MWaddress1,address2
Placesamemoryon-writebreakpointstartingataddress1and
spanninguntiladdress2.Willreplaceanyexistingmemorybreakpoint.
WATCHexpressionWexpression
OpenstheWatcheswindowandaddsexpressiontothewatchlist.Expressionsinthislistwillbereevaluatedeverytimetheprocessreceivesamessageandtheevaluationresultswillbedisplayedbesidethem.
Thecommandlineplug-inwasmadebytheOllyDbgdeveloperandshouldcomepreinstalledwithOllyDbg.
VisualizingControlFlowwithOllyFlowOllyFlow,whichcanbefoundintheOpenRCEplug-indirectory,isapurelyvisualplug-inthatcangeneratecodegraphsliketheoneinFigure2-9anddisplaythemusingWingraph32.
Figure2-9:AnOllyFlowfunctionflowchart
![Page 85: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/85.jpg)
NOTE
Wingraph32isnotprovidedwithOllyFlow,butitisavailablewiththefreeversionofIDAhere:https://www.hex-rays.com/products/ida/.Downloaditanddropthe.exeinyourOllyDbginstallationfolder.
Thoughnotinteractive,thesegraphsallowyoutoeasilyidentifyconstructssuchasloopsandnestedif()statementsingamecode,whichcanbeparamountincontrolflowanalysis.WithOllyFlowinstalled,youcangenerateagraphbygoingtoPlugins▸OllyFlow(alternatively,right-clickinthedisassemblerpaneandexpandtheOllyFlowgraphsubmenu)andselectingoneofthefollowingoptions:
GeneratefunctionflowchartGeneratesagraphofthefunctioncurrentlyinscope,breakingapartdifferentcodeblocksandshowingjumppaths.Figure2-9showsafunctionflowchart.Withoutadoubt,thisisOllyFlow’smostusefulfeature.
GeneratexrefsfromgraphGeneratesagraphofallfunctionscalledbythefunctionthatiscurrentlyinscope.
GeneratexrefstographGeneratesagraphofallfunctionsthatcallthefunctioncurrentlyinscope.
GeneratecallstackgraphGeneratesagraphoftheassumedcallpathfromtheprocessentrypointtothefunctioncurrentlyinscope.
GeneratemodulegraphTheoreticallygeneratesacompletegraphofallfunctioncallsintheentiremodule,butrarelyactuallyworks.
TogetanideaoftheusefulnessofOllyFlow,takealookatthegraphinFigure2-9andcompareittotherelativelysimpleassemblyfunctionthatgeneratedit:
76f86878:➊MOVEAX,DWORDPTRDS:[76FE7E54]TESTAL,1JEntdll.76F8689B76f86881:➋MOVEAX,DWORDPTRFS:[18]MOVEAX,DWORDPTRDS:[EAX+30]ORDWORDPTRDS:[EAX+68],2000000
![Page 86: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/86.jpg)
MOVEAX,DWORDPTRDS:[76FE66E0]ORDWORDPTRDS:[EAX],1JMPntdll.76F868B276f8689b:➌TESTEAX,8000JEntdll.76F868B276f868a2:➍MOVEAX,DWORDPTRFS:[18]MOVEAX,DWORDPTRDS:[EAX+30]ORDWORDPTRDS:[EAX+68],200000076f868b2:➎MOVAL,1RETN
TherearefiveboxesinFigure2-9,andtheymaptothefivepiecesofthisfunction.Thefunctionstartswith➊,anditfallsthroughto➋ifthebranchfailsorjumpsto➌ifitsucceeds.After➋executes,itjumpsdirectlytopiece➎,whichthenreturnsoutofthefunction.After➌executes,iteitherfallsthroughto➍orbranchesto➎toreturndirectly.After➍executes,itunconditionallyfallsthroughto➎.WhatthisfunctiondoesisirrelevanttounderstandingOllyFlow;fornow,justfocusonseeinghowthecodemapstothegraph.
PATCHINGANIF()STATEMENTIfyouthinkyou’rereadytogetyourhandsdirtywithOllyDbg,keepreading.Gotohttps://www.nostarch.com/gamehacking/,downloadthebook’sresourcefiles,grabBasicDebugging.exe,andexecuteit.Atfirstglance,you’llseethatitlooksliketheclassicgamePong.InthisversionofPong,theballisinvisibletoyouwhenitisonyouropponent’sscreen.Yourtaskistodisablethisfeaturesothatyoucanalwaysseetheball.Tomakeiteasierforyou,I’vemadethegameautonomous.Youdon’thavetoplay,onlyhack.
Tostart,attachOllyDbgtothegame.ThenfocustheCPUwindowonthemainmodule(findthe.exeinthemodulelistanddouble-clickit)andusetheReferencedtextstringsfeaturetolocatethestringthatisdisplayedwhentheballishidden.Next,double-clickthestringtobringitupinthecodeandanalyzethesurroundingcode
![Page 87: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/87.jpg)
untilyoufindtheif()statementthatdetermineswhethertohidetheball.Lastly,usingthecode-patchingfeature,patchtheif()statementsotheballisalwaysdrawn.Asanaddedbonus,youmighttryusingOllyFlowtographthisfunctionsoyoucangetabetterunderstandingofwhatexactlyitisdoing.(Hint:Theif()statementcheckswhethertheball’sx-coordinateislessthan0x140.Ifso,itjumpstocodethatdrawstheball.Ifnot,itdrawsthescenewithouttheball.Ifyoucanchange0x140to,say,0xFFFF,theballwillnevergethidden.)
ClosingThoughtsOllyDbgisamuchmorecomplexbeastthanCheatEngine,butyou’lllearnbestbyusingit,sodiveinandgetyourhandsdirty!Youcanstartbypairingthecontrolstaughtinthischapterwithyourdebuggingskillsandgoingtoworkonsomerealgames.Ifyouarenotyetreadytotamperwithyourvirtualfate,however,trytacklingtheexamplein“Patchinganif()Statement”forapracticeenvironment.Whenyou’redone,readontoChapter3,whereI’llintroduceyoutoProcessMonitorandProcessExplorer,twotoolsyou’llfindinvaluableingame-hackingreconnaissance.
![Page 88: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/88.jpg)
3RECONNAISSANCEWITHPROCESSMONITORANDPROCESSEXPLORER
CheatEngineandOllyDbgcanhelpyoutearapartagame’smemoryandcode,butyoualsoneedtounderstandhowthegameinteractswithfiles,registryvalues,networkconnections,andotherprocesses.Tolearnhowthoseinteractionswork,youmustusetwotoolsthatexcelatmonitoringtheexternalactionsofprocesses:ProcessMonitorandProcessExplorer.Withthesetools,youcantrackdownthecompletegamemap,locatesavefiles,identifyregistrykeysusedtostoresettings,andenumeratetheInternetProtocol(IP)addressesofremotegameservers.
Inthischapter,I’llteachyouhowtousebothProcessMonitorandProcessExplorertologsystemeventsandinspectthemtoseehowagamewasinvolved.Usefulmainlyforinitialreconnaissance,thesetoolsareamazingatgivingaclear,verbosepictureofexactlyhowagameinteractswithyoursystem.YoucandownloadbothprogramsfromtheWindowsSysinternalswebsite(https://technet.microsoft.com/en-us/sysinternals/).
ProcessMonitorYoucanlearnalotaboutagamesimplybyexploringhowitinteractswiththeregistry,filesystem,andnetwork.ProcessMonitorisapowerfulsystem-monitoringtoolthatlogssucheventsinrealtimeandletsyouseamlessly
![Page 89: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/89.jpg)
monitoringtoolthatlogssucheventsinrealtimeandletsyouseamlesslyintegratethedataintoadebuggingsession.Thistoolprovidesextensiveamountsofusefuldataregardingagame’sinteractionwiththeexternalenvironment.Withcalculatedreview(andsometimes,spontaneousintuition)onyourpart,thisdatacanrevealdetailsaboutdatafiles,networkconnections,andregistryeventsthatarehelpfultoyourabilitytoseeandmanipulatehowthegamefunctions.
Inthissection,I’llshowyouhowtouseProcessMonitortologdata,navigateit,andmakeeducatedguessesaboutthefilesagameinteractswith.Afterthisinterfacetour,you’llhaveachancetotryoutProcessMonitorforyourselfin“FindingaHighScoreFile”onpage55.
LoggingIn-GameEventsProcessMonitor’slogscanholdallsortsofpotentiallyusefulinformation,buttheirmostpracticaluseistohelpyoufigureoutwheredatafiles,suchasin-gameitemdefinitions,mightbestored.WhenyoustartProcessMonitor,thefirstdialogyouseeistheProcessMonitorFilter,showninFigure3-1.
Figure3-1:ProcessMonitorFilterdialog
Thisdialogallowsyoutoshoworsuppresseventsbasedonanumberofdynamicpropertiestheypossess.Tostartmonitoringprocesses,selectProcessName▸Is▸YourGameFilename.exe▸Includeandthenpress
![Page 90: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/90.jpg)
Add,Apply,andOK.ThistellsProcessMonitortoshoweventsinvokedbyYourGameFilename.exe.Withtheproperfiltersset,youwillbetakentothemainwindowshowninFigure3-2.
Figure3-2:ProcessMonitormainwindow
ToconfigurethecolumnsdisplayedinProcessMonitor’slogarea,right-clickontheheaderandchooseSelectColumns.There’sanimpressivenumberofoptions,butIrecommendseven.
TimeofDayLetsyouseewhenactionsarehappening.
ProcessNameIsusefulifyou’remonitoringmultipleprocesses,butwiththesingle-processfilterthatistypicallyusedforgames;disablingthisoptioncansavepreciousspace.
ProcessIDIslikeProcessName,butitshowstheIDratherthanthename.
OperationShowswhatactionwasperformed;thus,thisoptioniscompulsory.
PathShowsthepathoftheaction’starget;alsocompulsory.
DetailIsusefulonlyinsomecases,butenablingitwon’thurt.
ResultShowswhenactions,suchasloadingfiles,fail.
Asyoushowmorecolumns,thelogcangetverycrowded,butstickingwiththeseoptionsshouldhelpkeeptheoutputsuccinct.
![Page 91: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/91.jpg)
withtheseoptionsshouldhelpkeeptheoutputsuccinct.Oncethemonitorisrunningandyou’vedefinedthecolumnsyouwishto
see,therearefiveeventclassfilters,outlinedinblackinFigure3-2,thatyoucantoggletocleanupyourlogsevenfurther.Eventclassfiltersletyouchoosewhicheventstoshowinthelog,basedontype.Fromlefttoright,thesefiltersareasfollows:
RegistryShowsallregistryactivity.Therewillbealotofwhitenoiseintheregistryuponprocesscreation,asgamesrarelyusetheregistryandWindowslibrariesalwaysuseit.Leavingthisfilterdisabledcansavealotofspaceinthelog.
FilesystemShowsallfilesystemactivity.Thisisthemostimportanteventclassfilter,sinceknowingwheredatafilesarestoredandhowtheyareaccessedisintegraltowritinganeffectivebot.
NetworkShowsallnetworkactivity.Thecallstackonnetworkeventscanbeusefulinfindingnetwork-relatedcodewithinagame.
ProcessandthreadactivityShowsallprocessandthreadactions.Thecallstackontheseeventscangiveyouinsightintohowagame’scodehandlesthreads.
ProcessprofilingPeriodicallyshowsinformationaboutthememoryandCPUusageofeachrunningprocess;agamehackerwillrarelyuseit.
Ifclass-leveleventfilteringisstillnotpreciseenoughtofilteroutunwantedpollutioninyourlogs,right-clickonspecificeventsforevent-levelfilteringoptions.Onceyouhaveyoureventfilteringconfiguredtologonlywhatyouneed,youcanbeginnavigatingthelog.Table3-1listssomeusefulhotkeysforcontrollingthelog’sbehavior.
Table3-1:ProcessMonitorHotkeys
HotkeyAction
CTRL-E Toggleslogging.
CTRL-A Togglesautomaticscrollingofthelog.
CTRL-X Clearsthelog.
CTRL-L DisplaystheFilterdialog.
CTRL- DisplaystheHighlightdialog.Thisdialoglooksverysimilartothe
![Page 92: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/92.jpg)
CTRL-H
DisplaystheHighlightdialog.ThisdialoglooksverysimilartotheFilterdialog,butitisusedtoindicatewhicheventsshouldbehighlighted.
CTRL-F DisplaystheSearchdialog.
CTRL-P DisplaystheEventPropertiesdialogfortheselectedevent.
Asyounavigatethelog,youcanexaminetheoperationsrecordedtoseethefine-graineddetailsofanevent.
InspectingEventsintheProcessMonitorLogProcessMonitorlogseverydatapointitpossiblycanaboutanevent,enablingyoutolearnmoreabouttheseeventsthanjustthefilestheyactupon.Carefullyinspectingdata-richcolumns,suchasResultandDetail,canyieldsomeveryinterestinginformation.
Forexample,I’vefoundthatgamessometimesreaddatastructures,elementbyelement,directlyfromfiles.Thisbehaviorisapparentwhenalogcontainsalargenumberofreadstothesamefile,whereeachreadhassequentialoffsetsbutdifferinglengths.ConsiderthehypotheticaleventlogshowninTable3-2.
Table3-2:ExampleEventLog
OperationPath Detail
CreateFileC:\file.datDesiredAccess:Read
ReadFile C:\file.datOffset:0Size:4
ReadFile C:\file.datOffset:4Size:2
ReadFile C:\file.datOffset:6Size:2
ReadFile C:\file.datOffset:8Size:4
ReadFile C:\file.datOffset:12Size:4
... ... ...Continuestoreadchunksof4bytesforawhile
Thislogrevealsthatthegameisreadingastructurefromthefilepiecebypiece,disclosingsomehintsaboutwhatthestructurelookslike.Forexample,let’ssaythatthesereadsreflectthefollowingdatafile:
![Page 93: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/93.jpg)
structmyDataFile{intheader;//4bytes(offset0)shorteffectCount;//2bytes(offset4)shortitemCount;//2bytes(offset6)int*effects;int*items;};
ComparetheloginTable3-2withthisstructure.First,thegamereadsthe4headerbytes.Then,itreadstwo2-bytevalues:effectCountanditemCount.Itthencreatestwointegerarrays,effectsanditems,ofrespectivelengthseffectCountanditemCount.Thegamethenfillsthesearrayswithdatafromthefile,reading4byteseffectCount+itemCounttimes.
NOTE
Developersdefinitelyshouldn’tuseaprocesslikethistoreaddatafromafile,butyou’dbeamazedathowoftenithappens.Fortunatelyforyou,naïvetélikethisjustmakesyouranalysiseasier.
Inthiscase,theeventlogcanidentifysmallpiecesofinformationwithinafile.Butkeepinmindthat,whilecorrelatingthereadswiththeknownstructureiseasy,it’smuchhardertoreverseengineeranunknownstructurefromnothingbutaneventlog.Typically,gamehackerswilluseadebuggertogetmorecontextabouteachinterestingevent,andthedatafromProcessMonitorcanbeseamlesslyintegratedintoadebuggingsession,effectivelytyingtogetherthetwopowerfulreverseengineeringparadigms.
DebuggingaGametoCollectMoreDataLet’sstepawayfromthishypotheticalfilereadandlookathowProcessMonitorletsyoutransitionfromeventloggingtodebugging.ProcessMonitorstoresacompletestacktraceforeachevent,showingthefullexecutionchainthatledtotheeventbeingtriggered.YoucanviewthesestacktracesintheStacktaboftheEventPropertieswindow(double-clicktheeventorpressCTRL-P),asshowninFigure3-3.
![Page 94: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/94.jpg)
Figure3-3:ProcessMonitoreventcallstack
ThestacktraceisdisplayedinatablestartingwithaFramecolumn➊,whichshowstheexecutionmodeandstackframeindex.ApinkKinthiscolumnmeansthecallhappenedinkernelmode,whileablueUmeansithappenedinusermode.Sincegamehackerstypicallyworkinusermode,kernelmodeoperationsareusuallymeaningless.
TheModulecolumn➋showstheexecutablemodulewherethecallingcodewaslocated.Eachmoduleisjustthenameofthebinarythatmadethecall;thismakesiteasytoidentifywhichcallswereactuallymadefromwithinagamebinary.
TheLocationcolumn➌showsthenameofthefunctionthatmadeeachcall,aswellasthecalloffset.Thesefunctionnamesarededucedfromthe
![Page 95: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/95.jpg)
exporttableofthemoduleandwillgenerallynotbepresentforthefunctionswithinagamebinary.Whennofunctionnamesarepresent,theLocationcolumninsteadshowsthemodulenameandthecall’soffset(howmanybytespasttheoriginaddressthecallisinmemory)fromthemodule’sbaseaddress.
NOTE
Inthecontextofcode,theoffsetishowmanybytesofassemblycodearebetweenanitemanditsorigin.
TheAddresscolumn➍showsthecodeaddressofthecall,whichisveryusefulbecauseyoucanjumptotheaddressintheOllyDbgdisassembler.Finally,thePathcolumn➎showsthepathtothemodulethatmadethecall.
Inmyopinion,thestacktraceis,byfar,themostpowerfulfeatureinProcessMonitor.Itrevealstheentirecontextthatledtoanevent,whichcanbeimmenselyusefulwhenyouaredebuggingagame.Youcanuseittofindtheexactcodethattriggeredanevent,crawlupthecallchaintoseehowitgotthere,andevendetermineexactlywhatlibrarieswereusedtocompleteeachaction.
ProcessMonitor’ssisterapplication,ProcessExplorer,doesn’thavemanycapabilitiesbeyondthoseinProcessMonitororOllyDbg.Butitdoesexposesomeofthosecapabilitiesmuchmoreeffectively,makingitanidealpickincertainsituations.
FINDINGAHIGHSCOREFILEIfyou’rereadytotestyourProcessMonitorskills,you’vecometotherightplace.OpentheGameHackingExamples/Chapter3_FindingFilesdirectoryandexecuteFindingFiles.exe.You’llseethatitisagameofPong,liketheonein“Patchinganif()Statement”onpage46.UnlikeinChapter2,though,nowthegameisactuallyplayable.Italsodisplaysyourcurrentscoreandyourall-time-highscore.
Nowrestartthegame,firingupProcessMonitorbeforeexecutingitforthesecondtime.Filteringforfilesystemactivityandcreatinganyotherfiltersyouseefit,trytolocatewherethegamestoresthe
![Page 96: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/96.jpg)
anyotherfiltersyouseefit,trytolocatewherethegamestoresthehigh-scorefile.Forbonuspoints,trytomodifythisfiletomakethegameshowthehighestpossiblescore.
ProcessExplorerProcessExplorerisanadvancedtaskmanager(itevenhasabuttonyoucanpresstomakeityourdefaulttaskmanager),andit’sveryhandywhenyou’restartingtounderstandhowagameoperates.Itprovidescomplexdataaboutrunningprocesses,suchasparentandchildprocesses,CPUusage,memoryusage,loadedmodules,openhandles,andcommandlinearguments,anditcanmanipulatethoseprocesses.Itexceedsatshowingyouhigh-levelinformation,suchasprocesstrees,memoryconsumption,fileaccess,andprocessIDs,allofwhichcanbeveryuseful.
Ofcourse,noneofthisdataisspecificallyusefulinisolation.Butwithakeeneye,youcanmakecorrelationsanddrawsomeusefulconclusionsaboutwhatglobalobjects—includingfiles,mutexes,andsharedmemorysegments—agamehasaccessto.Additionally,thedatashowninProcessExplorercanbeevenmorevaluablewhencross-referencedwithdatagatheredinadebuggingsession.
ThissectionintroducestheProcessExplorerinterface,discussesthepropertiesitshows,anddescribeshowyoucanusethistooltomanipulatehandles(referencestosystemresources).Afterthisintroduction,use“FindingandClosingaMutex”onpage60tohoneyourskills.
ProcessExplorer’sUserInterfaceandControlsWhenyouopenProcessExplorer,youseeawindowthatissplitintothreedistinctsections,asinFigure3-4.
![Page 97: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/97.jpg)
Figure3-4:ProcessExplorermainwindow
Thosethreesectionsarethetoolbar➊,anupperpane➋,andalowerpane➌.Theupperpaneshowsalistofprocesses,utilizingatreestructuretodisplaytheirparent/childrelationships.Differentprocessesarehighlightedwithdifferentcolors;ifyoudon’tlikethecurrentcolors,clickOptions▸ConfigureColorstodisplayadialogthatallowsyoutoviewandchangethem.
JustasinProcessMonitor,thedisplayforthistableishighlyversatile,andyoucancustomizeitbyright-clickingonthetableheaderandchoosingSelectColumns.Thereareprobablymorethan100customizationoptions,butIfindthatthedefaultswiththeadditionoftheASLREnabledcolumnworkjustfine.
NOTE
AddressSpaceLayoutRandomization(ASLR)isaWindowssecurity
![Page 98: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/98.jpg)
featurethatallocatesexecutableimagesatunpredictablelocations,andknowingwhetherit’sonisinvaluablewhenyou’retryingtoaltergamestatevaluesinmemory.
Thelowerpanehasthreepossiblestates:Hidden,DLLs,andHandles.TheHiddenoptionhidesthepanefromview,DLLsdisplaysalistofDynamicLinkLibrariesloadedwithinthecurrentprocess,andHandlesshowsalistofhandlesheldbytheprocess(visibleinFigure3-4).YoucanhideorunhidetheentirelowerpanebytogglingView▸ShowLowerPane.Whenitisvisible,youcanchangetheinformationdisplaybyselectingeitherView▸LowerPaneView▸DLLsorView▸LowerPaneView▸Handles.
Youcanalsousehotkeystoquicklychangebetweenlowerpanemodeswithoutaffectingprocessesintheupperpane.ThesehotkeysarelistedinTable3-3.
Table3-3:ProcessExplorerHotkeys
Hotkey Action
CTRL-F Searchthroughlowerpanedatasetsforavalue.
CTRL-L Togglethelowerpanebetweenhiddenandvisible.
CTRL-D TogglethelowerpanetodisplayDLLs.
CTRL-H Togglethelowerpanetodisplayhandles.
spacebar Toggleprocesslistautorefresh.ENTER DisplaythePropertiesdialogfortheselectedprocess.DEL Killtheselectedprocess.
SHIFT-DELKilltheselectedprocessandallchildprocesses.
UsetheGUIorhotkeystopracticechangingmodes.Whenyou’reacquaintedwiththemainwindow,we’lllookatanotherimportantProcessExplorerdialog,calledProperties.
ExaminingProcessPropertiesMuchlikeProcessMonitor,ProcessExplorerhasaverykineticapproachto
![Page 99: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/99.jpg)
datagathering;theendresultisabroadandverbosespectrumofinformation.Infact,ifyouopenthePropertiesdialog(showninFigure3-5)foraprocess,you’llseeamassivetabbarcontaining10tabs.
TheImagetab,selectedbydefaultandshowninFigure3-5,displaystheexecutablename,version,builddate,andcompletepath.ItalsodisplaysthecurrentworkingdirectoryandtheAddressSpaceLayoutRandomizationstatusoftheexecutable.ASLRstatusisthemostimportantpieceofinformationhere,becauseithasadirecteffectonhowabotcanreadthememoryfromagame.I’lltalkaboutthismoreinChapter6.
Figure3-5:ProcessExplorerPropertiesdialog
ThePerformance,PerformanceGraph,DiskandNetwork,andGPUGraphtabsdisplayamyriadofmetricsabouttheCPU,memory,disk,network,andGPUusageoftheprocess.Ifyoucreateabotthatinjectsintoa
![Page 100: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/100.jpg)
network,andGPUusageoftheprocess.Ifyoucreateabotthatinjectsintoagame,thisinformationcanbeveryusefultodeterminehowmuchofaperformanceimpactyourbothasonthegame.
TheTCP/IPtabdisplaysalistofactiveTCPconnections,whichyoucanusetofindanygameserverIPaddressesthatagameconnectsto.Ifyou’retryingtotestconnectionspeed,terminateconnections,orresearchagame’snetworkprotocol,thisinformationiscritical.
TheStringstabdisplaysalistofstringsfoundineitherthebinaryorthememoryoftheprocess.UnlikethestringlistinOllyDbg,whichshowsonlystringsreferencedbyassemblycode,thelistincludesanyoccurrencesofthreeormoreconsecutivereadablecharacters,followedbyanullterminator.Whenagamebinaryisupdated,youcanuseadiffingtoolonthislistfromeachgameversiontodeterminewhetherthereareanynewstringsthatyouwanttoinvestigate.
TheThreadstabshowsyoualistofthreadsrunningwithintheprocessandallowsyoutopause,resume,orkilleachthread;theSecuritytabdisplaysthesecurityprivilegesoftheprocess;andtheEnvironmenttabdisplaysanyenvironmentvariablesknowntoorsetbytheprocess.
NOTE
IfyouopenthePropertiesdialogfora.NETprocess,you’llnoticetwoadditionaltabs:.NETAssembliesand.NETPerformance.Thedatainthesetabsisprettyself-explanatory.Pleasekeepinmindthatamajorityofthetechniquesinthisbookwon’tworkwithgameswrittenin.NET.
HandleManipulationOptionsAsyou’veseen,ProcessExplorercanprovideyouwithawealthofinformationaboutaprocess.That’snotallit’sgoodfor,though:itcanalsomanipulatecertainpartsofaprocess.Forexample,youcanviewandmanipulateopenhandlesfromthecomfortofProcessExplorer’slowerpane(seeFigure3-4).ThisalonemakesastrongargumentforaddingProcessExplorertoyourtoolbox.Closingahandleisassimpleasright-clickingonitandselectingCloseHandle.Thiscancomeinhandywhenyouwant,forinstance,toclosemutexes,whichisessentialtocertaintypesofhacks.
![Page 101: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/101.jpg)
NOTE
Youcanright-clickonthelowerpaneheaderandclickSelectColumnstocustomizethedisplay.OnecolumnyoumightfindparticularlyusefulisHandleValue,whichcanhelpwhenyouseeahandlebeingpassedaroundinOllyDbgandwanttoknowwhatitdoes.
ClosingMutexesGamesoftenallowonlyoneclienttorunatatime;thisiscalledsingle-instancelimitation.Youcanimplementsingle-instancelimitationinanumberofways,butusingasystemmutexiscommonbecausemutexesaresessionwideandcanbeaccessedbyasimplename.It’strivialtolimitinstanceswithmutexes,andthankstoProcessExplorer,it’sjustastrivialtoremovethatlimit,allowingyoutorunmultipleinstancesofagameatthesametime.
First,here’showagamemighttacklesingle-instancelimitationwithamutex:
intmain(intargc,char*argv[]){//createthemutexHANDLEmutex=CreateMutex(NULL,FALSE,"onlyoneplease");if(GetLastError()==ERROR_ALREADY_EXISTS){//themutexalreadyexists,soexitErrorBox("Aninstanceisalreadyrunning.");return0;}//themutexdidn'texist;itwasjustcreated,so//letthegamerunRunGame();//thegameisover;closethemutextofreeitup//forfutureinstancesif(mutex)CloseHandle(mutex);return0;}
Thisexamplecodecreatesamutexnamedonlyoneplease.Next,thefunctionchecksGetLastError()toseewhetherthemutexwasalreadycreated,andifso,itclosesthegame.Ifthemutexdoesn’talreadyexist,thegamecreatesthefirstinstance,therebyblockinganyfuturegameclientsfromrunning.Inthisexample,thegamerunsnormally,andonceitfinishes,
![Page 102: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/102.jpg)
CloseHandle()iscalledtoclosethemutexandallowfuturegameinstancestorun.
YoucanuseProcessExplorertocloseinstance-limitingmutexesandrunmanygameinstancessimultaneously.Todoso,choosetheHandlesviewofthelowerpane,lookforallhandleswithatypeofMutant,determinewhichoneislimitinginstancesofthegame,andclosethatmutex.
WARNING
Mutexesarealsousedtosynchronizedataacrossthreadsandprocesses.Closeoneonlyifyou’resurethatitssolepurposeistheoneyou’retryingtosubvert!
Multiclienthacksaregenerallyinhighdemand,sobeingabletoquicklydevelopthemforemerginggamesiscrucialtoyouroverallsuccessasabotdeveloperwithinthatmarket.Sincemutexesareoneofthemostcommonwaystoachievesingle-instancelimitation,ProcessExplorerisanintegraltoolforprototypingthesekindsofhacks.
InspectingFileAccessesUnlikeProcessMonitor,ProcessExplorercan’tshowalistoffilesystemcalls.Ontheotherhand,theHandlesviewofProcessExplorer’slowerpanecanshowallfilehandlesthatagamecurrentlyhasopen,revealingexactlywhatfilesareincontinuoususewithouttheneedtosetupadvancedfilteringcriteriainProcessMonitor.JustlookforhandleswithatypeofFiletoseeallfilesthegameiscurrentlyusing.
Thisfunctionalitycancomeinhandyifyou’retryingtolocatelogfilesorsavefiles.Moreover,youcanlocatenamedpipesthatareusedforinterprocesscommunication(IPC);thesearefilesprefixedwith\Device\NamedPipe\.Seeingoneofthesepipesisoftenahintthatthegameistalkingtoanotherprocess.
FINDINGANDCLOSINGAMUTEXToputyourProcessExplorerskillstouse,gototheGameHackingExamples/Chapter3_CloseMutexdirectoryandexecute
![Page 103: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/103.jpg)
CloseMutex.exe.Thisgameplaysexactlyliketheonein“FindingaHighScoreFile”onpage55,butitpreventsyoufromsimultaneouslyrunningmultipleinstances.Asyoumighthaveguessed,itdoesthisusingasingle-instance-limitationmutex.UsingProcessExplorer’sHandlesviewinthelowerpane,findthemutexresponsibleforthislimitationandcloseit.Ifyousucceed,you’llbeabletoopenasecondinstanceofthegame.
ClosingThoughtsTobeeffectivewhenusingProcessMonitorandProcessExplorer,youneed,aboveallelse,adeepfamiliaritywiththedatathattheseapplicationsdisplayaswellastheinterfacestheyusetodisplayit.Whilethischapter’soverviewisagoodbaseline,theintricaciesoftheseapplicationscanbelearnedonlythroughexperience,soIencourageyoutoplayaroundwiththemonyoursystem.
Youwon’tusethesetoolsonaregularbasis,butatsomepoint,they’llsavetheday:asyoustruggletofigureouthowsomecodeworks,you’llrecallanobscurepieceofinformationthatcaughtyoureyeduringapreviousProcessExplorerorProcessMonitorsession.That’swhyIconsiderthemusefulreconnaissancetools.
![Page 104: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/104.jpg)
PART2GAMEDISSECTION
![Page 105: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/105.jpg)
4FROMCODETOMEMORY:AGENERAL
PRIMER
Atthelowestlevel,agame’scode,data,input,andoutputarecomplexabstractionsoferraticallychangingbytes.Manyofthesebytesrepresentvariablesormachinecodegeneratedbyacompilerthatwasfedthegame’ssourcecode.Somerepresentimages,models,andsounds.Othersexistonlyforaninstant,postedbythecomputer’shardwareasinputanddestroyedwhenthegamefinishesprocessingthem.Thebytesthatremaininformtheplayerofthegame’sinternalstate.Buthumanscan’tthinkinbytes,sothecomputermusttranslatetheminawaywecanunderstand.
There’sahugedisconnectintheoppositedirectionaswell.Acomputerdoesn’tactuallyunderstandhigh-levelcodeandvisceralgamecontent,sothesemustbetranslatedfromtheabstractintobytes.Somecontent—suchasimages,sounds,andtext—isstoredlosslessly,readytobepresentedtotheplayeratamicrosecond’snotice.Agame’scode,logic,andvariables,ontheotherhand,arestrippedofallhumanreadabilityandcompileddowntomachinedata.
Bymanipulatingagame’sdata,gamehackersobtainhumanlyimprobableadvantageswithinthegame.Todothis,however,theymustunderstandhowadeveloper’scodemanifestsonceithasbeencompiledandexecuted.Essentially,theymustthinklikecomputers.
Togetyouthinkinglikeacomputer,thischapterwillbeginbyteachingyouhownumbers,text,simplestructures,andunionsarerepresentedin
![Page 106: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/106.jpg)
youhownumbers,text,simplestructures,andunionsarerepresentedinmemoryatthebytelevel.Thenyou’lldivedeepertoexplorehowclassinstancesarestoredinmemoryandhowabstractinstancesknowwhichvirtualfunctionstocallatruntime.Inthelasthalfofthechapter,you’lltakeanx86assemblylanguagecrashcoursethatcoverssyntax,registers,operands,thecallstack,arithmeticoperations,branchingoperations,functioncalls,andcallingconventions.
Thischapterfocusesveryheavilyongeneraltechnicaldetails.Thereisn’talotofjuicyinformationthatimmediatelyrelatestohackinggames,buttheknowledgeyougainherewillbecentralinthecomingchapters,whenwetalkabouttopicslikeprogrammaticallyreadingandwritingmemory,injectingcode,andmanipulatingcontrolflow.
SinceC++isthedefactostandardforbothgameandbotdevelopment,thischapterexplainstherelationshipsbetweenC++codeandthememorythatrepresentsit.Mostnativelanguageshaveverysimilar(sometimesidentical)low-levelstructureandbehavior,however,soyoushouldbeabletoapplywhatyoulearnheretojustaboutanypieceofsoftware.
AlloftheexamplecodeinthischapterisintheGameHackingExamples/Chapter4_CodeToMemorydirectoryofthisbook’ssourcefiles.TheincludedprojectscanbecompiledwithVisualStudio2010butshouldalsoworkwithanyotherC++compiler.Downloadthemathttps://www.nostarch.com/gamehacking/andcompilethemifyouwanttofollowalong.
HowVariablesandOtherDataManifestinMemoryProperlymanipulatingagame’sstatecanbeveryhard,andfindingthedatathatcontrolsitisnotalwaysaseasyasclickingNextScanandhopingCheatEnginewon’tfailyou.Infact,manyhacksmustmanipulatedozensofrelatedvaluesatonce.Findingthesevaluesandtheirrelationshipsoftenrequiresyoutoanalyticallyidentifystructuresandpatterns.Moreover,developinggamehackstypicallymeansre-creatingtheoriginalstructureswithinyourbot’scode.
Todothesethings,youneedanin-depthunderstandingofexactlyhowvariablesanddataarelaidoutinthegame’smemory.Throughexample
![Page 107: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/107.jpg)
variablesanddataarelaidoutinthegame’smemory.Throughexamplecode,OllyDbgmemorydumps,andsometablestotieeverythingtogether,thissectionwillteachyoueverythingthereistoknowabouthowdifferenttypesofdatamanifestinmemory.
NumericDataMostofthevaluesgamehackersneed(liketheplayer’shealth,mana,location,andlevel)arerepresentedbynumericdatatypes.Becausenumericdatatypesarealsoabuildingblockforallotherdatatypes,understandingthemisextremelyimportant.Luckily,theyhaverelativelystraightforwardrepresentationsinmemory:theyarepredictablyalignedandhaveafixedbitwidth.Table4-1showsthefivemainnumericdatatypesyou’llfindinWindowsgames,alongwiththeirsizesandranges.
Table4-1:NumericDataTypes
Typename(s)
SizeSignedrange Unsignedrange
char,BYTE 8bits
-128to127 0to255
short,WORD,wchar_t
16bits
-32,768to-32,767 0to65535
int,long,DWORD
32bits
-2,147,483,648to2,147,483,647
0to4,294,967,295
longlong 64bits
-9,223,372,036,854,775,808to9,223,372,036,854,775,807
0to18,446,744,073,709,551,615
float 32bits
+/-1.17549*10-38to+/-3.40282*1038
N/A
Thesizesofnumericdatatypescandifferbetweenarchitecturesandevencompilers.Sincethisbookfocusesonhackingx86gamesonWindows,I’musingtypenamesandsizesmadestandardbyMicrosoft.Withtheexceptionoffloat,thedatatypesinTable4-1arestoredwithlittle-endianordering,
![Page 108: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/108.jpg)
meaningtheleastsignificantbytesofanintegerarestoredinthelowestaddressesoccupiedbythatinteger.Forexample,Figure4-1showsthatDWORD0x0A0B0C0Disrepresentedbythebytes0x0D0x0C0x0B0x0A.
Figure4-1:Little-endianorderingdiagram
Thefloatdatatypecanholdmixednumbers,soitsrepresentationinmemoryisn’tassimpleasthatofotherdatatypes.Forexample,ifyousee0x0D0x0C0x0B0x0Ainmemoryandthatvalueisafloat,youcan’tsimplyconvertitto0x0A0B0C0D.Instead,floatvalueshavethreecomponents:thesign(bit0),exponent(bits1–8),andmantissa(bits9–31).
Thesigndetermineswhetherthenumberisnegativeorpositive,theexponentdetermineshowmanyplacestomovethedecimalpoint(startingbeforethemantissa),andthemantissaholdsanapproximationofthevalue.Youcanretrievethestoredvaluebyevaluatingtheexpressionmantissa×10n
(wherenistheexponent)andmultiplyingtheresultby–1ifthesignisset.Nowlet’slookatsomenumericdatatypesinmemory.Listing4-1
initializesninevariables.
unsignedcharubyteValue=0xFF;charbyteValue=0xFE;unsignedshortuwordValue=0x4142;shortwordValue=0x4344;unsignedintudwordValue=0xDEADBEEF;intdwordValue=0xDEADBEEF;unsignedlonglongulongLongValue=0xEFCDAB8967452301;longlonglongLongValue=0xEFCDAB8967452301;floatfloatValue=1337.7331;
![Page 109: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/109.jpg)
Listing4-1:CreatingvariablesofnumericdatatypesinC++
Startingfromthetop,thisexampleincludesvariablesoftypeschar,short,int,longlong,andfloat.Fouroftheseareunsigned,andfivearesigned.(InC++,afloatcan’tbeunsigned.)Takingintoaccountwhatyou’velearnedsofar,carefullystudytherelationshipbetweenthecodeinListing4-1andthememorydumpinFigure4-2.Assumethatthevariablesaredeclaredinglobalscope.
Figure4-2:OllyDbgmemorydumpofournumericdata
Youmightnoticethatsomevaluesseemarbitrarilyspacedout.Sinceit’smuchfasterforprocessorstoaccessvaluesresidingataddressesthataremultiplesoftheaddresssize(whichis32bitsinx86),compilerspadvalueswithzerosinordertoalignthemonsuchaddresses—hence,paddingisalsocalledalignment.Single-bytevaluesarenotpadded,sinceoperationsthataccessthemperformthesameregardlessofalignment.
Keepingthisinmind,takealookatTable4-2,whichprovidesasortofmemory-to-codecrosswalkbetweenthememorydumpinFigure4-2andthevariablesdeclaredinListing4-1.
Table4-2:Memory-to-CodeCrosswalkforListing4-1andFigure4-2
Address Size Data Object
0x00BB3018 1byte
0xFF ubyteValue
0x00BB3019 1byte
0xFE byteValue
0x00BB301A 2bytes
0x000x00 PaddingbeforeuwordValue
0x00BB301C 2bytes
0x420x41 uwordValue
0x00BB301E 2bytes
0x000x00 PaddingbeforewordValue
![Page 110: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/110.jpg)
bytes wordValue
0x00BB3020 2bytes
0x440x43 wordValue
0x00BB3022 2bytes
0x000x00 PaddingbeforeudwordValue
0x00BB3024 4bytes
0xEF0xBE0xAD0xDE udwordValue
0x00BB3028 4bytes
0xEF0xBE0xAD0xDE dwordValue
0x00BB302C 4bytes
0x760x370xA70x44 floatValue
0x00BB3030 8bytes
0x010x230x450x670x890xAB0xCD0xEF
ulongLongValue
0x00BB3038 8bytes
0x010x230x450x670x890xAB0xCD0xEF
LongLongValue
TheAddresscolumnlistslocationsinmemory,andtheDatacolumntellsyouexactlywhat’sstoredthere.TheObjectcolumntellsyouwhichvariablefromListing4-1eachpieceofdatarelatesto.NoticethatfloatValueisplacedbeforeulongLongValueinmemory,eventhoughit’sthelastvariabledeclaredinListing4-1.Becausethesevariablesaredeclaredinglobalscope,thecompilercanplacethemwhereveritwants.Thisparticularmoveislikelyaresultofeitheralignmentoroptimization.
StringDataMostdevelopersusethetermstringasifit’ssynonymouswithtext,buttextisonlythemostcommonuseforstrings.Atalowlevel,stringsarejustarraysofarbitrarynumericobjectsthatappearlinearandunalignedinmemory.Listing4-2showsfourtextstringdeclarations.
//charwillbe1bytepercharacterchar*thinStringP="my_thin_terminated_value_pointer";charthinStringA[40]="my_thin_terminated_value_array";
//wchar_twillbe2bytespercharacter
![Page 111: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/111.jpg)
//wchar_twillbe2bytespercharacterwchar_t*wideStringP=L"my_wide_terminated_value_pointer";wchar_twideStringA[40]=L"my_wide_terminated_value_array";
Listing4-2:DeclaringseveralstringsinC++
Inthecontextoftext,stringsholdcharacterobjects(charfor8-bitencodingorwchar_tfor16-bitencoding),andtheendofeachstringisspecifiedbyanullterminator,acharacterequalto0x0.Let’slookatthememorywherethesevariablesarestored,asshowninthetwomemorydumpsinFigure4-3.
Figure4-3:InthisOllyDbgmemorydumpofstringdata,thehuman-readabletextintheASCIIcolumnisthetextwestoredinListing4-2.
Ifyou’renotusedtoreadingmemory,theOllyDbgdumpmightbeabitdifficulttofollowatthispoint.Table4-3showsadeeperlookatthecorrelationbetweenthecodeinListing4-2andthememoryinFigure4-3.
Table4-3:Memory-to-CodeCrosswalkforListing4-2andFigure4-3
Address Size Data Object
Pane1
0x012420F8 32bytes
0x6D0x790x5F{...}0x740x650x72
thinStringPcharacters
0x01242118 4bytes
0x000x000x000x00 thinStringPterminatorandpadding
0x0124211C 4bytes
0x000x000x000x00 Unrelateddata
![Page 112: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/112.jpg)
0x01242120 64bytes
0x6D0x000x79{...}0x000x720x00
wideStringPcharacters
0x01242160 4bytes
0x000x000x000x00 wideStringPterminatorandpadding
{...} Unrelateddata
Pane2
0x01243040 4bytes
0xF80x200x240x01 PointertothinStringPat0x012420F8
0x01243044 30bytes
0x6D0x790x5F{...}0x720x610x79
thinStringAcharacters
0x01243062 10bytes
0x00repeated10times thinStringAterminatorandarrayfill
0x0124306C 4bytes
0x200x210x240x01 PointertowideStringPat0x01242120
0x01243070 60bytes
0x6D0x000x79{...}0x000x790x00
wideStringAcharacters
0x012430AC 20bytes
0x00repeated10times wideStringAterminatorandarrayfill
InFigure4-3,pane1showsthatthevaluesstoredwherethinStringP(address0x01243040)andwideStringP(address0x0124306C)belonginmemoryareonly4byteslongandcontainnostringdata.That’sbecausethesevariablesareactuallypointerstothefirstcharactersoftheirrespectivearrays.Forexample,thinStringPcontains0x012420F8,andinpane2inFigure4-3,youcansee"my_thin_terminated_value_pointer"locatedataddress0x012420F8.
Lookatthedatabetweenthesepointersinpane1,andyoucanseethetextbeingstoredbythinStringAandwideStringA.Furthermore,noticethatthinStringAandwideStringAarepaddedbeyondtheirnullterminators;thisisbecausethesevariablesweredeclaredasarrayswithlength40,sotheyarefilledupto40characters.
![Page 113: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/113.jpg)
DataStructuresUnlikethedatatypeswehavepreviouslydiscussed,structuresarecontainersthatholdmultiplepiecesofsimple,relateddata.Gamehackerswhoknowhowtoidentifystructuresinmemorycanmimicthosestructuresintheirowncode.Thiscangreatlyreducethenumberofaddressestheymustfind,astheyneedtofindonlytheaddresstothestartofthestructure,nottheaddressofeveryindividualitem.
NOTE
Thissectiontalksaboutstructuresassimplecontainersthatlackmemberfunctionsandcontainonlysimpledata.Objectsthatexceedtheselimitationswillbediscussedin“ClassesandVFTables”onpage74.
StructureElementOrderandAlignmentSincestructuressimplyrepresentanassortmentofobjects,theydon’tvisiblymanifestinmemorydumps.Instead,amemorydumpofastructureshowstheobjectsthatarecontainedwithinthatstructure.ThedumpwouldlookmuchliketheothersI’veshowninthischapter,butwithimportantdifferencesinbothorderandalignment.
Toseethesedifferences,startbytakingalookatListing4-3.
structMyStruct{unsignedcharubyteValue;charbyteValue;unsignedshortuwordValue;shortwordValue;unsignedintudwordValue;intdwordValue;unsignedlonglongulongLongValue;longlonglongLongValue;floatfloatValue;};MyStruct&m=0;printf("Offsets:%d,%d,%d,%d,%d,%d,%d,%d,%d\n",&m->ubyteValue,&m->byteValue,&m->uwordValue,&m->wordValue,&m->udwordValue,&m->dwordValue,&m->ulongLongValue,&m->longLongValue,&m->floatValue);
![Page 114: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/114.jpg)
Listing4-3:AC++structureandsomecodethatusesit
ThiscodedeclaresastructurenamedMyStructandcreatesavariablenamedmthatsupposedlypointstoaninstanceofthestructureataddress0.There’snotactuallyaninstanceofthestructureataddress0,butthistrickletsmeusetheampersandoperator(&)intheprintf()calltogettheaddressofeachmemberofthestructure.Sincethestructureislocatedataddress0,theaddressprintedforeachmemberisequivalenttoitsoffsetfromthestartofthestructure.
Theultimatepurposeofthisexampleistoseeexactlyhoweachmemberislaidoutinmemory,relativetothestartofthestructure.Ifyouweretorunthecode,you’dseethefollowingoutput:
Offsets:0,1,2,4,8,12,16,24,32
Asyoucansee,thevariablesinMyStructareorderedexactlyastheyweredefinedincode.Thissequentialmemberlayoutisamandatorypropertyofstructures.ComparethistotheexamplefromListing4-1,whenwedeclaredanidenticalsetofvariables;inthememorydumpfromFigure4-2,thecompilerclearlyplacedsomevaluesoutoforderinmemory.
Furthermore,youmayhavenoticedthatthemembersarenotalignedlikethegloballyscopedvariablesinListing4-1;iftheywere,forexample,therewouldbe2paddingbytesbeforeuwordValue.Thisisbecausestructuremembersarealignedonaddressesdivisiblebyeitherthestructmemberalignment(acompileroptionthataccepts1,2,4,8,or16bytes;inthisexample,it’ssetto4)orthesizeofthemember—whicheverissmaller.IarrangedthemembersofMyStructsothatthecompilerdidn’tneedtopadthevalues.
If,however,weputacharimmediatelyafterulongLongValue,theprintf()callwouldgivethefollowingoutput:
Offsets:0,1,2,4,8,12,16,28,36
Now,takealookattheoriginalandthemodifiedoutputstogether:
Original:Offsets:0,1,2,4,8,12,16,24,32Modified:Offsets:0,1,2,4,8,12,16,28,36
Inthemodifiedversion,thelasttwovalues,whicharetheoffsetsfor
![Page 115: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/115.jpg)
longLongValueandfloatValuefromthestartofthestructure,havechanged.Thankstothestructmemberalignment,thevariablelongLongValuemovesby4bytes(1forthecharvalueand3followingit)toensureitgetsplacedonanaddressdivisibleby4.
HowStructuresWorkUnderstandingstructures—howtheyarealignedandhowtomimicthem—canbeveryuseful.Forinstance,ifyoureplicateagame’sstructuresinyourowncode,youcanreadorwritethoseentirestructuresfrommemoryinasingleoperation.Consideragamethatdeclarestheplayer’scurrentandmaxhealthlikeso:
struct{intcurrent;intmax;}vital;vitalhealth;
Ifaninexperiencedgamehackerwantstoreadthisinformationfrommemory,theymightwritesomethinglikethistofetchthehealthvalues:
intcurrentHealth=readIntegerFromMemory(currentHealthAddress);intmaxHealth=readIntegerFromMemory(maxHealthAddress);
Thisgamehackerdoesn’trealizethatseeingthesevaluesrightnexttoeachotherinmemorycouldbemorethanaluckyhappenstance,sothey’veusedtwoseparatevariables.Butifyoucamealongwithyourknowledgeofstructures,youmightconcludethat,sincethesevaluesarecloselyrelatedandareadjacentinmemory,ourhackercouldhaveusedastructureinstead:
struct{intcurrent;intmax;}_vital;➊_vitalhealth=readTypeFromMemory<_vital>(healthStructureAddress);
Sincethiscodeassumesastructureisbeingusedandcorrectlymimicsit,itcanfetchbothhealthandmaxhealthinjustoneline➊.We’lldivedeeperintohowtowriteyourowncodetoreadmemoryfrominChapter6.
![Page 116: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/116.jpg)
UnionsUnlikestructures,whichencapsulatemultiplepiecesofrelateddata,unionscontainasinglepieceofdatathatisexposedthroughmultiplevariables.Unionsfollowthreerules:
•Thesizeofaunioninmemoryisequaltothatofitslargestmember.
•Membersofaunionallreferencethesamememory.
•Aunioninheritsthealignmentofitslargestmember.
Theprintf()callinthefollowingcodehelpsillustratethefirsttworules:
union{BYTEbyteValue;struct{WORDfirst;WORDsecond;}words;DWORDvalue;}dwValue;dwValue.value=0xDEADBEEF;printf("Size%d\nAddresses0x%x,0x%x\nValues0x%x,0x%x\n",sizeof(dwValue),&dwValue.value,&dwValue.words,dwValue.words.first,dwValue.words.second);
Thiscalltoprintf()outputsthefollowing:
Size4Addresses0x2efda8,0x2efda8Values0xbeef,0xdead
ThefirstruleisillustratedbytheSizevalue,whichisprintedfirst.EventhoughdwValuehasthreemembersthatoccupyatotalof9bytes,ithasasizeofonly4bytes.Thesizeresultvalidatesthesecondruleaswell,becausedwValue.valueanddwValue.wordsbothpointtoaddress0x2efda8,asshownbythevaluesprintedafterthewordAddresses.ThesecondruleisalsovalidatedbythefactthatdwValue.words.firstanddwValue.words.secondcontain0xbeefand0xdead,printedafterValues,whichmakessenseconsideringthatdwValue.valueis0xdeadbeef.Thethirdruleisn’tdemonstratedinthisexamplebecausewedon’thaveenoughmemorycontext,butifyouweretoputthisunioninsideastructureandsurrounditwithwhatevertypesyoulike,itwouldinfactalwaysalignlikeaDWORD.
![Page 117: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/117.jpg)
ClassesandVFTablesMuchlikestructures,classesarecontainersthatholdandisolatemultiplepiecesofdata,butclassescanalsocontainfunctiondefinitions.
ASimpleClassClasseswithnormalfunctions,suchasbarinListing4-4,conformtothesamememorylayoutsasstructures.
classbar{public:bar():bar1(0x898989),bar2(0x10203040){}voidmyfunction(){bar1++;}intbar1,bar2;};
bar_bar=bar();printf("Size%d;Address0x%x:_bar\n",sizeof(_bar),&_bar);
Listing4-4:AC++class
Theprintf()callinListing4-4wouldoutputthefollowing:
Size8;Address0x2efd80:_bar
Eventhoughbarhastwomemberfunctions,thisoutputshowsthatitspansonlythe8bytesneededtoholdbar1andbar2.Thisisbecausethebarclassdoesn’tincludeabstractionsofthosememberfunctions,sotheprogramcancallthemdirectly.
NOTE
Accesslevelssuchaspublic,private,andprotecteddonotmanifestinmemory.Regardlessofthesemodifiers,membersofclassesarestillorderedastheyaredefined.
AClasswithVirtualFunctionsInclassesthatdoincludeabstractfunctions(oftencalledvirtualfunctions),theprogrammustknowwhichfunctiontocall.ConsidertheclassdefinitionsinListing4-5:
![Page 118: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/118.jpg)
classfoo{public:foo():myValue1(0xDEADBEEF),myValue2(0xBABABABA){}intmyValue1;staticintmyStaticValue;virtualvoidbar(){printf("callfoo::bar()\n");}virtualvoidbaz(){printf("callfoo::baz()\n");}virtualvoidbarbaz(){}intmyValue2;};
intfoo::myStaticValue=0x12121212;
classfooa:publicfoo{public:fooa():foo(){}virtualvoidbar(){printf("callfooa::bar()\n");}virtualvoidbaz(){printf("callfooa::baz()\n");}};
classfoob:publicfoo{public:foob():foo(){}virtualvoidbar(){printf("callfoob::bar()\n");}virtualvoidbaz(){printf("callfoob::baz()\n");}};
Listing4-5:Thefoo,fooa,andfoobclasses
Theclassfoohasthreevirtualfunctions:bar,baz,andbarbaz.Classesfooaandfoobinheritfromclassfooandoverloadbothbarandbaz.Sincefooaandfoobhaveapublicbaseclassoffoo,afoopointercanpointtothem,buttheprogrammuststillcallthecorrectversionsofbarandbaz.Youcanseethisbyexecutingthefollowingcode:
foo*_testfoo=(foo*)newfooa();_testfoo->bar();//callsfooa::bar()
Andhereistheoutput:
callfooa::bar()
Theoutputshowsthat_testfoo->bar()invokedfooa::bar()eventhough_testfooisafoopointer.Theprogramknewwhichversionofthefunctiontocall,becausethecompilerincludedaVF(virtualfunction)tableinthememoryof_testfoo.VFtablesarearraysoffunctionaddressesthatabstractclassinstancesusetotellaprogramwheretheiroverloadedfunctionsare
![Page 119: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/119.jpg)
located.
ClassInstancesandVirtualFunctionTablesTounderstandtherelationshipbetweenclassinstancesandVFtables,let’sinspectamemorydumpofthethreeobjectsdeclaredinthislisting:
foo_foo=foo();fooa_fooa=fooa();foob_foob=foob();
TheseobjectsareofthetypesdefinedinListing4-5.YoucanseetheminmemoryinFigure4-4.
Figure4-4:OllyDbgmemorydumpofclassdata
Pane1showsthateachclassinstancestoresitsmembersjustlikeastructure,butitprecedesthemwithaDWORDvaluethatpointstotheclassinstance’sVFtable.Pane2showstheVFtablesforeachofourthreeclassinstances.Thememory-to-codecrosswalkinTable4-4showshowthesepanesandthecodetietogether.
Table4-4:Memory-to-CodeCrosswalkforListing4-5andFigure4-4
Address Size Data Object
Pane1
0x0018FF20 4bytes
0x004022B0 Startof_fooandpointertofooVFtable
0x0018FF24 8bytes
0xDEADBEEF0xBABABABA
_foo.myValue1and_foo.myValue2
![Page 120: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/120.jpg)
0x0018FF2C 4bytes
0x004022C0 Startof_fooaandpointertofooaVFtable
0x0018FF30 8bytes
0xDEADBEEF0xBABABABA
_fooa.myValue1and_fooa.myValue2
0x0018FF38 4bytes
0x004022D0 Startof_foobandpointertofoobVFtable
0x0018FF3C 8bytes
0xDEADBEEF0xBABABABA
_foob.myValue1and_foob.myValue2
{...} Unrelateddata
Pane2
0x004022B0 4bytes
0x00401060 StartoffooVFtable;addressoffoo::bar
0x004022B4 4bytes
0x00401080 Addressoffoo::baz
0x004022B8 4bytes
0x004010A0 Addressoffoo::barbaz
0x004022BC 4bytes
0x0040243C Unrelateddata
0x004022C0 4bytes
0x004010D0 StartoffooaVFtable;addressoffooa::bar
0x004022C4 4bytes
0x004010F0 Addressoffooa::baz
0x004022C8 4bytes
0x004010A0 Addressoffoo::barbaz
0x004022CC 4bytes
0x004023F0 Unrelateddata
0x004022D0 4bytes
0x00401130 StartoffoobVFtable;addressoffoob::bar
0x004022D4 4bytes
0x00401150 Addressoffoob::baz
![Page 121: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/121.jpg)
bytes
0x004022D8 4bytes
0x004010A0Addressoffoo::barbaz
ThiscrosswalkshowshowtheVFtablesforthecodeinListing4-5arelaidoutinmemory.EachVFtableisgeneratedbythecompilerwhenthebinaryismade,andthetablesremainconstant.Tosavespace,instancesofthesameclassallpointtothesameVFtable,whichiswhytheVFtablesaren’tplacedinlinewiththeclass.
SincewehavethreeVFtables,youmightwonderhowaclassinstanceknowswhichVFtabletouse.Thecompilerplacescodesimilartothefollowingbitofassemblyineachvirtualclassconstructor:
MOVDWORDPTRDS:[EAX],VFADDR
ThisexampletakesthestaticaddressofaVFtable(VFADDR)andplacesitinmemoryasthefirstmemberoftheclass.
Nowlookataddresses0x004022B0,0x004022C0,and0x004022D0inTable4-4.Theseaddressescontainthebeginningofthefoo,fooa,andfoobVFtables.Noticethatfoo::barbazexistsinallthreeVFtables;thisisbecausethefunctionisnotoverloadedbyeithersubclass,meaninginstancesofeachsubclasswillcalltheoriginalimplementationdirectly.
Notice,too,thatfoo::myStaticValuedoesnotappearinthiscrosswalk.Sincethevalueisstatic,itdoesn’tactuallyneedtoexistasapartofthefooclass;it’splacedinsidethisclassonlyforbettercodeorganization.Inreality,itgetstreatedlikeaglobalvariableandisplacedelsewhere.
VFTABLESANDCHEATENGINERememberCheatEngine’sFirstelementofpointerstructmustpointtomoduleoptionforpointerscansfromFigure1-4onpage14?Nowthatyou’vereadabitaboutVFtables,thatknowledgeshouldhelpyouunderstandhowthisoptionworks:itmakesCheatEngineignoreallheapchunkswherethefirstmemberisnotapointertoavalidVFtable.Itspeedsupscans,butitworksonlyifeverystepinapointerpathispartofanabstractclassinstance.
![Page 122: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/122.jpg)
Thememorytourendshere,butifyouhavetroubleidentifyingachunkofdatainthefuture,comebacktothissectionforreference.Next,we’lllookathowacomputercanunderstandagame’shigh-levelsourcecodeinthefirstplace.
x86AssemblyCrashCourseWhenaprogram’ssourcecodeiscompiledintoabinary,itisstrippedofallunnecessaryartifactsandtranslatedintomachinecode.Thismachinecode,madeupofonlybytes(commandbytesarecalledopcodes,buttherearealsobytesrepresentingoperands),getsfeddirectlytotheprocessorandtellsitexactlyhowtobehave.Those1sand0sfliptransistorstocontrolcomputation,andtheycanbeextremelydifficulttounderstand.Tomakecomputersalittleeasiertotalkto,engineersworkingwithsuchcodeuseassemblylanguage,ashorthandthatrepresentsrawmachineopcodeswithabbreviatednames(calledmnemonics)andasimplisticsyntax.
Assemblylanguageisimportantforgamehackerstoknowbecausemanypowerfulhackscanbeachievedonlythroughdirectmanipulationofagame’sassemblycode,viamethodssuchasNOPingorhooking.Inthissection,you’lllearnthebasicsofx86assemblylanguage,aspecificflavorofassemblymadeforspeakingto32-bitprocessors.Assemblylanguageisveryextensive,soforthesakeofbrevitythissectiontalksonlyaboutthesmallsubsetofassemblyconceptsthataremostusefultogamehackers.1
NOTE
Throughoutthissection,manysmallsnippetsofassemblycodeincludecommentssetoffbyasemicolon(;)todescribeeachinstructioningreaterdetail.
CommandSyntaxAssemblylanguageisusedtodescribemachinecode,soitssyntaxisprettysimplistic.Whilethissyntaxmakesitveryeasyforsomeonetounderstandindividualcommands(alsocalledoperations),italsomakesunderstanding
![Page 123: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/123.jpg)
complexblocksofcodeveryhard.Evenalgorithmsthatareeasilyreadableinhigh-levelcodeseemobfuscatedwhenwritteninassembly.Forexample,thefollowingsnippetofpseudocode:
if(EBX>EAX)ECX=EDXelseECX=0
wouldlooklikeListing4-6inx86assembly.
CMPEBX,EAXJGlabel1MOVECX,0JMPlabel2label1:MOVECX,EDXlabel2:
Listing4-6:Somex86assemblycommands
Therefore,ittakesextensivepracticetounderstandeventhemosttrivialfunctionsinassembly.Understandingindividualcommands,however,isverysimple,andbytheendofthissection,you’llknowhowtoparsethecommandsIjustshowedyou.
InstructionsThefirstpartofanassemblycommandiscalledaninstruction.Ifyouequateanassemblycommandtoaterminalcommand,theinstructionistheprogramtorun.Atthemachinecodelevel,instructionsaretypicallythefirstbyteofacommand;2therearealsosome2-byteinstructions,wherethefirstbyteis0x0F.Regardless,aninstructiontellstheprocessorexactlywhattodo.InListing4-6,CMP,JG,MOV,andJMPareallinstructions.
OperandSyntaxWhilesomeinstructionsarecompletecommands,thevastmajorityareincompleteunlessfollowedbyoperands,orparameters.EverycommandinListing4-6hasatleastoneoperand,likeEBX,EAX,andlabel1.
Assemblyoperandscomeinthreeforms:
![Page 124: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/124.jpg)
ImmediatevalueAnintegervaluethatisdeclaredinline(hexadecimalvalueshaveatrailingh).
RegisterAnamethatreferstoaprocessorregister.
MemoryoffsetAnexpression,placedinbrackets,thatrepresentsthememorylocationofavalue.Theexpressioncanbeanimmediatevalueoraregister.Alternatively,itcanbeeitherthesumordifferenceofaregisterandimmediatevalue(somethinglike[REG+Ah]or[REG-10h]).
Eachinstructioninx86assemblycanhavebetweenzeroandthreeoperands,andcommasareusedtoseparatemultipleoperands.Inmostcases,instructionsthatrequiretwooperandshaveasourceoperandandadestinationoperand.Theorderingoftheseoperandsisdependentontheassemblysyntax.Forexample,Listing4-7showsagroupofpseudocommandswrittenintheIntelsyntax,whichisusedbyWindows(and,thus,byWindowsgamehackers):
MOVR1,1;setR1(register)to1(immediate)➊MOVR1,[BADF00Dh];setR1tovalueat[BADFOODh](memoryoffset)MOVR1,[R2+10h];setR1tovalueat[R2+10h](memoryoffset)MOVR1,[R2-20h];setR1tovalueat[R2+20h](memoryoffset)
Listing4-7:DemonstratingIntelsyntax
IntheIntelsyntax,thedestinationoperandcomesfirst,followedbythesource,soat➊,R1isthedestinationand[BADFOODh]isthesource.Ontheotherhand,compilerslikeGCC(whichcanbeusedtowritebotsonWindows)useasyntaxknownasAT&T,orUNIX,syntax.Thissyntaxdoesthingsalittledifferently,asyoucanseeinthefollowingexample:
MOV$1,%R1;setR1(register)to1(immediate)MOV0xBADF00D,%R1;setR1tovalueat0xBADFOOD(memoryoffset)MOV0x10(%R2),%R1;setR1tovalueat0x10(%R2)(memoryoffset)MOV-0x20(%R2),%R1;setR1tovalueat-0x20(%R2)(memoryoffset)
ThiscodeistheAT&TversionofListing4-7.AT&Tsyntaxnotonlyreversestheoperandorderbutalsorequiresoperandprefixingandhasadifferentformatformemoryoffsetoperands.
AssemblyCommandsOnceyouunderstandassemblyinstructionsandhowtoformattheir
![Page 125: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/125.jpg)
Onceyouunderstandassemblyinstructionsandhowtoformattheiroperands,youcanstartwritingcommands.Thefollowingcodeshowsanassemblyfunction,consistingofsomeverybasiccommands,thatessentiallydoesnothing.
PUSHEBP;putEBP(register)onthestackMOVEBP,ESP;setEBPtovalueofESP(register,topofstack)PUSH-1;put-1(immediate)onthestackADDESP,4;negatethe'PUSH-1'toputESPbackwhereitwas(aPUSH;subtracts4fromESP,sinceitgrowsthestack)MOVESP,EBP;setESPtothevalueofEBP(theywillbethesameanyway,;sincewehavekeptESPinthesameplace)POPEBP;setEBPtothevalueontopofthestack(itwillbewhat;EBPstartedwith,putonthestackbyPUSHEBP)XOREAX,EAX;exclusive-orEAX(register)withitself(sameeffectas;'MOVEAX,0'butmuchfaster)RETN;returnfromthefunctionwithavalueof0(EAXtypically;holdsthereturnvalue)
Thefirsttwolines,aPUSHcommandandaMOVcommand,setupastackframe.Thenextlinepushes–1tothestack,whichisundonewhenthestackissetbacktoitsoriginalpositionbytheADDESP,4command.Followingthat,thestackframeisremoved,thereturnvalue(storedinEAX)issetto0withanXORinstruction,andthefunctionreturns.
You’lllearnmoreaboutstackframesandfunctionsin“TheCallStack”onpage86and“FunctionCalls”onpage94.Fornow,turnyourattentiontotheconstantsinthecode—namelyEBP,ESP,andEAX,whichareusedfrequentlyinthecodeasoperands.Thesevalues,amongothers,arecalledprocessorregisters,andunderstandingthemisessentialtounderstandingthestack,functioncalls,andotherlow-levelaspectsofassemblycode.
ProcessorRegistersUnlikehigh-levelprogramminglanguages,assemblylanguagedoesnothaveuser-definedvariablenames.Instead,itaccessesdatabyreferencingitsmemoryaddress.Duringintensivecomputation,however,itcanbeextremelycostlyfortheprocessortoconstantlydealwiththeoverheadofreadingandwritingdatatoRAM.Tomitigatethishighcost,x86processorsprovideasmallsetoftemporaryvariables,calledprocessorregisters,which
![Page 126: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/126.jpg)
provideasmallsetoftemporaryvariables,calledprocessorregisters,whicharesmallstoragespaceswithintheprocessoritself.SinceaccessingtheseregistersrequiresfarlessoverheadthanaccessingRAM,assemblyusesthemtodescribeitsinternalstate,passvolatiledataaround,andstorecontext-sensitivevariables.
GeneralRegistersWhenassemblycodeneedstostoreoroperateonarbitrarydata,itusesasubsetofprocessregisterscalledgeneralregisters.Theseregistersareusedexclusivelytostoreprocess-specificdata,suchasafunction’slocalvariables.Eachgeneralregisteris32bitsandthuscanbethoughtofasaDWORDvariable.Generalregistersarealsooptimizedforspecificpurposes:
EAX,theaccumulatorThisregisterisoptimizedformathematicalcomputations.Someoperations,suchasmultiplicationanddivision,canonlyoccurinEAX.
EBX,thebaseregisterThisregisterisusedarbitrarilyforextrastorage.Sinceits16-bitpredecessor,BX,wastheonlyregisterthatoperationscouldusetoreferencememoryaddresses,EBXwasusedasareferencetoRAM.Inx86assembly,however,allregisterscanbeaddressreferences,leavingEBXwithoutatruepurpose.
ECX,thecounterThisregisterisoptimizedtoactasthecountervariable(oftencallediinhigh-levelcode)inaloop.
EDX,thedataregisterThisregisterisoptimizedtoactasahelpertoEAX.In64-bitcomputations,forinstance,EAXactsasbits0–31andEDXactsasbits32–63.
Theseregistersalsohaveasetof8-and16-bitsubregistersthatyoucanusetoaccesspartialdata.Thinkofeverygeneralregisterasaunion,wherearegisternamedescribesthe32-bitmemberandthesubregistersarealternatemembersthatallowaccesstosmallerpiecesoftheregister.ThefollowingcodeshowswhatthisunionmightlooklikeforEAX:
union{DWORDEAX;WORDAX;struct{BYTEL;
![Page 127: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/127.jpg)
BYTEH;}A;}EAX;
Inthisexample,AXallowsaccesstothelowerWORDofEAX,whileALallowsaccesstothelowerBYTEofAXandAHtoitshigherBYTE.Everygeneralregisterhasthisstructure,andIoutlinetheotherregisters’subregistersinFigure4-5.
Figure4-5:x86registersandsubregisters
EAX,EBC,ECX,andEDXhavehigherwords,too,butthecompilerwillalmostneveraccessthemonitsown,asitcanjustusethelowerwordwhenitneedsword-onlystorage.
IndexRegistersx86assemblyalsohasfourindexregisters,whichareusedtoaccessdatastreams,referencethecallstack,andkeeptrackoflocalinformation.Likethegeneralregisters,indexregistersare32bits,butindexregistershavemorestrictlydefinedpurposes:
EDI,thedestinationindexThisregisterisusedtoindexmemorytargetedbywriteoperations.Iftherearenowriteoperationsinapieceofcode,thecompilercanuseEDIforarbitrarystorageifneeded.
ESI,thesourceindexThisregisterisusedtoindexmemorytargetedby
![Page 128: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/128.jpg)
readoperations.Itcanalsobeusedarbitrarily.
ESP,thestackpointerThisregisterisusedtoreferencethetopofthecallstack.Allstackoperationsdirectlyaccessthisregister.YoumustuseESPonlywhenworkingwiththestack,anditmustalwayspointtothetopofthestack.
EBP,thestackbasepointerThisregistermarksthebottomofthestackframe.Functionsuseitasareferencetotheirparametersandlocalvariables.Somecodemaybecompiledwithanoptiontoomitthisbehavior,inwhichcaseEBPcanbeusedarbitrarily.
Likethegeneralregisters,eachindexregisterhasa16-bitcounterpart:DI,SI,SP,andBP,respectively.However,theindexregistershaveno8-bitsubregisters.
WHYDOSOMEX86REGISTERSHAVESUBREGISTERS?
Thereisahistoricalreasonwhybothgeneralandindexregistershave16-bitcounterparts.Thex86architecturewasbasedona16-bitarchitecture,fromwhichitextendedtheregistersAX,BX,CX,DX,DI,SI,SP,andBP.Appropriately,theextensionsretainthesamenamesbutareprefixedwithanE,for“extended.”The16-bitversionsremainforbackwardcompatibility.Thisalsoexplainswhyindexregistershaveno8-bitabstractions:theyareintendedtobeusedasmemory-addressoffsets,andthereisnopracticalneedtoknowpartialbytesofsuchvalues.
TheExecutionIndexRegisterTheExecutionIndexregister,referredtoasEIP,hasaveryconcretepurpose:itpointstotheaddressofthecodecurrentlybeingexecutedbytheprocessor.Becauseitcontrolstheflowofexecution,itisdirectlyincrementedbytheprocessorandisoff-limitstoassemblycode.TomodifyEIP,assemblycodemustindirectlyaccessitusingoperationssuchasCALL,
![Page 129: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/129.jpg)
JMP,andRETN.
TheEFLAGSRegisterUnlikehigh-levelcode,assemblylanguagedoesn’thavebinarycomparisonoperatorslike==,>,and<.Instead,itusestheCMPcommandtocomparetwovalues,storingtheresultinginformationintheEFLAGSregister.Then,thecodechangesitscontrolflowusingspecialoperationsthatdependonthevaluestoredinELFAGS.
Whilecomparisoncommandsaretheonlyuser-modeoperationsthatcanaccessEFLAGS,theyuseonlythisregister’sstatusbits:0,2,4,6,7,and11.Bits8–10actascontrolflags,bits12–14and16–21actassystemflags,andtheremainingbitsarereservedfortheprocessor.Table4-5showsthetype,name,anddescriptionofeachEFLAGSbit.
Table4-5:EFLAGSbits
Bit(s)Type Name Description
0 Status Carry Setifacarryorborrowwasgeneratedfromthemostsignificantbitduringthepreviousinstruction.
2 Status Parity Setiftheleastsignificantbyteresultingfromthepreviousinstructionhasanevennumberofbitsset.
4 Status Adjust Sameasthecarryflag,butconsidersthe4leastsignificantbits.
6 Status Zero Setiftheresultingvaluefromthepreviousinstructionisequalto0.
7 Status Sign Setiftheresultingvaluefromthepreviousinstructionhasitssignbit(mostsignificantbit)set.
8 Control Trap Whenset,theprocessorsendsaninterrupttotheoperatingsystemkernelafterexecutingthenextoperation.
9 Control Interrupt Whennotset,thesystemignoresmaskable
![Page 130: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/130.jpg)
interrupts.
10 Control Direction Whenset,ESIandEDIaredecrementedbyoperationsthatautomaticallymodifythem.Whennotset,theyareincremented.
11 Status Overflow Setwhenavalueisoverflowedbythepreviousinstruction,suchaswhenADDisperformedonapositivevalueandtheresultisanegativevalue.
TheEFLAGSregisteralsocontainsasystembitandareservedbit,butthoseareirrelevantinuser-modeassemblyandgamehacking,soI’veomittedthemfromthistable.KeepEFLAGSinmindwhenyou’redebugginggamecodetofigureouthowitworks.Forexample,ifyousetabreakpointonaJE(jumpifequal)instruction,youcanlookattheEFLAGS0bittoseewhetherthejumpwillbetaken.
SegmentRegistersFinally,assemblylanguagehasasetof16-bitregisterscalledsegmentregisters.Unlikeotherregisters,segmentregistersarenotusedtostoredata;theyareusedtolocateit.Intheory,theypointtoisolatedsegmentsofmemory,allowingdifferenttypesofdatatobestoredincompletelyseparatememorysegments.Theimplementationofsuchsegmentationisleftuptotheoperatingsystem.Thesearethex86segmentregistersandtheirintendedpurposes:
CS,thecodesegmentThisregisterpointstothememorythatholdsanapplication’scode.
DS,thedatasegmentThisregisterpointstothememorythatholdsanapplication’sdata.
ES,FS,andGS,theextrasegmentsTheseregisterspointtoanyproprietarymemorysegmentsusedbytheoperatingsystem.
SS,thestacksegmentThisregisterpointstomemorythatactsasadedicatedcallstack.
Inassemblycode,segmentregistersareusedasprefixestomemoryoffsetoperands.Whenasegmentregisterisn’tspecified,DSisusedbydefault.
![Page 131: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/131.jpg)
ThismeansthatthecommandPUSH[EBP]iseffectivelythesameasPUSHDS:[EBP].ButthecommandPUSHFS:[EBP]isdifferent:itreadsmemoryfromtheFSsegment,nottheDSsegment.
IfyoulookcloselyattheWindowsx86implementationofmemorysegmentation,youmightnoticethatthesesegmentregisterswerenotexactlyusedasintended.Toseethisinaction,youcanrunthefollowingcommandswiththeOllyDbgcommandlineplug-inwhileOllyDbgisattachedtoapausedprocess:
?CALC(DS==SS&&SS==GS&&GS==ES)?1?CALCDS-CS?8?CALCFS-DS;returnsnonzero(andchangesbetweenthreads)
Thisoutputtellsusthreedistinctthings.First,itshowsthatthereareonlythreesegmentsbeingusedbyWindows:FS,CS,andeverythingelse.ThisisdemonstratedbyDS,SS,GS,andESbeingequal.Forthesamereason,thisoutputshowsthatDS,SS,GS,andEScanallbeusedinterchangeably,astheyallpointtothesamememorysegments.Lastly,sinceFSchangesdependingonthethread,thisoutputshowsthatitisthreaddependent.FSisaninterestingsegmentregister,anditpointstocertainthread-specificdata.In“BypassingASLRinProduction”onpage128,we’llexplorehowthedatainFScanbeusedtobypassASLR—somethingmostbotswillneedtodo.
Infact,inassemblycodegeneratedforWindowsbyacompiler,you’donlyeverseethreesegmentsused:DS,FS,andSS.Interestinglyenough,eventhoughCSseemstoshowaconstantoffsetfromDS,ithasnorealpurposeinuser-modecode.Knowingallofthesethings,youcanfurtherconcludethatthereareonlytwosegmentsbeingusedbyWindows:FSandeverythingelse.
Thesetwosegmentsactuallypointtodifferentlocationsinthesamememory(there’snosimplewaytoverifythis,butitistrue),whichshowsthatWindowsactuallydoesn’tusememorysegmentsatall.Instead,itusesaflatmemorymodelinwhichsegmentregistersarenearlyirrelevant.Whileallsegmentregisterspointtothesamememory,onlyFSandCSpointtodifferentlocations,andCSisnotused.
Inconclusion,thereareonlythreethingsyouneedtoknowabout
![Page 132: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/132.jpg)
Inconclusion,thereareonlythreethingsyouneedtoknowaboutsegmentregisterswhenworkingwithx86assemblyinWindows.First,DS,SS,GS,andESareinterchangeable,butforclarityDSshouldbeusedtoaccessdataandSSshouldbeusedtoaccessthecallstack.Second,CScanbesafelyforgotten.Third,FSistheonlysegmentregisterwithaspecialpurpose;itshouldbeleftalonefornow.
TheCallStackRegistersarepowerful,butunfortunatelytheycomeinverylimitedsupply.Inorderforassemblycodetoeffectivelystoreallofitslocaldata,itmustalsousethecallstack.Thestackisusedtostoremanydifferentvalues,includingfunctionparameters,returnaddresses,andsomelocalvariables.
Understandingtheinsandoutsofthecallstackwillcomeinhandywhenyou’rereverseengineeringagame.Moreover,you’llrelyonthisknowledgeheavilywhenwejumpintocontrolflowmanipulationinChapter8.
StructureYoucanthinkofthecallstackasaFILO(first-in-last-out)listofDWORDvaluesthatcanbedirectlyaccessedandmanipulatedbyassemblycode.Thetermstackisusedbecausethestructureresemblesastackofpaper:objectsarebothaddedtoandremovedfromthetop.DataisaddedtothestackthroughthePUSHoperandcommand,anditisremoved(andplacedinaregister)throughthePOPregistercommand.Figure4-6showshowthisprocessmightlook.
![Page 133: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/133.jpg)
Figure4-6:Thestructureofastack
InWindows,thestackgrowsfromhighermemoryaddressestolowerones.Itoccupiesafiniteblockofmemory,pilinguptoaddress0x00000000(theabsolutetop)fromaddressn(theabsolutebottom).ThismeansthatESP(thepointertothetopofthestack)decreasesasitemsareaddedandincreasesasitemsareremoved.
TheStackFrameWhenanassemblyfunctionusesthestacktostoredata,itreferencesthedatabycreatingastackframe.ItdoessobystoringESPinEBPandthensubtractingnbytesfromESP,effectivelyopeningann-bytegapthatisframedbetweentheregistersEBPandESP.Tobetterunderstandthis,firstimaginethatthestackinFigure4-7ispassedtoafunctionthatrequires0x0Cbytesoflocalstoragespace.
![Page 134: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/134.jpg)
Figure4-7:Initialexamplestack(readfrombottomtotop)
Inthisexample,address0x0000istheabsolutetopofthestack.Wehaveunusedmemoryfromaddresses0x0000to0xFF00–4,andatthetimeofthefunctioncall,0xFF00isthetopofthestack.ESPpointstothisaddress.Thestackmemoryafter0xFF00isusedbyprecedingfunctionsinthecallchain(from0xFF04to0xFFFF).Whenthefunctioniscalled,thefirstthingitdoesisexecutethefollowingassemblycode,whichcreatesastackframeof0x0C(12indecimal)bytes:
PUSHEBP;savesthebottomofthelowerstackframeMOVEBP,ESP;storesthebottomofthecurrentstackframe,inEBP;(also4bytesabovethelowerstackframe)SUBESP,0x0C;subtracts0x0CbytesfromESP,movingitupthestack;tomarkthetopofthestackframe
Afterthiscodeexecutes,thestacklooksmoreliketheoneshowninFigure4-8.Aftercreatingthisstack,thefunctioncanworkwiththe0x0Cbytesitallocatedonthestack.
0x0000isstilltheabsolutetopofthestack.Wehaveunusedstackmemoryfromaddresses0x0000to0xFF00–20,andthememoryataddress0xFF00–16containsthefinal4bytesoflocalstorage(referencedby[EBP-Ch]).Thisisalsothetopofthecurrentstackframe,soESPpointshere.0xFF00–12containsthemiddle4bytesoflocalstorage(referencedby[EBP-8h]),and0xFF00–8containsthefirst4bytesoflocalstorage(referencedby[EBP-4h]).EBPpointsto0xFF00–4,whichisthebottomofthecurrentstackframe;thisaddressholdstheoriginalvalueofEBP.0xFF00isthetopofthelowerstackframe,andtheoriginalESPinFigure4-7pointedhere.Finally,youcanstillseethestackmemoryfromprecedingfunctionsinthecallchainfrom0xFF04to0xFFFF.
![Page 135: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/135.jpg)
Figure4-8:Examplestackwithstackframesetup(readfrombottomtotop)
Withthestackinthisstate,thefunctionisfreetouseitslocaldataasitpleases.Ifthisfunctioncalledanotherfunction,thenewfunctionwouldbuilditsownstackframeusingthesametechnique(thestackframesreallystackup).Onceafunctionfinishesusingastackframe,however,itmustrestorethestacktoitspreviousstate.Inourcase,thatmeansmakingthestacklooklikeitdidinFigure4-7.Whenthesecondfunctionfinishes,ourfirstfunctioncleansthestackusingthefollowingtwocommands:
MOVESP,EBP;demolishesthestackframe,bringingESPto4bytesabove;itsoriginalvalue(0xFF00-4)POPEBP;restoresthebottomoftheoldstackframethatwassavedby;'PUSHEBP'.Alsoadds4bytestoESP,puttingitbackat;itsoriginalvalue
Butifyouwanttochangetheparameterspassedtoafunctioninagame,don’tlookfortheminthatfunction’sstackframe.Afunction’sparametersarestoredinthestackframeofthefunctionthatcalledit,andthey’re
![Page 136: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/136.jpg)
referencedthrough[EBP+8h],[EBP+Ch],andsoon.Theystartat[EBP+8h]because[EBP+4h]storesthefunction’sreturnaddress.(“FunctionCalls”onpage94explainsthistopicfurther.)
NOTE
Codecanbecompiledwithstackframesdisabled.Whenthisisthecase,you’llnoticethatfunctionsdon’topenwithPUSHEBPandinsteadreferenceeverythingrelativetoESP.Moreoftenthannot,though,stackframesareenabledincompiledgamecode.
Nowthatyouhaveagrasponthefundamentalsofassemblycode,let’sexploresomespecificsthatwillcomeinhandywhenhackinggames.
Importantx86InstructionsforGameHackingWhileassemblylanguagehashundredsofinstructions,manywell-equippedgamehackersunderstandonlyasmallsubsetofthem,whichIcoverindetailhere.Thissubsettypicallyencapsulatesallinstructionsthatareusedtomodifydata,callfunctions,comparevalues,orjumparoundwithincode.
DataModificationDatamodificationoftenhappensoverseveralassemblyoperations,buttheendresulthastobestoredeitherinmemoryorinaregister,typicallywiththeMOVinstruction.TheMOVoperationtakestwooperands:adestinationandasource.Table4-6showsallpossiblesetsofMOVoperandsandtheresultsyoucanexpectfromthosecalls.
Table4-6:OperandstotheMOVInstruction
Instructionsyntax Result
MOVR1,R2 CopiesR2’svaluetoR1.MOVR1,[R2] CopiesthevaluefromthememoryreferencedbyR2to
R1.MOVR1,[R2+Ah] Copiesthevaluefromthememoryreferencedby
R2+0xAtoR1.
![Page 137: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/137.jpg)
MOVR1,[DEADBEEFh] Copiesthevaluefromthememoryat0xDEADBEEFtoR1.
MOVR1,BADF00Dh Copiesthevalue0xBADF00DtoR1.MOV[R1],R2 CopiesR2’svaluetothememoryreferencedbyR1.MOV[R1],BADF00Dh Copiesthevalue0xBADF00Dtothememory
referencedbyR1.MOV[R1+4h],R2 CopiesR2’svaluetothememoryreferencedbyR1+0x4.MOV[R1+4h],BADF00Dh
Copiesthevalue0xBADF00DtothememoryreferencedbyR1+0x4.
MOV[DEADBEEFh],R1 CopiesR1’svaluetothememoryat0xDEADBEEF.MOV[DEADBEEFh],BADF00Dh
Copiesthevalue0xBADF00Dtothememoryat0xDEADBEEF.
TheMOVinstructioncantakealotofoperandcombinations,butsomearen’tallowed.First,thedestinationoperandcan’tbeanimmediatevalue;itmustbearegisterormemoryaddress,becauseimmediatevaluescan’tbemodified.Second,valuescan’tbedirectlycopiedfromonememoryaddresstoanother.Copyingavaluerequirestwoseparateoperations,likeso:
MOVEAX,[EBP+10h];copymemoryfromEBP+0x10toEAXMOV[DEADBEEFh],EAX;MOVthecopiedmemorytomemoryat0xDEADBEEF
TheseinstructionscopywhateverisstoredatEBP+0x10tothememoryat0xDEADBEEF.
ArithmeticLikemanyhigh-levellanguages,assemblylanguagehastwotypesofarithmetic:unaryandbinary.Unaryinstructionstakeasingleoperandthatactsasbothadestinationandasource.Thisoperandcanbearegisteroramemoryaddress.Table4-7showsthecommonunaryarithmeticinstructionsinx86.
Table4-7:UnaryArithmeticInstructions
![Page 138: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/138.jpg)
Instructionsyntax
Result
INCoperand Adds1totheoperandvalue.
DECoperand Subtracts1fromtheoperandvalue.NOToperand Logicallynegatestheoperandvalue(flipsallbits).NEGoperand Performstwo’s-complementnegation(flipsallbitsandadds1;
essentiallymultipliesby-1).
Binaryinstructions(whichmakeupthemajorityofx86arithmetic),ontheotherhand,aresyntacticallysimilartotheMOVinstruction.Theyrequiretwooperandsandhavesimilaroperandlimitations.UnlikeMOV,however,theirdestinationoperandservesasecondpurpose:itisalsotheleft-handvalueinthecalculation.Forexample,theassemblyoperationADDEAX,EBXequatestoEAX=EAX+EBXorEAX+=EBXinC++.Table4-8showsthecommonx86binaryarithmeticinstructions.
Table4-8:BinaryArithmeticInstructions
Instructionsyntax
Function Operandnotes
ADDdestination,source
destination+=source
SUBdestination,source
destination-=source
ANDdestination,source
destination&=source
ORdestination,source
destination|=source
XORdestination,source
destination^=source
SHLdestination,source
destination=destination<<source
sourcemustbeCLoran8-bitimmediatevalue.
![Page 139: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/139.jpg)
source source
SHRdestination,
source
destination=destination>>
source
sourcemustbeCLoran8-bitimmediatevalue.
IMULdestination,source
destination*=source
destinationmustbearegister;sourcecannotbeanimmediatevalue.
Ofthesearithmeticinstructions,IMULisspecialbecauseyoucanpassitathirdoperand,intheformofanimmediatevalue.Withthisprototype,thedestinationoperandisnolongerinvolvedinthecalculation,whichinsteadtakesplacebetweentheremainingoperands.Forexample,theassemblycommandIMULEAX,EBX,4hequatestoEAX=EBX*0x4inC++.
YoucanalsopassasingleoperandtoIMUL.3Inthiscase,theoperandactsasthesourceandcanbeeitheramemoryaddressoraregister.Dependingonthesizeofthesourceoperand,theinstructionwillusedifferentpartsoftheEAXregisterforinputsandoutput,asshowninTable4-9.
Table4-9:PossibleIMULRegisterOperands
Sourcesize
InputOutput
8bits AL 16bit,storedinAH:AL(whichisAX)
16bits AX 32bit,storedinDX:AX(bits0–15inAXandbits16–31inDX)
32bits EAX 64bit,storedinEDX:EAX(bits0–31inEAXandbits32–64inEDX)
Noticethateventhoughtheinputisonlyoneregister,eachoutputusestworegisters.That’sbecauseinmultiplication,theresultgenerallyislargerthantheinputs.
Let’slookatanexamplecalculationusingIMULwithasingle32-bitoperand:
IMUL[BADFOODh];32-bitoperandisataddress0xBADFOOD
Thiscommandbehaveslikethefollowingpseudocode:
![Page 140: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/140.jpg)
EDX:EAX=EAX*[BADFOODh]
Similarly,here’sanoperationthatusesIMULwithasingle16-bitoperand:
IMULCX;16-bitoperandisstoredinCX
Anditscorrespondingpseudocode:
DX:AX=AX*CX
Finally,thisisanIMULcommandwithasingle8-bitoperand:
IMULCL;8-bitoperandisstoredinCL
Anditscorrespondingpseudocode:
AX=AL*CL
x86assemblylanguagehasdivisionaswell,throughtheIDIVinstruction.4TheIDIVinstructionacceptsasinglesourceoperandandfollowsregisterrulessimilartothoseforIMUL.AsTable4-10shows,IDIVoperationsrequiretwoinputsandtwooutputs.
Table4-10:PossibleIDIVRegisterOperands
Sourcesize
Input Output
8bit 16bit,storedinAH:AL(whichisAX)
RemainderinAH;quotientinAL
16bit 32bit,storedinDX:AX RemainderinDX;quotientinAX
32bit 64bit,storedinEDX:EAX RemainderinEDX;quotientinEAX
Indivision,theinputsaregenerallylargerthantheoutput,soheretheinputstaketworegisters.Moreover,divisionoperationsmuststorearemainder,whichgetsstoredinthefirstinputregister.Forexample,here’showa32-bitIDIVcalculationwouldlook:
![Page 141: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/141.jpg)
MOVEDX,0;there'snohigh-orderDWORDintheinput,soEDXis0MOVEAX,inputValue;32-bitinputvalueIDIVECX;divideEDX:EAXbyECX
Andhere’ssomepseudocodethatexpresseswhathappensunderthehood:
EAX=EDX:EAX/ECX;quotientEDX=EDX:EAX%ECX;remainder
ThesedetailsofIDIVandIMULareimportanttoremember,asthebehaviorcanotherwisebequiteobfuscatedwhenyou’resimplylookingatthecommands.
BranchingAfterevaluatinganexpression,programscandecidewhattoexecutenextbasedontheresult,typicallyusingconstructssuchasif()statementsorswitch()statements.Thesecontrolflowstatementsdon’texistattheassemblylevel,however.Instead,assemblycodeusestheEFLAGSregistertomakedecisionsandjumpoperationstoexecutedifferentblocks;thisprocessiscalledbranching.
TogetthepropervalueinEFLAGS,assemblycodeusesoneoftwoinstructions:TESTorCMP.Bothcomparetwooperands,setthestatusbitsofEFLAGS,andthendiscardanyresults.TESTcomparestheoperandsusingalogicalAND,whileCMPusessignedsubtractiontosubtractthelatteroperandfromtheformer.
Inordertobranchproperly,thecodehasajumpcommandimmediatelyfollowingthecomparison.Eachtypeofjumpinstructionacceptsasingleoperandthatspecifiestheaddressofthecodetojumpto.HowaparticularjumpinstructionbehavesdependsonthestatusbitsofEFLAGS.Table4-11describessomex86jumpinstructions.
Table4-11:Commonx86JumpInstructions
InstructionName Behavior
JMPdest Unconditionaljump
Jumpstodest(setsEIPtodest).
![Page 142: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/142.jpg)
JEdest Jumpifequal JumpsifZF(zeroflag)is1.
JNEdest Jumpifnotequal JumpsifZFis0.JGdest Jumpifgreater JumpsifZFis0andSF(signflag)isequalto
OF(overflowflag).JGEdest Jumpifgreater
orequalJumpsifSFisequaltoOF.
JAdest UnsignedJG JumpsifCF(carryflag)is0andZFis0.JAEdest UnsignedJGE JumpsifCFis0.JLdest Jumpifless JumpsifSFisnotequaltoOF.JLEdest Jumpiflessor
equalJumpsifZFis1orSFisnotequaltoOF.
JBdest UnsignedJL JumpsifCFis1.JBEdest UnsignedJLE JumpsifCFis1orZFis1.JOdest Jumpifoverflow JumpsifOFis1.JNOdest Jumpifnot
overflowJumpsifOFis0.
JZdest Jumpifzero JumpsifZFis1(identicaltoJE).JNZdest Jumpifnotzero JumpsifZFis0(identicaltoJNE).
Rememberingwhichflagscontrolwhichjumpinstructionscanbeapain,buttheirpurposeisclearlyexpressedintheirname.AgoodruleofthumbisthatajumpprecededbyaCMPisthesameasitscorrespondingoperator.Forexample,Table4-11listsJEas“jumpifequal,”sowhenJEfollowsaCMPoperation,it’sthesameasthe==operator.Similarly,JGEwouldbe>=,JLEwouldbe>=,andsoon.
Asanexample,considerthehigh-levelcodeshowninListing4-8.
--snip--if(EBX>EAX)ECX=EDX;elseECX=0;
![Page 143: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/143.jpg)
--snip--
Listing4-8:Asimpleconditionalstatement
Thisif()statementjustcheckswhetherEBXisgreaterthanEAXandsetsECXbasedontheresult.Inassembly,thesamestatementmaylooksomethinglikethis:
--snip--CMPEBX,EAX;if(EBX>EAX)JGlabel1;jumptolabel1ifEBX>EAXMOVECX,0;ECX=0(elseblock)JMPlabel2;jumpovertheifblocklabel1:➊MOVECX,EDX;ECX=EDX(ifblock)label2:--snip--
Theassemblyfortheif()statementinListing4-8beginswithaCMPinstructionandbranchesifEBXisgreaterthanEAX.Ifthebranchistaken,EIPissettotheifblockat➊courtesyoftheJGinstruction.Ifthebranchisnottaken,thecodecontinuesexecutinglinearlyandhitstheelseblockimmediatelyaftertheJGinstruction.Whentheelseblockfinishesexecuting,anunconditionalJMPsetsEIPto0x7,skippingovertheifblock.
FunctionCallsInassemblycode,functionsareisolatedblocksofcommandsexecutedthroughtheCALLinstruction.TheCALLinstruction,whichtakesafunctionaddressastheonlyoperand,pushesareturnaddressontothestackandsetsEIPtoitsoperandvalue.ThefollowingpseudocodeshowsaCALLinaction,withmemoryaddressesontheleftinhex:
0x1:CALLEAX0x2:...
WhenCALLEAXisexecuted,thenextaddressispushedtothestackandEIPissettoEAX,showingthatCALLisessentiallyaPUSHandJMP.Thefollowingpseudocodeunderscoresthispoint:
0x1:PUSH3h0x2:JMPEAX0x3:...
![Page 144: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/144.jpg)
Whilethere’sanextraaddressbetweenthePUSHinstructionandthecodetoexecute,theresultisthesame:beforetheblockofcodeatEAXisexecuted,theaddressofthecodethatfollowsthebranchispushedtothestack.Thishappenssothecallee(thefunctionbeingcalled)knowswheretojumptointhecaller(thefunctiondoingthecall)whenitreturns.
Ifafunctionwithoutparametersiscalled,aCALLcommandisallthat’snecessary.Ifthecalleetakesparameters,however,theparametersmustfirstbepushedontothestackinreverseorder.Thefollowingpseudocodeshowshowafunctioncallwiththreeparametersmightlook:
PUSH300h;arg3PUSH200h;arg2PUSH100h;arg1CALLECX;call
Whenthecalleeisexecuted,thetopofthestackcontainsareturnaddressthatpointstothecodeafterthecall.Thefirstparameter,0x100,isbelowthereturnaddressonthestack.Thesecondparameter,0x200,isbelowthat,followedbythethirdparameter,0x300.Thecalleesetsupitsstackframe,usingmemoryoffsetsfromEBPtoreferenceeachparameter.Oncethecalleehasfinishedexecuting,itrestoresthecaller’sstackframeandexecutestheRETinstruction,whichpopsthereturnaddressoffthestackandjumpstoit.
Sincetheparametersarenotapartofthecallee’sstackframe,theyremainonthestackafterRETisexecuted.Ifthecallerisresponsibleforcleaningthestack,itadds12(3parameters,at4byteseach)toESPimmediatelyafterCALLECXcompletes.Ifthecalleeisresponsible,itcleansupbyexecutingRET12insteadofRET.Thisresponsibilityisdeterminedbythecallee’scallingconvention.
Afunction’scallingconventiontellsthecompilerhowtheassemblycodeshouldpassparameters,storeinstancepointers,communicatethereturnvalue,andcleanthestack.Differentcompilershavedifferentcallingconventions,buttheoneslistedinTable4-12aretheonlyfourthatagamehackerislikelytoencounter.
Table4-12:CallingConventionstoKnowforGameHacking
Directive CleanerNotes__cdecl caller DefaultconventioninVisualStudio.
![Page 145: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/145.jpg)
__stdcall callee ConventionusedbyWin32APIfunctions.__fastcallcallee FirsttwoDWORD(orsmaller)parametersarepassedin
ECXandEDX.__thiscallcallee Usedformemberfunctions.Thepointertotheclass
instanceispassedinECX.
TheDirectivecolumninTable4-12givesthenameofthecallingconvention,andtheCleanercolumntellsyouwhetherthecallerorcalleeisresponsibleforcleaningthestackgiventhatdirective.Inthecaseofthesefourcallingconventions,parametersarealwayspushedrighttoleft,andreturnvaluesarealwaysstoredinEAX.Thisisastandard,butnotarule;itcandifferacrossothercallingconventions.
ClosingThoughtsMygoalinwritingthischapterwastohelpyouunderstandmemoryandassemblyinageneralsense,beforewedigintogame-hackingspecifics.Withyournewfoundabilitytothinklikeacomputer,youshouldbeadequatelyarmedtostarttacklingmoreadvancedmemoryforensicstasks.Ifyou’reitchingforapeekathowyou’llapplyallofthistosomethingreal,flipto“ApplyingCallHookstoAdobeAIR”onpage169or“ApplyingJumpHooksandVFHookstoDirect3D”onpage175.
Ifyouwantsomehands-ontimewithmemory,compilethischapter’sexamplecodeanduseCheatEngineorOllyDbgtoinspect,tweak,andpokeatthememoryuntilyou’vegotthehangofit.Thisisimportant,asthenextchapterwillbuildontheseskillsbyteachingyouadvancedmemoryforensictechniques.
![Page 146: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/146.jpg)
5ADVANCEDMEMORYFORENSICS
Whetheryouhackgamesasahobbyorabusiness,you’lleventuallyfindyourselfbetweenarockand...anunintelligiblememorydump.Beitaracewitharivalbotdevelopertoreleaseahighlyrequestedfeature,abattleagainstagamecompany’sconstantbarrageofupdates,orastruggletolocatesomecomplexdatastructureinmemory,you’llneedtop-notchmemoryforensicsskillstoprevail.
Successfulbotdevelopmentisprecariouslybalancedatopspeedandskill,andtenacioushackersmustrisetothechallengebyswiftlyreleasingingeniousfeatures,promptlyrespondingtogameupdates,andreadilysearchingforeventhemostelusivepiecesofdata.Doingthis,however,requiresacomprehensiveunderstandingofcommonmemorypatterns,advanceddatastructures,andthepurposeofdifferentpiecesofdata.
Thosethreeaspectsofmemoryforensicsareperhapsthemosteffectiveweaponsinyourarsenal,andthischapterwillteachyouhowtousethem.First,I’lldiscussadvancedmemory-scanningtechniquesthatfocusonsearchingfordatabyunderstandingitspurposeandusage.Next,I’llteachyouhowtousememorypatternstotacklegameupdatesandtweakyourbotswithouthavingtorelocateallofyouraddressesfromscratch.Towrapup,I’lldissectthefourmostcommoncomplexdatastructuresintheC++standardlibrary(std::string,std::vector,std::list,andstd::map)soyoucanrecognizetheminmemoryandenumeratetheircontents.Bytheendofthechapter,myhopeisthatyou’llhaveadeepunderstandingofmemory
![Page 147: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/147.jpg)
forensicsandbeabletotakeonanychallengerelatedtomemoryscanning.
AdvancedMemoryScanningWithinagame’ssourcecode,eachpieceofdatahasacold,calculateddefinition.Whenthegameisbeingplayed,however,allofthatdatacomestogethertocreatesomethingnew.Playersonlyexperiencethebeautifulscenery,visceralsounds,andintenseadventures;thedatathatdrivestheseexperiencesisirrelevant.
Withthatinmind,imagineHackerAhasjuststartedtearingintohisfavoritegame,wantingtoautomatesomeoftheboringbitswithabot.Hedoesn’thaveacompleteunderstandingofmemoryyet,andtohim,thedataisnothingbutassumptions.Hethinks,“Ihave500health,soIcanfindthehealthaddressbytellingCheatEnginetolookfora4-byteintegerwithavalueof500.”HackerAhasanaccurateunderstandingofdata:it’sjustinformation(values)storedatparticularlocations(addresses)usingdefinedstructures(types).
NowimagineHackerB,whoalreadyunderstandsthegamebothinsideandout;sheknowshowplayingthegamealtersitsstateinmemory,andthedatanolongerhasanysecrets.Sheknowsthateverydefinedpropertyofthedatacanbedeterminedgivenitspurpose.UnlikeHackerA,HackerBhasanunderstandingofdatathattranscendstheconfinesofasinglevariabledeclaration:sheconsidersthedata’spurposeandusage.Inthissection,we’lldiscussboth.
Eachpieceofdatainagamehasapurpose,andtheassemblycodeofthegamemust,atsomepoint,referencethedatatofulfillthatpurpose.Findingtheuniquecodethatusesapieceofdatameansfindingaversion-agnosticmarkerthatpersistsacrossgameupdatesuntilthedataiseitherremovedoritspurposeischanged.Letmeshowyouwhythisisimportant.
DeducingPurposeSofar,I’veonlyshownyouhowtoblindlysearchmemoryforagivenpieceofdatawithoutconsideringhowit’sbeingused.Thismethodcanbeeffective,butitisnotalwaysefficient.Inmanycases,it’smuchquickertodeducethepurposeofdata,determinewhatcodemightusethatdata,andthenlocatethatcodetoultimatelyfindtheaddressofthedata.
![Page 148: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/148.jpg)
thenlocatethatcodetoultimatelyfindtheaddressofthedata.Thismightnotsoundeasy,butneitherdoes“scanthegame’smemoryfor
aspecificvalueofaspecificdatatype,andthencontinuouslyfiltertheresultlistbasedonchangingcriteria,”whichiswhatyou’velearnedtodothusfar.Solet’slookathowwemightlocatetheaddressforhealthgivenitspurpose.ConsiderthecodeinListing5-1.
structPlayerVital{intcurrent,maximum;};PlayerVitalhealth;--snip--printString("Health:%dof%d\n",health.current,health.maximum);
Listing5-1:Astructurecontainingtheplayer’svitals,andafunctionthatdisplaysthem
IfyoupretendthatprintString()isafancyfunctiontodrawtextonanin-gameinterface,thenthiscodeisprettyclosetowhatyoumightfindinagame.ThePlayerVitalstructurehastwoproperties:thecurrentvalueandamaximumvalue.ThevaluehealthisaPlayerVitalstructure,soithastheseproperties,too.Basedonthenamealone,youcandeducethathealthexiststodisplayinformationabouttheplayer’shealth,andyoucanseethispurposefulfilledwhenprintString()usesthedata.
Evenwithoutthecode,youcanintuitivelydrawsimilarconclusionsbyjustlookingatthehealthtextdisplayedinthegame’sinterface;acomputercan’tdoanythingwithoutcode,afterall.Asidefromtheactualhealthvariable,thereareafewcodeelementsthatneedtoexisttoshowaplayerthistext.First,thereneedstobesomefunctiontodisplaytext.Second,thestringsHealthandofmustbenearby.
NOTE
WhydoIassumethetextissplitintotwoseparatestringsinsteadofone?Thegameinterfaceshowsthatthecurrenthealthvalueisbetweenthesetwostrings,buttherearemanywaysthatcouldhappen,includingformatstrings,strcat(),ortextalignedwithmultipledisplaytextcalls.Whenyou’reanalyzingdata,it’sbesttokeepyourassumptionsbroadtoaccountforallpossibilities.
Tofindhealthwithoutusingamemoryscanner,wecouldutilizethesetwodistinctstrings.Weprobablywouldn’thaveacluewhatthefunctionto
![Page 149: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/149.jpg)
displaytextlookslike,whereitis,orhowmanytimesit’scalled,though.Realistically,thestringsareallwewouldknowtolookfor,andthat’senough.Let’swalkthroughit.
FindingthePlayer’sHealthwithOllyDbgI’llwalkyouthroughhowtotrackdownthehealthstructureinthissection,butI’vealsoincludedthebinaryIanalyzeinthebook’sresourcefiles.Tofollowalongandgetsomehands-onpractice,usethefileChapter5_AdvancedMemoryForensics_Scanning.exe.
First,openOllyDbgandattachittotheexecutable.Then,openOllyDbg’sExecutablemoduleswindowanddouble-clickthemainmodule;inmyexample,themainmoduleistheonly.exeinthemodule’swindow.TheCPUwindowshouldpopup.Now,right-clickintheDisassemblerpaneandselectSearchfor▸Allreferencedtextstrings.ThisshouldopentheReferenceswindow,showninFigure5-1.
Figure5-1:OllyDbg’sReferenceswindow,showingonlyalistofstrings.Therewouldbealotmorethanfourinarealgame.
Fromthiswindow,right-clickandselectSearchfortext.Asearchdialogappears.Enterthestringyou’relookingfor,asshowninFigure5-2,andmakethesearchasbroadaspossiblebydisablingCasesensitiveandenablingEntirescope.
![Page 150: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/150.jpg)
Figure5-2:SearchingforstringsinOllyDbg
ClickOKtoexecutethesearch.TheReferenceswindowcomesbackintofocuswiththefirstmatchhighlighted.Double-clickthematchtoseetheassemblycodethatusesthestringinsidetheCPUwindow.TheDisassemblerpanefocusesonthelineofcodeat0x401030,whichpushestheformatstringparametertoprintString().YoucanseethislineinFigure5-3,whereI’vehighlightedtheentirefunctioncallblock.
Figure5-3:ViewingtheprintString()callintheCPUwindow’sDisassemblerpane
Byreadingtheassemblycode,youcangetaveryaccurateunderstandingofexactlywhatthegameisdoing.TheblackbracketontheleftshowsthatthestringHealthisinsideafunctioncall.Noticetheargumentstothatfunction.Inorder,theseareEAX➊,ECX➋,andtheformatstringat0x4020D0➌.EAXisthevalueat0x40301C,ECXisthevalueat0x403018,andtheformatstringcontainsHealth.Sincethestringcontainstwoformatplaceholders,youcanassumethattheremainingtwoparametersaretheargumentsforthoseplaceholders.
Knowingwhattheargumentsareandthattheyarepushedinreverseorder,youcanworkbackwardandconcludethattheoriginalcodelookedsomethinglikeListing5-2.
intcurrentHealth;//valueat0x403018
![Page 151: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/151.jpg)
intmaxHealth;//valueat0x40301C--snip--someFunction("Health:%dof%d\n",currentHealth,maxHealth);
Listing5-2:HowagamehackermightinterprettheassemblythatFigure5-3compilesto
ThevaluesstoredinEAXandECXareadjacentinmemory,whichmeanstheymaybepartofastructure.Tokeepitsimple,though,thisexamplejustshowsthemasvariabledefinitions.Eitherway,thesearethetwonumbersusedtodisplaytheplayer’shealth.Becausebothoftheseimportantvaluesweredisplayedinthegame’sUI,itwaseasytomakeassumptionsabouttheunderlyingcodethatdisplaysthem.Whenyouknowthepurposeofapieceofdata,youcanquicklyfindthecoderesponsibleforfulfillingit;inthiscase,thatknowledgehelpedusquicklyfindbothaddresses.
Inmanycases,findingaddressescanbethiseasy,butsomepiecesofdatahavesuchcomplexpurposesthatit’shardertoguesswhattolookfor.FiguringouthowtosearchformapdataorcharacterlocationsinOllyDbg,forinstance,canbeprettytricky.
Stringsarefarfromtheonlymarkersthatyoucanusetofindthedatayouwanttochangeinagame,buttheyaredefinitelytheeasiesttoteachwithoutgivingcontrivedexamples.Moreover,somegameshaveloggingorerrorstringsembeddedintheircode,andpokingaroundintheReferencedtextstringswindowofOllyDbgcanbeaquickwaytodeterminewhetherthesestringsarepresent.Ifyoubecomefamiliarwithagame’sloggingpractices,you’llbeabletofindvaluesevenmoreeasily.
DeterminingNewAddressesAfterGameUpdatesWhenapplicationcodeismodifiedandrecompiled,abrand-newbinarythatreflectsthechangesisproduced.Thisbinarymightbeverysimilartothepreviousone,orthebinariesmightbenothingalike;thedifferencebetweenthetwoversionshasadirectcorrelationtothecomplexityofthehigh-levelchanges.Smallchanges,likemodifiedstringsorupdatedconstants,canleavebinariesnearlyidenticalandoftenhavenoeffectontheaddressesofcodeordata.Butmorecomplexchanges—likeaddedfeatures,anewuserinterface,refactoredinternals,ornewin-gamecontent—oftencauseshiftsinthelocationofcrucialmemory.
![Page 152: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/152.jpg)
AUTOMATICALLYFINDCURRENTHEALTHANDMAXHEALTH
In“SearchingforAssemblyPatterns”onpage19and“SearchingforStrings”onpage21,IshowedafewCheatEngineLuascriptsandexplainedhowtheyworked.UsingthefindString()functionintheseexamples,youcanmakeCheatEngineautomaticallylocatetheaddressoftheformatstringthatwejustfoundmanuallyinOllyDbg.Next,youcanwriteasmallfunctiontoscanforthisaddressfollowingbyte0x68(thebyteforthePUSHcommand,asyoucanseebesideitat0x401030inFigure5-3)tolocatetheaddressofthecodethatpushesittothestack.Then,youcanread4bytesfrompushAddress-5andpushAddress-12tolocatecurrentHealthandmaxHealth,respectively.
Thismaynotseemusefulsincewe’vealreadyfoundtheaddresses,butifthiswerearealgame,theseaddresseswouldchangewhenanupdateisreleased.Usingthisknowledgetoautomatefindingthemcanbeveryhelpful.Ifyou’reuptothechallenge,giveitawhirl!
Duetoconstantbugfixes,contentimprovements,andfeatureadditions,onlinegamesareamongthemostrapidlyevolvingtypesofsoftware.Somegamesreleaseupdatesasoftenasonceaweek,andgamehackersoftenspendamajorityoftheirtimereverseengineeringthenewbinariesinordertoaccordinglyupdatetheirbots.
Ifyoucreateadvancedbots,theywillbecomeincreasinglysupportedbyafoundationofmemoryaddresses.Whenanupdatecomes,determiningthenewaddressesforalargenumberofvaluesandfunctionsisthemosttime-consuminginevitabilityyouwillface.Relyingonthe“TipsforWinningtheUpdateRace”canbeverybeneficial,butthetipswon’thelpyoulocatetheupdatedaddresses.YoucanautomaticallylocatesomeaddressesusingCheatEnginescripts,butthatwon’talwaysworkeither.Sometimesyou’llhavetodothedirtyworkbyhand.
Ifyoutrytoreinventthewheelandfindtheseaddressesthesamewayyoudidinitially,you’llbewastingyourtime.Youactuallyhaveabigadvantage,though:theoldbinaryandtheaddressesthemselves.Usingthesetwothings,itispossibletofindeverysingleaddressyouneedtoupdateina
![Page 153: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/153.jpg)
twothings,itispossibletofindeverysingleaddressyouneedtoupdateinafractionofthetime.
Figure5-4showstwodifferentdisassemblies:anewgamebinaryontheleftandthepreviousversionontheright.Ihavetakenthisimagefromanactualgame(whichwillremainnameless)inordertogiveyouarealisticexample.
Figure5-4:Side-by-sidedisassembliesoftwoversionsofonegame
Mybotmodifiedthecodeat0x047B542(right),andIneededtofindthecorrespondingcodeinthenewversion,whichIdiscoveredat0x047B672(left).Thisfunctioncallinvokesapacket-parsingfunctionwhenapackethasbeenreceived.Inordertofindthisaddressoriginally(andby“originally,”Imeanabout100updatesprevious),Ifiguredouthowthegame’snetworkprotocolworked,setbreakpointsonmanynetwork-relatedAPIcalls,steppedthroughexecution,andinspecteddataonthestackuntilIfoundsomethingthatlookedsimilartowhatIexpectedgivenmyknowledgeoftheprotocol.
TIPSFORWINNINGTHEUPDATERACEInsaturatedmarkets,beingthefirstbotdevelopertoreleaseastableupdateiscriticaltosuccess.Theracestartsthesecondthegameupdates,andhackersdeterminedtobethefastestwillspendhundredsofhourspreparing.Thesearethemostcommonwaystostayontop:
CreateupdatealarmsBywritingsoftwarethatalertsyouassoonasthegamepatches,youcanbeginworkingonyourupdatesassoonaspossible.
AutomatebotinstallsGamesoftenscheduleexpectedupdatesattimeswhenthefewestplayersareonline.Bottershatewakingupand
![Page 154: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/154.jpg)
downloadingnewsoftwarebeforetheybot,buttheylovewakinguptofinditsilentlyinstalledwhilethegameispatching.
UsefeweraddressesThelessthereistoupdate,thebetter.Consolidatingrelateddataintostructuresandeliminatingunnecessarymemoryaddressusagecansaveabunchoftime.
HavegreattestcasesDatachanges,andhackersmakemistakes.Havingwaystoquicklytesteveryfeaturecanbethedifferencebetweenastablebotandonethatrandomlycrashes,getsuserskilled,orevenleadstotheircharactersbeingbannedfromthegame.
Attackingupdateswiththesepracticeswillgiveyouasizableheadstart,buttheymightnotalwaysbeenoughtoleadyoutovictory.Aboveallelse,strivetounderstandreverseengineeringasmuchaspossibleandusethatunderstandingtoyouradvantage.
Icouldhavefollowedthesamestepsforeachofthe100+updatessincethen,butthatwouldhavebeenunnecessary.Thecodestayedrelativelythesamethroughouttheyears,whichletmeusepatternsfromtheoldcodetofindthatfunctioncall’saddressinthenewcode.
Now,considerthischunkofassemblycode:
PUSHEDIPUSHEAXLEAEAX,DWORDPTRSS:[EBP-C]MOVDWORDPTRFS:[0],EAXMOVDWORDPTRSS:[EBP-10],ESPMOVDWORDPTRSS:[EBP-220],-1MOVDWORDPTRSS:[EBP-4],0
Doesitlookfamiliar?CompareittoFigure5-4,andyou’llseethatthisexactcodeexistsrightabovethehighlightedfunctioncallinbothversionsofthegame.Regardlessofwhatitdoes,thecombinationofoperationslooksprettydistinctive;becauseofthenumberofdifferentoffsetsthecodeisusingrelativetoEBP,it’sunlikelythatanidenticalchunkofcodeexistsinanyotherpartofthebinary.
EverytimeIhavetoupdatethisaddress,IopentheoldbinaryinOllyDbg,highlightthischunkofoperations,right-click,andselect
![Page 155: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/155.jpg)
Asm2Clipboard▸Copyfixedasmtoclipboard.Then,IopenthenewbinaryinOllyDbg,navigatetotheCPUWindow,pressCTRL-S,pastetheassemblycode,andhitFind.In9.5casesoutof10,thisplacesmedirectlyabovethefunctioncallIneedtofindinthenewversion.
Whenanupdatecomes,youcanusethesamemethodtofindnearlyallofyourknownaddresses.Itshouldworkforeveryaddressyoucanfindeasilyinassemblycode.Thereareafewcaveats,though:
•OllyDbglimitssearchtoeightoperations,soyoumustfindcodemarkersofthatsizeorsmaller.
•Theoperationsyouusecannotcontainanyotheraddresses,asthoseaddresseshavelikelychanged.
•Ifpartsofthegamehavechangedthatusetheaddressyou’relookingfor,thecodemightbedifferent.
•Ifthegamechangescompilersorswitchesoptimizationsettings,almostallcodewillbeentirelydifferent.
Asdiscussedin“AutomaticallyFindcurrentHealthandmaxHealth”onpage102,youcanbenefitfromwritingscriptsthatcarryoutthesetasksforyou.Seriousgamehackersworkveryhardtoautomaticallylocateasmanyaddressesaspossible,andsomeofthebestbotsareengineeredtoautomaticallydetecttheiraddressesatruntime,everytime.Itcanbealotofworkinitially,buttheinvestmentcandefinitelypayoff.
IdentifyingComplexStructuresinGameDataChapter4describedhowagamemightstoredatainstaticstructures.Thisknowledgewillsufficewhenyou’retryingtofindsimpledata,butitfallsshortfordatathatisstoredthroughdynamicstructures.Thisisbecausedynamicstructuresmightbescatteredacrossdifferentmemorylocations,followlongpointerchains,orrequirecomplexalgorithmstoactuallyextractthedatafromthem.
Thissectionexplorescommondynamicstructuresyou’llfindinvideogamecode,andhowtoreaddatafromthemoncethey’refound.Tobegin,I’lltalkabouttheunderlyingcompositionofeachdynamicstructure.Next,I’lloutlinethealgorithmsneededtoreadthedatafromthesestructures.(For
![Page 156: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/156.jpg)
simplicity,eachalgorithmdiscussionassumesyouhaveapointertoaninstanceofthestructureaswellassomewaytoreadfrommemory.)Lastly,I’llcovertipsandtricksthatcanhelpyoudeterminewhenavalueyou’researchingforinmemoryisactuallyencapsulatedinoneofthesestructures,soyou’llknowwhentoapplythisknowledge.I’llfocusonC++,asitsobject-orientednatureandheavilyusedstandardlibraryaretypicallyresponsibleforsuchstructures.
NOTE
Someofthesestructuresmightdifferslightlyfrommachinetomachinebasedoncompilers,optimizationsettings,orstandardlibraryimplementations,butthebasicconceptswillremainthesame.Also,intheinterestofbrevity,Iwillbeomittingirrelevantpartsofthesestructures,suchascustomallocatorsorcomparisonfunctions.Workingexamplecodecanbefoundathttps://www.nostarch.com/gamehacking/intheresourcefilesforChapter5.
Thestd::stringClassInstancesofstd::stringareamongthemostcommonculpritsofdynamicstorage.ThisclassfromtheC++StandardTemplateLibrary(STL)abstractsstringoperationsawayfromthedeveloperwhilepreservingefficiency,makingitwidelyusedinalltypesofsoftware.Avideogamemightusestd::stringstructureforanystringdata,suchascreaturenames.
ExaminingtheStructureofastd::stringWhenyoustripawaythememberfunctionsandothernondatacomponentsofthestd::stringclass,thisisthestructurethatremains:
classstring{union{char*dataP;chardataA[16];};intlength;};
//pointtoastringinmemory
![Page 157: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/157.jpg)
string*_str=(string*)stringAddress;
Theclassreserves16charactersthatarepresumablyusedtostorethestringinplace.Italso,however,declaresthatthefirst4bytescanbeapointertoacharacter.Thismightseemodd,butit’saresultofoptimization.Atsomepoint,thedevelopersofthisclassdecidedthat15characters(plusanullterminator)wasasuitablelengthformanystrings,andtheychosetosaveonmemoryallocationsandde-allocationsbyreserving16bytesofmemoryinadvance.Toaccommodatelongerstrings,theyallowedthefirst4bytesofthisreservedmemorytobeusedasapointertothecharactersoftheselongerstrings.
NOTE
Ifthecodewerecompiledto64bits,thenitwouldactuallybethefirst8(not4)bytesthatpointtoacharacter.Throughoutthisexample,however,youcanassume32-bitaddressesandthatintisthesizeofanaddress.
Accessingstringdatathiswaytakessomeoverhead.Thefunctiontolocatetherightbufferlookssomethinglikethis:
constchar*c_str(){if(_str->length<=15)return(constchar*)&_str->dataA[0];elsereturn(constchar*)_str->dataP;}
Thefactthatastd::stringcanbeeitheracompletestringorapointertoalongerstringmakesthisparticularstructurequitetrickyfromagame-hackingperspective.Somegamesmayusestd::stringtostorestringsthatonlyrarelyexceed15characters.Whenthisisthecase,youmightimplementbotsthatrelyonthesestrings,neverknowingthattheunderlyingstructureisinfactmorecomplicatedthanasimplestring.
Overlookingastd::stringCanRuinYourFunNotknowingthetruenatureofthestructurecontainingthedatayouneedcanleadyoutowriteabotthatworksonlysomeofthetimeandfailswhenitcounts.Imagine,forexample,thatyou’retryingtofigureouthowagame
![Page 158: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/158.jpg)
storescreaturedata.Inyourhypotheticalsearch,youfindthatallthecreaturesinthegamearestoredinanarrayofstructuresthatlooksomethinglikeListing5-3.
structcreatureInfo{intuniqueID;charname[16];intnameLength;inthealthPercent;intxPosition;intyPosition;intmodelID;
intcreatureType;};
Listing5-3:Howyoumightinterpretcreaturedatafoundinmemory
Afterscanningthecreaturedatainmemory,sayyounoticethatthefirst4bytesofeachstructureareuniqueforeachcreature,soyoucallthosebytestheuniqueIDandassumetheyformasingleintproperty.Lookingfurtherinthememory,youfindthatthecreature’snameisstoredrightafteruniqueID,andaftersomededuction,youfigureoutthenameis16byteslong.ThenextvalueyouseeinmemoryturnsouttobethenameLength;it’sabitstrangethatanull-terminatedstringhasanassociatedlength,butyouignorethatoddityandcontinueanalyzingthedatainmemory.Afterfurtheranalysis,youdeterminewhattheremainingvaluesarefor,definethestructureshowninListing5-3,andwriteabotthatautomaticallyattackscreatureswithcertainnames.
AfterweeksoftestingyourbotwhilehuntingcreatureswithnameslikeDragon,Cyclops,Giant,andHound,youdecideit’stimetogiveyourbottoyourfriends.Fortheinauguraluse,yougathereveryonetogethertokillabossnamedSuperBossmanSupreme.TheentireteamsetsthebottoattackthebossfirstandtargetlessercreatureslikeaDemonorGrimReaperwhenthebossgoesoutofrange.
Onceyourteamarrivesattheboss’sdungeon...you’reallslowlyobliterated.
Whatwentwronginthisscenario?Yourgamemustbestoringcreaturenameswithstd::string,notjustasimplecharacterarray.ThenameandnameLengthfieldsincreatureInfoare,infact,partofastd::stringfield,andthenamecharacterarrayisaunionofdataAanddataPmembers.Super
![Page 159: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/159.jpg)
BossmanSupremeislongerthan15characters,andbecausethebotwasnotawareofthestd::stringimplementation,itdidn’trecognizetheboss.Instead,itconstantlyretargetedsummonedDemoncreatures,effectivelykeepingyoufromtargetingthebosswhileheslowlydrainedyourhealthandsupplies.
DeterminingWhetherDataIsStoredinastd::stringWithoutknowinghowthestd::stringclassisstructured,you’dhavetroubletrackingdownbugslikethehypotheticaloneIjustdescribed.Butpairwhatyou’velearnedherewithexperience,andyoucanavoidthesekindsofbugsentirely.Whenyoufindastringlikenameinmemory,don’tjustassumeit’sstoredinasimplearray.Tofigureoutwhetherastringisinfactastd::string,askyourselfthesequestions:
•Whyisthestringlengthpresentforanull-terminatedstring?Ifyoucan’tthinkofagoodreason,thenyoumayhaveastd::stringonyourhands.
•Dosomecreatures(orothergameelements,dependingonwhatyou’relookingfor)havenameslongerthan16letters,butyoufindroomforonly16charactersinmemory?Ifso,thedataisalmostdefinitelystoredinastd::string.
•Isthenamestoredinplace,requiringthedevelopertousestrcpy()tomodifyit?It’sprobablyastd::string,becauseworkingwithrawCstringsinthiswayisconsideredbadpractice.
Finally,keepinmindthatthereisalsoaclasscalledstd::wstringthatisusedtostorewidestrings.Theimplementationisverysimilar,butwchar_tisusedinplaceofeverychar.
Thestd::vectorClassGamesmustkeeptrackofmanydynamicarraysofdata,butmanagingdynamicallysizedarrayscanbeverytricky.Forspeedandflexibility,gamedevelopersoftenstoresuchdatausingatemplatedSTLclasscalledstd::vectorinsteadofasimplearray.
ExaminingtheStructureofastd::vector
![Page 160: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/160.jpg)
AdeclarationofthisclasslookssomethinglikeListing5-4.
template<typenameT>classvector{T*begin;T*end;T*reservationEnd;};
Listing5-4:Anabstractedstd::vectorobject
Thistemplateaddsanextralayerofabstraction,soI’llcontinuethisdescriptionusingastd::vectordeclaredwiththeDWORDtype.Here’showagamemightdeclarethatvector:
std::vector<DWORD>_vec;
Now,let’sdissectwhatastd::vectorofDWORDobjectswouldlooklikeinmemory.Ifyouhadtheaddressof_vecandsharedthesamememoryspace,youcouldre-createtheunderlyingstructureoftheclassandaccess_vecasshowninListing5-5.
classvector{DWORD*begin;DWORD*end;DWORD*tail;};//pointtoavectorinmemoryvector*_vec=(vector*)vectorAddress;
Listing5-5:ADWORDstd::vectorobject
Youcantreatthememberbeginlikearawarray,asitpointstothefirstelementinthestd::vectorobject.Thereisnoarraylengthmember,though,soyoumustcalculatethevector’slengthbasedonbeginandend,whichisanemptyobjectfollowingthefinalobjectinthearray.Thelengthcalculationcodelookslikethis:
intlength(){return((DWORD)_vec->end-(DWORD)_vec->begin)/sizeof(DWORD);}
Thisfunctionsimplysubtractstheaddressstoredinbeginfromtheaddressstoredinendtofindthenumberofbytesbetweenthem.Then,to
![Page 161: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/161.jpg)
calculatethenumberofobjects,itdividesthenumberofbytesbythenumberofbytesperobject.
Usingbeginandthislength()function,youcansafelyaccesselementsin_vec.Thatcodewouldlooksomethinglikethis:
DWORDat(intindex){if(index>=_vec->length())thrownewstd::out_of_range();return_vec->begin[index];}
Givenanindex,thiscodewillfetchanitemfromthevector.Butiftheindexisgreaterthanthevector’slength,astd::out_of_rangeexceptionwillbethrown.Addingvaluestoastd::vectorwouldbeveryexpensiveiftheclasscouldn’treserveorreusememory,though.Toremedythis,theclassimplementsafunctioncalledreserve()thattellsthevectorhowmanyobjectstoleaveroomfor.
Theabsolutesizeofastd::vector(itscapacity)isdeterminedthroughanadditionalpointer,whichiscalledtailinthevectorclasswe’vere-created.Thecalculationforthecapacityresemblesthelengthcalculation:
intcapacity(){return((DWORD)_vec->tail-(DWORD)_vec->begin)/sizeof(DWORD);}
Tofindthecapacityofastd::vector,insteadofsubtractingthebeginaddressfromtheendaddress,asyouwouldtocalculatelength,thisfunctionsubtractsthebeginaddressfromtail.Additionally,youcanusethiscalculationathirdtimetodeterminethenumberoffreeelementsinthevectorbyusingtailandendinstead:
intfreeSpace(){return((DWORD)_vec->tail-(DWORD)_vec->end)/sizeof(DWORD);}
Givenpropermemoryreadingandwritingfunctions,youcanusethedeclarationinListing5-4andthecalculationsthatfollowtoaccessandmanipulatevectorsinthememoryofagame.Chapter6discussesreadingmemoryindetail,butfornow,let’slookatwaysyoucandeterminewhetherdatayou’reinterestedinisstoredinastd::vector.
![Page 162: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/162.jpg)
DeterminingWhetherDataIsStoredinastd::vectorOnceyou’vefoundanarrayofdatainagame’smemory,thereareafewstepsyoucanfollowtodeterminewhetheritisstoredinastd::vector.First,youcanbesurethatthearrayisnotstoredinastd::vectorifithasastaticaddress,becausestd::vectorobjectsrequirepointerpathstoaccesstheunderlyingarray.Ifthearraydoesrequireapointerpath,havingafinaloffsetof0wouldindicateastd::vector.Toconfirm,youcanchangethefinaloffsetto4andcheckifitpointstothefinalobjectinthearrayinsteadofthefirstone.Ifso,you’realmostdefinitelylookingatavector,asyou’vejustconfirmedthebeginandendpointers.
Thestd::listClassSimilartostd::vector,std::listisaclassthatyoucanusetostoreacollectionofitemsinalinkedlist.Themaindifferencesarethatstd::listdoesn’trequireacontiguousstoragespaceforelements,cannotdirectlyaccesselementsbytheirindex,andcangrowinsizewithoutaffectinganypreviouselements.Duetotheoverheadrequiredtoaccessitems,itisraretoseethisclassusedingames,butitshowsupinsomespecialcases,whichI’lldiscussinthissection.
ExaminingtheStructureofastd::listThestd::listclasslookssomethinglikeListing5-6.
template<typenameT>classlistItem{listItem<T>*next;listItem<T>*prev;Tvalue;};
template<typenameT>classlist{listItem<T>*root;intsize;};
Listing5-6:Anabstractedstd::listobject
Therearetwoclasseshere:listItemandlist.Toavoidextraabstractionwhileexplaininghowstd::listworks,I’lldescribethisobjectasitwould
![Page 163: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/163.jpg)
lookwhenthetypeisDWORD.Here’showagamewoulddeclareastd::listoftheDWORDtype:
std::list<DWORD>_lst;
Giventhatdeclaration,thestd::listisstructuredlikethecodeinListing5-7.
classlistItem{listItem*next;listItem*prev;DWORDvalue;};classlist{listItem*root;intsize;};//pointtoalistlist*_lst=(list*)listAddress;
Listing5-7:ADWORDstd::listobject
Theclasslistrepresentsthelistheader,whilelistItemrepresentsavaluestoredinthelist.Insteadofbeingstoredcontiguously,theitemsinthelistarestoredindependently.Eachitemcontainsapointertotheitemthatcomesafterit(next)andtheonethatcomesbeforeit(prev),andthesepointersareusedtolocateitemsinthelist.Therootitemactsasamarkerfortheendofthelist;thenextpointerofthelastitempointstoroot,asdoestheprevpointerofthefirstitem.Therootitem’snextandprevpointersalsopointtothefirstitemandthelastitem,respectively.Figure5-5showswhatthislookslike.
Giventhisstructure,youcanusethefollowingcodetoiterateoverastd::listobject:
![Page 164: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/164.jpg)
Figure5-5:Astd::listflowchart
//iterateforwardlistItem*it=_lst->root->next;for(;it!=_lst->root;it=it->next)printf("Valueis%d\n",it->value);
//iteratebackwardlistItem*it=_lst->root->prev;for(;it!=_lst->root;it=it->prev)printf("Valueis%d\n",it->value);
Thefirstloopstartsatthefirstitem(root->next)anditeratesforward(it=it->next)untilithitstheendmarker(root).Thesecondloopstartsatthelastitem(root->pres)anditeratesbackward(it=it->prev)untilithitstheendmarker(root).Thisiterationreliesonnextandprevbecauseunlikeobjectsinanarray,objectsinastd::listarenotcontiguous.Sincethememoryofeachobjectinastd::listisnotcontiguous,there’snoquick-and-dirtywaytocalculatethesize.Instead,theclassjustdefinesasizemember.Additionally,theconceptofreservingspacefornewobjectsisirrelevantforlists,sothere’snovariableorcalculationtodeterminealist’scapacity.
DeterminingWhetherGameDataIsStoredinastd::listIdentifyingobjectsstoredinthestd::listclasscanbetricky,butthereareafewhintsyoucanwatchfor.First,itemsinastd::listcannothavestaticaddresses,soifthedatayouseekhasastaticaddress,thenyou’reintheclear.Itemsthatareobviouslypartofacollectionmay,however,bepartofastd::listifthey’renotcontiguousinmemory.
Alsoconsiderthatobjectsinastd::listcanhaveinfinitelylongpointerchains(thinkit->prev->next->prev->next->prev...),andpointerscanningfortheminCheatEnginewillshowmanymoreresultswhenNoLoopingPointersisturnedoff.
Youcanalsouseascripttodetectwhenavalueisstoredinalinkedlist.Listing5-8showsaCheatEnginescriptthatdoesjustthis.
function_verifyLinkedList(address)localnextItem=readInteger(address)or0localpreviousItem=readInteger(address+4)or0localnextItemBack=readInteger(nextItem+4)localpreviousItemForward=readInteger(previousItem)
![Page 165: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/165.jpg)
return(address==nextItemBackandaddress==previousItemForward)end
functionisValueInLinkedList(valueAddress)foraddress=valueAddress-8,valueAddress-48,-4doif(_verifyLinkedList(address))thenreturnaddressendendreturn0end
localnode=isValueInLinkedList(addressOfSomeValue)if(node>0)thenprint(string.format("ValueinLL,topofnodeat0x0%x",node))end
Listing5-8:Determiningwhetherdataisinastd::listusingaCheatEngineLuascript
There’squiteabitofcodehere,butwhatit’sdoingisactuallyprettysimple.TheisValueInLinkedList()functiontakesanaddressofsomevalueandthenlooksbackwardforupto40bytes(10integerobjects,incasethevalueisinsomelargerstructure),starting8bytesabovetheaddress(twopointersmustbepresent,andtheyare4byteseach).Becauseofmemoryalignment,thisloopiteratesinstepsof4bytes.
Oneachiteration,theaddressispassedtothe_verifyLinkedList()function,whichiswherethemagichappens.Ifwelookatitintermsoflinkedliststructureasdefinedinthischapter,thefunctionsimplydoesthis:
return(node->next->prev==node&&node->prev->next==node)
Thatis,thefunctionbasicallyassumesthememoryaddressit’sgivenpointstoalinkedlist,anditmakessurethesupposednodehasvalidnextandpreviousnodes.Ifthenodesarevalid,theassumptionwascorrectandtheaddressisthatofalinkedlistnode.Ifthenodesdon’texistordon’tpointtotherightlocations,theassumptionwaswrongandtheaddressisnotpartofalinkedlist.
Keepinmindthatthisscriptwon’tgiveyoutheaddressofthelist’srootnodebutsimplytheaddressofthenodecontainingthevalueyou’vegivenit.Toproperlytraversealinkedlist,you’llneedtoscanforavalidpointerpathtotherootnode,soyou’llneeditsaddress.
![Page 166: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/166.jpg)
Findingthataddresscanrequiresomesearchingofmemorydumps,alotoftrialanderror,andatonofheadscratching,butit’sdefinitelypossible.Thebestwaytostartistofollowthechainofprevandnextnodesuntilyoufindanodewithdatathatiseitherblank,nonsensical,orfilledwiththevalue0xBAADF00D(some,butnotall,standardlibraryimplementationsusethisvaluetomarkrootnodes).
Thisinvestigationcanalsobemadeeasierifyouknowexactlyhowmanynodesareinthelist.Evenwithoutthelistheader,youcandeterminetheamountofnodesbycontinuouslyfollowingthenextpointeruntilyouendupbackatyourstartingnode,asinListing5-9.
functioncountLinkedListNodes(nodeAddress)localcounter=0localnext=readInteger(nodeAddress)while(next~=nodeAddress)docounter=counter+1next=readInteger(next)endreturncounterend
Listing5-9:Determiningthesizeofanarbitrarystd::listusingaCheatEngineLuascript
First,thisfunctioncreatesacountertostorethenumberofnodesandavariabletostorethenextnode’saddress.Thewhilelooptheniteratesoverthenodesuntilitendsupbackattheinitialnode.Finally,itreturnsthecountervariable,whichwasincrementedoneveryiterationoftheloop.
FINDTHEROOTNODEWITHASCRIPTIt’sactuallypossibletowriteascriptthatcanfindtherootnode,butI’llleaveitasanoptionalexerciseforyou.Howdoesitwork?Well,therootnodemustbeinthechainofnodes,thelistheaderpointstotheroot,andthesizeofthelistwillimmediatelyfollowtherootinmemory.Giventhisinformation,youcanwriteascriptthatwillsearchforanymemorycontainingapointertooneofthelist’snodes,followedbythesizeofthelist.Moreoftenthannot,thispieceofmemoryisthelistheader,andthenodeitpointstoistherootnode.
![Page 167: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/167.jpg)
Thestd::mapClassLikeastd::list,astd::mapuseslinksbetweenelementstoformitsstructure.Uniquetostd::map,however,isthefactthateachelementstorestwopiecesofdata(akeyandavalue),andsortingtheelementsisaninherentpropertyoftheunderlyingdatastructure:ared-blacktree.Thefollowingcodeshowsthestructuresthatcomposeastd::map.
template<typenamekeyT,typenamevalT>structmapItem{mapItem<keyT,valT>*left;mapItem<keyT,valT>*parent;mapItem<keyT,valT>*right;keyTkey;valTvalue;};
template<typenamekeyT,typenamevalT>structmap{DWORDirrelevant;mapItem<keyT,valT>*rootNode;intsize;}
Ared-blacktreeisaself-balancingbinarysearchtree,soastd::mapis,too.IntheSTL’sstd::mapimplementation,eachelement(ornode)inthetreehasthreepointers:left,parent,andright.Inadditiontothepointers,eachnodealsohasakeyandavalue.Thenodesarearrangedinthetreebasedonacomparisonbetweentheirkeys.Theleftpointerofanodepointstoanodewithasmallerkey,andtherightpointerpointstoanodewithalargerkey.Theparentpointstotheuppernode.ThefirstnodeinthetreeiscalledtherootNode,andnodesthatlackchildrenpointtoit.
Visualizingastd::mapFigure5-6showsastd::mapthathasthekeys1,6,8,11,13,15,17,22,25,and27.
![Page 168: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/168.jpg)
Figure5-6:Ared-blacktree
Thetopnode(holdingthevalue13)ispointedtobytheparentofrootNode.Everythingtotheleftofithasasmallerkey,andeverythingtotherighthasagreaterkey.Thisistrueforanynodeinthetree,andthistruthenablesefficientkey-basedsearch.Whilenotrepresentedintheimage,theleftpointeroftherootnodewillpointtotheleftmostnode(1),andtherightpointerwillpointtotherightmostnode(27).
AccessingDatainastd::mapOnceagain,I’lluseastaticstd::mapdefinitionwhendiscussinghowtoextractdatafromthestructure.Sincethetemplatetakestwotypes,I’llalsousesomepseudotypestokeepthingsobvious.Here’sthedeclarationforthestd::mapobjectI’llreferencefortherestofthesection:
typedefintkeyInt;typedefintvalInt;std::map<keyInt,valInt>myMap;
Withthisdeclaration,thestructureofmyMapbecomes:
![Page 169: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/169.jpg)
structmapItem{mapItem*left;mapItem*parent;mapItem*right;keyIntkey;valIntvalue;};structmap{DWORDirrelevant;mapItem*rootNode;intsize;}map*_map=(map*)mapAddress;
Therearesomeimportantalgorithmsthatyoumightneedtoaccessthedatainastd::mapstructureinagame.First,blindlyiteratingovereveryiteminthemapcanbeusefulifyoujustwanttoseeallofthedata.Todothissequentially,youcouldwriteaniterationfunctionlikethis:
voiditerateMap(mapItem*node){if(node==_map->rootNode)return;iterateMap(node->left);printNode(node);iterateMap(node->right);}
Afunctiontoiterateoveranentiremapwouldfirstreadthecurrentnodeandcheckwhetherit’stherootNode.Ifnot,itwouldrecurseleft,printthenode,andrecurseright.
Tocallthisfunction,you’dhavetopassapointertotherootNodeasfollows:
iterateMap(_map->rootNode->parent);
Thepurposeofastd::map,however,istostorekeyeddatainaquicklysearchableway.Whenyouneedtolocateanodegivenaspecifickey,mimickingtheinternalsearchalgorithmispreferabletoscanningtheentiretree.Thecodeforsearchingastd::maplookssomethinglikethis:
mapItem*findItem(keyIntkey,mapItem*node){if(node!=_map->rootNode){if(key==node->key)returnnode;elseif(key<node->key)returnfindItem(key,node->left);
![Page 170: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/170.jpg)
elsereturnfindItem(key,node->right);}elsereturnNULL;}
Startingatthetopofthetree,yousimplyrecurseleftifthecurrentkeyisgreaterthanthesearchkeyandrecurserightifitissmaller.Ifthekeysareequal,youreturnthecurrentnode.Ifyoureachthebottomofthetreeanddon’tfindthekey,youreturnNULLbecausethekeyisn’tstoredinthemap.
Here’sonewayyoumightusethisfindItem()function:
mapItem*ret=findItem(someKey,_map->rootNode->parent);if(ret)printNode(ret);
AslongasfindItem()doesn’treturnNULL,thiscodeshouldprintanodefrom_map.
DeterminingWhetherGameDataIsStoredinastd::mapTypically,Idon’tevenconsiderwhetherdatacouldbeinastd::mapuntilIknowthecollectionisnotanarray,astd::vector,orastd::list.Ifyouruleoutallthreeoptions,thenaswithastd::list,youcanlookatthethreeintegervaluesbeforethevalueandcheckiftheypointtomemorythatcouldpossiblybeothermapnodes.
Onceagain,thiscanbedonewithaLuascriptinCheatEngine.ThescriptissimilartotheoneIshowedforlists,loopingbackwardovermemorytoseeifavalidnodestructureisfoundbeforethevalue.Unlikethelistcode,though,thefunctionthatverifiesanodeismuchtrickier.TakealookatthecodeinListing5-10,andthenI’lldissectit.
function_verifyMap(address)localparentItem=readInteger(address+4)or0
localparentLeftItem=readInteger(parentItem+0)or0localparentRightItem=readInteger(parentItem+8)or0
➊localvalidParent=parentLeftItem==addressorparentRightItem==addressif(notvalidParent)thenreturnfalseend
localtries=0
![Page 171: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/171.jpg)
locallastChecked=parentItemlocalparentsParent=readInteger(parentItem+4)or0➋while(readInteger(parentsParent+4)~=lastCheckedandtries<200)dotries=tries+1lastChecked=parentsParentparentsParent=readInteger(parentsParent+4)or0end
returnreadInteger(parentsParent+4)==lastCheckedend
Listing5-10:Determiningwhetherdataisinastd::mapusingaCheatEngineLuascript
Givenaddress,thisfunctionchecksifaddressisinamapstructure.Itfirstchecksifthere’savalidparentnodeand,ifso,checkswhetherthatparentnodepointstoaddressoneitherside➊.Butthischeckisn’tenough.Ifthecheckpasses,thefunctionwillalsoclimbupthelineofparentnodesuntilitreachesanodethatistheparentofitsownparent➋,trying200timesbeforecallingitquits.Iftheclimbsucceedsinfindinganodethatisitsowngrandparent,thenaddressdefinitelypointstoamapnode.Thisworksbecause,asIoutlinedin“Visualizingastd::map”onpage114,atthetopofeverymapisarootnodewhoseparentpointstothefirstnodeinthetree,andthatnode’sparentpointsbacktotherootnode.
NOTE
Ibetyoudidn’texpecttorunintothegrandfatherparadoxfromtimetravelwhenreadingagame-hackingbook!
UsingthisfunctionandaslightlymodifiedbacktrackingloopfromListing5-8,youcanautomaticallydetectwhenavalueisinsideamap:
functionisValueInMap(valueAddress)foraddress=valueAddress-12,valueAddress-52,-4doif(_verifyMap(address))thenreturnaddressendendreturn0end
localnode=isValueInMap(addressOfSomeValue)if(node>0)then
![Page 172: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/172.jpg)
print(string.format("Valueinmap,topofnodeat0x0%x",node))end
Asidefromfunctionnames,theonlychangeinthiscodefromListing5-8isthatitstartslooping12bytesbeforethevalueinsteadof8,becauseamaphasthreepointersinsteadofthetwoinalist.Onegoodconsequenceofamap’sstructureisthatit’seasytoobtaintherootnode.Whenthe_verifyMapfunctionreturnstrue,theparentsParentvariablewillcontaintheaddressoftherootnode.Withsomesimplemodifications,youcouldreturnthistothemaincallandhaveeverythingyouneedtoreadthedatafromastd::mapinoneplace.
ClosingThoughtsMemoryforensicsisthemosttime-consumingpartofhackinggames,anditsobstaclescanappearinallshapesandsizes.Usingpurpose,patterns,andadeepunderstandingofcomplexdatastructures,however,youcanquicklyovercometheseobstacles.Ifyou’restillabitconfusedaboutwhat’sgoingon,makesuretodownloadandplaywiththeexamplecodeprovided,asitcontainsproofsofconceptforallofthealgorithmscoveredinthischapter.
InChapter6,we’llstartdivingintothecodeyouneedtoreadfromandwritetoagame’smemoryfromyourownprogramssoyoucantakethefirststepinputtingtoworkallofthisinformationaboutmemorystructures,addresses,anddata.
![Page 173: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/173.jpg)
6READINGFROMANDWRITINGTOGAME
MEMORY
EarlierchaptersdiscussedhowmemoryisstructuredaswellashowtoscanandmodifymemoryusingCheatEngineandOllyDbg.Workingwithmemorywillbeessentialwhenyoubegintowritebots,andyourcodewillneedtoknowhowtodoso.
Thischapterdigsintothecode-leveldetailsofmemorymanipulation.First,you’lllearnhowtousecodetolocateandobtainhandlestogameprocesses.Next,you’lllearnhowtousethosehandlestoreadfromandwritetomemorybothfromremoteprocessesandfrominjectedcode.Towrapup,you’lllearnbypassesforacertainmemoryprotectiontechnique,completewithasmallexampleofcodeinjection.You’llfindtheexamplecodeforthischapterintheGameHackingExamples/Chapter6_AccessingMemorydirectoryinthisbook’ssourcefiles.
NOTE
WhenItalkaboutAPIfunctionsinthischapter(andinlaterones),I’mreferringtotheWindowsAPIunlessotherwisespecified.IfIdon’tmentionaheaderfileforthelibrary,youcanassumeitisWindows.h.
![Page 174: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/174.jpg)
ObtainingtheGame’sProcessIdentifierToreadfromorwritetoagame’smemory,youneeditsprocessidentifier(PID),anumberthatuniquelyidentifiesanactiveprocess.Ifthegamehasavisiblewindow,youcanobtainthePIDoftheprocessthatcreatedthatwindowbycallingGetWindowThreadProcessId().Thisfunctiontakesthewindow’shandleasthefirstparameterandoutputsthePIDtothesecondparameter.Youcanfindthewindow’shandlebypassingitstitle(thetextonthetaskbar)asthesecondparametertoFindWindow(),asshowninListing6-1.
HWNDmyWindow=FindWindow(NULL,"Titleofthegamewindowhere");DWORDPID;GetWindowThreadProcessId(myWindow,&PID);
Listing6-1:Fetchingawindow’shandletoobtainaPID
Withthewindowhandlesecured,allyouhavetodoiscreateaplacetostorethePIDandcallGetWindowThreadProcessId(),asshowninthisexample.
Ifagameisn’twindowedorthewindownameisn’tpredictable,youcanfindthegame’sPIDbyenumeratingallprocessesandlookingforthenameofthegamebinary.Listing6-2doesthisusingtheAPIfunctionsCreateToolhelp32Snapshot(),Process32First(),andProcess32Next()fromtlhelp32.h.
#include<tlhelp32.h>
PROCESSENTRY32entry;entry.dwSize=sizeof(PROCESSENTRY32);HANDLEsnapshot=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,NULL);if(Process32First(snapshot,&entry)==TRUE){while(Process32Next(snapshot,&entry)==TRUE){wstringbinPath=entry.szExeFile;if(binPath.find(L"game.exe")!=wstring::npos){printf("gamepidis%d\n",entry.th32ProcessID);break;}}}CloseHandle(snapshot);
Listing6-2:Fetchingagame’sPIDwithoutthewindowname
![Page 175: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/175.jpg)
Listing6-2mightlookabitmorecomplexthanListing6-1,butunderneathallthatcode,thefunctionisactuallylikeacanonicalfor(iterator;comparator;increment)loop.TheCreateToolhelp32Snapshot()functionobtainsalistofprocessesnamedsnapshot,andentryisaniteratoroverthatlist.ThevaluereturnedbyProcess32First()initializestheiterator,whileProcess32Next()incrementsit.Finally,theBooleanreturnvalueofProcess32Next()isthecomparator.Thiscodejustiteratesoverasnapshotofeveryrunningprocess,looksforonewhosebinarypathcontainsthetextgame.exe,andprintsitsPID.
ObtainingProcessHandlesOnceyouknowagame’sPID,youcanobtainahandletotheprocessitselfusinganAPIfunctioncalledOpenProcess().Thisfunctionallowsyoutofetchhandleswiththeaccesslevelsyouneedtoreadfromandwritetomemory.Thisiscrucialtogamehacking,asanyfunctionthatoperatesonaprocesswillrequireahandlewithproperaccess.
Let’stakealookattheprototypeofOpenProcess():
HANDLEOpenProcess(DWORDDesiredAccess,BOOLInheritHandle,DWORDProcessId);
Thefirstparameter,DesiredAccess,expectsoneoramixtureofprocessaccessflagstosetonthehandlethatOpenProcess()returns.Therearemanyflagsyoucanuse,butthesearethemostcommoningamehacking:
PROCESS_VM_OPERATIONThereturnedhandlecanbeusedwithVirtualAllocEx(),VirtualFreeEx(),andVirtualProtectEx()toallocate,free,andprotectchunksofmemory,respectively.
PROCESS_VM_READThereturnedhandlecanbeusedwithReadProcessMemory().
PROCESS_VM_WRITEThereturnedhandlecanbeusedwithWriteProcessMemory(),butitmustalsohavePROCESS_VM_OPERATIONrights.YoucansetbothflagsbypassingPROCESS_VM_OPERATION|PROCESS_VM_WRITEastheDesiredAccessparameter.
PROCESS_CREATE_THREADThereturnedhandlecanbeusedwithCreateRemoteThread().
![Page 176: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/176.jpg)
PROCESS_ALL_ACCESSThereturnedhandlecanbeusedtodoanything.Avoidusingthisflag,asitcanonlybeusedbyprocesseswithdebugprivilegesenabledandhascompatibilityissueswitholderversionsofWindows.
Whenfetchingahandletoagame,youcantypicallyjustsettheOpenProcess()function’ssecondparameter,InheritHandle,tofalse.Thethirdparameter,ProcessId,expectsthePIDoftheprocesstobeopened.
WorkingwithOpenProcess()Nowlet’swalkthroughanexamplecalltoOpenProcess()thatusesahandlewithaccesspermissionsallowingittoreadfromandwritetomemory:
DWORDPID=getGamePID();HANDLEprocess=OpenProcess(PROCESS_VM_OPERATION|PROCESS_VM_READ|PROCESS_VM_WRITE,
FALSE,PID);➊if(process==INVALID_HANDLE_VALUE){printf("FailedtoopenPID%d,errorcode%d",PID,GetLastError());}
First,thecalltogetGamePID()fetchesthePIDyou’relookingfor.(Thefunctionissomethingyou’llhavetowriteyourself,thoughitcouldjustbeoneofthesnippetsIshowedinListings6-1and6-2,fleshedoutintoafullblownfunction.)Then,thecodecallsOpenProcess()withthreeflags:thePROCESS_VM_OPERATIONflaggivesthishandlememoryaccesspermissions,andtheothertwocombinedgiveitreadandwritepermissions.Thisexamplealsocontainsanerror-handlingcase➊,butaslongasyouhavethecorrectPID,youhavevalidaccessflags,andyourcodeisrunningunderthesameorhigherpermissionsasthegame(forexample,ifyoustartyourbotusingRunAsAdmin),thecallshouldneverfail.
Onceyou’redoneusingahandle,cleanitupusingCloseHandle()asfollows:
CloseHandle(process);
![Page 177: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/177.jpg)
CloseHandle(process);
Youcanreusehandlesasmuchasyouwant,soyoucanleaveoneopenuntilyou’recompletelydoneusingitoruntilyourbotisexited.
Nowthatyou’veseenhowtoopenaprocesshandleinpreparationformanipulatinggamememory,let’sdigintohowtoactuallyaccessthememoryofthatprocess.
AccessingMemoryTheWindowsAPIexposestwofunctionsthatarecrucialtomemoryaccess:ReadProcessMemory()andWriteProcessMemory().Youcanusethesefunctionstoexternallymanipulateagame’smemory.
WorkingwithReadProcessMemory()andWriteProcessMemory()Theprototypesforthesetwofunctions(showninListing6-3)resembleeachotherclosely,andyou’llfollowalmostexactlythesamestepstousethem.
BOOLReadProcessMemory(HANDLEProcess,LPVOIDAddress,LPVOIDBuffer,DWORDSize,DWORD*NumberOfBytesRead);BOOLWriteProcessMemory(HANDLEProcess,LPVOIDAddress,LPCVOIDBuffer,DWORDSize,
DWORD*NumberOfBytesWritten);
Listing6-3:ReadProcessMemory()andWriteProcessMemory()prototypes
BothfunctionsexpectProcesstobeaprocesshandleandAddresstobethetargetmemoryaddress.Whenthefunctionisreadingfrommemory,Bufferisexpectedtopointtoanobjectthatwillholdthereaddata.Whenthefunctioniswritingtomemory,Bufferisexpectedtopointtothedatatowrite.Inbothcases,SizedefinesthesizeofBuffer,inbytes.Thefinalparametertobothfunctionsisusedtooptionallyreturnthenumberofbytesthatwereaccessed;youcansafelysetittoNULL.Unlessthefunctionfails,the
![Page 178: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/178.jpg)
valuereturnedinthefinalparametershouldbeequaltoSize.
AccessingaValueinMemorywithReadProcessMemory()andWriteProcessMemory()ThecodeinListing6-4showshowyoumightusethesefunctionstoaccessavalueinmemory.
DWORDval;ReadProcessMemory(proc,adr,&val,sizeof(DWORD),0);printf("Currentmemvalueis%d\n",val);
val++;
WriteProcessMemory(proc,adr,&val,sizeof(DWORD),0);ReadProcessMemory(proc,adr,&val,sizeof(DWORD),0);printf("Newmemvalueisconfirmedas%d\n",val);
Listing6-4:ReadingfromandwritingtoprocessmemoryusingtheWindowsAPI
Beforecodelikethisappearsinaprogram,youneedtofindthePID(proc)asdescribedin“ObtainingtheGame’sProcessIdentifier”onpage120,aswellasthememoryaddress(adr)youwanttoreadfromorwriteto.Withthosevaluesinplace,theReadProcessMemory()functionstoresafetchedvaluefrommemoryinval.Then,thecodeincrementsvalandreplacestheoriginalvaluebycallingWriteProcessMemory().Afterthewritetakesplace,ReadProcessMemory()iscalledonthesameaddresstoconfirmthenewmemoryvalue.Noticethatvalisn’tactuallyabuffer.Passing&valastheBufferparameterworksbecauseitcanbeapointertoanystaticmemorystructure,aslongasSizematches.
WritingTemplatedMemoryAccessFunctionsOfcourse,theexampleinListing6-4assumesyoualreadyknowwhattypeofmemoryyou’redealingwith,andithardcodesthetypeasDWORD.Tobeaversatilegamehacker,it’sbettertohavesomegenericcodeinyourtoolboxtoavoidduplicatingcodefordifferenttypes.GenericmemoryreadingandwritingfunctionsthatsupportdifferenttypesmightlooklikeListing6-5.
template<typenameT>
![Page 179: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/179.jpg)
TreadMemory(HANDLEproc,LPVOIDadr){Tval;ReadProcessMemory(proc,adr,&val,sizeof(T),NULL);returnval;}
template<typenameT>voidwriteMemory(HANDLEproc,LPVOIDadr,Tval){WriteProcessMemory(proc,adr,&val,sizeof(T),NULL);}
Listing6-5:Genericmemoryfunctions
ThesefunctionsuseC++templatestoacceptarbitrarytypesasarguments.Theyallowyoutoaccessmemorywithwhatevertypesyoulikeinaverycleanway.Forexample,giventhesereadMemory()andwriteMemory()templatesIjustshowed,youcouldmakethecallsinListing6-6.
DWORDvalue=readMemory<DWORD>(proc,adr);//readwriteMemory<DWORD>(proc,adr,value++);//incrementandwrite
Listing6-6:Callingtemplatedmemoryaccessfunctions
ComparethistothecallstoWriteProcessMemory()andReadProcessMemory()inListing6-4.Thiscodestillreadsavalue,incrementsit,andwritesthenewvaluetomemory.Butsincethetemplatedfunctionsletyouspecifythetypewhenyoucallthem,youdon’tneedanewreadMemory()andwriteMemory()functionforeverydatatypeyoumightneedtoworkwith.That’smuchcleaner,sinceyou’lloftenwanttoworkwithallkindsofdata.
MemoryProtectionWhenmemoryisallocatedbyagame(oranyprogram),itisplacedinapage.Inx86Windows,pagesarechunksof4,096bytesthatstoredata.Becauseallmemorymustbewithinapage,theminimalallocationunitis4,096bytes.Theoperatingsystemcanplacememorychunkssmallerthan4,096bytesasasubsetofanexistingpagethathasenoughuncommittedspace,inanewlyallocatedpage,oracrosstwocontiguouspagesthathavethesameattributes.
Memorychunks4,096bytesorlargerspannpages,wherenis
![Page 180: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/180.jpg)
Theoperatingsystemtypicallylooksforroominexistingpageswhenallocatingmemory,butitallocatesnewpagesondemandifnecessary.
NOTE
It’salsopossibleforlargechunkstospann+1pages,asthere’snoguaranteethatachunkbeginsatthestartofapage.
Theimportantthingtounderstandaboutmemorypagesisthateachpagehasasetofspecificattributes.Mostoftheseattributesaretransparentinusermode,butthere’soneyoushouldbeextraconsciousofwhenworkingwithmemory:protection.
Differentiatingx86WindowsMemoryProtectionAttributesThememory-readingtechniquesyou’velearnedsofarareverybasic.Theyassumethatthememoryyou’reaccessingisprotectedwiththePAGE_READWRITEattribute.Whilethisassumptioniscorrectforvariabledata,othertypesofdataexistonpageswithdifferenttypesofprotection.Table6-1describesthedifferenttypesofmemoryprotectioninx86Windows.
Table6-1:MemoryProtectionTypes
Protectiontype Value Readpermission?
Writepermission?
Executepermission?
Specialpermissions?
PAGE_NOACCESS 0x01 No No No PAGE_READONLY 0x02 Yes No No PAGE_READWRITE 0x04 Yes No No PAGE_WRITECOPY 0x08 Yes Yes No Yes,copyon
writePAGE_EXECUTE 0x10 No No Yes PAGE_EXECUTE_READ 0x20 Yes No Yes
![Page 181: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/181.jpg)
PAGE_EXECUTE_READ 0x20 Yes No Yes PAGE_EXECUTE_READWRITE 0x40 Yes Yes Yes
PAGE_EXECUTE_WRITECOPY 0x80 Yes Yes Yes Yes,copyonwrite
PAGE_GUARD 0x100 No No No Yes,guardpage
IfaprotectiontypeinTable6-1hasaYesinanypermissioncolumn,itmeanstheactioninquestioncanbeperformedonthatpageofmemory.Forexample,ifapageisPAGE_READONLY,thenaprogramcanreadthememoryonthatpage,buttheprogramcannotwritetothatmemory.
Constantstrings,forexample,areusuallystoredwithPAGE_READONLYprotection.Otherconstantdata,suchasvirtualfunctiontablesandamodule’sentirePortableExecutable(PE)header(whichcontainsinformationaboutaprogram,suchasthekindofapplicationitis,libraryfunctionsituses,itssize,andsoon),arealsostoredonread-onlypages.Assemblycode,ontheotherhand,isstoredonpagesprotectedwithPAGE_EXECUTE_READ.
Mostprotectiontypesinvolveonlysomecombinationofread,write,andexecuteprotection.Fornow,youcansafelyignorespecialprotectiontypes;Icoverthemin“SpecialProtectionTypes”onpage126ifyou’recurious,butonlyveryadvancedhackswilleverrequireknowledgeofthem.Thebasicprotectiontypes,though,willbeprevalentinyourgame-hackingadventures.
SPECIALPROTECTIONTYPESTwoprotectiontypesinTable6-1includecopy-on-writeprotection.Whenmultipleprocesseshavepagesofmemorythatareidentical(suchaspageswithmappedsystemDLLs),copy-on-writeprotectionisusedtoconservememory.Theactualdataisstoredinonlyonephysicalplace,andtheoperatingsystemvirtuallymapsallmemorypagescontainingthatdatatothephysicallocation.Ifaprocesssharingthememorymakesachangetoit,acopyofthedatawillbemadeinphysicalmemory,thechangewillbeapplied,andthememorypage(s)forthatprocesswillberemappedtothenewphysical
![Page 182: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/182.jpg)
memory.Whenacopyonwritehappens,theprotectionforallaffectedpageschangesaccordingly;PAGE_WRITECOPYwillbecomePAGE_READWRITE,andPAGE_EXECUTE_WRITECOPYwillbecomePAGE_EXECUTE_READWRITE.I’vefoundnogamehacking–specificusesforcopy-on-writepages,butit’susefultounderstandthem.
Pagescanalsobecreatedwithguardprotection.Guardedpagesmusthaveasecondaryprotection,definedlikePAGE_GUARD|PAGE_READONLY.Whentheprogramtriestoaccessaguardedpage,theoperatingsystemwillthrowaSTATUS_GUARD_PAGE_VIOLATIONexception.Oncetheexceptionishandled,theguardprotectionisremovedfromthepage,leavingonlythesecondaryprotection.Onewayinwhichtheoperatingsystemusesthistypeofprotectionistodynamicallyexpandthecallstackbyplacingaguardedpageatthetopandallocatingmorememorywhenthatguardedpageishit.Somememoryanalysistoolsplaceguardedpagesafterheapmemorytodetectheapcorruptionbugs.Inthecontextofgamehacking,aguardedpagecanbeusedasatripwirethattellsyouwhenagamemightbeattemptingtodetectyourcodewithinitsmemory.
ChangingMemoryProtectionWhenyouwanttohackagame,you’llsometimesneedtoaccessmemoryinawaythatisforbiddenbythememorypage’sprotection,makingitimportanttobeabletochangememoryprotectionatwill.Luckily,theWindowsAPIprovidestheVirtualProtectEx()functionforthispurpose.Thisisthefunction’sprototype:
BOOLVirtualProtectEx(HANDLEProcess,LPVOIDAddress,DWORDSize,DWORDNewProtect,PDWORDOldProtect);
TheparametersProcess,Address,andSizetakethesameinputastheydointheReadProcessMemory()andWriteProcessMemory()functions.NewProtectshouldspecifythenewprotectionflagsforthememory,andOldProtectcanoptionallypointtoaDWORDwheretheoldprotectionflagswillbestored.
![Page 183: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/183.jpg)
Themostgranularscaleformemoryprotectionisperpage,whichmeansVirtualProtectEx()willsetthenewprotectiontoeverypagethatisonorbetweenAddressandAddress+Size-1.
NOTE
TheVirtualProtectEx()functionhasasistercalledVirtualProtect().Theyworkthesameway,butVirtualProtect()operatesonlyontheprocesscallingitand,thus,doesnothaveaprocesshandleparameter.
Whenyou’rewritingyourowncodetochangememoryprotections,Isuggestmakingitflexiblebycreatingatemplate.AgenericwrappedfunctionforVirtualProtectEx()shouldlooksomethinglikeListing6-7.
template<typenameT>DWORDprotectMemory(HANDLEproc,LPVOIDadr,DWORDprot){DWORDoldProt;VirtualProtectEx(proc,adr,sizeof(T),prot,&oldProt);returnoldProt;}
Listing6-7:Agenericfunctiontochangememoryprotection
Withthistemplateinplace,ifyouwantedto,say,writeaDWORDtoamemorypagewithoutwritepermission,youmightdosomethinglikethis:
protectMemory<DWORD>(process,address,PAGE_READWRITE)writeMemory<DWORD>(process,address,newValue)
First,thissetstheprotectiononthememorytochangetoPAGE_READWRITE.Withwritepermissiongranted,thedoorisopentocallwriteMemory()andchangethedataataddress.
Whenyou’rechangingmemoryprotection,it’sbestpracticetoletthechangepersistonlyaslongasneededandrestoretheoriginalprotectionassoonaspossible.Thisislessefficient,butitensuresthatagamedoesn’tdetectyourbot(forexample,bynoticingthatsomeofitsassemblycodepageshavebecomewritable).
Atypicalwriteoperationonread-onlymemoryshouldlooklikethis:
DWORDoldProt=protectMemory<DWORD>(process,address,PAGE_READWRITE);
![Page 184: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/184.jpg)
writeMemory<DWORD>(process,address,newValue);protectMemory<DWORD>(process,address,oldProt);
ThiscodecallstheprotectMemory()functionfromListing6-7tochangetheprotectiontoPAGE_READWRITE.ItthenwritesnewValuetothememorybeforechangingtheprotectionbacktooldProt,whichwassettothepage’soriginalprotectionbytheinitialcalltoprotectMemory().ThewriteMemory()functionusedhereisthesameonedefinedinListing6-5.
Afinalimportantpointisthatwhenyou’remanipulatingagame’smemory,it’sentirelypossiblethatthegamewillaccessthememoryatthesametimeasyou.Ifthenewprotectionthatyousetisnotcompatiblewiththeoriginalprotection,thegameprocesswillgetanACCESS_VIOLATIONexceptionandcrash.Forinstance,ifyouchangememoryprotectionfromPAGE_EXECUTEtoPAGE_READWRITE,thegamemighttrytoexecutethecodeonthepage(s)whenthememoryisnotmarkedasexecutable.Inthiscase,you’dwanttoinsteadsetthememoryprotectiontoPAGE_EXECUTE_READWRITEtoensurethatyoucanoperateonthememorywhilestillallowingthegametoexecuteit.
AddressSpaceLayoutRandomizationSofar,I’vedescribedmemoryaddressesasstaticintegersthatchangeonlyasthebinarychanges.ThismodeliscorrectonWindowsXPandearlier.OnlaterWindowssystems,however,memoryaddressesareonlystaticrelativetothebaseaddressofthegamebinary,becausethesesystemsenableafeaturecalledaddressspacelayoutrandomization(ASLR)forsupportedbinaries.WhenabinaryiscompiledwithASLRsupport(enabledbydefaultonMSVC++2010andmanyothercompilers),itsbaseaddresscanbedifferenteverytimeitisrun.Conversely,non-ASLRbinarieswillalwayshaveabaseaddressof0x400000.
NOTE
SinceASLRdoesn’tworkonXP,I’llcall0x400000theXP-base.
DisablingASLRtoSimplifyBotDevelopmentTokeepdevelopmentsimple,youcandisableASLRanduseaddresseswith
![Page 185: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/185.jpg)
Tokeepdevelopmentsimple,youcandisableASLRanduseaddresseswiththetransparentXP-base.Todoso,enterasinglecommandintheVisualStudioCommandPrompt:
>editbin/DYNAMICBASE:NO"C:\path\to\game.exe"
Tore-enableit,enter:
>editbin/DYNAMICBASE"C:\path\to\game.exe"
BypassingASLRinProductionDisablingASLRissuitableforbotdevelopment,butitisano-noforproduction;enduserscannotbeexpectedtoturnoffALSR.Instead,youcanwriteafunctiontodynamicallyrebaseaddressesatruntime.IfyouuseaddresseswiththeXP-base,thecodetodoarebasewouldlooklikethis:
DWORDrebase(DWORDaddress,DWORDnewBase){DWORDdiff=address-0x400000;returndiff+newBase;}
Whenyouknowthebaseaddressofthegame(newBase),thisfunctionallowsyoutoessentiallyignoreASLRbyrebasingaddress.
TofindnewBase,however,youneedtousetheGetModuleHandle()function.WhentheparametertoGetModuleHandle()isNULL,italwaysreturnsahandletothemainbinaryinaprocess.Thefunction’sreturnedtypeisHMODULE,butthevalueisactuallyjusttheaddresswherethebinaryismapped.Thisisthebaseaddress,soyoucandirectlycastittoaDWORDtogetnewBase.Sinceyou’relookingforthebaseaddressinanotherprocess,though,youneedawaytoexecutethefunctioninthecontextofthatprocess.
Todothis,callGetModuleHandle()usingtheCreateRemoteThread()APIfunction,whichcanbeusedtospawnthreadsandexecutecodeinaremoteprocess.IthastheprototypeshowninListing6-8.
HANDLECreateRemoteThread(HANDLEProcess,LPSECURITY_ATTRIBUTESThreadAttributes,DWORDStackSize,LPTHREAD_START_ROUTINEStartAddress,LPVOIDParam,
![Page 186: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/186.jpg)
DWORDCreationFlags,LPDWORDThreadId);
Listing6-8:Afunctionthatspawnsathread
ThespawnedthreadwillstartexecutiononStartAddress,treatingitasasingle-parameterfunctionwithParamasinputandsettingthevaluereturnedasthethreadexitcode.Thisisideal,asthethreadcanbestartedwithStartAddresspointingtotheaddressofGetModuleHandle()andParamsettoNULL.YoucanthenusetheAPIfunctionWaitForSingleObject()towaituntilthethreadisdoneexecutingandgetthereturnedbaseaddressusingtheAPIfunctionGetExitCodeThread().
Onceallofthesethingsaretiedtogether,thecodetogetnewBasefromanexternalbotshouldlooklikeListing6-9.
DWORDnewBase;
//gettheaddressofkernel32.dllHMODULEk32=GetModuleHandle("kernel32.dll");
//gettheaddressofGetModuleHandle()LPVOIDfuncAdr=GetProcAddress(k32,"GetModuleHandleA");if(!funcAdr)funcAdr=GetProcAddress(k32,"GetModuleHandleW");
//createthethreadHANDLEthread=CreateRemoteThread(process,NULL,NULL,(LPTHREAD_START_ROUTINE)funcAdr,NULL,NULL,NULL);
//letthethreadfinishWaitForSingleObject(thread,INFINITE);
//gettheexitcodeGetExitCodeThread(thread,&newBase);
//cleanupthethreadhandleCloseHandle(thread);
Listing6-9:FindingthebaseaddressofagamewithAPIfunctions
TheGetModuleHandle()functionispartofkernel32.dll,whichhasthesamebaseaddressineveryprocess,sofirstthiscodegetstheaddressforkernel32.dll.Sincethebaseaddressofkernel32.dllisthesameinevery
![Page 187: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/187.jpg)
process,theaddressofGetModuleHandle()willbethesameinthegameasitisintheexternalbot.Giventhebaseaddressofkernel32.dll,thiscodefindstheaddressofGetModuleHandle()easilywiththeAPIfunctionGetProcAddress().Fromthere,itcallstheCreateRemoteThread()functionfromListing6-8,letsthethreaddoitsjob,andfetchestheexitcodetoobtainnewBase.
ClosingThoughtsNowthatyou’veseenhowtomanipulatememoryfromyourowncode,I’llshowyouhowtoapplytheskillsfromPartsIandIItogames.Theseskillsareparamounttotheconceptsyou’llexploreinthecomingchapters,somakesureyouhaveafirmgrasponwhat’shappening.Ifyou’rehavingtrouble,playwiththeexamplecodeasyoureviewconcepts,asitprovidesasafesandboxfortestingandtweakinghowthemethodsinthisandearlierchaptersbehave.
ThewayListing6-9tricksthegameintoexecutingGetModuleHandle()isaformofcodeinjection.Butthat’sjustaglimpseintowhatinjectioncando.Ifyou’reexcitedtolearnmoreaboutit,diveintoChapter7,whichexploresthistopicindetail.
![Page 188: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/188.jpg)
PART3PROCESSPUPPETEERING
![Page 189: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/189.jpg)
7CODEINJECTION
Imaginebeingabletowalkintoagamecompany’soffice,sitdown,andstartaddingcodetotheirgameclient.Imaginethatyoucandothisforanygameyouwant,wheneveryouwant,andforanyfunctionalityyouwant.Almostanygameryoutalktowillhaveideasonhowtoimproveagame,but,asfarastheyknow,it’sjustapipedream.Butyouknowthatdreamsaremeanttobefulfilled,andnowthatyou’velearnedabitabouthowmemoryworks,you’rereadytostartthrowingtherulesoutthewindow.Usingcodeinjection,youcan,forallintentsandpurposes,becomeaspowerfulasanygame’sdevelopers.
Codeinjectionisameansofforcinganyprocesstoexecuteforeigncodewithinitsownmemoryspaceandexecutioncontext.Itouchedonthistopicpreviouslyin“BypassingASLRinProduction”onpage128,whereIshowedyouhowtoremotelysubvertASLRusingCreateRemoteThread(),butthatexampleonlyscratchedthesurface.Inthefirstpartofthischapter,you’lllearnhowtocreatecodecaves,injectnewthreads,andhijackthreadexecutiontoforcegamestoexecutesmallsnippetsofassemblycode.Inthesecondpart,you’lllearnhowtoinjectforeignbinariesdirectlyintogames,forcingthosegamestoexecuteentireprogramsthatyou’vecreated.
InjectingCodeCaveswithThreadInjection
![Page 190: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/190.jpg)
Thefirststeptoinjectingcodeintoanotherprocessiswritingposition-agnosticassemblycode,knownasshellcode,intheformofabytearray.Youcanwriteshellcodetoremoteprocessestoformcodecaves,whichactastheentrypointforanewthreadthatyouwantagametoexecute.Onceacodecaveiscreated,youcanexecuteitusingeitherthreadinjectionorthreadhijacking.I’llshowyouanexampleofthreadinjectioninthissection,andI’llillustratethreadhijackingin“HijackingaGame’sMainThreadtoExecuteCodeCaves”onpage138.
You’llfindexamplecodeforthischapterinthisbook’sresourcefilesinthedirectoryGameHackingExamples/Chapter7_CodeInjection.Openmain-codeInjection.cpptofollowalongasIexplainhowtobuildasimplifiedversionofthefunctioninjectCodeUsingThreadInjection()fromthatfile.
CreatinganAssemblyCodeCaveIn“BypassingASLRinProduction”onpage128,IusedthreadinjectiontocallthefunctionGetModuleHandle()bywayofCreateRemoteThread()andobtainaprocesshandle.Inthatcase,GetModuleHandle()actedasthecodecave;ithadthepropercodestructuretoactastheentrypointforanewthread.Threadinjectionisn’talwaysthateasy,though.
Forexample,sayyouwantyourexternalbottoremotelycallafunctionwithinagame,andthefunctionhasthisprototype:
DWORD__cdeclsomeFunction(inttimes,constchar*string);
Afewthingsmakeremotelycallingthisfunctiontricky.First,ithastwoparameters,meaningyouneedtocreateacodecavethatwillbothsetupthestackandproperlymakethecall.CreateRemoteThread()allowsyoutopassoneargumenttothecodecave,andyoucanaccessthatargumentrelativetoESP,buttheotheronewouldstillneedtobehardcodedintothecodecave.Hardcodingthefirstargument,times,iseasiest.Additionally,you’dneedtomakesurethatthecaveproperlycleansthestack.
NOTE
RecallthatwhenbypassingASLRinChapter6,IusedCreateRemoteThread()tostartnewthreadsbyexecutinganyarbitrarycodeatagivenaddressandpassingthatcodeasingleparameter.That’swhytheseexamplescanpassone
![Page 191: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/191.jpg)
parameterusingthestack.
Ultimately,thecodecavetoinjectthatcalltosomeFunctionintoarunninggameprocesswouldlooksomethinglikethispseudocode:
PUSHDWORDPTR:[ESP+0x4]//getsecondargfromstackPUSHtimesCALLsomeFunctionADDESP,0x8RETN
Thiscodecaveisalmostperfect,butitcouldbelesscomplex.TheCALLoperationexpectsoneoftwooperands:eitheraregisterwithanabsolutefunctionaddressoranimmediateintegerthatholdsanoffsettoafunction,relativetothereturnaddress.Thismeansyou’dhavetodoabunchofoffsetcalculations,whichcanbetedious.
Tokeepthecavepositionagnostic,modifyittousearegisterinstead,asinListing7-1.
PUSHDWORDPTR:[ESP+0x4]//getsecondargfromstackPUSHtimesMOVEAX,someFunctionCALLEAXADDESP,0x8RETN
Listing7-1:AcodecavetocallsomeFunction
SinceacallerknowsthatafunctionitcallswilloverwriteEAXwithitsreturnvalue,thecallershouldensurethatEAXdoesn’tholdanycriticaldata.Knowingthis,youcanuseEAXtoholdtheabsoluteaddressofsomeFunction.
TranslatingtheAssemblytoShellcodeBecausecodecavesneedtobewrittentoanotherprocess’smemory,theycannotbewrittendirectlyinassembly.Instead,you’llneedtowritethembytebybyte.There’snostandardwaytodeterminewhichbytesrepresentwhichassemblycode,butthereareafewhackyapproaches.MypersonalfavoriteistocompileanemptyC++applicationwiththeassemblycodeinafunctionanduseOllyDbgtoinspectthatfunction.Alternatively,youcouldopenOllyDbgonanyarbitraryprocessandscanthroughthedisassemblyuntilyoufindthebytesforalloftheoperationsyouneed.Thismethodis
![Page 192: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/192.jpg)
untilyoufindthebytesforalloftheoperationsyouneed.Thismethodisactuallyreallygood,asyourcodecavesshouldbewrittenassimplyaspossible,meaningalloftheoperationsshouldbeverycommon.Youcanalsofindchartsofassemblyopcodesonline,butIfindthatthey’reallprettyhardtoread;themethodsIjustdescribedareeasieroverall.
Whenyouknowwhatyourbytesshouldbe,youcanuseC++toeasilygeneratethepropershellcode.Listing7-2showsthefinishedshellcodeskeletonfortheassemblyinListing7-1.
BYTEcodeCave[20]={0xFF,0x74,0x24,0x04,//PUSHDWORDPTR:[ESP+0x4]0x68,0x00,0x00,0x00,0x00,//PUSH00xB8,0x00,0x00,0x00,0x00,//MOVEAX,0x00xFF,0xD0,//CALLEAX0x83,0xC4,0x08,//ADDESP,0x080xC3//RETN};
Listing7-2:Shellcodeskeleton
ThisexamplecreatesaBYTEarraycontainingtheneededbytesofshellcode.Butthetimesargumentneedstobedynamic,andit’simpossibletoknowtheaddressofsomeFunctionatcompiletime,whichiswhythisshellcodeiswrittenasaskeleton.Thetwogroupsoffoursequential0x00bytesareplaceholdersfortimesandtheaddressofsomeFunction,andyoucaninserttherealvaluesintoyourcodecaveatruntimebycallingmemcpy(),asinthesnippetinListing7-3.
memcpy(&codeCave[5],×,4);memcpy(&codeCave[10],&addressOfSomeFunc,4);
Listing7-3:InsertingtimesandthelocationofsomeFunctionintothecodecave
BothtimesandtheaddressofsomeFunctionare4byteseach(recallthattimesisanintandaddressesare32-bitvalues),andtheybelongatcodeCave[5-8]andcodeCave[10-13],respectively.Thetwocallstomemcpy()passthisinformationasparameterstofilltheblanksinthecodeCavearray.
WritingtheCodeCavetoMemoryWiththepropershellcodecreated,youcanplaceitinsidethetargetprocess
![Page 193: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/193.jpg)
usingVirtualAllocEx()andWriteProcessMemory().Listing7-4showsonewaytodothis.
intstringlen=strlen(string)+1;//+1toincludenullterminatorintcavelen=sizeof(codeCave);➊intfulllen=stringlen+cavelen;autoremoteString=//allocatethememorywithEXECUTErights➋VirtualAllocEx(process,0,fulllen,MEM_COMMIT,PAGE_EXECUTE);
autoremoteCave=//keepanoteofwherethecodecavewillgo➌(LPVOID)((DWORD)remoteString+stringlen);
//writethestringfirst➍WriteProcessMemory(process,remoteString,string,stringlen,NULL);
//writethecodecavenext➎WriteProcessMemory(process,remoteCave,codeCave,cavelen,NULL);
Listing7-4:Writingthefinalshellcodetoacodecavememory
First,thiscodedeterminesexactlyhowmanybytesofmemoryitwillneedtowritethestringargumentandthecodecaveintothegame’smemory,anditstoresthatvalueinfulllen➊.Then,itcallstheAPIfunctionVirtualAllocEx()toallocatefulllenbytesinsideofprocesswithPAGE_EXECUTEprotection(youcanalwaysuse0andMEM_COMMIT,respectively,forthesecondandfourthparameters),anditstorestheaddressofthememoryinremoteString➋.ItalsoincrementsremoteStringbystringlenbytesandstorestheresultinremoteCave➌,astheshellcodeshouldbewrittendirectlytothememoryfollowingthestringargument.Finally,itusesWriteProcessMemory()tofilltheallocatedbufferwithstring➍andtheassemblybytes➎storedincodeCave.
Table7-1showshowamemorydumpofthecodecavemightlook,assumingthatitisallocatedat0x030000,someFunctionisat0xDEADBEEF,timesissetto5,andstringispointingtotheinjected!text.
Table7-1:CodeCaveMemoryDump
Address Coderepresentation
Rawdata Datameaning
0x030000 remoteString[0-4]
0x690x6E0x6A0x650x63
injec
![Page 194: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/194.jpg)
4] 0x63
0x030005 remoteString[5-9] 0x740x650x640x0A0x00
ted!\0
0x03000A remoteCave[0-3] 0xFF0x740x240x04 PUSHDWORDPTR[ESP+0x4]
0x03000E remoteCave[4-8] 0x680x050x000x000x00
PUSH0x05
0x030013 remoteCave[9-13] 0xB80xEF0xBE0xAD0xDE
MOVEAX,0xDEADBEEF
0x030018 remoteCave[14-15] 0xFF0xD0 CALLEAX
0x03001A remoteCave[16-18]
0x830xC40x08 ADDESP,0x08
0x03001D remoteCave[19] 0xC3 RETN
TheAddresscolumnshowswhereeachpieceofthecaveislocatedinmemory;theCoderepresentationcolumntellsyouwhichindexesofremoteStringandremoteCavecorrespondtothebytesintheRawdatacolumn;andtheDatameaningcolumnshowswhatthebytesrepresent,inhuman-readableformat.Youcanseetheinjected!stringat0x030000,thevalueoftimesat0x03000E,andtheaddressofsomeFunctionat0x030014.
UsingThreadInjectiontoExecutetheCodeCaveWithacompletecodecavewrittentomemory,theonlythinglefttodoisexecuteit.Inthisexample,youcouldexecutethecaveusingthefollowingcode:
HANDLEthread=CreateRemoteThread(process,NULL,NULL,(LPTHREAD_START_ROUTINE)remoteCave,remoteString,NULL,NULL);
WaitForSingleObject(thread,INFINITE);CloseHandle(thread);VirtualFreeEx(process,remoteString,fulllen,MEM_RELEASE)
ThecallstoCreateRemoteThread(),WaitForSingleObject(),andCloseHandle()worktoinjectandexecutethecodecave,andVirtalFreeEx()
![Page 195: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/195.jpg)
coversthebot’stracksbyfreeingthememoryallocatedincodelikeListing7-4.Inthesimplestform,that’sallthereistoexecutingacodecaveinjectedintoagame.Inpractice,youshouldalsocheckreturnvaluesaftercallingVirtualAllocEx(),WriteProcessMemory(),andCreateRemoteThread()tomakesurethateverythingwassuccessful.
Forinstance,ifVirtualAllocEx()returns0x00000000,itmeansthatthememoryallocationfailed.Ifyoudon’thandlethefailure,WriteProcessMemory()willalsofailandCreateRemoteThread()willbeginexecutingwithanentrypointof0x00000000,ultimatelycrashingthegame.ThesameistrueforthereturnvaluesofWriteProcessMemory()andCreateRemoteThread().Typically,thesefunctionswillonlyfailwhentheprocesshandleisopenedwithouttherequiredaccessflags.
HijackingaGame’sMainThreadtoExecuteCodeCavesInsomecases,injectedcodecavesneedtobeinsyncwiththemainthreadofthegameprocess.Solvingthisproblemcanbeverytrickybecauseitmeansthatyoumustcontroltheexistingthreadsinanexternalprocess.
Youcouldsimplysuspendthemainthreaduntilthecodecavefinishesexecuting,whichmightwork,butthatwouldproveveryslow.Theoverheadrequiredtowaitforacodecaveandthenresumeathreadisprettyheavy.Afasteralternativeistoforcethethreadtoexecutethecodeforyou,aprocesscalledthreadhijacking.
NOTE
Openthemain-codeInjection.cppfileinthisbook’ssourcecodefilestofollowalongwithbuildingthisthread-hijackingexample,whichisasimplifiedversionofinjectCodeUsingThreadHijacking().
BuildingtheAssemblyCodeCaveAswiththreadinjection,thefirststeptothreadhijackingisknowingwhatyouwanttohappeninyourcodecave.Thistime,however,youdon’tknow
![Page 196: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/196.jpg)
whatthethreadwillbeexecutingwhenyouhijackit,soyou’llneedtomakesuretosavethethread’sstatewhenthecodecavestartsandrestorethestatewhenyou’redonehijackingit.Thismeansyourshellcodeneedstobewrappedinsomeassembly,asinListing7-5.
PUSHAD//pushgeneralregisterstothestackPUSHFD//pushEFLAGStothestack
//shellcodeshouldbehere
POPFD//popEFLAGSfromthestackPOPAD//popgeneralregisterstothestack
//resumethethreadwithoutusingregistershere
Listing7-5:Aframeworkforthethread-hijackingcodecave
IfyouweretocallthesamesomeFunctionthatyoudidwiththreadinjection,youcoulduseshellcodesimilartothatinListing7-2.Theonlydifferenceisthatyoucouldn’tpassthesecondparametertoyourbotusingthestackbecauseyouwouldn’tbeusingCreateRemoteThread().Butthat’snoproblem;youcouldjustpushitthesamewayyou’dpushthefirstparameter.ThepartofthecodecavethatexecutesthefunctionyouwanttocallwouldneedtolooklikeListing7-6.
PUSHstringPUSHtimesMOVEAX,someFunctionCALLEAXADDESP,0x8
Listing7-6:AssemblyskeletonforcallingsomeFunction
Allthat’schangedherefromListing7-1isthatthisexamplepushesstringexplicitlyandthere’snoRETN.Youdon’tcallRETNinthiscasebecauseyouwantthegamethreadtogobacktowhateveritwasdoingbeforeyouhijackedit.
Toresumetheexecutionofthethreadnormally,thecaveneedstojumpbacktothethread’soriginalEIPwithoutusingregisters.Fortunately,youcanusetheGetThreadContext()functiontofetchEIP,fillingtheshellcodeskeletoninC++.Thenyoucanpushittothestackinsideyourcodecaveanddoareturn.Listing7-7showshowyourcodecavewouldneedtoend.
PUSHoriginalEIP
![Page 197: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/197.jpg)
PUSHoriginalEIPRETN
Listing7-7:JumpingtoEIPindirectly
Areturnjumpstothevalueonthetopofthestack,sodoingthisimmediatelyafterpushingEIPwilldothetrick.Youshouldusethismethodinsteadofajump,becausejumpsrequireoffsetcalculationandmaketheshellcodeabitmorecomplextogenerate.IfyoutieListings7-5through7-7together,youcomeupwiththefollowingcodecave:
//savestatePUSHAD//pushgeneralregisterstothestackPUSHFD//pushEFLAGStothestack
//doworkwithshellcodePUSHstringPUSHtimesMOVEAX,someFunctionCALLEAXADDESP,0x8
//restorestatePOPFD//popEFLAGSfromthestackPOPAD//popgeneralregisterstothestack
//un-hijack:resumethethreadwithoutusingregistersPUSHoriginalEIPRETN
Next,followtheinstructionsin“TranslatingtheAssemblytoShellcode”onpage135andplugthosebytesintoanarrayrepresentingyourcodecave.
GeneratingSkeletonShellcodeandAllocatingMemoryUsingthesamemethodshowninListing7-2,youcouldgeneratetheshellcodeforthiscave,asshowninListing7-8.
BYTEcodeCave[31]={0x60,//PUSHAD0x9C,//PUSHFD0x68,0x00,0x00,0x00,0x00,//PUSH00x68,0x00,0x00,0x00,0x00,//PUSH00xB8,0x00,0x00,0x00,0x00,//MOVEAX,0x00xFF,0xD0,//CALLEAX0x83,0xC4,0x08,//ADDESP,0x080x9D,//POPFD
![Page 198: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/198.jpg)
0x61,//POPAD0x68,0x00,0x00,0x00,0x00,//PUSH00xC3//RETN};
//we'llneedtoaddsomecodeheretoplace//thethread'sEIPintothreadContext.Eip
memcpy(&codeCave[3],&remoteString,4);memcpy(&codeCave[8],×,4);memcpy(&codeCave[13],&func,4);memcpy(&codeCave[25],&threadContext.Eip,4);
Listing7-8:Creatingthethread-hijackingshellcodearray
AsinListing7-3,memcpy()isusedtoputthevariablesintotheskeleton.Unlikeinthatlisting,though,therearetwovariablesthatcannotbecopiedrightaway;timesandfuncareknownimmediately,butremoteStringisaresultofallocationandthreadContext.Eipwillbeknownonlyoncethethreadisfrozen.Italsomakessensetoallocatememorybeforefreezingthethread,becauseyoudon’twantthethreadtobefrozenanylongerthanithastobe.Here’showthismightlook:
intstringlen=strlen(string)+1;intcavelen=sizeof(codeCave);intfulllen=stringlen+cavelen;
autoremoteString=VirtualAllocEx(process,0,fulllen,MEM_COMMIT,PAGE_EXECUTE);autoremoteCave=(LPVOID)((DWORD)remoteString+stringlen);
Theallocationcodeisthesameasitwasforthreadinjection,soyoucanreusethesamesnippet.
FindingandFreezingtheMainThreadThecodetofreezethemainthreadisabittrickier.First,yougetthethread’suniqueidentifier.ThisworksmuchlikegettingaPID,andyoucandoitusingCreateToolhelp32Snapshot(),Thread32First(),andThread32Next()fromTlHelp32.h.Asdiscussedin“ObtainingtheGame’sProcessIdentifier”onpage120,thesefunctionsareusedtoessentiallyiterateoveralist.Aprocesscanhavemanythreads,butthefollowingexampleassumesthatthefirstthreadthegameprocesscreatedistheonethatneedstobehijacked:
![Page 199: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/199.jpg)
DWORDGetProcessThreadID(HANDLEProcess){THREADENTRY32entry;entry.dwSize=sizeof(THREADENTRY32);HANDLEsnapshot=CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD,0);
if(Thread32First(snapshot,&entry)==TRUE){DWORDPID=GetProcessId(Process);while(Thread32Next(snapshot,&entry)==TRUE){if(entry.th32OwnerProcessID==PID){CloseHandle(snapshot);returnentry.th32ThreadID;}}}CloseHandle(snapshot);returnNULL;}
Thiscodesimplyiteratesoverthelistofallthreadsonthesystemandfindsthefirstonethatmatchesthegame’sPID.Thenitgetsthethreadidentifierfromthesnapshotentry.Onceyouknowthethreadidentifier,fetchthethread’scurrentregisterstatelikethis:
HANDLEthread=OpenThread((THREAD_GET_CONTEXT|THREAD_SUSPEND_RESUME|THREAD_SET_CONTEXT),false,threadID);SuspendThread(thread);
CONTEXTthreadContext;threadContext.ContextFlags=CONTEXT_CONTROL;GetThreadContext(thread,&threadContext);
ThiscodeusesOpenThread()togetathreadhandle.ItthensuspendsthethreadusingSuspendThread()andobtainsthevaluesofitsregistersusingGetThreadContext().Afterthis,thememcpy()codeinListing7-8shouldhaveallofthevariablesitneedstofinishgeneratingtheshellcode.
Withtheshellcodegenerated,thecodecavecanbewrittentotheallocatedmemoryinthesamefashionasinListing7-4:
WriteProcessMemory(process,remoteString,string,stringlen,NULL);WriteProcessMemory(process,remoteCave,codeCave,cavelen,NULL);
Oncethecaveisreadyandwaitinginmemory,allyouneedtodoissetthethread’sEIPtotheaddressofthecodecaveandletthethreadresumeexecution,asfollows:
![Page 200: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/200.jpg)
threadContext.Eip=(DWORD)remoteCave;threadContext.ContextFlags=CONTEXT_CONTROL;SetThreadContext(thread,&threadContext);ResumeThread(thread);
Thiscodecausesthethreadtoresumeexecutionattheaddressofthecodecave.Becauseofthewaythecodecaveiswritten,thethreadhasnocluethatanythinghaschanged.Thecavestoresthethread’soriginalstate,executesthepayload,restoresthethread’soriginalstate,andthenreturnstotheoriginalcodewitheverythingintact.
Whenyou’reusinganyformofcodeinjection,itisalsoimportanttounderstandwhatdatayourcodecavestouch.Forexample,ifyouweretocreateacodecavethatcallsagame’sinternalfunctionstocreateandsendanetworkpacket,you’dneedtomakesurethatanyglobalvariablesthatthefunctionstouch(likeapacketbuffer,packetpositionmarker,andsoon)aresafelyrestoredonceyou’redone.Youneverknowwhatthegameisdoingwhenyourcodecaveisexecuted—itcouldbecallingthesamefunctionasyou!
InjectingDLLsforFullControlCodecavesareverypowerful(youcanmakeagamedoanythingusingassemblyshellcode),buthandcraftingshellcodeisn’tpractical.ItwouldbemuchmoreconvenienttoinjectC++code,wouldn’tit?That’spossible,buttheprocessisfarmorecomplex:thecodemustbecompiledtoassembly,packagedinaposition-agnosticformat,madeawareofanyexternaldependencies,entirelymappedintomemory,andthenexecutedonsomeentrypoint.
Luckily,allofthesethingsarealreadytakencareofinWindows.BychangingaC++projecttocompileasadynamiclibrary,youcancreateaself-contained,position-agnosticbinarycalledadynamiclinklibrary(DLL).ThenyoucanuseamixofthreadinjectionorhijackingandtheLoadLibrary()APIfunctiontomapyourDLLfileintoagame’smemory.
Openmain-codeInjection.cppintheGameHackingExamples/Chapter7_CodeInjectiondirectoryanddllmain.cppunderGameHackingExamples/Chapter7_CodeInjection_DLLtofollowalongwithsomeexamplecodeasyoureadthissection.Inmain-codeInjection.cpp,lookat
![Page 201: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/201.jpg)
theLoadDLL()functionspecifically.
TrickingaProcessintoLoadingYourDLLUsingacodecave,youcantrickaremoteprocessintoinvokingLoadLibrary()onaDLL,effectivelyloadingforeigncodeintoitsmemoryspace.BecauseLoadLibrary()takesonlyasingleparameter,youcouldcreateacodecavetocallitasfollows:
//writethedllnametomemorywchar_t*dllName="c:\\something.dll";intnamelen=wcslen(dllName)+1;LPVOIDremoteString=VirtualAllocEx(process,NULL,namelen*2,MEM_COMMIT,PAGE_EXECUTE);WriteProcessMemory(process,remoteString,dllName,namelen*2,NULL);
//gettheaddressofLoadLibraryW()HMODULEk32=GetModuleHandleA("kernel32.dll");LPVOIDfuncAdr=GetProcAddress(k32,"LoadLibraryW");
//createathreadtocallLoadLibraryW(dllName)HANDLEthread=CreateRemoteThread(process,NULL,NULL,(LPTHREAD_START_ROUTINE)funcAdr,remoteString,NULL,NULL);
//letthethreadfinishandcleanupWaitForSingleObject(thread,INFINITE);CloseHandle(thread);
Thiscodeissomewhatamixofthethreadinjectioncodefrom“BypassingASLRinProduction”onpage128andthecodecavecreatedtocallsomeFunctioninListings7-2and7-3.Liketheformer,thisexampleusesthebodyofasingle-parameterAPIfunction,namelyLoadLibrary,asthebodyofthecodecave.Likethelatter,though,ithastoinjectastringintomemory,sinceLoadLibraryexpectsastringpointerasitsfirstargument.Oncethethreadisinjected,itforcesLoadLibrarytoloadtheDLLwhosenamewasinjectedintomemory,effectivelyputtingforeigncodeintoagame.
NOTE
GiveanyDLLyouplantoinjectauniquename,like
![Page 202: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/202.jpg)
MySuperBotV2Hook.dll.Simplernames,suchasHook.dllorInjected.dll,aredangerouslygeneric.IfthenameconflictswithaDLLthatisalreadyloaded,LoadLibrary()willassumethatitisthesameDLLandnotloadit!
OncetheLoadLibrary()codecaveloadsyourDLLintoagame,theDLL’sentrypoint—knownasDllMain()—willbeexecutedwithDLL_PROCESS_ATTACHasthereason.WhentheprocessiskilledorFreeLibrary()iscalledontheDLL,itsentrypointwillbecalledwiththeDLL_PROCESS_DETACHreason.Handlingtheseeventsfromtheentrypointmightlooklikethis:
BOOLAPIENTRYDllMain(HMODULEhModule,DWORDul_reason_for_call,LPVOIDlpReserved){switch(ul_reason_for_call){caseDLL_PROCESS_ATTACH:printf("DLLattached!\n");break;caseDLL_PROCESS_DETACH:printf("DLLdetached!\n");break;}returnTRUE;}
ThisexamplefunctionstartsbycheckingwhyDllMain()wascalled.ItthenoutputstextindicatingwhetheritwascalledbecausetheDLLwasattachedordetached,returningTRUEeitherway.
KeepinmindthattheentrypointofaDLLisexecutedinsidealoaderlock,whichisaglobalsynchronizationlockusedbyallfunctionsthatreadormodifythelistofmodulesloadedinaprocess.ThisloaderlockgetsusedbyfunctionslikeGetModuleHandle(),GetModuleFileName(),Module32First(),andModule32Next(),whichmeansthatrunningnontrivialcodefromaDLLentrypointcanleadtodeadlocksandshouldbeavoided.
IfyouneedtoruncodefromaDLLentrypoint,dosofromanewthread,asfollows:
DWORDWINAPIrunBot(LPVOIDlpParam){//runyourbotreturn1;}
![Page 203: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/203.jpg)
//dothisfromDllMain()forcaseDLL_PROCESS_ATTACHautothread=CreateThread(NULL,0,&runBot,NULL,0,NULL);CloseHandle(thread);
FromDllMain(),thiscodecreatesanewthreadstartingonthefunctionrunBot().Itthenimmediatelyclosesitshandletothethread,asdoinganyfurtheroperationsfromDllMain()canleadtoseriousproblems.FrominsidethisrunBot(),youcanbeginexecutingyourbot’scode.Thecoderunsinsidethegame,meaningyoucandirectlymanipulatememoryusingthetype-castingmethods.Youcanalsodoalotmore,asyou’llseeinChapter8.
WheninjectingDLLs,makesureyouhavenodependencyissues.IfyourDLLreliesonsomenonstandardDLLs,forexample,youhavetoeitherinjectthoseDLLsintothegamefirstorputtheminafolderthatLoadLibrary()willsearch,suchasanyfolderinthePATHenvironmentvariable.TheformerwillworkonlyiftheDLLshavenodependenciesoftheirown,whereasthelatterisabittrickytoimplementandsubjecttonamecollisions.ThebestoptionistolinkallexternallibrariesstaticallysothattheyarecompileddirectlyintoyourDLL.
AccessingMemoryinanInjectedDLLWhenyou’retryingtoaccessagame’smemoryfromaninjectedDLL,processhandlesandAPIfunctionsareahindrance.Becauseagamesharesthesamememoryspaceasallcodeinjectedintoit,youcanaccessagame’smemorydirectlyfrominjectedcode.Forexample,toaccessaDWORDvaluefrominjectedcode,youcouldwritethefollowing:
DWORDvalue=*((DWORD*)adr);//readaDWORDfromadr*((DWORD*)adr)=1234;//write1234toDWORDadr
ThissimplytypecaststhememoryaddressadrtoaDWORD*anddereferencesthatpointertoaDWORD.Doingtypecastsinplacelikethatisfine,butyourmemoryaccesscodewilllookcleanerifthefunctionsareabstractedandmadegeneric,justliketheWindowsAPIwrappers.
Thegenericfunctionsforaccessingmemoryfrominsideinjectedcodelooksomethinglikethis:
template<typenameT>TreadMemory(LPVOIDadr){return*((T*)adr);
![Page 204: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/204.jpg)
}
template<typenameT>voidwriteMemory(LPVOIDadr,Tval){*((T*)adr)=val;}
Usingthesetemplatesisjustlikeusingthefunctionsunder“WritingTemplatedMemoryAccessFunctions”onpage123.Here’sanexample:
DWORDvalue=readMemory<DWORD>(adr);//readwriteMemory<DWORD>(adr,value++);//incrementandwrite
ThesecallsarenearlyidenticaltothecallsinListing6-6onpage124;theyjustdon’tneedtotaketheprocesshandleasanargumentbecausethey’rebeingcalledfrominsidetheprocessitself.YoucanmakethismethodevenmoreflexiblebycreatingathirdtemplatedfunctioncalledpointMemory(),asfollows:
template<typenameT>T*pointMemory(LPVOIDadr){return((T*)adr);}
Thisfunctionskipsthedereferencingstepofamemoryreadandsimplygivesyouthepointertothedata.Fromthere,you’refreetobothreadfromandwritetothememorybydereferencingthatpointeryourself,likethis:
DWORD*pValue=pointMemory<DWORD>(adr);//pointDWORDvalue=*pValue;//'read'(*pValue)++;//incrementand'write'
WithafunctionlikepointMemory()inplace,youcouldeliminatethecallstoreadMemory()andwriteMemory().You’dstillneedtofindadraheadoftime,butfromthere,thecodetoreadavalue,changeit,andwriteitbackwouldbemuchsimplertofollow.
BypassingASLRinanInjectedDLLSimilarly,sincethecodeisinjected,there’snoneedtoinjectathreadintothegametogetthebaseaddress.Instead,youcanjustcallGetModuleHandle()directly,likeso:
DWORDnewBase=(DWORD)GetModuleHandle(NULL);
![Page 205: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/205.jpg)
DWORDnewBase=(DWORD)GetModuleHandle(NULL);
Afasterwaytogetthebaseaddressistoutilizethegame’sFSmemorysegment,whichisanothersuperpoweryougetfrominjectedcode.Thismemorysegmentpointstoastructurecalledthethreadenvironmentblock(TEB),and0x30bytesintotheTEBisapointertotheprocessenvironmentblock(PEB)structure.Thesestructuresareusedbytheoperatingsystemandcontainatonofdataaboutthecurrentthreadandthecurrentprocess,butwe’reinterestedonlyinthebaseaddressofthemainmodule,whichisstored0x8bytesintothePEB.Usinginlineassembly,youcantraversethesestructurestogetnewBase,likethis:
DWORDnewBase;__asm{MOVEAX,DWORDPTRFS:[0x30]MOVEAX,DWORDPTRDS:[EAX+0x8]MOVnewBase,EAX}
ThefirstcommandstoresthePEBaddressinEAX,andthesecondcommandreadsthemainmodule’sbaseaddressandstoresitinEAX.ThefinalcommandthencopiesEAXtonewBase.
ClosingThoughtsInChapter6,IshowedyouhowtoreadfrommemoryremotelyandhowaninjectedDLLcandirectlyaccessagame’smemoryusingpointers.Thischapterdemonstratedhowtoinjectalltypesofcode,frompureassemblybytecodetoentireC++binaries.Inthenextchapter,you’lllearnjusthowmuchpowerbeinginagame’smemoryspaceactuallygivesyou.Ifyouthoughtassemblycodeinjectionwascool,you’lllovewhatyoucandowhenyoumixinjectedC++withcontrolflowmanipulation.
Theexamplecodeforthischaptercontainsproofsofconceptforeverythingwe’vediscussed.Ifyou’restillunclearaboutanyofthetopics,youcanpokeatthecodetolearnexactlywhat’sgoingonandseeallofthetricksinaction.
![Page 206: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/206.jpg)
8MANIPULATINGCONTROLFLOWINA
GAME
Forcingagametoexecuteforeigncodeisdefinitelypowerful,butwhatifyoucouldalterthewayagameexecutesitsowncode?Whatifyoucouldforcethegametobypassthecodethatdrawsthefogofwar,trickitintomakingenemiesvisiblethroughwalls,ormanipulatetheargumentsitpassestofunctions?Controlflowmanipulationletsyoudoexactlythat,allowingyoutochangewhataprocessdoesbyinterceptingcodeexecutionandmonitoring,modifying,orpreventingit.
Therearemanywaystomanipulatethecontrolflowofaprocess,butalmostallrequireyoutomodifytheprocess’sassemblycode.Dependingonyourgoals,you’llneedtoeithercompletelyremovecodefromtheprocess(calledNOPing)orforcetheprocesstoredirectexecutiontoinjectedfunctions(calledhooking).Inthebeginningofthischapter,you’lllearnaboutNOPing,severaltypesofhooking,andothercontrolflowmanipulationtechniques.OnceI’veexplainedthebasics,I’llshowyouhowI’veappliedtheseprinciplestocommongamelibrarieslikeAdobeAIRandDirect3D.
OpenthedirectoryGameHackingExamples/Chapter8_ControlFlowinthisbook’sresourcefilestoseethecompletesamplecodeforthenextsectionand“HookingtoRedirectGameExecution”onpage153.
![Page 207: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/207.jpg)
NOPingtoRemoveUnwantedCodeChapter7describedhowtoinjectnewcodeintoagame,buttheopposite—removingcodefromagame—canalsobeuseful.Somehacksrequireyoutostopsomeofagame’soriginalcodefrombeingexecuted,andtodothat,you’llhavetogetridofit.OnewaytoeliminatecodefromagameprocessisNOPing,whichinvolvesoverwritingtheoriginalx86assemblycodewithNOPinstructions.
WhentoNOPConsideragamethatwon’tshowthehealthbarsofcloakedenemies.It’sprettyhardtoseecloakedenemiescoming,andyou’dhaveahugeadvantageincombatifyoucouldatleastseetheirhealthbars.ThecodetodrawhealthbarsoftenlookslikeListing8-1.
for(inti=0;i<creatures.size();i++){autoc=creatures[i];if(c.isEnemy&&c.isCloaked)continue;drawHealthBar(c.healthBar);}
Listing8-1:TheloopfromthedrawCreatureHealthBarExample()function
Whendrawinghealthbars,agamewithcloakedcreaturesmightuseaforlooptocheckwhetherthecreatureswithinthescreen’sboundsarecloaked.Ifanenemyisn’tcloaked,theloopcallssomefunction(drawHealthBar()inthisexample)todisplaytheenemy’shealthbar.
Giventhesourcecode,youcouldforcethegametodrawevencloakedenemies’healthbarsbysimplyremovingif(c.isEnemy&&c.isCloaked)continue;fromthecode.Butasagamehacker,youhaveonlytheassemblycode,notthesourcecode.Whensimplified,theassemblythatListing8-1translatesintolookssomethinglikethispseudocode:
startOfLoop:;forMOVi,0;inti=0JMPcondition;firstloop,skipincrementincrement:ADDi,1;i++condition:CMPi,creatures.Size();i<creatures.size()JNBendOfLoop;exitloopifi>=
![Page 208: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/208.jpg)
creatures.size()body:MOVc,creatures[i];autoc=creatures[i]TESTc.isEnemy,c.isEnemy;ifc.isEnemyJZdrawHealthBar;drawbarifc.isEnemy==falseTESTc.isCloaked,c.isCloaked;&&c.isCloakedJZdrawHealthBar;drawbarifc.isCloaked==false➊JMPincrement;continuedrawHealthBar:CALLdrawHealthBar(c.healthBar);drawHealthBar(c.healthBar)JMPincrement;continueendOfLoop:
Totrickthegameintodrawingallenemyhealthbars,regardlessofcloaking,you’dneedtoremovetheJMPincrementcommand➊thatexecuteswhenc.isEnemy&&c.isCloakedevaluatestotrue.Inassembly,though,replacingunwantedcodewithinstructionsthatdonothingiseasierthandeletingcode.That’swheretheNOPcommandcomesin.SinceNOPisasinglebyte(0x90),youcanoverwritethe2-byteJMPincrementcommandwithtwoNOPcommands.WhentheprocessorreachesthoseNOPcommands,itrollsoverthemandfallsintodrawHealthBar()evenwhenc.isEnemy&&c.isCloakedevaluatestotrue.
HowtoNOPThefirststeptoNOPingachunkofassemblycodeismakingthememorychunkwherethecodeliveswritable.It’spossibleforthecodeonthesamememorypagetobeexecutedwhileyou’rewritingtheNOPcommands,though,soyoualsowanttomakesurethememoryisstillexecutable.Youcanaccomplishbothofthesetasksbysettingthememory’sprotectiontoPAGE_EXECUTE_READWRITE.Oncethememoryisproperlyprotected,youcanwritetheNOPcommandsandbedone.Ittechnicallydoesn’thurttoleavethememorywritable,butit’sgoodpracticetoalsorestoretheoriginalprotectionwhenyou’refinished.
Providedyouhavefacilitiesinplaceforwritingandprotectingmemory(asdescribedinChapter6),youcanwriteafunctionliketheoneshowninListing8-2towriteNOPcommandstogamememory.(Followalongbyopeningtheproject’sNOPExample.cppfile.)
template<intSIZE>
![Page 209: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/209.jpg)
voidwriteNop(DWORDaddress){autooldProtection=protectMemory<BYTE[SIZE]>(address,PAGE_EXECUTE_READWRITE);
for(inti=0;i<SIZE;i++)writeMemory<BYTE>(address+i,0x90);
protectMemory<BYTE[SIZE]>(address,oldProtection);}
Listing8-2:ProperNOPing,completewithmemoryprotection
Inthisexample,thewriteNop()functionsetstheappropriatememoryprotection,writesanumberofNOPcommandsequaltoSIZE,andreappliestheoriginalmemoryprotectionlevel.
ThewriteNop()functiontakesthenumberofNOPinstructionstoplaceasatemplateparameter,sincethememoryfunctionsrequireacorrectlysizedtypeatcompiletime.PassinganintegerSIZEtellsthememoryfunctionstooperateonatypeofBYTE[SIZE]atcompiletime.Tospecifyadynamicsizeatruntime,simplydroptheloopandinsteadcallprotectMemory<BYTE>andpassaddressandaddress+SIZEasarguments.Aslongasthesizeisn’tlargerthanapage(andreally,youshouldn’tbeNOPingafullpage),thiswillensurethatthememorygetsproperlyprotectedevenifit’sonapageboundary.
CallthisfunctionwiththeaddresswhereyouwanttoplaceyourNOPsandthenumberofNOPcommandstoplace:
writeNop<2>(0xDEADBEEF);
KeepinmindthatthenumberofNOPcommandsshouldmatchthesizeinbytesofthecommandbeingremoved.ThiscalltowriteNop()writestwoNOPcommandstotheaddress0xDEADBEEF.
PRACTICENOPINGIfyouhaven’talready,openNOPExample.cppinthischapter’sexamplecodenowandplayaroundwithitforabit.You’llfindaworkingimplementationofthewriteNop()functionandaninterestingfunctioncalledgetAddressforNOP()thatscanstheexampleprogram’s
![Page 210: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/210.jpg)
memorytofindwheretheNOPcommandshouldbeplaced.ToseetheNOPcommandinaction,runthecompiled
NOPapplicationinVisualStudio’sdebuggerwithbreakpointsatthestartandendofthewriteNop()function.Whenthefirstbreakpointishit,pressALT-8toopenthedisassemblywindow,enteraddressintheinputbox,andpressENTER.ThisbringsyoutotheNOP’stargetaddress,whereyou’llseetheassemblycodefullyintact.PressF5tocontinueexecution,whichtriggersthesecondbreakpointafterallowingtheapplicationtoplacetheNOPs.Finally,jumpbacktoaddressinthedisassemblytabtoseethatthecodewasreplacedbyNOPs.
Youcanreworkthiscodetodoothercoolstuff.Forexample,youmighttryplacingNOPsonthecomparisonsinsteadofthejumporevenmodifyingthejump’stypeordestination.
Theseandotheralternativeapproachesmaywork,butnotethattheyintroducemoreroomforerrorthanoverwritingthesingleJMPwithNOPcommands.Whenmodifyingforeigncode,makeasfewchangesaspossibletominimizethepotentialforerrors.
HookingtoRedirectGameExecutionSofar,I’veshownyouhowtomanipulategamesbyaddingcodetothem,hijackingtheirthreads,creatingnewthreads,andevenremovingexistingcodefromtheirexecutionflow.Thesemethodsareverypowerfulontheirown,butwhencombined,theyformanevenmorepotentmethodofmanipulationcalledhooking.Hookingallowsyoutointerceptprecisebranchesofexecutionandredirectthemtoinjectedcodethatyou’vewrittentodictatewhatthegameshoulddonext,anditcomesinavarietyofflavors.Inthissection,I’llteachyouaboutfourofthemostpowerfulhookingmethodsforgamehacking:callhooking,virtualfunctiontablehooking,importaddresstablehooking,andjumphooking.
CallHookingAcallhookdirectlymodifiesthetargetofaCALLoperationtopointtoanew
![Page 211: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/211.jpg)
pieceofcode.ThereareafewvariationsoftheCALLoperationinx86assembly,butcallhooksaregenerallyusedononlyone:thenearcall,whichtakesanimmediateaddressasanoperand.
WorkingwithNearCallsinMemoryInanassemblyprogram,anearcalllookslikethis:
CALL0x0BADF00D
Thisnearcallisrepresentedbythebyte0xE8,soyoumightassumeitisstoredinmemorylikethis:
0xE80x0BADF00D
Or,whensplitintosinglebytesandswappedforendianness,likethis:
0xE80x0D0xF00xAD0x0B
Buttheanatomyofanearcallinmemoryisnotthatsimple.Insteadofstoringthecallee’sabsoluteaddress,anearcallstoresanoffsettothecalleerelativetotheaddressimmediatelyafterthecall.Sinceanearcallis5bytes,theaddressimmediatelyafterthecallis5byteslaterinmemory.Giventhat,theaddressstoredcanbecomputedasfollows:
calleeAddress–(callAddress+5)
IfCALL0x0BADF00Dlivesat0xDEADBEEFinmemory,thenthevalueafter0xE8isthis:
0x0BADF00D–(0xDEADBEEF+5)=0x2D003119
Inmemory,then,thatCALLinstructionlookslikethis:
0xE80x190x310x000x2D
Tohookanearcall,youfirstneedtochangetheoffsetfollowing0xE8(thatis,thelittle-endian0x190x310x000x2D)topointtoyournewcallee.
HookingaNearCall
![Page 212: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/212.jpg)
FollowingthesamememoryprotectionrulesshowninListing8-2,youhookanearcalllikeso(followalongbyopeningCallHookExample.cpp):
DWORDcallHook(DWORDhookAt,DWORDnewFunc){DWORDnewOffset=newFunc-hookAt-5;
autooldProtection=protectMemory<DWORD>(hookAt+1,PAGE_EXECUTE_READWRITE);
DWORDoriginalOffset=readMemory<DWORD>(➊hookAt+1);writeMemory<DWORD>(hookAt+1,newOffset);protectMemory<DWORD>(hookAt+1,oldProtection);
➋returnoriginalOffset+hookAt+5;}
ThisfunctiontakesasargumentstheaddressoftheCALLtohook(hookAt)andtheaddresstoredirectexecutionto(newFunc),anditusesthemtocalculatetheoffsetrequiredtocallthecodeattheaddressnewFunccontains.Afteryouapplythecorrectmemoryprotections,thecallHook()functionwritesthenewoffsettothememoryathookAt+1➊,appliestheoldmemoryprotections,calculatestheaddressoftheoriginalcall➋,andreturnsthatvaluetothecaller.
Here’showyoumightactuallyuseafunctionlikethisinagamehack:
DWORDorigFunc=callHook(0xDEADBEEF,(DWORD)&someNewFunction);
Thishooksthenearcallto0x0BADF00Dat0xDEADBEEFandredirectsittotheaddressofsomeNewFunction,whichisthecodeyourhackwillexecute.Afterthisiscalled,theorigFuncvaluewillhold0x0BADF00D.
CleaningUptheStackThenewcalleemustalsoproperlyhandlethestack,preserveregisters,andpassproperreturnvalues.Attheleast,thismeansyourreplacementfunctionmustmatchthegame’soriginalfunctioninbothcallingconventionandargumentcount.
Let’ssaythisistheoriginalfullfunctioncall,inassembly:
PUSH1PUSH456PUSH321
![Page 213: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/213.jpg)
PUSH321CALL0x0BADF00DADDESP,0x0C
YoucantellthefunctionhastheC++__cdeclconventionbecausethestackisbeingresetbythecaller.Additionally,the0x0Cbytesbeingcleanedfromthestackshowthattherearethreearguments,whichyoucancalculateasfollows:
Ofcourse,youcanalsoobtainthenumberofargumentsbycheckinghowmanythingsarepushedtothestack:therearethreePUSHcommands,oneforeachargument.
WritingaCallHookInanycase,thenewcallee,someNewFunction,mustfollowthe__cdeclconventionandhavethreearguments.Here’sanexampleskeletonforthenewcallee:
DWORD__cdeclsomeNewFunction(DWORDarg1,DWORDarg2,DWORDarg3){
}
InVisualStudio,C++programsusethe__cdeclconventionbydefault,sotechnicallyyoucouldomititfromyourfunctiondefinition;however,I’vefoundit’sbettertobeverbosesoyougetintothehabitofbeingspecific.Alsokeepinmindthatifthecallerexpectsavaluetobereturned,thereturntypeofyourfunctionshouldmatchaswell.ThisexampleassumesthereturntypeisalwaysaDWORDorsmaller.SincereturntypesinthissizerangewillallbepassedbackonEAX,furtherexampleswillalsouseareturntypeofDWORD.
Inmostcases,ahookfinishesbycallingtheoriginalfunctionandpassingitsreturnvaluebacktothecaller.Here’showallofthatmightfittogether:
typedefDWORD(__cdecl_origFunc)(DWORDarg1,DWORDarg2,DWORDarg3);
_origFunc*originalFunction=(_origFunc*)hookCall(0xDEADBEEF,(DWORD)&someNewFunction);
DWORD__cdeclsomeNewFunction(DWORDarg1,DWORDarg2,DWORDarg3){
![Page 214: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/214.jpg)
returnoriginalFunction(arg1,arg2,arg3);}
Thisexampleusestypedeftodeclareatyperepresentingtheoriginalfunction’sprototypeandcreatesapointerwiththistypetotheoriginalfunction.ThensomeNewFunction()usesthispointertocalltheoriginalfunctionwiththeoriginalargumentsandpassthereturnedvaluebacktothecaller.
Rightnow,allsomeNewFunction()doesisreturntotheoriginalfunction.ButyoucandowhateveryouwantfrominsidethesomeNewFunction()callfromhere.Youcanmodifytheparametersbeingpassedtotheoriginalfunctionorinterceptandstoreinterestingparametersforlateruse.Ifyouknowthecallerisn’texpectingareturnvalue(orifyouknowhowtospoofthereturnvalue),youcanevenforgetabouttheoriginalfunctionandcompletelyreplace,replicate,orimproveitsfunctionalityinsidethenewcallee.Onceyou’veperfectedthisskill,youcanaddyourownnativeCorC++codetoanypartofagamethatyouwish.
VFTableHookingUnlikecallhooks,virtualfunction(VF)tablehooksdon’tmodifyassemblycode.Instead,theymodifythefunctionaddressesstoredintheVFtablesofclasses.(IfyouneedarefresheronVFtables,see“AClasswithVirtualFunctions”onpage75.)AllinstancesofthesameclasstypeshareastaticVFtable,soVFtablehookswillinterceptallcallsmadetoamemberfunction,regardlessofwhichclassinstancethegameiscallingthefunctionfrom.Thiscanbebothpowerfulandtricky.
THETRUTHABOUTVFTABLESTosimplifytheexplanation,IliedalittlewhenIsaidthatVFtablehookscouldinterceptallcallsmadetoafunction.Inreality,theVFtableistraversedonlywhenavirtualfunctioniscalledinawaythatleavesthecompilerwithsomeplausibletypeambiguity.Forexample,aVFtablewillbetraversedwhenafunctioniscalledthroughtheinst->function()callformat.AVFtablewon’tbetraversedwhena
![Page 215: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/215.jpg)
virtualfunctionisinvokedinsuchawaythatthecompilerissureaboutthetype,asininst.function()orsimilarcalls,sincethecompilerwillknowthefunction’saddress.Conversely,callinginst.function()fromascopewhereinstispassedinasareferencewouldtriggeraVFtabletraversal.BeforeyoutrytodeployVFtablehooking,makesurethefunctioncallsyouwanttohookhavetypeambiguity.
WritingaVFTableHookBeforewegoanydeeperintohowtoplaceaVFtablehook,weneedtotalkaboutthosepeskycallingconventionsagain.VFtablesareusedbyclassinstancestocallvirtualmemberfunctions,andallmemberfunctionswillhavethe__thiscallconvention.Thename__thiscallisderivedfromthethispointerthatmemberfunctionsusetoreferencetheactiveclassinstance.Thus,memberfunctionsaregiventhisasapseudoparameteronECX.
It’spossibletomatchtheprototypeofa__thiscallbydeclaringaclassthatactsasacontainerforall__thiscallhookcallbacks,butIdon’tpreferthismethod.Instead,Ifinditeasiertocontrolthedatausinginlineassembly.Let’sexplorehowyoucontrolthedatawhenplacingaVFhookonaclassthatlookslikethis:
classsomeBaseClass{public:virtualDWORDsomeFunction(DWORDarg1){}};classsomeClass:publicsomeBaseClass{public:virtualDWORDsomeFunction(DWORDarg1){}};
ThesomeBaseClassclassjusthasonemember(apublicvirtualfunction),andthesomeClassclassinheritsfromsomeBaseClassandoverridesthesomeBaseClass::someFunctionmember.TohooksomeClass::someFunction,youreplicatetheprototypeinyourVFtablehook,asshowninListing8-3(followalongintheVFHookExample.cppfileoftheproject).
DWORD__stdcallsomeNewVFFunction(DWORDarg1){➊staticDWORD_this;
![Page 216: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/216.jpg)
__asmMOV_this,ECX}
Listing8-3:ThestartofaVFtablehook
Thisfunctionworksasahookbecause__thiscallonlydiffersfrom__stdcallinthattheformerisgiventhisonECX.Toreconcilethissmalldifference,thecallbackfunctionusesinlineassembly(denotedby__asm)tocopythisfromECXtoastaticvariable➊.Sincethestaticvariableisactuallyinitializedasaglobal,theonlycodethatexecutesbeforeMOV_this,ECXisthecodethatsetsupthestackframe—andthatcodenevertouchesECX.ThatensuresthatthepropervalueisinECXwhentheassemblyisexecuted.
NOTE
IfmultiplethreadsstartcallingthesameVFfunction,thesomeNewVFFunction()hookwillbreakbecause_thismightbemodifiedbyonecallwhilestillbeingusedbyanothercall.I’veneverpersonallyrunintothisproblem,asgamesdon’ttypicallythrowaroundmultipleinstancesofcriticalclassesbetweenthreads,butanefficientremedywouldbetostore_thisinthreadlocalstorage,ensuringeachthreadwouldhaveitsowncopy.
Beforereturning,aVFtablecallbackmustalsorestoreECX,tokeepwiththe__thiscallconvention.Here’showthatprocesslooks:
DWORD__stdcallsomeNewVFFunction(DWORDarg1){staticDWORD_this;__asmMOV_this,ECX
//dogamemodifyingstuffhere
__asm➊MOVECX,_this}
Afterexecutingsomegame-hackingcode,thisversionofthefunctionsomeNewVFFunction()restoresECX➊withareversedversionofthefirstMOVinstructionfromListing8-3.
Unlikewith__cdeclfunctions,however,youshouldn’tcallfunctionsthat
![Page 217: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/217.jpg)
usethe__thiscallconventionfrompureC++usingonlyafunctionpointerandtypedef(asyouwouldforacallhook).WhencallingtheoriginalfunctionfromaVFtablehook,youmustuseinlineassembly—that’stheonlywaytobesureyou’repassingdata(specifically_this)aroundproperly.Forexample,thisishowyoucontinuetobuildthesomeNewVFFunction()hook:
DWORD__stdcallsomeNewVFFunction(DWORDarg1){staticDWORD_this,_ret;__asmMOV_this,ECX
//dopre-callstuffhere
__asm{PUSHarg1MOVECX,_this➊CALL[originalVFFunction]➋MOV_ret,EAX}
//dopost-callstuffhere
➌__asmMOVECX,_thisreturn_ret;}
Now,someNewVFFunction()storesthisinthe_thisvariable,allowssomecodetoexecute,callstheoriginalgamefunction➊that’sbeinghooked,storesthatfunction’sreturnvaluein_ret➋,allowssomemorecodetoexecute,restoresthistoECX➌,andreturnsthevaluestoredin_ret.Thecalleecleansthestackfor__thiscallcalls,sounlikeacallhook,thepushedargumentdoesn’tneedtoberemoved.
NOTE
Ifyouwanttoremoveasinglepushedargumentatanypoint,usetheassemblyinstructionADDESP,0x4becauseasingleargumentis4bytes.
UsingaVFTableHookWiththecallingconventionestablishedandaskeletoncallbackinplace,it’stimetomoveontothefunpart:actuallyusingaVFtablehook.Apointerto
![Page 218: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/218.jpg)
timetomoveontothefunpart:actuallyusingaVFtablehook.Apointertoaclass’sVFtableisthefirstmemberofeveryclassinstance,soplacingaVFtablehookrequiresonlyaclassinstanceaddressandtheindexofthefunctiontobehooked.Usingthesetwopiecesofinformation,youneedonlyamodestamountofcodetoplaceahook.Here’sanexample:
DWORDhookVF(DWORDclassInst,DWORDfuncIndex,DWORDnewFunc){DWORDVFTable=➊readMemory<DWORD>(classInst);DWORDhookAt=VFTable+funcIndex*sizeof(DWORD);
autooldProtection=protectMemory<DWORD>(hookAt,PAGE_READWRITE);DWORDoriginalFunc=readMemory<DWORD>(hookAt);writeMemory<DWORD>(hookAt,newFunc);protectMemory<DWORD>(hookAt,oldProtection);
returnoriginalFunc;}
ThehookVF()functionfindstheVFtablebyreadingthefirstmemberoftheclassinstance➊andstoringitinVFTable.SincetheVFtableisjustanarrayofDWORD-sizedaddresses,thiscodefindsthefunctionaddressbymultiplyingthefunction’sindexintheVFtable(funcIndexinthisexample)bythesizeofaDWORD,whichis4,andaddingtheresulttotheVFtable’saddress.Fromthere,hookVF()actssimilartoacallhook:itmakessurethememoryisproperlyaccessiblebysettingappropriateprotections,storestheoriginalfunctionaddressforlater,writesthenewfunctionaddress,andfinally,restorestheoriginalmemoryprotection.
You’lltypicallyhooktheVFtableofaclassinstantiatedbythegame,andcallingafunctionlikehookVF()foraVFtablehooklookslikethis:
DWORDorigVFFunction=hookVF(classInstAddr,0,(DWORD)&someNewVFFunction);
Asusual,youneedtofindclassInstAddrandthefuncIndexargumentaheadoftime.
TherearesomeverynichecasesinwhichVFtablehooksareuseful,anditcanbereallyhardtofindtherightclasspointersandfunctions.Giventhat,insteadofshowingcontrivedusecases,I’llcomebacktoVFtablehooksin“ApplyingJumpHooksandVFHookstoDirect3D”onpage175,onceI’vediscussedothertypesofhooking.
![Page 219: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/219.jpg)
IfyouwanttoplaywithVFhooksbeforereadingmore,addnewvirtualfunctionstotheexampleclassesinthisbook’sresourcefilesandpracticehookingthem.YoumightevencreateasecondclassthatderivesfromsomeBaseClassandplaceahookonitsvirtualtabletodemonstratehowyoucanhavetwocompletelyseparateVFhooksontwoclassesthatinheritthesamebaseclass.
IATHookingIAThooksactuallyreplacefunctionaddressesinaspecifictypeofVFtable,calledtheimportaddresstable(IAT).EachloadedmoduleinaprocesscontainsanIATinitsPEheader.Amodule’sIATholdsalistofalltheothermodulesonwhichthemoduledepends,aswellasalistoffunctionsthatthemoduleusesfromeachdependency.ThinkofanIATasalookuptableforAPIstocalloneanother.
Whenamoduleisloaded,itsdependenciesarealsoloaded.Dependencyloadingisarecursiveprocessthatcontinuesuntilalldependenciesforallmodulesareloaded.Aseachdependencyisloaded,theoperatingsystemfindsallfunctionsusedbythedependentmoduleandfillsanyblankspacesinitsIATwiththefunctionaddresses.Then,whenamodulecallsafunctionfromadependency,itmakesthatcallbyresolvingthefunction’saddressfromtheIAT.
PayingforPortabilityFunctionaddressesarealwaysresolvedfromtheIATinrealtime,sohookingtheIATissimilartohookingVFtables.SincefunctionpointersarestoredintheIATbesidetheiractualnames,there’snoneedtodoanyreverseengineeringormemoryscanning;aslongasyouknowthenameoftheAPIyouwanttohook,youcanhookit!Moreover,IAThookingletsyoueasilyhookWindowsAPIcallsonamodule-specificbasis,allowingyourhookstointerceptonlyAPIcallsfromagame’smainmodule.
Thisportabilityhasacost,though;thecodetoplaceanIAThookismuchmorecomplexthanwhatyou’veseensofar.First,youneedtolocatethePEheaderofthegame’smainmodule.SincethePEheaderisthefirststructureinanybinary,youcanfinditatthebaseaddressofeachmodule,asshowninListing8-4(followalongintheIATHookExample.cppfileofthe
![Page 220: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/220.jpg)
project).
DWORDbaseAddr=(DWORD)GetModuleHandle(NULL);
Listing8-4:Fetchingthemodule’sbaseaddress
Onceyou’vefoundthebaseaddress,youmustverifythatthePEheaderisvalid.Thisvalidationcanbeveryimportant,assomegamestrytopreventthesetypesofhooksbyscramblingnonessentialpartsoftheirPEheaderaftertheyload.AvalidPEheaderisprefixedbyaDOSheader,whichindicatesthefileisaDOSMZexecutable;theDOSheaderisidentifiedbythemagicvalue0x5A4D.AmemberoftheDOSheadercallede_lfanewthenpointstotheoptionalheader,whichcontainsvalueslikethesizeofthecode,aversionnumber,andsoonandisidentifiedbythemagicvalue0x10B.
TheWindowsAPIhasPEstructurescalledIMAGE_DOS_HEADERandIMAGE_OPTIONAL_HEADERthatcorrespondtotheDOSheaderandoptionalheader,respectively.YoucanusethemtovalidatethePEheaderwithcodelikeListing8-5.
autodosHeader=pointMemory<IMAGE_DOS_HEADER>(baseAddr);if(dosHeader->e_magic!=0x5A4D)return0;
autooptHeader=pointMemory<IMAGE_OPTIONAL_HEADER>(baseAddr+dosHeader->e_lfanew+24);if(optHeader->Magic!=0x10B)return0;
Listing8-5:ConfirmingtheDOSandoptionalheadersarevalid
ThecallstopointMemory()createpointerstothetwoheadersthatneedtobechecked.Ifeitherif()statementreturns0,thenthecorrespondingheaderhasthewrongmagicnumber,meaningthePEheaderisn’tvalid.
ReferencestotheIATfromassemblyarehardcoded,meaningassemblyreferencesdon’ttraversethePEheadertolocatetheIAT.Instead,eachfunctioncallhasastaticlocationindicatingwheretofindthefunctionaddress.ThatmeansoverwritingthePEheadertosaythattherearenoimportsisaviablewaytoprotectagainstIAThooks,andsomegameshavethisprotection.
Toaccountforthat,youalsoneedtomakesurethegame’sIATstill
![Page 221: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/221.jpg)
exists.Listing8-6showshowtoaddsuchachecktothecodeinListing8-5.
autoIAT=optHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];if(IAT.Size==0||IAT.VirtualAddress==0)return0;
Listing8-6:CheckingthattheIATactuallyexists
ThePEheadercontainsmanysectionsthatstoreinformationabouttheapplication’scode,embeddedresources,relocations,andsoon.ThepieceofcodeinListing8-6isparticularlyinterestedinthedatasection,which—asyoumightguess—storesmanydifferenttypesofdata.Eachtypeofdataisstoredinitsowndirectory,andtheDataDirectorymemberofIMAGE_OPTIONAL_HEADERisanarrayofdirectoryheadersthatdescribesthesizeandvirtualaddressofeachdirectoryinthedatasection.TheWindowsAPIdefinesaconstantcalledIMAGE_DIRECTORY_ENTRY_IMPORT,whichhappenstobetheindexoftheIATheaderwithintheDataDirectoryarray.
Thus,thiscodeusesoptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]toresolvetheheaderoftheIATandcheckthattheheader’sSizeandVirtualAddressarenonzero,essentiallyconfirmingitsexistence.
TraversingtheIATOnceyouknowtheIATisstillintact,youcanstarttraversingit,andthisiswhereIAThookingstartstogetugly.TheIATisanarrayofstructurescalledimportdescriptors.Thereisoneimportdescriptorforeachdependency,eachimportdescriptorpointstoanarrayofstructurescalledthunks,andeachthunkrepresentsafunctionimportedfromthedependency.
Luckily,theWindowsAPIexposesboththeimportdescriptorsandthunksthroughtheIMAGE_IMPORT_DESCRIPTORandIMAGE_THUNK_DATAstructures,respectively.Havingthestructurespredefinedsavesyoufromcreatingyourown,butitdoesn’tmakethecodetotraversetheIATanyprettier.ToseewhatImean,lookatListing8-7,whichbuildsonListings8-4through8-6.
autoimpDesc=pointMemory<IMAGE_IMPORT_DESCRIPTOR>(➊baseAddr+IAT.VirtualAddress);
![Page 222: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/222.jpg)
➋while(impDesc->FirstThunk){➌autothunkData=pointMemory<IMAGE_THUNK_DATA>(baseAddr+impDesc->OriginalFirstThunk);intn=0;➍while(thunkData->u1.Function){//thehookhappensinheren++;thunkData++;}impDesc++;}
Listing8-7:IteratingovertheIATtofindafunction
KeepinginmindthattheimportdescriptorsarestoredrelativetothestartofthePEheader,thiscodeaddsthemodule’sbaseaddresstothevirtualaddressfoundintheIAT’sdirectoryheader➊,creatingapointer,impDesc,thatpointstothemodule’sfirstimportdescriptor.
Importdescriptorsarestoredinasequentialarray,andadescriptorwithaFirstThunkmembersettoNULLsignifiestheendofthearray.Knowingthis,thecodeusesawhileloop➋thatcontinuesuntilimpDesc->FirstThunkisNULL,incrementingthedescriptorbyexecutingimpDesc++eachiteration.
Foreachimportdescriptor,thecodecreatesapointercalledthunkData➌thatpointstothefirstthunkinsidethedescriptor.Usingafamiliarloop,thecodeiteratesoverthunks➍untiloneisfoundwithaFunctionmembersettoNULL.Theloopalsousesaninteger,n,tokeeptrackofthecurrentthunkindex,astheindexisimportantwhenplacingthehook.
PlacingtheIATHookFromhere,placingthehookisjustamatteroffindingtheproperfunctionnameandreplacingthefunctionaddress.Youcanfindthenameinsidethenestedwhileloop,asshowninListing8-8.
char*importFunctionName=pointMemory<char>(baseAddr+(DWORD)thunkData->u1.AddressOfData+2);
Listing8-8:Findingthefunctionname
ThefunctionnameforeachthunkisstoredatthunkData-
![Page 223: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/223.jpg)
>u1.AddressOfData+2bytesintothemodule,soyoucanaddthatvaluetothemodule’sbaseaddresstolocatethefunctionnameinmemory.
Afterobtainingapointertothefunctionname,usestrcmp()tocheckwhetherit’sthetargetfunction,likeso:
if(strcmp(importFuncName,funcName)==0){//thefinalstephappensinhere}
Onceyou’velocatedthetargetfunctionusingitsname,yousimplyneedtooverwritethefunctionaddresswiththeaddressofyourownfunction.Unlikefunctionnames,functionaddressesarestoredinanarrayatthestartofeachimportdescriptor.Usingnfromthethunkloop,youcanfinallysetthehook,asshowninListing8-9.
autovfTable=pointMemory<DWORD>(baseAddr+impDesc->FirstThunk);DWORDoriginal=vfTable[n];
➊autooldProtection=protectMemory<DWORD>((DWORD)&vfTable[n],PAGE_READWRITE);➋vfTable[n]=newFunc;protectMemory<DWORD>((DWORD)&vfTable[n],oldProtection);
Listing8-9:Findingthefunctionaddress
ThiscodelocatestheVFtableforthecurrentdescriptorbyaddingtheaddressofthefirstthunktothemodulebaseaddress.TheVFtableisanarrayoffunctionaddresses,sothecodeusesthenvariableasanindextolocatethetargetfunctionaddress.
Oncetheaddressisfound,thecodeinListing8-9worksjustlikeatypicalVFhook:itstorestheoriginalfunctionaddress,setstheprotectionofindexnintheVFtabletoPAGE_READWRITE➊,insertsthenewfunctionaddressintotheVFtable➋,andfinallyrestorestheoldprotection.
IfyoustitchtogetherthecodefromListings8-4through8-9,thefinalIAThookingfunctionlookslikeListing8-10.
DWORDhookIAT(constchar*funcName,DWORDnewFunc){DWORDbaseAddr=(DWORD)GetModuleHandle(NULL);autodosHeader=pointMemory<IMAGE_DOS_HEADER>(baseAddr);if(dosHeader->e_magic!=0x5A4D)return0;
![Page 224: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/224.jpg)
autooptHeader=pointMemory<IMAGE_OPTIONAL_HEADER>(baseAddr+dosHeader->e_lfanew+24);if(optHeader->Magic!=0x10B)return0;
autoIAT=optHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];if(IAT.Size==0||IAT.VirtualAddress==0)return0;
autoimpDesc=pointMemory<IMAGE_IMPORT_DESCRIPTOR>(baseAddr+IAT.VirtualAddress);
while(impDesc->FirstThunk){autothunkData=pointMemory<IMAGE_THUNK_DATA>(baseAddr+impDesc->OriginalFirstThunk);intn=0;while(thunkData->u1.Function){char*importFuncName=pointMemory<char>(baseAddr+(DWORD)thunkData->u1.AddressOfData+2);if(strcmp(importFuncName,funcName)==0){autovfTable=pointMemory<DWORD>(baseAddr+impDesc->FirstThunk);DWORDoriginal=vfTable[n];autooldProtection=protectMemory<DWORD>((DWORD)&vfTable[n],PAGE_READWRITE);vfTable[n]=newFunc;protectMemory<DWORD>((DWORD)&vfTable[n],oldProtection);returnoriginal;}n++;thunkData++;}impDesc++;}}
Listing8-10:ThecompleteIAThookingfunction
Thisisthemostcomplexcodethatwe’veputtogethersofar,andit’sprettyhardtoreadwhensquishedtofitonapage.Ifyouhaven’tyetwrappedyourheadaroundwhatit’sdoing,youmightwanttostudytheexamplecodefromthisbook’sresourcefilesbeforecontinuing.
![Page 225: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/225.jpg)
UsinganIATHooktoSyncwithaGameThreadWiththecodeinListing8-10,hookinganyWindowsAPIfunctionisassimpleasknowingthefunctionnameandtheproperprototype.TheSleep()APIisacommonAPItohookwhengamehacking,asbotscanuseaSleep()hooktothread-syncwithagame’smainloop.
GETTINGINSYNCWITHTHREADSYNCYourinjectedcodewillinevitablyhavetosyncwithagame’smainloop,oritwon’twork.Whenyou’rereadingorwritingdatalargerthan4bytes,forexample,beingoutofsyncallowsthegametoreadorwritethatdataatthesametimeasyou.You’llbesteppingonthegame’stoes,andviceversa,leadingtoallsortsofraceconditionsanddatacorruptionissues.Similarly,ifyoutrytocallagame’sfunctionfromyourownthread,youruntheriskofcrashingthegameifthefunctionisnotthreadsafe.
SinceIAThooksarethread-safemodificationstothePEheader,theycanbeplacedfromanythread.Byplacingoneonafunctionthat’scalledbeforeorafterthegame’smainloop,youcaneffectivelysyncwiththegame’smainthread.Allyouneedtodoisplacethehookandexecuteanythread-sensitivecodefromyourhookcallback.
Here’sonewaytousehookIAT()tohooktheSleep()API:
VOIDWINAPInewSleepFunction(DWORDms){//dothread-sensitivethingsoriginalSleep(ms);}
typedefVOID(WINAPI_origSleep)(DWORDms);_origSleep*originalSleep=(_origSleep*)hookIAT("Sleep",(DWORD)&newSleepFunction);
Here’swhythisworks.Attheendofagame’smainloop,itmightcallSleep()torestuntilit’sreadytodrawthenextframe.Sinceit’ssleeping,it’ssafeforyoutodoanythingyouwantwithoutworryingabout
![Page 226: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/226.jpg)
synchronizationissues.Somegamesmightnotdothis,ortheymightcallSleep()frommultiplethreads,andthosegameswillrequireadifferentmethod.
AmoreportablealternativeistohookthePeekMessageA()APIfunction,becausegamesoftencallthatfunctionfromthemainloopwhilewaitingforinput.Then,yourbotcandothread-sensitiveoperationsfromwithinthePeekMessageA()hook,ensuringthatthey’redonefromthegame’smainthread.Youmayalsowantyourbottousethismethodtohookthesend()andrecv()APIfunctions,asinterceptingtheseallowsyoutocreateapacketsnifferrelativelysimply.
JumpHookingJumphookingallowsyoutohookcodeinplaceswherethereisnobranchingcodetomanipulate.Ajumphookreplacesthecodebeinghookedwithanunconditionaljumptoatrampolinefunction.Whenthejumpishit,thetrampolinefunctionstoresallcurrentregisterandflagvalues,callsacallbackfunctionofyourchoice,restorestheregisters,restorestheflags,executesthecodethatwasreplacedbythehook,andfinallyjumpsbacktothecodejustbelowthehook.ThisprocessisshowninFigure8-1.
Figure8-1:Ajumphook
Theoriginalcodeshowsanexampleofsomeunmodifiedassemblyyoumightfindinagame,andthehookedcodeshowshowthatassemblymightlookafterbeinghookedbyajumphook.Thetrampolineboxshowsanexampletrampolinefunction,inassembly,andthecallbackrepresentsthe
![Page 227: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/227.jpg)
codeyou’retryingtoexecutethroughhooking.Intheoriginalcode,theassemblyexecutesfromtoptobottom.Inthehookedcode,togetfromtheSUBEAX,1instructiontotheRETNinstruction,executionmustfollowthepathshownbythedashedarrows.
NOTE
Ifyourcallbackcodeissimple,itcanbeintegratedintothetrampolineinstead.It’salsonotalwaysnecessarytostoreandrestoretheregistersandflags,butdoingsoisgoodpractice.
PlacingaJumpThebytecodeofanunconditionaljumpresemblesthatofanearcall,butthefirstbyteis0xE9insteadof0xE8.(See“WorkingwithNearCallsinMemory”onpage153forarefresher.)InFigure8-1,theunconditionaljumpJMPtrampolinereplacesthefollowingfouroperations:
POPEAXMOVAL,1POPEDIPOPESI
Inthiscase,youneedtoreplacemultiplesequentialoperationstoaccommodatethe5-bytesizeoftheunconditionaljump.Youmaycomeacrosscaseswherethesizeoftheoperation(oroperations)beingreplacedislargerthan5bytes.Whenthishappens,replacetheremainingbyteswithNOPinstructions.
Now,let’slookathowtoreplacethoseoperations.Listing8-11showsthecodetoplaceajumphook.
DWORDhookWithJump(DWORDhookAt,DWORDnewFunc,intsize){if(size>12)//shouldn'teverhavetoreplace12+bytesreturn0;➊DWORDnewOffset=newFunc-hookAt-5;
autooldProtection=protectMemory<DWORD[3]>(hookAt+1,PAGE_EXECUTE_READWRITE);➋writeMemory<BYTE>(hookAt,0xE9);➌writeMemory<DWORD>(hookAt+1,newOffset);
![Page 228: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/228.jpg)
for(unsignedinti=5;i<size;i++)writeMemory<BYTE>(hookAt+i,0x90);protectMemory<DWORD[3]>(hookAt+1,oldProtection);
returnhookAt+5;}
Listing8-11:Howtoplaceajumphook
Thisfunctiontakestheaddresstohookat,theaddressofthecallbackfunction,andthesizeofthememorytooverwrite(inbytes)asarguments.First,itcalculatestheoffsetbetweenthehooksiteandthetrampolineandstorestheresultinnewOffset➊.Next,PAGE_EXECUTE_READWRITEpermissionsareappliedtothememorytobechanged.Theunconditionaljump(0xE9)➋andtheaddressofthecallbackfunction➌arethenwrittentomemory,andaforloopwritesNOPinstructions(0x90)toanyabandonedbytes.Aftertheoldprotectionsarereapplied,hookWithJump()returnstotheoriginaladdress.
NoticethatthehookWithJump()functionensuresthatsizeisnotabove12beforeplacingthejump.Thischeckisimportantbecauseajumptakesup5bytes,meaningitcanreplaceuptofivecommandsifthefirstfourareeachasinglebyte.Ifthefirstfourcommandsareeachasinglebyte,thefifthcommandwouldneedtobemorethan8bytestotriggertheif(size>12)clause.Because9-byteoperationsarevery,veryrare,12isasafebutflexiblelimit.Havingthislimitcanstopallsortsofbugsfromhappening,especiallyifyourbotisdynamicallydetectingthesizeparameter.Ifthebotmessesupandpassesasizeof500,000,000,forinstance,thecheckwillstopyoufromNOPingthewholeuniverse.
WritingtheTrampolineFunctionUsingthefunctioninListing8-11,youcanreplicatethehookshowninFigure8-1,butfirstyou’llhavetocreatethetrampolinefunctionasfollows:
DWORDrestoreJumpHook=0;void__declspec(naked)myTrampoline(){__asm{➊PUSHFD➋PUSHAD➌CALLjumpHookCallback➍POPAD
![Page 229: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/229.jpg)
➎POPFD➏POPEAXMOVAL,1POPEDI➐POPESI➑JMP[restoreJumpHook]}}
JustlikethetrampolinedescribedalongsideFigure8-1,thistrampolinestoresallcurrentflag➊andregistervalues➋,callsacallbackfunction➌,restorestheregisters➍,restorestheflags➎,executesthecodethatwasreplacedbythehookat➏and➐,andfinallyjumpsbacktotheoriginalcodejustbelowthejumpandNOPs➑.
NOTE
Toensurethatthecompilerdoesn’tautogenerateanyextracodewithinthetrampoline,alwaysdeclarethetrampolineusingthe__declspec(naked)convention.
FinishingtheJumpHookOnceyoucreatethetrampoline,definethecallbackandsetthehooklikeso:
voidjumpHookCallback(){//dostuff}restoreJumpHook=hookWithJump(0xDEADBEEF,&myTrampoline,5);
Finally,insidethejumpHookCallback()function,executethecodethatreliesonthehook.Ifyourcodeneedstoreadorwritethevaluesoftheregistersastheywerewhenthehookexecuted,you’reinluck.ThePUSHADcommandpushesthemtothestackintheorderEAX,ECX,EDX,EBX,originalESP,EBP,ESI,andEDI.ThetrampolinecallsPUSHADdirectlybeforethejumpHookCallback()call,soyoucanreferencetheregistervaluesasarguments,likethis:
voidjumpHookCallback(DWORDEDI,DWORDESI,DWORDEBP,DWORDESP,DWORDEBX,DWORDEDX,DWORDECX,DWORDEAX){//dostuff
![Page 230: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/230.jpg)
}restoreJumpHook=hookWithJump(0xDEADBEEF,&myTrampoline,5);
SincethetrampolineusesPOPADtodirectlyrestoretheregistersfromthesevaluesonthestack,anymodificationsyoumaketotheparameterswillbeappliedtotheactualregisterswhentheyarerestoredfromthestack.
LikeVFtablehooks,jumphooksarerarelyneeded,andtheycanbetrickytosimulatewithasimpleexample.Tohelpyouwrapyourheadaroundthem,I’llexploreareal-world,practicalusecasein“ApplyingJumpHooksandVFHookstoDirect3D”onpage175.
PROFESSIONALAPIHOOKINGLIBRARIESThereareprewrittenhookinglibraries,likeMicrosoft’sDetoursandMadCHook,thatuseonlyjumphooks.Theselibrariescanautomaticallydetectandfollowotherhooks,theyknowhowmanyinstructionstoreplace,andtheygeneratetrampolinefunctionsforyou.Thelibrariesareabletodothisbecausetheyunderstandhowtodisassembleandwalkthroughassemblyinstructionstodeterminelengths,jumpdestinations,andsoon.Ifyouneedtousehookswiththatmuchpower,itisarguablybettertouseoneofthoselibrariesthantocreateyourown.
ApplyingCallHookstoAdobeAIRAdobeAIRisadevelopmentframeworkthatcanbeusedtomakecross-platformgamesinanenvironmentsimilartoAbodeFlash.AIRisacommonframeworkforonlinegames,asitallowsdeveloperstowritecross-platformcodeinaversatile,high-levellanguagecalledActionScript.ActionScriptisaninterpretedlanguage,andAIRrunsthecodeinsideavirtualmachine,whichmakesitinfeasibletohookgame-specificcodewithAIR.Instead,itiseasiertohookAIRitself.
TheexamplecodeforthissectioncanbefoundinGameHackingExamples/Chapter8_AdobeAirHookinthisbook’ssourcefiles.
![Page 231: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/231.jpg)
Thecodecomesfromanoldprojectofmine,anditworksonanygamerunningAdobeAIR.dllversion3.7.0.1530.I’vegottenitworkingonotherversionsaswell,butIcan’tguaranteeitwillworkwithmuchnewerormucholderversions,sotreatthisasacasestudy.
AccessingtheRTMPGoldmineTheRealTimeMessagingProtocol(RTMP)isatext-basednetworkprotocolthatActionScriptusestoserializeandsendentireobjectsoverthenetwork.RTMPsitsontopoftheHyperTextTransferProtocol(HTTP),andasecureversion,RTMPS,sitsontopofHTTPSecure(HTTPS).RTMPSallowsgamedeveloperstoeasilysendandreceiveentireobjectinstancesoverasecureconnectionwithlittlecomplication,makingitthenetworkprotocolofchoiceforanygamesrunningonAIR.
NOTE
DatasentoverRTMP/RTMPSisserializedthroughActionMessageFormat(AMF),andparsingAMFpacketsisbeyondthescopeofthisbook.Searchonlinefor“AMF3Parser,”andyou’llfindalotofcodethatdoesit.
DatasentoverRTMPandRTMPSisveryrich.Thepacketscontaininformationaboutobjecttypes,names,andvalues.Thisisagoldmine.Ifyoucaninterceptthisdatainrealtime,youcaninstantaneouslyrespondtochangesingamestate,seeawealthofcriticalinformationwithouteverreadingitfrommemory,andfindusefulpiecesofdatathatyoumightnotevenknowexist.
Awhileback,Iwasworkingonatoolthatrequiredatonofinsightintothestateofagame.Obtainingsuchalargeamountofdatadirectlyfrommemorywouldhavebeenextremelyhard,ifnotimpossible.Aftersomeresearch,IrealizedthatthegamewasusingRTMPStocommunicatewiththeserver,andthatpromptedmetostartdiggingintothisgoldmine.
SinceRTMPSisencrypted,IknewIhadtosomehowhookthecryptographicfunctionsusedbyAIRbeforeIcouldgetanyusabledata.Aftersearchingonline,Ifoundsourcecodeforasmalltoolcalledairlog,createdbyanothergamehackerwho,likeme,wastryingtologpacketssentoverRTMPS.AlthoughthetoolhookedtheexactfunctionsIneeded,thecodewasoutdated,messy,and,worstofall,didn’tworkontheversionof
![Page 232: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/232.jpg)
codewasoutdated,messy,and,worstofall,didn’tworkontheversionofAIRIwastryingtohook.
Butthatdidn’tmeanitwasuseless.NotonlydidairloghookthetwofunctionsIneeded,butitalsolocatedthembyscanningforcertainbytepatternswithintheAdobeAIRlibrary.Thesebytepatternswerethreeyearsold,though,sotheyweren’tworkinganymore.ThenewerversionsofAdobeAIRhadchangedenoughthattheassemblybyteswerenolongerthesame.Thedifferenceinbyteswasaproblemforthecodeinairlog,butnotforme.
Insideaninlineassemblyblock,youcanspecifyrawbyteswiththefollowingfunctioncall:
_emitBYTE
IfyoureplaceBYTEwith,say,0x03,thecodewillbecompiledinawaythattreats0x03asabyteintheassemblycode,regardlessofwhetherthatmakessense.Usingthistrick,Icompiledthebytearraysbacktoassemblycode.Thecodedidn’tdoanything,anditwasn’tmeantto;usingthistricksimplyallowedmetoattachtomydummyapplicationwithOllyDBGandinspectbytes,whichwereconvenientlypresentedasacleandisassembly.
SincethesebytesrepresentedthecodesurroundingthefunctionsIneeded,so,too,didtheirdisassembly.Thecodewasprettystandardanddidn’tseemlikelytochange,soIturnedmyattentiontotheconstants.Thecodehadafewimmediatevaluespassedasoffsetsincommands.Knowinghowcommonlythesecanchange,Irewiredairlog’spattern-matchingalgorithmtosupportwildcards,updatedthepatternstotreatanyconstantsaswildcards,andthenranthematch.Aftersometweakstothepatternsandabitofdiggingthroughduplicatesearchresults,ItrackeddownthefunctionsIwantedtohook.Iappropriatelynamedthemencode()anddecode()andbeganworkingonatoolsimilartoairlog—butbetter.
HookingtheRTMPSencode()FunctionIdiscoveredthattheencode()function,whichisusedtoencryptthedataforoutgoingpackets,isanonvirtual__thiscall,meaningit’scalledbyanearcall.Moreover,thecallhappensinsidealoop.TheentirelooplookslikeListing8-12,takendirectlyfromtheOllyDBGdisassemblypane.
loop:
![Page 233: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/233.jpg)
MOVEAX,[ESI+3C58]SUBEAX,EDIPUSHEAX➊LEAEAX,[ESI+EDI+1C58]PUSHEAXMOVECX,ESI➋CALLencodeCMPEAX,-1➌JESHORTendLoopADDEDI,EAX➍CMPEDI,[ESI+3C58]JLloopendLoop:
Listing8-12:Theencode()loop
Withabitofanalysisandsomeguidancefromairlog,Ideterminedthattheencode()functioncalledat➊takesabytearrayandbufferlength(let’scallthembufferandsize,respectively)asparameters.Thefunctionreturns-1whenitfailsandreturnssizeotherwise.Thefunctionoperatesonchunksof4,096bytes,whichiswhythishappensinaloop.
Turnedintomorereadablepseudocode,theloopcallingencode()lookslikethis(thenumbersrefertotherelevantassemblyinstructionsinListing8-12):
for(EDI=0;EDI<➍[ESI+3C58];){EAX=➋encode(➊&[ESI+EDI+1C58],[ESI+3C58]-EDI);if(EAX==-1)➌break;EDI+=EAX;}
Iwasn’tinterestedinwhatencode()did,butIneededtheentirebufferitwasloopingover,andhookingencode()wasmymeansofgettingthatbuffer.LookingattherealloopinListing8-12,Iknewthatthecallingobjectinstance’sfullbufferwasstoredatESI+0x1C58,thatthefullsizewasstoredatESI+0x3C58,andthatEDIcontainedtheloopcounter.Idevisedthehookwiththesethingsinmind,ultimatelycreatingatwo-parthook.
ThefirstpartofmyhookwasareportEncode()functionthatlogstheentirebufferonthefirstloopiteration.Here’sthereportEncode()functioninfull:
DWORD__stdcallreportEncode(
![Page 234: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/234.jpg)
constunsignedchar*buffer,unsignedintsize,unsignedintloopCounter){if(loopCounter==0)printBuffer(buffer,size);returnorigEncodeFunc;}
Thisfunctiontakesbuffer,size,andloopCounterasparametersandreturnstheaddressofthefunctionIdubbedencode().Beforefetchingthataddress,however,thesecondpartofmyhook,amyEncode()function,doesallofthedirtyworktoobtainbuffer,size,andloopCounter,asfollows:
void__declspec(naked)myEncode(){__asm{MOVEAX,DWORDPTRSS:[ESP+0x4]//getbufferMOVEDX,DWORDPTRDS:[ESI+0x3C58]//getfullsizePUSHECX//storeecxPUSHEDI//pushcurrentpos(loopcounter)PUSHEDX//pushsizePUSHEAX//pushbufferCALLreportEncode//reporttheencodecallPOPECX//restoreecxJMPEAX//jumptoencode}}
ThemyEncode()functionisapureassemblyfunctionthatreplacestheoriginalencode()functioncallusinganearcallhook.AfterstoringECXonthestack,myEncode()obtainsbuffer,size,andloopCounterandpassesthemtothereportEncode()function.AftercallingthereportEncode()function,themyEncode()functionrestoresECXandjumpsdirectlyintoencode(),causingtheoriginalfunctiontoexecuteandreturngracefullytotheloop.
SincemyEncode()cleanseverythingitusesfromthestack,thestackstillcontainstheoriginalparametersandreturnaddressinthecorrectspotaftermyEncode()runs.That’swhymyEncode()jumpsdirectlyintoencode()insteadofusingafunctioncall:thatstackisalreadysetupwiththeproperreturnaddressandparameters,sotheencode()functionwillthinkeverythinghappenedasnormal.
HookingtheRTMPSdecode()Function
![Page 235: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/235.jpg)
ThefunctionInameddecode(),whichisusedtodecryptincomingdata,wasalsoa__thiscallthatwascalledinaloop.Itworkedonchunksof4,096bytesandtookabufferandsizeasparameters.Theloopwasquiteabitmorecomplex,containingmultiplefunctioncalls,nestedloops,andloopescapes,buthookingworkedmuchthesameashookingtheso-calledencode()function.Thereasonfortheaddedcomplexityisnotrelevanttohookingthefunction,butitmakesthecodedifficulttosummarize,soIwon’tshowtheoriginalfunctionhere.Thebottomlineisthis:onceallthecomplexitywasrubbedaway,thedecode()loopwastheencode()loopinreverse.
Onceagain,Idevisedatwo-partnearcallhook.Thefirstpart,reportDecode(),isshownhere:
void__stdcallreportDecode(constunsignedchar*buffer,unsignedintsize){printBuffer(buffer,size);}
Thefunctionlogseachpacketthatcomesthrough.Ididn’thavealoopindexatthetime,soIdecidedthatitwasokaytologeverysinglepartialpacket.
Thesecondpartofthehook,themyDecode()function,actsasthenewcalleeanddoesallofthedirtywork,asfollows:
void__declspec(naked)myDecode(){__asm{MOVEAX,DWORDPTRSS:[ESP+0x4]//getbufferMOVEDX,DWORDPTRSS:[ESP+0x8]//getsizePUSHEDX//pushsizePUSHEAX//pushbuffer➊CALL[origDecodeFunc]
MOVEDX,DWORDPTRSS:[ESP+0x4]//getthebuffer
PUSHEAX//storeeax(returnvalue)PUSHECX//storeecxPUSHEAX//pushsizePUSHEDX//pushbufferCALLreportDecode//reporttheresultsnowPOPECX//restoreecx➋POPEAX//restoreeax(returnvalue)
![Page 236: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/236.jpg)
➌RETN8//returnandcleanstack}}
Iknewthebufferwasdecryptedinplace,meaningtheencryptedchunkwouldbeoverwrittenwiththedecryptedoneoncethecalltodecode()wascomplete.ThismeantthatmyDecode()hadtocalltheoriginaldecode()function➊beforecallingthereportDecode()function,whichwouldgivetheresultsofthedecoding.Ultimately,myDecode()alsoneededtoreturnwiththesamevaluethattheoriginaldecode()functionwouldandcleanupthestack,andthefinalPOP➋andRETN➌instructionstookcareofthat.
PlacingtheHooksThenextproblemIranintowasthatthehookswereforcodeinsidethemoduleAdobeAIR.dll,whichwasnotthemainmoduleofthegame.Becauseofthecode’slocation,Ineededtofindthebaseaddressesforthehooksabitdifferently.Additionally,sinceIneededthesehookstoworkacrossafewdifferentversionsofAdobeAIR,Ialsohadtofindtherightaddressesforeachversion.InsteadoftryingtogetmyhandsonallofthedifferentversionsofAdobeAIR,Itookanotherpageoutofairlog’splaybookanddecidedtoprogrammaticallylocatetheaddressesbywritingasmallmemoryscanner.BeforeIcouldwritethememoryscanner,IneededboththebaseaddressandsizeofAdobeAIR.dllsoIcouldlimitmymemorysearchtoonlythatarea.
IfoundthesevaluesusingModule32First()andModule32Next()asfollows:
MODULEENTRY32entry;entry.dwSize=sizeof(MODULEENTRY32);HANDLEsnapshot=CreateToolhelp32Snapshot(TH32CS_SNAPMODULE,NULL);
DWORDbase,size;if(Module32First(snapshot,&entry)==TRUE){➊while(Module32Next(snapshot,&entry)==TRUE){std::wstringbinaryPath=entry.szModule;➋if(binaryPath.find("AdobeAIR.dll")!=std::wstring::npos){size=(DWORD)entry.modBaseSize;base=(DWORD)entry.modBaseAddr;break;}
![Page 237: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/237.jpg)
}}
CloseHandle(snapshot);
ThiscodeloopsthroughallmodulesintheprocessuntilitfindsAdobeAIR.dll➊.Whenitfindsthecorrectmoduleentry➋,itfetchesthemodBaseSizeandmodBaseAddrpropertiesfromitandbreaksoutimmediately.
ThenextstepwasfindingasequenceofbytesIcouldusetoidentifythefunctions.Idecidedtousethebytecodesurroundingeachcall.Ialsohadtomakesurethateachsequencewasuniquewhileavoidingtheuseofanyconstantsinthepatternstoensurethecode’sportability.Listing8-13showsthebytesequencesIendedupwith.
constcharencodeSeq[16]={0x8B,0xCE,//MOVECX,ESI0xE8,0xA6,0xFF,0xFF,0xFF,//CALLencode0x83,0xF8,0xFF,//CMPEAX,-10x74,0x16,//JESHORTendLoop0x03,0xF8,//ADDEDI,EAX0x3B,0xBE};//partofCMPEDI,[ESI+0x3C58]constchardecodeSeq[12]={0x8B,0xCE,//MOVECX,ESI0xE8,0x7F,0xF7,0xFF,0xFF,//CALLdecode0x83,0xF8,0xFF,//CMPEAX,-10x89,0x86};//partofMOV[ESI+0x1C54],EAX
Listing8-13:Theencode()anddecode()bytesequences
NoticetheCALLinstructionineachpattern;thesearethecallstotheAdobeAIRfunctionsInamedencode()anddecode().Iscannedforthesesequenceswiththefollowingfunction:
DWORDfindSequence(DWORDbase,DWORDsize,constchar*sequence,unsignedintseqLen){for(DWORDadr=base;adr<=base+size–seqLen;adr++){if(memcmp((LPVOID)sequence,(LPVOID)adr,seqLen)==0)returnadr;}return0;}
TreatingthememoryofAdobeAIR.dllasabytearray,thefindSequence()functionlooksforasequenceofbytesasasubsetofthatbytearrayand
![Page 238: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/238.jpg)
returnstheaddressofthefirstmatchitfinds.WiththefindSequence()functionwritten,findingtheaddressesIneededtohookencode()anddecode()wassimple.Here’showthosecallslooked:
DWORDencodeHookAt=findSequence(base,size,encodeSeq,16)+2;DWORDdecodeHookAt=findSequence(base,size,decodeSeq,12)+2;
Sinceeachtargetcallwas2bytesintoitsreceptivesearchsequence,allIhadtodowaslocateeachsequenceandadd2.Afterthat,thefinalstepwastoplacethehooksusingthemethoddescribedin“CallHooking”onpage153.
Withmyhookfinished,Icouldseeeverysinglepieceofdatathatwentbetweenthegame’sclientandserver.Moreover,sincetheRTMPSprotocolsendsserializedActionScriptobjects,thedatawasbasicallyself-documenting.Everysinglepieceofinformationwasaccompaniedbyavariablename.Everyvariableexistedasamemberofawell-describedobject.Everyobjecthadaconsistentname.LikeIsaid—itwasagoldmine.
ApplyingJumpHooksandVFHookstoDirect3DUnliketheAdobeAIRhookIjustdescribed,hooksforDirect3D(the3DgraphicscomponentofMicrosoft’sDirectXAPI)areverycommonandhighlydocumented.Direct3Disubiquitousintheworldofgaming:amajorityofPCgamesusethelibrary,whichmeansthathookingitgivesyouaverypowerfulmethodforinterceptingdataandmanipulatingthegraphicslayersofmanydifferentgames.YoucanuseaDirect3Dhookforanumberoftasks,suchasdetectinglocationsofhiddenenemyplayers,increasingthelightingofdarkin-gameenvironments,andseamlesslydisplayingadditionalgraphicalinformation.MakingeffectiveuseofaDirect3DhookrequiresyoutolearnabouttheAPI,butthere’smorethanenoughinformationinthisbooktogetyoustarted.
Inthissection,I’llgiveyouahigh-levelintroductiontoagameloopthatusesDirect3DbeforedivingrightintotheimplementationofaDirect3Dhook.RatherthandetailingtheinternalsandgivingyoutheanalyticalbackstoryasIdidwiththeAdobeAIRhook,I’llgooverthemostpopularDirect3Dhookmethod,asitiswelldocumentedandusedbythemajorityof
![Page 239: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/239.jpg)
Direct3Dhookmethod,asitiswelldocumentedandusedbythemajorityofgamehackers.
Theonlineresourcesforthisbookincludetwopiecesofexamplecodeforthissection;findthosefilesnowifyouwanttofollowalong.Thefirstpart,anexampleDirect3D9applicationforyoutohackon,canbefoundunderGameHackingExamples/Chapter8_Direct3DApplication.Thesecondpart,theactualhook,isunderChapter8_Direct3DHook.
TherearemultipleversionsofDirect3Dinuseatanygiventime,andtherearewaystohookeachone.Forthisbook,I’llfocusonhookingDirect3D9,becauseitistheonlycommonlyusedversionthatissupportedbyWindowsXP.
NOTE
EventhoughXPhasreachedendoflife,manypeopleinlessdevelopedcountriesstilluseitasaprimarygamingsystem.Direct3D9worksonallversionsofWindowsandisnearlyaspowerfulasitssuccessors,somanygamecompaniesstillprefertouseitovernewerversionsthatdon’thaveasmuchbackwardcompatibility.
TheDrawingLoopLet’sjumprightinwithacrashcourseonhowDirect3Dworks.InsideaDirect3Dgame’ssourcecode,you’llfindaninfiniteloopthatprocessesinputandrendersgraphics.Eachiterationinthisdrawingloopiscalledaframe.Ifwecutoutalltheextraneouscodeandfocussimplyonabareskeleton,wecanvisualizeagame’smainloopwiththefollowingcode:
intWINAPIWinMain(args){/*SomecodeherewouldbecalledtosetupDirect3Dandinitializethegame.Leavingitoutforbrevity.*/MSGmsg;while(TRUE){/*Somecodewouldbeheretohandleincomingmouseandkeyboardmessages.*/drawFrame();//thisisthefunctionwecareabout}/*Somecodeherewouldbecalledtocleanupeverythingbeforeexiting.*/}
![Page 240: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/240.jpg)
Thisfunctionistheentrypointofthegame.Simplyput,itinitializesthegameandthenentersthegame’smainloop.Insidethemainloop,itexecutescoderesponsibleforprocessinguserinputbeforecallingdrawFrame()toredrawthescreenusingDirect3D.(CheckoutthecodeinGameHackingExamples/Chapter8_Direct3DApplicationtoseeafullyfunctionalgameloop.)
Eachtimeitiscalled,thedrawFrame()functionredrawstheentirescreen.Thecodelookssomethinglikethis:
voiddrawFrame(){➊device->Clear(0,NULL,D3DCLEAR_TARGET,D3DCOLOR_XRGB(0,0,0),1.0f,0);device->BeginScene();//drawingwillhappenheredevice->EndScene();device->Present(NULL,NULL,NULL,NULL);}
Afterclearingthescreenwithdevice->Clear➊,thedrawFrame()functioncallsdevice->BeginScene()tounlockthescenefordrawing.Itthenexecutessomedrawingcode(whatthatdrawingcodeactuallydoesisn’timportantrightnow)andlocksthescenewithadevice->EndScene()call.Tofinishup,itrendersthescenetothescreenbycallingthedevice->Present()function.
Noticethatallofthesefunctionsarecalledasmembersofsomeinstancecalleddevice.ThisissimplyanobjectinstancerepresentingtheDirect3Ddevice,whichisusedtoinvokeallsortsofdrawingcalls.Also,noticethatthisfunctionisdevoidofanyactualdrawingcode,butthat’sokay.It’sreallyonlyimportantforyoutounderstandthehigh-levelconceptsofdrawingloops,frames,andtheDirect3Ddevice.Torecap,gameshaveamainloopwithtworesponsibilities:
•Handlingincomingmessages
•Drawingthegametothescreen
Eachiterationinthisloopiscalledaframe,andeachframeisdrawnbyadevice.Takingcontrolofthedevicegivesyouaccesstothemostsensitiveanddescriptivedetailsofthegame’sstate;thatis,you’llbeabletopeekintothegame’sstateafterthedatahasbeenparsed,processed,andrenderedtothescreen.Moreover,you’llbeabletomodifytheoutputofthisstate.These
![Page 241: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/241.jpg)
thescreen.Moreover,you’llbeabletomodifytheoutputofthisstate.Thesetwosuperpowersenableyoutopulloffallkindsofawesomehacks.
FindingtheDirect3DDeviceTotakecontrolofaDirect3Ddevice,youhookthememberfunctionsinthedevice’sVFtable.Unfortunately,however,usingtheDirect3DAPItoinstantiateyourowninstanceofthesamedeviceclassfrominjectedcodedoesn’tmeanyou’llshareaVFtablewiththegame’sinstance.Direct3DdevicesuseacustomizedruntimeimplementationofVFtables,andeachdevicegetsitsownuniqueVFtable.Additionally,devicessometimesrewritetheirownVFtables,removinganyhooksandrestoringtheoriginalfunctionaddresses.
BothoftheseDirect3Dquirksleaveyouwithoneinevitableoption:youmustfindtheaddressofthegame’sdeviceandmodifyitsVFtabledirectly.Here’show:
1. CreateaDirect3DdeviceandtraverseitsVFtabletolocatethetrueaddressofEndScene().
2. PlaceatemporaryjumphookonEndScene().
3. Whenthejumphookcallbackisexecuted,storetheaddressofthedevicethatwasusedtocallthefunction,removethehook,andrestoreexecutionnormally.
4. Fromthere,useVFhookstohookanymemberfunctionoftheDirect3Ddevice.
JumpHookingEndScene()SinceeverydevicewillcallEndScene()attheendofeachframe,youcanhookEndScene()usingajumphookandinterceptthegame’sdevicefromyourhookcallback.UniquedevicesmayhavetheirownuniqueVFtables,butthedifferenttablesstillpointtothesamefunctions,soyoucanfindtheaddressofEndScene()intheVFtableofanyarbitrarydevice.UsingstandardDirect3DAPIcalls,youcancreateyourowndevicelikethis:
LPDIRECT3D9pD3D=Direct3DCreate9(D3D_SDK_VERSION);if(!pD3D)return0;
![Page 242: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/242.jpg)
D3DPRESENT_PARAMETERSd3dpp;ZeroMemory(&d3dpp,sizeof(d3dpp));d3dpp.Windowed=TRUE;d3dpp.SwapEffect=D3DSWAPEFFECT_DISCARD;d3dpp.hDeviceWindow=hWnd;
LPDIRECT3DDEVICE9device;HRESULTres=pD3D->CreateDevice(D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL,hWnd,D3DCREATE_SOFTWARE_VERTEXPROCESSING,&d3dpp,&device);if(FAILED(res))return0;
ExplaininghoweverythinginDirect3Dworksisoutsidethescopeofthisbook,sojustknowthatyoucancopythiscodetocreateaDirect3DdevicethatcontainstheEndScene()functionasamember.TheEndScene()addressisatindex42intheVFtableofdevice(see“TheMeaningofDevice,Direct3D,andVFHooks”boxtolearnhowtofindthatindex),andyoucanreaditusingasubsetoftheVFtablehookingcodefrom“UsingaVFTableHook”onpage159,asfollows:
DWORDgetVF(DWORDclassInst,DWORDfuncIndex){DWORDVFTable=readMemory<DWORD>(classInst);DWORDhookAddress=VFTable+funcIndex*sizeof(DWORD);returnreadMemory<DWORD>(hookAddress);}DWORDEndSceneAddress=getVF((DWORD)device,42);
Onceyou’veobtainedtheaddress,yourdiscoverydevicehasserveditspurpose,anditcanbedestroyedwithacalltotheRelease()function:
pD3D->Release();device->Release();
WiththeaddressofEndScene()inhand,you’dbereadytostartthinkingabouthowtoplaceyourhookinmemory.Butsinceyoujusthaveafunctionaddress,youronlyoptionistoplaceajumphookatthetopofthefunction.
THEMEANINGOFDEVICE,DIRECT3D,ANDVF
![Page 243: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/243.jpg)
HOOKSIfyou’rewonderinghowIknowthattheindexoftheEndScene()functionis42,you’vecometotherightbox.SinceDirect3D9isafreelyavailablelibrary,youcanactuallyseequiteabitofwhatgoesonunderthehood.Themainheaderfileforthelibraryisd3d9.h.Ifyouopenthisfileinyoureditorandsearchfor“EndScene,”you’llendupinthemiddleofalargeclassdefinitionthatspecifiesseveralfunctionsusingCmacros.ThisisthebaseclassforallDirect3D9deviceimplementations,anditdefinesthevirtualfunctionsusedbytheclass.
TheVFtableisconstructedinthesameorderasthefunctionsaredefinedincode,soyoucandeterminetheindexofanymemberfunctionbysimplycountingthelines.Youcanscrolltothetopoftheclassdefinition(atline426inmyversionofthelibrary,andprobablyyourstoo),notethelinewherethefirstfunctionisdeclared(line429),andthenscrolltotheEndScene()definitionandnotethatline(line473).Finally,countthenumberofblankorcommentedlines(twoforme)anddosomemath:473–429–2=42.
Presto!TheEndScene()functionisthe43rdfunctiondeclared,soitsitsatthe42ndspotintheVFtable.Anotheradvantagetohavingthisheaderisthatyoucanseethename,argumenttypes,argumentnames,andreturntypeofeverysinglefunctioninthedeviceclass.Sowhenyou’rewritingyourownhooksinthefuture,you’llknowexactlywheretolook.
PlacingandRemovingtheJumpHookSinceyou’rejustusingthehooktofindthedevice,youneedtocallitonlyonce.Afterobtainingthedevice,you’llremovethejumphookandrestoreexecutionbacktothestartofEndScene()sothatthedrawingloopcancarryonitswork.Believeitornot,thismakesyourlifemucheasier.Sincethecodewillberestoredimmediately,there’snoneedforyourtrampolinetoexecutethecommandsthatarereplacedbythejump,andthere’snoneedtopadthejumpwithNOPs.Allyouneedtodoisstoretheoriginalbytesandplacethehook.Todoso,youuseaslightlytweakedversionofthejump-hookingcodefromListing8-11:
![Page 244: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/244.jpg)
unsignedchar*hookWithJump(DWORDhookAt,DWORDnewFunc){DWORDnewOffset=newFunc-hookAt-5;➊autooldProtection=protectMemory<BYTE[5]>(hookAt,PAGE_EXECUTE_READWRITE);unsignedchar*originals=newunsignedchar[5];for(inti=0;i<5;i++)➋originals[i]=readMemory<unsignedchar>(hookAt+i);➌writeMemory<BYTE>(hookAt,0xE9);writeMemory<DWORD>(hookAt+1,newOffset);protectMemory<BYTE[5]>(hookAt,oldProtection);returnoriginals;}
LikethefunctioninListing8-11,thisfunctionmakesthememorywritable➊,placesthehook➌,andrestoresthememoryprotection.Beforeplacingthehook,itallocatesa5-bytebuffercalledoriginals➋andfillsitwiththeoriginalbytes.Afterthehookisplaced,itreturnsoriginalstothecallingfunction.
Whenit’stimetoremovethehook,passoriginalstothefollowingfunction:
voidunhookWithJump(DWORDhookAt,unsignedchar*originals){autooldProtection=protectMemory<BYTE[5]>(hookAt,PAGE_EXECUTE_READWRITE);for(inti=0;i<5;i++)writeMemory<BYTE>(hookAt+i,originals[i]);protectMemory<BYTE[5]>(hookAt,oldProtection);delete[]originals;}
Thiscodesimplyiteratesoveroriginalsandquietlyplacesthose5bytesbackwheretheywerefoundsothateverythingisasexpectedwhenexecutionreturnstotheEndScene()function.Whenthetimecomes,youcanplaceandremoveyouractualhookusingtwolinesofcode,likethis:
autooriginals=hookWithJump(EndSceneAddress,(DWORD)&endSceneTrampoline);unhookWithJump(EndSceneAddress,originals);
OnceyouhavethehookWithJump()andunhookWithJump()functions,it’stimetopreparethecallbackandfindthedevice.
![Page 245: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/245.jpg)
WritingtheCallbackandTrampolineEventhoughyoucanobtaintheEndScene()addressfromaVFtable,theEndScene()functiondoesn’tactuallyfollowthe__thiscallconvention.Direct3DclassesaresimplewrappersaroundaCAPI,andallofthememberfunctioncallsareforwardedto__stdcallfunctionsthattakeaclassinstanceasafirstparameter.Thismeansthatyourtrampolineonlyneedstograbthedevicefromthestack,passittothecallback,andthenjumpbacktoEndScene().Thecallbackonlyhastoremovethejumphookbeforereturningtothetrampoline.
Thefinalcodeforthecallbackandtrampolinetothisjumphooklookssomethinglikethis:
LPDIRECT3DDEVICE9discoveredDevice;DWORD__stdcallreportInitEndScene(LPDIRECT3DDEVICE9device){discoveredDevice=device;unhookWithJump(EndSceneAddress,originals);returnEndSceneAddress;}__declspec(naked)voidendSceneTrampoline(){__asm{MOVEAX,DWORDPTRSS:[ESP+0x4]PUSHEAX//givethedevicetothecallback➊CALLreportInitEndSceneJMPEAX//jumptothestartofEndScene}}
UsingthehookWithJump()function,youcanplaceajumphookonEndScene()thatcallstheendSceneTrampoline()function.Whenthegame’sdevicecallstheEndScene()function,thetrampolinefunctioncallsthereportInitEndScene()function➊.ThereportInitEndScene()functionstoresthecaptureddevicepointertoaglobalvariablecalleddiscoveredDevice,removesthehookbycallingunhookWithJump(),andreturnstheaddressofEndScene()tothetrampoline.Tofinishup,thetrampolinejumpsdirectlytoEAX,whichwillbeholdingtheaddressthatwasreturnedfromthereportingfunction.
NOTE
![Page 246: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/246.jpg)
YoucanusejumphookstocompletelyskiptheVFtablehookingthatI’llshowyou,butit’sveryunreliabletouse“dumb”jumphooksoncommonlyhookedAPIfunctions.Consistentlyobtaininggoodresultswithonlyjumphooksrequiresprofessionalhookinglibraries,andI’dratherteachyouhowtodoitcompletelyonyourown.
Atthispoint,allthat’slefttodoishooktheVFtableofdiscoveredDevicetohackthegame.ThenexttwosectionswillwalkyouthroughhooksontheEndScene()andReset()functions,whicharerequiredifyouwantastablehook.
WritingaHookforEndScene()AhookonEndScene()isusefulbecauseitallowsyoutointerceptacompletedframejustbeforeitisrendered;youcaneffectivelyexecuteyourownrenderingcodeinsidethegameloop.Asyousawwhenlocatingthisfunction’saddressin“JumpHookingEndScene()”onpage178,thisfunctionisatindex42intheVFtable.YoucanhookEndScene()usingaVFhookasfollows:
typedefHRESULT(WINAPI*_endScene)(LPDIRECT3DDEVICE9pDevice);_endSceneorigEndScene=(_endScene)hookVF((DWORD)discoveredDevice,42,(DWORD)&myEndScene);HRESULTWINAPImyEndScene(LPDIRECT3DDEVICE9pDevice){//drawyourownstuffherereturnorigEndScene(pDevice);}
ThiscodeusesthehookVF()functionfrom“UsingaVFTableHook”onpage159tohookEndScene()atindex42ofdiscoveredDevice,usingmyEndScene()asthecallbackfunction.AdirectDirect3DdevicewilloccasionallyrepatchitsownVFtableandrestoretheoriginalfunctionaddresses.ThistypicallyhappensfromwithintheEndScene()function,meaningyoualsohavetorepatchtheVFtableaftercallingtheoriginalEndScene()function.Thereareafewchangesyoucanmaketothishooktohandlethat,asshowninListing8-14.
_endSceneorigEndScene=NULL;voidplaceHooks()
![Page 247: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/247.jpg)
{autoret=hookVF((DWORD)discoveredDevice,42,(DWORD)&myEndScene);if(ret!=(DWORD)&myEndScene)//don'tpointtoyourhookorigEndScene=(_endScene)ret;}placeHooks();
HRESULTWINAPImyEndScene(LPDIRECT3DDEVICE9pDevice){//drawyourownstuffhereautoret=origEndScene(pDevice);placeHooks();//updatehooksreturnret;}
Listing8-14:FinalcodetohookEndScene()
ThecodetoplacethehookhasbeenmovedintoafunctioncalledplaceHooks()soitcanbecalledmultipletimeswithease.Thecallbackfunctionstillforwardsthecalltotheoriginalfunction,butitmakessuretocallplaceHooks()beforereturning.Thisensuresthatthehookisalwaysactive,eveniftheoriginalEndScene()functionremovesit.
AnotherpointtonoticeisthatplaceHooks()updatestheaddressoforigEndScene()everytimethehookisreplaced,aslongastheaddressreturnedfromhookVF()isn’ttheaddressofthemyEndScene()function.Thisdoestwodistinctthings.First,itallowsotherapplicationstohookEndScene()withoutsteppingontheirtoes,sinceitwillupdateorigEndScene()towhateverisseenintheVFtable.Second,itmakessurethatthevalueoforigEndScene()canneverbetheaddressofourcallback,preventingapotentialinfiniteloop.Aninfiniteloopispossibleotherwise,becauseorigEndScene()doesn’talwaysfixthedevice’sVFtable,meaningplaceHooks()canbecalledwhentheVFtablestillcontainsthemyEndScene()function.
WritingaHookforReset()Whenyou’reusingaDirect3Dhookinproduction,you’llbedoingallkindsoftaskslikedrawingcustomtext,displayingimagesrelatedtoyourbot,andinteractingwithfunctioncallsfromthegame.ThesetaskswillrequireyoutocreateyourownDirect3Dobjectsthataretiedtothegame’sdevice,andthatcanbeaproblem.Fromtimetotime,thegamemaycompletelyresetitsdevicethroughaReset()function.Whenadeviceisreset,you’llneedto
![Page 248: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/248.jpg)
updateanyobjects(mostcommonlyfontsandsprites)thatyou’vecreatedforthedevice,usingtheirOnLostDevice()memberfunctions.
SinceReset()iscalledfromtheVFtableofthedevice,youcanuseahookonittotellyouwhenthedevicehasbeenreset.Reset()takestwoparametersandisatindex16intheVFtable.YoucanaddthiscodetoplaceHooks()inListing8-14tohooktheReset()function:
autoret=hookVF((DWORD)discoveredDevice,16,(DWORD)&myReset);if(ret!=(DWORD)&myReset)origReset=(_reset)ret;
AndthisisthedeclarationtousefororigReset:
typedefHRESULT(WINAPI*_reset)(LPDIRECT3DDEVICE9pDevice,D3DPRESENT_PARAMETERS*pPresentationParameters);_resetorigReset=NULL;
Whenaresetissuccessful,theoriginalfunctionreturnsD3D_OK.YourhookfunctionrecognizesthisandcallsOnLostDevice()accordingly:
HRESULTWINAPImyReset(LPDIRECT3DDEVICE9pDevice,D3DPRESENT_PARAMETERS*pPresentationParameters){autoresult=origReset(pDevice,pPresentationParameters);if(result==D3D_OK){//callonLostDevice()forallofyourobjects}returnresult;}
Onceyoufillinthecontentsoftheif()statement,allofyourobjectsarereadytouseagain.
What’sNext?NowthatI’veshownyouhowtotakecontrolofagame’sDirect3Ddevice,you’reprobablywonderingwhatyoucandowithit.Unliketheotherexamplesinthebook,thecodeinthissectionandtheexamplecodedon’thaveaone-to-onecorrelation,butthefunctionalityisstillthesame.Here’sahigh-levelviewofthecorrelationbetweenthischapterandthecodeintheChapter8_Direct3DHookexampleproject.
![Page 249: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/249.jpg)
ThefileDirectXHookCallbacks.hcontainsthecallbacksfortheEndScene()andReset()functions,twocallbacksforothercommonfunctions,andthetrampolineandreporterfunctionsforthetemporaryjumphook.Thesefunctionsareallprettymuchasdescribedinthischapter,excepttheycallintoasingletonclassdefinedinDirectXHook.handDirectXHook.cpp.Thissingletonclassisresponsibleforforwardingthecallstotheoriginalfunctions.
Theclassisalsoresponsibleforalloftheheavylifting,anditcontainsthecodetocreatethediscoverydevice,placethehooks,drawtext,handledeviceresets,anddisplayimages.Furthermore,itallowsexternalcodetoaddcustomcallbacksforeachhook,asyoucanseeinmain.cpp.Here,you’llseeanumberofdifferentcallbacksthataredrawingcustomtext,addingnewimagestothescreen,andchangingthetexturesofmodelsthataredrawnbythegame.Irecommendpokingaroundinthecodetogetabetterunderstandingofwhat’sgoingon,butdon’tgettoocarriedaway.We’lldiveintothiscodeinChapter9totalkaboutallthecoolhacksitcando.
OPTIONALFIXESFORSTABILITYTheReset()andEndScene()hooksdescribedinthischaptershouldworkwellforanygamerunningDirect3D9,butitisslightlyunstable.IfthegametriestoexecuteEndScene()whenthejumphookisplaced,itwillcrashbecausethebytesarebeingmodified.Therearetwowaystofixthis.First,youcanplacethejumphookfromwithinanIAThookonPeekMessage().ThiswillworkbecauseplacinganIAThookisathread-safeoperation,butitassumesthatPeekMessage()iscalledonlyfromthesamethreadthatdoestheDirect3Ddrawing.
Asafer,butmorecomplex,alternativeistoiterateovereverythreadinthegame(similartohowitworkedforthreadhijacking)anduseSuspendThread()topauseallthreadsinthegame(exceptfortheoneplacingthehook,ofcourse).Beforepausingathread,youmustmakesureitsEIPisnotexecutingthefirst5bytesofEndScene().Afterthehookisplaced,youmustuseResumeThread()torestoreexecutionwithyourhookinplace.
![Page 250: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/250.jpg)
ClosingThoughtsControlflowmanipulationisaveryimportantskillingamehacking,andalotofthehacksinthisbookrelyonit.Throughoutthenexttwochaptersyou’lllearnhowtocreatecommonhacksusingtheDirect3Dhook,andyou’llgetabetterideaofthegeneralusecasesofhooking.Evenifyoufeelalittleshaky,continuetoChapter9.ThecodeexamplestherecenterontheDirect3Dhookandwillgetyouevenmorefamiliarwithhookingtechniques.
![Page 251: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/251.jpg)
PART4CREATINGBOTS
![Page 252: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/252.jpg)
9USINGEXTRASENSORYPERCEPTIONTO
WARDOFFFOGOFWAR
Fogofwar(oftenshortenedtojustfog)isamechanismthatgamedeveloperscommonlyusetolimitaplayer’ssituationalawarenessandhideinformationaboutthegameenvironment.Fogisoftenaliterallackofsightinmassiveonlinebattlearena(MOBA)games,buttheconceptalsoincludesanylackorobscurityofpertinentgameplayinformation.Cloakedfigures,darkrooms,andenemieshidingbehindwallsareallformsoffog.
Gamehackerscanreduceorevencompletelyremovefogusinganextrasensoryperception(ESP)hack.AnESPhackuseshooking,memorymanipulation,orbothtoforceagametodisplayhiddeninformation.Thesehackstakeadvantageofthefactthatsometypesoffogareoftenimplementedontheclientside,asopposedtotheserverside,meaningthatthegameclientsstillcontaininformation(partialorcomplete)aboutwhatisbeinghidden.
Inthischapter,youwilllearnhowtoimplementdifferenttypesofESPhacks.First,you’lllearntolightupdarkenvironments.Next,you’llusex-rayvisiontoseethroughwalls.Finally,you’lllearnaboutzoomhacking,tweakingheads-updisplays,andothersimpleESPhacksthatcanrevealallsortsofuseful(butotherwisehidden)informationaboutthegameyou’replaying.
![Page 253: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/253.jpg)
BackgroundKnowledgeThischapterstartsthetransitionfromhacking,puppeteering,andreverseengineeringtocoding.Fromhereonout,you’llbelearninghowtoactuallycodeyourownhacks.Tokeepontopic,everythingI’vetalkedaboutthusfarwillbetreatedasbackgroundknowledge.Ifyouseeatechniqueusedthatyoudon’tquiteremember,suchasmemoryscanning,settingmemorybreakpoints,hooking,orwritingmemory,flipbacktotherelevantchaptersandstudythemabitmorebeforecontinuing.Throughoutthetext,you’llfindnotestoremindyouwhereyoucanbrushuponcertaintopics.
Specifically,thischapterwilltalkalotaboutDirect3D.In“ApplyingJumpHooksandVFHookstoDirect3D”onpage175,Iexplainedhowtohookintoagame’sDirect3Ddrawingloop.TheexamplecodeforthatchapterincludesafullyfeaturedDirect3DhookingengineinGameHackingExamples/Chapter8_Direct3DHook.Alotofthehacksinthischapterbuildonthathook,andtheirexamplecodecanbefoundinthemain.cppfileoftheDirect3Dhookcode.YoucanrunthecompiledapplicationfromGameHackingExamples/Chapter8_Direct3DApplicationtoseethehacksinactiononatestapplication.
RevealingHiddenDetailswithLighthacksLighthacksincreaselightingindarkenvironments,allowingyoutoclearlyseeenemies,treasurechests,pathways,andanythingelsethatisnormallyobscuredbydarkness.Lightingisoftenacosmeticchangethat’saddedatagame’sgraphicallayer,anditcanusuallybedirectlymodifiedwithahookonthegraphicslayer.
Optimallightingdependsoncameraorientation,environmentlayout,andevenspecifictraitsofagame’sengine,andyoucanmanipulateanyofthesefactorstocreatelighthacks.Buttheeasiestwayissimplytoaddmorelighttoaroom.
AddingaCentralAmbientLightSourceTheonlineresourcesforthisbookincludetwosmalllighthackexamples.ThefirstistheenableLightHackDirectional()functioninmain.cpp,whichis
![Page 254: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/254.jpg)
showninListing9-1.
voidenableLightHackDirectional(LPDIRECT3DDEVICE9pDevice){D3DLIGHT9light;ZeroMemory(&light,sizeof(light));light.Type=D3DLIGHT_DIRECTIONAL;light.Diffuse=D3DXCOLOR(0.5f,0.5f,0.5f,1.0f);light.Direction=D3DXVECTOR3(-1.0f,-0.5f,-1.0f);
pDevice->SetLight(0,&light);pDevice->LightEnable(0,TRUE);}Whenyouknowhowmuchexperienceyou
Listing9-1:Adirectionallighthack
ThiscodeiscalledfromtheEndScene()hook,anditaddslighttothescenebycreatingalightsourcecalledlight.Thecodesetslight.Typetodirectional,whichmeansthelightsourcewillactlikeaspotlightandprojectlightinaspecificdirection.Thecodethensetsthered,green,andbluevaluesoflight.Diffuseto0.5,0.5,and0.5,givingthelightanoff-whiteshinewhenreflectedfromasurface.Next,itsetslight.Directiontoanarbitrarypointinthethree-dimensionalspace.Finally,thecodeusesthegame’sDirect3Ddevicetosetupthelightatindex0andenablelightingeffects.
NOTE
Intheexampleapplication,thelightshinesupandtotherightfromthebottomleftofthescene.Youmayneedtochangethislocationdependingonhowyourtargetgameisrendered.
Notethatinsertingthelightatindex0worksforthisproofofconcept,butitwon’talwayswork.Gamestypicallyhavemultiplelightsourcesdefined,andsettingyourlightatanindexthegameusesmightoverridecriticallightingeffects.Inpractice,youmighttrysettingtheindextoanarbitrarilyhighnumber.There’sanissuewiththistypeoflighthack,though:directionallightswillbeblockedbyobjectssuchaswalls,creatures,andterrain,meaningshadowscanstillbecast.Directionallightsworkgreatforwide-openspaces,butnotsowellfortightlywoundcorridorsorundergroundcaves.
![Page 255: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/255.jpg)
IncreasingtheAbsoluteAmbientLightTheotherlighthackmethod,seenintheenableLightHackAmbient()function,isfarmoreaggressivethantheoneinListing9-1.Itaffectsthelightlevelglobally,ratherthanaddinganextralightsource.Here’swhatthecodelookslike:
voidenableLightHackAmbient(LPDIRECT3DDEVICE9pDevice){pDevice->SetRenderState(D3DRS_AMBIENT,D3DCOLOR_XRGB(100,100,100));}
Thislighthacksetstheabsoluteambientlight(whichyouindicatebypassingD3DRS_AMBIENTtotheSetRenderState()function)toamedium-strengthwhite.TheD3DCOLOR_XRGBmacrosetsthatstrength,taking100asitsparametersforthered,green,andbluelevels.Thislightsupobjectsusinganomnidirectionalwhitelight,effectivelyrevealingeverythingatthecostofshadowsandotherlighting-baseddetails.
CreatingOtherTypesofLighthacksTherearemanyotherwaystocreatelighthacks,buttheydifferfromgametogame.OnecreativewaytoaffectthelightinagameistoNOPthecodethatthegameusestocallthedevice->SetRenderState()function.Sincethisfunctionisusedtosetuptheglobalambientlightstrength,disablingcallstoitleavesDirect3Datthedefaultlightsettingsandmakeseverythingvisible.Thisisperhapsthemostpowerfultypeoflighthack,butitrequiresyourbottoknowtheaddressofthelightingcodetoNOP.
Therearealsomemory-basedlighthacks.Insomegames,playersandcreaturesemitlightofdifferentcolorsandstrengths,oftendependingonattributesliketheirequipment,mount,oractivespells.Ifyouunderstandthestructureofthegame’screaturelist,youcandirectlymodifythevaluesthatdetermineacreature’slightlevel.
Forinstance,imagineagameinwhichcharactersemitabluishballoflightwhenunderahealingorstrengtheningspell.Somewhereinthegame’smemoryarevaluesassociatedwitheachcreaturethattellthegamethecolorandintensityoflightthecreatureshouldemit.Ifyoucanlocatethesevaluesinmemory,youcanchangethemsothatthecreatureseffectivelyemitorbsoflight.Thistypeoflighthackiscommonlyusedingameswitha2Dtop-
![Page 256: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/256.jpg)
oflight.Thistypeoflighthackiscommonlyusedingameswitha2Dtop-downstyle,sincetheorbsaroundindividualcreaturesproduceacoolartisticeffectwhilesheddinglightonimportantpartsofthescreen.In3Dgames,however,thissortofhackjustturnscreaturesintoblobsoflightthatrunaround.
YoucanalsohooktheSetLight()memberfunctionatindex51intheVFtableofthegame’sDirect3Ddevice.Then,wheneveryourhookcallbackisinvoked,youcanmodifythepropertiesoftheinterceptedD3DLIGHT9lightstructurebeforepassingittotheoriginalfunction.Youmight,forinstance,changealllightstotheD3DLIGHT_POINTtype,causinganyexistinglightsourcesinthegametoradiatelightineverydirectionlikealightbulb.Thistypeoflighthackisverypowerfulandaccurate,butitcanproducesomedisturbingvisuals.Italsotendstobreakinanyenvironmentthathasnolighting,andopaqueobstaclesstillblockpointlightsources.
Lighthacksareverypowerful,buttheydon’trevealanything.Ifinformationishiddenbehindanobstacle,ratherthanbydarkness,you’llneedawallhacktorevealit.
RevealingSneakyEnemieswithWallhacksYoucanusewallhackstoshowenemiesthatarehiddenbywalls,floors,andotherobstacles.Thereareafewwaystocreatethesehacks,butthemostcommonmethodtakesadvantageofatypeofrenderingknownasz-buffering.
RenderingwithZ-BufferingMostgraphicsengines,includingDirect3D,supportz-buffering,whichisawaytomakesurethatwhenthereareoverlappingobjectsinascene,onlythetopobjectisdrawn.Z-bufferingworksby“drawing”thescenetoatwo-dimensionalarraythatdescribeshowclosetheobjectateachpixelonthescreenistotheviewer.Thinkofthearray’sindicesasaxes:theycorrespondtothex-axis(rightandleft)andy-axis(upanddown)foreachpixelonthescreen.Eachvaluestoredinthearrayisthez-axisvalueforapixel.
Whenanewobjectappears,whetheritisactuallydrawnonthescreenisdecidedbythez-bufferarray.Ifthespotattheobject’sx-andy-positionisalreadyfilledinthearray,thatmeansthere’sanotherobjectatthatpixelon
![Page 257: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/257.jpg)
alreadyfilledinthearray,thatmeansthere’sanotherobjectatthatpixelonthescreen.Thenewobjectwillappearonlyifithasalowerz-axisvalue(thatis,ifit’sclosertotheviewer)thanthepixelalreadythere.Whenthesceneisfinishedbeingdrawntothearray,itisflushedtothescreen.
Toillustratethis,imagineathree-dimensionalspacethatneedstobedrawntoatwo-dimensionalcanvasbysomegamewith4×4-pixelviewport.Thez-bufferforthisscenariowouldlooklikeFigure9-1.
Figure9-1:Anemptyz-buffer
Tostart,thegamedrawsabluebackgroundthatcompletelyfillstheviewportandislocatedasfarawayonthez-axisaspossible;let’ssaythehighestz-valueis100.Next,thegamedrawsa2×2-pixelredrectangleatposition(0,0)withaz-positionof5.Finally,thegamedrawsa2×2-pixelgreenrectangleatposition(1,1)withaz-positionof3.Thez-bufferwouldnowlooklikeFigure9-2.
![Page 258: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/258.jpg)
Figure9-2:Afilledz-buffer
Thez-bufferneatlyhandledoverlappingobjectsbasedontheirz-positions.Thegreensquarethat’sclosestonthez-axisoverlapstheredsquarethat’sabitfartheraway,andbothsquaresoverlapthebluebackground,whichisveryfaraway.
Thisbehaviorallowsagametodrawitsmap,players,creatures,details,andparticleswithoutworryingaboutwhatisactuallyvisibletotheplayer.Thisisahugeoptimizationforgamedevelopers,butitexposesalargeareaofattack.Sinceallgamemodelsarealwaysgiventothegraphicsengine,youcanusehookstodetectobjectsthattheplayercan’tactuallysee.
CreatingaDirect3DWallhackYoucancreatewallhacksthatmanipulatez-bufferinginDirect3DusingahookontheDrawIndexedPrimitive()function,whichiscalledwhenagamedrawsa3Dmodeltothescreen.Whenanenemyplayermodelisdrawn,a
![Page 259: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/259.jpg)
wallhackofthistypedisablesz-buffering,callstheoriginalfunctiontodrawthemodel,andthenreenablesz-buffering.Thiscausestheenemymodeltobedrawnontopofeverythingelseinthescene,regardlessofwhat’sinfrontofit.Somewallhackscanalsorenderspecificmodelsinasolidcolor,suchasredforenemiesandgreenforallies.
TogglingZ-BufferingTheDirect3Dhookinmain.cppfromGameHackingExamples/Chapter8_Direct3DHookhasthisexamplewallhackintheonDrawIndexedPrimitive()function:
voidonDrawIndexedPrimitive(DirectXHook*hook,LPDIRECT3DDEVICE9device,D3DPRIMITIVETYPEprimType,INTbaseVertexIndex,UINTminVertexIndex,UINTnumVertices,UINTstartIndex,UINTprimCount){if(numVertices==24&&primCount==12){//it'sanenemy,dothewallhack}}
ThisfunctionisusedasacallbackforahookonDrawIndexedPrimitive()atVFindex82ofthegame’sDirect3Ddevice.Everymodelthegamedrawspassesthroughthisfunction,accompaniedbysomemodel-specificproperties.Byinspectingasubsetoftheproperties,namelythenumVerticesandprimCountvalues,thehookdetectswhenanenemymodelisdrawnandcommencesthewallhack.Inthisexample,thevaluesrepresentinganenemymodelare24and12.
Themagichappensinsidetheif()statement.Usingjustafewlinesofcode,thewallhackdrawsthemodelinawaythatignoresz-buffering,likeso:
device->SetRenderState(D3DRS_ZENABLE,false);//disablez-bufferingDirectXHook::origDrawIndexedPrimitive(//drawmodeldevice,primType,baseVertexIndex,minVertexIndex,numVertices,startIndex,primCount);device->SetRenderState(D3DRS_ZENABLE,true);//enablez-buffering
Simplyput,thiscodedisablesz-bufferingwhendrawingtheenemymodelandreenablesitafterward.Withz-bufferingoff,theenemyisdrawninfrontofeverything.
![Page 260: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/260.jpg)
ChanginganEnemyTextureWhenamodelisrenderedonscreen,atextureisusedtoskinthemodel.Texturesare2Dimagesthatarestretchedaround3Dmodelstoapplythecolorsandpatternsthatmakeupthemodel’s3Dartwork.Tochangethewayanenemylookswhenit’sdrawninyourwallhack,youcansetittobedrawnwithadifferenttexture,asinthisexample:
//whenhookinitializesLPDIRECT3DTEXTURE9red;D3DXCreateTextureFromFile(device,"red.png",&red);//justbeforedrawingtheprimitivedevice->SetTexture(0,red);
Thefirstblockofthiscodeloadsthetexturefromafileandisexecutedonlyonce—whenthehookisinitialized.Thefullexamplecodedoesthisinaninitialize()function,whichgetscalledthefirsttimetheEndScene()hookcallbackisinvoked.ThesecondblockofthiscodehappensrightbeforethecalltotheoriginalDrawIndexedPrimitive()functioninthewallhack,anditcausesthemodeltobedrawnwiththecustomtexture.
FingerprintingtheModelYouWanttoRevealThetrickiestparttocreatingagoodwallhackisfindingtherightvaluesfornumVerticesandprimCount.Todothis,youcancreateatoolthatlogseveryuniquecombinationofthetwovariablesandallowsyoutoiterateoverthelistusingyourkeyboard.Workingexamplecodeforthistoolwon’tbeusefulintheexampleapplicationprovidedwiththischapter,butI’llgiveyousomehigh-levelimplementationdetails.
First,intheglobalscope,you’ddeclareastructurethathasmemberstostorethefollowing:
•numVerticesandprimCount
•Astd::setofthisstructure(let’scallitseenParams)
•Aninstanceofthatstructure(let’scallitcurrentParams)
Thestd::setrequiresacomparatorforthisstructure,soyou’dalsodeclareacomparisonfunctorthatcallsmemcmp()tocomparetwoofthestructuresusingmemcmp().EachtimetheDrawIndexedPrimitive()callbackis
![Page 261: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/261.jpg)
invoked,yourhackcouldcreateastructureinstancewiththeinterceptedvaluesandpassittoaseenParams.insert()function,whichshouldinserttheparameterpairintothelistonlyifthepairisn’talreadythere.
UsingtheGetAsyncKeyState()WindowsAPIfunction,youcouldthendetectwhenthespacebarispressedandexecutesomethingsimilartothispseudocode:
autocurrent=seenParams.find(currentParam);if(current==seenParams.end())current=seenParams.begin();elsecurrent++;currentParams=*current;
ThiswouldsetcurrentParamstothenextpairinseenParamswhenthespacebarispressed.Withthiscodeinplace,youcouldusecodesimilartoawallhacktochangethetextureofmodelsmatchingcurrentParams.numVerticesandcurrentParams.primCount.Thetoolcouldalsodrawthosevaluesonthescreensoyoucouldseethemandwritethemdown.
Withatoollikethis,findingthepropermodelsisaseasyasstartingupagameinamodewhereyourcharacterwon’tdie(againstafriend,inacustomizationmode,andsoon),runningthebot,andpressingthespacebaruntileachmodelyouneedishighlighted.Onceyouhavethevaluesforyourtargetmodels,you’llmodifythenumVerticesandprimCountcheckinyourwallhacksoitknowswhichmodelstohighlight.
NOTE
Charactermodelsarecommonlymadeupofsmallermodelsforindividualbodysegments,andgamesoftenshowdifferentmodelsofacharacteratdifferentdistances.Thatmeansagamemayhave20ormoremodelsforonetypeofcharacter.Eveninthatcase,selectingonlyonemodel(say,theenemy’storso)toshowinyourwallhackmaybeenough.
GettingaWiderFieldofVisionwithZoomhacksManygamesintheMOBAandreal-timestrategy(RTS)genresusea3Dtop-downstylethatmakesthemimmunetowallhacks.Theyalsousedarknessonthemapasatypeoffog,butshowingthedarkareasusinga
![Page 262: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/262.jpg)
darknessonthemapasatypeoffog,butshowingthedarkareasusingalighthackdoesn’tgiveanyextrainformation;modelshiddeninsidethefogareknownonlytothegameserver,nottotheclient.
ThisstylemakesmosttypesofESPhacksuseless:there’slittleunknowninformationtoreveal,sothesehacksonlyaugmentyourviewoftheinformationyoucanalreadysee.OnetypeofESPhack,however,canstillbehelpful.Zoomhacksletyouzoomoutmuchfartherthanagamenormallyallows,effectivelyrevealinglargeportionsofthemapthatyoucouldn’tseeotherwise—andthusgettingaroundthegame’swallhackandlighthackimmunity.
UsingNOPingZoomhacksMOBAandRTSgamestypicallyallowplayersavariablebutlimitedamountofzoom.Thesimplesttypeofzoomhackfindsthevalueofthezoomfactor(amultiplierthatchangesasthezoomlevelchanges,typicallyafloatordouble)andoverwritesitwithalargervalue.
Tofindthezoomfactor,fireupCheatEngineandsearchforafloatwithanunknowninitialvalue.(TobrushuponCheatEngine,headoverto“CheatEngine’sMemoryScanner”onpage5.)Forrescans,repeatthefollowingprocessuntilthereareonlyafewvalueslefttofindthezoomfactor:
1. Gotothegamewindowandzoomin.
2. SearchforanincreasedvalueinCheatEngine.
3. Gotothegamewindowandzoomout.
4. SearchforadecreasedvalueinCheatEngine.
Trytogetthevaluelistdowntooneoption.Toconfirmthattheremainingvalueisthezoomfactor,freezeitinCheatEngineandseehowzoombehavesin-game;freezingthepropervaluewilldisablezooming.Ifyoufailtofindthezoomfactorusingafloatsearch,retrythesearchusingadouble.Ifbothsearchesfail,trythemagainbutcorrespondzoominginwithdecreasedvaluesandzoomingoutwithincreasedvaluesinstead.Onceyou’vefoundthezoomfactorinmemory,youcanwriteasmallbottooverwriteittothezoomfactorthatbestsuitsyou.
![Page 263: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/263.jpg)
MoreadvancedzoomhacksNOPthegamecoderesponsibleformakingsurethezoomfactoriswithinasetrange.YoushouldbeabletofindthiscodewithOllyDbg.Setamemoryon-writebreakpointonthezoomfactor,zoomin-gametotriggerthebreakpoint,andinspectthecodeatthebreakpoint.(TohoneyourOllyDbgmemorybreakpointskills,flipto“ControllingOllyDbgThroughtheCommandLine”onpage43.)Youshouldseethecodethatmodifiedthezoomfactor.Zoomlimitationcodeistypicallyeasytospot:constantsthatmatchtheminimumandmaximumzoomvaluesareadeadgiveaway.
Ifyoucan’tfindthelimitationcodeusingthismethod,thenthelimitationmaybeappliedwhenthegraphicsareredrawnatanewzoomlevel,ratherthanwhenthezoomfactorchanges.Inthiscase,switchyourbreakpointtomemoryon-readandlookforthesameclues.
ScratchingtheSurfaceofHookingZoomhacksYoucanalsocreatezoomhacksbyusingaDirect3Dhookonthefunctiondevice->SetTransform(type,matrix),butthisrequiresadeepunderstandingofhowagamesetsuptheplayer’sperspective.Thereareafewdifferentwaystomanageperspective,butyoucontrolzoomlevelusingeitherview(transformtypeD3DTS_VIEW)orprojection(transformtypeD3DTS_PROJECTION).
Properlymanipulatingtransformmatricesthatcontrolviewandprojectionrequiressomeprettyextensiveknowledgeofthemathematicsbehind3Dgraphics,though,soIstayawayfromthismethodatallcosts—andI’veneverhadtroublesimplymanipulatingthezoomfactor.Ifyou’reinterestedinthiskindofhack,though,Irecommendreadinga3Dgameprogrammingbooktolearnmoreabout3Dmathematicsfirst.
Butsometimes,evenazoomhackisn’tenough.Someusefulinformationmayremainhiddenasapartofagame’sinternalstateormaysimplybehardforaplayertodetermineatamoment’sglance.Forthesesituations,aheads-updisplayisthetoolforthejob.
DisplayingHiddenDatawithHUDsAheads-updisplay(HUD)isatypeofESPhackthatdisplayscriticalgameinformationinanoverlay.HUDsoftenresembleagame’sexistinginterface
![Page 264: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/264.jpg)
fordisplayinginformationlikeyourremainingammunition,amini-map,yourcurrenthealthlevel,anyactiveabilitycooldowns,andsoon.HUDstypicallydisplayeitherhistoricaloraggregatedinformation,andthey’remostlyusedonMMORPGs.Theyareoftentextbased,butsomealsocontainsprites,shapes,andothersmallvisualeffects.
TheHUDsyoucancreatedependonwhatdataisavailableinthegame.Commondatapointsarethese:
•Experiencegainperhour(exp/h)
•Creaturekillsperhour(KPH)
•Damagepersecond(DPS)
•Goldlootedperhour(GPH)
•Healingperminute
•Estimatedtimeuntilnextlevel
•Amountofgoldspentonsupplies
•Overallgoldvalueofitemslooted
MoreadvancedcustomHUDsmaydisplaylargetablescontainingitemslooted,suppliesused,thenumberofkillsforeachtypeofcreature,andthenamesofplayersthathaverecentlybeenseen.
Beyondwhatyou’vealreadylearnedaboutreadingmemory,hookinggraphicsengines,anddisplayingcustomizeddata,there’snotmuchelseIcanteachyouabouthowtocreateaHUD.Mostgameshaveasimpleenougharchitecturethatyoucaneasilyobtainmostoftheinformationyouneedfrommemory.Then,youcanrunsomebasichourly,percentage,orsummationcalculationstogetthedataintoausableformat.
CreatinganExperienceHUDImagineyouwantaHUDthatdisplaysyourcurrentlevel,hourlyexperience,andhowlongyou’llhavetoplaybeforeyourcharacterlevelsup.First,youcoulduseCheatEnginetofindthevariablesthatcontainyourlevelandexperience.Whenyouknowthosevalues,youcanuseeitheragame-specificalgorithmorahardcodedexperiencetabletocalculatetheexperiencerequiredtoreachthenextlevel.
![Page 265: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/265.jpg)
Whenyouknowhowmuchexperienceyouneedtolevelup,youcancalculateyourhourlyexperience.Putintopseudocode,thatprocessmightlooklikethis:
//thisexampleassumesthetimeisstoredinmilliseconds//forseconds,removethe"1000*"timeUnitsPerHour=1000*60*60timePassed=(currentTime-startTime)➊timePassedToHourRatio=timeUnitsPerHour/timePassed➋expGained=(currentExp-startExp)hourlyExp=expGained*timePassedToHourRatio
➌remainingExp=nextExp-currentExp➍hoursToGo=remainingExp/hourlyExp
Tofindyourhourlyexperience,hourlyExp,you’dstoreyourexperienceandthetimewhenyourHUDfirststarts;thesearestartExpandstartTime,respectively.ThisexamplealsoassumescurrentLevelandcurrentExparepreviouslydefined,wherecurrentLevelisthecharacter’slevelandcurrentExpisthecurrentamountofexperience.
Withthesevalues,hourlyExpcanbecalculatedbymultiplyingaratio➊ofthetimeunitsinanhourtothetimethathaspassedbytheexperiencegainedsincestartTime➋.Inthiscase,thetimeunitisamillisecond,sothetimeunitsgetmultipliedby1,000.
Next,currentExpissubtractedfromnextExptodeterminetheremainingexperience➌tolevelup.Tocalculatehowmanyhoursarelefttolevelup,yourremainingexperienceisdividedbyyourhourlyexperience➍.
Whenyouhaveallthisinformation,youcanfinallydisplayitonscreen.UsingtheDirect3Dhookingengineprovidedinthisbook’sexamplecode,you’ddrawthetextusingthiscallinsidetheEndScene()hookcallback:
hook->drawText(10,10,D3DCOLOR_ARGB(255,255,0,0),"Willreachlevel%din%0.20fhours(%dexpperhour)",currentLevel,hoursToGo,hourlyExp);
That’sallyouneedforaworking,experience-trackingHUD.VariationsofthesesameequationscanbeusedtocalculateKPH,DPS,GPH,andotherusefultime-basedmeasures.Furthermore,youcanusethedrawText()
![Page 266: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/266.jpg)
functionoftheDirect3Dhooktodisplayanyinformationyoucanlocateandnormalize.ThehookalsocontainsaddSpriteImage()anddrawSpriteImage()functionsthatyoucanusetodrawyourowncustomimages,allowingyoutomakeyourHUDsasfancyasyouwant.
UsingHookstoLocateDataMemoryreadingisn’ttheonlywaytogetdataforacustomHUD.YoucanalsogatherinformationbycountingthenumberoftimesaspecificmodelisdrawnbytheDrawIndexedPrimitive()function,hookingthegame’sinternalfunctionsresponsiblefordrawingcertaintypesoftext,oreveninterceptingfunctioncallsresponsibleforprocessingdatapacketsfromthegameserver.Themethodsyouusetodothiswillbedrasticallydifferentforeverygame,andfindingthosemethodswillrequireyoutopaireverythingyou’velearnedfromthisbookwithyourowningenuityandprogramminginstincts.
Forinstance,tocreateaHUDthatdisplayshowmanyenemiesareonthemap,youcouldusethemodel-fingerprintingmethodsusedbywallhackstocountthenumberofenemiesandoutputthatnumbertothescreen.Thismethodisbetterthancreatingawaytoreadthelistofenemiesfrommemory,sinceitdoesn’trequirenewmemoryaddresseseverytimethegamepatches.
Anotherexampleisdisplayingalistofenemycooldowns,whichwouldrequireyoutointerceptincomingpacketsthattelltheclientwhichspelleffectstodisplay.Youcouldthencorrelatecertainspellswithcertainenemiesbasedonspellandenemylocation,spelltype,andsoon,andusethatinformationtotrackspellseachenemyhasused.Ifyoucorrelatethedatawithadatabaseofcooldowntimes,youcandisplayexactlywheneachenemyspellcanbeusedagain.Thisisespeciallypowerfulbecausemostgamesdon’tstoreenemycooldownsinmemory.
AnOverviewofOtherESPHacksInadditiontothehacksdiscussedinthischapter,thereareanumberofESPhacksthatdon’thavecommonnamesandarespecifictocertaingenresorevencertaingames.I’llquicklytakeyouthroughthetheory,background,andarchitectureofsomeofthesehacks.
![Page 267: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/267.jpg)
RangeHacksRange hacks use a method similar to wallhacks to detect when themodelsfordifferenttypesofchampionsorheroesaredrawn.Thentheydrawcirclesonthegroundaroundeachheromodel.Theradiusofeachcirclecorrespondstothemaximumattackrangeofthechampionorheroitsurrounds,effectivelyshowingyouareaswhereyoucanbedamagedbyeachenemy.
Loading-ScreenHUDsLoading-screen HUDs are common in MOBA and RTS games thatrequireallplayerstositthroughaloadingscreenwhileeveryone’sgameis starting up.These hacks take advantage of the fact that such gamesoftenhavewebsiteswherehistoricalplayerstatisticscanbequeried.Youcanwriteabotthatautomaticallyqueriesthestatisticsofeachplayerinthegameandseamlesslydisplaysthe informationasanoverlayonyourloadingscreen,allowingyoutostudyyourenemiesbeforelaunchingintobattle.
Pick-PhaseHUDsPick-phaseHUDs are similar to their loading-screen cousins, but theyare displayed during the pregame phase when each player is picking achampion or hero to play. Instead of showing enemy statistics, pick-phase HUDs show statistics about allies. This allows you to quicklyassessthestrengthsandweaknessesofyouralliessoyoucanmakebetterdecisionsaboutwhichcharactertoplay.
FloorSpyHacksFloor spy hacks are common in older 2D top-down games that havedifferent distinct floors or platforms. If you’re on the top floor, youmightwanttoknowwhat’sgoingondownstairsbeforeyougochargingin. You can write floor spy hacks that modify the current floor value(typically an unsigned int) to a different floor above or below you,allowingyoutospyonotherfloors.
Gamesoftenrecalculatethecurrentfloorvalueeveryframebasedonplayerposition,soNOPsaresometimesrequiredtokeepthevaluefrombeingreseteverytimeaframeisredrawn.FindingthecurrentfloorvalueandthecodetoNOPwouldbesimilartofindingthezoomfactor,as
![Page 268: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/268.jpg)
discussedin“UsingNOPingZoomhacks”onpage197.
ClosingThoughtsESPhacksarepowerfulwaystoobtainextrainformationaboutagame.SomeofthemcanbedoneprettyeasilythroughDirect3Dhooksorsimplememoryediting.Othersrequireyoutolearnaboutagame’sinternaldatastructuresandhookproprietaryfunctions,givingyouareasontoemployyourreverseengineeringskills.
IfyouwanttoexperimentwithESPhacks,studyandtweaktheexamplecodeforthischapter.ForpracticewithmorespecificESPhacks,Iencourageyoutogooutandfindsomegamestoplayaroundwith.
![Page 269: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/269.jpg)
10RESPONSIVEHACKS
Theaveragegamerhasareactiontimeof250milliseconds,oraquarterofasecond.Professionalgamersaverageafifthofasecond,butsomecanreactinasixthofasecond.Thesefiguresarebasedononlineteststhatmeasureplayers’reactiontimestosingular,predictableevents.Inactualgames,though,playersmustreacttodozensofdifferentevents,likehealthloss,incomingskillshots,abilitiescomingoffofcooldown,enemyattacks,andmanyothers.Onlyveryskilledgamerscanmaintainafourth-orfifth-of-a-secondreactiontimeinsuchdynamicenvironments;theonlywaytobefasteristobeacomputer.
Inthischapter,you’lllearnhowtomakebotsthatreactfasterthananyplayer.First,I’llshowyousomecodepatternsyoucanincorporateintoabottodetectwhencertaineventshappenwithinagame.Next,you’lllearnhowtomakeabotthatmovesyourcharacter,heals,orcastsspellsallonitsown.Onceyou’veexploredthosefundamentaltechniques,I’llhelpyoutiethemtogethertoimplementsomeofthemostcommon,andmostpowerful,responsivehacks.
ObservingGameEventsWithinjustafewsecondsofplayingagame,mostpeoplecanmakeessentialobservationsaboutthegameenvironment.Youcanclearlyseewhenmissilesareflyingtowardyourcharacter,whenyourhealthistoolow,andwhen
![Page 270: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/270.jpg)
areflyingtowardyourcharacter,whenyourhealthistoolow,andwhenabilitiescomeoffofcooldown.Forabot,though,theseseeminglyintuitiveobservationsarenotaseasytomake.Thebotmustdetecteacheventbylookingforchangesinmemory,detectingvisualcues,orinterceptingnetworktraffic.
MonitoringMemoryTodetectsimpleevents,suchasyourhealthbardroppinglow,youcanprogramabottoperiodicallyreadyourhealthfrommemoryandcompareittosomeminimumacceptablevalue,asinListing10-1.
//dothisevery10milliseconds(100timesasecond)autohealth=readMemory<int>(HEALTH_ADDRESS);if(health<=500){//somecodetotellthebothowtoreact}
Listing10-1:Anifstatementthatcheckshealth
Giventheaddressofyourcharacter’shealth,youcancheckthevaluethereasoftenasyouneed;every10millisecondsistypicallyagoodrate.(FlipbacktoChapter1ifyouneedarefresheronlocatingvaluesinmemory.)Oncehealthdropsbelowacertainvalue,you’llwanttorunsomereactioncodetocastahealingspellordrinkapotion.I’lltalkabouthowyoucandothislaterinthechapter.
Ifyouwantyourbottohavemoregranularinformationandthechanceforagreatervarietyofresponses,youcanprogramittoreacttoanychangeinhealth,insteadofonlyafterasetthreshold.Todoso,changethecodeinListing10-1tocompareyourcurrenthealthtotheamountyouhadduringthepreviousexecution,asfollows:
//stilldothisevery10millisecondsstaticintpreviousHealth=0;autohealth=readMemory<int>(HEALTH_ADDRESS);if(health!=previousHealth){if(health>previousHealth){//reacttoincrease}else{//reacttodecrease}previousHealth=health;}
![Page 271: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/271.jpg)
Now,thiscodeusesastaticvariablecalledpreviousHealthtotrackthevalueofhealthonthepreviousiteration.IfpreviousHealthandhealthdiffer,thebotnotonlyreactstothechangeinhealthbutalsoreactsdifferentlytohealthincreasesanddecreases.Thistechniqueisthesimplest,andmostcommon,waytoreacttochangesinagamestate.Withthepropermemoryaddresses,youcanusethiscodepatterntoobservechangesinhealth,mana,abilitycooldowns,andothercriticalinformation.
DetectingVisualCuesHealthisrelativelysimpleforabottocheckbecauseit’sjustanumber,butsomegameelementshavetoberelayedtothebotdifferently.Forexample,whenstatusailmentsorbuffsareaffectingacharacter,theeasiestwayforyoutotellistosimplylookforanonscreenstatusindicator,andthesameistrueforbots.
Whenreadingmemoryisn’tenough,youcandetectcertaineventsbyhookingagame’sgraphicsengineandwaitingforthegametorenderaspecificmodel.(Referbackto“ApplyingJumpHooksandVFHookstoDirect3D”onpage175and“CreatingaDirect3DWallhack”onpage194togetrefreshedonDirect3Dhooks.)Whenthemodelisdrawn,youcanqueueupareactiontobeexecutedaftertheframeisdrawn,likethis:
//belowisthedrawIndexedPrimitivehookvoidonDrawIndexedPrimitive(...){if(numVertices==EVENT_VERT&&primCount==EVENT_PRIM){//react,preferablyafterdrawingisdone}}
Usingthesamemodel-fingerprintingtrickasthewallhackcodeinChapter9,thiscodedetectswhenaspecificmodelisdrawntothescreenandreactsaccordingly.Thiscodereactstotheeventeverysingleframe,though,andthatcanmakeyourgameunplayable.You’llprobablywantsomeinternalcooldowntoavoidspammingareaction.Incaseswheretheindicatormodelispersistentlydrawn(thatis,notblinking),youcanactuallytrackitacrossframestodeterminewhenitappearsanddisappears.
Here’sacodesnippetthatalsohandlestracking:
booleventActive=false;booleventActiveLastFrame=false;
![Page 272: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/272.jpg)
//belowisthedrawIndexedPrimitivehookvoidonDrawIndexedPrimitive(...){if(numVertices==EVENT_VERT&&primCount==EVENT_PRIM)eventActive=true;}
//belowistheendScenehookvoidonDrawFrame(...){if(eventActive){if(!eventActiveLastFrame){//reacttoeventmodelappear}eventActiveLastFrame=true;}else{if(eventActiveLastFrame){//reacttoeventmodeldisappear}eventActiveLastFrame=false;}eventActive=false;}
TheonDrawIndexedPrimitive()functionstillcheckswhetheracertainmodelwasdrawn,butnow,twoBooleanstrackwhetherthemodelwasdrawnthisframeorthepreviousframe.Then,whentheframeiscompletelydrawn,thebotcancheckthesevariablesandreacttothemodeleitherappearingordisappearing.
Thismethodworksgreatfordetectingvisualstatusindicatorsthatappearonlywhenyourcharacterisaffectedbystuns,movementslows,snares,poisons,andsoon.YoucanalsouseittodetectwhenenemiesappearanddisappearinMOBAandRTSgames,asthesegamesdrawonlyenemiesthatareexplicitlyinthesightrangeofanalliedunitorplayer.
InterceptingNetworkTrafficOneofthemostreliablewaystoobserveeventsisthesamewaythegameclientdoes:bywaitingforthegameservertotellyouthattheyoccurred.Inthistypeofcommunication,thegameserversendsbytearrayscalledpacketsoverthenetworktotheclient,usingsockets.Thepacketsaretypicallyencryptedandcontainblobsofdataserializedthroughaproprietaryformat.
ATypicalPacket-ParsingFunctionToreceiveandprocesspackets,agameclientdoessomethinglikeListing
![Page 273: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/273.jpg)
10-2beforeitdrawsaframe.
voidparseNextPacket(){if(!network->packetReady())return;
autopacket=network->getPacket();autodata=packet->decrypt();switch(data->getType()){casePACKET_HEALTH_CHANGE:onHealthChange(data->getMessage());break;casePACKET_MANA_CHANGE:onManaChange(data->getMessage());break;//morecasesformorepackettypes}}
Listing10-2:Asimplifiedlookathowagameparsespackets
Theexactcodeforanyparticulargamemightlookdifferent,butthecontrolflowisalwaysthesame:receiveapacket,decryptit,decidewhatkindofmessageitcontains,andcallafunctionthatknowswhattodowithit.Somegamehackersinterceptrawnetworkpacketsandreplicatethisfunctionalityintheirbots.Thistechniqueworks,butitrequiresextensiveknowledgeofencryption,acompleteunderstandingofhowthegamestoresdatainsideapacket,theabilitytoman-in-the-middlethenetworkconnection,andawaytolocatethedecryptionkeysbeingusedbythegameclient.
Hookingthefunctionsresponsibleforhandlingthepacketsaftertheyaredecryptedandparsedisamuchbetterapproach;inListing10-2,thosefunctionsaretheonHealthChange()andonManaChange()functions.Thismethodleveragesthegame’sinherentabilitytoprocesspackets,allowingabottoremainignorantofthevariousnetworkfacilitiesthegameuses.Italsogivesyoudiscretionoverwhichnetworkdatayouintercept,asyouneedtohookonlythehandlersthatmeetyourneeds.
NOTE
Interceptingentirepacketscansometimesbeadvantageous—forexample,inanygamethatusesAdobeAIRandcommunicatesusingRTMPS.SinceRTMPSissoheavilydocumented,there’snoneedtoreverseengineertheformatorencryption.Chapter8explainshowtohookRTMPSindetail.
![Page 274: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/274.jpg)
Thereareafewtricksyoucanusetoeasilyfindtheparserfunctionand,ultimately,theswitch()statementthatdispatchespacketstotheirhandlers.ThemostusefulmethodI’vefoundistoplaceabreakpointonthefunctionthegameusestoreceivedatafromthenetwork,andthenanalyzetheflowoftheapplicationwhenthebreakpointishit.
Let’swalkthroughhowyoumightdothiswithOllyDbgattachedtoyourtargetgame.InWindows,recv()istheAPIfunctiontoreceivedatafromasocket.FromtheOllyDbgcommandline,youcansetabreakpointonrecv()byenteringthebprecvcommand.Whenthebreakpointishit,youcanclimbthecallstackusingCTRL-F9,theshortcutforexecuteuntilreturn,andF8,theshortcutforstepover.Thiscombinationessentiallyletstheprogramexecuteuntilthecalleehasreturnedtothecaller,allowingyoutoclimbthecallstackintandemwiththegame.Ateachstacklevel,youcaninspectthecodeofeachcalleruntilyoufindonethathasabigswitch()statement;thisshouldbethepacketparser.
ATrickierParserDependingonthegame’sarchitecture,though,findingtheparserfunctionmaynotbethatsimple.Consideragamewithaparserfunctionthatlookslikethis:
packetHandlers[PACKET_HEALTH_CHANGE]=onHealthChange;packetHandlers[PACKET_MANA_CHANGE]=onManaChange;
voidparseNextPacket(){if(!network->packetReady())return;autopacket=network->getPacket();autodata=packet->decrypt();autohandler=packetHandlers[data->getType()];handler->invoke(data->getMessage());}
SincetheparseNextPacket()functiondoesn’thaveaswitch()statement,there’snoobviouswaytoidentifyitinmemory.Unlessyoupayverycloseattention,you’lllikelyclimbrightpastitonthecallstack.Whenagamehasaparserfunctionlikethis,tryingtofigureoutwhattheparserfunctionlookslikemightbepointless.Ifyoudon’tseeaswitch()statementwhenclimbing
![Page 275: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/275.jpg)
therecv()callstack,you’llhavetonoteeverycalleeonthecallstackinstead.Insteadofclimbingupthecallstackfromthebreakpoint,you’dgoto
everyaddressmarkedasaRETURNbelowESPintheOllyDbgstackpane.Thesearethereturnaddressesintoeachcallerforeachcallee.Ateachreturnaddress,you’dneedtofindthetopofthecallerinOllyDbg’sdisassemblypaneandnotetheaddress.Asaresult,you’dhavealistofeveryfunctioncallleadinguptotherecv()call.
Next,you’drepeatthesamelist-makingprocessfrombreakpointsplacedonafewofthegame’shandlerfunctions.Youcanfindahandlerfunctionbymonitoringmemorythatitwillinevitablyuse.Thehandlerforahealthchangepacket,forinstance,willupdateyourhealthinmemory.UsingOllyDbg,youcansetamemoryonwritebreakpointtothehealthaddress.Whenthebreakpointgetstriggered,itmeansthegameupdatedthehealthvaluefromahandlerfunction.Thisshouldworkthesamewayformostvaluesthatarecontrolledbytheserver.Theserverwillcontrolanygame-criticalvalues,suchashealth,mana,level,items,andsoon.
Onceyou’verecordedthecallstackfromrecv()andafewhandlerfunctions,youcancorrelatethemtolocatetheparserfunction.Forexample,considerthethreepseudo–callstacksinTable10-1.
Table10-1:Pseudo–CallStacksforThreePacket-RelatedFunctions
recv()stack onHealthChange()stackonManaChange()stack
0x0BADF00D 0x101E1337 0x14141414
0x40404040 0x50505050 0x60606060
0xDEADBEEF0xDEADBEEF 0xDEADBEEF
0x30303030 0x30303030 0x30303030
0x20202020 0x20202020 0x20202020
0x10101010 0x10101010 0x10101010
Thesestacksshowwhatmemorymightlooklikeduringacalltorecv()andtoagame’shypotheticalonHealthChange()andonManaChange()functions.Noticethateachfunctionoriginatesfromachainoffourcommonfunctioncalls(showninboldface).Thedeepestcommonaddress,0xDEADBEEF,istheaddressoftheparser.Forabetterunderstandingofthisstructure,lookat
![Page 276: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/276.jpg)
thecallstackslaidoutinatreeview,asinFigure10-1.
Figure10-1:Treeviewofourthreecallstacks
Eachfunction’scallstackbranchesoutfromthefunctionat0xDEADBEEF,meaningthatfunctionisacommonpointoforiginforallthreecalls.TheexampleparseNextPacket()functionisresponsibleforcallingthesefunctions,soitmustbethemostrecentcommonancestorat0xDEADBEEF.
NOTE
Thesecallstacksarehypothetical,andthey’resimplifiedbeyondwhatyou’lltypicallyencounter.Realcallstackswillprobablyhavequiteafewmorefunctioncalls,andcomparingthemwon’tbeaseasy.
AHybridParsingSystemAthirdvariationoftheparsingloopmightbeahybridoftheprevioustwothatusesaswitch()statementafterafunctioncall.Here’sanotherhypotheticalfunction:
voidprocessNextPacket(){if(!network->packetReady())return;autopacket=network->getPacket();
![Page 277: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/277.jpg)
autodata=packet->decrypt();dispatchPacket(data);}
voiddispatchPacket(data){switch(data->getType()){casePACKET_HEALTH_CHANGE:processHealthChangePacket(data->getMessage());break;casePACKET_MANA_CHANGE:processManaChangePacket(data->getMessage());break;//morecasesformoredatatypes}}
TheprocessNextPacket()functionfetchesanewpacketandcallsdispatchPacket()tohandlethedata.Inthiscase,thedispatchPacket()functionexistsinthecallstackofeachhandler,butnotintheonefortherecv()function.LookatthehypotheticalstacksinTable10-2,forexample.
Table10-2:Pseudo–CallStacksforThreePacket-RelatedFunctions
recv()stack onHealthChange()stackonManaChange()stack
0x0BADF00D 0x101E1337 0x14141414
0x40404040 0x00ABCDEF 0x00ABCDEF
0xDEADBEEF0xDEADBEEF 0xDEADBEEF
0x30303030 0x30303030 0x30303030
0x20202020 0x20202020 0x20202020
0x10101010 0x10101010 0x10101010
Althoughthesethreefunctionshavethesamefirstfouraddressesintheircallstacks,onlythetwohandlershaveonemoreaddressincommon(againshowninboldface).That’s0x00ABCDEF,andit’stheaddressofthedispatchPacket()function.Onceagain,youcanimaginetheselaidoutinatreeview,asinFigure10-2.
![Page 278: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/278.jpg)
Figure10-2:Treeviewofourthreecallstacks
AParserHackOnceyou’velocatedthefunctionresponsiblefordispatchingpacketstotheirhandlers,you’llbeabletospoteveryhandlerthatcanbecalled.Youcandeduceahandler’spurposebyplacingabreakpointonitandwatchingwhatvalueschangeinmemorywhenitexecutes.Then,youcanhookanyhandlersthatyourbotneedstoreactto.(FlipbacktoChapter8ifyouneedarefresheronhowyoumighthookthesefunctions.)
Ofcourse,thereareendlesswaystoimplementnetworkbehavior.Ican’tcoverthemall,butseeingthesethreecommontechniquesshouldhelpyouunderstandthemethodology.Nomatterwhatgameyou’redealingwith,abreakpointonrecv()shouldbeastepintherightdirection.
PerformingIn-GameActionsBeforeabotcanreacttoevents,youhavetoteachittoplaythegame.Itneedstobeabletocastspells,movearound,andactivateitems.Onthisfront,botsaren’tmuchdifferentfrompeople:theycanjustbetoldwhichbuttonstopress.Pressingbuttonsissimpleandsufficesinmanycases,butinmoreintricatesituations,abotmayhavetocommunicateonthenetworkandtelltheserverwhatit’stryingtodo.
Tofollowalongwiththeexamplesinthissectionandexploreonyourownafterward,openthefilesintheGameHackingExamples/Chapter10_
![Page 279: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/279.jpg)
ResponsiveHacks/folderinthisbook’sresourcefiles.
EmulatingtheKeyboardThemostcommonbuttonsyou’llpressinagamearekeyboardkeys,andthereareacoupleofwaysyoucanteachyourbottotype.
TheSendInput()FunctionOnecommonwaytoemulatethekeyboardiswiththeSendInput()WindowsAPIfunction.Thisfunction,whichsendskeyboardandmouseinputtothetopmostwindow,hasthefollowingprototype:
UINTSendInput(UINTinputCount,LPINPUTinputs,intsize);
Thefirstparameter,inputCount,isthenumberofinputsbeingsent.Fortheexamplesinthisbook,I’llalwaysuseavalueof1.Thesecondparameter,inputs,isapointertoastructure(oranarrayofstructureswhoselengthmatchestheinputCountvalue)withthepredefinedtypeINPUT.Thefinalparameteristhesizeofinputsinmemory,ascalculatedwiththeformulasize=inputCount×sizeof(INPUT).
TheINPUTstructuretellstheSendInput()functionwhattypeofinputtosend,andthefollowingcodeshowshowyoumightinitializeaninstanceofINPUTtopresstheF1key:
INPUTinput={0};input.type=INPUT_KEYBOARD;input.ki.wVk=VK_F1;
TohaveyourbotactuallypressF1,you’dneedtosendthisinputtwice,likeso:
SendInput(1,&input,sizeof(input));//changeinputtokeyupinput.ki.dwFlags|=KEYEVENTF_KEYUP;SendInput(1,&input,sizeof(input));
ThefirstcalltoSendInput()pressesF1,andthesecondreleasesit.Thereleasehappensnotbecausetheinputwassenttwice,butbecausethesecondcallwasmadewiththeKEYEVENTF_KEYUPflagenabledintheinputparameter’skeyboardflagsfield.Sincesettingupinputforevenasinglekeyisabit
![Page 280: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/280.jpg)
messy,it’sbesttowrapeverythinginsideafunction.TheresultlookssomethinglikeListing10-3.
voidsendKeyWithSendInput(WORDkey,boolup){INPUTinput={0};input.type=INPUT_KEYBOARD;input.ki.wVk=key;input.ki.dwFlags=0;
if(up)input.ki.dwFlags|=KEYEVENTF_KEYUP;SendInput(1,&input,sizeof(input));}sendKeyWithSendInput(VK_F1,false);//presssendKeyWithSendInput(VK_F1,true);//release
Listing10-3:AwrapperforemulatingkeystrokeswithSendInput()
Thisfunctioninitializesinputwiththegivenkey,enablestheflagKEYEVENTF_KEYUPifupisset,andcallstheSendInput()function.ThismeanssendKeyWithSendInput()mustbecalledasecondtimetosendthekeyrelease,eventhoughthereleaseisalwaysrequired.ThefunctioniswrittenthiswaybecausekeycombinationsthatinvolvemodifierslikeSHIFT,ALT,orCTRL
mustbesentabitdifferently;themodifier’spressmustcomebeforethekey’spress,butitsreleasemustcomeafterthekey’srelease.
Thefollowingcodeshowshowyou’dusethesendKeyWithSendInput()functiontotellabottopressSHIFT-F1:
sendKeyWithSendInput(VK_LSHIFT,false);//pressshiftsendKeyWithSendInput(VK_F1,false);//pressF1sendKeyWithSendInput(VK_F1,true);//releaseF1sendKeyWithSendInput(VK_LSHIFT,true);//releaseshift
You’dhavetocallsendKeyWithSendInput()fourtimes,butthat’sstilleasierthanusingthecodewithoutawrapperfunction.
TheSendMessage()FunctionAnalternativemethodforsendingkeystrokesreliesontheSendMessage()WindowsAPIfunction.Thisfunctionallowsyoutosendinputtoanywindow,evenifit’sminimizedorhidden,bypostingdatadirectlytothetargetwindow’smessagequeue.Thisadvantagemakesitthemethodof
![Page 281: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/281.jpg)
choiceforgamehackers,becauseitenablesuserstodootherthingswhiletheirbotplaysthegameinthebackground.SendMessage()hasthefollowingprototype:
LRESULTSendMessage(HWNDwindow,UINTmessage,WPARAMwparam,LPARAMlparam);
Thefirstparameter,window,isahandletothewindowthattheinputisbeingsentto.Thesecondparameter,message,isthetypeofinputbeingsent;forkeyboardinput,thisparameterisWM_KEYUP,WM_KEYDOWN,orWM_CHAR.Thethirdparameter,wparam,shouldbethekeycode.Thefinalparameter,lparam,shouldbe0whenthemessageisWM_KEYDOWNand1otherwise.
BeforeyoucanusetheSendMessage()function,youmustobtainahandletothetargetprocess’smainwindow.Giventhetitleofthewindow,youcanobtainahandleusingtheFindWindow()WindowsAPIfunction,asfollows:
autowindow=FindWindowA(NULL,"TitleOfGameWindow");
Withavalidwindowhandle,makingacalltoSendMessage()lookssomethinglikethis:
SendMessageA(window,WM_KEYDOWN,VK_F1,0);SendMessageA(window,WM_KEYUP,VK_F1,0);
ThefirstcallpressestheF1key,andthesecondcallreleasesit.Keepinmind,however,thatthisseriesofcallsworksonlyforkeysthatdon’tinputtext,likeF1,INSERT,orTAB.Tohaveyourbotpresskeysthatinputtext,youmustalsosendaWM_CHARmessagebetweenthedownandupmessages.TotypeW,forinstance,you’ddosomethinglikethis:
DWORDkey=(DWORD)'W';SendMessageA(window,WM_KEYDOWN,key,0);SendMessageA(window,WM_CHAR,key,1);SendMessageA(window,WM_KEYUP,key,1);
Thiscreatesakeyvariablesotheletterkeytopresscanbechangedeasily.ThenitfollowsthesamestepstheF1exampleused,justwithaWM_CHARmessageinbetween.
![Page 282: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/282.jpg)
NOTE
YoucanactuallysendnothingbuttheWM_CHARmessageandgetthesameresult,butit’sbestpracticetosendallthreemessages.GamedeveloperscaneasilyshutdownbotsbypatchingthegametoignoreWM_CHARmessagesthatdon’tfollowWM_KEYDOWN,andtheycanevenuseitasawaytodetectyourbotandbanyou.
AsIshowedwiththeSendInput()technique,youcancreateawrapperaroundthisfunctionalitytomakeyourbotcodeeasiertoworkwith.Thewrapperlookssomethinglikethis:
voidsendKeyWithSendMessage(HWNDwindow,WORDkey,charletter){SendMessageA(window,WM_KEYDOWN,key,0);if(letter!=0)SendMessageA(window,WM_CHAR,letter,1);SendMessageA(window,WM_KEYUP,key,1);}
UnlikeListing10-3,thiswrapperactuallysendsboththepressandrelease.ThisisbecauseSendMessage()can’tbeusedtosendkeystrokeswithmodifiers,sothere’sneveranyneedtoinsertcodebetweenthetwocalls.
NOTE
Therearemultiplewaysagamemightcheckwhetheramodifierkeyispressed,though.YoumightbeabletosendmodifierkeystocertaingamesbycallingtheSendMessage()function,butitdependsonhowthosegamesdetectmodifiers.
YoucanusethiswrapperinasimilarwayastheoneinListing10-3.Forexample,thiscodesendsF1followedbyW:
sendKeyWithSendMessage(window,VK_F1,0);sendKeyWithSendMessage(window,'W','W');
Thisexample,likealloftheSendMessage()codeI’veshownsofar,simplygetsthejobdone.Itcaninputtext,butitdoesn’texactlysendpropermessages.
Therearealotofsmalldetailsyouhavetogetrightifyouwanttosend100percentvalidmessageswiththeSendMessage()function.Forinstance,
![Page 283: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/283.jpg)
thefirst16bitsoflparamshouldstorethenumberoftimesthekeyhasbeenautomaticallyrepeatedasaresultofbeinghelddown.Thenext8bitsshouldstorethescancode,akeyidentifierthatisspecifictoeachkeyboardmanufacturer.Thenextbit,number24,shouldbesetonlyifthebuttonisonanextendedpartofthekeyboard,suchasthenumberpad.Thefollowing4bitsareundocumented,andthenextbitshouldbesetonlyiftheALTkeywasdownwhenthemessageoriginated.Thelast2bitsarethepreviousstateflagandthetransitionstateflag.Thepreviousstateflagissetonlyifthekeywaspreviouslydown,andthetransitionstateissetonlyifthekeywaspreviouslyinthestateoppositeitscurrentposition(thatis,ifthekeyisnowupandwaspreviouslydown,orviceversa).
Thankfully,theaveragegamedoesn’tconsidermostofthesevalues.Forthatmatter,theaveragepieceofsoftwaredoesn’tcareaboutthemeither.Ifyouhavetofillallofthesevalueswithproperdatatomakeyourbotwork,you’removinginthewrongdirection.Therearemanyotherwaystoperformactions,themajorityofwhicharesimplerthantryingtoemulatetheexactbehavioroftheoperatingsystem’skernel-levelkeyboardinputhandler/dispatcher.Infact,there’salreadyafunctionthatdoesthat,andI’vealreadytalkedaboutit:theSendInput()function.
YoucanalsocontrolthemousewiththeSendInput()andSendMessage()functions,butIhighlyrecommendavoidingit.Anymousecommandsyousendwillaffect,andbeaffectedby,anylegitimatemousemovements,mouseclicks,orkeystrokessentbytheplayer.Thesameistrueforkeyboardinput,butthecomplicationsaremuchrarer.
SendingPacketsBeforeagamedrawsaframe,itchecksforkeyboardandmouseinput.Whenitreceivesinputthatresultsinanaction,suchasmovingaroundorcastingaspell,itcheckstomakesuretheactionispossibleand,ifso,tellsthegameserverthattheactionhasbeenperformed.Thegamecodetocheckforeventsandalerttheserveroftenlookssomethinglikethis:
voidprocessInput(){do{autoinput=getNextInput();if(input.isKeyboard())processKeyboardInput(input);//handleotherinputtypes(e.g.,mouse)
![Page 284: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/284.jpg)
}while(!input.isEmpty());}voidprocessKeyboardInput(input){if(input.isKeyPress()){if(input.getKey()=='W')step(FORWARD);elseif(input.getKey()=='A')step(BACKWARD);//handleotherkeystrokes(e.g.,'S'and'D')}}voidstep(intdirection){if(!map->canWalkOn(player->position))return;playerMovePacketpacket(direction);network->send(packet);}
TheprocessInput()functioniscalledeveryframe.Thefunctioniteratesoverallpendinginputsanddispatchesdifferenttypesofinputstotheirrelevanthandlers.Inthiscase,whenkeyboardinputisreceived,it’sdispatchedtotheprocessKeyboardInput()function.ThishandlerthencheckswhetherthekeyiseitherWorS,and,ifso,callsstep()tomovetheplayerinthecorrespondingdirection.
Sincestep()isusedtoperformanaction,itiscalledanactorfunction.Theinvocationofanactorfunctioniscalledactuation.Youcandirectlycallagame’sactorfunctionsfromyourbottoperformanactionwhilecompletelybypassingtheinputlayer.
Beforeyoucancallanactor,though,youmustfinditsaddress.Todothis,youcanattachOllyDbgtothegame,openthecommandline,andenterbpsend.Thiswillplaceabreakpointonthesend()function,whichisusedtosenddataoverthenetwork.Whenyouplaythegame,everytimeyoutakeastep,castaspell,pickuploot,ordoanythingelse,yourbreakpointshouldtrigger,andyoucannoteeachfunctioninthecallstack.
NOTE
Thegameshouldcallsend()everytimeyoudoanythingwhileplaying.Payattentiontowhatyoudidbeforeeachsend()breakpointishit,asthatwillgiveyouaroughideaofwhatactioneachcalliscommunicatingtotheserver,and,ultimately,whattheactoryoufindisresponsiblefor.
![Page 285: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/285.jpg)
Onceyouhaveafewdifferentcallstacks,youcancomparethemtolocatetheactorfunctions.Toseehowtospottheactorfunctions,let’scomparethetwoannotatedcallstacksinFigure10-3.
Figure10-3:Treeviewofcallstackstotwoactorfunctions
Likethesetwostacks,thecallstacksyoufindshouldbeidenticalatthetop,sharingacoupleofcommonfunctionsresponsibleforgenericnetworktransmission.Theyshouldalsobeidenticalonthebottom,sinceeachcalltosend()shouldhaveoriginatedfromtheprocessInput()function.Eachstackshouldhavesomeuniquefunctionsbetweentheseidenticalregions,though,andthosearetheactorfunctionsyou’relookingfor.Typically,thefunctionofinterestisimmediatelybeneaththecommonnetworkcalls.Inthiscase,thetwoactorsarethestep()andcastSpell()functions.
Afterhackingthesamegameforawhile,you’lllearnhowfarupthestacktheactorfunctionsarefromthesend()call.InFigure10-3,forexample,theactorshappenthreecallsbeforethesend()call.Knowingthis,youcouldjustclimbthestackinOllyDbg(CTRL-F9followedbyF8)threetimeswhenyoursend()breakpointishitandbeinsidetheactorfunctionthatsentthedata.
Onceyou’vefoundanactorfunction,youcancallitfromaninjectedDLL.Here’showyoumightcallstep()ifyoufounditat0xDEADBEEF:
typedefvoid_step(intdirection);autostepActor=(_step*)0xDEADBEEF;
![Page 286: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/286.jpg)
autostepActor=(_step*)0xDEADBEEF;
stepActor(FORWARD);
Sincethebotwon’tknowtheactualnameforthisgamefunction,thecodeassignsthecontentsofmemoryat0xDEADBEEFtoaconvenientlynamedvariable:stepActor.Then,thecodejustcallsstepActor()likeanyotherfunction.
Ifyou’vegottherightaddress,functionprototype,andparameters,thisshouldworkbeautifully;you’llbeabletoautomateactionsasifyouhaveaccesstothegame’ssourcecode.Justmakesuretocalltheactorfunctionsfrominsidethesamethreadasthegame,oryoucanrunintothreadingissues.ThebestwaytodothisistocalltheactorsfromahookonamajorfunctionlikeDirect3D’sEndScene()ortheWindowsAPI’sPeekMessage()function,asthesefunctionswillusuallybecalledonlyfromthegame’smainthread.
USINGTHISTOCALL__THISCALLIfyoutrytocallanactorfunctionthat’sanonstaticmemberofaclass,thefunctionwillhavea_thiscallcallingconvention,whichmeansyou’llneedtopasstheinstanceoftheclassontheECXregister.(Youcanbrushuponcallingconventionsin“FunctionCalls”onpage94.)Passingtheinstanceisstraightforward,butyou’llhavetolocateapointerchaintotheclassinstancefirst.
Tofindthepointerchain,youcandropabreakpointontheactorfunction,grabtheclassinstancevaluefromECXwhenthebreakpointkicks,andthrowthatvalueintoaCheatEnginepointerscan.Then,tocallthefunction,you’dwalkthepointerchain,obtainthecurrentinstanceaddress,anduseinlineassemblytosetupECXandmaketheactualfunctioncall.ThisprocessworkssimilarlytothewayVFhookcallbackscalltheiroriginalcounterparts,asshownin“WritingaVFTableHook”onpage156.
![Page 287: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/287.jpg)
TyingthePiecesTogetherAfteryou’vecreatedframeworksforobservingeventsandperformingactions,youcantiethemtogethertocreateresponsivehacks.Responsivehackscomeinmanyflavors,butthereareafewcommonones.
MakingthePerfectHealerAfavoritebotamonggamersisautohealing,ahackthatautomaticallyusesahealingspellwhentheplayer’shealthdecreasesdrasticallyordropsbelowacertainthreshold.Givenawaytodetectchangesinhealthandanactorfunctiontocastspells,anautohealermightlooksomethinglikethis:
voidonHealthDecrease(inthealth,intdelta){if(health<=500)//healthbelow500castHealing();elseif(delta>=400)//largedropinhealthcastHealing();}
Thisautohealingfunctionisprettysimple,butitworkswell.Moreadvancedautohealersmighthavemanymorelevelsofhealingandbeabletolearnastheygo.You’llgetworkingexamplecodeandanin-depthexplanationofadvancedautohealersin“ControlTheoryandGameHacking”onpage222.
ResistingEnemyCrowd-ControlAttacksAnti-crowd-controlhacksdetectincomingcrowd-controlattacksandautomaticallycastspellsthatreducetheireffectsorcompletelynegatethem.Crowd-controlattacksdisableplayersinsomeway,sohavingenemiescastthemonyoucanbeapain.
Givenawaytodetectincomingoractivecrowd-controleffects,suchasbydetectingaDirect3Dmodelorbyinterceptinganincomingpacket,andanactorfunctiontocastspells,youcouldhaveabotreactinstantlytosuchattackslikeso:
voidonIncomingCrowdControl(){//castashieldtoblockthecrowdcontrolcastSpellShield();
![Page 288: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/288.jpg)
}voidonReceiveCrowdControl(){//cleansecrowdcontrolthathasalreadytakeneffectcastCleanse();}
AnonIncomingCrowdControl()functionmighttrytostopthecrowd-controlspellfromeverhittingyou.Failingthat,thebotcouldcallanonReceiveCrowdControl()spelltoremovetheeffects.
AvoidingWastedManaSpelltrainersarealsoquitecommonamongbotters.Spelltrainerswaituntiltheplayerhasfullmanaandthencastspellstoincreasetheplayer’smagiclevelorstats.Thisallowsplayerstoquicklyincreasetheirmagicskills,astheywillneverwastemanaregenerationjustbecausetheyhavefullmana.
Givenawaytodetectchangesinmanaandanactorfunctiontocastspells,abotmightincludethefollowingpseudocodeforaspelltrainer:
voidonManaIncrease(intmana,intdelta){if(delta>=100)//playerisusingmanapotions,return;//theymustneedthemana,abortif(mana>=MAX_MANA-10)//manaisnearlyfull,wastesomecastManaWasteSpell();}
Thisfunctiontakestheplayer’smanaandtheincreaseinthatplayer’smana(delta)asparameters.Iftheincreaseinmanaisaboveacertainamount,itassumestheplayerisusingpotionsorotheritemstoreplenishmana,anditwon’tcastanyextraspells.Otherwise,iftheplayerhasplentyofmana,thefunctionfiresoffanyoldspelltogettheplayersomeexperiencepoints.
Othercommonresponsivehacksareautoreloadtoinstantlyreloadammo,autododgetoevadeincomingprojectiles,andautocombotoinstantlyattackthesametargetasanearbyally.Really,theonlylimittothenumberofresponsivehacksyoucanaddtoabotisthenumberofeventsyourbotcanobserveinthegame,multipliedbythenumberofvalidandhelpfulresponsesitcansendforeachevent.
![Page 289: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/289.jpg)
ClosingThoughtsUsinghooks,memorymanipulation,andkeyboardsimulation,youcanbegincreatingyourfirstresponsivehacks.Thesehacksareyourentrypointintogamingautonomy,butthey’reonlyaglimpseofwhat’spossible.Chapter11willbethepinnacleofyourgame-hackingadventure.Usingeverythingyou’velearnedsofar,andbuildingontheprinciplesofresponsivehacks,you’lllearnhowtoautomateadvancedactionsandcreateatrulyautonomousbot.
Ifyou’renotfeelingquitereadytogodeeper,Istronglyrecommendreviewingtheearliermaterialandthengettingsomepracticeinanisolatedenvironmentonyourownmachine.Implementingbotslikethisisaloteasierthanyoumightthink,andit’sanamazinglysatisfyingexperience.Onceyou’recomfortablemakingautohealersandotherbasicresponsivehacks,you’llbereadytostartcompletelyautomatinggameplay.
![Page 290: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/290.jpg)
11PUTTINGITALLTOGETHER:WRITING
AUTONOMOUSBOTS
Theendgoalofgamehackingistomakeafull-fledgedautomatedbotcapableofplayingagameforhoursonend.Suchbotscanheal,drinkpotions,farmmonsters,lootcorpses,walkaround,sellloot,buysupplies,andmore.Makingbotsthispowerfulrequiresyoutocombineyourhooksandmemoryreadswithconceptslikecontroltheory,statemachines,andsearchalgorithms,whichareallcoveredinthischapter.
Throughoutthelessonshere,you’llalsolearnaboutcommonautomatedhacksandhowtheyshouldbehaveatahighlevel.Aftercoveringthetheoryandcodebehindautomatedhacks,I’llgiveyouahigh-levellookattwotypesofbotsthatrelyonsuchcode:cavebots,whichcanexplorecavesandbringhometheloot,andwarbots,whichcanfightenemiesforyou.Bytheendofthechapter,youshouldbereadytobustoutyourtools,fireupyourdevelopmentenvironment,andstartmakingsomereallyawesomebots.
ControlTheoryandGameHackingControltheoryisabranchofengineeringthatprovidesawaytocontrolthebehaviorofdynamicsystems.Controltheorydeterminesthestateofasystemusingsensors,afterwhichacontrollerdeterminesthesetofactionsneededto
![Page 291: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/291.jpg)
bringthesystem’scurrentstatetosomeotherdesiredstate.Afterthecontrollerexecutesthefirstactionintheset,theentireprocess—knownasafeedbackloop—repeats(seeFigure11-1).
Figure11-1:Acontroltheoryfeedbackloop
Let’sapplythisfeedbacklooptogamehacking.Toautomateplaywithinagame(thesystem),abotimplementssomealgorithms(thecontroller)thatunderstandhowtoplaythegameinanystateobservedbythememoryreads,networkhooks,andsoon(thesensors).Thecontrollertypicallyhassomehumaninputs,likethepathtowalk,creaturestoattack,andloottopickup.Thus,toreachthedesiredstate,thecontrollermustperformsomesubsetoftheseinputsthatarepossiblegiventhecurrentstate.
Forinstance,iftherearenocreaturesonscreenandnocorpsestoloot,thedesiredstatemaybefortheplayertoreachthenextlocation(calledawaypoint)inthepredefinedpath.Inthiscase,thecontrollermovestheplayeronestepclosertothewaypointoneachiteration.Iftheplayerencountersacreature,thecontrollermightdecidetoattackthecreatureinthefirstframeand,inthefollowingframes,switchbetweenrunningfromthecreature(knownaskiting)andshootingspellsatit.Oncethecreaturedies,thecontrollerexecutesasetofactionstolootthebodyandcontinuetothenextwaypoint.
Giventhisexampleofhowafeedbackloopmightoperate,itmightseemoverwhelmingtocodesuchasystem.Luckily,thereareafewdesignpatternsthatmakethetaskmucheasierthanitsounds.
StateMachinesStatemachinesaremathematicalmodelsofcomputationthatdescribehowasystembehavesbasedoninput.Figure11-2showsasimplestatemachine
![Page 292: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/292.jpg)
thatreadsalistofbinarydigits.ThemachinestartswithaninitialstateofS1.Asititeratesoverthedigitsintheinput,itchangesitsstateaccordingly.Inthiscase,statesS1andS2repeatthemselveswhenthemachineencountersa1andactivateoneanotherwhenitencountersa0.Forexample,forthebinarydigits11000111,thestatetransitionswouldbeS1,S1,S2,S1,S2,S2,S2,andfinallyS2.
Figure11-2:Asimplestatemachine
Withasmallspinontheclassicalstatemachinetheory,astatemachinecanbethecontrollerinacontroltheoryfeedbackloop.Thistweakedversionofastatemachinecomprisesalistofstates,theconditionssignifyingeachstate,andtheactionsthatmusthappentoreacheachstate.
STATEMACHINESANDGAMEHACKINGAgame-hackingstatemachinenotonlymustkeepaninternalstatebutalsomustrespondto(oractuate)thegameenvironmentbasedonthatstate.Theoverallgamestatecanchangebasedonyourbot’sactuation,thebehaviorofotherplayers,andotherunpredictableoccurrencesinthegameenvironment.Forthisreason,tryingtopersistentlywalkastatemachinebasedontheobservedgameenvironmentisfutile;it’snearlyimpossibletocreateasetoftransitionsforeachstatetoaccountforeverypossibleobservationthatcanbemadebetweeniterations.Itmakesmoresenseforthestatemachinetoreevaluatethegameenvironmentasafreshslateeachtimeitconsiderstheinput.Todothis,thestatemachinemustusethegameenvironmentitselfasthemechanismfortransitioningbetween
![Page 293: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/293.jpg)
states—thatis,themachine’sactuationontheenvironmentshouldhaveenoughofaneffectonthenextiterationsthatitactivatesanewstate.Classicalstatemachinescanbedevisedthatarecapableofworkinglikethis,butwe’regoingtoflattenthemoutandusetheminamuchsimpler,yetstillverypowerful,way.
Ifyou’refamiliarwithclassicalstatemachines,thismaynotseemintuitive,butinthecomingsectionsyou’llseehowstatemachinescanbemutatedandpairedwithcontroltheorytoachievewhatwewant.
Themajordifferenceisthatinsteadofonestatemerelyactivatinganother,foreachstateinagameautomationstatemachine,abotwillperformin-gameactionsthatchangetheoverallstateofthegameand,thus,thestatethatisdetectedonthenextiterationofthefeedbackloop.Incode,anobjecttorepresentastateinthismachinemightlooklikethis:
classStateDefinition{public:StateDefinition(){}~StateDefinition(){}boolcondition();voidreach();};
YoucanassembleStateDefinitionobjectsintoastatemachinewithasimplestd::vectordefinition,likethis:
std::vector<StateDefinition>stateMachine;
Andpresto,youhavetheskeletonofastatemachine,readytoreceiveanyStateDefinitionobjectsyoucreate.Inconjunctionwithafeedbackloop,thisstatemachinecanbeusedtodefinetheflowofautomation.
First,youcancreatealistofdefinitionsthatmodelyourbot’sdesiredbehavior,orderedinthevectorbyimportance.EachStateDefinitionobjectcanuseinformationfromyoursensorsasinput,passingthatdatatothecondition()functiontodeterminewhetherornotthestateshouldbeactivated.Then,youcancreateacontrollerthatloopsoverthelistofstates,callingthereach()functionofthefirststatewhosecondition()functionreturnsfalse.Finally,youcanwrapthecontrollerinafeedbackloop.Ifyoudon’tseehowthisfeedbackloopwouldworkyet,don’tworry;I’llshowyou
![Page 294: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/294.jpg)
howtocodeitnow.
NOTE
Youcanthinkofthestatementinyourcondition()functionasarequirementforthemachinetotransitiontothenextstate.Ifthestatementistrue,itmeansnoactuationmusthappenbeforethenextstateinthelistcanbeevaluatedandtheloopcancontinueiterating.Ifthestatementisfalse,itmeanssomeactuatormustoccurbeforethetransitioncanhappen.
You’llfindalloftheexamplecodeforthefollowingsectionand“ErrorCorrection”onpage230intheGameHackingExamples/Chapter11_StateMachinesdirectoryofthisbook’ssourcefiles.TheincludedprojectscanbecompiledwithVisualStudio2010,buttheyshouldalsoworkwithanyotherC++compiler.Downloadthemathttps://www.nostarch.com/gamehacking/andcompilethemifyouwanttofollowalong.
CombiningControlTheoryandStateMachinesTotiestatestogetherwithafeedbackloop,firstyouhavetoprovideeachStateDefinitionobjectwithagenericwaytoaccessthesensorsandactuatorsthatyou’veimplemented.TheStateDefinitionclassthenbecomesthefollowing:
classStateDefinition{public:StateDefinition(){}~StateDefinition(){}boolcondition(GameSensors*sensors);voidreach(GameSensors*sensors,GameActuators*actuators);};
Thischangesimplymodifiesthecondition()andreach()functionstoacceptinstancesoftheclassesGameSensorsandGameActuatorsasarguments.GameSensorsandGameActuatorsareclassesyouneedtodefine;GameSensorswillcontaintheresultsofmemoryreads,networkhooks,andotherdatasourcesyourbotinterceptsfromthegame,whileGameActuatorswillbea
![Page 295: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/295.jpg)
collectionofactorfunctionscapableofperformingactionsinsidethegame.Next,youneedagenericwaytodefineeachindividualstate.Youcould
abstractthedefinitionofeachstatetoitsownclassthatinheritsStateDefinitionandimplementscondition()andreach()asvirtualfunctions.Alternatively,ifthesourcecodeneedstofitinasmallspace(likeabook,winkwink),youcouldkeepasingleclasstorepresenteachdefinitionandusestd::functiontoimplementthecondition()andreach()functionsoutsidetheclassdefinition.
Followingthatalternativemethod,thefinalversionofStateDefinitionwouldlooklikethis:
classStateDefinition{public:StateDefinition(){}~StateDefinition(){}std::function<bool(GameSensors*)>condition;std::function<void(GameSensors*,GameActuators*)>reach;};
WiththisversionoftheStateDefinitionclass,youcoulddefineanewstatebycreatinganinstanceoftheclassandassigningcondition()andreach()tofunctionsthatcorrespondwiththeintendedbehavior.
ABasicHealerStateMachineThenextstepisdefiningthebot’sactualbehavior.Tokeeptheexamplecodesimple,let’ssayyou’reimplementinganautomatichealer.Thishealerhastwohealingmethods:itusesstronghealingiftheplayerisatorbelow50percenthealthandweakhealingiftheplayerisbetween51and70percenthealth.
Astatemachinerepresentingthisbehaviorneedstwostates,oneforstronghealingandoneforweakhealing.Tostart,youneedtodefinethestatemachineasavectorwithtwoStateDefinitionobjects:
std::vector<StateDefinition>stateMachine(2);
ThiscodecreatesastatemachinecalledstateMachineandinitializesitwithtwoemptyStateDefinitionobjects.Next,youdefinethecondition()andreach()functionsforthesestatedefinitions.Thestronghealingstateisthemostimportantbecauseitkeepsthecharacterfromdying,soitshould
![Page 296: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/296.jpg)
comefirstinthevector,asshowninListing11-1.
autocurDef=stateMachine.begin();curDef->condition=[](GameSensors*sensors){➊returnsensors->getHealthPercent()>50;};curDef->reach=[](GameSensors*sensors,GameActuators*actuators){➋actuators->strongHeal();};
Listing11-1:Codeforastronghealingstate
ThiscodefirstcreatesaniteratorcalledcurDefthatpointstothefirstStateDefinitionobjectinthestateMachinevector.Theobject’scondition()functionisthendefined➊;inEnglish,thisdefinitionsays,“Thestateismetiftheplayer’shealthpercentisgreaterthan50.”Ifthestateisn’tmet,thentheobject’sreach()functioncallsthestrongHeal()actorfunction➋sothatstronghealingcanbeperformed.
Withthestronghealingstatedefined,nextyoudefinetheweakhealingstate,asshowninListing11-2.
curDef++;curDef->condition=[](GameSensors*sensors){➊returnsensors->getHealthPercent()>70;};curDef->reach=[](GameSensors*sensors,GameActuators*actuators){➋actuators->weakHeal();};
Listing11-2:Codeforweakhealing
AfterincrementingcurDefsoitpointstothesecondStateDefinitionobjectinthestateMachinevector,thiscodedefinestheobject’scondition()function➊as,“Thestateismetiftheplayer’shealthpercentisgreaterthan70.”Italsodefinestheobject’sreach()functionasanactuators->weakHeal()call➋.
Onceyou’vefinisheddefiningthestatemachine,youmustimplementthecontroller.Sincetheactualbehaviorofthecontrolleriscontainedinthestatemachine,youonlyneedtoaddasimplelooptocompleteit:
for(autostate=stateMachine.begin();state!=stateMachine.end();state++){
![Page 297: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/297.jpg)
if(➊!state->condition(&sensors)){state->reach(&sensors,&actuators);break;}}
Thiscontrollerloopiteratesoverthestatemachine,executesthereach()functionofthefirststatewhosecondition()functionreturnsfalse➊,andbreaksoutifanyreach()functioniscalled.Thefinalstepistoimplementthefeedbackloopandplopthecontrollerloopinsideit,asshowninListing11-3.
while(true){for(autostate=stateMachine.begin();state!=stateMachine.end();state++){if(!state->condition(&sensors)){state->reach(&sensors,&actuators);break;}Sleep(FEEDBACK_LOOP_TIMEOUT);}
Listing11-3:Finalhealingstatemachineandfeedbackloop
ThisloopcontinuouslyexecutesthecontrollerloopandsleepsforFEEDBACK_LOOP_TIMEOUTmillisecondsbetweeneachexecution.TheSleep()callallowsthegameservertoreceiveandprocessanyactuationfromthepreviousiterationandallowsthegameclienttoreceiveanyresultsoftheactuationfromtheserverbeforeexecutingthenextcontrollerloop.
Ifyou’restillabitconfusedaboutwhatIjustshowedyou,checkoutFigure11-3,whichshowshowtheinfinitelyloopingcodeinListing11-3works.First,itcheckswhetherthestronghealingconditionistrue,andifitis,theweakhealingconditionischecked.Ifthestronghealingconditionisfalse,thentheplayer’shealthmustbeatorbelow50percent,soastronghealingmethodgetscalled.Iftheweakhealingconditioncheckisfalse,thentheplayer’shealthmustbebetween51and70percent,sotheweakhealingmethodisexecuted.
![Page 298: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/298.jpg)
Figure11-3:Flowchartofthehealingstatemachineandfeedbackloop
Aftereithermethod,themachinesleeps.Ifbothconditionchecksaretrue,thentheplayerneedsnohealing.Themachinedoesnothingtochangethestateandsleepsbeforestartingagainatthetopofthewhileloop.
AComplexHypotheticalStateMachineThebehaviorimplementedinthehealingstatemachineissimple,sorollingitintothiskindofcontrolstructuremayseemlikeoverkill,butit’susefulifyouwanttoexpandthecontroller.If,forexample,youwantedtocombinethehealingstatemachinewiththe“walk,attack,loot”behaviorthatI
![Page 299: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/299.jpg)
discussedin“ControlTheoryandGameHacking”onpage222,thecontrolstructurewouldbemuchmorecomplex.Let’stakeahigh-levellookatthestatesyou’dneed:
StronghealingConditionmetifhealthisover50percent.Reachbycastingstronghealingspell.
WeakhealingConditionmetifhealthisover70percent.Reachbycastingweakhealingspell.
AttackspellConditionmetifnotargetisavailableorifattackspellisoncooldown.Reachbycastingattackspellontarget.
KitemonsterConditionmetifnotargetisavailableorifdistancefromtargetisadequate.(Thedefinitionof“adequate”dependsonhowfarawayyouwanttobefromenemieswhenkiting.)Reachbytakingastepawayfromtarget.
TargetmonsterConditionmetifthere’snocreaturetoattack.Reachbyattackingacreature.
LootitemConditionmetifthere’snocorpseopenorifopencorpsehasnothingtoloot.Reachbytakinganitemfromopencorpse.
ApproachcorpseConditionmetiftherearenocorpsestoopenorifadjacenttoacorpse.Reachbytakingasteptowardacorpsethatwillbeopened.
OpencorpseConditionmetifthecharacterisnotadjacenttoacorpsethatcanbeopened.Reachbyopeningadjacentcorpse.
FollowpathConditionmetifthecharacterisunabletomovetocurrentwaypointorifstandingoncurrentwaypoint.Reachbytakingasteptowardcurrentwaypoint.
AdvancewaypointConditionmetiftherearenowaypointslefttofollow.Reachbyupdatingthecurrentwaypointtothenextwaypointinthelist.Ifthecharactercan’treachthecurrentwaypointforsomereason(say,ifthecharacterisstuck),thentheAdvanceWaypointstatekeepsitfrombeingstuck.Ifthecharacterhasreachedthecurrentwaypoint,AdvanceWaypointselectsthenextwaypointtokeepthingsmovingalong.
![Page 300: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/300.jpg)
Thisstatemachineisquiteabitmorecomplexthanthehealing-onlystatemachine.IfIdiagrammedthisstatemachine,therewouldbe23objectsinthediagram,witharrowsgoingover33controlpaths.ComparethattoFigure11-3,whichhasonly7objectsand9controlpaths.
Youcouldcodethehealerbehaviorwithoutusingastatemachineorfeedbackloop,butIcan’timaginehowtoeasilydothesameforthisfull-fledgedbot.Eachofthese10statesreliesonnotonlyitsownconditionbutalsotheconditionofeverystateprecedingit.Moreover,hardcodingthelogicwouldeitherrequireatonofnestedif()statementsorabunchofstackedif()/return()statements—and,eitherway,itwouldjustbehaveexactlylikethestatemachinebutwithnoruntimeflexibility.
Runtimeflexibilityreferstoastatemachine’sabilitytomutate.Unlikehardcodedconditionchecks,statedefinitionsinastatemachinecanbemoved,removed,andaddeddynamically.Thestatemachinemethodallowsyoutoplugandplaydifferentbehaviorsandfeaturesdependingonuserinput.
Totakethisconceptastepfurther,youcouldexposeyoursensorsandactuatorstoaLuaenvironment,createLuafunctionscapableofaddingandremovingstatesfromthestatemachine,andmodifytheStateDefinitionsothatitscondition()andreach()functionscancallLuafunctionsexposedbytheLuaenvironment.Writingacontrolsystemthiswaywouldallowyoutocodethecoreofyourbot(hooks,memoryreading,actuation)inC++whilemakingLua(ahigh-level,dynamiclanguage)availabletoyouforautomation.
NOTE
YoucanembedLuainyourownprogramsbyincludingafewheadersandlinkingagainsttheLualibrary.Thisprocessisnotdifficult,butit’soutsidethescopeofthisbook,soIencourageyoutocheckoutChapter24ofProgramminginLuabyRobertoIerusalimschy(http://www.lua.org/pil/24.html)formoreinformation.
ErrorCorrectionAnotherpieceofcontroltheorythat’susefulforgamehackingiserror
![Page 301: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/301.jpg)
correction.Anerrorcorrectionmechanisminacontrollerobservestheoutcomeofactuation,comparestheoutcometoanexpectedresult,andadjustsfuturecalculationstobringlateroutcomesclosertotheexpectedone.Errorcorrectioncancomeinhandywhenyou’reworkingwithstochasticsystems,wheretheoutputgeneratedfromagiveninputisnotfullypredictable.
Gamesasawholearestochastic,but,luckilyforgamehackers,theresultsofactionsaremostlydeterministic.Takethehealingcontroller,forexample.Inmostgames,youcancalculateexactlyhowmuchhealthyoucanhealwithagivenspell,and,thus,youknowexactlywhentoheal.Butimagineyou’rewritingahealerforthesmallspectrumofsituationswhereyourhealingisimpossibletocalculate;forinstance,maybethebotissupposedtoworkonavarietyofcharactersspanningmanylevelswithoutuserinput.
Errorcorrectioncouldenableyourbottolearnhowtobesthealtheplayers.Inthisscenario,therearetwowaysyoucanimplementerrorcorrection,eachofwhichdependsonhowthehealingsystemworks.
AdjustingforaConstantRatioIfyouhealforaconstantratioofhealth,you’llonlyneedtoadjustyourcontrollerafterthefirstheal.Assumingthatyoursensorscandetecthowmuchyou’vehealed,thisaddsonlyafewlinesofcode.YoucouldeasilymodifytheweakhealingstateinListing11-2tosomethinglikethis:
curDef->condition=[](GameSensors*sensors)->bool{staticfloathealAt=70;staticboolhasLearned=false;if(!hasLearned&&sensors->detectedWeakHeal()){hasLearned=true;healAt=100-sensors->getWeakHealIncrease();}returnsensors->getHealthPercent()>healAt;};
Insteadofhardcoding70asthethresholdforweakhealing,thiscodemovesthethresholdtoastaticvariablecalledhealAt.ItalsoaddsanotherstaticvariablecalledhasLearnedsothatthecodeknowswhenlearningiscomplete.
Oneachinvocationofthiscondition()function,thecodecheckstwoconditions:whetherhasLearnedisfalseandwhetherthesensorsdetecteda
![Page 302: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/302.jpg)
weakhealingevent.Whenthischeckpasses,thecodesetshasLearnedtotrueandupdateshealAttohealatorbelowtheperfectpercentage;thatis,ifyourweakhealingmusteredupa20percentincreaseinhealth,healAtwouldbesetto80percenthealthinsteadof70percent,soeachhealwouldbringtheplayerbackupto100percenthealth.
ImplementingAdaptableErrorCorrectionButwhatifyourhealingpowerincreases?Ifacharactercangainlevels,applyskillpoints,orincreasemaximumhealth,theamountofhealthitcanhealmaychangeaccordingly.Forexample,ifyoustartabotonalevel-10characterandletitrununtilthecharacterislevel40,yourhealingcodewillneedtoadapt.Alevel-40characterhealinglikeitdidatlevel10wouldeitherimmenselyoverhealordiequicklyagainston-levelgameenemies.
Tohandlethisscenario,abotneedstoconstantlyupdateitshealingthresholdtoreflecttheobservedhealingamount.Listing11-4showshowyoucanmodifythestronghealingconditionfunctioninListing11-1todothis.
curDef->condition=[](GameSensors*sensors)->bool{staticfloathealAt=50;➊if(sensors->detectedStrongHeal()){autonewHealAt=100-sensors->getStrongHealIncrease();➋healAt=(healAt+newHealAt)/2.00f;➌sensors->clearStrongHealInfo();}returnsensors->getHealthPercent()>healAt;};
Listing11-4:Tweakingthestronghealingconditioncode
Asinthemodifiedweakhealingfunction,thehealingthresholdhasbeenmovedtoastaticvariablecalledhealAt,butthistime,thelogicisabitdifferent.Sincelearningmusthappencontinually,there’snovariabletotrackwhetherthebothasalreadylearneditstruehealingcapacity.Instead,thecodejustcheckswhetherthesensorshaveseenastronghealingeventsinceitslastinvocation➊.Ifso,thecodereplaceshealAtwiththeaverageofhealAtandnewHealAtandcallsafunctiontoclearthesensorsofinformationrelatedtostronghealing➌.
Clearingthesensorsisactuallyveryimportant,becauseitkeepsthecode
![Page 303: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/303.jpg)
fromconstantlyupdatinghealAtagainstfeedbackfromthesamestronghealingcast.Notice,too,thatthisfunctiondoesn’tupdatehealAttoaperfectvaluebutinsteadslidesittowardtheobservedoptimalvalue.Thisbehaviormakesthenewfunctionidealforsituationswherethereissomeamountofrandomnessinhowmuchyoucanactuallyheal.Ifyourbotneedstoslidetowardthenewvaluefaster,youmightchangethelineat➋tosomethinglikethis:
healAt=(healAt+newHealAt*2)/3.00f;
ThiscodetoupdatehealAtusesanaverageweightedtowardthenewHealAtvalue.Thereareafewpointstoconsiderwhenusingthisapproach,however.First,whathappenswhenyouoverheal?Insomegames,whenyouhealtofullhealth,yoursensorsmightbeabletodetectonlyhowmuchyouactuallyhealed.Inothergames,yoursensorsmaybeabletodetecttheactualamounthealed.Putanotherway,ifyoucasta30percentstronghealfrom85percenthealth,doyoursensorsseeahealof30percentor15percent?Iftheansweris30percent,you’reset.Iftheansweris15percent,yourcodeneedsawaytoadjustdownward.
OnewaytoadjustaccordinglyistodecrementhealAtwhenyoursensorsseeahealthatbringsyoutofullhealth,likethis:
curDef->condition=[](GameSensors*sensors)->bool{staticfloathealAt=50;if(sensors->detectedStrongHeal()){➊if(sensors->getStrongHealMaxed()){healAt--;}else{autonewHealAt=100-sensors->getStrongHealIncrease();healAt=(healAt+newHealAt)/2.00f;}sensors->clearStrongHealInfo();}returnsensors->getHealthPercent()>healAt;};
ThiscodeisalmostthesameasListing11-4,butitaddsanif()clausetodecrementhealAtifamaxhealisdetected➊.Otherwise,thefunctionshouldbehavelikeListing11-4.
Healingisasimplecase,butthiscodeshowsagreatexampleofhowyoucanuseerrorcorrectiontodynamicallyimproveyourbots’behavior.Onemoreadvancedusecaseisadjustingskillshotstoaccountforenemy
![Page 304: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/304.jpg)
moreadvancedusecaseisadjustingskillshotstoaccountforenemymovementpatterns.Everyplayerhaspatternsinhowtheyavoidskillshots,soifyoursensorsareabletomeasurethedirectionanddistanceanenemymoveswhendodgingaskillshot,yourcontrollercodecanadjustthelocationwherethebotinitiallyshootstheskillshot.Inthissamescenario,learningwouldalsohelpthebotaccountfordifferencesingameserverlatency,charactermovementspeed,andsoon.
Whenusingerrorcorrection,notethatyourcodewillbecleanerandmoreportableifyourstatedefinitionshavesomeformofinternalbookkeepingotherthanstaticvariables.Moreover,toavoidclutteringyourstatedefinitions,Isuggestencapsulatingtheerrorcorrectionlogicinsomeexternalmodulesthatareeasilyinvokedwhenneeded.
PathfindingwithSearchAlgorithmsOnecommonchallengeyou’llfacewhenwritinganautonomousbotiscalculatingapathforacharactertofollowfromonelocationtoanother.Asidefromthesheerreverseengineeringchallengeofcreatingsensorstoreadwhichcoordinatesonthegamemapareblockingforwardmovementornot,there’salsothealgorithmicchallengeofcalculatingapathwithinthatmap.Calculatingapathiscalledpathfinding,andgamehackersoftenuseasearchalgorithmtotackleit.
TwoCommonSearchTechniquesGivenagridoftiles,astartinglocationa,andanendinglocationb,asearchalgorithmcalculatesapathfromatob.Thealgorithmdoesthisbycreatinganodeata,addingnodesadjacenttoatoalistoftilestobeexplored(calledthefrontier),updatingthenodetothebesttileinthefrontier,andrepeatingtheprocessuntilthenodereachesb.Differentsearchalgorithmsselectthebestnodedifferently,usingeitheracost,aheuristic,orboth.
Dijkstra’salgorithm,forexample,calculatesthecostofatilebasedonitsdistancefromtheanodeandselectsthetilewiththelowestcost.Imagineanemptytwo-dimensionalgridwithainthemiddle.InasearchfollowingDijkstra’salgorithm,thefrontierwillexpandinacircularpatternaroundauntilbliesontheedgeofthecircle,asseeninFigure11-4.
![Page 305: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/305.jpg)
Thegreedybest-firstsearchalgorithm,insteadofprioritizingnodesbytheirdistancefromthestartingpoint,usesaheuristictoestimatethedistancefromanodeinthefrontiertob.Thealgorithmthenselectsthenodewiththeshortestestimateddistance.Imaginethisalgorithminthesamegridasbefore;thefrontierwouldbealinegoingalmostdirectlyfromatob,asseeninFigure11-5.
Figure11-4:ThefrontierofDijkstra’salgorithm.Lightertilesarehighercost.
Figure11-5:Thefrontierofthegreedybest-firstsearchalgorithm.Lightertilesarehighercost.
HowObstaclesDisruptSearchesThedifferenceinhowthesealgorithmsbehavebecomescleareronceobstaclesareaddedtothegrid.If,forinstance,awallseparatesaandb,Dijkstra’salgorithmwillalwaysfindthequickestpath,butwithahugeconsequence.Theradiusofthecircularfrontieraroundawillbeequaltothe
![Page 306: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/306.jpg)
lengthofthefinalpath;let’scallthatradiusr.Ifnogridboundariesclipthefrontier,youcanroughlycalculatethenumberofnodesopenedbytakingtheareaofacirclewithradiusr.Ifthepatharoundthewallis50tiles,thealgorithmwillopenroughly7,854tiles,asshowninthisequation:
π×502=7,854
Inthesamescenario,greedybest-firstsearchwillcalculatealess-than-optimalpathbutopensubstantiallyfewertiles.It’snotaseasytovisualizehowthefrontierwillexpand,andit’snotimportantrightnow,soIwon’tgointoithere.Attheendoftheday,neitherofthesealgorithmsreallyfitsthepathfindingproblemwell.Theoptimalpathisslow,andthefastpathisn’toptimal.
Toquicklycalculateanoptimalpath,youneedtofuseDijkstra’salgorithmwithgreedybest-firstsearch.Luckily,someonehasalreadydonethis,andtheresultingalgorithmisamonsterknownasA-starsearch(oftenjustcalledA*).
A*usesthesumofacost,calledg,andaheuristic,calledh,toselectnodes.Theseresultingsumiscalledthescore.Putsimply,score=g+h.LikeDijkstra’salgorithm,A*cancalculatethemostoptimalpathfromatob,andlikegreedybest-firstsearch,itcandosorelativelyquickly.
AnA*SearchAlgorithmNowthatyouknowthefundamentals,let’swritecodetoimplementtheA*algorithm.Thisimplementationwillworkinatwo-dimensionalgrid.Itwon’tallowdiagonalmovementatfirst,butI’lldiscussinabithowyoucanmodifythecodetoworkwithdiagonalmovement,too.
AlloftheexamplecodeforthissectionisintheGameHackingExamples/Chapter11_SearchAlgorithmsdirectoryofthisbook’ssourcefiles.TheincludedprojectscanbecompiledwithVisualStudio2010,buttheyshouldalsoworkwithanyotherC++compiler.Downloadthemathttps://www.nostarch.com/gamehacking/andcompilethemtofollowalong.IfyouexecuteChapter11_SearchAlgorithms.exe,you’llbeabletodefineyourown20×20gridandwatchthealgorithmcalculateasearchpath.
CreatinganA*Node
![Page 307: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/307.jpg)
Tostart,defineanemptyAStarNodeclassasfollows:
typedefstd::shared_ptr<classAStarNode>AStarNodePtr;classAStarNode{public:};
ThiscodedefinestheAStarNodeclassandastd::shared_ptrtypedefinitioncalledAStarNodePtrtomakeiteasiertocreatesafepointerstotheclass.Next,withinthepublicscopeofthisclass,declaremembervariablesforthenode’sx-position,y-position,cost,andnode’sscore:
intx,y;intg,score;
Additionally,youneedapublicmemberoftypeAStarNodePtrthatreferencestheparentnode:
AStarNodePtrparent;
Afterdeclaringallmembervariables,declareapublicconstructorthatinitializesthemuponinstancecreation,asfollows:
AStarNode(intx,inty,intcost,AStarNodePtrp,intscore=0):x(x),y(y),g(cost),score(score),parent(p){}
Now,tomakecreatingsafepointerseasier,addastatichelperfunctionlikethis:
staticAStarNodePtrmakePtr(intx,inty,intcost,AStarNodePtrp,intscore=0){returnAStarNodePtr(newAStarNode(x,y,cost,p,score));}
ThismakePtr()functioncreatesanewinstanceofAStarNodeandreturnstheinstancewrappedinsideofanAstarNodePtr.
Let’srecap.TheAStarNodeclasshasmembervariablesx,y,g,score,andparent.Whentheclassisconstructed,allofthesemembersareinitializedfromvaluespassedtotheconstructor,withtheexceptionofscore,whichis
![Page 308: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/308.jpg)
optional(becauseyouuseitonlywhenmakingcopiesofanAStarNodeinstance)andsetto0ifnotprovided.
Next,defineapublicmemberfunctiontocalculatetheheuristicwhengiventhedestinationcoordinates:
intheuristic(constintdestx,intdesty)const{intxd=destx-x;intyd=desty-y;➊returnabs(xd)+abs(yd);}
ThisfunctionreturnstheManhattandistanceheuristic➊,adistancecalculationdesignedforgridswherediagonalmovementisnotpossible:
|Δx|+|Δy|Tocalculateapaththatallowsdiagonalmovement,you’dneedtomodify
thisfunctiontousetheEuclideandistanceheuristic,whichlookslikethis:
Theclassalsoneedsafunctiontoupdatescore.Youaddthatfunctiontothepublicscopeasfollows:
#defineTILE_COST1voidupdateScore(intendx,intendy){autoh=this->heuristic(endx,endy)*TILE_COST;this->score=g+h;}
Now,scoreshouldchangetog+hwhengivendestinationcoordinatestocalculateh.
Towrapup,thenodeclassalsoneedsafunctionthatcancalculateallofitschildnodes.Thefunctioncoulddothisbycreatingnewnodesforeachtileadjacenttothecurrentnode.Eachnewnodereferstothecurrentnodeasitsparent,sotheclassneedstobeabletocreateanAStarNodePtrtoacopyofthecurrentnodeaswell.Here’showallthatworks:
AStarNodePtrgetCopy(){returnAStarNode::makePtr(x,y,g,parent,score);
![Page 309: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/309.jpg)
}std::vector<AStarNodePtr>getChildren(intwidth,intheight){std::vector<AStarNodePtr>ret;autocopy=getCopy();if(x>0)➊ret.push_back(AStarNode::makePtr(x-1,y,g+TILE_COST,copy));if(y>0)➋ret.push_back(AStarNode::makePtr(x,y-1,g+TILE_COST,copy));if(x<width-1)➌ret.push_back(AStarNode::makePtr(x+1,y,g+TILE_COST,copy));if(y<height-1)➍ret.push_back(AStarNode::makePtr(x,y+1,g+TILE_COST,copy));returnret;}
Thisfunctioncreateschildnodesat(x–1,y)➊,(x,y–1)➋,(x+1,y)➌,and(x,y+1)➍.TheirparentisthenodethatcalledgetChildren,andtheirgistheparent’sgplusTILE_COST.
Toallowfordiagonalmovement,thisfunctionneedstoaddchildrenat(x–1,y–1),(x+1,y–1),(x+1,y+1),and(x–1,y+1).Additionally,ifmovingdiagonallywouldcostmore—thatis,ifthecharacterrequiresmoretimetodoit—you’dalsoneedtodothefollowing:
1. ChangeTILE_COSTto10.
2. DefineaconstantDIAG_TILE_COSTasTILE_COSTmultipliedbythetimeincrease.Ifadiagonalsteptakes1.5timesaslong,DIAG_TILE_COSTwouldbe15.
3. Givediagonalchildrenagoftheparent’sgplusDIAG_TILE_COST.
TofinishoffAStarNode,declareoperatorsforcomparingthepriorityandequalityoftwonodes.Youcouldplacethesedeclarationsoutsidetheclassinglobalscopelikethis:
➊booloperator<(constAStarNodePtr&a,constAStarNodePtr&b){returna.score>b.score;}
![Page 310: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/310.jpg)
➋booloperator==(constAStarNodePtr&a,constAStarNodePtr&b){returna.x==b.x&&a.y==b.y;}
Theseoperatorsallowstd::priority_queuetosortnodesbyscore➊andstd::findtodeterminenodeequalitybylocation➋.
WritingtheA*SearchFunctionNowthatyou’vecompletedtheAStarNodeclass,youcancodetheactualsearchfunction.Startbydefiningthefunctionprototype:
template<intWIDTH,intHEIGHT,intBLOCKING>booldoAStarSearch(intmap[WIDTH][HEIGHT],intstartx,intstarty,intendx,intendy,intpath[WIDTH][HEIGHT]){}
Theprototypeacceptsthegamemap’swidthandheight,aswellasthevaluethatsignifiesablockingtileonthemap,astemplateparameters.ThedoAStarSearch()functionalsotakesthemapitself(map),thestartingcoordinates(startxandstarty),thedestinationcoordinates(endxandendy),andablankmap(path)whereitcanfillthecalculatedpathwhenitfinishes.
NOTE
Thefirstthreeparametersaretemplateparameters,soyoucanpassthemascompiletimeconstants.I’vedonethisfortheexamplecodetoallowexplicitarraysizedeclarationsforthemapandpathparametersandtoallowadefinitevaluetosignifyblockingtilesonthemap.Inpractice,themapyoureadfromagamewillhaveadynamicsize,andyou’llprobablyneedamorerobustwaytopassthisdata.
Next,thedoAStarSearch()functionneedsasortedlisttoholdthefrontierandacontainertotrackallcreatednotessoyoucanupdatethescoreandparentofanexistingnodeifit’sopenedasachildofadifferentparent.Youcancreatetheseasfollows:
std::vector<AStarNodePtr>allNodes;
![Page 311: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/311.jpg)
std::vector<AStarNodePtr>allNodes;std::priority_queue<AStarNodePtr>frontier;
Thefrontierisdefinedwithstd::priority_queuesinceitcanautomaticallysortthenodesbasedontheirscore.Thenodecontainer,allNodes,isdefinedasastd::vector.
Now,let’screatethefirstnode:
autonode=AStarNode::makePtr(startx,starty,0,nullptr);node->updateScore(endx,endy);allNodes.push_back(node);
Thefirstnodeisano-costorphannodeattheposition(startx,starty).ThenodeisgivenascorebasedonwhattheupdateScore()functionreturns,andthenit’saddedtotheallNodescontainer.
Withanodeinthecontainer,it’stimetowritethemeatoftheA*algorithm,startingwithasimpleloop:
while(true){}
Untilotherwisespecified,therestofthecodeinthissectionwillappearinsideofthisloop,intheordershown.
Fromhere,thefirststepistocheckthegoalstate.Inthiscase,thegoalistofindapathfortheplayertofollowtothenextwaypoint,whichhappenswhenthenodeobject’spositionis(endx,endy).Thus,tocheckthegoalstate,theprogramneedstocheckwhethernodehasreachedthosecoordinatesornot.Here’showthatcheckshouldlook:
if(node->x==endx&&node->y==endy){makeList<WIDTH,HEIGHT>(node,allNodes,path);returntrue;}
Whenthegoalstateismet,theprogramreportstruebacktothecallerandfillspathwiththefinalpath.Fornow,assumeafunctioncalledmakeList()canfillinpathforyou;I’llshowyouthisfunctionshortly.Ifthegoalstateisn’tmet,youneedtoexpandthechildrenofnode,whichisactuallyaprettycomplicatedprocess:
autochildren=node->getChildren(WIDTH,HEIGHT);for(autoc=children.begin();c!=children.end();c++){
![Page 312: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/312.jpg)
➊if(map[(*c)->x][(*c)->y]==BLOCKING)continue;autofound=std::find(allNodes.rbegin(),allNodes.rend(),*c);➋if(found!=allNodes.rend()){➌if(*found>*c){(*found)->g=(*c)->g;(*found)->parent=(*c)->parent;(*found)->updateScore(endx,endy);}}else{(*c)->updateScore(endx,endy);➍frontier.push(*c);➎allNodes.push_back(*c);}}
Aftercallingnode->getChildrentogeneratealistofnodesthatcanbeaddedtothefrontier,thecodeiteratesovereachchildandignoresanythatareonblockingtiles➊.Next,foreachchild,thecodecheckswhetheranodehasalreadybeenopenedatthesamecoordinates➋.Ifso,andifthescoreoftheexistingnodeisgreaterthanthescoreofthenewchild,theexistingnodeisupdatedtotheparent,cost,andscoreofthenewchildbytheif()statementat➌.Ifthenewchilddoesn’thaveabrother-from-another-mother,itwillbeaddedasistothefrontier➍andthenodelist➎.
Alsonoticethatstd::findusesthereversebeginandreverseenditeratorsofallNodesinsteadoftheregulariterators➊.Theexampledoesthisbecausenewnodesareappendedtotheendofthevectorandduplicatenodeswillbeclosetogether,soduplicateswillusuallybeclosertotheendofthevector.(Thisstepcouldalsobedonedirectlyagainstthefrontier,butstd::priority_queuedoesn’tallowiterationovernodesandwritingthesortinplacewouldmakethecodetoolargeforprint.)
Eventually,thefunctionwillrunoutofnewchildrentoaddtothefrontier;thefollowingif()statementhandlesthatsituation:
if(frontier.size()==0)returnfalse;➊node=frontier.top();➋frontier.pop();
Thiscodepointsnodetothecheapestnodefromthefrontier➊,removesitfromthefrontier➋,andletsthelooprepeat.Ifthefrontierendsup
![Page 313: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/313.jpg)
empty,thefunctionreportsfalsebacktothecaller,sincethere’snothinglefttosearch.
CreatingthePathListFinally,it’stimetoimplementthemakeList()function:
template<intWIDTH,intHEIGHT>voidmakeList(AStarNodePtrend,std::vector<AStarNodePtr>nodes,intpath[WIDTH][HEIGHT]){for(auton=nodes.begin();n!=nodes.end();n++)➊path[(*n)->x][(*n)->y]=2;autonode=end;while(node.get()!=nullptr){➋path[node->x][node->y]=1;node=node->parent;}}
Thisfunctionupdatespathwithbothalistofclosednodes➊andthecalculatedpath➋.Forthisexample,thevalue2representstheclosednodesand1representsthepathnodes.Theprogramcalculatesnodesinthepathbyfollowingparentnodesfromthegoalnodeuntilitreachesthestartingnode,whichisanorphanwithnullptrasaparent.
WhenA*SearchesAreParticularlyUsefulMakesuretoplaywiththeexamplecodeandexecutablefortheprevioussection,becausethat’stheonlywayyou’llreallygetacquaintedwiththebehaviorofA*searches.Inmostnewergames,youshouldbeabletojustsendapacketwiththedestinationorevenemulateaclickonthemapatthedesiredspot,butwhenyoucomeacrossasituationwhereyouneedtocalculateapath,you’llbegladyoulearnedA*.
Thereareactuallymanysituationswherecalculatingapathcanbeuseful:
SelectingtargetsWhen your bot is selecting targets to attack, you may want to checkwhetheryourcharactercanactuallyreachthem.Otherwise,ifanenemy
![Page 314: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/314.jpg)
isisolatedinanunreachableroom,youmightgetstuckinplacetryingtotargetthemforever!
SelectingcorpsesAs your looting state(s) determine which corpses to open, you canoptimizebyalwaystryingtoloottheclosestcorpsefirst.
EmulatingmousemovementsVery rarely, some heavily protected games actually correlate in-gameactionswithmousemovementstoensurethatthere’snobotrunning.Inthis case, you might need to emulate the mouse. Using a modifiedversionofA*where the screen is themap, there are no blocking tiles,and node costs are slightly randomized, you can calculate human-likepathsforyourmousetofollowwhenyousimulatemovement.
KitingmonstersIfyoueverneed towritecode tokitemonsters,youcan implementA*withagoalstateofbeingNunitsawayfromallcreatures.Usingthesamecostmechanismshown in thischapter,playwith theheuristic togiveahigher cost to nodes that are closer to creatures.Kiting isn’t exactly aconventionalusecase,andtheheuristicwillrequireabunchoftweaking,butitworksamazinglyonceyou’vegotitgoing.Someimplementationscankiteanynumberofmonstersbetterthanahuman!
PredictingenemymovementsIfyou’rewritingabotthatfightsotherplayers,youcanuseA*topredicttheirmovementsandactaccordingly.Forinstance,ifyourenemystartsrunning away, your bot can assume they are running to their base,calculatetheirroute,anduseaspelltoblocktheirpathoreventeleporttoalocationwhereitexpectsthemtobe.
ThesearejustafewusecasesforA*searches,andyou’lldefinitelyfindmanymoreasyouimproveyourbots.Fortherestofthechapter,I’lldescribesomepopularautomatedhacksthatyoucanimplementusingthetechniquesdescribedinthisbook.
![Page 315: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/315.jpg)
OTHERUSESFORA*SEARCHA*isn’tjustforcalculatingpaths.WithabstractionsontopoftheAStarNodeclass,youcanadaptthesamealgorithmtoanysearchproblem.Realistically,A*isjustaweightediterationoveramultidimensionaldatasetthatiteratesuntilsomegoalobjectisfound,and,thus,itcansolveanyproblemthatcanberepresentedasamultidimensionaldataset.MoreadvancedapplicationsforA*includeplayingchessandcheckers,and—whenit’spairedwithathree-dimensionalManhattandistanceheuristicandadepth-firstsearchimplementation—evensolvingaRubik’scube.Sadly,I’mnotgoingtogointotheseusecases;ifyouwanttogetreallygoodwithsearchalgorithms,Iencourageyoutoresearchmoreonline.
CommonandCoolAutomatedHacksNowthatyou’veseenthedesignpatternsandalgorithmsneededtocreateefficient,self-teachingbots,it’stimetolearnaboutsomepopularautomatedhacksthatgobeyondsimplehealingandpathfinding.Let’sflyupto10,000feettoexploretwotypesofbotsatahighlevel.
LootingwithCavebotsWhilediscussingcontroltheory,statemachines,andsearchalgorithms,Itouchedontheideaofacavebotthatkillscreatures,grabsloot,andwalksaroundcaves.Theabilitiesofcavebotscanvarygreatly.
DepositingGoldandRestockingSuppliesIfyouwanttoleaveacharacterbottingfordaysonend,you’llneedadepositorandarefiller.Adepositorcandepositlootinyourbankorvault,whilearefillerrefillsyourpotions,runes,andothersupplies.Thesefeaturescanbedescribedwithsixbasicstates:
LeavespawnConditionmetifthecharacterisinthespawnareaorcave,
![Page 316: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/316.jpg)
ifithasnothingtodeposit,andifithasenoughsupplies.Reachthisstatebyexitingthespawnareaorcave.
WalktotownConditionmetifthecharacterisinthespawnareaorcave.Reachthisstatebywalkingfromthespawnorcavetotown.
DepositConditionmetifthecharacterisinthespawnareaorcave,orifthecharacterisintownandhasnothingtodeposit.Reachthisstatebyputtinglootinthebankorvault.
WithdrawcashConditionmetifthecharacterisinthespawnareaorcave,isintownwithnosuppliestopurchase,orhasenoughgoldtopurchasesupplies.Reachthisstatebywithdrawinggoldfromthebankorvault.
PurchasesuppliesConditionmetifthecharacterisinthespawnareaorcaveorifthecharacterhasenoughsuppliestostarthunting.Reachbybuyingsupplies.
EnterspawnConditionmetifthecharacterisinthespawnareaorcave.Reachthisstatebywalkingtothespawnareaorcave.
Thesestateswouldcomebeforethestatesrelatedtofollowingwaypoints(Idescribeacoupleofthosestatesin“AComplexHypotheticalStateMachine”onpage228)inthevectorofStateDefinitionobjects.Placingthemfirstgivesthempriorityoverremaininginthecave,whilestillallowingthecharactertotarget,kill,andlootmonstersonthewaybacktotown.Dependingonwhereyou’rehuntingandhowyouwantthebottobehave,youmayalsotellyourtargetingstatesnottoattackcreaturesifthecharacterisn’tinthespawnareaorcave,andyoumightaddanextrastatebeforewalktotownthatattacksonlycreaturesthatblockthecharacter’spathtotown.Specifyingthatextrastateincreasesthebot’sefficiency,sincetripstoandfromtownwillbemuchquickerifthemonstersonthewayaren’tworthkilling.
UsingtheCharacterasBaitTwoothercavebotfeaturesthatcanmakeyourbotawesomeareluremodeanddynamiclure.Youwouldn’timplementthesetwofeaturesasactualstatesinacomplexbot;rather,you’dhavetheminformthebot’stargetingandwalkingstatestohelpthebotmakedecisions.
![Page 317: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/317.jpg)
Youcancontrolluremodewithspecialwaypointsinyourpath,anditscodewilltellyourtargetingstatestoattackcreaturesonlyifthebotisstuck,similartothemechanismdiscussedforwalkingtoorfromtown.Thedifferenceisthatluremodecanbeswitchedonandoffatdifferentareasinthecave,allowingyoutoluremultiplemobsofmonsterstocertainlocationsbeforeattackingthem.Thiscanmakeyourbotmuchmoreefficient,ascertaintypesofcharactersmayexcelatkillingmanymonstersatonce.
Dynamiclureissimilar,butinsteadofturningitonandoffatdefinitelocationsviawaypoints,youcanautomaticallyturnluremodeonwhentherearen’tenoughmonsters.Forexample,abotwiththedynamiclurefeaturemighttellthetargetingstatesnottoattackanycreatureuntilfivemonstersareonscreen.Thetargetingstateswouldresumeattackingandkitinguntilallfivemonstersaredead,andthebotwouldsnapbackintoluremodeuntilasuitablysizedmobappearsagain.
Ifyourcharacterisquickenoughtooutrunmonsters,though,you’llneedtomodifyyourbot’swalkingstatestowalkslowlywhenluremodeisonandcreaturesarepresent.Otherwise,yourcharacterwillleavemobsbehindwithoutkillingthem.Youcanslowdownacharacterbyaddingastatebeforethefollowpathstateinyourstatemachinedefinitionthatdelaysmovementslightlywhenluremodeisonandanycreaturesaretoofaraway.
AllowingPlayerstoScriptCustomBehaviorsNearlyeverycavebotincludesascriptinginterfacethatallowsplayerstoaddtheirownbehaviors.Youcouldimplementthisinterfaceasawaytospecifycustomwaypointstofollow,spellstouse,oritemstoloot.Inmoreadvancedbots,youmightmakeyourtargeting,looting,walking,andluringsystemsasdynamicaspossiblesoplayerscanadduniquefeatures.IfyouimplementyourautomationinLua,thirdpartiescouldeasilyimproveandexpandyourbot’sabilities.
Makingyourboteasytowritescriptsfortakesalotofworkoffyourshoulders,sinceotherprogrammerswhoplaythegamemightreleasescriptstoaddsupportfornewhuntingspotsandimproveyourautomation.Suchscriptingservicesarecommoninbottingcommunities,andplayersoftencreateandsellprofessional-gradescriptsthatintegratewithbots.
![Page 318: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/318.jpg)
AutomatingCombatwithWarbotsAnotherclassofautomatedbotsisusedforplayerversusplayer(PvP)combat.Thesewarbots,orPvPbots,havemanyfeaturescategorizedasresponsiveorESPhacks,sincethebotsfocusonrespondingtoincomingdamageorspells,revealinghiddenenemies,andgivingtheplayeraninformationadvantage.
Fullyautomatedwarbotsarerare,butI’vealreadylightlydiscussedhowyoucanusesomeautomationtechniquestomakesmarterhealers,teachbotstolandmoreaccurateskillshots,andpredictplayers’pathstostopthemintheirtracks.Let’sexploreafewothercoolhacksthatfallonthefringeofresponsive,ESP,andautomated.
NOTE
IngamesthatarecompletelyPvPbased,suchasbattlegroundsorreal-timestrategygames,someplayersmightalsojustcallthesebots,sincewarorPvPisthebot’sonlypurpose.
AutowallBotsIfyourcharacterhasa spell tocreatea temporarywall,youcancodeabot that automatically blocks enemy players when they enter smallcorridors.Usingerrorcorrection, thebotcould learnhow faraheadoftheenemytoplacethewall.Withsomereallycreativeengineering,thebot could even learn which enemies can jump over walls by checkingwhethereachenemymanagestogetpastthewallbeforeitdisappears.
AutosnipeBotsForcharacterswithalong-rangeskillshotorglobalexecutionspell,youcan use automation to detect when an enemy across themap has lowhealthandcastyourspelltokillthem.Youcanalsouseerrorcorrectiontomoreaccuratelyguesswheretoshootalong-rangeskillshot.Ifyou’reunabletocalculateexactdamageamounts,errorcorrectioncanalsohelpa bot determine howmuch damage a spell does and tweak the castingthresholdaccordingly.
AutokiteBotsIf you’re playing a carry character that does most of its damage by
![Page 319: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/319.jpg)
attackingatashortdistance,youmightimplementabottoautomaticallykiteenemies.Usingasetofstatessimilartotheonesacavebotmightuseto kite monsters, you can make a bot that automatically kites enemycharacterswhenyouattack them.Whenyou stop targeting theenemy,the bot can stop kiting. Using A* search, you can improve the kitingmechanism to avoidmultiple enemies, or, if you want to escape whileattacking,guidethekitingmechanismbacktoasafeplace,suchasyourteam’sbaseoraneutrallocation.
ClosingThoughtsBythispoint,youshouldbereadytogooutandmakesomeprettyawesomebots.Don’tworryifyou’restillnotcompletelycomfortablewiththetechniquesinthischapter;thebestwaytolearnistojustdiveinandstarthacking.Usethethousandsoflinesofexamplecodeprovidedforthisbooktogetstartedwithoutworkingfromscratch,andmostofall,havefun!
Inthenextchapter,I’lldiscusswaysthatbotscanhidefromanti-cheatmechanisms,whicharepiecesofsoftwarethatgamesusetodetectandstopbotters.
![Page 320: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/320.jpg)
12STAYINGHIDDEN
Gamehackingisanever-evolvingpractice,agameofcatandmousebetweenhackersandgamedeveloperswhereeachpartyworkstosubverttheother.Aslongaspeoplemakebots,gamecompanieswillfindwaystohinderbotadvancesandbanplayerswhousebots.Ratherthanmakingtheirgamesinherentlyhardertohack,though,gamecompaniesfocusondetection.
Thelargestgamecompanieshaveverysophisticateddetectionsuitescalledanti-cheatsoftware.Inthebeginningofthischapter,I’lldiscussthecapabilitiesofthemostcommonanti-cheatsuites.Afterrevealinghowthesesuitesdetectbots,I’llteachyousomepowerfulwaystoevadethem.
ProminentAnti-CheatSoftwareThebest-knownanti-cheatsuitesusethesamemethodsasmostantivirussoftwaretoscanforbotsandflagthemasthreats.Someanti-cheatsuitesarealsodynamic,meaningtheirinnerworkingsandcapabilitiescanchangebasedonthegamethey’reprotecting.Anti-cheatsoftwaredevelopersalsotrackdownandpatchtheirsuitesagainstbypasssoftware,soalwaysdoyourownin-depthresearchofanyanti-cheatsoftwarethatyoumightface.
Whenthesesuitesdetectabotter,theyflagthebotter’saccountforbanishment.Everyfewweeks,gamecompanyadministratorsbantheflaggedplayersinabanwave.Gamecompaniesusebanwavesinsteadof
![Page 321: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/321.jpg)
instantaneousbansbecausebanninginwavesismoreprofitable.Ifbottersarebannedafterafewweeksofplaying,theirfamiliaritywiththegamewillmakethemmorelikelytobuyanewaccountthaniftheywerebannedthemomenttheirbotstartedrunning.
Therearedozensofanti-cheatsuites,butI’llfocusonthefivepackagesthatarethemostcommonandthoroughlyunderstood:PunkBuster,ESEAAnti-Cheat,ValveAnti-Cheat(VAC),GameGuard,andWarden.
ThePunkBusterToolkitPunkBuster,madebyEvenBalanceInc.,istheoriginalanti-cheattoolkit.ManygamesusePunkBuster,butit’smostcommoninfirst-personshootergameslikeMedalofHonor,FarCry3,andseveralinstallmentsoftheBattlefieldseries.
Thetoolkitusesamyriadofdetectionmethods,themostformidableofwhicharesignature-baseddetection(SBD),screenshots,andhashvalidation.PunkBusterisalsoknownforimposinghardwarebansthatpermanentlybanacheater’scomputer,ratherthanjusttheirgameaccount,bysavingafingerprintofthehardware’sserialnumbersandblockingloginsfromamachinethatmatchesit.
Signature-BasedDetectionPunkBusterscansthememoryofallprocessesonasystemrunningagamethatemploysit,searchingforbytepatternsuniquetoknowncheatsoftware,calledsignatures.IfPunkBusterdetectsasignature,theplayerisflaggedforaban.PunkBustercarriesoutmemoryscansfromusermodeusingtheNtQueryVirtualMemory()WindowsAPIfunction,anditsometimesrunsscansfrommultiplehiddenprocesses.
Signature-baseddetectionisblindtocontextbydesign,anditultimatelysuffersfromafatalflaw:falsepositives.OnMarch23,2008,ateamofhackerssetouttoprovetheexistenceofthisflawbyspammingpublicchatroomswithatextstringthatPunkBusterwouldidentifyasabotsignature.SinceSBDblindlyscansprocessmemoryformatchingpatterns,anyandalllegitimateplayersinsidethesepublicchatroomswereflaggedasbotters.
![Page 322: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/322.jpg)
Thiscausedthousandsoffairplayerstobebannedwithnojustification.AsimilarsituationhappenedagaininNovember2013:PunkBusterfalselybannedthousandsofplayersonBattlefield4.Thattime,noonewastryingtoproveapoint;thecompanyhadjustaddedabadsignaturetoitssoftware.
PunkBusterresolvedbothoftheseissuesbyrestoringtheplayers’accounts,buttheseincidentsshowjusthowaggressiveitsflavorofSBDis.Inthetimesincetheseattacks,though,PunkBuster’sSBDhasreducedthenumberoffalsepositivesbycheckingonlyforsignaturesatpredefinedbinaryoffsets.
ScreenshotsAsanothermethodofbotdetection,PunkBusteralsoperiodicallytakesscreenshotsofaplayer’sscreenandsendsthemtothecentralgameserver.Thisformofdetectionisanuisance,andit’sweakcomparedtoSDB.Game-hackingcommunitiesspeculatethatPunkBusterimplementedthisfeaturetogivegameadminsproofagainstbotterswhodisputebans.
HashValidationInadditiontoemployingSBDandscreenshots,PunkBusterdetectsbotsbycreatingcryptographichashesofagame’sexecutablebinariesonaplayer’ssystemandcomparingthemtohashesstoredonacentralserver.Ifthehashesdonotmatch,theplayerisflaggedforaban.Thischeckiscarriedoutonlyonthebinariesonthefilesystem,notonin-memorybinaries.
TheESEAAnti-CheatToolkitTheESEAAnti-CheattoolkitisusedbytheE-SportsEntertainmentAssociation(ESEA),primarilyforitsCounter-Strike:GlobalOffensiveleague.UnlikePunkBuster,thissuiteisknownforgeneratingveryfewfalsepositivesandbeinghighlyeffectiveatcatchingcheaters.
ESEAAnti-Cheat’sdetectioncapabilitiesresemblethoseofPunkBuster,withonenoteworthydifference.ESEAAnti-Cheat’sSBDalgorithmiscarriedoutfromakernel-modedriverusingthreedifferentWindowsKernelfunctions:theMmGetPhysicalMemoryRanges()function,theZwOpenSection()
![Page 323: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/323.jpg)
function,andtheZwMapViewOfSection()function.Thisimplementationmakestheanti-cheatsystemnearlyimmunetomemoryspoofing(acommonwaytodefeatSBD),asthefunctionsusedbythescanaremuchhardertohookwhenthey’recalledfromadriver.
TheVACToolkitVACisthetoolkitValveCorporationappliestoitsowngamesandmanyofthethird-partygamesavailableonitsSteamgamingplatform.VACusesSDBandhashvalidationmethodsthatresemblePunkBuster’sdetectiontechniques,anditalsousesDomainNameSystem(DNS)cachescansandbinaryvalidation.
DNSCacheScansDNSisaprotocolthatconvertsbetweendomainnamesandIPaddressessmoothly,andtheDNScacheiswherethatinformationgetsstoredonacomputer.WhenVAC’sSBDalgorithmdetectscheatsoftware,VACscanstheplayer’sDNScacheforanydomainnamesassociatedwithcheatingwebsites.It’snotcertainwhetherapositiveDNScachescanisrequiredforVAC’sSBDalgorithmtoflagaplayerforbanishment,oriftheDNScachescansimplyactsasanothernailinthecoffinforplayerswhoarealreadyflaggedbySBD.
NOTE
ToseeyourDNScache,enteripconfig/displaydnsatacommandprompt.Yes,VAClooksatallofthat.
BinaryValidationVACalsousesbinaryvalidationtopreventin-memorytamperingofexecutablebinaries.ItscansformodificationslikeIAT,jump,andcodehookingbycomparinghashesofin-memorybinarycodetohashesofthesamecodeinthebinariesonthefilesystem.Ifitfindsamismatch,VACflagstheplayerforaban.
![Page 324: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/324.jpg)
Thisdetectionmethodisformidable,butValve’sinitialimplementationofthealgorithmwasflawed.InJuly2010,VAC’sbinaryvalidationfalselybanned12,000CallofDutyplayers.ThebinaryvalidationmodulefailedtoaccountforaSteamupdate,anditbannedtheplayerswhentheirin-memorycodedidnotmatchtheupdatedbinariesonthefilesystem.
FalsePositivesVAChashadotherissueswithfalsepositives.Itsinitialreleaseroutinelybannedfairplayersfor“faultymemory.”ThissameearlyversionbannedplayersforusingCedega,aplatformthatranWindowsgamesonLinux.AndonApril1,2004,Valvefalselybannedacouplethousandplayersduetoaserver-sideglitch.Ontwoseparateoccasions,oneinJune2011andoneinFebruary2014,VACalsofalselybannedthousandsofTeamFortress2andCounter-Strikeplayersduetobugsthatthecompanyrefusestodisclose.AswithPunkBuster,theseincidentsshowthatVACisveryaggressive.
TheGameGuardToolkitGameGuardisananti-cheattoolkitmadebyINCAInternetCo.Ltd.andusedbymanyMMORPGs,includingLineageII,CabalOnline,andRagnarokOnline.InadditiontosomemildlyaggressiveSBD,GameGuardusesrootkitstoproactivelypreventcheatsoftwarefromrunning.
User-ModeRootkitGameGuardutilizesauser-moderootkittodenybotsaccesstotheWindowsAPIfunctionstheyusetooperate.Therootkithooksthefunctionsattheirlowest-levelentrypoint,ofteninsideundocumentedfunctionsinntdll.dll,user32.dll,andkernel32.dll.ThesearethemostnotableAPIfunctionsGameGuardhooks,andhere’swhatGameGuarddoesfrominsideeachhookedfunction:
NtOpenProcess()BlocksanyOpenProcess()attemptsonthegamebeingprotected.
NtProtectVirtualMemory()BlocksanyVirtualProtect()or
![Page 325: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/325.jpg)
VirtualProtectEx()attemptsonthegame.
NtReadVirtualMemory()andNtWriteVirtualMemory()BlockanyReadProcessMemory()andWriteProcessMemory()attemptsonthegame.
NtSuspendProcess()andNtSuspendThread()BlockanyattemptstosuspendGameGuard.
NtTerminateProcess()andNtTerminateThread()BlockanyattemptstoterminateGameGuard.
PostMessage(),SendMessage(),andSendInput()Blockanyattemptstosendprogrammaticinputtothegame.
SetWindowsHookEx()Preventsbotsfromgloballyinterceptingmouseandkeyboardinput.
CreateProcessInternal()Automaticallydetectsandhooksintonewprocesses.
GetProcAddress(),LoadLibraryEx(),andMapViewOfFileEx()PreventanyattempttoinjectlibrariesintothegameorGameGuard.
Kernel-ModeRootkitGameGuardalsousesadriver-basedrootkittopreventbotsthatworkinthekernel.Thisrootkithasthesameabilitiesasitsuser-modecounterpart,anditworksbyhookingZwProtectVirtualMemory(),ZwReadVirtualMemory(),ZwWriteVirtualMemory(),SendInput(),andsimilarfunctions.
TheWardenToolkitWarden,madeexclusivelyforBlizzard’sgames,isbyfarthemostadvancedanti-bottoolkitI’veencountered.It’shardtosaywhatexactlyWardendoes,becauseitdownloadsdynamiccodeatruntime.Thiscode,deliveredascompiledshellcode,typicallyhastworesponsibilities:
•Detectbots.
•Periodicallysendaheartbeatsignaltothegameserver.Thevaluesentisnotpredefinedbutinsteadisgeneratedbysomesubsetofthedetectioncode.
![Page 326: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/326.jpg)
code.
IfWardenfailstocompletethesecondtaskorsendsthewrongvalue,thegameserverwillknowthatit’sbeendisabledortamperedwith.Furthermore,abotcan’tdisablethedetectioncodeandleavetheheartbeatcoderunning.
THEHALTINGPROBLEM
AbotthatcoulddisableWarden’sdetectioncodeandstillsendtheheartbeatsignalwouldsolvethehaltingproblem,whichAlanTuringprovedtobeimpossiblein1936.Thehaltingproblemistheproblemofdetermining,withagenericalgorithm,whetheraprogramwillfinishrunningorcontinueforever.BecauseWardendoestwotasksusingthesameshellcode,writingagenericalgorithmthatcandisablejustonetaskisavariationofthehaltingproblem:thealgorithmcan’tbesurewhichpartsofthecodewilldefinitelyexecute,whichpartswon’t,andwhichpartsareresponsibleforeachtask.
Wardenisformidablebecauseyounotonlyhavenowaytoknowwhatyou’rehidingfrombutalsohavenowaytodisablethetoolkit.Evenifyoumanagetoavoiddetectiontoday,anewdetectionmethodmightbeusedtomorrow.
Ifyouplanonpubliclydistributingbots,youwilleventuallymeetoneoftheanti-cheatsolutionsdescribedintheprevioussections—andyou’llhavetobeatit.Dependingonyourbot’sfootprint,thetypeofdetectioninthegameyou’rebotting,andyourimplementation,thedifficultyofevadingoneofthesetoolkitscanrangefromtrivialtoextremelyhard.
CarefullyManagingaBot’sFootprintAbot’sfootprintishowmanyunique,detectablecharacteristicsithas.Forexample,abotthathooks100functionswilltypicallybeeasiertodetectthanabotthathooksonly10functionsbecausetheformermakesanorderofmagnitudemorechangestoagame’scodethanthelatter.Sinceatargeted
![Page 327: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/327.jpg)
detectionsystemneedstodetectonlyonehook,thedeveloperoftheformerbotneedstospendmuchmoretimemakingsureallofthebot’shooksareasstealthyaspossible.
Anotherfootprintcharacteristicishowdetailedabot’suserinterfaceis.Ifaknownbothasmanydialogboxesthatallhavespecifictitles,agamecompanycanjusthaveitsanti-cheatsoftwaredetectthebotbysearchingforwindowsthathavethosetitles.Thissamebasicreasoningcanbeusedwithprocessnamesandfilenames.
MinimizingaBot’sFootprintDependingonhowyourbotworks,therearemanywaystominimizeitsfootprint.Ifyourbotreliesheavilyonhooks,forinstance,youcanavoiddirectlyhookingagame’scodeandinsteadfocusonhookingWindowsAPIfunctions.WindowsAPIhookingissurprisinglycommon,sodeveloperscan’tassumeaprogramthathookstheWindowsAPIisabot.
Ifyourbothasawell-defineduserinterface,youcanmasktheinterfacebyremovingallstringsfromwindowbars,buttons,andsoon.Instead,displayimagesthatshowtext.Ifyou’reworriedaboutspecificprocessnamesorfilenamesbeingdetectedbytheanti-cheatsoftware,usegenericfilenamesandmakeyourbotcopyitselftoanew,randomizeddirectoryeverytimeitlaunches.
MaskingYourFootprintMinimizingyourfootprintisapreferredwaytoavoiddetection,butit’snotnecessary.Youcanalsoobfuscateyourbot,makingitharderforanyonetofigureouthowitworks.Obfuscationcanpreventbothanti-botdevelopersfromtryingtodetectyourbotandotherbotdevelopersfromanalyzingyourbottostealproprietaryfunctionality.Ifyousellyourbot,obfuscationpreventspeoplefromcrackingittobypassyourpurchaseverification,too.
Onecommontypeofobfuscationiscalledpacking.Packinganexecutableencryptsitandhidesitinsideanotherexecutable.Whenthecontainerexecutableislaunched,thepackedexecutableisdecryptedandexecutedin-memory.Whenabotispacked,analyzingthebinarytolearnwhatthebotdoesisimpossible,anddebuggingthebotprocessismuchharder.SomecommonpackerprogramsareUPX,Armadillo,Themida,andASPack.
![Page 328: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/328.jpg)
TeachingaBottoDetectDebuggersWhenanti-botdevelopers(orotherbotcreators)candebugabot,theycanfigureouthowitworksandthushowtostopit.Ifsomeoneisactivelytryingtopickapartabot,packingtheexecutablemaynotbeenoughtoevadethem.Toprotectagainstthis,botsoftenemployanti-debuggingtechniques,whichobfuscatecontrolflowbychangingthebot’sbehaviorwhenadebuggerisdetected.Inthissection,I’llquicklycoversomewell-knownmethodsfordetectingwhenadebuggerisattachedtoyourbot,andinthenext,I’llshowyousometricksforobfuscation.
CallingCheckRemoteDebuggerPresent()CheckRemoteDebuggerPresent()isaWindowsAPIfunctionthatcantellyouifadebuggerisattachedtothecurrentprocess.Codetocheckforadebuggermightlooklikethis:
boolIsRemoteDebuggerPresent(){BOOLdbg=false;CheckRemoteDebuggerPresent(GetCurrentProcess(),&dbg);returndbg;}
Thischeckisprettystraightforward—itcallsCheckRemoteDebuggerPresent()withthecurrentprocessandapointertothedbgBoolean.Callingthisfunctionistheeasiestwaytodetectadebugger,butit’salsoveryeasyforadebuggertoevade.
CheckingforInterruptHandlersInterruptsaresignalstheprocessorsendstotriggeracorrespondinghandlerintheWindowskernel.Interruptsaretypicallygeneratedbyhardwareevents,buttheycanalsobegeneratedinsoftwareusingtheINTassemblyinstruction.Thekernelallowssomeinterrupts—namely,interrupts0x2Dand0x03—totriggeruser-modeinterrupthandlersintheformofexceptionhandlers.Youcantakeadvantageoftheseinterruptstodetectdebuggers.
Whenadebuggersetsabreakpointonaninstruction,itreplacesthatinstructionwithabreakpointinstruction,suchasINT0x03.Whentheinterruptisexecuted,thedebuggerisnotifiedviaanexceptionhandler,whereithandlesthebreakpoint,replacestheoriginalcode,andallowstheapplicationtoresumeexecutionseamlessly.Whenfacedwithan
![Page 329: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/329.jpg)
applicationtoresumeexecutionseamlessly.Whenfacedwithanunrecognizedinterrupt,somedebuggersevensilentlystepoverthatinterruptandallowexecutiontocontinuenormally,withouttriggeringanyotherexceptionhandlers.
Youcandetectthisbehaviorbypurposelygeneratinginterruptswithinexceptionhandlersinyourcode,asshowninListing12-1.
inlineboolHas2DBreakpointHandler(){__try{__asmINT0x2D}__except(EXCEPTION_EXECUTE_HANDLER){returnfalse;}returntrue;}
inlineboolHas03BreakpointHandler(){__try{__asmINT0x03}__except(EXCEPTION_EXECUTE_HANDLER){returnfalse;}returntrue;}
Listing12-1:Detectinginterrupthandlers
Duringnormalexecution,theseinterruptstriggertheexceptionhandlerssurroundingtheminthecode.Duringadebuggingsession,somedebuggersmightintercepttheexceptionsgeneratedbytheseinterruptsandsilentlyignorethem,preventingthesurroundingexceptionhandlersfromexecuting.Thus,iftheinterruptsdon’ttriggeryourexceptionhandler,thenadebuggerispresent.
CheckingforHardwareBreakpointsDebuggerscanalsosetbreakpointsusingtheprocessor’sdebugregisters;thesearecalledhardwarebreakpoints.Adebuggercansetahardwarebreakpointonaninstructionbywritingtheaddressoftheinstructiontooneofthefourdebugregisters.
Whenanaddresspresentonadebugregisterisexecuted,thedebuggerisnotified.Todetecthardwarebreakpoints(andthus,thepresenceofadebugger),youcancheckfornonzerovaluesonanyofthefourdebugregisterslikethis:
boolHasHardwareBreakpoints(){CONTEXTctx={0};ctx.ContextFlags=CONTEXT_DEBUG_REGISTERS;autohThread=GetCurrentThread();
![Page 330: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/330.jpg)
if(GetThreadContext(hThread,&ctx)==0)returnfalse;return(ctx.Dr0!=0||ctx.Dr1!=0||ctx.Dr2!=0||ctx.Dr3!=0);}
PrintingDebugStringsOutputDebugString()isaWindowsAPIfunctionthatcanbeusedtoprintlogmessagestoadebuggerconsole.Ifnodebuggerispresent,thefunctionwillreturnwithanerrorcode.Ifadebuggerispresent,however,thefunctionwillreturnwithnoerrorcode.Here’showyoucanusethisfunctionasatrivialdebuggercheck:
inlineboolCanCallOutputDebugString(){SetLastError(0);OutputDebugStringA("test");return(GetLastError()==0);}
LiketheCheckRemoteDebuggerPresent()method,thismethodisverystraightforwardbutalsoveryeasyforadebuggertoevade.
CheckingforDBG_RIPEXCEPTIONHandlersDebuggerstypicallyhaveexceptionhandlersthatblindlycatchexceptionswithWindows’DBG_RIPEXCEPTIONexceptioncode,makingthatcodeaclearwaytospotadebugger.YoucandetecttheseexceptionhandlersinmuchthesamewayListing12-1detectsinterrupthandlers:
#defineDBG_RIPEXCEPTION0x40010007inlineboolhasRIPExceptionHandler(){__try{RaiseException(DBG_RIPEXCEPTION,0,0,0);}__except(EXCEPTION_EXECUTE_HANDLER){returnfalse;}returntrue;}
TimingControl-CriticalRoutinesIfananti-botdeveloperisdebuggingyourbot,thedeveloperwilllikelyplacebreakpointsonandsingle-stepthroughpartsofyourcodethatarecriticaltothebot’sbehavior.Youcandetectthisactivitybymeasuringcodeexecutiontimes;whensomeonestepsthroughcode,executiontakesalotlongerthanusual.
![Page 331: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/331.jpg)
usual.Forexample,ifafunctiononlyplacessomehooks,youcanbesurethat
thecodeshouldn’ttakemorethanatenthofasecondtodothememoryprotection.YoucouldchecktheexecutiontimeformemoryprotectionwithhelpfromtheGetTickCount()WindowsAPIfunction,asfollows:
--snip--autostartTime=GetTickCount();protectMemory<>(...);if(GetTickCount()-startTime>=100)debuggerDetectedGoConfuseIt();--snip--
CheckingforDebugDriversSomedebuggersloadkernel-modedriverstoassisttheiroperation.Youcandetectthesedebuggersbyattemptingtogetahandletotheirkernel-modedrivers,likethis:
boolDebuggerDriversPresent(){//anarrayofcommondebuggerdriverdevicenamesconstchardrivers[9][20]={"\\\\.\\EXTREM","\\\\.\\ICEEXT","\\\\.\\NDBGMSG.VXD","\\\\.\\RING0","\\\\.\\SIWVID","\\\\.\\SYSER","\\\\.\\TRW","\\\\.\\SYSERBOOT","\0"};for(inti=0;drivers[i][0]!='\0';i++){autoh=CreateFileA(drivers[i],0,0,0,OPEN_EXISTING,0,0);if(h!=INVALID_HANDLE_VALUE){CloseHandle(h);returntrue;}}returnfalse;}
Thereareafewcommonkernel-modedriverdevicenamestocheckfor,like\\\\.\\EXTREMandtheothersshowninthedriversarray.Ifthishandle-fetchingcodesucceeds,thenthere’sadebuggerrunningonthesystem.Unlikewiththepreviousmethods,though,obtainingahandletooneofthosedriversdoesn’talwaysmeanthedebuggerisattachedtoyourbot.
![Page 332: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/332.jpg)
Anti-DebuggingTechniquesOnceyoudetectadebugger,therearemultiplewaystoobfuscateyourcontrolflow.Forinstance,youmighttrytocrashthedebugger.ThefollowingcodecrashesOllyDbgv1.10:
OutputDebugString("%s%s%s%s");
Thestring"%s%s%s%s"containsformatspecifiers,andOllyDbgpassesittoprintf()withoutanyextraparameters,whichiswhythedebuggercrashes.Youcouldplacethiscodeinafunctionthatgetscalledinresponsetodetectingadebugger,butthisoptionworksonlyagainstOllyDbg.
CausinganUnavoidableInfiniteLoopAnotherobfuscationmethodtotryisoverloadingthesystemuntilthepersondebuggingyourbotisforcedtoclosethebotanddebugger.Thisfunctiondoesthetrick:
voidSelfDestruct(){std::vector<char*>explosion;while(true)explosion.push_back(newchar[10000]);}
Theinfinitewhileloopjustkeepsaddingelementstoexplosionuntiltheprocessrunsoutofmemoryorsomeonepullstheplug.
OverflowingtheStackIfyouwanttoreallyconfusetheanalyst,youcanmakeachainoffunctionsthateventuallycauseastackoverflow,butinanindirectway:
#include<random>typedefvoid(*_recurse)();voidrecurse1();voidrecurse2();voidrecurse3();voidrecurse4();voidrecurse5();_recurserecfuncs[5]={&recurse1,&recurse2,&recurse3,&recurse4,&recurse5};voidrecurse1(){recfuncs[rand()%5]();}voidrecurse2(){recfuncs[(rand()%3)+2]();}
![Page 333: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/333.jpg)
voidrecurse3(){if(rand()%100<50)recurse1();elserecfuncs[(rand()%3)+1]();}voidrecurse4(){recfuncs[rand()%2]();}voidrecurse5(){for(inti=0;i<100;i++)if(rand()%50==1)recfuncs[i%5]();recurse5();}//callanyoftheabovefunctionstotriggerastackoverflow
Inanutshell,thesefunctionsrandomlyandinfinitelyrecurseuntilthere’snoroomleftonthecallstack.Causingtheoverflowindirectlymakesithardfortheanalysttopauseandexaminepreviouscallsbeforetheyrealizewhat’shappened.
CausingaBSODIfyou’reseriousaboutobfuscation,youcaneventriggeraBlueScreenofDeath(BSOD)whenyoudetectadebugger.Onewaytodothatistosetyourbot’sprocessascriticalusingtheSetProcessIsCritical()WindowsAPIfunctionandthencallexit(),sinceWindowswilltriggeraBSODwhenacriticalprocessiskilled.Here’showyoumightdothat:
voidBSODBaby(){typedeflong(WINAPI*RtlSetProcessIsCritical)(BOOLEANNew,BOOLEAN*Old,BOOLEANNeedScb);autontdll=LoadLibraryA("ntdll.dll");if(ntdll){autoSetProcessIsCritical=(RtlSetProcessIsCritical)GetProcAddress(ntdll,"RtlSetProcessIsCritical");if(SetProcessIsCritical)SetProcessIsCritical(1,0,0);}}
BSODBaby();exit(1);
Ormaybeyou’reevil,inwhichcaseyoucandothis:
BSODBaby();OutputDebugString("%s%s%s%s");recurse1();exit(1);
![Page 334: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/334.jpg)
Assumingyou’veimplementedallofthetechniquesdescribedinthissection,thiscodewouldcauseaBSOD,crashthedebugger(ifit’sOllyDbgv1.10),overflowthestack,andexittherunningprogram.Ifanyoneofthemethodsfailsorgetspatched,theanalyststillhastodealwiththeremainingonesbeforetheycancontinuedebugging.
DefeatingSignature-BasedDetectionEvenwithamazingobfuscation,youwon’teasilybeatsignaturedetection.Engineerswhoanalyzebotsandwritesignaturesareveryskilled,andobfuscationis,atbest,anuisancethatmakestheirjobmarginallyharder.
TocompletelyevadeSBD,youneedtosubvertthedetectioncode.ThisrequiresknowingexactlyhowtheSBDworks.PunkBuster,forinstance,usesNtQueryVirtualMemory()toscanthememoryofallrunningprocessesforanysignatures.Ifyouwanttobypassthis,youcaninjectcodeintoallPunkBusterprocesseswithahookontheNtQueryVirtualMemory()function.
Whenthefunctiontriestoquerymemoryfromyourbotprocess,youcangiveitwhateverdatayouwant,likethis:
NTSTATUSonNtQueryVirtualMemory(HANDLEprocess,PVOIDbaseAddress,MEMORY_INFORMATION_CLASSmemoryInformationClass,PVOIDbuffer,ULONGnumberOfBytes,PULONGnumberOfBytesRead){
//ifthescanisonthisprocess,makesureitcan'tseethehookDLLif((process==INVALID_HANDLE_VALUE||process==GetCurrentProcess())&&baseAddress>=MY_HOOK_DLL_BASE&&baseAddress<=MY_HOOK_DLL_BASE_PLUS_SIZE)➊returnSTATUS_ACCESS_DENIED;
//ifthescanisonthebot,zerothereturnedmemoryautoret=origNtQueryVirtualMemory(process,baseAddress,memoryInformationClass,buffer,numberOfBytes,numberOfBytesRead);if(GetProcessId(process)==MY_BOT_PROCESS)➋ZeroMemory(buffer,numberOfBytesRead);returnret;}
![Page 335: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/335.jpg)
ThisonNtQueryVirtualMemory()hookreturnsSTATUS_ACCESS_DENIED➊whenNtQueryVirtualMemory()triestoquerythehookDLL’smemory,butitgiveszeroedmemory➋whenNtQueryVirtualMemory()triestoquerythebot’smemory.Thedifferenceisn’tforanyspecificreason;I’mjustshowingtwowaysyoucanhidefromtheNtQueryVirtualMemory()functioncall.Ifyou’rereallyparanoid,youcanevenreplacetheentirebufferwitharandombytesequence.
Ofcourse,thismethodworksonlyforSBDthathappensfromusermode,liketheSBDinPunkBusterorVAC.SBDthathappensfromthedriver,likeESEA’s,orthatisn’tpredictable,likeWarden’s,isn’taseasytobypass.
Inthosecases,youcantakeprecautionstoeliminateuniquesignaturesinyourbot.Ifyou’redistributingthebottomorethanadozenorsopeople,however,removingalldistinguishingpropertiesistricky.Tothrowanalystsoffthescent,eachtimeyougivesomebodyacopyofthebot,youcouldtrysomecombinationofthefollowing:
•Compilingthebotusingadifferentcompiler
•Changingthecompileroptimizationsettings
•Togglingbetweenusing__fastcalland__cdecl
•Packingthebinariesusingadifferentpacker
•Switchingbetweenstaticanddynamiclinkingofruntimelibraries
Varyingtheseelementscreatesadifferentassemblyforeachuser,butthere’salimitonhowmanyuniqueversionsofthebotyoucanproducethatway.Pastsomepoint,thismethoddoesn’tscaletodemand,andeventually,gamecompanieswillhavesignaturesforeveryincarnationofyourbot.
Apartfromobfuscationandcodemutation,therearen’tmanywaystodefeatadvancedSBDmechanisms.Youcouldimplementyourbotinadriverorcreateakernel-moderootkittohideyourbot,buteventhosemethodsaren’tfoolproof.
NOTE
Thisbookdoesn’tcoverimplementingabotinadriverorcreatingarootkitto
![Page 336: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/336.jpg)
hideabot,asbothtopicsareprettycomplex.Rootkitdevelopmentaloneisasubjectthatdozensofbookshavecoveredalready.I’drecommendBillBlunden’sTheRootkitArsenal:EscapeandEvasioninTheDarkCornersofTheSystem(Jones&BartlettLearning,2009).
Somegamehackerstrytocovereverysinglebase,hookingeverymemory-readingfunctionandtheentirefilesystemAPI,butstillgetcaughtbydeterminedsystemslikeWarden.Infact,IrecommendstayingawayfromWardenandBlizzardatallcosts.
DefeatingScreenshotsIfyouencounteradetectionmechanismthatusesscreenshotsasadditionalprooftonailbotters,you’reinluck.Bypassingscreenshotmechanismsiseasy:don’tletyourbotbeseen.
YoucansubvertthistypeofdetectionbykeepingaminimalUIandmakingnovisiblydistinguishablechangestothegameclient.IfyourbotrequiresaHUDorotherdistinctiveUIdisplays,though,don’tfret—youcanhaveyourcakeandeatit,too.Aslongasyoucaninterceptthescreenshotcode,youcanhideyourfingerprintswhileascreenshotistaken.
InsomeversionsofPunkBuster,forexample,theWindowsAPIfunctionGetSystemTimeAsFileTime()iscalledjustbeforeascreenshotistaken.YoucanuseahookonthisfunctiontoquicklyhideyourUIforafewsecondstoensureit’snotseen:
voidonGetSystemTimeAsFileTime(LPFILETIMEsystemTimeAsFileTime){myBot->hideUI(2000);//hideUIfor2secondsorigGetSystemTimeAsFileTime(systemTimeAsFileTime);}
JusthookGetSystemTimeAsFileTime()usingthetechniquesdescribedin“HookingtoRedirectGameExecution”onpage153,writeahideUI()function,andcallthehideUI()functionbeforeexecutionresumes.
DefeatingBinaryValidationDefeatingbinaryvalidationisassimpleasnotplacinghooksinsidegame-
![Page 337: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/337.jpg)
Defeatingbinaryvalidationisassimpleasnotplacinghooksinsidegame-specificbinaries.JumphooksandIAThooksonWindowsAPIfunctionsareextremelycommon,sowhereveryoucan,trytogetawaywithusingthosemethodsinsteadofusingjumpornear-callhooksinagamebinary.Incaseswhereyoumustdirectlyhookagame’scode,youcantricktheanti-cheatsoftware’sbinaryvalidationroutinesbyinterceptingthebinaryscanandspoofingthedatatomatchwhatthesoftwareexpectstosee.
LikeSBD,binaryvalidationoftenusesNtQueryVirtualMemory()toscanmemory.Totrickthevalidationcode,startwithahookonthatfunction.Then,writeafunctionlikethisonetospoofthedatawhenNtQueryVirtualMemory()iscalled:
NTSTATUSonNtQueryVirtualMemory(HANDLEprocess,PVOIDbaseAddress,MEMORY_INFORMATION_CLASSmemoryInformationClass,PVOIDbuffer,ULONGnumberOfBytes,PULONGnumberOfBytesRead){
autoret=origNtQueryVirtualMemory(process,baseAddress,memoryInformationClass,buffer,numberOfBytes,numberOfBytesRead);//placetrickycodesomewhereinherereturnret;}
Insidethishook,you’llneedtowatchforanymemoryscansovermemorythathasbeenmodifiedbyoneofyourhooks.
NOTE
ThisexampleassumesthebothasonlyonehookandthatvariablesprefixedwithHOOK_alreadyexistanddescribethecodethehookreplaces.
Listing12-2showssomescan-monitoringcode.
//isthescanonthecurrentprocess?boolcurrentProcess=process==INVALID_HANDLE_VALUE||process==GetCurrentProcess();
//isthehookinthememoryrangebeingscanned?autoendAddress=baseAddress+numberOfBytesRead-1;boolcontainsHook=(HOOK_START_ADDRESS>=baseAddress&&
![Page 338: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/338.jpg)
HOOK_START_ADDRESS<=endAddress)||(HOOK_END_ADDRESS>=baseAddress&&HOOK_END_ADDRESS<=endAddress);➊if(currentProcess&&containsHook){//hidethehook}
Listing12-2:Checkingwhetherhookedmemoryisbeingscanned
Whenamemoryscanoverthehookedcodehappens(whichmakescurrentProcessandcontainsHookbecometrueatthesametime),codeinsidetheif()statement➊updatestheoutputbuffertoreflecttheoriginalcode.Thismeansyoumustknowwherethehookedcodeiswithinthescannedblock,takingintoaccountthefactthattheblockmayspanonlyasubsetofthehookedcode.
SoifbaseAddressmarkstheaddresswherethescanstarts,HOOK_START_ADDRESSmarksthespotwherethemodifiedcodestarts,endAddressmarkstheaddresswherethescanends,andHOOK_END_ADDRESSmarkstheaddresswherethemodifiedcodeends,youcanusesomesimplemathtocalculatewhichpartsofthemodifiedcodearepresentinwhichpartsofthebuffer.Youdosoasfollows,usingwriteStarttostoretheoffsetofthemodifiedcodeinthescanbufferandreadStarttostoretheoffsetofthescanbufferrelativetothemodifiedcode,incasethescanbufferstartsinthemiddleofthemodifiedcode:
intreadStart,writeStart;if(HOOK_START_ADDRESS>=baseAddress){readStart=0;writeStart=HOOK_START_ADDRESS-baseAddress;}else{readStart=baseAddress-HOOK_START_ADDRESS;writeStart=baseAddress;}
intreadEnd;if(HOOK_END_ADDRESS<=endAddress)readEnd=HOOK_LENGTH-readStart-1;elsereadEnd=endAddress–HOOK_START_ADDRESS;
Onceyouknowhowmanybytesyouneedtoreplace,wheretoputthem,andwheretogetthem,youcandothespoofwiththreelinesofcode:
char*replaceBuffer=(char*)buffer;
![Page 339: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/339.jpg)
for(;readStart<=readEnd;readStart++,writeStart++)replaceBuffer[writeStart]=HOOK_ORIG_DATA[readStart];
Completelyassembled,thecodelookslikethis:
NTSTATUSonNtQueryVirtualMemory(HANDLEprocess,PVOIDbaseAddress,MEMORY_INFORMATION_CLASSmemoryInformationClass,PVOIDbuffer,ULONGnumberOfBytes,PULONGnumberOfBytesRead){autoret=origNtQueryVirtualMemory(process,baseAddress,memoryInformationClass,buffer,numberOfBytes,numberOfBytesRead);boolcurrentProcess=process==INVALID_HANDLE_VALUE||process==GetCurrentProcess();autoendAddress=baseAddress+numberOfBytesRead-1;boolcontainsHook=(HOOK_START_ADDRESS>=baseAddress&&HOOK_START_ADDRESS<=endAddress)||(HOOK_END_ADDRESS>=baseAddress&&HOOK_END_ADDRESS<=endAddress);if(currentProcess&&containsHook){intreadStart,writeStart;if(HOOK_START_ADDRESS>=baseAddress){readStart=0;writeStart=HOOK_START_ADDRESS-baseAddress;}else{readStart=baseAddress-HOOK_START_ADDRESS;writeStart=baseAddress;}
intreadEnd;if(HOOK_END_ADDRESS<=endAddress)readEnd=HOOK_LENGTH-readStart-1;elsereadEnd=endAddress–HOOK_START_ADDRESS;
char*replaceBuffer=(char*)buffer;for(;readStart<=readEnd;readStart++,writeStart++)replaceBuffer[writeStart]=HOOK_ORIG_DATA[readStart];}returnret;}
Ofcourse,ifyouhadmultiplehooksthatyouneededtohidefrombinaryvalidationscans,youwouldneedtoimplementthisfunctionalityinamorerobustwaythatwouldallowittotrackmultiplemodifiedcoderegionsaccordingly.
![Page 340: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/340.jpg)
DefeatinganAnti-CheatRootkitGameGuardandsomeotheranti-cheatsuitescomewithuser-moderootkitsthatnotonlydetectbotsbutalsoproactivelypreventthemfromrunning.Todefeatthistypeofprotection,ratherthanthinkoutsidethebox,youcancompletelycopytheboxandworkinsidethatcopy.
Forexample,ifyouwanttowritememorytoagame,youmustcalltheWriteProcessMemory()function,whichisexportedbykernel32.dll.Whenyoucallthisfunction,itdirectlycallsNtWriteVirtualMemory()fromntdll.dll.GameGuardhooksntdll.NtWriteVirtualMemory()topreventyoufromwritingmemory.ButifNtWriteVirtualMemory()isexportedfrom,say,ntdll_copy.dll,GameGuardwon’thookthatfunction.
Thatmeansyoucancopyntdll.dllanddynamicallyimportallofthefunctionsyouneed,asfollows:
//copyandloadntdllcopyFile("ntdll.dll","ntdll_copy.dll");automodule=LoadLibrary("ntdll_copy.dll");
//dynamicallyimportNtWriteVirtualMemorytypedefNTSTATUS(WINAPI*_NtWriteVirtualMemory)(HANDLE,PVOID,PVOID,ULONG,PULONG);automyWriteVirtualMemory=(_NtWriteVirtualMemory)GetProcAddress(module,"NtWriteVirtualMemory");
//callNtWriteVirtualMemorymyWriteVirtualMemory(process,address,data,length,&writtenlength);
Aftercopyingntdll.dll,thiscodeimportstheNtWriteVirtualMemory()fromthecopywiththenamemyWriteVirtualMemory().Fromthere,thebotcanusethisfunctioninplaceoftheNtWriteVirtualMemory()function.They’reeffectivelythesamecodeinthesamelibrary,justloadedunderdifferentnames.
Copyingafunctionthatanti-cheatsoftwarehooksworksonlyifyoucallthatfunctionatitslowest-levelentrypoint,though.Ifthiscodecopiedkernel32.dllanddynamicallyimportedtheWriteProcessMemory()function,ananti-cheatrootkitwouldstillstopthebot,becausekernel32_copy.dllwouldstillrelyonntdll.NtWriteVirtualMemory()whencallingtheWriteProcessMemory()function.
![Page 341: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/341.jpg)
DefeatingHeuristicsInadditiontoalloftheadvancedclient-sidedetectionmechanismswe’vejustdiscussed,gamecompanieswillemployserver-sideheuristicsthatcandetectbotssimplybymonitoringaplayer’sbehavior.Thesesystemslearntodistinguishbetweenhumanandautonomousplayerbehaviorthroughmachine-learningalgorithms.Theirdecision-makingprocessisofteninternalandincomprehensibletohumans,soit’sdifficulttopinpointexactlywhatfeaturesofgameplayleadtodetection.
Youdon’tneedtoknowhowsuchalgorithmsworktotrickthem;yourbotjustneedstoacthuman.Herearesomecommonbehaviorsthataredistinguishablydifferentbetweenhumansandbots:
IntervalsbetweenactionsManybots perform actions unreasonably fast or at consistent intervals.Bots will seem more human-like if they have a reasonable cooldownperiod between actions. They should also have some form ofrandomization to prevent them from repeating an action at a constantrate.
PathrepetitionBots that farm enemies automatically visit a preprogrammed list oflocations to kill creatures. These waypoint lists are often extremelyaccurate,indicatingeachlocationasanexactpixel.Humans,conversely,moveinlesspredictablewaysandvisitmoreuniquelocationsalongthewaytoafamiliararea.Toreplicatethisbehavior,abotmightwalktoarandomlocationwithinacertainrangeofatargetlocation,ratherthantothetargetlocationitself.Also,ifthebotrandomizestheorderinwhichitvisitstargetlocations,thevarietyofpathsittakeswillincreasefurther.
UnrealisticplaySome botters run their bots in the same location for hundreds ofconsecutivehours, buthumans can’t play a game that long.Encourageyourusers to refrain frombotting formore than eighthours at a timeand warn them that doing the same thing for seven straight days willdefinitelytriggeralarmsinaheuristicsystem.
![Page 342: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/342.jpg)
PerfectaccuracyBotscanhitathousandheadshotsinarowwithoutfiringasingleextrabullet,andtheycanhiteveryskillshotwithconsistentprecision.Butit’svirtuallyimpossibleforahumantodothesame,soasmartbotshouldbeintentionallyinaccurateattimes.
Thesearejustafewexamples,butingeneral,youcansneakpastheuristicchecksifyoujustusecommonsense.Don’ttrytohaveabotdosomethingahumancan’t,anddon’thavethebotdoanysinglethingfortoolong.
ClosingThoughtsGamehackersandgamedevelopersareengagedinaconstantbattleofwits.Hackerswillkeepfindingwaystosubvertdetection,anddeveloperswillkeepfindingbetterwaystodetectthem.Ifyou’redetermined,however,theknowledgeinthischaptershouldhelpyoudefeatanyanti-cheatsoftwareyouencounter.
![Page 343: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/343.jpg)
INDEX
AAbouttextfield,Trainergeneratordialog,9accessingmemory
ininjectedDLL,145–146forwritingandreading,122–124
ActionMessageFormat(AMF),169actorfunctions,216actuation,216,223Addresscolumn
EventPropertiesdialog,55OllyDbgdisassemblerpane,27
addresses,memory.SeememoryaddressesAddressSpaceLayoutRandomization(ASLR),128
bypassingininjectedDLL,146–147bypassinginproduction,128–130disablingforbotdevelopment,128inProcessExplorer,56,57
AdobeAIRhooking,169decode()function,172–173,174–175encode()function,171–172,174–175placinghooks,173–175RTMP,assessing,169–170
AdobeAIR.dll,173–175airlogtool,170alignment
innumericdata,68ofvariables,indatastructures,70–71
ambientlight,adding,190–192
![Page 344: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/344.jpg)
AMF(ActionMessageFormat),169anti-cheatsoftware,245–246
anti-cheatrootkit,defeating,261–262binaryvalidation,defeating,259–261botfootprints,managing,250–256ESEAAnti-Cheattoolkit,247GameGuardtoolkit,248–249heuristics,defeating,262–263PunkBustertoolkit,246–247screenshots,defeating,258signature-baseddetection,evading,256–257VACtoolkit,247–248Wardentoolkit,249–250
anti-crowd-controlhacks,218anti-debuggingtechniques,251,255–256arithmeticinstructions,90–92A*searchalgorithm,234
cost,233creatingnode,234–237creatingpathlist,239–240score,234usesfor,240–241writingsearchfunction,237–239
ASLR.SeeAddressSpaceLayoutRandomization(ASLR)Asm2Clipboardplug-in,42assemblycode
copying,42tracing,32–33viewingandnavigatinginOllyDbg,27–29
assemblylanguage,78.Seealsox86assemblylanguageassemblypatterns,searchingfor,19–21AStarNodeclass,234–236AT&Tsyntax,80
![Page 345: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/345.jpg)
autocombo,219autododge,219autokitebots,244automatichealer,218,225–228,230–232autonomousbots,221–222.Seealsocontroltheory;statemachines
cavebots,241–243complexhypotheticalstatemachine,228–230errorcorrection,230–232healerstatemachine,225–228pathfindingwithsearchalgorithms,232–234warbots,243–244
autoreload,219autosnipebots,244autowallbots,244
Bbanwaves,246BiggerThanscantype,CheatEngine,6binaryarithmeticinstructions,90binaryvalidation,248,259–261bits,EFLAGSregister,84BlueScreenofDeath(BSOD),256bots.Seealsoautonomousbots;extrasensoryperception(ESP)hacks
anti-crowd-controlhacks,218anti-debuggingtechniques,251,255–256automatichealer,218,225–228,230–232detectingdebuggers,251–254detectingvisualcues,205–206disablingASLRfordevelopment,128emulatingkeyboard,211–215footprints,managing,250–256gameupdates,dealingwith,101–104
![Page 346: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/346.jpg)
interceptingnetworktraffic,206–211monitoringmemory,204–205obfuscation,251,255–256sendingpackets,215–217spelltrainers,219
branching,92–94breakpoints,30,34,38Breakpointswindow,OllyDbg,26BSOD(BlueScreenofDeath),256BYTEdatatype,67bytes,machinecode,78
CC++,66callee,94–95caller,94–95callHook()function,154callhooking,153–156.SeealsoAdobeAIRhookingcallingconventions,95
forcallhooks,155__cdecl,95,155__fastcall,95__stdcall,95__thiscall,95,217fortrampolinefunctions,168forVFtablehooks,156–158
CALLinstruction,94–95callstack
overflow,255–256viewing,30x86assemblylanguage,86–88
Callstackwindow,OllyDbg,26
![Page 347: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/347.jpg)
capacityofstd::vector,109castingspells.Seespellscavebots,241–243__cdeclconvention,95,155ChangedValuescantype,CheatEngine,7characters.Seealsoenemies
healthbars,monitoringwithbots,204–205pausingexecutionwhenhealthdrops,39–42playerhealth,findingwithOllyDbg,99–101
chardatatype,67CheatEngine,3,5–6
automaticallylocatingstringaddresseswith,102cheattables,7–8correctaddress,determining,7firstscan,running,6installing,4Luascriptingenvironment,18–22memorymodification,8–11nextscan,running,7pointerscanningwith,14–18scantypes,6std::list,determiningwhetherdataisstoredin,112–113std::map,determiningwhetherdataisstoredin,117trainergenerator,9–11VFtables,78zoomfactor,finding,197
cheattables,CheatEngine,7–8CheatUtilityplug-in,42–43CheckRemoteDebuggerPresent()function,251classes,74–78classinstances,76CloseHandle()function,122,138closingmutexes,59–60
![Page 348: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/348.jpg)
CMPinstruction,92codecaves,134
loadingDLLs,143–146threadhijacking,138–142threadinjection,134–138
codeinjection,133–134bypassingASLRinproduction,128–130DLLs,142–146withthreadhijacking,138–142withthreadinjection,134–138
codepatches,creating,31–32columnconfigurations,ProcessMonitor,51combat,automating,243–244commandlineplug-in,OllyDbg,43–44commandsyntax,x86assemblylanguage,79–81Commentcolumn,OllyDbgdisassemblerpane,28complexhypotheticalstatemachine,228–230conditionalbreakpoints,34,38conditionalstatements,93constantratioofhealth,adjustingfor,230–231control-criticalroutines,timing,254controlflowhacks,31controlflowmanipulation,149–150.SeealsoAdobeAIRhooking;Direct3D
hookingcallhooking,153–156IAThooking,160–165jumphooking,165–169NOPing,150–152VFtablehooking,156–160
controltheory,222combiningwithstatemachines,225complexhypotheticalstatemachine,228–230errorcorrection,230–232
![Page 349: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/349.jpg)
healerstatemachine,225–228controlwindows,OllyDbg,25–26cooldowns,displayingenemy,200–201copyingassemblycode,42copy-on-writeprotection,126corpses,botbehaviortoward,229,240correctaddress,determininginCheatEngine,7CPUwindow,OllyDbg,26–30,40crashingdebuggers,255CreateRemoteThread()function,129,130,134,138CreateToolhelp32Snapshot()function,120,141creaturedata,knowingstructurebehind,106–107criticalgameinformation,displaying,198–201crowd-controlattacks,218cryptographicfunctions,hooking,170CSregister,85C-styleoperators,OllyDbg,34–35custombehaviorsforcavebots,scripting,243
Ddarkenvironments,lightingup,190–192datamodificationinstructions,89datastructures,71–73datatypes,66
classesandVFtables,74–78numericdata,67–69OllyDbg,36stringdata,69–71unions,73–74
DBG_RIPEXCEPTIONhandlers,checkingfor,253debugging.SeealsoOllyDbg
anti-debuggingtechniques,255–256
![Page 350: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/350.jpg)
debugdrivers,checkingfor,254debugstrings,printing,253detectingdebuggers,251–254ProcessMonitor,52–53
__declspec(naked)convention,168decode()function,hooking,172–173,174–175DecreasedValueByscantype,CheatEngine,7DecreasedValuescantype,CheatEngine,7dependencies,DLL,145dependencyloading,160depositor,242destinationoperand,80detection,avoiding.Seeanti-cheatsoftwaredevice->SetRenderState()function,192Dijkstra’salgorithm,233–234Direct3D9,176Direct3Dhooking,175–176.Seealsoextrasensoryperception(ESP)hacks
detectingvisualcuesingames,205–206drawingloop,176–177findingdevices,177–181optionalfixesforstability,184writinghookforEndScene(),182–183writinghookforReset(),183–184
directionallighthacks,190–191disablingASLR,128disassemblerpane,OllyDbg,27–29,42Disassemblycolumn,OllyDbgdisassemblerpane,28dispatchPacket()function,210displaybase,27DLL(dynamiclinklibrary),injecting,142–146DllMain()entrypoint,144–145DLLsoption,ProcessExplorerpane,57
![Page 351: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/351.jpg)
DomainNameSystem(DNS)cachescans,248DOSheader,160–161DrawIndexedPrimitive()function,194,195,196,200drawingloop,Direct3D,176–177DSregister,85dumppane,OllyDbg,29–30DWORDdatatype,67,145–146dynamicallyallocatedmemory,6,11,12dynamiclinklibrary(DLL),injecting,142–146dynamiclure,242–243dynamicstructures,105
std::listclass,110–113std::mapclass,114–118std::stringclass,105–108std::vectorclass,108–110
EEAXregister,81EBPregister,83EBXregister,82ECXregister,82,157EDIregister,83EDXregister,82EFLAGSregister,84,92EIPregister,83,139emulatingkeyboard,211–215enableLightHackDirectional()function,190–191encode()function,hooking,171–172,174–175EndScene()function
jumphooking,178–181stabilityof,184writinghookfor,182–183
![Page 352: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/352.jpg)
endSceneTrampoline()function,181enemies.Seealsoextrasensoryperception(ESP)hacks
cooldowns,displaying,200–201criticalgameinformation,displaying,198–201predictingmovementsof,241texture,changing,195–196
entropy,5,7Environmenttab,ProcessExplorerPropertiesdialog,58errorcorrection,230–232ESEA(E-SportsEntertainmentAssociation),247ESEAAnti-Cheattoolkit,247ESIregister,83ESPhacks.Seeextrasensoryperception(ESP)hacksESPregister,83ESregister,85Euclideandistanceheuristic,236eventclassfilters,ProcessMonitor,51–52eventlog,ProcessMonitor,52–53EventPropertiesdialog,54–55ExactValuescantype,CheatEngine,6exceptionhandlers,checkingfor,253executeprotection,125–128Executeuntilreturnbutton,OllyDbg,25experience-trackingHUD,200exponent,floatdatatype,68expressions,OllyDbg,36–37
accessingmemorycontentswith,36elementsevaluatedby,35–36expressionengine,33–36pausingexecutionwhenhealthofcharacterdrops,39–42pausingexecutionwhennameofplayerisprinted,37–38supporteddatatypes,36
extrasensoryperception(ESP)hacks,189–190
![Page 353: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/353.jpg)
backgroundknowledge,190floorspyhacks,201–202HUDs,198–201lighthacks,190–192loading-screenHUDs,201pick-phaseHUDs,201rangehacks,201wallhacks,192–197zoomhacks,197–198
Ffalsepositives,VACtoolkit,248__fastcallconvention,95feedbackloop,222fileaccesses,inspectinginProcessExplorer,60Filesystemeventclassfilter,52FILO(first-in-last-out),86filters,eventclass,51–52findItem()function,116–117findSequence()function,175first-in-last-out(FILO),86first-personshooter(FPS),xxii,246firstscan,runninginCheatEngine,6flags,processaccess,121floatdatatype,67–68floorspyhacks,201–202fogofwar,189.Seealsoextrasensoryperception(ESP)hacksfootprints,managing,250–256Foundintermodularcallswindow,OllyDbg,40FPS(first-personshooter),xxii,246FPUregisters,29Framecolumn,EventPropertieswindow,54
![Page 354: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/354.jpg)
frames,inDirect3Ddrawingloop,176Freezeinterval,Trainergeneratordialog,9freezing
addresses,8mainthread,141
frontier,233FSregister,85functioncalls,x86assemblylanguage,94–95functionflowchart,OllyFlow,45functionnames,findingforIAThooking,163
GGameActuatorsclass,225gameautomationstatemachine,223–224GameGuardtoolkit,248–249gameupdates,determiningnewaddressesafter,101–104generalregisters,81–82genericmemoryfunctions,123–124getAddressforNOP()function,152GetAsyncKeyState()function,196GetExitCodeThread()function,129GetModuleFileName()function,144GetModuleHandle()function,129–130,134,144,146–147GetSystemTimeAsFileTime()function,258GetThreadContext()function,139,142GetTickCount()function,254GetWindowThreadProcessId()function,120goalstate,238GoTobutton,OllyDbg,25greedybest-firstsearchalgorithm,233–234GSregister,85
![Page 355: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/355.jpg)
guardprotection,126
Hhaltingproblem,250handlemanipulationoptions,ProcessExplorer,59–60handlerfunctions,208handles,56,121,210–211,252Handlesoption,ProcessExplorerpane,57Handleswindow,OllyDbg,26hardwarebreakpoints,checkingfor,252–253hashvalidation,247heads-updisplay(HUD),198–201healerstatemachine,225–228,230–232healthofcharacters
healthbars,monitoringwithbots,204–205healthbarsofenemies,displaying,150–152pausingexecutionupondropin,39–42
heapdata,16heuristics,233
defeating,262–263Euclideandistance,236Manhattandistance,235
Hexdumpcolumn,OllyDbgdisassemblerpane,27–28hiddendata,displaying,198–201Hiddenoption,ProcessExplorerpane,57hooking,42,149,153.SeealsoAdobeAIRhooking;Direct3Dhooking;
extrasensoryperception(ESP)hackscall,153–156detectingvisualcuesingames,205–206IAT,160–165interceptingnetworktraffic,206–211jump,165–169
![Page 356: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/356.jpg)
prewrittenlibraries,169signature-baseddetection,evading,257VFtable,156–160zoomhacks,198
hotkeysPatcheswindow,OllyDbg,32ProcessExplorer,57ProcessMonitor,52fortrainer,settingup,10
hourlyexperience,finding,200HTTP(HyperTextTransferProtocol),169HTTPS(HTTPSecure),169HUD(heads-updisplay),198–201
IIAT(importaddresstable)hooking,160–165IDIVinstruction,92IMAGE_DOS_HEADERstructure,161IMAGE_IMPORT_DESCRIPTORstructure,162IMAGE_OPTIONAL_HEADERstructure,161Imagetab,ProcessExplorerPropertiesdialog,57–58IMAGE_THUNK_DATAstructure,162immediatevalue,80importaddresstable(IAT)hooking,160–165importdescriptors,162IMULarithmeticinstruction,90–91IncreasedValueByscantype,CheatEngine,7IncreasedValuescantype,CheatEngine,7indexregisters,83infiniteloops,causingunavoidable,255in-gameactions,botsfor
anti-crowd-controlhacks,218
![Page 357: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/357.jpg)
automatichealer,218,225–228,230–232emulatingkeyboard,211–215sendingpackets,215–217spelltrainers,219
in-gameevents,logging,50–52instructions,79
arithmetic,90–92branching,92–94datamodification,89functioncalls,94–95jump,92–94
intdatatype,67Intelsyntax,80interrupthandlers,checkingfor,252iterator,120
JjumpHookCallback()function,168jumphooking,165–169,178–181jumpinstructions,x86assemblylanguage,92–94
Kkernel-moderootkit,GameGuardtoolkit,249keyboard,emulating,211–215KEYEVENTF_KEYUPflag,212kiting,222,240–241
Llibraries,hooking,169lighthacks,190–192
![Page 358: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/358.jpg)
listclass,110–111listItemclass,110–111little-endianordering,67loaderlock,144loading-screenHUDs,201LoadLibrary()function,143–144Locationcolumn,EventPropertieswindow,54loggingevents,ProcessMonitor,50–52Logwindow,OllyDbg,25longdatatype,67longlongdatatype,67looting,229,241–243Luascriptingenvironment,CheatEngine,18–22luremode,242
Mmachinecode,78mainloop
Direct3Ddrawingloop,176–177syncingwith,164–165
mana,avoidingwasted,219Manhattandistanceheuristic,235mantissa,floatdatatype,68massivelymultiplayeronlinerole-playinggames(MMORPGs),xxi–xxii,198,
248massiveonlinebattlearena(MOBA),xxii,189,197,201,206memcpy()function,136memory,65–66
classesandVFtables,74–78datastructures,71–73numericdata,67–69stringdata,69–71
![Page 359: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/359.jpg)
unions,73–74memoryaccess
ininjectedDLL,145–146forwritingandreading,122–124
memoryaddresses,4accessingwithOllyDbgexpressions,36correct,determininginCheatEngine,7freezing,8new,determiningaftergameupdates,101–104rebasingatruntime,128–129static,6
memory-basedlighthacks,192memorydump
ofclassdata,76ofcodecave,137ofdatastructures,inspecting,70–71ofnumericdata,inspecting,68–69ofstringdata,inspecting,70
memoryforensics,97–98newaddresses,determiningaftergameupdates,101–104playerhealth,findingwithOllyDbg,99–101purposeofdata,deducing,98–99std::listclass,110–113std::mapclass,114–118std::stringclass,105–108std::vectorclass,108–110
memorymanipulation,119accessingmemory,122–124addressspacelayoutrandomization,128–130memoryprotection,124–128processidentifier,obtaining,120–122
Memorymapwindow,OllyDbg,26memorymodification,8–11memorymonitoringwithbots,204–205
![Page 360: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/360.jpg)
memoryoffset,80memoryonwritebreakpoint,208memorypointer,11memoryprotection,124–128,151memoryscanning,3,98.SeealsoCheatEngine;pointerscanning
basic,4–5importanceof,4memorymodification,8–11newaddresses,determiningaftergameupdates,101–104optimizationofcode,22playerhealth,findingwithOllyDbg,99–101purposeofdata,deducing,98–99
MMORPGs(massivelymultiplayeronlinerole-playinggames),xxi–xxii,198,248
mnemonics,78MOBA(massiveonlinebattlearena),xxii,189,197,201,206modifyingmemoryvalues,8–11Module32First()function,144,174Module32Next()function,144,174Modulecolumn,EventPropertieswindow,54Moduleswindow,OllyDbg,25monitoringmemorywithbots,204–205monsters,kiting,240–241mousemovements,emulating,215,240MOVinstruction,89multiclientpatching,30mutexes,closing,59–60
Nnamedpipes,locating,60nameofspecificplayer,pausingexecutionwhenprinted,37–38Nameswindow,OllyDbg,29
![Page 361: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/361.jpg)
nearcalls,153–154nearfunctioncall,39.NETprocesses,59Networkeventclassfilter,52newaddresses,determiningaftergameupdates,101–104nextscan,runninginCheatEngine,7nodes,233,234–238no-operation(NOP)commands,31,32NOPing,150–152
lighthacks,192zoomhacks,197–198
NtQueryVirtualMemory()function,246,257,259NtWriteVirtualMemory()function,261–262nullterminator,70numericdatatypes,67–69numericoperators,OllyDbg,34–35
Oobfuscation,251,255–256observinggameevents
detectingvisualcues,205–206interceptingnetworktraffic,206–211monitoringmemory,204–205
obstacles,searchesdisruptedby,233–234offset,54OllyDbg,23–24
assemblycode,27–29,32–33callstack,viewing,30codepatches,creating,31–32commandlinefor,43–44controlwindows,25–26CPUwindow,26–30
![Page 362: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/362.jpg)
crashingdebuggers,255dealingwithgameupdates,104debuggerbuttonsandfunctions,25expressionengine,33–37memory,viewingandsearching,29–30memorydumpofnumericdata,68–69memorydumpofstringdata,70packetparser,finding,207–208Patcheswindow,31–32patchingif()statements,46–47pausingexecutionwhenhealthofcharacterdrops,39–42pausingexecutionwhennameofplayerisprinted,37–38plug-ins,42–46registercontents,viewingandediting,29Runtracewindow,32–33supporteddatatypes,36translatingcodecaveassemblytoshellcode,135–136userinterface,24–26zoomlimitationcode,finding,198
OllyFlowplug-in,45–46opcodes,78OpenProcess()function,121–122OpenThread()function,142operands
binaryarithmeticinstructions,90IDIVinstruction,92MOVinstruction,89syntax,80–81unaryarithmeticinstructions,90
operations,79operators,usinginOllyDbgexpressionengine,34–35optimizingmemorycode,22ordering,little-endian,67
![Page 363: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/363.jpg)
orderofvariables,indatastructures,70–71OutputDebugString()function,253
Ppackets
intercepting,206–211sending,215–217
packing,251padding,68pageprotection,125–126pages,124parsingpackets,206–211Patcheswindow,OllyDbg,26,31–32patching,multiclient,30patchingif()statements,46–47Pathcolumn,EventPropertiesdialog,55pathfindingwithsearchalgorithms,232–234.SeealsoA*searchalgorithmpathlist,A*searchalgorithm,239–240Pausebutton,OllyDbg,25pausingexecution,37–38,39–42pausingthreads,184PEB(processenvironmentblock)structure,146PeekMessage()function,184PEheader,160–161pick-phaseHUDs,201PID(processidentifier),120–122pipes,locatingnamed,60Playbutton,OllyDbg,25playerhealth,findingwithOllyDbg,99–101playerversusplayer(PvP)combat,243–244plug-ins,OllyDbg,42–46
![Page 364: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/364.jpg)
pointerchains,11–12pointerpath,11PointerscannerScanoptionsdialog,CheatEngine,14–16pointerscanning,11
basicsof,12–14withCheatEngine,14–18pointerchains,11–12rescanning,17–18
Pong,46–47Popuptraineronkeypressfield,Trainergeneratordialog,9predictingenemymovements,241prewrittenhookinglibraries,169printf()call,72,73–74,75printingdebugstrings,253Process32First()function,120Process32Next()function,120–121processaccessflags,121PROCESS_ALL_ACCESSflag,121Processandthreadactivityeventclassfilter,52PROCESS_CREATE_THREADflag,121processenvironmentblock(PEB)structure,146ProcessExplorer,49–50,55–56
configuringcolors,56handlemanipulationoptions,59–60hotkeys,57Propertiesdialog,57–59userinterfaceandcontrols,56–57
processhandles,obtaining,121processidentifier(PID),120–122processInput()function,215–216processKeyboardInput()function,216ProcessMonitor,49–50
configuringcolumnsin,51
![Page 365: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/365.jpg)
debugging,53–55eventclassfilters,51–52high-scorefile,finding,55hotkeys,52inspectingeventsineventlog,52–53loggingin-gameevents,50–52
ProcessMonitorFilterdialog,50Processnamefield,Trainergeneratordialog,9processNextPacket()function,210processorregisters,81–86Processprofilingeventclassfilter,52PROCESS_VM_OPERATIONflag,121,122PROCESS_VM_READflag,121PROCESS_VM_WRITEflag,121Propertiesdialog,ProcessExplorer,57–59protection,memory,124–128,151PunkBustertoolkit,246–247,257purposeofdata,deducing,98–99PvP(playerversusplayer)combat,243–244
Rrangehacks,201readingfromgamememory,119
accessingmemory,122–124addressspacelayoutrandomization,128–130memoryprotection,124–128processidentifier,obtaining,120–122
ReadProcessMemory()function,122–124readprotection,125–128RealTimeMessagingProtocol(RTMP)
assessing,169–170decode()function,hooking,172–173,174–175
![Page 366: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/366.jpg)
encode()function,hooking,171–172,174–175interceptingpackets,207
real-timestrategy(RTS),xxii,197,201,206,243rebasingaddressesatruntime,128–129reconnaissance,49–50
ProcessExplorer,55–60ProcessMonitor,50–55
recv()function,207–208red-blacktree,114–115Referenceswindow,OllyDbg,26,28–29,40,100refiller,242registers,processor,81–86registerspane,OllyDbg,29Registryeventclassfilter,51Rescanpointerlistwindow,CheatEngine,17–18responsivehacks,203
anti-crowd-controlhacks,218automatichealer,218,225–228,230–232detectingvisualcues,205–206emulatingkeyboard,211–215interceptingnetworktraffic,206–211monitoringmemory,204–205sendingpackets,215–217spelltrainers,219
rootkitsdefeatinganti-cheat,261–262GameGuardtoolkit,248–249
rootnode,113–114RTMP.SeeRealTimeMessagingProtocolRTS(real-timestrategy),xxii,197,201,206,243runtimeflexibility,229Runtracewindow,OllyDbg,26,32–33
![Page 367: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/367.jpg)
SSBD.Seesignature-baseddetection(SBD)scancode,214scantypes,CheatEngine,6scanvalue,4score,234screenshots,247,258scriptingcustombehaviorsforcavebots,243scriptingengine,CheatEngine,18–22searchalgorithms,232–234.SeealsoA*searchalgorithmSecuritytab,ProcessExplorerPropertiesdialog,58segmentregisters,84–86send()function,216–217sendingpackets,215–217SendInput()function,211–212,215SendMessage()function,213–215sensors,ofasystem,222Set/Changehotkeyscreen,CheatEngine,10SetLight()memberfunction,192SetProcessIsCritical()function,256shellcode,134,135–136,138–141shortdatatype,67sign,floatdatatype,68signature-baseddetection(SBD)
ESEAAnti-Cheattoolkit,247evading,256–257PunkBustertoolkit,246–247
signatures,246single-instancelimitation,59–60skillshots,232Sleep()function,164–165,227
![Page 368: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/368.jpg)
SmallerThanscantype,CheatEngine,6sourceoperand,80Sourcewindow,OllyDbg,26spawningthreads,129spells
anti-crowd-controlhacks,218complexhypotheticalstatemachine,228–230spelltrainers,219
SSregister,85stackframe,87–89stackoverflow,255–256stackpane,OllyDbg,30stacktrace,ProcessMonitor,54–55statemachines,223–224
automatedhealer,225–228combiningwithcontroltheory,225complexhypothetical,228–230errorcorrection,230–232Luafunctions,adding,229–230runtimeflexibility,229
staticaddresses,6__stdcallconvention,95std::listclass,110–113std::mapclass,114–118std::stringclass,105–108std::vectorclass,108–110Stepintobutton,OllyDbg,25Stepoverbutton,OllyDbg,25stochasticsystems,230stringdata,21,69–71,100–101stringoperators,OllyDbg,35Stringstab,ProcessExplorerPropertiesdialog,58
![Page 369: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/369.jpg)
structmemberalignment,71structures,data,71–73subregisters,83SuspendThread()function,142,184syncingwithgamethreads,164–165systems,controllingbehaviorof,222
Ttargets,selecting,240TCP/IPtab,ProcessExplorerPropertiesdialog,58TEB(threadenvironmentblock),146templates
forchangingmemoryprotection,127memoryaccessfunctions,123–124,145–146
TESTinstruction,92textstrings,21,69–71,100–101textureofenemies,changing,195–196__thiscallconvention,95,156–158,217Thread32First()function,141Thread32Next()function,141threadenvironmentblock(TEB),146threads
hijacking,138–142injection,134–138spawning,129
Threadstab,ProcessExplorerPropertiesdialog,58Threadswindow,OllyDbg,26thunks,162–163timingcontrol-criticalroutines,254Titlefield,Trainergeneratordialog,9togglingz-buffering,195
![Page 370: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/370.jpg)
Traceintobutton,OllyDbg,25Traceoverbutton,OllyDbg,25tracingwithOllyDbg,32–33,39–42trainergenerator,CheatEngine,9–11trampolinefunctions,165–168,181traversals
IAThooking,162VFtables,156
Uunaryarithmeticinstructions,90unavoidableinfiniteloops,causing,255UnchangedValuescantype,CheatEngine,7unions,73–74Unixsyntax,80UnknownInitialValuescantype,CheatEngine,6updates,determiningnewaddressesafter,101–104userinterface,ProcessExplorer,56–57user-moderootkit,GameGuardtoolkit,248–249
VVACtoolkit,247–248ValueBetweenscantype,CheatEngine,6ValueTypedirective,CheatEngine,6VF(virtualfunction)tables
classinstancesand,76–78findingDirect3Ddevices,177–181hooking,156–160,182–183traversals,156
VirtualAllocEx()function,136–137,138virtualfunctions,classeswith,75–76
![Page 371: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/371.jpg)
VirtualProtectEx()function,126–128VirtualProtect()function,127
WWaitForSingleObject()function,129,138wallhacks,192
creatingforDirect3D,194–197renderingwithz-buffering,193–194
warbots,243–244Wardentoolkit,249–250waypoints,222,229wchar_tdatatype,67windowhandle,fetching,120Windowswindow,OllyDbg,26WM_CHARmessages,213–214WORDdatatype,67WriteProcessMemory()function,122–124,136–137,138writeprotection,125–128writingtogamememory,119
accessingmemory,122–124addressspacelayoutrandomization,128–130codecaves,136–137memoryprotection,124–128processidentifier,obtaining,120–122
Xx86assemblylanguage,78–79
arithmeticinstructions,90–92branchinginstructions,92–94callstack,86–88commandsyntax,79–81
![Page 372: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/372.jpg)
datamodificationinstructions,89functioncalls,94–95jumpinstructions,92–94NOPing,150–152processorregisters,81–86
x86Windowsmemoryprotectionattributes,125–126
Zz-buffering,192–195zoomfactor,197zoomhacks,197–198
![Page 373: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/373.jpg)
Footnotes
Chapter4:FROMCODETOMEMORY:AGENERALPRIMER1.RandallHyde’sTheArtofAssemblyLanguage,2ndedition(NoStarchPress,2010)isawonderfulbookthatcanteachyoueverythingthereistoknowaboutassembly.2.Eachcommandmustfitwithin15bytes.Mostcommandsare6orfewer.3.Thereisalsoanunsignedmultiplicationinstruction,MUL,whichonlyworkswithasingleoperand.4.JustasMUListoIMUL,DIVistheunsignedcounterparttoIDIV.
![Page 374: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/374.jpg)
RESOURCESVisithttps://www.nostarch.com/gamehacking/forresources,errata,andotherinformation.
Moreno-nonsensebooksfrom NOSTARCHPRESS
BLACKHATPYTHONPythonProgrammingforHackersandPentestersbyJUSTINSEITZ
DEC2014,192PP.,$34.95ISBN978-1-59327-590-7
![Page 375: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/375.jpg)
THECARHACKER’SHANDBOOKAGuideforthePenetrationTesterbyCRAIGSMITH
MAR2016,304PP.,$49.95ISBN978-1-59327-703-1
THEIDAPROBOOK,2NDEDITIONTheUnofficialGuidetotheWorld’sMostPopularDisassemblerbyCHRISEAGLE
JUL2011,672PP.,$69.95ISBN978-1-59327-289-0
PRACTICALFORENSICIMAGINGSecuringDigitalEvidencewithLinuxToolsbyBRUCENIKKEL
FALL2016,256PP.,$49.95
![Page 376: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/376.jpg)
ISBN978-1-59327-793-2
IOSAPPLICATIONSECURITYTheDefinitiveGuideforHackersandDevelopersbyDAVIDTHIEL
FEB2016,296PP.,$49.95ISBN978-1-59327-601-0
PRACTICALMALWAREANALYSISTheHands-OnGuidetoDissectingMaliciousSoftwarebyMICHAELSIKORSKIandANDREWHONIG
FEB2012,800PP.,$59.95ISBN978-1-59327-290-6
800.420.7240OR415.863.9900|[email protected]|WWW.NOSTARCH
![Page 377: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/377.jpg)
![Page 378: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/378.jpg)
GetInsidetheGameYoudon’tneedtobeawizardtotransformagameyoulikeintoagameyoulove.ImagineifyoucouldgiveyourfavoritePCgameamoreinformativeheads-updisplayorinstantlycollectallthatlootfromyourlatestepicbattle.
BringyourknowledgeofWindows-baseddevelopmentandmemorymanagement,andGameHackingwillteachyouwhatyouneedtobecomeatruegamehacker.Learnthebasics,likereverseengineering,assemblycodeanalysis,programmaticmemorymanipulation,andcodeinjection,andhoneyournewskillswithhands-onexamplecodeandpracticebinaries.
Levelupasyoulearnhowto:
ScanandmodifymemorywithCheatEngine
ExploreprogramstructureandexecutionflowwithOllyDbg
LogprocessesandpinpointusefuldatafileswithProcessMonitor
ManipulatecontrolflowthroughNOPing,hooking,andmore
Locateanddissectcommongamememorystructures
You’llevendiscoverthesecretsbehindcommongamebots,including:
Extrasensoryperceptionhacks,suchaswallhacksandheads-updisplays
Responsivehacks,suchasautohealersandcombobots
Botswithartificialintelligence,suchascavewalkersandautomaticlooters
Gamehackingmightseemlikeblackmagic,butitdoesn’thavetobe.Onceyouunderstandhowbotsaremade,you’llbebetterpositionedtodefendagainsttheminyourowngames.JourneythroughtheinnerworkingsofPCgameswithGameHacking,andleavewithadeeperunderstandingofbothgamedesignandcomputersecurity.
![Page 379: ihatefeds.com · 2020-04-21 · 005.8--dc23 2015036294 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names](https://reader034.vdocuments.net/reader034/viewer/2022050107/5f45a33c1342e344e05a2cf4/html5/thumbnails/379.jpg)
AbouttheAuthorNickCanowrotehisfirstscriptsforopensourcegameserverswhenhewas12andhasbeenapartofthegame-hackingcommunityeversince.Hehasyearsofexperienceindetectinganddefendingagainstmalware,andadvisesdevelopersanddesignersonbestpracticestoprotecttheirgamesagainstbots.Nickhasspokenabouthisresearchandtoolsatmanyconferences.
WARNING!Thisbookdoesnotcondonepiracy,violatingtheDMCA,infringingcopyright,orbreakingin-gameTermsofService.Gamehackershavebeenbannedfromgamesforlife,suedformillionsofdollars,andevenjailedfortheirwork.
THEFINESTINGEEKENTERTAINMENT™www.nostarch.com