├── .gitignore
├── LICENSE
├── README.md
├── interpol.mtz
├── project.py
├── requirements.txt
└── transforms
├── ConvertToSearchFaceEntity.py
├── RedNoticeByPhraseFaceSearch.py
├── RedNoticeEntitiesByName.py
├── RedNoticeEntitiesByPhrase.py
├── RedNoticeFaceSearch.py
├── UNSCNoticeEntitiesByName.py
├── UNSCNoticeEntitiesByPhrase.py
├── YellowNoticeEntitiesByName.py
├── YellowNoticeEntitiesByPhrase.py
└── common.py
/.gitignore:
--------------------------------------------------------------------------------
1 | # Byte-compiled / optimized / DLL files
2 | __pycache__/
3 | *.py[cod]
4 | *$py.class
5 |
6 | # C extensions
7 | *.so
8 |
9 | # Distribution / packaging
10 | .Python
11 | build/
12 | develop-eggs/
13 | dist/
14 | downloads/
15 | eggs/
16 | .eggs/
17 | lib/
18 | lib64/
19 | parts/
20 | sdist/
21 | var/
22 | wheels/
23 | share/python-wheels/
24 | *.egg-info/
25 | .installed.cfg
26 | *.egg
27 | MANIFEST
28 |
29 | # PyInstaller
30 | # Usually these files are written by a python script from a template
31 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
32 | *.manifest
33 | *.spec
34 |
35 | # Installer logs
36 | pip-log.txt
37 | pip-delete-this-directory.txt
38 |
39 | # Unit test / coverage reports
40 | htmlcov/
41 | .tox/
42 | .nox/
43 | .coverage
44 | .coverage.*
45 | .cache
46 | nosetests.xml
47 | coverage.xml
48 | *.cover
49 | *.py,cover
50 | .hypothesis/
51 | .pytest_cache/
52 | cover/
53 |
54 | # Translations
55 | *.mo
56 | *.pot
57 |
58 | # Django stuff:
59 | *.log
60 | local_settings.py
61 | db.sqlite3
62 | db.sqlite3-journal
63 |
64 | # Flask stuff:
65 | instance/
66 | .webassets-cache
67 |
68 | # Scrapy stuff:
69 | .scrapy
70 |
71 | # Sphinx documentation
72 | docs/_build/
73 |
74 | # PyBuilder
75 | .pybuilder/
76 | target/
77 |
78 | # Jupyter Notebook
79 | .ipynb_checkpoints
80 |
81 | # IPython
82 | profile_default/
83 | ipython_config.py
84 |
85 | # pyenv
86 | # For a library or package, you might want to ignore these files since the code is
87 | # intended to run in multiple environments; otherwise, check them in:
88 | # .python-version
89 |
90 | # pipenv
91 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
92 | # However, in case of collaboration, if having platform-specific dependencies or dependencies
93 | # having no cross-platform support, pipenv may install dependencies that don't work, or not
94 | # install all needed dependencies.
95 | #Pipfile.lock
96 |
97 | # poetry
98 | # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
99 | # This is especially recommended for binary packages to ensure reproducibility, and is more
100 | # commonly ignored for libraries.
101 | # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
102 | #poetry.lock
103 |
104 | # pdm
105 | # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
106 | #pdm.lock
107 | # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
108 | # in version control.
109 | # https://pdm.fming.dev/#use-with-ide
110 | .pdm.toml
111 |
112 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
113 | __pypackages__/
114 |
115 | # Celery stuff
116 | celerybeat-schedule
117 | celerybeat.pid
118 |
119 | # SageMath parsed files
120 | *.sage.py
121 |
122 | # Environments
123 | .env
124 | .venv
125 | env/
126 | venv/
127 | ENV/
128 | env.bak/
129 | venv.bak/
130 |
131 | # Spyder project settings
132 | .spyderproject
133 | .spyproject
134 |
135 | # Rope project settings
136 | .ropeproject
137 |
138 | # mkdocs documentation
139 | /site
140 |
141 | # mypy
142 | .mypy_cache/
143 | .dmypy.json
144 | dmypy.json
145 |
146 | # Pyre type checker
147 | .pyre/
148 |
149 | # pytype static type analyzer
150 | .pytype/
151 |
152 | # Cython debug symbols
153 | cython_debug/
154 |
155 | # PyCharm
156 | # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
157 | # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
158 | # and can be added to the global gitignore or merged into this file. For a more nuclear
159 | # option (not recommended) you can uncomment the following to ignore the entire idea folder.
160 | #.idea/
161 |
162 | # local
163 | interpol_transforms
164 | .mtg
165 | .zip
166 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023 Soxoj
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Interpol Notices transforms for Maltego
2 |
3 | A list of transforms for searching Red, Yellow, and UNSC notices by Name or Phrase.
4 |
5 | 
6 |
7 | [Official source](https://www.interpol.int/How-we-work/Notices/View-Red-Notices), [API description](https://interpol.api.bund.dev/).
8 |
9 | # How to use
10 |
11 | ## Import entities
12 |
13 | Import Entities and Icons from `interpol.mtz` to your Maltego (thanks sinwindie!).
14 |
15 |
16 |
17 | Automatic configuring of imported local transforms is a bit difficult and will be implemented later.
18 |
19 | ## Create transforms (manually)
20 |
21 | Configure each file in transforms folder like this:
22 |
23 | 1. Press "New Local Transforms..." button
24 |
25 |
26 |
27 | 2. Fill in the fields in the first window
28 |
29 |
30 |
31 | 3. Fill in the fields in the second window
32 |
33 |
34 |
35 | # Running
36 |
37 | Create Person entity for searching by namme. Be sure you've entered first/last name in the right order, change it if you don't get results.
38 |
39 | Create Phrase entity for searching by keyword OR part of name, even for mentioned relatives.
40 |
41 |
42 |
43 | ## TODO
44 |
45 | - [ ] Face search transforms / converters
46 | - [ ] Local transforms configuring automation
47 | - [ ] Test examples
48 |
49 | =======
50 | ## Credits
51 |
52 | **Many thanks to OSINT Dojo / Sinwindie for entities, icons and initial source code: https://github.com/OsintDojo/public**
53 |
--------------------------------------------------------------------------------
/interpol.mtz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SocialLinks-IO/interpol-notices-maltego/2c14859da87c109a2865bd188dd08bd1f5a50f3f/interpol.mtz
--------------------------------------------------------------------------------
/project.py:
--------------------------------------------------------------------------------
1 | import sys
2 | import transforms
3 |
4 | from maltego_trx.registry import register_transform_function, register_transform_classes
5 | from maltego_trx.server import app, application
6 | from maltego_trx.handler import handle_run
7 |
8 | register_transform_classes(transforms)
9 |
10 | handle_run(__name__, sys.argv, app)
11 |
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | maltego_trx
2 | requests
3 | chardet
--------------------------------------------------------------------------------
/transforms/ConvertToSearchFaceEntity.py:
--------------------------------------------------------------------------------
1 | # Required Imports
2 | from maltego_trx.maltego import MaltegoMsg, MaltegoTransform
3 | from maltego_trx.transform import DiscoverableTransform
4 |
5 | class ConvertToSearchFaceEntity(DiscoverableTransform):
6 |
7 | @classmethod
8 | def create_entities(cls, request: MaltegoMsg, response: MaltegoTransform):
9 |
10 | # Obtain Target Information from Entity
11 | request_firstname = request.getProperty("firstname")
12 | if bool(request_firstname) == False:
13 | request_firstname = ''
14 |
15 | request_lastname = request.getProperty("lastname")
16 | if bool(request_lastname) == False:
17 | request_lastname = ''
18 |
19 | photo_url = request.getProperty("photo") or request.getProperty("PhotoURL") or request.getProperty("URL")
20 |
21 | face_search = response.addEntity("maltego.SearchFace")
22 |
23 | face_search.addProperty("firstname", value = request_firstname)
24 | face_search.addProperty("lastname", value = request_lastname)
25 | face_search.addProperty("fullname", value = request_firstname + " " + request_lastname)
26 | face_search.addProperty("photo", value = photo_url)
27 |
28 |
--------------------------------------------------------------------------------
/transforms/RedNoticeByPhraseFaceSearch.py:
--------------------------------------------------------------------------------
1 | # Required Imports
2 | from maltego_trx.maltego import MaltegoMsg, MaltegoTransform
3 | from maltego_trx.transform import DiscoverableTransform
4 | import requests
5 |
6 | class RedNoticeByPhraseFaceSearch(DiscoverableTransform):
7 |
8 | @classmethod
9 | def create_entities(cls, request: MaltegoMsg, response: MaltegoTransform):
10 |
11 | # Obtain Target Information from Entity
12 | request_phrase = request.getProperty("text")
13 | if bool(request_phrase) == False:
14 | request_phrase = ''
15 |
16 | # Search for Target Information via Interpol Red Notice API
17 | red_notice_url = 'https://ws-public.interpol.int/notices/v1/red?&freeText=' + request_phrase
18 |
19 | api_response = requests.get(red_notice_url)
20 | red_notices = api_response.json()
21 | red_notices = (red_notices['_embedded']['notices'])
22 |
23 | # Iterate through all returned Red Notices
24 | for i in red_notices:
25 |
26 | red_notice_entity = response.addEntity("maltego.SearchFace")
27 |
28 | response_firstname = i.get("forename", '')
29 | if response_firstname:
30 | red_notice_entity.addProperty("firstname", value = response_firstname)
31 |
32 | response_lastname = i.get("name", '')
33 | if response_lastname:
34 | red_notice_entity.addProperty("lastname", value = response_lastname)
35 |
36 | red_notice_entity.addProperty("fullname", value = response_firstname + " " + response_lastname)
37 |
38 | # red_notice_entity.addProperty("Full Name / Alias", response_firstname + response_lastname)
39 |
40 | response_photo = i['_links'].get('thumbnail')
41 | if response_photo:
42 | photo_url = response_photo['href']
43 | photo_url_id = photo_url.split('/')[-1]
44 | full_photo_url_id = int(photo_url_id) -1
45 | full_photo_url = photo_url.rsplit('/', 1)[0] + '/' + str(full_photo_url_id)
46 |
47 | red_notice_entity.addProperty("photo", value = full_photo_url)
48 |
--------------------------------------------------------------------------------
/transforms/RedNoticeEntitiesByName.py:
--------------------------------------------------------------------------------
1 | # Required Imports
2 | from maltego_trx.maltego import MaltegoMsg, MaltegoTransform
3 | from maltego_trx.transform import DiscoverableTransform
4 | from .common import *
5 |
6 | class RedNoticeEntitiesByName(DiscoverableTransform):
7 |
8 | @classmethod
9 | def create_entities(cls, request: MaltegoMsg, response: MaltegoTransform):
10 |
11 | # Obtain Target Information from Entity
12 | request_firstname = request.getProperty("firstname")
13 | if bool(request_firstname) == False:
14 | request_firstname = ''
15 |
16 | request_lastname = request.getProperty("lastname")
17 | if bool(request_lastname) == False:
18 | request_lastname = ''
19 |
20 | # Search for Target Information via Interpol Red Notice API
21 | url = 'https://ws-public.interpol.int/notices/v1/red?&name=' + request_lastname + '&forename=' + request_firstname
22 |
23 | api_response = requests.get(url)
24 | notices = api_response.json()
25 | notices = (notices['_embedded']['notices'])
26 |
27 | # Iterate through all returned Red Notices
28 | for notice_data in notices:
29 | notice_entity = response.addEntity("yourorganization.InterpolRedNotice")
30 | create_notice_entity(notice_entity, notice_data)
31 |
--------------------------------------------------------------------------------
/transforms/RedNoticeEntitiesByPhrase.py:
--------------------------------------------------------------------------------
1 | # Required Imports
2 | from maltego_trx.maltego import MaltegoMsg, MaltegoTransform
3 | from maltego_trx.transform import DiscoverableTransform
4 | from .common import *
5 |
6 | class RedNoticeEntitiesByPhrase(DiscoverableTransform):
7 |
8 | @classmethod
9 | def create_entities(cls, request: MaltegoMsg, response: MaltegoTransform):
10 |
11 | # Obtain Target Information from Entity
12 | request_phrase = request.getProperty("text")
13 | if bool(request_phrase) == False:
14 | request_phrase = ''
15 |
16 | # Search for Target Information via Interpol Red Notice API
17 | url = 'https://ws-public.interpol.int/notices/v1/red?&freeText=' + request_phrase
18 |
19 | api_response = requests.get(url)
20 | notices = api_response.json()
21 | notices = (notices['_embedded']['notices'])
22 |
23 | # Iterate through all returned Red Notices
24 | for notice_data in notices:
25 | notice_entity = response.addEntity("yourorganization.InterpolRedNotice")
26 | create_notice_entity(notice_entity, notice_data)
27 |
--------------------------------------------------------------------------------
/transforms/RedNoticeFaceSearch.py:
--------------------------------------------------------------------------------
1 | # Required Imports
2 | from maltego_trx.maltego import MaltegoMsg, MaltegoTransform
3 | from maltego_trx.transform import DiscoverableTransform
4 | import requests
5 |
6 | class RedNoticeFaceSearch(DiscoverableTransform):
7 |
8 | @classmethod
9 | def create_entities(cls, request: MaltegoMsg, response: MaltegoTransform):
10 |
11 | # Obtain Target Information from Entity
12 | request_firstname = request.getProperty("firstname")
13 | if bool(request_firstname) == False:
14 | request_firstname = ''
15 |
16 | request_lastname = request.getProperty("lastname")
17 | if bool(request_lastname) == False:
18 | request_lastname = ''
19 |
20 |
21 | # Search for Target Information via Interpol Red Notice API
22 | red_notice_url = 'https://ws-public.interpol.int/notices/v1/red?&name=' + request_lastname + '&forename=' + request_firstname
23 |
24 | api_response = requests.get(red_notice_url)
25 | red_notices = api_response.json()
26 | red_notices = (red_notices['_embedded']['notices'])
27 |
28 | # Iterate through all returned Red Notices
29 | for i in red_notices:
30 |
31 | red_notice_entity = response.addEntity("maltego.SearchFace")
32 |
33 | response_firstname = i.get("forename", '')
34 | if response_firstname:
35 | red_notice_entity.addProperty("firstname", value = response_firstname)
36 |
37 | response_lastname = i.get("name", '')
38 | if response_lastname:
39 | red_notice_entity.addProperty("lastname", value = response_lastname)
40 |
41 | red_notice_entity.addProperty("fullname", value = response_firstname + " " + response_lastname)
42 |
43 | response_photo = i['_links'].get('thumbnail')
44 | if response_photo:
45 | photo_url = response_photo['href']
46 | photo_url_id = photo_url.split('/')[-1]
47 | full_photo_url_id = int(photo_url_id) -1
48 | full_photo_url = photo_url.rsplit('/', 1)[0] + '/' + str(full_photo_url_id)
49 |
50 | red_notice_entity.addProperty("photo", value = full_photo_url)
51 |
52 |
53 |
54 |
--------------------------------------------------------------------------------
/transforms/UNSCNoticeEntitiesByName.py:
--------------------------------------------------------------------------------
1 | # Required Imports
2 | from maltego_trx.maltego import MaltegoMsg, MaltegoTransform
3 | from maltego_trx.transform import DiscoverableTransform
4 | from .common import *
5 |
6 | class UNSCNoticeEntitiesByName(DiscoverableTransform):
7 |
8 | @classmethod
9 | def create_entities(cls, request: MaltegoMsg, response: MaltegoTransform):
10 |
11 | # Obtain Target Information from Entity
12 | request_firstname = request.getProperty("firstname")
13 | if bool(request_firstname) == False:
14 | request_firstname = ''
15 |
16 | request_lastname = request.getProperty("lastname")
17 | if bool(request_lastname) == False:
18 | request_lastname = ''
19 |
20 | # Search for Target Information via Interpol UNSC Notice API
21 | url = 'https://ws-public.interpol.int/notices/v1/un?&name=' + request_lastname + '&forename=' + request_firstname
22 |
23 | api_response = requests.get(url)
24 | notices = api_response.json()
25 | notices = (notices['_embedded']['notices'])
26 |
27 | # Iterate through all returned UNSC Notices
28 | for notice_data in notices:
29 | notice_entity = response.addEntity("yourorganization.InterpolUNSCNotice")
30 | create_notice_entity(notice_entity, notice_data)
31 |
32 |
33 |
--------------------------------------------------------------------------------
/transforms/UNSCNoticeEntitiesByPhrase.py:
--------------------------------------------------------------------------------
1 | # Required Imports
2 | from maltego_trx.maltego import MaltegoMsg, MaltegoTransform
3 | from maltego_trx.transform import DiscoverableTransform
4 | from .common import *
5 |
6 | class UNSCNoticeEntitiesByPhrase(DiscoverableTransform):
7 |
8 | @classmethod
9 | def create_entities(cls, request: MaltegoMsg, response: MaltegoTransform):
10 |
11 | # Obtain Target Information from Entity
12 | request_phrase = request.getProperty("text")
13 | if bool(request_phrase) == False:
14 | request_phrase = ''
15 |
16 | # Search for Target Information via Interpol UNSC Notice API
17 | url = 'https://ws-public.interpol.int/notices/v1/un?&freeText=' + request_phrase
18 |
19 | api_response = requests.get(url)
20 | notices = api_response.json()
21 | notices = (notices['_embedded']['notices'])
22 |
23 | # Iterate through all returned UNSC Notices
24 | for notice_data in notices:
25 | notice_entity = response.addEntity("yourorganization.InterpolUNSCNotice")
26 | create_notice_entity(notice_entity, notice_data)
27 |
28 |
29 |
--------------------------------------------------------------------------------
/transforms/YellowNoticeEntitiesByName.py:
--------------------------------------------------------------------------------
1 | # Required Imports
2 | from maltego_trx.maltego import MaltegoMsg, MaltegoTransform
3 | from maltego_trx.transform import DiscoverableTransform
4 | from .common import *
5 |
6 | class YellowNoticeEntitiesByName(DiscoverableTransform):
7 |
8 | @classmethod
9 | def create_entities(cls, request: MaltegoMsg, response: MaltegoTransform):
10 |
11 | # Obtain Target Information from Entity
12 | request_firstname = request.getProperty("firstname")
13 | if bool(request_firstname) == False:
14 | request_firstname = ''
15 |
16 | request_lastname = request.getProperty("lastname")
17 | if bool(request_lastname) == False:
18 | request_lastname = ''
19 |
20 | # Search for Target Information via Interpol Yellow Notice API
21 | url = 'https://ws-public.interpol.int/notices/v1/yellow?&name=' + request_lastname + '&forename=' + request_firstname
22 |
23 | api_response = requests.get(url)
24 | notices = api_response.json()
25 | notices = (notices['_embedded']['notices'])
26 |
27 | # Iterate through all returned Yellow Notices
28 | for notice_data in notices:
29 | notice_entity = response.addEntity("yourorganization.InterpolYellowNotice")
30 | create_notice_entity(notice_entity, notice_data)
31 |
--------------------------------------------------------------------------------
/transforms/YellowNoticeEntitiesByPhrase.py:
--------------------------------------------------------------------------------
1 | # Required Imports
2 | from maltego_trx.maltego import MaltegoMsg, MaltegoTransform
3 | from maltego_trx.transform import DiscoverableTransform
4 | from .common import *
5 |
6 | class YellowNoticeEntitiesByPhrase(DiscoverableTransform):
7 |
8 | @classmethod
9 | def create_entities(cls, request: MaltegoMsg, response: MaltegoTransform):
10 |
11 | # Obtain Target Information from Entity
12 | request_phrase = request.getProperty("text")
13 | if bool(request_phrase) == False:
14 | request_phrase = ''
15 |
16 | # Search for Target Information via Interpol Yellow Notice API
17 | url = 'https://ws-public.interpol.int/notices/v1/yellow?&freeText=' + request_phrase
18 |
19 | api_response = requests.get(url)
20 | notices = api_response.json()
21 | notices = (notices['_embedded']['notices'])
22 |
23 | # Iterate through all returned Yellow Notices
24 | for notice_data in notices:
25 | notice_entity = response.addEntity("yourorganization.InterpolYellowNotice")
26 | create_notice_entity(notice_entity, notice_data)
27 |
--------------------------------------------------------------------------------
/transforms/common.py:
--------------------------------------------------------------------------------
1 | import requests
2 |
3 | def create_notice_entity(notice_entity, notice_data):
4 | response_firstname = notice_data.get("forename")
5 | if response_firstname:
6 | notice_entity.addProperty("firstname", value = response_firstname)
7 |
8 | response_lastname = notice_data.get("name")
9 | if response_lastname:
10 | notice_entity.addProperty("lastname", value = response_lastname)
11 |
12 | response_dob = notice_data.get("date_of_birth")
13 | if response_dob:
14 | notice_entity.addProperty("DateOfBirth", value = response_dob)
15 |
16 | response_nationality = notice_data.get("nationalities")
17 | if response_nationality:
18 | notice_entity.addProperty("Nationality", value = response_nationality[0])
19 |
20 | response_photo = notice_data['_links'].get('thumbnail')
21 | if response_photo:
22 | photo_url = response_photo['href']
23 | # preview
24 | notice_entity.addProperty("PhotoURL", value = photo_url)
25 | # full photo
26 | photo_url_id = photo_url.split('/')[-1]
27 | full_photo_url_id = int(photo_url_id) -1
28 | full_photo_url = photo_url.rsplit('/', 1)[0] + '/' + str(full_photo_url_id)
29 |
30 | notice_entity.addProperty("photo", value = full_photo_url)
31 |
--------------------------------------------------------------------------------