cip.py (13336B)
1 import requests
2 import sys
3 import os
4 from colorama import init, Fore, Style
5 from pathlib import Path
6 import json
7
8 # colorama 초기화
9 init()
10
11 def get_config_dir():
12 """설정 디렉토리 경로 반환"""
13 return Path.home() / '.cip'
14
15 def get_api_key_file():
16 """API 키 파일 경로 반환"""
17 return get_config_dir() / 'api_key.txt'
18
19 def validate_api_key(api_key):
20 """API 키 유효성 검증 및 사용자 정보 반환"""
21 url = "https://api.criminalip.io/v1/user/me"
22 headers = {"x-api-key": api_key}
23
24 try:
25 response = requests.post(url, headers=headers) # POST 메서드로 API 호출
26 if response.status_code == 200:
27 return response.json() # 유효한 API 키일 경우 JSON 반환
28 return None # 유효하지 않은 API 키일 경우 None 반환
29 except Exception as e:
30 print("An error occurred:", e)
31 return None
32
33
34 def initialize_api_key(api_key):
35 """API 키 초기화 및 저장"""
36 config_dir = get_config_dir()
37 api_key_file = get_api_key_file()
38
39 # 설정 디렉토리 생성
40 if not config_dir.exists():
41 config_dir.mkdir()
42 print(f"{Fore.GREEN}[+] Work directory created at {config_dir}{Style.RESET_ALL}")
43
44 # API 키 유효성 검증
45 user_info = validate_api_key(api_key)
46 if user_info:
47 print(f"{Fore.GREEN}[+] API key is valid")
48 print(f"[+] API key check successful.{Style.RESET_ALL}")
49
50 # 사용자 정보 출력
51 data = user_info.get('data', {})
52 print(f"EMAIL:{data.get('email', 'N/A')}")
53 print(f"NAME:{data.get('name', 'N/A')}")
54 print(f"LAST_ACCESS_DATE:{data.get('last_access_date', 'N/A')}")
55 print(f"MAX_SEARCH:{data.get('max_search', 'N/A')}")
56
57 # API 키 저장
58 with open(api_key_file, 'w') as f:
59 f.write(api_key)
60 print(f"{Fore.GREEN}[+] API key stored in {api_key_file}{Style.RESET_ALL}")
61 return True
62 else:
63 print(f"{Fore.RED}[-] Invalid API key{Style.RESET_ALL}")
64 return False
65
66 def load_api_key():
67 """저장된 API 키 로드"""
68 api_key_file = get_api_key_file()
69 if api_key_file.exists():
70 return api_key_file.read_text().strip()
71 return None
72
73 def print_header(text):
74 """섹션 헤더 출력"""
75 print(f"\n{Fore.CYAN}{'='*50}")
76 print(f"{Style.BRIGHT}{text}")
77 print(f"{Fore.CYAN}{'='*50}{Style.RESET_ALL}")
78
79 def print_field(label, value, color=Fore.WHITE):
80 """필드 출력"""
81 print(f"{Fore.YELLOW}{label}: {color}{value}{Style.RESET_ALL}")
82
83 # 악성 정보 및 개방 포트, 취약성 정보 가져오기
84 def get_malicious_data(ip, api_key):
85 url = f"https://api.criminalip.io/v1/feature/ip/malicious-info?ip={ip}"
86 headers = {"x-api-key": api_key}
87 response = requests.get(url, headers=headers)
88 return response.json()
89
90 # 기본 정보 가져오기
91 def get_summary_data(ip, api_key):
92 url = f"https://api.criminalip.io/v1/asset/ip/summary?ip={ip}"
93 headers = {"x-api-key": api_key}
94 response = requests.get(url, headers=headers)
95 return response.json()
96
97 def process_options(options):
98 """옵션 문자열을 개별 옵션으로 분리"""
99 valid_options = {'c', 'm', 'p', 'a'}
100 if not options.startswith('-'):
101 return []
102
103 options = options[1:]
104 selected_options = []
105
106 if 'a' in options:
107 return ['-c', '-m', '-p']
108
109 for char in options:
110 if char in valid_options:
111 option = f"-{char}"
112 if option not in selected_options:
113 selected_options.append(option)
114
115 return selected_options
116
117 def print_basic_info(data):
118 """기본 정보 출력"""
119 print_header("기본 정보")
120
121 country = data.get("country", "N/A")
122 isp = data.get("isp", "N/A")
123 score = data.get("score", {}).get("inbound", "N/A")
124
125 # 점수에 따른 색상 설정
126 score_color = Fore.GREEN if score == "Safe" else Fore.RED
127
128 print_field("국가", country)
129 print_field("ISP", isp)
130 print_field("Inbound IP Score", score, score_color)
131
132 def print_vulnerability_info(data):
133 """취약성 정보 출력"""
134 print_header("취약성 정보")
135
136 vulnerabilities = data.get("vulnerability", {}).get("data", [])
137 if vulnerabilities:
138 print(f"{Fore.WHITE}발견된 취약성: {Fore.RED}{len(vulnerabilities)}개{Style.RESET_ALL}")
139 for vuln in vulnerabilities:
140 port = vuln.get("ports", {}).get("tcp", "N/A")
141 cve_id = vuln.get("cve_id", "N/A")
142 cvssv3_score = vuln.get("cvssv3_score", "N/A")
143
144 # CVSS 점수에 따른 색상 설정
145 score_color = Fore.GREEN
146 if cvssv3_score != "N/A":
147 score = float(cvssv3_score)
148 if score >= 7.0:
149 score_color = Fore.RED
150 elif score >= 4.0:
151 score_color = Fore.YELLOW
152
153 print(f"\n{Fore.CYAN}CVE ID: {Fore.WHITE}{cve_id}")
154 print_field(" 포트", port)
155 print_field(" CVSSv3 점수", f"{cvssv3_score}", score_color)
156 else:
157 print(f"{Fore.GREEN}취약성이 없습니다.{Style.RESET_ALL}")
158
159 def print_malicious_info(data):
160 """악성 정보 출력"""
161 print_header("악성 정보")
162
163 is_vpn = data.get("is_vpn", "N/A")
164 is_malicious = data.get("is_malicious", "N/A")
165
166 vpn_color = Fore.YELLOW if is_vpn else Fore.GREEN
167 malicious_color = Fore.RED if is_malicious else Fore.GREEN
168
169 print_field("VPN 사용 여부", str(is_vpn), vpn_color)
170 print_field("최근 악성 활동 여부", str(is_malicious), malicious_color)
171
172 def print_port_info(data):
173 """포트 정보 출력"""
174 print_header("개방 포트 정보")
175
176 open_ports = data.get("current_opened_port", {}).get("data", [])
177 if open_ports:
178 print(f"{Fore.WHITE}발견된 포트: {Fore.YELLOW}{len(open_ports)}개{Style.RESET_ALL}\n")
179 # 포트를 프로토콜별로 분류
180 common_ports = []
181 unknown_ports = []
182
183 for port_info in open_ports:
184 port = port_info.get("port", "N/A")
185 protocol = port_info.get("protocol", "None")
186
187 if protocol and protocol != "None":
188 common_ports.append((port, protocol))
189 else:
190 unknown_ports.append(port)
191
192 if common_ports:
193 print(f"{Fore.CYAN}일반 포트:{Style.RESET_ALL}")
194 for port, protocol in common_ports:
195 print(f"{Fore.WHITE} ∟ {Fore.GREEN}포트: {port}{Fore.WHITE}, 프로토콜: {protocol}{Style.RESET_ALL}")
196
197 if unknown_ports:
198 print(f"\n{Fore.CYAN}알 수 없는 포트:{Style.RESET_ALL}")
199 for port in unknown_ports:
200 print(f"{Fore.WHITE} ∟ {Fore.YELLOW}포트: {port}{Style.RESET_ALL}")
201 else:
202 print(f"{Fore.GREEN}개방된 포트가 없습니다.{Style.RESET_ALL}")
203
204 # 도메인 기본 정보 가져오기
205 def get_domain_summary(domain, api_key):
206 """도메인 기본 정보 조회"""
207 url = f"https://api.criminalip.io/v1/domain/summary?query={domain}"
208 headers = {"x-api-key": api_key}
209 response = requests.get(url, headers=headers)
210 response_data = response.json()
211
212 # 전체 응답 JSON 출력
213 print("Full Domain Summary JSON Response:", json.dumps(response_data, indent=4))
214 return response.json()
215
216 def print_domain_info(data):
217 """도메인 정보 출력"""
218 print_header("도메인 정보")
219
220 domain_data = data.get("data", {})
221
222 # 기본 정보 출력
223 registrar = domain_data.get("registrar", "N/A")
224 creation_date = domain_data.get("creation_date", "N/A")
225 expiration_date = domain_data.get("expiration_date", "N/A")
226 is_blacklisted = domain_data.get("is_blacklisted", False)
227
228 # 블랙리스트 상태에 따른 색상 설정
229 blacklist_color = Fore.RED if is_blacklisted else Fore.GREEN
230
231 print_field("등록 기관", registrar)
232 print_field("생성일", creation_date)
233 print_field("만료일", expiration_date)
234 print_field("블랙리스트 여부", str(is_blacklisted), blacklist_color)
235
236 # DNS 레코드 정보 출력
237 print_header("DNS 레코드")
238 dns_records = domain_data.get("dns_records", {})
239
240 if dns_records:
241 # A 레코드
242 a_records = dns_records.get("a", [])
243 if a_records:
244 print(f"\n{Fore.CYAN}A 레코드:{Style.RESET_ALL}")
245 for record in a_records:
246 print(f" ∟ {Fore.WHITE}{record}{Style.RESET_ALL}")
247
248 # MX 레코드
249 mx_records = dns_records.get("mx", [])
250 if mx_records:
251 print(f"\n{Fore.CYAN}MX 레코드:{Style.RESET_ALL}")
252 for record in mx_records:
253 print(f" ∟ {Fore.WHITE}{record}{Style.RESET_ALL}")
254
255 # NS 레코드
256 ns_records = dns_records.get("ns", [])
257 if ns_records:
258 print(f"\n{Fore.CYAN}NS 레코드:{Style.RESET_ALL}")
259 for record in ns_records:
260 print(f" ∟ {Fore.WHITE}{record}{Style.RESET_ALL}")
261 else:
262 print(f"{Fore.YELLOW}DNS 레코드를 찾을 수 없습니다.{Style.RESET_ALL}")
263
264 def main():
265 if len(sys.argv) < 2 or sys.argv[1] == '-h':
266 print(f"{Fore.CYAN}사용법:{Style.RESET_ALL}")
267 print(f" python script_name.py <command> [options]")
268 print("\n명령어:")
269 print(f" {Fore.YELLOW}init <api_key>{Style.RESET_ALL} - API 키를 초기화하고 저장합니다.")
270 print(f" {Fore.YELLOW}ip <ip_address> [options]{Style.RESET_ALL} - 지정된 IP 주소에 대한 정보를 분석합니다.")
271 print(f" {Fore.YELLOW}domain <domain_name>{Style.RESET_ALL} - 지정된 도메인에 대한 정보를 분석합니다.")
272 print("\nIP 분석 옵션:")
273 print(f" {Fore.YELLOW}-c{Style.RESET_ALL} - 취약성 정보 출력")
274 print(f" {Fore.YELLOW}-m{Style.RESET_ALL} - 악성 정보 출력")
275 print(f" {Fore.YELLOW}-p{Style.RESET_ALL} - 개방 포트 정보 출력")
276 print(f" {Fore.YELLOW}-a{Style.RESET_ALL} - 기본 정보, 취약성, 악성, 개방 포트 정보를 모두 출력")
277 print(f"\n예시:")
278 print(f" python script_name.py init <api_key>")
279 print(f" python script_name.py ip 1.1.1.1 -a")
280 print(f" python script_name.py domain example.com\n")
281 return
282
283 command = sys.argv[1]
284
285 if command == 'init':
286 if len(sys.argv) < 3:
287 print(f"{Fore.RED}Usage: python script_name.py init <api_key>{Style.RESET_ALL}")
288 return
289 api_key = sys.argv[2]
290 initialize_api_key(api_key)
291 return
292
293 elif command == 'ip':
294 if len(sys.argv) < 3:
295 print(f"{Fore.RED}Usage: python script_name.py ip <ip_address> [-c | -m | -p | -a | -cmp | -mpc | ...]{Style.RESET_ALL}")
296 return
297
298 # API 키 로드
299 api_key = load_api_key()
300 if not api_key:
301 print(f"{Fore.RED}[-] API key not found. Please run 'python script_name.py init <api_key>' first{Style.RESET_ALL}")
302 return
303
304 ip_address = sys.argv[2]
305 options = sys.argv[3] if len(sys.argv) > 3 else ""
306
307 print(f"\n{Fore.CYAN}[*] IP 주소 {Fore.WHITE}{ip_address}{Fore.CYAN} 분석 중...{Style.RESET_ALL}")
308
309 active_options = process_options(options)
310
311 if 'a' in options or not active_options:
312 basic_data = get_summary_data(ip_address, api_key)
313 print_basic_info(basic_data)
314
315 if active_options or 'a' in options:
316 data = get_malicious_data(ip_address, api_key)
317
318 for option in active_options:
319 if option == '-c':
320 print_vulnerability_info(data)
321 elif option == '-m':
322 print_malicious_info(data)
323 elif option == '-p':
324 print_port_info(data)
325
326 print(f"\n{Fore.CYAN}[*] 분석 완료{Style.RESET_ALL}\n")
327
328 elif command == 'domain':
329 if len(sys.argv) < 3:
330 print(f"{Fore.RED}Usage: python script_name.py domain <domain_name>{Style.RESET_ALL}")
331 return
332
333 # API 키 로드
334 api_key = load_api_key()
335 if not api_key:
336 print(f"{Fore.RED}[-] API key not found. Please run 'python script_name.py init <api_key>' first{Style.RESET_ALL}")
337 return
338
339 domain_name = sys.argv[2]
340 print(f"\n{Fore.CYAN}[*] 도메인 {Fore.WHITE}{domain_name}{Fore.CYAN} 분석 중...{Style.RESET_ALL}")
341
342 # 도메인 정보 조회 및 출력
343 domain_data = get_domain_summary(domain_name, api_key)
344 print_domain_info(domain_data)
345
346 print(f"\n{Fore.CYAN}[*] 분석 완료{Style.RESET_ALL}\n")
347
348 else:
349 print(f"{Fore.RED}Unknown command: {command}{Style.RESET_ALL}")
350 print("Available commands:")
351 print(" init <api_key> Initialize API key")
352 print(" ip <ip_address> [-c | -m | -p | -a | -cmp | -mpc | ...] Analyze IP address")
353 print(" domain <domain_name> Analyze domain")
354
355 if __name__ == "__main__":
356 main()