Skip to content

Writing Extns

Neo edited this page Jul 23, 2021 · 1 revision

Writing Extensions

Table of Contents


Introduction

By definition, extensions are meant for extending the tool's capabilities from just a mere patcher to much more by adding features to it.

At present there are 2 extensions available inbuilt and they cannot be modified.

We would be focusing on the extensions that are defined externally and implemented via QJS functions.

A general use case would be to generate a specific file based on information extracted from the loaded Exe.

We can make use of TextFile and/or BinFile classes for this purpose.


Extension location

Extensions are intended to be an addition to the Main GUI.

Each new extension defined gets added to the Extension drawer on the right side.


We can test extensions against multiple apps just like patches in the Test Bench.

Here they get added to a seperate list inside Extensions tab instead.


The appearance is similar to the entries in the Patch list.


Defining extensions

Extensions are defined by means of it's name along with title, author, icon & tooltip keys.

Only the name is the mandatory information required.

The tool reads extension definitions from a specific YAML file called 'Extensions.yml' . It has the following format:

- ExtName1:
    title : <Brief title to be displayed in the drawer>
    author : <Name of the author(s)>
    tooltip : <Proper description of the extension. While it can be longer than the title. Keep it of reasonable length.>
    icon : <Path to image serving as the icon. Relative paths will be wrt the repo folder.>

- ExtName2:
    title : <Brief title>
    author : <Author name(s)>
    tooltip : <Proper description of the extension.>
    icon : <Path to image serving as the icon.>

# etc.

Couple of points to consider:

  1. The name of the extension also serves as the name of the Extension function which is invoked when the extension is clicked.

  2. In the case of Test Bench the function is called while running tests.

  3. The title, author, icon & tooltip are all used for creating the extension's Action item and Delegate.

  4. As mentioned earlier, aside from the name all other members of an extension are optional.

    If not specified, they pick up the following default values:

    Extension Member Default value
    title extension name itself
    author 'Unknown'
    tooltip will be empty
    icon will be empty

Extension functions

As stated before, every extension has an associated QJS function and it shares the name with the extension.

For an extension to be added to the Extension drawer, this function should have already been defined.

For this reason, the tool auto-loads scripts first if not done atleast once.

The function can be implemented as either a regular function or an arrow function. A general syntax is shown below:

ExtnName = function()
{
	<bunch of code>
	return true;
};

The function takes no arguments.


Return values

The return values are similar to a Patch function but with slight differences.

There are 3 scenarios in which an Extension function stops further execution and return control back to the tool.

  1. Error occured:

    The QJS engine will automatically detect known errors like syntax issues, unknown variable access etc.

    In addition to this, it is also possible to report an error from the script by means of the throw keyword and an Error object.

    throw Error("Something failed");

    This message will get displayed in an Error MessageBox.

  2. Normal exit

    If you end the function returning anything other than a false it is considered to be a normal exit.

    If the returned value is not true then it is displayed in an Info MessageBox.

    • no message
    return true;
    • with message
    return "File has been generated";

    Please note: a QJS function always returns something.
    If you do not have an explicit return or throw statement, then the returned value is undefined and it will be displayed as such in the MessageBox

  3. Abnormal exit

    When you return a false, the tool shows a Warning MessageBox saying it received a false value.

    This can be useful to check for unexpected inputs or invalid switch cases for e.g.


Usual steps

Every extension function is different and therefore difficult to generalize the steps.

However, these are some of the usual steps involved in an extension function:

  • Gathering information

    • Find the reference location (usually a PUSH) of a string using combination of the Exe.Find functions.

    • Find the address(es) where a known code pattern occurs using Exe.FindHex & Exe.FindHexN functions.

    • Use the reference address to discover a second pattern in it's vicinity.

    • Extract some data from the addresses found with one of the Exe.Get functions.

    • Retrieve inputs from user with the Exe.GetUserInput function.

    • Sometimes, the inputs are YAML files which need to be loaded using Warp.LoadYaml function to get an array or hashmap.

    • Use TextFile & BinFile classes for loading custom input files.

  • Processing information

    • Open output file(s) in write mode using TextFile OR BinFile classes (depending on the type of file).

    • Compile the information into the format required.

    • Write the formatted data to the file(s).

    • Save the file and optionally move/copy it to a different location.

  • Finally either return true or return "message to be shown"

While the last step is not mandatory, it is a best practice to have atleast return true to avoid a message box saying undefined.


Return to top


Further reading