2024第三次线上赛wp
MISC 卫继龚的日常 将题目中的图片抠出来,放进谷歌,识别出是日本横滨北仲桥。 根据题意附近应该有JR地铁站,继续谷歌地图,发现附近有JR樱木町站。 根据题意,接着找附近的商店街。谷歌一下,附近有野毛小路商店街。 同时寻找日本知名的一元店,百度到了几个日本知名品牌。 如果你是这样做或是以类似思路做的,那么此时你的思路和寻找方向已经偏了。 最关键的原因,还是审题不完全。关键词:5分钟就能到地铁。仔细看题目图片,假设图片是在上下班路途上拍的,那么他必然要经过北仲桥。如果他是从家到地铁经过的北仲桥,那么他家附近的商店街应该在北仲桥附近,而野毛商店街的位置是相反方向。也就是说我应该去找北仲桥附近的商店街,但是找了一圈,没有发现很知名的商店街。 此时,假如北仲桥是在作者公司附近呢?樱木町站是作者公司附近的地铁站,因此题目图片中,加了一句:“只需要坐5分钟地铁”。 以樱木町站为起点,5分钟的车程,大致1-2站。继续谷歌,找到JR东日本的路线图。 根岸线樱木町站,5分钟车程,前后不会超过2站,分别是石川町、关内、横滨、东神奈川。 以这4个站,再结合谷歌出来的横滨知名商店街 继续谷歌地图 在横滨站附近寻找,一无所获 关内站附近发现伊势佐木町商店街。 依次谷歌日本知名的百元品牌,输入CanDo终于发现目标 使用谷歌街景 Project-X 题目给了一个 pcapng 的流量包文件,在分析前先来过一下Vmess协议下数据包加密过程(官方配置文档、通信协议文档) 假设有如下网络拓补 此时用户在配置好代理软件后使用vmess协议进行通信,在浏览器中使用google,发起了一个下面这样的数据包(1.1.1.1是用户ip,1145是用户发起请求端口) 为了方便画图,以上数据包所有内容都包含在请求包体中。此时数据包会被交给代理软件,vmess协议会在数据包前加上一个用来加密该数据包的加密方式 vmess允许用户自定义加密包体的方式,一般会在配置页面选择auto。这里我们假设使用AES-128-GCM加密,这样请求包体的内容就会被加密成无规则的字节流,被加密后包体就变成这样(遮挡部分表示被加密,后面使用的颜色不同表示加密方式不同) 接着会根据用户在配置文件中使用的用户id进行AES-128-CFB加密,将包体加密方式这部分也加密起来(下面是官方文档给的加密方式,看不懂也没事,只要知道会用一个特定的值与用户id进行加密运算,将这部分给搞糊) 并且会在前面加上当前时间戳与用户id的md5值作为一个验证值,此时整个数据包就是这个样子 最后拼接上代理服务器的ip地址与端口,就变成了这样 当数据包来到防火墙时,由于请求包体被完全加密,防火墙无法识别出用户意图,且代理服务器不在防火墙黑明单,于是就会放行数据包。代理服务器拿到数据包后,会先开一个大小为30~90左右的数组,对当前时间戳的+-30秒进行逐个的md5校验,当数据包中携带的校验值与数组中某个值匹配后,就会认定该数据包为有效数据包,于是对后面被加密的两个部分进行解密。解密后就重新拿到了下面这个数据包 接着再进行一层解密,就能得到我们的请求意图。这便是最原始的vmess协议通信过程。这里有一个配置信息我们没有说到,就是额外id。其实额外id的存在就是为了防止在同一时间段内发送大量数据包导致校验值重复,比如原本校验值是md5(11451),当额外id为1时就有md5(11452),以此类推。但这种验证方式也有局限性,在实际使用中已被发现存在被重放攻击的风险,具体可以看这篇,下面是官方文档对这一风险的应对手段 VMessMD5 被弃用的原因是因为它能够被很容易地通过主动探测的手段检测到,见上面提到的那篇 v2ray-core#2523。 简单来说就是使用AEAD认证的方式取代我们上述的md5验证值。这样即便防火墙试图修改被加密的数据包,被修改的数据包发送到代理服务器后也会被丢弃,就能避免重放攻击的风险。置方式也很简单,就是将额外id设置为0。而在最新版v2ray-core中,已经对vmess协议强制使用AEAD认证 介绍完vmess协议的通信原理后,再来看看赛题。这道题就是AEAD 的加密方式 用wireshark翻流量可以得到一个 v2ray 的 json 配置文件,也是从这里确定了是VMess流量分析 解密流量有两种方法,一种是通过阅读代码来自己实现解密,另一种是通过重放流量来获取明文。 关于协议的部分实现,可以参考 extra-VMessAEADdoc.zip 但是协议的最终实现还是需要参考 v2ray-core 的源码,因为有些地方的实现和文档中的描述不一致。 这里我们可以使用一个专门用来解析AEAD认证的库,并使用其编写一段exp import uuid from vmess_aead.encoding import VMessBodyEncoder from vmess_aead.headers.request import VMessAEADRequestPacketHeader from vmess_aead.utils.reader import BytesReader data = "a49502ee07ffdd20f11597e961f7768b41be7bc32030107fc81f235f72ff1b294d074ade94281242412b4c19123b15250ac3d5ad9524df9acd0ee5f6dcca7b0c2849b2f4df20190dd084c01c3f6e2834dd87cb8e97fa178b2ec454755f89d9b735ae6dab9c7989cf4154f7eae53774d9d6cdb55d0a76fdaf21e08bae26e49cbb3c56d11a3fe540454bfbae06305460301caca4109df3335b0c3646b6e2d856a927f9298b87da3a7cf3cffcca6c27259fc055faa9f3155cc95f698bb37436008783b6cd03d38a8e109f78a48c860b600fcbe825cd6c6a5be2c95fce121df574c70fe62e4f24e28de5983db6c3c0192d72ec785b6d58c4b8301c4f70eab683" data = bytes.fromhex(data) reader = BytesReader(data) user_id = uuid.UUID("f3a5cae3-6bd2-40d1-b13b-2cc3d87af2c7") header = VMessAEADRequestPacketHeader.from_packet(reader, user_id) print(header) encoder = VMessBodyEncoder( header.payload.body_key, header.payload.body_iv, header.payload.options, header.payload.security, header.payload.command, ) body = encoder.decode_once(reader) print(body) ...