Reading Properties
Consider the Website Entity: It has a static property called Ports with a default of 80.
Maltego defines this as a list of integers, but it needs to be handled differently in TRX.

Let’s start a new Transform. We’ll call it Mangle and register it on the TDS (using a website Entity).
Our Transform code looks like this:
def create_entities(cls, request, response):
if (not request.Value.isdigit()):
response.addUIMessage("Sorry but [" + request.Value + "] is not a whole number",
UIM_TYPES["partial"])
else:
isdiv = request.getTransformSetting('ISDIV')
if (not isdiv.isdigit()):
response.addUIMessage('Silly! We need a number',UIM_TYPES["fatal"])
else:
howmany = int(request.Value)
accum = 0
for i in range(1, howmany + 1):
if (i % int(isdiv) == 0):
Ent =response.addEntity('maltego.AS', str(i))
Ent.setWeight( howmany - 1 )
accum = accum + 1
if (accum >= request.Slider):
break We use the ‘getProperty’ method to get the property’s value. You will see that we do not return any Entities, which is correct, we simply write a message to the output with the Output screen. On a default website Entity the output looks like this:

If we add a port to the list…

...and run the Transform again we get:


The list is returned as a comma-delimited list.
Adding dynamic properties
We can write properties using the Maltego TRX Python Library. Each property has a:
Display Name: The name displayed in Maltego
Name: The unique name referenced in code
Value: The value of the property
Matching rule: Whether this property must be the same as for other Entities before merging
Let’s assume we want to create a Transform that runs on an IP address and generates a netblock. It will always assume a class C netblock (255 IPs) but it will add a dynamic property to the netblock to indicate if it’s a private netblock or not. We’ll do this with a dynamic property called ‘private’ and it will be set to ‘yes’ or ‘no’.
Create a new Transform code file and register the Transform on the TDS. We begin our Transform (without input validation) like this:
from maltego_trx.transform import DiscoverableTransform
from IPy import IP
from maltego_trx.entities import Netblock
class NetblocksRUs(DiscoverableTransform):
"""
Transform returns a netblock for an IP address input.
"""
@classmethod
def create_entities(cls, request, response):
start = request.Value[0:request.Value.rfind('.')]
netblock = start + ".0-" + start + ".255"
Ent = response.addEntity('maltego.Netblock')
Ent.setValue(netblock)Note that at this point we haven’t added any dynamic properties to the netblock. We need to first have something that checks if an IP address is private or not. A quick search on the Internet finds this useful Python routine:
>>> from IPy import IP
>>> ip = IP('10.0.0.1')
>>> ip.iptype()
'PRIVATE'This function relies on a Python module called IPy. On Ubuntu installing this is as simple as:
sudo apt-get install python-ipy
or use PIP install:
pip3 install IPy
We add a line importing this library into our Transform code file (NetblocksRUs.py) file:
from IPy import IP
The Transform now appears as follows:
class NetblocksRUs(DiscoverableTransform):
"""
Transform returns a netblock for an IP address input.
"""
@classmethod
def create_entities(cls, request, response):
start = request.Value[0:request.Value.rfind('.')]
netblock = start + ".0-" + start + ".255"
Ent = response.addEntity('maltego.Netblock')
ip = IP(request.Value)
if (ip.iptype() == 'PRIVATE'):
Ent.addProperty('private','Private network','strict','yes')
else:
Ent.addProperty('private','Private network','strict','no')
Ent.setValue(netblock)Now running the Transform on two different IP addresses we get:


Yes, we can create a Transform that uses netblocks as input and simply outputs a phrase ‘public’ or ‘private’ (though not very useful, this does indicate how to use additional properties).
from maltego_trx.transform import DiscoverableTransform
from maltego_trx.entities import Phrase
class PublicPrivate(DiscoverableTransform):
"""
A transform that uses netblocks as input and simply outputs a phrase ‘public’ or
‘private’.
"""
@classmethod
def create_entities(cls, request, response):
Ent = response.addEntity('maltego.Phrase')
if request.getProperty('private')=='yes':
Ent.setValue('Private')
else:
Ent.setValue('Public')The resultant graph (when populated with some IPs->Netblock->Public/Private) in a Bubble view block layout:

Developer reference for Maltego-TRX library can be found here: Maltego TRX Python Library