Writeup for 中国技能大赛决赛 2019

Crypto

垃圾比赛,才2道Crypto,就值个30分。

Crypto1 10pt

打开题目描述,看到是一段字符串,直接看到结尾,c666,内心甚至毫无波动,。

1
2
s = 'xxx'
print(bytes.fromhex(s[::-1]))

Crypto2 20pt

RSA.txt

n= 703739435902178622788120837062252491867056043804038443493374414926110815100242619
e= 59159
c= 449590107303744450592771521828486744432324538211104865947743276969382998354463377
m=???

n.bit_length()看了一下,才269bit,直接factor。

可惜没外网,用不了小网站,不过还好有sage,放后台几分钟就跑出来了。

1
2
3
factor(703739435902178622788120837062252491867056043804038443493374414926110815100242619)

# 782758164865345954251810941 * 810971978554706690040814093 * 1108609086364627583447802163

exp.py

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
from Crypto.Util.number import *

n= 703739435902178622788120837062252491867056043804038443493374414926110815100242619
e= 59159
c= 449590107303744450592771521828486744432324538211104865947743276969382998354463377

p = [782758164865345954251810941, 810971978554706690040814093, 1108609086364627583447802163
]
phi = (p[0] - 1) * (p[1] - 1) * (p[2] - 1)
d = inverse(e, phi)
m = pow(c, d, n)
print(long_to_bytes(m))
# b'flag{1e257b39a25c6a7c4d66e197}'

抢了2个一血,题目太简单了。。

Steg

Steg1 xxpt

拿到一个图片,用010打开,能看到output里面报错,说CRC Mismatch @ chunk[0],再去看看原图,发现图片的高度是有点不太对。

利用CRC32来计算正确的宽度和高度。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
import binascii
import struct

with open('XImg.png', 'rb') as f:
    data = f.read()
    for width in range(2048):
        for height in range(2048):
            guess = data[0xC:0xF+1] + struct.pack('>ii', width, height) + data[0x18:0x1C+1]
            crc = binascii.crc32(guess)
            if crc == 0x53D1578A:
                 print(f"width: {width:#06x}, height: {height:#06x}")

# width: 0x0400, height: 0x0271

修改对应位置的高度,然后保存。

本以为flag就会在图片的下面的,可是并没有。。

试着粗略地看了下图片的lsb,没有发现什么有用的信息。

后来队友说,用Stegsolver在某个通道里发现了一个二维码。好吧,毕竟垃圾比赛,题目也就只能是这些套路了。

不能上外网,手机也都上交了,还好之前有了解过一个命令行工具zbarimg可以离线解析二维码。把图片保存下来,然后zbarimg xxx.png就能得到flag

steg2 xxpt

拿到一个.exe文件,没敢运行,直接先010看一下,发现是个图片的base64

复制进浏览器url栏,回车得到一张刘大爷的图片:

再拖进010,发现末尾藏了一个压缩包。

复制hex数据,新建文件,Edit As: Hex,粘贴,保存,得到压缩包。

打开压缩包,发现有密码。试了下伪加密,并不是。

看来要爆破密码,不过这时习惯性地看了下前面那张图片的details

嗯,都是套路。

password is QwE12#,输入解压得到flag{06e9e74c449042d19e6ee3f6c04fed92}

Misc

Misc3 15pt

拿到一个.raw文件,看起来是个取证题,不过没管那么多,还是拖进010

搜索字符串flag{,直接看到

试着交了下,不对。

hex转成ascii,提交,正确!

这题目真垃圾。。。

Misc1 30pt

没外网,不太会流量包分析的题目。

(赛后复现)

流量分析题,wifi流量,wep加密,告诉我们密码是6666xxxx

掩码攻击,上网搜寻了一番,找了一个linux环境下的工具aircrack-ng

不太会写掩码爆破bb的命令行参数,直接先生成了一个字典,然后字典攻击。

1
2
3
with open('dic.txt', 'w') as f:
    for i in range(10000):
        f.write(f"6666{i:04d}\n")

所以flag应该就是flag{0566668912-f059-448f}

Misc2 30pt

(赛后复现)

题目要求从流量包里面找到黑客用的菜刀密码。

参考了下wireshark的基本使用及分析流量包的技巧

里面有讲到:

同样试着先http.request.method == POST过滤。

按上面那题的思路,菜刀密码应该就是cmd,可是这一题跟上面那一题有一个区别就是这边多了一个strrev

比赛的时候,我交过flag{cmd},并不对。

所以flag到底是什么??

Reverse

Re2 30pt

一道迷宫题,输入key,走出去就输出Good!,走错了就error!flagkey的md5值。 要过两道check,两道check基本上是一样的,唯一的区别就是check1要保证18步走出去,而check2则没有步数限制。

迷宫如下:

201111111100000000000000000011111
101111111101111111111011110011111
101111111101111111111011110011111
100000000000000500000100000000011
111111110101111011111111111111111
111100001101111000000000000000000
111100101000000111111111111111112

5是出发点,只能走0,要走到2。

'w': 上
'.': 下
'0': 左
'm': 右

这题就很沙雕,没说必须两次要走不同的出口,导致有多解。

check1限制了18步,那只能左上出去。 14左+3上+1左:'0'*14 + 'w'*3 + '0' == '00000000000000www0'

一开始,我觉得check2直接按照check1的走法完全没问题。 也就是:00000000000000www000000000000000www0

flag,显示不对。。

找来主办方,主办方说这题是有点坑,然后又提示我后半部分有问题。

嗯,那看来check2只能从右下出去了。 2下+17右+1下: '.'*2 + 'm'*17 + '.' == ..mmmmmmmmmmmmmmmmm.

那么key = 00000000000000www0..mmmmmmmmmmmmmmmmm.

转成md5

1
2
3
4
5
import hashlib

print(hashlib.md5(b'00000000000000www0..mmmmmmmmmmmmmmmmm.').hexdigest())

# flag{d8ec55f877596b311117434cfc9e0cff}

交了flag,终于对了。。又拿了个一血,不过并没有什么加成。。

Re1 30pt

先要脱个upx的壳。

没怎么打过逆向,不会脱壳,又没外网,现场学都学不了。。 tcl…

(赛后复现)

upx壳,原理先暂时缓一缓,找个工具脱了再说。

上网搜寻了一波,找到了一个UPX Easy GUI,直接脱。

脱完就很简单了。


输入长度不超过27,过一个check。

input经过一通替换后变为tfoQ5ckkwhX51HYpxAjkMQYTAp5

  1. diff = input[i] - key[i]
  2. output[i] = table[diff % 4][diff]

大致流程可以看[源代码]。(https://www.cnblogs.com/QKSword/p/9095242.html)

exp.py

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
table = [
    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",
    "+/abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ",
    "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/",
    "0123456789+/ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
]
key = "QASWZXDECVFRBNGTHYJUMKIOLP"
output = "tfoQ5ckkwhX51HYpxAjkMQYTAp5"

for k, out in enumerate(output):
    for i in range(4):
        index = table[i].index(out)
        if index % 4 == i:
            add = ord(key[k]) + index
            if 33 <= add <=126:
                print(chr(add), end='')
    print()

md,又是一道多解。

flag{this_is_a_easy_suanfa}

PWN

三道堆题,dnm

Web

队友说三道题全都是第五空间的原题。。

垃圾比赛。

下午AWD

完全不会。。

手动尝试用初始密码登录别的靶机,找到了3台。。迅速改了密码。

然后每回合手动交flag。。

Summary

Web相关的等有时间要去学一手了。

AWD也要好好搞一下了。

Load Comments?