Skip to content

Commit 0640e1c

Browse files
author
netevert
committed
committed v.1.1
1 parent 2b4d8d8 commit 0640e1c

File tree

4 files changed

+250
-27
lines changed

4 files changed

+250
-27
lines changed

CHANGELOG.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,19 @@ All notable changes to this project will be documented in this file.
44
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
55
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
66

7+
## [1.1.0] - 2019-12-08
8+
9+
### Added
10+
11+
- Ability to save investigation
12+
- Ability to load investigation
13+
- Ability to delete investigation
14+
- Ability to clear investigation data
15+
16+
### Fixed
17+
18+
- GUI freezing due to absence of threaded transforms
19+
720
## [1.0.0] - 2019-06-23
821

922
### Added

README.md

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -96,13 +96,4 @@ MD5 and SHA256 hashes are searchable
9696
</p>
9797
</details>
9898

99-
New APIs and input integrations are constantly being added to the tool. Consult the [roadmap](https://github.com/netevert/pockint/milestones) to check out what's brewing or [propose](https://github.com/netevert/pockint/issues) your own favourite API/input.
100-
101-
## Credits
102-
103-
Credit goes to the following people for their contributions to the project, either as providers of early feedback/ideas or for their awesome help in spreading the word:
104-
105-
* [Olaf Hartong](https://twitter.com/olafhartong)
106-
* [Uriel](https://github.com/0x557269656C)
107-
* [Jake Creps](https://twitter.com/jakecreps)
108-
* [Simon Biles](https://twitter.com/si_biles)
99+
New APIs and input integrations are in the works, consult the [issues page](https://github.com/netevert/pockint/issues) to check out what's brewing or feel free to propose your own.

pockint.py

Lines changed: 203 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
#!/usr/bin/env python
22

33
import datetime
4+
from threading import Thread
45
import tkinter as tk
56
from tkinter import messagebox
67
import tkinter.ttk as ttk
78
from utils import InputValidator, Database, load_icon, callback
89
import sys
910

10-
__version__ = '1.0.0'
11+
__version__ = '1.1.0'
1112

1213
class CreditsTool(tk.Toplevel):
1314
"""Opens a new window providing credits"""
@@ -16,7 +17,6 @@ def __init__(self, master=None, *args, **kwargs):
1617
"""Initializes Toplevel object and builds credit interface."""
1718
super().__init__(master, *args, **kwargs)
1819
# hide window in background during drawing and load, to prevent flickering and glitches during frame load
19-
#
2020
self.withdraw()
2121
# build and draw the window
2222
self.build()
@@ -85,7 +85,7 @@ def save_data(self):
8585
"""Stores investigation data within database"""
8686
if self.data:
8787
try:
88-
self.db_handler.store_investigation(self.investigation_id, self.data)
88+
self.db_handler.store_investigation(self.entry.get(), self.data)
8989
messagebox.showinfo("Success", "Successfully saved investigation")
9090
self.quit_save()
9191

@@ -100,6 +100,130 @@ def quit_save(self):
100100
self.db_handler.close_connection()
101101
self.destroy()
102102

103+
class OpenTool(tk.Toplevel):
104+
"""Opens a window to retrieve investigation data"""
105+
def __init__(self, master=None, *args, **kwargs):
106+
"""Initializes Toplevel object and builds interface"""
107+
super().__init__(master, *args, **kwargs)
108+
# initialize variables
109+
self.selection = tk.StringVar(self)
110+
# initialize database
111+
self.db_handler = Database()
112+
# hide window in background during drawing and load, to prevent flickering and glitches during frame load
113+
self.withdraw()
114+
# build and draw the window
115+
self.build()
116+
# unhide the Toplevel window immediately after draw and load
117+
self.after(0, self.deiconify)
118+
119+
def build(self):
120+
"""Initializes and builds application widgets"""
121+
# create input labelframe
122+
labelframe_1 = tk.LabelFrame(self, fg='brown')
123+
labelframe_1.pack(side="top", expand='yes', fill='both', padx=2, pady=2, anchor="n")
124+
125+
# create explanation label
126+
self.label = tk.Label(labelframe_1, text='Load...')
127+
self.label.pack(expand=True, fill='x', side="left", padx=2, pady=2)
128+
129+
# create data input entry widget
130+
self.options = tk.OptionMenu(labelframe_1, self.selection, *self.db_handler.retrieve_investigation_ids(),
131+
command=self.open_data)
132+
self.options.pack(expand=True, fill='x', side="left", padx=2, pady=2)
133+
self.selection.set(self.db_handler.retrieve_investigation_ids()[0])
134+
135+
# create save button
136+
self.save_button = tk.Button(labelframe_1, text="Open", command=self.open_data)
137+
self.save_button.pack(expand=False, side="left", padx=2, pady=2, anchor="e")
138+
139+
# create cancel button
140+
self.cancel_button = tk.Button(labelframe_1, text="Cancel", command=self.quit_open)
141+
self.cancel_button.pack(expand=False, side="left", padx=2, pady=2, anchor="e")
142+
143+
def open_data(self, value=None):
144+
"""Retrieves investigation data from database"""
145+
pockint.treeview.delete(*pockint.treeview.get_children())
146+
pockint.id_tracker = {}
147+
if value:
148+
investigation_id = value
149+
else:
150+
investigation_id = self.selection.get()
151+
try:
152+
iid, data = self.db_handler.open_investigation(investigation_id)
153+
for target in data:
154+
for transform in data[target]:
155+
pockint.treeview.insert(pockint.getID(target), "end", values=(transform[0], transform[1]))
156+
pockint.investigation_id_tracker = iid
157+
self.quit_open()
158+
159+
except Exception as e:
160+
print("[*] Error: ", e)
161+
self.quit_open()
162+
163+
def quit_open(self):
164+
"""Quits the open window"""
165+
self.db_handler.close_connection()
166+
self.destroy()
167+
168+
class DeleteTool(tk.Toplevel):
169+
"""Opens a window to retrieve investigation data"""
170+
def __init__(self, master=None, *args, **kwargs):
171+
"""Initializes Toplevel object and builds interface"""
172+
super().__init__(master, *args, **kwargs)
173+
# initialize variables
174+
self.selection = tk.StringVar(self)
175+
# initialize database
176+
self.db_handler = Database()
177+
# hide window in background during drawing and load, to prevent flickering and glitches during frame load
178+
self.withdraw()
179+
# build and draw the window
180+
self.build()
181+
# unhide the Toplevel window immediately after draw and load
182+
self.after(0, self.deiconify)
183+
184+
def build(self):
185+
"""Initializes and builds application widgets"""
186+
# create input labelframe
187+
labelframe_1 = tk.LabelFrame(self, fg='brown')
188+
labelframe_1.pack(side="top", expand='yes', fill='both', padx=2, pady=2, anchor="n")
189+
190+
# create explanation label
191+
self.label = tk.Label(labelframe_1, text='Delete...')
192+
self.label.pack(expand=True, fill='x', side="left", padx=2, pady=2)
193+
194+
# create data input entry widget
195+
self.options = tk.OptionMenu(labelframe_1, self.selection, *self.db_handler.retrieve_investigation_ids(),
196+
command=self.delete_data)
197+
self.options.pack(expand=True, fill='x', side="left", padx=2, pady=2)
198+
self.selection.set(self.db_handler.retrieve_investigation_ids()[0])
199+
200+
# create save button
201+
self.save_button = tk.Button(labelframe_1, text="Delete", command=self.delete_data)
202+
self.save_button.pack(expand=False, side="left", padx=2, pady=2, anchor="e")
203+
204+
# create cancel button
205+
self.cancel_button = tk.Button(labelframe_1, text="Cancel", command=self.quit)
206+
self.cancel_button.pack(expand=False, side="left", padx=2, pady=2, anchor="e")
207+
208+
def delete_data(self, value=None):
209+
"""Deletes investigation data from database"""
210+
if value:
211+
investigation_id = value
212+
else:
213+
investigation_id = self.selection.get()
214+
try:
215+
self.db_handler.delete_investigation(investigation_id)
216+
self.quit()
217+
218+
except Exception as e:
219+
print("[*] Error: ", e)
220+
self.quit()
221+
222+
def quit(self):
223+
"""Quits the open window"""
224+
self.db_handler.close_connection()
225+
self.destroy()
226+
103227
class ApiTool(tk.Toplevel):
104228
"""Opens a new window providing users ability to input api keys"""
105229

@@ -187,8 +311,9 @@ def build_menu(self):
187311

188312
# create file menu
189313
self.file = tk.Menu(self.top, tearoff=False)
190-
self.file.add_command(label="Open investigation...", compound=tk.LEFT, underline=0, command=None)
314+
self.file.add_command(label="Load investigation...", compound=tk.LEFT, underline=0, command=self.open_investigation)
191315
self.file.add_command(label="Save investigation...", compound=tk.LEFT, underline=0, command=self.save_investigation)
316+
self.file.add_command(label="Delete investigation...", compound=tk.LEFT, underline=0, command=self.delete_investigation)
192317
self.file.add_separator()
193318
self.file.add_command(label='Exit', command=self.quit_program,
194319
underline=0)
@@ -197,6 +322,8 @@ def build_menu(self):
197322

198323
# create edit menu
199324
self.edit = tk.Menu(self.top, tearoff=False)
325+
self.edit.add_command(label="Clear data", compound=tk.LEFT, underline=0, command=self.clear_investigation_data)
326+
self.edit.add_separator()
200327
self.edit.add_command(label='API keys', command=self.manage_apis,
201328
compound=tk.LEFT, underline=0)
202329
self.top.add_cascade(label='Edit', menu=self.edit, underline=0)
@@ -308,6 +435,7 @@ def validate_input(self, event=None):
308435

309436
def run_data_mining(self, event=None):
310437
"""Performs the select OSINT data mining operation"""
438+
self.finished = False
311439
if self.multi_select.get():
312440
self.transforms_tracker.add(self.selector.get())
313441
self.status['text'] = "multi-select: [{}]".format(" - ".join([transform for transform in self.transforms_tracker]))
@@ -318,18 +446,31 @@ def run_data_mining(self, event=None):
318446
transform = self.selector.get()
319447
self.transforms_tracker.add(transform)
320448
try:
321-
for i in _input:
322-
for transform in self.transforms_tracker:
323-
data = self.validator.execute_transform(i, transform)
324-
for item in data:
325-
self.treeview.insert(self.getID(i), "end", values=(transform, item))
449+
t = Thread(target=self.run_transform, args=(_input, self.transforms_tracker,))
450+
t.daemon = True
451+
t.start()
452+
self.check_status()
326453
self.entry.focus()
327454
self.status['text'] = "ready"
328455
self.transforms_tracker.clear()
329456
except Exception as e:
330457
messagebox.showerror("Error", "Error message:" + str(e))
331458
else:
332459
self.status['text'] = "no inputs"
460+
461+
def run_transform(self, _input, transforms):
462+
"""Run lisf of transforms on input data"""
463+
for i in _input:
464+
for transform in transforms:
465+
data = self.validator.execute_transform(i, transform)
466+
for item in data:
467+
self.treeview.insert(self.getID(i), "end", values=(transform, item))
468+
self.finished = True
469+
470+
def check_status(self):
471+
"""Checks if the transform thread has finished executing"""
472+
while self.finished is False:
473+
root.update()
333474

334475
def getID(self, item):
335476
"""Grabs the ID of the queried treeview item"""
@@ -362,6 +503,7 @@ def view_credits(self):
362503
self.win_credits.title('Credits')
363504
self.win_credits.geometry('+%d+%d' % (root.winfo_x() +
364505
20, root.winfo_y() + 20))
506+
self.win_credits.geometry("160x100")
365507
if sys.platform == "win32":
366508
self.win_credits.iconbitmap(self.icon)
367509
self.win_credits.resizable(width=False, height=False)
@@ -403,7 +545,7 @@ def grab_investigation_data(self):
403545
def save_investigation(self):
404546
"""Saves investigation data"""
405547
if not self.investigation_id_tracker:
406-
self.investigation_id_tracker = datetime.datetime.now().strftime("%Y%m%d%H%M")
548+
self.investigation_id_tracker = datetime.datetime.now().strftime("%Y-%m-%d_%H:%M")
407549
data = self.grab_investigation_data()
408550

409551
self.save = SaveTool(investigation_id=self.investigation_id_tracker, data=data)
@@ -421,6 +563,56 @@ def save_investigation(self):
421563
# start mainloop
422564
self.save.mainloop()
423565

566+
def open_investigation(self):
567+
"""Open investigation data"""
568+
db = Database()
569+
investigation_ids = db.retrieve_investigation_ids()
570+
if not investigation_ids:
571+
messagebox.showinfo("No saved investigations", "Please save an investigation before loading data")
572+
db.close_connection()
573+
if investigation_ids:
574+
# clear investigation id
575+
self.investigation_id_tracker = ""
576+
577+
self.open = OpenTool()
578+
self.open.title('Open investigation')
579+
self.open.geometry('+%d+%d' % (root.winfo_x() +
580+
20, root.winfo_y() + 20))
581+
if sys.platform == "win32":
582+
self.open.iconbitmap(self.icon)
583+
self.open.resizable(width=False, height=False)
584+
self.open.protocol('WM_DELETE_WINDOW', self.open.quit_open)
585+
# set focus on window
586+
self.open.grab_set()
587+
self.open.focus()
588+
589+
# start mainloop
590+
self.open.mainloop()
591+
592+
def delete_investigation(self):
593+
"""Delete investigation data"""
594+
self.delete = DeleteTool()
595+
self.delete.title('Delete investigation')
596+
self.delete.geometry('+%d+%d' % (root.winfo_x() +
597+
20, root.winfo_y() + 20))
598+
if sys.platform == "win32":
599+
self.delete.iconbitmap(self.icon)
600+
self.delete.resizable(width=False, height=False)
601+
self.delete.protocol('WM_DELETE_WINDOW', self.delete.quit)
602+
# set focus on window
603+
self.delete.grab_set()
604+
self.delete.focus()
605+
606+
# start mainloop
607+
self.delete.mainloop()
608+
609+
def clear_investigation_data(self, event=None):
610+
"""Clears investigation data from treeview"""
611+
self.treeview.delete(*pockint.treeview.get_children())
612+
self.id_tracker = {}
613+
self.entry.delete(0, "end")
614+
self.validate_input()
615+
424616
@staticmethod
425617
def quit_program():
426618
"""Quits main program window"""
@@ -435,4 +627,4 @@ def quit_program():
435627
if sys.platform == "win32":
436628
root.iconbitmap(pockint.icon)
437629
root.protocol('WM_DELETE_WINDOW', pockint.quit_program)
438-
root.mainloop()
630+
root.mainloop()

0 commit comments

Comments
 (0)