mirror of
git://git.acid.vegas/IRCP.git
synced 2024-11-22 16:06:41 +00:00
Added multi-logs & memory management has been improved for performance
This commit is contained in:
parent
cfa0e3c2bb
commit
751b28eac5
20
README.md
20
README.md
@ -24,15 +24,17 @@ The IRC networks we scanned are PUBLIC networks...any person can freely connect
|
|||||||
|
|
||||||
## Config
|
## Config
|
||||||
###### Settings
|
###### Settings
|
||||||
| Setting | Default Value | Description |
|
| Setting | Default Value | Description |
|
||||||
| ---------- | ------------------------------ | ------------------------------------------ |
|
| ------------- | ------------------------------ | ----------------------------------------------------- |
|
||||||
| `errors` | `False` | Show errors in console |
|
| `errors` | `True` | Show errors in console |
|
||||||
| `nickname` | `"IRCP"` | IRC nickname *(`None` = random)* |
|
| `errors_conn` | `False` | Show connection errors in console |
|
||||||
| `username` | `"ircp"` | IRC username *(`None` = random)* |
|
| `log_max` | `5000000` | Maximum log size *(in bytes)* before starting another |
|
||||||
| `realname` | `"internetrelaychat.org"` | IRC realname *(`None` = random)* |
|
| `nickname` | `"IRCP"` | IRC nickname *(`None` = random)* |
|
||||||
| `ns_mail` | `"scan@internetrelaychat.org"` | NickServ email address *(`None` = random)* |
|
| `username` | `"ircp"` | IRC username *(`None` = random)* |
|
||||||
| `ns_pass` | `"changeme"` | NickServ password *(None = random)* |
|
| `realname` | `"internetrelaychat.org"` | IRC realname *(`None` = random)* |
|
||||||
| `vhost` | `None` | Bind to a specific IP address |
|
| `ns_mail` | `"scan@internetrelaychat.org"` | NickServ email address *(`None` = random)* |
|
||||||
|
| `ns_pass` | `"changeme"` | NickServ password *(None = random)* |
|
||||||
|
| `vhost` | `None` | Bind to a specific IP address |
|
||||||
|
|
||||||
###### Throttle
|
###### Throttle
|
||||||
| Setting | Default Value | Description |
|
| Setting | Default Value | Description |
|
||||||
|
63
ircp.py
63
ircp.py
@ -11,13 +11,15 @@ import sys
|
|||||||
import time
|
import time
|
||||||
|
|
||||||
class settings:
|
class settings:
|
||||||
errors = True # Show errors in console
|
errors = True # Show errors in console
|
||||||
nickname = 'IRCP' # None = random
|
errors_conn = False # Show connection errors in console
|
||||||
username = 'ircp' # None = random
|
log_max = 5000000 # Maximum log size (in bytes) before starting another
|
||||||
realname = 'scan@internetrelaychat.org' # None = random
|
nickname = 'IRCP' # None = random
|
||||||
ns_mail = 'scan@internetrelaychat.org' # None = random@random.[com|net|org]
|
username = 'ircp' # None = random
|
||||||
ns_pass = 'changeme' # None = random
|
realname = 'scan@internetrelaychat.org' # None = random
|
||||||
vhost = None # Bind to a specific IP address
|
ns_mail = 'scan@internetrelaychat.org' # None = random@random.[com|net|org]
|
||||||
|
ns_pass = 'changeme' # None = random
|
||||||
|
vhost = None # Bind to a specific IP address
|
||||||
|
|
||||||
class throttle:
|
class throttle:
|
||||||
channels = 3 # Maximum number of channels to scan at once
|
channels = 3 # Maximum number of channels to scan at once
|
||||||
@ -137,7 +139,8 @@ class probe:
|
|||||||
self.display = server.ljust(18)+' | '
|
self.display = server.ljust(18)+' | '
|
||||||
self.semaphore = semaphore
|
self.semaphore = semaphore
|
||||||
self.nickname = None
|
self.nickname = None
|
||||||
self.snapshot = copy.deepcopy(snapshot) # <--- GET FUCKED PYTHON
|
self.snapshot = {'raw':list()}
|
||||||
|
self.multi = ''
|
||||||
self.channels = {'all':list(), 'current':list(), 'users':dict()}
|
self.channels = {'all':list(), 'current':list(), 'users':dict()}
|
||||||
self.nicks = {'all':list(), 'check':list()}
|
self.nicks = {'all':list(), 'check':list()}
|
||||||
self.loops = {'init':None,'chan':None,'nick':None,'whois':None}
|
self.loops = {'init':None,'chan':None,'nick':None,'whois':None}
|
||||||
@ -150,11 +153,13 @@ class probe:
|
|||||||
try:
|
try:
|
||||||
await self.connect()
|
await self.connect()
|
||||||
except Exception as ex:
|
except Exception as ex:
|
||||||
error(self.display + 'failed to connect using SSL/TLS', ex)
|
if settings.error_conn:
|
||||||
|
error(self.display + 'failed to connect using SSL/TLS', ex)
|
||||||
try:
|
try:
|
||||||
await self.connect(True)
|
await self.connect(True)
|
||||||
except Exception as ex:
|
except Exception as ex:
|
||||||
error(self.display + 'failed to connect', ex)
|
if settings.error_conn:
|
||||||
|
error(self.display + 'failed to connect', ex)
|
||||||
|
|
||||||
async def raw(self, data):
|
async def raw(self, data):
|
||||||
self.writer.write(data[:510].encode('utf-8') + b'\r\n')
|
self.writer.write(data[:510].encode('utf-8') + b'\r\n')
|
||||||
@ -176,17 +181,17 @@ class probe:
|
|||||||
}
|
}
|
||||||
self.nickname = identity['nick']
|
self.nickname = identity['nick']
|
||||||
self.reader, self.writer = await asyncio.wait_for(asyncio.open_connection(**options), throttle.timeout)
|
self.reader, self.writer = await asyncio.wait_for(asyncio.open_connection(**options), throttle.timeout)
|
||||||
|
del options
|
||||||
if not fallback:
|
if not fallback:
|
||||||
self.snapshot['ssl'] = True
|
self.snapshot['ssl'] = True
|
||||||
await self.raw('USER {0} 0 * :{1}'.format(identity['user'], identity['real']))
|
await self.raw('USER {0} 0 * :{1}'.format(identity['user'], identity['real']))
|
||||||
await self.raw('NICK ' + identity['nick'])
|
await self.raw('NICK ' + identity['nick'])
|
||||||
|
del identity
|
||||||
await self.listen()
|
await self.listen()
|
||||||
for item in self.loops:
|
for item in self.loops:
|
||||||
if self.loops[item]:
|
if self.loops[item]:
|
||||||
self.loops[item].cancel()
|
self.loops[item].cancel()
|
||||||
for item in [rm for rm in self.snapshot if not self.snapshot[rm]]:
|
with open(f'logs/{self.server}.json{self.multi}', 'w') as fp:
|
||||||
del self.snapshot[item]
|
|
||||||
with open(f'logs/{self.server}.json', 'w') as fp:
|
|
||||||
json.dump(self.snapshot, fp)
|
json.dump(self.snapshot, fp)
|
||||||
debug(self.display + 'finished scanning')
|
debug(self.display + 'finished scanning')
|
||||||
|
|
||||||
@ -204,6 +209,7 @@ class probe:
|
|||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
await asyncio.sleep(1.5)
|
await asyncio.sleep(1.5)
|
||||||
|
del login
|
||||||
if not self.channels['all']:
|
if not self.channels['all']:
|
||||||
error(self.display + 'no channels found')
|
error(self.display + 'no channels found')
|
||||||
await self.raw('QUIT')
|
await self.raw('QUIT')
|
||||||
@ -217,8 +223,8 @@ class probe:
|
|||||||
while self.channels['all']:
|
while self.channels['all']:
|
||||||
while len(self.channels['current']) >= throttle.channels:
|
while len(self.channels['current']) >= throttle.channels:
|
||||||
await asyncio.sleep(1)
|
await asyncio.sleep(1)
|
||||||
chan = random.choice(self.channels['all'])
|
|
||||||
await asyncio.sleep(self.jthrottle)
|
await asyncio.sleep(self.jthrottle)
|
||||||
|
chan = random.choice(self.channels['all'])
|
||||||
self.channels['all'].remove(chan)
|
self.channels['all'].remove(chan)
|
||||||
try:
|
try:
|
||||||
await self.raw('JOIN ' + chan)
|
await self.raw('JOIN ' + chan)
|
||||||
@ -228,6 +234,7 @@ class probe:
|
|||||||
while self.nicks['check']:
|
while self.nicks['check']:
|
||||||
await asyncio.sleep(1)
|
await asyncio.sleep(1)
|
||||||
self.loops['whois'].cancel()
|
self.loops['whois'].cancel()
|
||||||
|
del self.loops['whois']
|
||||||
await self.raw('QUIT')
|
await self.raw('QUIT')
|
||||||
except asyncio.CancelledError:
|
except asyncio.CancelledError:
|
||||||
pass
|
pass
|
||||||
@ -257,6 +264,7 @@ class probe:
|
|||||||
except:
|
except:
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
|
del nick
|
||||||
await asyncio.sleep(throttle.whois)
|
await asyncio.sleep(throttle.whois)
|
||||||
else:
|
else:
|
||||||
await asyncio.sleep(1)
|
await asyncio.sleep(1)
|
||||||
@ -275,8 +283,13 @@ class probe:
|
|||||||
args = line.split()
|
args = line.split()
|
||||||
numeric = args[1]
|
numeric = args[1]
|
||||||
#debug(line)
|
#debug(line)
|
||||||
if numeric in self.snapshot:
|
if sys.getsizeof(self.snapshot) >= settings.log_max:
|
||||||
if not self.snapshot[numeric]:
|
with open(f'logs/{self.server}.json{self.multi}', 'w') as fp:
|
||||||
|
json.dump(self.snapshot, fp)
|
||||||
|
self.snapshot = {'raw':list()}
|
||||||
|
self.multi = '.1' if not self.multi else '.' + str(int(self.multi[1:])+1)
|
||||||
|
if numeric in snapshot:
|
||||||
|
if numeric not in self.snapshot:
|
||||||
self.snapshot[numeric] = line
|
self.snapshot[numeric] = line
|
||||||
elif line not in self.snapshot[numeric]:
|
elif line not in self.snapshot[numeric]:
|
||||||
if type(self.snapshot[numeric]) == list:
|
if type(self.snapshot[numeric]) == list:
|
||||||
@ -308,13 +321,15 @@ class probe:
|
|||||||
self.display = f'{self.server.ljust(18)} | {host.ljust(25)} | '
|
self.display = f'{self.server.ljust(18)} | {host.ljust(25)} | '
|
||||||
debug(self.display + 'connected')
|
debug(self.display + 'connected')
|
||||||
self.loops['init'] = asyncio.create_task(self.loop_initial())
|
self.loops['init'] = asyncio.create_task(self.loop_initial())
|
||||||
elif numeric == '322' and len(args) >= 5: # RPL_LIST
|
elif numeric == '322' and len(args) >= 4: # RPL_LIST
|
||||||
chan = args[3]
|
chan = args[3]
|
||||||
users = args[4]
|
|
||||||
self.channels['all'].append(chan)
|
self.channels['all'].append(chan)
|
||||||
self.channels['users'][chan] = users
|
if len(args) >= 5:
|
||||||
|
users = args[4]
|
||||||
|
self.channels['users'][chan] = users
|
||||||
elif numeric == '323': # RPL_LISTEND
|
elif numeric == '323': # RPL_LISTEND
|
||||||
if self.channels['all']:
|
if self.channels['all']:
|
||||||
|
del self.loops['init']
|
||||||
debug(self.display + 'found {0} channel(s)'.format(str(len(self.channels['all']))))
|
debug(self.display + 'found {0} channel(s)'.format(str(len(self.channels['all']))))
|
||||||
self.loops['chan'] = asyncio.create_task(self.loop_channels())
|
self.loops['chan'] = asyncio.create_task(self.loop_channels())
|
||||||
self.loops['nick'] = asyncio.create_task(self.loop_nick())
|
self.loops['nick'] = asyncio.create_task(self.loop_nick())
|
||||||
@ -329,6 +344,7 @@ class probe:
|
|||||||
self.channels['current'].append(chan)
|
self.channels['current'].append(chan)
|
||||||
if chan in self.channels['users']:
|
if chan in self.channels['users']:
|
||||||
debug('{0}scanning {1} users in {2}'.format(self.display, self.channels['users'][chan].ljust(4), chan))
|
debug('{0}scanning {1} users in {2}'.format(self.display, self.channels['users'][chan].ljust(4), chan))
|
||||||
|
del self.channels['users'][chan]
|
||||||
else:
|
else:
|
||||||
debug(f'{self.display}scanning users in {chan}')
|
debug(f'{self.display}scanning users in {chan}')
|
||||||
await self.raw('WHO ' + chan)
|
await self.raw('WHO ' + chan)
|
||||||
@ -406,17 +422,18 @@ else:
|
|||||||
if not os.path.isfile(targets_file):
|
if not os.path.isfile(targets_file):
|
||||||
raise SystemExit('error: invalid file path')
|
raise SystemExit('error: invalid file path')
|
||||||
else:
|
else:
|
||||||
|
try:
|
||||||
|
os.mkdir('logs')
|
||||||
|
except FileExistsError:
|
||||||
|
pass
|
||||||
targets = [line.rstrip() for line in open(targets_file).readlines() if line and line not in donotscan]
|
targets = [line.rstrip() for line in open(targets_file).readlines() if line and line not in donotscan]
|
||||||
found = len(targets)
|
found = len(targets)
|
||||||
debug(f'loaded {found:,} targets')
|
debug(f'loaded {found:,} targets')
|
||||||
targets = [target for target in targets if not os.path.isfile(f'logs/{target}.json')] # Do not scan targets we already have logged for
|
targets = [target for target in targets if not os.path.isfile(f'logs/{target}.json')] # Do not scan targets we already have logged for
|
||||||
if len(targets) < found:
|
if len(targets) < found:
|
||||||
debug(f'removed {found-len(targets):,} targets we already have logs for already')
|
debug(f'removed {found-len(targets):,} targets we already have logs for already')
|
||||||
|
del found, targets_file
|
||||||
random.shuffle(targets)
|
random.shuffle(targets)
|
||||||
try:
|
|
||||||
os.mkdir('logs')
|
|
||||||
except FileExistsError:
|
|
||||||
pass
|
|
||||||
loop = asyncio.get_event_loop()
|
loop = asyncio.get_event_loop()
|
||||||
loop.run_until_complete(main(targets))
|
loop.run_until_complete(main(targets))
|
||||||
debug('IRCP has finished probing!')
|
debug('IRCP has finished probing!')
|
Loading…
Reference in New Issue
Block a user