Skip to content

Introduction to Scripting

Bennett Blodinger edited this page Mar 18, 2017 · 1 revision

Scripting

Scripts allow you to create and run code in order to make modifications (e.g, scanning for memory, modifying values, watching for when data is accessed..)

Bit Slicer uses Python for writing scripts. Before proceeding further, it may be a good idea to read up on the language a bit, otherwise feel free trying to barge in.

Using a programming editor such as Xcode, TextMate 2.0, TextWrangler, or Sublime Text is also necessary. Avoid non-programming editors like TextEdit.

Your First Script

  1. Create a new document in Bit Slicer. Choose an appropriate target application.
  2. Navigate to Variable -> Add Variable -> Script in the menu bar.
  3. A template script is created for you. Make sure your target process is running, and activate the 'Active' checkbox on the script. Then un-activate the script by unchecking the check box. (Don't worry, this script does nothing special as explained in steps 4 & 5)
  4. Navigate to Debug -> Show Logs in the menu bar. You will see your script printed out two lines in there. That's all it did.
  5. Double click on the script variable's value. This will open it into a text editor (it will use the one that is associated with python .py files). You will see a template of code already filled out. (Note: the template uses space characters by default for indentation and Python cares a lot about indentation.)

Here is the code for reference:

#Edit Me!
from bitslicer import VirtualMemoryError, DebuggerError

class Script(object):
    def __init__(self):
        debug.log('Initialization goes here')
    #def execute(self, deltaTime):
        #write some interesting code, or don't implement me
    def finish(self):
        debug.log('Cleaning up goes here')

When a user activates a script, Bit Slicer will create an instance of the "Script" class and call the methods _init_, execute, and finish.

When the script starts running, _init_ is called.

After that, execute is called frequently (approximately every 0.03 seconds) if it's implemented; deltaTime (delta as in "change in") is the time in seconds that has passed since execute was last called, as a floating point. In this example, execute is not implemented and commented out.

When the user deactivates your script, finish is called if it's implemented.

If you're unfamiliar with Python and its concept of classes, self is basically a table used to share data from one method to another. Every method has self passed in as the first argument. (Just to note: this is an incomplete explanation.)

Another Example

Here is another more interesting example (this isn't specific to any particular game by the way, and the memory addresses used below are made up):

#Increase Speed!
from bitslicer import VirtualMemoryError, DebuggerError

#memory address to 32-bit speed integer
SPEED_ADDRESS = 0x1A168
#initial starting speed
START_SPEED = 10
#how frequently time should change in seconds
TIME_INTERVAL = 1.0

class Script(object):
    def __init__(self):
        #store original speed
        self.orignalSpeed = vm.readInt32(SPEED_ADDRESS)
        #write start speed
        vm.writeInt32(SPEED_ADDRESS, START_SPEED)
        #set time counter
        self.timePassed = 0.0
    def execute(self, deltaTime):
        self.timePassed += deltaTime
        #every TIME_INTERVAL, increase speed by 1
        if self.timePassed >= TIME_INTERVAL:
            vm.writeInt32(SPEED_ADDRESS, vm.readInt32(SPEED_ADDRESS) + 1)
            self.timePassed -= TIME_INTERVAL
    def finish(self):
        #look up python formatters if you're wondering what %d is
        debug.log('Final speed: %d' % vm.readInt32(SPEED_ADDRESS))
        #restore speed back to the way it was before the script ran
        vm.writeInt32(SPEED_ADDRESS, self.orignalSpeed)

This script initially modifies the speed variable, then every 1 second, it increases the speed variable by 1. Finally, when the user is finished running the script, the speed is reverted back to the way it was before.

Up top I decided to initialize some constants. (I didn't have to do this, but I think it's good practice.) In execute we increment our time accumulator timePassed and decrease it once we've waited for TIME_INTERVAL seconds. Hopefully the rest of the script is self-explanatory enough.

You may have been noticing two objects that have been used in these scripts: vm and debug. When Bit Slicer runs your script, it first creates these two objects. vm has a set of methods for actions such as reading, writing, and scanning, and debug has a set of methods for logging and for utilizing the debugger. Visit the Scripting Functions page for reference.