改HTML step改成1,提交获取flag
第一个暴力尝试
第二个查RFC1149
第三个显然是Teeworlds(多年老玩家本人)
第四个随便找个带街景的地图数一下
第五个,官方的存档站暂时502了,但是archive.is有,直接找即可
点开所有js,肉眼审查一下,显然获胜判断在html_actuator.js,然后找到/getflag?my_favorite_fruit=banana
的api得到flag
用WSL运行,就不会退出了
写了好久的py自动解析大写数字(悲) (附件1)
第一问随手在Wikipedia上抄一个能平移的就好了
第二问试了好半天,最后没办法,写了个模拟器fuzzing了一下 (附件2)
先拉出来了第一句话在百度搜索。在房天下找到了一个网页,百度爬的是乱码,点进去是正确的。
比对了一下,正好是乱码的两个字对应一个字。
拿出来连续两个字,搜到了https://www.v2ex.com/t/421212
,直接运行命令得到flag
google搜索 reverse quine python
,稍作修改就能过第一问(去掉回车符)
x='x=%r;print((x%%x)[::-1],end="")';print((x%x)[::-1],end="")
第二问也是稍作修改
x='x=%r;print(__import__("hashlib").sha256((x%%x).encode()).hexdigest(),end="")';print(__import__("hashlib").sha256((x%x).encode()).hexdigest(),end="")
得到flag
第一问是毒瘤Unicode问题 字符fl
(chr(64258))的upper是FL
,然后交一个flag
就可以了
第二问手动学习一下UTF-7编码。手动用UTF-16构造一个Base64结果。建议只编码一个字符,注意大小端序问题
交+AGY-lag
即可
下载Docker,查看Dockerfile,显然是利用overlayfs的一些特性
直接跑到/var/lib/docker 中 find flag.txt
即可
先挂个知乎提问https://www.zhihu.com/question/428175951
各位猜猜关注的人里头有多少是组委会的
其实很简单,先找个支持0端口的开http的东西。本人用的是python的socket。
本来直接发了个raw http包,但是发现真是个web,有点麻烦,于是改成了一个反代。
注意,由于有些NAT设备的要求,非公网ip设备没法连0端口。因此我找了个vps做反代。 (附件3)
随便找个 图片频域信息提取工具,扔进去得到flag
最开始想着改这两个文件,不过发现好像不太奏效。
大力出奇迹:下载一个OpenGL调试程序(本人下了个RenderDoc),之后随便截个帧。能点的按钮都xjb点一下:flag出现了!
打开IDA 用了gets 查看变量在内存的分布,第一问显然是多输入一点(大概150个)东西,溢出到success变量后将success搞成true,然后得到flag
第二问似乎是个构造rop链的pwn题,不过本人完全不会bin题,也没空学(全场bin题仅有150分)
显然暗示的是GitHub北极备份计划
照着https://github.com/github/archive-program/blob/master/GUIDE_zh.md
做,将每个二维码搞成一个bin后连接,就可以得到一个.xz文件,解压repo得到flag
由于市面上大部分解二维码的软件对bin的支持很差,所以本题浪费了很长时间。建议直接搜索zbar bin
以节省时间。
测试发现,所有利息计算居然是四舍五入
于是构造一下钱:每张信用卡借2050元,每张储蓄卡存167元。稍微计算一下发现这样显然是赚的。
多开几张卡,然后每隔几天倒腾一下避免信用卡利息上升,大量发包即可刷钱得到flag。
显然是解析积分然后计算
尝试全本地,但是cookies处理好像有点问题,索性全用浏览器
可以用header editor
浏览器插件屏蔽LaTex渲染,然后只用解析源码就可
Chromium的Console提供了一个叫"活动表达式"的东西,可以每次页面载入完后运行JS,利用这个每次刷新提交
写了个py处理latex,之后就是计算积分了
本人直接大力使用了https://zh.numberempire.com/definiteintegralcalculator.php
来做,就是算了几十个后要换下IP,很痛苦。
之后在本地用python开了个webserver,积分页面请求这个webserver,python再请求网站计算结果后返回。
(附件4)
好玩的数论题
看到求根号,考虑服务器是怎么计算的。
第一个想到Cipolla算法。复习了一下,发现根本没法直接把质数$p$换成$N=pq$,Cipolla会错。
因此考虑另外一种做法:对两个质数作为模数求二次剩余,之后用CRT合并。
关于一个质数取模的二次剩余有两个,那么对于$N=pq$就会有四个。
假如输入的$L$关于$p,q$的一个二次剩余分别是$X,Y$,那么服务器可能会得到以下四种
$X,Y$ $(p-X),Y$ $X,(q-Y)$ $(p-X),(q-Y)$
再考虑CRT过程,一个算法是$A\equiv X+p(\text{inv}(p,q)(Y-X)) \pmod N$,其中$\text{inv}(a,b)\equiv a^{-1}\pmod b$。
如果还能找到一个根$B\equiv X+p(\text{inv}(p,q)((q-Y)-X)) \pmod N$,那么将两式相减,就可以得到含有因子$p$的一个数字。显然这对于$p,q$互换也成立,因此对于上述的4种情况,有2种都可以得到含有一个质因数的数
然后直接和$N$求gcd即可得到一个质数,然后就可以算出另外一个质数,之后就可以得到RSA私钥$d$,直接算出flag
具体操作流程是:先输入一个$2^{1024}$左右的数与0相加,然后观察一下是否相等。如果大了,就说明对$N$取模了。利用这个方法可以直接得到$N$的具体值。
之后查询sqrt(114514)(我试的较大数字中,只有这个数字是有根的)得到一个根$X$
之后枚举$K$计算$(X+K)^2$,让服务器计算其二次剩余,看是否与$X+K$相等。
若相等,则再挑$K$,否则直接执行上述算法,若能跑出来则已经找到了$p,q$,得到flag
注意到~-x
是很重要的单目运算,可以让x减1。因此可以大力区间dp只处理双目运算,然后特判这种单目运算
本地先打表,之后直接提交即可 (附件5)
先来个算法链接 https://www.zhihu.com/question/27050108/answer/35041211
之后只要写出这个bf即可。
本人看到后,直接上StackOverflow找到了个bf中if(a>=b)
的实现,之后手动进行了一下内存管理,大力写了一段bf,多试几次得到flag。(代码没存)
进入Public下载一下Dockerfile和nginx.conf
发现关键点:Public和根目录各有一个h5ai
同时nginx.conf有缺陷:会先匹配.php而不是/的auth
看nginx.conf,找到h5ai的真正入口。因此可以直接访问/_h5ai/public/index.php
考虑怎么得到/flag.txt。进入网盘,直接点文件,发现是直接请求的文件本身,不能利用。
文件前有复选框,勾上后发现可以下一个tar文件。Network+curl修改一下h5ai的入口,把请求文件改为flag.txt,得到flag
(实际上本人是翻h5ai源码才发现存在这个download的api的,不过后续是借助浏览器完成的)
第一问:
nghttp https://146.56.228.227/
得到secret和flag
第二问差评:本人试了好半天H2发connect,总是被回Protocol Error。正纳闷这题怎么解释H2 Proxy,然后试了一下,发现curl似乎能直接以H1.1 CONNECT的方式连接
我:?
之后题目让干啥我就干啥:设secret,加referer,连接ip改成0.0.0.0来连localhost
curl http://0.0.0.0:8080 -x https://146.56.228.227/ -v -k --proxy-insecure --proxytunnel -H "Referer: https://146.56.228.227/" --proxy-header "Secret: abdad49e9a"
本人试了python-hyper,libcurl等不下十种直接发包工具,试了nginx,caddy,apache作反代,实在是没想到是个这。差评
心疼出题人土老师1s
本人似乎是唯一一个预期解
不过大概也和本人当年天天爆破mc种子有关
翻源代码:这个地图生成方式和mc村庄几乎一模一样,显然是要爆破种子。
爆破的具体方法不写了,各位参考官方wp和以下文章吧
https://www.mcbbs.net/thread-816891-1-1.html
之后考虑如何获取flag:查看Game.java:30
,发现要想获取flag必须使前后材料不同。
想到在SHORT_DURATION的等待时间内,将不是flag的方块变成flag
(在没有AIR的情况下)显然只能是利用reset。发现reset后的种子只有3bit是完全未知的,验证了爆破种子的猜想。
最终做法是:爆破出种子,预测可能接下来的8个种子。同时发挖这8个地方的请求,然后重置游戏,必有一个能挖出来。
审查源码,发现flag分为两种,要么无论种子此位置都有,要么由种子决定位置。写代码时要注意避免。
还有要判断坐标范围的问题。
本来想本地搭个localserver测试,结果发现作者用var强行不让用j8,不得不装了个openjdk11。用cpp写还要担心数据类型问题,最后还是强行编译了一下然后用jd-gui开了一下确认数据类型无误。
(附件6)
三道题都要先拉出flag长度。方法显然:本地钦定一个flag,构造16种输入,看和远程的长度分布是否一样。
第一问:首先利用CBC模式的性质:通过改变iv可以随意裁剪出中间的任意块。
不考虑padding问题,Bob可以返回一个hash正确与不正确的信息。一个想法是:逐个字符逐个枚举猜flag,让Bob告诉这个猜的字符对不对。
因此可以考虑,通过调整name长度,将flag的最后一个字符单独成块。之后计算一个猜测的字符的SHA256接到块后边。Alice加密后,将中间这一部分裁剪出来发给Bob进行验证。
找到最后一块后,其余同理
第二、三问:看到所有人都是同时过第二问和第三问,于是我也直接看第三问。
CRC本身有个很好的性质:crc(a)^crc(b)^crc(c)=crc(a^b^c)
简单推导一下,可以发现:翻转原mess的一个特定位,对最终crc也是翻转某些特定位。这些特定位仅和crc多项式P和翻转位置pos有关。
再转化一下:对于mess的可预测变化,crc的变化也是可预测的,观察和预测方式均为异或。
将这些crc的性质全部套上一层HMAC,试验发现仍然成立(mess长度不能改变)
因此考虑利用Alice计算的crc校验码:猜测flag的一个字符,然后将其它可控的块进行变化,使得在猜测正确的情况下crc不变。
再观察CBC模式的性质:如果块调换顺序,对明文的影响也是可计算的(异或上操作之前和操作之后的前序块的密文)。这达到了一定程度上的可预测性,考虑利用这个构造特定crc。
具体地:将含有flag最后一个字符的块与其它地方的块交换一下。枚举这个字符,并计算在此情况下对明文的改变。上文提到,可预测的明文变化对crc变化是固定的,因此将其算出。
现在只需要,如何通过调换其它块的顺序,使得可以抵消掉明文交换所造成的crc变化。
我们发现,如果对调两个相邻密文块,只会影响三个明文块的值。
为了减少不可预料的影响,可以考虑三个块一组:每组前两个块对调,计算变化前后明文对最终crc的影响。
选择一些组进行对调操作,使得恰好能抵消影响。运用 线性基 算法,即可得到选择哪些组。
为了留一点冗余,本人构造了150组。
注意到这个线性基并不能构造完全,不过已经能覆盖所有可能的crc的变化了。
(本人并不懂抽代那一套理论)
(附件7)
第一问:v=x0,则m0_=m0
第二问:
本人做题方向实在奇怪,以下是真实的心路历程。
具体是这样:因为RSA的d未知,因此m0_和m1_中加的两个数都是完全不可预测的随机信息,可以近似认为具有2048bit的信息量。
但是考虑一下,可以通过构造v,使得这两个数具有一定的关系。考虑到m0,m1,总共需要获得的信息量为3072bit。
我:?明明只有2048bit的物理信道宽度,凭什么传输3072bit。
于是从头阅读代码,突然发现m0和m1的信息量并不是1024bit,而是512bit。
具体的,每一位都是[0-9][a-f]的可见字符。
计算一下,发现正好达到理论最高信息传输量(不考虑RSA)。
考虑如何使两个的d次方相关。一个最简单的想法是,构造v=(x0+x1)/2。
则两个d次方恰为相反数。二者相加即可得到m0+m1,正好1024bit。
看起来已经得到答案了,实则未必:这m0+m1,真的有1024bit吗?
例如看第七位:必然恒为0。这显然不行,没有充分利用信道,丢失了信息。
写出所有可能数字的二进制表示。一个显然的想法是,将m0进行移位,即计算(m0<<3)+m1
。
但这一定最优吗?未必。既然我们已经知道问题出在哪了:每一位出现0/1的概率并不相同。那么可以考虑把这个式子升级一下,即计算A*m0+B*m1
。利用程序自动找到对于每个bit/byte,信息熵最大的AB组合。
由于当AB较小的时候,答案的每个byte几乎只与m0,m1的该位置byte和下一个位置的byte相关。因此可以暴力枚举算一下信息熵。
找到AB后,从低位到高位按bit枚举可能的m0和m1,并进行简单的大小范围和求和的检验。
之后对于所有可能的情况,利用RSA的性质进行检验(即验证$(m0_-m0)^e \equiv v-x0 \pmod N$)
最终对于AB采用了(61,43),这个组合,跑的比第一和官方都快(雾)。到最后有约1/2的概率情况数只有不到一万种,纯python可两分钟出解。因此其实这题也可以再增大bit数。
那么问题只剩:如何得到A*m0+B*m1
了。愉快的推公式时间来了(最终程序定义略有差别)。
定义:$D=x0-x1$
则有:$m0_ \equiv m0+V^d \pmod N$
因此:$Am0+Bm1+AV^d+B(V+D)^d \equiv m0_+m1_ \pmod N$
如果能抵消关于V的项,枚举右侧加上整数倍的N即可得到A*m0+B*m1
的可能值。这种可能性其实非常少,几乎是唯一的。
考虑抵消,有: $$ AV^d \equiv -B(V+D)^d \pmod N $$ 同时开$d$次根,有: $$ (A(-B)^{-1})^\frac{1}{d}V \equiv V+D $$ 欧拉公式,有: $$ ((A(-B)^{-1})^e-1)V \equiv D $$ 因此已经可以直接计算出$V$的值了,进而推出v。
提交后本地跑,快速得到flag。
(附件8)
题出的好!难度适中,覆盖知识点广,题目又着切合实际的背景,解法比较自然。给出题人点赞 !
明年一定再来。
def readfile(filename,encode="utf-8"):
f=open(filename,encoding=encode)
sr=f.read()
f.close()
return sr
def savefile(filename,content):
f=open(filename,'w')
f.write(content)
f.close()
def dect(t):
#print(t)
if len(t)==0:
return 0
jbl="零壹贰叁肆伍陆柒捌玖"
dw="拾佰"
ans=0
if "佰" in t:
a,b=t.split("佰")
ans+=dect(a)*100
ans+=dect(b)
return ans
if "拾" in t:
a,b=t.split("拾")
if len(a)==0:
ans+=10
else:
ans+=dect(a)*10
ans+=dect(b)
return ans
sp=t[-1]
for i in range(10):
if jbl[i]==sp:
return i
print("ERR")
print(t)
def toi(x):
if len(x)==0:
return 0
ans=0
if "元" in x:
a,b=x.split("元")
ans+=dect(a)
ans+=toi(b)
return ans
if "角" in x:
a,b=x.split("角")
ans+=dect(a)*0.1
ans+=toi(b)
return ans
if "分" in x:
return dect(x[:-1])*0.01
if x=="整":
return 0
print("ERR")
print(x)
g=readfile("bills.csv").split('\n')
jb=0
for x in g:
if len(x)==0:
break
a,b=x.split(',')
b=int(b)
xx=toi(a)
jb+=xx*b
#print(xx,a)
print(jb)
//I
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<set>
#include<map>
#include<cstdlib>
#include<ctime>
using namespace std;
template<typename __T>
inline void read(__T &x)
{
x=0;
int f=1;char c=getchar();
while(!isdigit(c)){if(c=='-') f=-1;c=getchar();}
while(isdigit(c)) {x=x*10+c-'0';c=getchar();}
x*=f;
}
typedef pair<int,int>pi;
pi mpi(int a,int b)
{
return make_pair(a,b);
}
const int mod=1000000007;
long long qpow(long long a,long long b=mod-2)
{
long long ans=1;
while(b)
{
if(b&1) ans=ans*a%mod;
b>>=1;
a=a*a%mod;
}
return ans;
}
long long rand(long long l,long long r)
{
long long a=rand();
long long b=rand();
long long c=rand();
a=((a<<30)|(b<<15)|c);
long long siz=(r-l+1);
return l+a%siz;
}
int n=50;
char inimp[100][100];
char mp[100][100];
void print()
{
for(int i=0;i<n;i++)
{
cout<<mp[i];
cout<<endl;
}
cout<<endl;
}
int fxx[8]={-1,-1,-1,0,1,1,1,0};
int fxy[8]={-1,0,1,1,1,0,-1,-1};
int getcnt(int x,int y)
{
int sum=0;
for(int i=0;i<8;i++)
{
int nx=x+fxx[i];
int ny=y+fxy[i];
if(nx<0 || nx>=n || ny<0 || ny>=n) continue;
sum+=(mp[nx][ny]=='#');
}
return sum;
}
char tmp[100][100];
void gen(int rnd=200)
{
for(int rd=0;rd<rnd;rd++)
{
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
{
int gg=getcnt(i,j);
if(gg<2) tmp[i][j]='.';
else if(gg>3) tmp[i][j]='.';
else
{
if(mp[i][j]=='#') tmp[i][j]='#';
else
{
if(gg==3) tmp[i][j]='#';
else
tmp[i][j]='.';
}
}
}
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
mp[i][j]=tmp[i][j];
//print();
}
}
void cpmp()
{
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
mp[i][j]=inimp[i][j];
}
bool ck()
{
if(mp[5][45]=='#') return 0;
if(mp[5][46]=='#') return 0;
if(mp[6][45]=='#') return 0;
if(mp[6][46]=='#') return 0;
if(mp[25][45]=='#') return 0;
if(mp[25][46]=='#') return 0;
if(mp[26][45]=='#') return 0;
if(mp[26][46]=='#') return 0;
return 1;
}
bool dot()
{
int rat=200;// per 1k
cpmp();
for(int i=0;i<15;i++)
for(int j=0;j<15;j++)
{
int sb=rand(0,999);
mp[i][j]=(sb<rat)?'#':'.';
}
print();
gen();
print();
return ck();
}
int main()
{
long long seed=time(NULL);
srand(seed);
freopen("imp","r",stdin);
for(int i=0;i<n;i++)
{
cin>>inimp[i];
}
while(dot()==0);
return 0;
}
import logging
import select
import socket
import struct
import socks
from socketserver import ThreadingMixIn, TCPServer, StreamRequestHandler
logging.basicConfig(level=logging.DEBUG)
SOCKS_VERSION = 5
class ThreadingTCPServer(ThreadingMixIn, TCPServer):
pass
class SocksProxy(StreamRequestHandler):
def handle(self):
logging.info('Accepting connection from %s:%s' % self.client_address)
remote = socket.socket()
remote.connect(("202.38.93.111",0))
self.exchange_loop(self.connection, remote)
def exchange_loop(self, client, remote):
while True:
r, w, e = select.select([client, remote], [], [])
if client in r:
data = client.recv(4096)
if remote.send(data) <= 0:
break
if remote in r:
data = remote.recv(4096)
if client.send(data) <= 0:
break
if __name__ == '__main__':
with ThreadingTCPServer(('0.0.0.0', 8080), SocksProxy) as server:
server.serve_forever()
- web.js
function post (data) {
let url = 'http://localhost:5000/que',
xhr = new XMLHttpRequest();
xhr.open('post', url,false);
xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
xhr.send(data);
console.log(xhr.responseText);
return xhr.responseText;
}
function toget()
{
cont=document.querySelector("body > div > div > div > center > p").innerText
return post("txt="+encodeURIComponent(cont))
}
ans=toget()
document.getElementsByName("ans")[0].value=String(ans)
document.getElementsByTagName("button")[1].click()
- web.py
import os
import json
import math
import time
import re
from shutil import copyfile
from flask import Flask,request
import queue
import logging
log=logging.getLogger("mid")
log.setLevel(logging.WARNING)
app = Flask("mid")
def after_request(resp):
resp.headers['Access-Control-Allow-Origin'] = '*'
return resp
app.after_request(after_request)
import re
import requests as rqs
import json
import time
proxyList={
"http":"socks5h://localhost:1081",
"https":"socks5h://localhost:1081"
}
jb=rqs.Session()
jb.headers.update({"Cookie":"PHPSESSID=114514; session=aaabbbccc"})
nms=rqs.Session()
nms.headers.update({'Cookie':"__cfduid=1; _ga=2; _gid=3; __gads=4; _gat=5; _game_success_count=6; _game_points=7",
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/114.514 (KHTML, like Gecko) Chrome/114.514 Safari/1919.810 Edg/114.514"})
def locbk(txt,pos):
sb=0
for i in range(pos,len(txt)):
if txt[i]=='(':
sb+=1
if txt[i]==')':
sb-=1
if sb==0:
return i
def tosstex(txt):
txt=re.sub(r"\$","",txt)
txt=re.sub(r"\}\{","/",txt)
txt=re.sub(r"\\frac","",txt)
txt=re.sub(r"\\left","",txt)
txt=re.sub(r"\\right","",txt)
txt=re.sub(r"ln","log",txt)
txt=re.sub(r",","*",txt)
txt=re.sub(r"\{","(",txt)
txt=re.sub(r"\}",")",txt)
txt=re.sub(r"\\","",txt)
txt=re.sub(r"([^\+\-*/]) ([^\+\-*/])","\\1*\\2",txt)
txt=re.sub(r"([^\+\-*/]) ([^\+\-*/])","\\1*\\2",txt)
return txt
def tossint(txt):
txt=tosstex(txt)
txt=txt[4:-6]
pm=txt.find('^')
p1=txt[0:pm]
eps=locbk(txt,pm+1)
p2=txt[pm+1:eps+1]
txt=txt[eps+1:]
if txt[0]=='*':
txt=txt[1:]
return (eval(p1),eval(p2),txt)
def getpage():
r=jb.get("http://202.38.93.111:10190/")
tx=r.text
p1=tx.find("<p>")
p2=tx.find("$</p>")+1
tx=tx[p1+4:p2]
lol=tossint(tx)
print(lol)
return lol
def queryans(tup):
r=nms.post("https://zh.numberempire.com/definiteintegralcalculator.php",data={"function":tup[2],"var":"x","a":tup[0],"b":tup[1],"_p1":2110},proxies=proxyList)
tx=r.text
tx=tx[tx.find("result1>")+8:]
tx=tx[:tx.find("</span>")]
print(tx)
return tx
@app.route('/que',methods=["POST"])
def que():
txt=(request.form["txt"])
tu=tossint(txt)
print(tu)
an=queryans(tu)
#time.sleep(1)
return an
app.run(host="0.0.0.0",port=5000,debug=False,threaded=True)
sb="114514"
dp=[]#(fr,st,num)
for i in range(6):
dp.append([])
for j in range(6):
dp[i].append({})
for i in range(0,6):
for j in range(i,6):
myn=int(sb[i:j+1])
dp[i][j][myn]=str(myn)
dp[i][j][-myn]="(-"+str(myn)+")"
def calc(a,b,t):
if t==0:
return a+b
if t==1:
return a-b
if t==2:
return a*b
if t==3:
if b==0:
return 99999999
return a//b
if t==4:
return a^b
if t==5:
return a|b
if t==6:
return a&b
print(a,b,t)
itb="+-*/^|&"
for x in range(1,6):
for a in range(0,6-x):
b=a+x
for m in range(a,b):
for lv in dp[a][m]:
for rv in dp[m+1][b]:
for t in range(0,7):
mv=calc(lv,rv,t)
if mv==99999999:
continue
ss="("+dp[a][m][lv]+itb[t]+dp[m+1][b][rv]+")"
if len(ss)>256:
continue
if not mv in dp[a][b]:
dp[a][b][mv]=ss
else:
if len(ss)<len(dp[a][b][mv]):
dp[a][b][mv]=ss
upl={}
for v in dp[a][b]:
for t in range(1,50):
ss="("+"-~"*t+dp[a][b][v]+")"
mv=v+t
if len(ss)>256:
continue
if not mv in upl:
upl[mv]=ss
else:
if len(ss)<len(upl[mv]):
upl[mv]=ss
for t in range(1,50):
ss="("+"~-"*t+dp[a][b][v]+")"
mv=v-t
if len(ss)>256:
continue
if not mv in upl:
upl[mv]=ss
else:
if len(ss)<len(upl[mv]):
upl[mv]=ss
for mv in upl:
if mv>114514*5:
continue
ss=upl[mv]
if len(ss)>256:
continue
if not mv in dp[a][b]:
dp[a][b][mv]=ss
else:
if len(ss)<len(dp[a][b][mv]):
dp[a][b][mv]=ss
print("FIN",a,b,len(dp[a][b]))
li=[]
for x in dp[0][5]:
it=dp[0][5][x]
li.append((x,it))
li.sort()
for x in li:
print(x)
流程:编译ustc.cpp后,执行getinfo.py,将信息输出到pos文件。
手动运行cpp程序,手动复制9个坐标到send.py,得到flag
- ustc.cpp
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<queue>
#include<bitset>
#include"anti.h"
//extern "C"
//{
// #include "finders.h"
// #include "generator.h"
//}
using namespace std;
template<typename T>
inline void read(T& s)
{
s=0;int f=1;char c=getchar();
while(c<'0' || c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0' && c<='9'){s=s*10+c-'0';c=getchar();}
s*=f;
}
long long rmod(long long a,long long b)
{
long long c=a%b;
if(c<0) return c+b;
return c;
}
int tpxx[20],tpyy[20];
typedef bitset<(1<<20)> bs2;
bitset<(1<<20)> anti(int x,int y)
{
bitset<(1<<20)> ret;
int fx=x;
int fy=y;
if(fx<0) fx-=31;
if(fy<0) fy-=31;
fx/=32;
fy/=32;
int px=x-32*fx;
int py=y-32*fy;
for(int s=0;s<(1<<20);s++)
{
mclib mc(s);
for(int i=4;i<=4;i++)
{
if(ret[s]==1)
break;
rrandom rd(mc.getsed(i,fx,fy));
for(int j=0;j<16;j++)
{
int rdx=(rd.nexti()*((1<<j)-1)+fx+1)&15;
int rdy=(rd.nexti()*((1<<j)-1)+fy+1)&15;
if(rdx!=(px&15)) continue;
if(rdy!=(py&15)) continue;
ret[s]=1;
break;
}
}
}
return ret;
}
int getison(int x,int y,ull sed)
{
mclib mc(sed);
int ckx=x/32;
int cky=y/32;
rrandom rd(mc.getsed(4,ckx,cky));
for(int i=0;i<16;i++)
{
int rdx=rmod((rd.nexti()*((1<<i)-1)+ckx+1),48);
int rdy=rmod((rd.nexti()*((1<<i)-1)+cky+1),48);
//cout<<rdx<<' '<<rdy<<endl;
if(rdx!=(x&31)) continue;
if(rdy!=(y&31)) continue;
cout<<"HIT "<<i<<' '<<rdx<<' '<<rdy<<endl;
return 1;
}
return 0;
}
int n=0;
int xx[100]={-248,-177,148,3,71,111,44,22,134,303,320,370};
int yy[100]={-18,-73,9,38,132,142,139,179,245,229,245,256};
int fkx[100],fky[100];
bs2 q;
vector<ull>alns;
int main()
{//OBS
// cout<<getison(1,34,-5780188730042453408ll)<<endl;
// cout<<getison(1,34,181391687578208ll)<<endl;
freopen("pos","r",stdin);
cin>>n;
n=min(n,64);
for(int i=0;i<n;i++)
{
cin>>xx[i]>>yy[i];
}
for(int i=0;i<n;i++)
{
fkx[i]=xx[i];
if(fkx[i]<0) fkx[i]-=31;
fky[i]=yy[i];
if(fky[i]<0) fky[i]-=31;
fkx[i]/=32;
fky[i]/=32;
// cout<<i<<' '<<xx[i]<<' '<<yy[i]<<' '<<fkx[i]<<' '<<fky[i]<<endl;
}
q=~q;
for(int i=0;i<n;i++)
{
q&=anti(xx[i],yy[i]);
cout<<"FIN"<<i<<endl;
flush(cout);
}
//ull x=0;
for(int i=0;i<(1<<20);i++)
if(q[i])
{
// x=i;
alns.push_back(i);
cout<<"LOCATED "<<i<<endl;
flush(cout);
}
//return 0;
// alns.push_back(684640);
int cnt=0;
ull fsd=0;
for(auto x:alns)
{
for(ull i=0;i<(1<<28);i++)
//for(ull i=172988593;i<=172988593;i++)
{
if ((i&((1<<24)-1))==0)
{
cout<<"NT"<<i<<endl;
flush(cout);
}
mclib mc(x+(i<<20));
// cout<<(x+(i<<20))<<endl;;
bool afg=1;
for(int j=0;j<n && afg;j++)
{
bool fg=0;
for(int ti=4;ti<=4;ti++)
{
if(fg==1)
break;
// cout<<"FF"<<j<<' '<<xx[j]<<' '<<yy[j]<<' '<<fkx[j]<<' '<<fky[j]<<endl;
rrandom rd(mc.getsed(ti,fkx[j],fky[j]));
for(int tj=0;tj<16;tj++)
{
// cout<<"FF"<<j<<' '<<xx[j]<<' '<<yy[j]<<' '<<fkx[j]<<' '<<fky[j]<<endl;
int rdx=rmod((rd.nexti()*((1<<tj)-1)+fkx[j]+1),48);
int rdy=rmod((rd.nexti()*((1<<tj)-1)+fky[j]+1),48);
// cout<<"RD: "<<tj<<' '<<rdx<<' '<<rdy<<endl;
if(rdx!=(xx[j]&31)) continue;
if(rdy!=(yy[j]&31)) continue;
fg=1;
break;
}
}
// cout<<j<<' '<<xx[j]<<' '<<yy[j]<<' '<<fg<<endl;
afg&=fg;
}
if(afg==1)
{
cout<<"FOUND"<<x+(i<<20)<<endl;
fsd=x+(i<<20);
flush(cout);
}
}
if(fsd==0)
continue;
int ckl=16777216;
int mdl=ckl+ckl/2;
cout<<"SEED "<<fsd<<endl;
for(int lst=0;lst<9;lst++)
{
ull jsd=(fsd<<3)|lst;
if(lst==8)
jsd=fsd;
mclib mc(jsd);
for(int cx=0;cx<5;cx++)
{
for(int cy=0;cy<5;cy++)
{
for(int i=5;i<=5;i++)
{
rrandom rd(mc.getsed(i,cx,cy));
for(int j=0;j<2;j++)
{
int rdx=rmod((rd.nexti()*((1<<j)-1)+cx+1),mdl);
int rdy=rmod((rd.nexti()*((1<<j)-1)+cy+1),mdl);
if(j==0) continue;
if (rdx<ckl && rdy<ckl)
{
cout<<"FLAG: "<<lst<<' '<<cx*ckl+rdx<<' '<<cy*ckl+rdy<<endl;
tpxx[lst]=cx*ckl+rdx;
tpyy[lst]=cy*ckl+rdy;
}
}
}
}
}
flush(cout);
}
for(int i=0;i<9;i++)
printf("(%d,%d),\n",tpxx[i],tpyy[i]);
}
return 0;
}
- anti.h
typedef unsigned long long ull;
struct rrandom
{
ull multip=0x5DEECE66D;
ull addp=0xB;
ull last=0;
ull mask=(1ll<<48)-1;
void init(ull sed)
{
last=(sed^multip)&mask;
}
int nexti()
{
last=(last*multip+addp)&mask;
return last>>(48-32);
}
int next()
{
last=(last*multip+addp)&mask;
return last>>(48-31);
}
int nextint(int x)
{
return next()%x;
}
rrandom(ull sed=0)
{
init(sed);
}
};
struct mclib
{
ull sed;
//ull mu1=341873128712;
//ull mu2=132897987541;
void init(ull x)
{
sed=x;
}
mclib(ull x=0)
{
init(x);
}
ull getsed(int p,ull a,ull b)
{
return sed^(p+0x6E5D5AF15FA1280Bull*a+0xE9716B1CE6339E6Cull*b);
}
};
- getinfo.py
import requests as rqs
import json
jb=rqs.Session()
jb.headers.update({"Cookie": "session=114514:1919810"})
def mkreq(met,dat):
dat["token"]="114514:1919810"
r=jb.post("http://202.38.93.111:10169/api/"+met,params=dat)
#r=jb.post("http://localhost:8088/api/"+met,params=dat)
return r.text
def reset():
mkreq("reset",{})
#print()
def getchunk(ckx,cky):
rt=json.loads(mkreq("state",{"x":ckx*32,"y":cky*32}))
return rt["materials"]
def domine(mx,my):
rt=json.loads(mkreq("damage",{"x":mx,"y":my,"material":"FLAG"}))
reset()
gl=[]
for a in range(0,6):
#print(len(gl))
for b in range(0,6):
mif=getchunk(a,b)
for x in range(32):
for y in range(32):
#print(mif[x][y])
if mif[x][y]=="OBSIDIAN":
gl.append((a*32+x,b*32+y))
print(len(gl))
for a,b in gl:
print(a,b)
- send.py
import requests as rqs
import json
import _thread
import time
jb=rqs.Session()
jb.headers.update({"Cookie": "session=114514:1919810"})
def mkreq(met,dat):
dat["token"]="114514:1919810"
r=jb.post("http://202.38.93.111:10169/api/"+met,params=dat)
#r=jb.post("http://localhost:8088/api/"+met,params=dat)
return r.text
def reset():
print(mkreq("reset",{}))
def getchunk(ckx,cky):
rt=json.loads(mkreq("state",{"x":ckx*32,"y":cky*32}))
return rt["materials"]
def domine(mx,my):
print(mx,my)
rt=json.loads(mkreq("damage",{"x":mx,"y":my,"material":"FLAG"}))
print(rt)
mnl=[(61746934,68779701),
(75170139,3690429),
(76791398,2344681),
(68439752,49624564),
(82400664,27808754),
(68220730,66468796),
(70938717,82993007),
(54979585,67433954),
(78880385,47709289)]
for i in range(0,8):
_thread.start_new_thread( domine, mnl[i] )
time.sleep(0.5)
reset()
while 1:
pass
- MITM1.py
from pwn import *
from Crypto.Cipher import AES
from hashlib import sha256
import os
from hashlib import sha256
from utils import *
import time
#r=process("python3 MITM1.py",shell=True)
r=remote("202.38.93.111",10041)
print(r.recv())
r.send(b"114514:1919810\n")
time.sleep(1)
r.send(b"1\n")
time.sleep(1)
def genmess(nm,et,fg=b"flxgagasdfddd0123456789abcdef0123456789abcdef"):
return
nm=bytes.fromhex(nm)
et=bytes.fromhex(et)
msg = b"Thanks " + nm + b" for taking my flag: " + fg + et
plaintext = msg + sha256(msg).digest()
plaintext=pad(plaintext)
print(plaintext)
print(plaintext.hex())
print(len(plaintext))
def doreq(P,M):
if P=='A':
r.send(b"Alice\n")
r.send(M[0].encode()+b"\n")
r.send(M[1].encode()+b"\n")
while True:
x=r.recv().decode()
#print(x)
if not "encrypted" in x:
continue
x=x.strip().split(':')[-1].strip()
if len(x)==0:
x=r.recv().decode().strip()
#print(x)
return x
if P=='B':
r.send(b"Bob\n")
#print(M)
r.send(M.encode()+b"\n")
while True:
x=r.recv().decode()
#print(x)
if (not "Thanks" in x) and (not "problem" in x):
continue
if "Thanks" in x:
return 1
return 0
#flag:32+13 = 45
#32-127
def genext(suf):
ret="00"*(48-len(suf))
ret+=sha256((suf+("\x00"*(48-len(suf)))).encode()).digest().hex()
ret+="10"*16
return ret
def genname(nt):
return "00"*(80-28+nt+3)
def tryn(nowc,okc):
gl=len(okc)
quen=genname(gl+1)
qext=genext(nowc+okc)
genmess(quen,qext)
mess=doreq('A',(quen,qext))
#print("MESSA: ",mess)
res=doreq('B',mess[8*32:15*32])
print(res)
return res
act=[chr(x) for x in range(1,128)]
nowpx=""
for i in range(45):
for x in act:
#print(x,end='')
#print(x)
rl=tryn(x,nowpx)
if rl==1:
nowpx=x+nowpx
break
print("\n")
print("OK",nowpx)
- MITM3(2).py 其中2的差异在代码中注释已写明。
from pwn import *
from Crypto.Cipher import AES
from hashlib import sha256
import os
from hashlib import sha256
from utils import *
import time
import random
import os
#r=process("python3 MITM3.py",shell=True)
r=remote("202.38.93.111",10041)
print(r.recv())
r.send(b"11451:1919810\n")
time.sleep(1)
r.send(b"3\n") #MITM2.py: r.send(b"3\n")
time.sleep(1)
BLS=150
def gencrc128(crc):
crc^=((1 << 128) - 1)
crc = (crc >> 1) ^ (0xB595CF9C8D708E2166D545CF7CFDD4F9 & -(crc & 1))
return crc^((1 << 128) - 1)
def sbcsc(msg,key=b"aq2rVxPq9adcUICm"):
cz=hmac_crc128(key,b"\x00"*len(msg))
return xor(hmac_crc128(key,msg),cz)
def genmess(nm,et,fg=b"flagflxgflxgflxgflxgflxgflxgflxgflxgflxgflxgffffffllllllxg"):
return
nm=bytes.fromhex(nm)
et=bytes.fromhex(et)
msg = b"Thanks " + nm + b" for taking my flag: " + fg + et
plaintext = msg + sha256(msg).digest()
plaintext=pad(plaintext)
print(plaintext)
print(plaintext.hex())
print(len(plaintext))
def doreq(P,M):
if P=='A':
r.send(b"Alice\n")
r.send(M[0].encode()+b"\n")
r.send(M[1].encode()+b"\n")
while True:
x=r.recv(409600).decode()
#print(x)
if not "encrypted" in x:
continue
x=x.strip().split(':')[-1].strip()
if len(x)==0:
x=r.recv(409600).decode().strip()
#print(x)
while True:
xx=r.recv(409600,0.1).strip()
if len(xx)==0:
break
x+=xx.decode().strip()
#print(x)
if "Whom" in x:
x=x[:x.find('\nWhom')]
return x
if P=='B':
r.send(b"Bob\n")
#print(M)
r.send(M.encode()+b"\n")
while True:
x=r.recv(409600).decode()
#print(x)
if (not "Thanks" in x) and (not "problem" in x):
continue
if "Thanks" in x:
return 1
return 0
#flag:32+13 = 45
# 48+10=58
#32-127
def genext(suf):
ret="00"*(64-len(suf))
ret+="00"*16
return ret
PB=b""
def genblo():
global PB
#PB=os.urandom(3*16*BLS)
PB=b"\x00"*(3*16*BLS)
return PB.hex()+"00"*16
#myl=""
#for i in range(BLS):
# myl+=("%02x"%((123*i+7)%256))*16+("%02x"%((114*i+3)%256))*16+("%02x"%((514*i+6)%256)*16)
#return myl
def genname(nt):
return "00"*(96-28+nt+6)#MITM2.py: return "00"*(96-28+nt+24)
def gbk(bts,bid):
return bts[bid*16:(bid+1)*16]
def getxxj(vl,msl,cv):
rms=0
#print(cv)
#print(bin(cv))
for i in range(128):
if ((cv>>i)&1)==0:
continue
#print(vl[i])
cv^=vl[i]
rms^=msl[i]
#print(cv)
assert cv==0
return rms
def getrb(mess,i,v):
if v==0:
return gbk(mess,15+3*i)+gbk(mess,16+3*i)+gbk(mess,17+3*i)
return gbk(mess,16+3*i)+gbk(mess,15+3*i)+gbk(mess,17+3*i)
def tryn(okc):
gl=len(okc)
quen=genname(gl+1)
qext=genext("g"+okc)
quxx=genblo()
genmess(quen,qext+quxx)
mess=doreq('A',(quen,qext+quxx))
#print(mess)
mess=bytes.fromhex(mess)
civ=mess[:16]
mess=mess[16:]
yx=[]
for i in range(BLS):
#15+3*i 16+3*i 17+3*i
fum=gbk(PB,0+3*i)+gbk(PB,1+3*i)+gbk(PB,2+3*i)
gueorc=sbcsc(fum+b"\x00"*(16*(3*BLS+15-17-3*i)))
bl1m=xor(gbk(PB,1+3*i),xor(gbk(mess,14+3*i),gbk(mess,15+3*i)))
bl2m=xor(gbk(PB,0+3*i),xor(gbk(mess,14+3*i),gbk(mess,16+3*i)))
bl3m=xor(gbk(PB,2+3*i),xor(gbk(mess,15+3*i),gbk(mess,16+3*i)))
fkm=bl1m+bl2m+bl3m+b"\x00"*(16*(3*BLS+15-17-3*i))
myx=int.from_bytes(gueorc,"big")^int.from_bytes(sbcsc(fkm),"big")
#print(bl1m+bl2m+bl3m,myx)
yx.append(myx)
rmsk=[]
rv=[]
#doreq('B',(civ+mess[:15*16]+gbk(mess,16)+gbk(mess,15)+mess[17*16:]).hex())
#print(yx)
#print(int.to_bytes(yx[0],16,"big").hex())
for i in range(BLS):
rmsk.append((1<<i))
rv.append(yx[i])
for i in range(128):
myj=-1
for j in range(i,BLS):
if ((rv[j]>>i)&1)==1:
myj=j
break
#print(i,myj)
#if myj==-1:
# print("ERR",i)
if i!=myj:
rv[i],rv[myj]=rv[myj],rv[i]
rmsk[i],rmsk[myj]=rmsk[myj],rmsk[i]
for j in range(i+1,BLS):
if ((rv[j]>>i)&1)==1:
rv[j]^=rv[i]
rmsk[j]^=rmsk[i]
#for j in range(0,BLS):
# print((rv[j]>>74)&1,end='')
#print()
#print(rv[i])
#for i in range(BLS):
# print(rv[i])
for myc in act:
gec=(myc+okc).encode()
fum=gec+b"\x00"*(64-len(gec))
gueorc=sbcsc(fum+b"\x00"*((3*BLS+1+1)*16))
bl1m=xor(xor(gbk(fum,3),gbk(mess,12)),gbk(mess,9))
bl2m=xor(xor(gbk(fum,0),gbk(mess,9)),gbk(mess,13))
bl3m=gbk(fum,1)
bl4m=gbk(fum,2)
bl5m=xor(gbk(mess,12),gbk(mess,13))
guefrc=sbcsc(bl1m+bl2m+bl3m+bl4m+bl5m+b"\x00"*(16*(3*BLS+1)))
ndc=int.from_bytes(gueorc,"big")^int.from_bytes(guefrc,"big")
uxj=getxxj(rv,rmsk,ndc)
bms=mess[:10*16]+gbk(mess,13)+gbk(mess,10)+gbk(mess,11)+gbk(mess,12)+gbk(mess,14)
assert len(bms)%16==0
for i in range(BLS):
bms+=getrb(mess,i,(uxj>>i)&1)
bms+=gbk(mess,15+3*BLS)
bms+=gbk(mess,16+3*BLS)
bms+=gbk(mess,17+3*BLS)
ffv=(civ+bms).hex()
res=doreq('B',ffv)
#print(res)
if res:
return myc
print(myc,end="")
#print("MESSA: ",mess)
#res=doreq('B',mess[8*32:15*32])
#print(res)
assert False
act=[chr(x) for x in range(1,128)]
nowpx=""
for i in range(58):#MITM2.py: for i in range(40):
rl=tryn(nowpx)
nowpx=rl+nowpx
print("\n")
print("OK",nowpx)
- MI.py
import math
sb=[]
jxl="0123456789abcdef"
def dfs(nows,nowl):
global sb
if nowl==0:
sb.append(nows.encode())
return
for i in jxl:
dfs(i+nows,nowl-1)
def genstrl(nl):
global sb
sb=[]
dfs("",nl)
return sb
def calcs(ma,mb):
ssl=1
jl=genstrl(ssl+1)
soso=[0]*256
for sa in jl:
for sb in jl:
va=int.from_bytes(sa,"big")
vb=int.from_bytes(sb,"big")
vn=ma*va+mb*vb
tiv=((vn>>(8*ssl))&255)
soso[tiv]+=1
xxs=0
qj=len(jl)*len(jl)
for x in soso:
if x==0:
continue
xxs+=(x/qj)*math.log(qj/x)
return xxs
#print(calcs(14,1))
miv=0
mip=(0,0)
ss=[]
for xa in range(1,64):
for xb in range(1,64):
vv=calcs(xa,xb)
print(xa,xb,vv)
ss.append((vv,xa,xb))
if vv>miv:
miv=vv
mip=(xa,xb)
print(mip,miv)
ss.sort()
#print(ss)
- sol.py
from pwn import *
import time
from gmpy2 import *
#r=process("python3 OT.py",shell=True)
r=remote("202.38.93.111",10031)
print(r.recv())
r.send(b"114514:1919810\n")
CCA=43
CCB=61
def sendv(x):
r.send(str(x).encode()+b"\n")
def check(vl,sa,sb,ll=0):
va=int.from_bytes(sa,"big")
vb=int.from_bytes(sb,"big")
ckv=(va*CCA+vb*CCB)#%(2**(8*ll))
ckx=vl#%(2**(8*ll))
return ckv==ckx
def facheck(vl,va,vb):
ckv=(va+vb)>>8
ckv&=255
return ckv==vl
def tryans(smv):
lasl=[(b"",b"",0,0)]
nowl=[]
stl="0123456789abcdef"
print("CALC",smv//n)
for i in range(128):
for nowv in lasl:
nowa,nowb,nowia,nowib=nowv
ndckv=(smv>>(8*i))&255
for ca in stl:
na=ca.encode()+nowa
fav=ord(ca)*256*CCA+nowia
for cb in stl:
fbv=ord(cb)*256*CCB+nowib
if facheck(ndckv,fav,fbv):
nb=cb.encode()+nowb
nowl.append((na,nb,fav>>8,fbv>>8))
lasl=nowl
nowl=[]
#print(lasl)
if len(lasl)==0:
break
if i>30:
print(i,len(lasl))
if len(lasl)==0:
return []
print(len(lasl))
for x in lasl:
nowa,nowb,_,__=x
if check(smv,nowa,nowb):
nowl.append((int.from_bytes(nowa,"big"),int.from_bytes(nowb,"big")))
print(len(nowl))
hoho=[]
for xxx in nowl:
vm0,vm1=xxx
dp=(c0-vm0)%n
cvv=pow(dp,e,n)
if cvv==vv:
print("FOUND:")
print(vm0)
print(vm1)
hoho.append((vm0,vm1))
return hoho
time.sleep(1)
x=r.recv().decode()
print(x)
xl=x.split('\n')
e=65537
for l in xl:
if len(l)==0:
continue
a,b=l.split('=')
a=a.strip()
b=b.strip()
if len(b)==0:
continue
if a=='n':
n=int(b)
if a=='x0':
x0=int(b)
if a=='x1':
x1=int(b)
print(n,e,x0,x1)
D=x0-x1
vv=(n-D)*invert(1+pow(CCA*invert(CCB,n)%n,e,n),n)%n
v=(vv+x0)%n
sendv(v)
time.sleep(1)
x=r.recv().decode()
print(x)
xl=x.split('\n')
for l in xl:
if len(l)==0:
continue
a,b=l.split('=')
a=a.strip()
b=b.strip()
if len(b)==0:
continue
if a=='m0_':
c0=int(b)
if a=='m1_':
c1=int(b)
jbl=(CCA*c0+c1*CCB)%n
print(jbl)
for i in range((CCA+CCB)//4,CCA+CCB):
ss=tryans(jbl+i*n)
r.interactive()