Skip to content

Instantly share code, notes, and snippets.

@swarupsro
Created May 4, 2026 10:07
Show Gist options
  • Select an option

  • Save swarupsro/1d4fb8c8448b10a187f393eb9c0392bf to your computer and use it in GitHub Desktop.

Select an option

Save swarupsro/1d4fb8c8448b10a187f393eb9c0392bf to your computer and use it in GitHub Desktop.
RevserseIP
#!/usr/bin/env python3
import requests
import socket
import curses
import sys
import math
class Colors:
GREEN = '\033[92m'
CYAN = '\033[96m'
YELLOW = '\033[93m'
RED = '\033[91m'
RESET = '\033[0m'
BOLD = '\033[1m'
SUSPICIOUS_KEYWORDS = [
"cpanel", "webmail", "mail", "ftp", "admin", "login",
"test", "dev", "uat", "staging", "backup", "old",
"portal", "vpn", "remote", "db", "database", "phpmyadmin",
"wordpress", "wp-admin", "api"
]
def get_ip(domain):
try:
return socket.gethostbyname(domain)
except Exception as e:
print(f"{Colors.RED}[!] Error resolving domain: {e}{Colors.RESET}")
sys.exit(1)
def reverse_ip_lookup(ip):
url = f"https://api.hackertarget.com/reverseiplookup/?q={ip}"
try:
response = requests.get(url, timeout=15)
return response.text
except Exception as e:
print(f"{Colors.RED}[!] API request failed: {e}{Colors.RESET}")
sys.exit(1)
def prepare_domains(data):
if "error" in data.lower():
return []
return sorted(set([d.strip() for d in data.strip().splitlines() if d.strip()]))
def is_suspicious(domain):
domain_lower = domain.lower()
return any(keyword in domain_lower for keyword in SUSPICIOUS_KEYWORDS)
def get_domain_color(domain):
d = domain.lower()
if is_suspicious(d):
return 4 # Red
if d.endswith(".gov") or ".gov." in d:
return 5 # Magenta
if d.endswith(".edu") or ".edu." in d or d.endswith(".ac.bd"):
return 6 # Blue
if d.endswith(".com") or ".com." in d:
return 2 # Green
if d.endswith(".bd"):
return 7 # White
return 2 # Green
def get_column_count(width):
if width >= 150:
return 3
elif width >= 90:
return 2
return 1
def build_rows(domains, width):
columns = get_column_count(width)
total = len(domains)
if total == 0:
return [[None]]
rows = math.ceil(total / columns)
table = []
for row in range(rows):
line_items = []
for col in range(columns):
index = row + (col * rows)
if index < total:
line_items.append((index + 1, domains[index]))
else:
line_items.append(None)
table.append(line_items)
return table
def draw_domain_item(stdscr, y, x, number, domain, col_width):
number_text = f"{number:03}"
arrow_text = " -> "
domain_text = domain[:max(1, col_width - 8)]
try:
stdscr.addstr(y, x, number_text, curses.color_pair(3) | curses.A_BOLD)
x += len(number_text)
stdscr.addstr(y, x, arrow_text, curses.color_pair(1))
x += len(arrow_text)
domain_color = get_domain_color(domain)
attr = curses.color_pair(domain_color)
if is_suspicious(domain):
attr |= curses.A_BOLD
stdscr.addstr(y, x, domain_text, attr)
except curses.error:
pass
def curses_ui(stdscr, domain, ip, domains):
curses.curs_set(0)
stdscr.nodelay(False)
stdscr.keypad(True)
curses.start_color()
curses.use_default_colors()
curses.init_pair(1, curses.COLOR_CYAN, -1) # Arrow / info
curses.init_pair(2, curses.COLOR_GREEN, -1) # .com / normal
curses.init_pair(3, curses.COLOR_YELLOW, -1) # Number
curses.init_pair(4, curses.COLOR_RED, -1) # Suspicious
curses.init_pair(5, curses.COLOR_MAGENTA, -1) # .gov
curses.init_pair(6, curses.COLOR_BLUE, -1) # .edu / .ac.bd
curses.init_pair(7, curses.COLOR_WHITE, -1) # .bd
curses.init_pair(8, curses.COLOR_BLACK, curses.COLOR_YELLOW) # Highlight label
scroll_pos = 0
search_query = ""
while True:
stdscr.clear()
height, width = stdscr.getmaxyx()
filtered = [d for d in domains if search_query.lower() in d.lower()]
rows = build_rows(filtered, width)
columns = get_column_count(width)
col_width = max(35, width // columns)
header1 = "Reverse IP Lookup Tool"
header2 = f"Domain: {domain} | IP: {ip} | Total: {len(domains)} | Showing: {len(filtered)} | Columns: {columns}"
header3 = f"Filter: {search_query if search_query else 'None'}"
help_line = "Keys: Up/Down Scroll | / Search | Backspace Clear | q Quit"
legend = "Legend: RED=Suspicious | MAGENTA=.gov | BLUE=.edu/.ac.bd | GREEN=.com/normal | WHITE=.bd"
stdscr.addstr(0, 0, header1[:width-1], curses.color_pair(2) | curses.A_BOLD)
stdscr.addstr(1, 0, header2[:width-1], curses.color_pair(3))
stdscr.addstr(2, 0, header3[:width-1], curses.color_pair(1))
stdscr.addstr(3, 0, help_line[:width-1], curses.color_pair(4))
stdscr.addstr(4, 0, legend[:width-1], curses.color_pair(1))
available_height = height - 6
max_scroll = max(0, len(rows) - available_height)
if scroll_pos > max_scroll:
scroll_pos = max_scroll
visible_rows = rows[scroll_pos:scroll_pos + available_height]
for row_index, row_items in enumerate(visible_rows):
y = row_index + 6
if row_items == [None]:
stdscr.addstr(y, 0, "No domains found.", curses.color_pair(4))
continue
for col_index, item in enumerate(row_items):
if item is None:
continue
number, domain_name = item
x = col_index * col_width
draw_domain_item(stdscr, y, x, number, domain_name, col_width)
stdscr.refresh()
key = stdscr.getch()
if key == ord("q"):
break
elif key == curses.KEY_DOWN:
scroll_pos = min(scroll_pos + 1, max_scroll)
elif key == curses.KEY_UP:
scroll_pos = max(scroll_pos - 1, 0)
elif key == ord("/"):
curses.echo()
curses.curs_set(1)
stdscr.addstr(5, 0, "Search: ".ljust(width-1), curses.color_pair(3))
stdscr.refresh()
search_query = stdscr.getstr(5, 8, 80).decode(errors="ignore").strip()
scroll_pos = 0
curses.noecho()
curses.curs_set(0)
elif key in [curses.KEY_BACKSPACE, 127, 8]:
search_query = ""
scroll_pos = 0
def main():
print(f"{Colors.BOLD}{Colors.GREEN}Reverse IP Lookup Tool{Colors.RESET}")
domain = input(f"{Colors.YELLOW}Enter Domain: {Colors.RESET}").strip()
if not domain:
print(f"{Colors.RED}[!] Domain cannot be empty{Colors.RESET}")
sys.exit(1)
ip = get_ip(domain)
print(f"{Colors.CYAN}Resolved IP:{Colors.RESET} {ip}")
print(f"{Colors.YELLOW}Fetching reverse IP results...{Colors.RESET}")
data = reverse_ip_lookup(ip)
domains = prepare_domains(data)
if not domains:
print(f"{Colors.RED}[!] No valid domains found or API error.{Colors.RESET}")
print(data)
sys.exit(1)
curses.wrapper(curses_ui, domain, ip, domains)
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment