【wp】2021CISCN初赛


上周末打的CISCN初赛,发现没整理wp来火速补上。

这次RE属实拉跨,就做了俩签到题,做完就去摸MISC了,冲刺卷还能摸出个robot是我没想到的。(以及想看零解HMI的wp,翻了半天没翻到check我可好奇死了x

Reverse

glass

说签到真的是签到题

用JEB看java层发现是直接调用so的,那直接apktool解压然后去逆so文件

显而易见的前两个函数是RC4相关(还以为会魔改= =,第三个函数是一个自定义加密函数

密文在unk_497C,长度0x27,先还原encrypt之前的数组,然后进行RC4解密(写了一些注释在代码里

exp:

# 还原encrypt前的数据
arr=[0xA3, 0x1A, 0xE3, 0x69, 0x2F, 0xBB, 0x1A, 0x84, 0x65, 0xC2, 0xAD, 0xAD, 0x9E, 0x96, 0x05, 0x02, 0x1F, 0x8E, 0x36, 0x4F, 0xE1, 0xEB, 0xAF, 0xF0, 0xEA, 0xC4, 0xA8, 0x2D, 0x42, 0xC7, 0x6E, 0x3F, 0xB0, 0xD3, 0xCC, 0x78, 0xF9, 0x98, 0x3F]
key=b"12345678"
pos=0
for j in range(0,39,8): #第一部分逐字节xor 根据xor的特性直接把加密方法照搬
    k=0
    while k!=8 and j+k<39:
        arr[pos+k]^=key[k]
        k+=1
    pos+=8
l=[]
for i in range(0,39,3): #第二部分乱七八糟的xor 直接拿已知数组copy了一下加密流程试出对应关系
    l+=[arr[i+1]^arr[i+2],arr[i]^arr[i+1],arr[i]^arr[i+1]^arr[i+2]]
data=bytes(l)

# RC4加/解密
from arc4 import ARC4
rc4=ARC4(key)
ans=rc4.encrypt(data)
print(ans)

CISCN{6654d84617f627c88846c172e0f4d46c}

baby_bc

.bc文件前不久某场比赛才接触过,直接走流程

先用clang -c baby.bc -o baby.bc.o(也可以clang baby.bc -o baby得到可执行文件),然后直接用ida逆.o文件

(是附件更新前做出来的,吐槽一句怎么更新附件以后还把符号表混淆了x

前半个check是用输入填充地图/棋盘,map空的部分填输入的ascii码-48,map有值的部分输入要为'0'。输入只能为0-5。

后半个check有四个部分,分别是同一行的数据各不相同、同一列的数据各不相同、col=1时当前值<下方的值&&col=2时当前值>下方的值、row=1时当前值>右方的值&&row=2时当前值<右方的值。

这个check规则不就是futoshiki吗hhh

比赛的时候想在网上找脚本,但是没找到能用的,完全靠手推(。

赛后被队里师兄提醒说其实可以用z3约束求解,猛然想起好像确实能用做哦(傻了x),现在复盘的话不如来学着写z3做(

参考wp:【CISCN2021】第十四届全国大学生信息安全竞赛初赛-writeup

写z3脚本有:

from z3 import *
from hashlib import md5

row=[0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00]
col=[0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01]
s=Solver()
res=[[Int("x%d%d"%(i,j)) for i in range(5)] for j in range(5)]
s.add(res[2][2]==4) #原map中已知值
s.add(res[3][3]==3)
for i in range(5):
    for j in range(5):
        s.add(res[i][j]>=1)
        s.add(res[i][j]<=5)
        for k in range(j): #同一行互不相等
            s.add(res[i][j]!=res[i][k])
        for k in range(i): #同一列互不相等
            s.add(res[i][j]!=res[k][j])
for i in range(5): #row=1时当前值>右方的值&&row=2时当前值<右方的值
    for j in range(4):
        if row[4*i+j]==1:
            s.add(res[i][j]>res[i][j+1])
        elif row[4*i+j]==2:
            s.add(res[i][j]下方的值
    for j in range(5):
        if col[5*i+j]==1:
            s.add(res[i][j]res[i+1][j])
ans=s.check()
if ans==sat:
    # print(s.model())
    m=s.model()
    flag=[]
    for i in res:
        for j in i:
            flag.append(m[j].as_long())
    flag=[x+0x30 for x in flag]
    flag[12]=0x30
    flag[18]=0x30
    flag=bytes(flag)
    print(flag)
    print("CISCN{"+md5(flag).hexdigest()+"}")

输入是1425353142350212150442315,得到flag:

CISCN{8a04b4597ad08b83211d3adfa1f61431}

Misc

tiny_traffic

翻流量包的时候有看到get了secret文件,这种文件名立刻警觉,感觉是关键文件

查看响应包21615,有一个Content-Encoding:br,查了一下是Brotli压缩的文本

于是试图导出http对象,得到secret文件后解压缩发现解不出什么可见字符,于是逐个试了一遍没后缀名的文件解压,试出了:

import brotli
with open('test','rb') as f:
    data=brotli.decompress(f.read())
print(data)

手动拆一下就是

syntax = "proto3";
message PBResponse {
  int32 code = 1;
  int64 flag_part_convert_to_hex_plz = 2;
  message data {
    string junk_data = 2;
    string flag_part = 1;
  }
  repeated data dataList = 3;
  int32 flag_part_plz_convert_to_hex = 4;
  string flag_last_part = 5;
}
message PBRequest {
  string cate_id = 1;
  int32 page = 2;
  int32 pageSize = 3;
}

查了一下proto3跟python的联动,找到了这篇文章,https://blog.csdn.net/menghaocheng/article/details/80176763,格式跟需求都一样,直接按步骤做

写入protobuf处理脚本:

import brotli
with open('test','rb') as f:
    data=brotli.decompress(f.read())
with open('../test.proto','wb') as f:
    f.write(data)

运行./protoc.exe --python_out=./ test.proto得到test_pb2.py

不知道先调哪个message于是两个都试了一下,最后exp是:

import brotli
import test_pb2

res=test_pb2.PBResponse()
with open('secret','rb') as f:
    s=brotli.decompress(f.read())
    res.ParseFromString(s)
    print(res)

得到:

于是再拼接一下变成flag:

print("CISCN{"+hex(15100450)[2:]+"e2345"+"7889b0"+hex(16453958)[2:]+"d172a38dc}")

CISCN{e66a22e23457889b0fb1146d172a38dc}

robot

看了一眼别人的wp发现我这个好像非预期了= =

依然是翻流量包,都是TCP协议包,于是直接追踪TCP流,能看到很明显的符合r"tgPos{\d+}\.Value\.\[\d+,\d+,-?\d+]"这种正则的字符串。

这种中括号形式就很像坐标,更何况这还是机器人绘制,肯定需要定位。

一开始以为是x,y,z这样分布,不过后来发现每个第三个值为-10的坐标点都是每个tgPos的最后一个,所以猜测第三个值是用来标定是否结束的。

所以把这里追踪的结果全部复制下来,然后用python提取并画图

import re
import matplotlib.pyplot as plt

x=[]
y=[]
with open('tcp.txt','r') as f:
    for line in f.readlines():
        ret=re.search(r"tgPos{\d+}\.Value\.\[\d+,\d+,-?\d+]",line) #提取目标字符串
        if ret!=None:
            s=ret.group()
            idx1=s.find('[')
            idx2=s.find(',')
            idx3=s.rfind(',')
            x.append(int(s[idx1+1:idx2]))
            y.append(int(s[idx2+1:idx3]))

plt.scatter(x,y)
plt.show()

可以得到图片:

垂直镜像处理一下就是:

print("CISCN{"+md5(b'easy_robo_xx').hexdigest()+"}")得到flag:

CISCN{d4f1fb80bc11ffd722861367747c0f10}