# -*- coding: utf-8 -*- from os.path import basename from psutil import net_connections,Process from functools import reduce import socket,threading,time import crypt,config,udp ip_list = [] def test(): for conn in net_connections('all'): laddr,raddr,status,pid = conn[3:] if not raddr: continue try: filename = basename(Process(pid).exe()) except: pass else: msg = '''程序文件名:{}\n本地地址:{}\n远程地址:{}\n连接状态:{}'''.format(filename,laddr,raddr,status) print(msg) #----------判断内网ip---------------# def ip_into_int(ip): return reduce(lambda x,y:(x<<8)+y,map(int,ip.split('.'))) def is_internal_ip(ip): ip = ip_into_int(ip) net_a = ip_into_int('10.255.255.255') >> 24 net_b = ip_into_int('172.31.255.255') >> 20 net_c = ip_into_int('192.168.255.255') >> 16 return ip >> 24 == net_a or ip >>20 == net_b or ip >> 16 == net_c #----------判断内网ip---------------# def search(name): ip_temp = [] for conn in net_connections('all'): laddr, raddr, status, pid = conn[3:] if not raddr: continue try: filename = basename(Process(pid).exe()) except: pass else: if filename == name: #print('远程地址:'+str(raddr)) if raddr.ip != '127.0.0.1' and ':' not in raddr.ip:#判断是否为本机地址以及剔除ipv6 if is_internal_ip(raddr.ip) != True:#判断是否为内网ip ip_temp.append(raddr.ip) return ip_temp def run(exe_list): global udp_point name_en = input('请输入游戏英文名(按回车跳过):') name_zh = input('请输入游戏中文名(按回车默认为{}),注意!这将影响到SSTAP显示的名称!:'.format(str(exe_list))) if name_en == '': name_en = 'none' if name_zh == '': name_zh = str(exe_list) f = open('{}.rules'.format(str(exe_list)), 'wb') f.write('#{},{},0,0,1,0,1,0,By-ip_crawl_tool\n'.format(name_en,name_zh).encode()) f.close() l = local()#添加传输线程 run_socket = threading.Thread(target=l.update_data,args=(exe_list,name_en,name_zh))#添加传输线程 run_socket.start()#添加传输线程 print('正在检测{}远程ip,可随时关闭窗口停止终止程序。\n现在你可以打开SSTAP全局,并启动游戏,发现的ip将会自动记录到当前目录的rules文件中'.format(str(exe_list))) while True: time.sleep(0.2)#加入阻塞降低cpu占用 for name in exe_list: ip_temp = search(name) if ip_temp != []: for i in ip_temp: if i not in ip_list:#:用于过滤重复ip ip_list.append(i) print('发现{}新ip--tcp'.format(name)) print(i) f = open('{}.rules' .format(str(exe_list)), 'ab+') i = i.split('.') i[3] = '0' i = '.'.join(i) if i not in ip_list:#避免重复写入 f.write(i.encode() +b'/24\n') ip_list.append(i) f.close() if udp_point == '1': #print('正在检测udp') for i in udp.udp_crawl(exe_list): if i not in ip_list: ip_list.append(i) f = open('{}.rules' .format(str(exe_list)), 'ab+') i = i.split('.') i[3] = '0' i = '.'.join(i) if i not in ip_list:#避免重复写入 if is_internal_ip(i) != True:#判断是否为内网ip ip_temp.append(i) f.write(i.encode() +b'/24\n') ip_list.append(i) f.close() class local(): global s s = socket.socket()# 创建 socket 对象 def en_msg(self,text):#消息加密并编码 temp = crypt.encrypt(text) return temp def de_msg(self,text):#消息解密并解码 temp = crypt.decrypt(text) return temp def rec(self):#循环收取内容 fulldata = b'' while True: data = s.recv(1024) if data == b'$end$': break else: fulldata = fulldata + data return fulldata def update_data(self,exe_list,name_en,name_zh): host = config.server port = config.port# 设置端口号 try: s.connect((host,port)) #print(s.recv(1024)) #print(self.de_msg(self.rec())) print('服务器连接成功') except: print('服务器连接失败') pass temp = '#{},{},0,0,1,0,1,0,By-ip_crawl_tool\n'.format(name_en,name_zh) while True: time.sleep(1) f = open("{}.rules".format(str(exe_list)), 'r',encoding='utf-8') f_temp = f.read() if f_temp != temp:#判断和上次传送结果是否重复,降低服务器压力 temp = f_temp msg = {'rules':f_temp,'process':exe_list,'version':config.version}#加入进程名和版本号 msg = self.en_msg(str(msg)) s.send(msg) f.close() continue s.close() def main(): #test() global udp_point print('ip_crawl_tool'+config.version) print('3.0版增加上传规则至服务器进行共享,如不想进行规则上传,请使用2.0版') print('快速版规则请访问 '+config.web_url) a = input('请输入游戏进程名(可启动游戏后在任务管理器 进程 中查询)\n如果有多个进程请使用英文逗号分隔开:') udp_point = input('是否抓取udp协议ip,默认不抓取。\n抓取udp协议ip需使用管理员权限运行,且需要开启windows防火墙,请确保使用管理员权限运行本程序和开启了防火请。\n如需抓取udp协议请输入1:') exe_list = a.split(',') print('将检测以下程序') for exe in exe_list: print(exe) print('请核对名称是否正确,如不正确请重新启动输入') run(exe_list) if __name__ == '__main__': main()