The Python TRX library was originally released in 2015 (v1.1). Many users may have written their TDS transforms, and would like to port them to the latest version of the TRX library.


This article will cover porting existing transforms to the latest version of our Maltego TRX library.


The code mentioned in this document is contained in our Maltego TRX Examples project. Please reference this project if you are unsure about anything mentioned in this article.


Create a project folder

Your transform code will need to be placed in a project folder that follows our recommended project structure.


First install the maltego-trx library by running the following commands:


pip install maltego-trx


After the maltego-trx library has been installed, you can use the following command to create a new project folder with the recommended layout:


maltego-trx start new_project


This will create a directory named "new_project" which contains the "project.py" file used to run your transforms, and the "transforms" directory that contains your transform code.


Add the old transform

Will will be working with the following transform, written using the first version of the library:


new_project/legacy_transform.py


import socket
from Maltego import *

## This is a fully functional example transform
## Input type is a DNSName. It will resolve to IP address
def trx_DNS2IP(m):
    TRX = MaltegoTransform()
    
    DNSName=None
    try:
        DNSName = socket.gethostbyname(m.Value)
        TRX.addEntity("maltego.IPv4Address",DNSName)
    except socket.error as msg:
        TRX.addUIMessage("Error:"+str(msg),UIM_PARTIAL)
    
    #Write the slider value as a UI message - just for fun
    TRX.addUIMessage("Slider value is at: "+str(m.Slider))
         
    return TRX.returnOutput()    


1. Change the import

You no longer need to include a "Maltego.py" file alongside your transform code, as the library code can be imported directly from the pip library.


We will change the import line from:


from Maltego import *


To:


from maltego_trx.maltego import MaltegoMsg, MaltegoTransform, UIM_PARTIAL


It is considered bad practice to "import *" from  a module, and we will instead choose which classes we need to import. In most cases you will not need the "MaltegoEntity" import.


2. Register the transform function

The latest version of the transform library automatically generates appropriate URLs for your transforms.


We just need to register the function as a transform in our "project.py" file.


We will add the following lines to the "project.py" file in our project folder:


from maltego_trx.registry import register_transform_function
from legacy_transform import trx_DNS2IP

register_transform_function(trx_DNS2IP)


The URL generated by the server will be based on the function name. Please ensure that you use unique transform names in your projects.


3. (Optional) Change variable names

The new library and it's documentation uses the variable names "request" and "response" rather than "m" and "TRX".


We believe that the new variable names are easier to understand as the "request" object contains information sent from the client, and the "response" object contains information returned to the client.


I will make the following option variable name changes from:


def trx_DNS2IP(m):
    TRX = MaltegoTransform()


To:


def trx_DNS2IP(request):
    response = MaltegoTransform()


Checking the Transform

We can check that the transform has been successfully ported and added to our project using the following command:


python project list


We should then get the following output:


= Transform Server URLs =
/run/trx-dns2ip/: trx_DNS2IP
/run/dnstoip/: DNSToIP
/run/greetperson/: GreetPerson


= Local Transform Names =
trx-dns2ip: trx_DNS2IP
dnstoip: DNSToIP
greetperson: GreetPerson


From the output we can see that our transform "trx_DNS2IP" has been added to our transform project successfully.


Writing New Transform

The new library encourages you to write each transform as a class in the "transforms" folder.


If you are writing a new transform, we would recommend that you follow this pattern. 


For more information on writing your transforms as classes, please see these articles: