强网杯2022 谍影重重 writeup

前半段y老师撸的,我简单弄了下后半段,当然还有或或👴帮我补全了一下脚本,我直接猪脑过载太菜了,看了眼其他选手的wp,都没发解析部分,vmess这个协议确实不是很适合公开发表,这里就直接贴y老师的脚本,牛逼,吹爆

时间戳

爆破获得时间戳

package main

import (
"bytes"
"crypto/hmac"
"crypto/md5"
"encoding/binary"
"encoding/hex"
"errors"
"fmt"
"os"
"strings"

"github.com/jarvisgally/v2simple/common"
)

func StrToUUID(s string) (uuid [16]byte, err error) {
b := []byte(strings.Replace(s, "-", "", -1))
if len(b) != 32 {
return uuid, errors.New("invalid UUID: " + s)
}
_, err = hex.Decode(uuid[:], b)
return
}

func main() {
auth := make([]byte, 16)
file, err := os.Open("./data.bin")
if err != nil {
panic(err)
}
defer file.Close()
_, err = file.Read(auth)
if err != nil {
panic(err)
}
uuidStr := "b831381d-6324-4d53-ad4f-8cda48b30811"

uuid, err := StrToUUID(uuidStr)

if err != nil {
panic(err)
}

ts := common.GetBuffer(8)
defer common.PutBuffer(ts)

hasher := hmac.New(md5.New, uuid[:])

time := uint64(1615528962)

delta := uint64(0)

for {
fmt.Printf("%d\n", delta)
t := time + delta
binary.BigEndian.PutUint64(ts, t)

hasher.Write(ts)

if bytes.Equal(hasher.Sum(nil), auth) {
fmt.Printf("%v\n", t)
break
}

hasher.Reset()

t = time - delta
binary.BigEndian.PutUint64(ts, t)

hasher.Write(ts)

if bytes.Equal(hasher.Sum(nil), auth) {
fmt.Printf("%v\n", t)
break
}

hasher.Reset()

delta++
}
}

解包服务器返回

package main

import (
"context"
"fmt"

"github.com/v2fly/v2ray-core/v5/common/net"
"github.com/v2fly/v2ray-core/v5/common/protocol"
"github.com/v2fly/v2ray-core/v5/proxy/vmess/encoding"
)

func main() {
rc, _ := net.Dial("tcp", "127.0.0.1:8443")
defer rc.Close()
reqHeader := &protocol.RequestHeader{
Version:  encoding.Version,
Command:  protocol.RequestCommandTCP,
Security: protocol.SecurityType_AES128_GCM,
Option:   13,
Port:     5000,
Address:  net.ParseAddress("127.0.0.1"),
}
session := encoding.NewClientSession(context.TODO(), false, protocol.DefaultIDHash, 0)
header, err := session.DecodeResponseHeader(rc)
if err != nil {
panic(err)
}
fmt.Printf("%+v\n", header)
reader, err := session.DecodeResponseBody(reqHeader, rc)
if err != nil {
panic(err)
}
mb, err := reader.ReadMultiBuffer()
if err != nil {
panic(err)
}
fmt.Println("Len:", mb.Len())
fmt.Printf("%+v\n", mb.String())
}

去源码里改两个参数

func NewClientSession(ctx context.Context, isAEAD bool, idHash protocol.IDHash, behaviorSeed int64) *ClientSession {
session := &ClientSession{
isAEAD: isAEAD,
idHash: idHash,
}

randomBytes := make([]byte, 33) // 16 + 16 + 1
common.Must2(rand.Read(randomBytes))
copy(session.requestBodyKey[:], []uint8{94, 74, 154, 169, 186, 88, 199, 227, 173, 54, 254, 36, 153, 220, 162, 89})
copy(session.requestBodyIV[:], []uint8{19, 39, 127, 87, 50, 218, 82, 173, 167, 144, 216, 123, 136, 41, 218, 169})
session.responseHeader = byte(0xa2)

if !session.isAEAD {
session.responseBodyKey = md5.Sum(session.requestBodyKey[:])
session.responseBodyIV = md5.Sum(session.requestBodyIV[:])
} else {
BodyKey := sha256.Sum256(session.requestBodyKey[:])
copy(session.responseBodyKey[:], BodyKey[:16])
BodyIV := sha256.Sum256(session.requestBodyIV[:])
copy(session.responseBodyIV[:], BodyIV[:16])
}
{
var err error
session.readDrainer, err = drain.NewBehaviorSeedLimitedDrainer(behaviorSeed, 18, 3266, 64)
if err != nil {
newError("unable to initialize drainer").Base(err).WriteToLog()
session.readDrainer = drain.NewNopDrainer()
}
}

return session
}

还有这个

func (r *AuthenticationReader) ReadMultiBuffer() (buf.MultiBuffer, error) {
const readSize = 128 * 1024
mb := make(buf.MultiBuffer, 0, readSize)
if err := r.readInternal(false, &mb); err != nil {
buf.ReleaseMulti(mb)
return nil, err
}

for i := 1; i < readSize; i++ {
err := r.readInternal(false, &mb)
if err == errSoft || err == io.EOF {
break
}
if err != nil {
buf.ReleaseMulti(mb)
return nil, err
}
}

return mb, nil
}

获得base64编码的doc,解码出来分析

获得word后直接后vt导入扫描

image-20220731050123596

把api.ipify.org加密md5即可解压,获得flag文件

根据描述为gob文件,搜索了一下,gob是golang的二进制序列号数据包,了解结构后可知直接把后面的PNG FILE复制到单独hex,根据提示,说是随机内容,并且flag文件并存在一个时间,猜测是时间戳为seed进行反向shuffle随机运算

随机后的文件提取后如下:

image-20220731172444137

反向shuffle随机运算脚本如下:

package main
​
import (
    "io/ioutil"
    "log"
    "math/rand"
    "os"
)
​
func main() {
    var attr []int
    var attr2 []byte
    content, err := os.ReadFile("1.png")
    if err != nil {
        log.Fatal(err)
    }
    // fmt.Println(content[1])
    rand.Seed(1658213396)
    //rand.shuffle逆运算
    for i := 0; i < len(content); i++ {
        attr = append(attr, i)
        attr2 = append(attr2, content[i])
    }
    // fmt.Println(attr)
    rand.Shuffle(len(attr), func(i, j int) {
        attr[i], attr[j] = attr[j], attr[i]
    })
    // fmt.Println(attr)
    // k := 0
    for key, v := range attr {
        attr2[v] = content[key]
    }
    // fmt.Println(attr2)
    //写入attr2
    err = ioutil.WriteFile("ffffff.png", attr2, 0644)
}
​

解密后获得图片

flag

看了一圈没什么东西,直接读像素值发现透明度比较可疑,写脚本导出获得falg

from operator import length_hint
from PIL import Image
​
im=Image.open('flag.png')
​
#读取图片像素
length = im.size[0]
width = im.size[1]
print(length,width)
for i in range(width):
    for j in range(length):
        im.getpixel((j,i))
        if im.getpixel((j,i)) == (255,255,255,255):
            continue
        else:
            pixel = im.getpixel((j,i))
            if pixel[3] ==255:
                continue
            print(chr(pixel[3]),end='')
        
image-20220731050626337
© 版权声明
THE END
喜欢就支持一下吧
点赞12 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情