Seite 1 von 2

Dynamic Memory Allocation für Anti-Cheating-Zwecke

Verfasst: 16.06.2006 18:42
von Thorium
Dynamic Memory Allocation (DMA) heißt nichts weiter, als das der benötigte Speicher für Daten während der Laufzeit des Programms festgelegt und reserviert (allokiert) wird.

Für Anti-Cheating-Zwecke ist das deswegen gut geeignet, da bei jedem Programmstart die Speicheradressen der allokierten Speicherblöcke anders sind. Viele Trainer-Coder haben Probleme mit DMA, da sie den Pointer im Speicher finden müssen, bevor der Trainer auf die Daten zugreifen kann. Allerdings gibt es auch viele die das können, also DMA bietet keinen absoluten Schutz. Aber es ist besser als garnichts.

Wie man im folgenden Code sehen kann, ist DMA in PureBasic sehr simpel. Lässt sich also ohne weiteres in jedes PB-Spiel implementieren.

Es ist darauf zu achten, dass nicht für jede Variable ein eigener Speicherblock allokiert wird, denn die Untergrenze für Speicherregionen befindet sich bei Win32-Systemen bei 4 Kilobyte. Das heißt, wenn wir jede Variable einzeln allokieren, haben wir für jede Variable einen Speicherverbrauch von 4 KB.

Wenns Fragen gibt, ruhig fragen, obwohl ich denke der Code ist eindeutig und leicht verständlich.

Code: Alles auswählen

;--------------------------------------------------------
;| Dynamic Memory Allocation for Anti-Cheating purposes |
;|                                                      |
;| Version 1.00                                         |
;| Developed by Thorium, http://www.SacredVault.de/     |
;|                                                      |
;| PureBasic 4.00 Code                                  |
;--------------------------------------------------------

EnableExplicit

;die Pointer der kritischen Variablen
Global Hitpoints.l ;Lebensenergie, hier wollen wir ein Long haben
Global Lifes.l ; Lebensanzahl, hier wollen wir ein Byte haben, müssen aber dennoch ein Long definieren

Procedure AllocCriticalVars()
Define Temp.l

;allokieren einer zufälligen Größe an Speicher
;ohne dies werden unsere Variablen immer an der gleichen Speicheradresse liegen

Temp = AllocateMemory(Random($10000)+1)

;allokieren des Speichers für die Hitpoints und Lifes
;wir wollen ein Long und ein Byte haben, also müssen wir 5 Byte allokieren
;Long=4Byte Byte=1Byte
;Jede Variable einzeln zu allokieren, währe Speicherverschwendung,
;da die Mindestgrenze für eine Speicherregion bei 4 Kilobyte liegt.

Hitpoints = AllocateMemory(5)

;Hitpoints sind ein Long, also 4 Byte,
;also müssen wir nur + 4 zur Speicheradresse von Hitpoints
;addieren um den Pointer zu Lifes zu bekommen

Lifes = Hitpoints + 4

;freigeben des zufällig allokierten Speichers
;immer schön aufräumen und freigeben, was wir nichtmehr benötigen
FreeMemory(Temp)
EndProcedure


;allokieren des Speichers für kritische Variablen
AllocCriticalVars()

;wir sehen, das sich unsere Variablen bei jedem Programmaufruf an einer anderen Speicheradresse befinden
Debug("Pointer to Hitpoints: " + Str(Hitpoints))
Debug("Pointer to Lifes: " + Str(Lifes))

;so müssen wir nun auf die Variablen zugreifen:

;schreiben
PokeL(Hitpoints,100)
PokeB(Lifes,3)

;lesen
Debug("Hitpoints: " + Str(PeekL(Hitpoints)))
Debug("Lifes: " + Str(PeekB(Lifes)))

Verfasst: 16.06.2006 18:50
von Hellhound66
Ein

Code: Alles auswählen

TEMP = AllocateMemory(Random($10000)+1) 
sonst kannst du den zufälligen Speicherbereich nicht freigeben.

Verfasst: 16.06.2006 18:53
von Thorium
Hellhound66 hat geschrieben:Ein

Code: Alles auswählen

