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

Was this article helpful?

That’s Great!

Thank you for your feedback

Sorry! We couldn't be helpful

Thank you for your feedback

Let us know how can we improve this article!

Select at least one of the reasons
CAPTCHA verification is required.

Feedback sent

We appreciate your effort and will try to fix the article