Example 3: IP Address and Ports

Modified on: Wed, 27 Sep, 2023 at 9:55 PM

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

Did you find it helpful? Yes No

Send feedback
Sorry we couldn't be helpful. Help us improve this article with your feedback.