题目简述
用浏览器访问,发现是这样,结合题目给的附件,应该是要发送json数据来得到flag:
![](/images/ctfjson1.JPG)
思路过程
查看附件,发现给出了/register,/login,/flag等地址,判断是要我们注册用户,登录后用get请求得到flag,使用postman发送json数据,方便快捷。先试了一下附件给出的账号,注册发现用户已存在,而且登录密码也不正确,所以需要自己注册一个用户:
![](/images/ctfjson1.JPG)
![](/images/ctfjson2.JPG)
![](/images/ctfjson3.JPG)
注册和登录都返回ok,但是获取flag时返回了一个假flag,并提示我们不是admin,根据题目cookie,判断问题出在cookie上,查看cookie发现有一个token,内容如下:
token=eyJ1c2VybmFtZSI6ICJodXN0bGVyIiwgInBhc3N3b3JkIjogIjEyMzQ1NiIsICJyb2xlIjogInVzZXIifQ==
看着末尾的两个大等号,说明这有可能时base64,进行base64解码后的数据是这样的:
{"username": "hustler", "password": "123456", "role": "user"}
显然,我们将role的值改为admin,即:
{"username": "hustler", "password": "123456", "role": "admin"}
再将这串数据用base64编码,得到修改后的token
Read More
题目概述
![](/images/ezup1.JPG)
一道经典的文件上传,看到这个思路马上就来了,就是上传一个php一句话木马,然后用蚁剑回连
初步尝试
我们先抓个包看看,这里有一个小插曲,就是如果我用127.0.0.1这个环回地址来访问,burp是抓不到包的,用局域网中的ip加端口号来访问就可以抓到包,配置好burp和浏览器的代理,先任意上传一个文件,得到如下提示:
![](/images/ezup2.JPG)
抓包并修改文件后缀为png发现能够上传,说明这是一个前端验证,很好绕过
我们再次尝试,这次传一个符合要求的文件:
![](/images/ezup3.JPG)
![](/images/ezup4.JPG)
发现上传成功,并返回了一个地址,但是直接访问这个地址会返回404,根据抓包结果以及题目的hint,猜想正确地址应该只有upload以及后面的url,尝试发现可以访问。
那么,我们是不是只要通过抓包修改后缀绕过前端,就可以上传php木马了呢?
进一步尝试
首先我们先构造一个一句话木马,使用文本编辑器编写,完成后将后缀改为png,下面附上一句话木马的基本知识:
什么是一句话木马
一句话木马就是只需要一行代码的木马,短短一行代码,就能做到和大马相当的功能。为了绕过waf的检测,一句话木马出现了无数中变形,但本质是不变的:木马的函数执行了我们发送的命令。
我们如何发送命令,发送的命令如何执行?
我们可以通过GET 、POST 、COOKIE这三种方式向一个网站提交数据,一句话木马用$_GET[‘ ‘]、$_POST[‘ ‘]、$_COOKIE[‘ ‘] 接收我们传递的数据,并把接收的数据传递给一句话木马中执行命令的函数,进而执行命令。
所以看到的经典一句话木马大多都是只有两个部分,一个是可以执行代码的函数部分,一个是接收数据的部分。
Read More
题目概述
题目给了一个pyc文件,我们尝试在线反编译后获得源文件:
import base64
from string import *
str1 = 'yD9oB3Inv3YAB19YynIuJnUaAGB0um0='
string1 = 'ZYXWVUTSRQPONMLKJIHGFEDCBAzyxwvutsrqponmlkjihgfedcba0123456789+/'
string2 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
flag = input('welcome to moectf\ninput your flag and I wiil check it:')
enc_flag = base64.b64encode(flag.encode()).decode()
enc_flag = enc_flag.translate(str.maketrans(string2, string1))
if enc_flag == str1:
print('good job!!!!')
else:
print('something wrong???')
exit(0)
分析加密
审计程序逻辑发现,程序的具体逻辑是,我们输入一个字符串,然后程序对这个字符串进行base64编码,然后通过某个映射加密这组字符串,然后将这组字符串和str1对比,如果相同即为flag,所以str1这个变量即是加密后的flag,我们需要对str1进行逆向。
我们要反向映射str1这个字符串,查找发现,maketrans函数的作用是创建一个将string1用string2替换的映射表,而maketrans就是使用这个映射表处理字符串。那么转念一想,我们反向映射,只要将函数中string1和string2的位置交换,创建一个将string2用string1来替换的映射表,再用这个新的映射表来处理str1,不就反映射成功了吗?
编写POC
说干就干,修改了以下题目的py脚本,反向映射str1,脚本如下:
import base64
from string import *
str1 = 'yD9oB3Inv3YAB19YynIuJnUaAGB0um0='
string1 = 'ZYXWVUTSRQPONMLKJIHGFEDCBAzyxwvutsrqponmlkjihgfedcba0123456789+/'
string2 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
f=str1.translate(str.maketrans(string1,string2))
print(f)
运行得到反映射结果:
![](/images/repy1.JPG)
再使用base64解码,得到flag:
![](/images/repyflag.JPG)
踩坑总结
Read More
题目简述
![](/images/dgutctfuni1.JPG)
大致就是一个“买”unicorn的商店,尝试购买,发现价格处只能填写一个字符,并且最后一个商品要1337四位数的价格,显然,题目要求我们使用一个字符来购买这个四位数价格的商品
思路简析
我们先什么都不输入,尝试寻找报错:
![](/images/dgctfuni2.JPG)
发现需要输入一个只占一个字符的unicode字符,那么有没有只占一个字符,但又能表示1337以上的数字的unicode字符呢?找到这样一个网站:https://www.compart.com/en/unicode 查到这个数值表示10000的字符:
![](/images/dgctfuni3.png)
由于提交要使用url编码,所以把0xE1 0x8D 0xBC换成%E1%8D%BC即可
拿flag
![](/images/dgctfflag1.JPG)
![](/images/dgctfflag2.JPG)
得到flag
反思总结
1.有时候会遇到一些很刁钻的知识点,不懂真的做不出来
Read More
题目简述
![](/images/dgctfserial1.JPG)
审计代码,题目大意是让我们将username变为admin就会给flag
思路过程
我们需要传入参数,但是遇到这种改怎么传参呢?我们注意到源代码有if($_GET['user'])
这样一段,这样的代码就是php获取网址后的参数的,比方这里就是获取user的值,那么我们传参时就可以写?user=需要传入的数据
这种结构是可以直接写在网址后面的。
知道了如何传参,那我们要传入什么数据呢?我们注意到,题目里有一个unserialize()
函数,这就是反序列化函数,那什么是序列和反序列呢?以下摘录网络的解释:
php程序为了保存和转储对象,提供了序列化的方法。php序列化是为了在程序运行的过程中对对象进行转储而产生的。序列化可以将对象转换成字符串,但仅保留对象里的成员变量,不保留函数方法。
php序列化的函数为serialize,可以将对象中的成员变量转换成字符串。
反序列化的函数为unserilize,可以将serialize生成的字符串重新还原为对象中的成员变量。
将用户可控的数据进行了反序列化,就是PHP反序列化漏洞。
序列化
序列化的目的是方便数据的传输和存储。
在PHP应用中,序列化和反序列化一般用作缓存,比如session缓存,cookie等。
Read More
题目简述
![](/images/http1.JPG)
满足题目的5点要求即可得到flag
使用Postman
要满足这些要求,有一个十分好用的工具叫postman,它是一个浏览器插件,也有exe的版本,这里我选用了exe版本的postman
使用post请求
直接修改postman的设置,如图:
![](/images/httppost.JPG)
满足use parameter: UwU=u
在postman的params一栏里设置,也可以直接在网站后面加:
![](/iamges/httpparam.JPG)
满足post form: Luv=u
这里要求post from-data格式或者x-www-from-urlencoded格式的数据,并且满足Luv=u,如图:
Read More
设计思路
灵感来源于watch dogs里面的黑客无人机,以树莓派+pixhawk为主体,搭载大疆F450机架,配以2000毫安锂电池,可以凭借pixhawk出色的飞控能力,以及树莓派优秀的运算能力,在空中完成近源渗透,人脸识别,数据转发(星链),无人机送货等多项功能。
注意:建议先给pixhawk和树莓派刷入固件,调试好各项参数(根据情况可以无线调试,建议先调试完可以无线调试的项目),再组装飞机(gps,电机电调调试必须先组装好飞机),不一定要按照文章顺序来做
材料准备
大概要这些
![](/images/dronemt1.jpg)
F450机架(动力套装)
如果懂得焊接可以更自由的购买电机电调来组装,不懂焊接的建议直接咸鱼(淘宝上很少或者没有组装好的)买F450的动力套装,因为动力套装插上飞控就可以操作,不需焊接,购买前请注意是否真的不需要焊接。
![](/images/djijia1.jpg)
![](/images/djijia2.jpg)
减震板
Read More
题目简述
![](/images/webxxe1.PNG)
![](/images/webxxe2.PNG)
题目给出了一个网站,点击左侧相应的汽车名字就会出现相应的图片和数据。一看没什么问题,那么我们就上burp,给浏览器设置代理,访问192.168.1.101,为什么不是127.0.0.1呢?因为访问这个回环地址burp抓不到包,原因未知但可以使用就好了。
![](/images/webxxecap1.PNG)
观察发现,当我们点击左侧汽车名字的时候,实际上我们是post了相应的请求,抓包修改相应位置的汽车名后发现会跳转到不同的汽车页面。思路这就来了:如果我们post一些其他的东西上去,是否会有突破口?
尝试突破
首先,我先post了一个不存在的汽车名称:
![](/images/webxxefake1.PNG)
得到这样一个结果:
Read More
题目简述
![](/images/pwnfd1.PNG)
![](/images/pwnfd2.PNG)
![](/images/pwnfd3.PNG)
大概是要我们输入一个叫fd的东西来读取文件,也就是只要我们输入正确的fd就可以得到flag,那什么是fd呢?
FD,即“文件描述符”,以下是摘录于知乎的简述:
fd是什么?
fd是File descriptor的缩写,中文名叫做:文件描述符。文件描述符是一个非负整数,本质上是一个索引值(这句话非常重要)。
什么时候拿到的fd?
当打开一个文件时,内核向进程返回一个文件描述符( open
系统调用得到 ),后续 read
、write
这个文件时,则只需要用这个文件描述符来标识该文件,将其作为参数传入 read
、write
。
fd 的值范围是什么?
在 POSIX 语义中,0,1,2 这三个 fd 值已经被赋予特殊含义,分别是标准输入( STDIN_FILENO ),标准输出( STDOUT_FILENO ),标准错误( STDERR_FILENO )。
文件描述符是有一个范围的:0 ~ OPEN_MAX-1 ,最早期的 UNIX 系统中范围很小,现在的主流系统单就这个值来说,变化范围是几乎不受限制的,只受到系统硬件配置和系统管理员配置的约束。
Read More
题目概述
![](/images/pwnlook1.PNG)
![](/images/pwnlook2.PNG)
大概就是要我们写一个程序来和这个二进制程序交互,还要使用到pwntools这个工具。
上网搜索了一下,pwntools是python的一个库,支持python3 使用pip安装:
apt-get update
apt-get install python3 python3-pip python3-dev git libssl-dev libffi-dev build-essential
python3 -m pip install --upgrade pip
python3 -m pip install --upgrade pwntools
python3 -m pip install pwntools -i https://pypi.tuna.tsinghua.edu.cn/simple/
稍微了解了一下pwntools的用法,基本够用:
send(data)
sendline(data)
recv(numb=4096, timeout=default)
recvuntil("hello,world\n", drop=False)
recvline(keepends=True)
recvall()
recvrepeat(timeout=default)
interactive()
编写POC
from pwn import *
r = remote("192.168.36.1","63551")
i = 0
t = 0
times = 0
win = "BlackBird"
lose = "WingS"
context.log_level="debug"
while t < 7:
welcome = r.recvline()
t = t + 1
while times < 102:
i = 0
while i < 3:
line = r.recvline(keepends=False)
mystr = line.decode("utf-8")
print(mystr)
if i == 2:
x = mystr.split("+")
a = int(x[0])
d = x[1]
e = d.split("=")
b = int(e[0])
c = int(e[1])
con = a + b
if con == c:
r.sendline(win.encode("utf-8"))
elif con != c:
r.sendline(lose.encode("utf-8"))
i = i + 1
times = times + 1
Read More