TEMP = AllocateMemory(Random($10000)+1) 
sonst kannst du den zufälligen Speicherbereich nicht freigeben.
Ups, hab ich doch glatt vergessen, thx ist korrigiert.

Verfasst: 16.06.2006 19:15
von ts-soft

Code: Alles auswählen

;lesen
Debug("Hitpoints: " + Str(PeekL(Hitpoints)))
Debug("Lifes: " + Str(PeekB(Lifes))) 
Das beweist mir garnichts, weil aus einer fremden Anwendung funktioniert das nicht.
Aus dem Spiel heraus ist es doch ein eingebautes Feature, warum also dieses wieder kaputt machen. Naja, ich Spiele aber nie. muß das also nicht verstehen.

Verfasst: 16.06.2006 19:19
von Hellhound66
Ne bessere Variante wäre vielleicht das sekündliche Wechseln des Speicherbereichs für die wichtigsten Werte. Dann kann sich ein Trainer totsuchen.

Verfasst: 16.06.2006 19:21
von Thorium
ts-soft hat geschrieben:

Code: Alles auswählen

;lesen
Debug("Hitpoints: " + Str(PeekL(Hitpoints)))
Debug("Lifes: " + Str(PeekB(Lifes))) 
Das beweist mir garnichts, weil aus einer fremden Anwendung funktioniert das nicht.
Aus dem Spiel heraus ist es doch ein eingebautes Feature, warum also dieses wieder kaputt machen. Naja, ich Spiele aber nie. muß das also nicht verstehen.
Ich verstehe nicht was du nicht verstehst?

Der Code, den du zitiert hast, ist auch nicht dafür da was zu beweisen, sondern zu zeigen, wie man mit den Variablen operieren kann, ohne sie wirklich als Variable deklariert zu haben, man hat halt nur die Pointer.

Der Sinn der Sache ist es, das die Variablen bei jedem Programmstart an einer anderen Speicheradresse liegen um es zu erschweren ein Programm zu machen, welches diese Variablen von aussen manipuliert.

Verfasst: 16.06.2006 19:22
von Thorium
Hellhound66 hat geschrieben:Ne bessere Variante wäre vielleicht das sekündliche Wechseln des Speicherbereichs für die wichtigsten Werte. Dann kann sich ein Trainer totsuchen.
Jep. :allright:
Ich hab noch viele Ideen im Kopf, eins nach dem anderen. :D
Das DMA, was ich hier gepostet habe ist sehr simpel und wird so auch in vielen komerziellen Spielen eingesetzt.

Wenn du das Programmieren willst, ich verlinke gerne alles was mit Anti-Cheating zutun hat in meinem Artikel.

Verfasst: 16.06.2006 19:30
von remi_meier
Sorry, ich behaupte jetzt mal, dass das so nicht verwendet wird. Versuch
mal so ein Spiel zu schreiben, total mühsam. Besser:

Code: Alles auswählen

EnableExplicit 

Structure CRITICAL
  Life.l
  Points.l
EndStructure
Global *datas.CRITICAL

Procedure AllocCriticalVars() 
  Define Temp.l 
  
  Temp = AllocateMemory(Random($10000)+1) 
  *datas = AllocateMemory(SizeOf(CRITICAL))
  FreeMemory(Temp) 
EndProcedure 



AllocCriticalVars() 

Debug("Pointer to Data: " + Str(@*datas\Life)) 


*datas\Points = 100
*datas\Life = 3

Debug("Hitpoints: " + Str(*datas\Points))
Debug("Lifes: " + Str(*datas\Life))
Andere Varianten wären mit z. B. Linked Lists / Arrays oder Objekten (OOP).

Aber das Prinzip deines Codes stimmt natürlich. :)

Verfasst: 16.06.2006 19:33
von Thorium
Jo hast recht. Mir war es jetzt auch nur wichtig das Prinzip rüberzubringen. Wie man das am besten implementiert muss man dann sowieso von Fall zu Fall schauen.

Verfasst: 19.06.2006 00:10
von Konne
So ein schutz ist IMHO aber nicht wirklch noetig. Wenn jemand einen Spielwert aus dem Varoablen Stack auslesen kann ist es auch ein leichtes den Pointer auszulesen und damit dann auf den Memory zuzugreifen.