Files
hackergame2020-writeups/players/ranwen/wp.md
T
2020-11-07 21:03:42 +08:00

1785 lines
43 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Hackergame 2020 Writeups-ranwen
## 0x00 签到
改HTML step改成1,提交获取flag
## 0x01 猫咪问答++
第一个暴力尝试
第二个查RFC1149
第三个显然是Teeworlds(多年老玩家本人)
第四个随便找个带街景的地图数一下
第五个,官方的存档站暂时502了,但是archive.is有,直接找即可
## 0x02 2048
点开所有js,肉眼审查一下,显然获胜判断在html_actuator.js,然后找到`/getflag?my_favorite_fruit=banana`的api得到flag
## 0x03 一闪而过的 Flag
用WSL运行,就不会退出了
## 0x04 从零开始的记账工具人
写了好久的py自动解析大写数字(悲) (附件1)
## 0x05 超简单的世界模拟器
第一问随手在Wikipedia上抄一个能平移的就好了
第二问试了好半天,最后没办法,写了个模拟器fuzzing了一下 (附件2)
## 0x06 从零开始的火星文生活
先拉出来了第一句话在百度搜索。在房天下找到了一个网页,百度爬的是乱码,点进去是正确的。
比对了一下,正好是乱码的两个字对应一个字。
拿出来连续两个字,搜到了`https://www.v2ex.com/t/421212`,直接运行命令得到flag
## 0x07 自复读的复读机
google搜索 `reverse quine python`,稍作修改就能过第一问(去掉回车符)
```python
x='x=%r;print((x%%x)[::-1],end="")';print((x%x)[::-1],end="")
```
第二问也是稍作修改
```python
x='x=%r;print(__import__("hashlib").sha256((x%%x).encode()).hexdigest(),end="")';print(__import__("hashlib").sha256((x%x).encode()).hexdigest(),end="")
```
得到flag
## 0x08 233 同学的字符串工具
第一问是毒瘤Unicode问题 字符`fl`(chr(64258))的upper是`FL`,然后交一个`flag`就可以了
第二问手动学习一下UTF-7编码。手动用UTF-16构造一个Base64结果。建议只编码一个字符,注意大小端序问题
`+AGY-lag`即可
## 0x09 233 同学的 Docker
下载Docker,查看Dockerfile,显然是利用overlayfs的一些特性
直接跑到/var/lib/docker 中 `find flag.txt` 即可
## 0x0A 从零开始的 HTTP 链接
先挂个知乎提问`https://www.zhihu.com/question/428175951` 各位猜猜关注的人里头有多少是组委会的
其实很简单,先找个支持0端口的开http的东西。本人用的是python的socket。
本来直接发了个raw http包,但是发现真是个web,有点麻烦,于是改成了一个反代。
注意,由于有些NAT设备的要求,非公网ip设备没法连0端口。因此我找了个vps做反代。 (附件3)
## 0x0B 来自一教的图片
随便找个 图片频域信息提取工具,扔进去得到flag
## 0x0C 超简陋的 OpenGL 小程序
最开始想着改这两个文件,不过发现好像不太奏效。
大力出奇迹:下载一个OpenGL调试程序(本人下了个RenderDoc),之后随便截个帧。能点的按钮都xjb点一下:flag出现了!
## 0x0D 生活在博弈树上
打开IDA 用了gets 查看变量在内存的分布,第一问显然是多输入一点(大概150个)东西,溢出到success变量后将success搞成true,然后得到flag
第二问似乎是个构造rop链的pwn题,不过本人完全不会bin题,也没空学(全场bin题仅有150分)
## 0x0E 来自未来的信笺
显然暗示的是GitHub北极备份计划
照着`https://github.com/github/archive-program/blob/master/GUIDE_zh.md`做,将每个二维码搞成一个bin后连接,就可以得到一个.xz文件,解压repo得到flag
由于市面上大部分解二维码的软件对bin的支持很差,所以本题浪费了很长时间。建议直接搜索`zbar bin`以节省时间。
## 0x0F 狗狗银行
测试发现,所有利息计算居然是四舍五入
于是构造一下钱:每张信用卡借2050元,每张储蓄卡存167元。稍微计算一下发现这样显然是赚的。
多开几张卡,然后每隔几天倒腾一下避免信用卡利息上升,大量发包即可刷钱得到flag。
## 0x10 超基础的数理模拟器
显然是解析积分然后计算
尝试全本地,但是cookies处理好像有点问题,索性全用浏览器
可以用`header editor`浏览器插件屏蔽LaTex渲染,然后只用解析源码就可
Chromium的Console提供了一个叫"活动表达式"的东西,可以每次页面载入完后运行JS,利用这个每次刷新提交
写了个py处理latex,之后就是计算积分了
本人直接大力使用了`https://zh.numberempire.com/definiteintegralcalculator.php`来做,就是算了几十个后要换下IP,很痛苦。
之后在本地用python开了个webserver,积分页面请求这个webserver,python再请求网站计算结果后返回。
(附件4)
## 0x11 永不溢出的计算器
好玩的数论题
看到求根号,考虑服务器是怎么计算的。
第一个想到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
## 0x12 超精巧的数字论证器
注意到`~-x`是很重要的单目运算,可以让x减1。因此可以大力区间dp只处理双目运算,然后特判这种单目运算
本地先打表,之后直接提交即可 (附件5)
## 0x13 超自动的开箱模拟器
先来个算法链接 `https://www.zhihu.com/question/27050108/answer/35041211`
之后只要写出这个bf即可。
本人看到后,直接上StackOverflow找到了个bf中`if(a>=b)`的实现,之后手动进行了一下内存管理,大力写了一段bf,多试几次得到flag。(代码没存)
## 0x14 超简易的网盘服务器
进入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的,不过后续是借助浏览器完成的)
## 0x15 超安全的代理服务器
第一问:
```bash
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
```bash
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作反代,实在是没想到是个这。差评
## 0x16 超迷你的挖矿模拟器
心疼出题人土老师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)
## 0x17 中间人
三道题都要先拉出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)
## 0x18 不经意传输
第一问: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$ $V=v-x0$
则有:$m0\_ \equiv m0+V^d \pmod N$ $m1\_ \equiv m1+(V+D)^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)
## 0xFE 感想
题出的好!难度适中,覆盖知识点广,题目又着切合实际的背景,解法比较自然。给出题人点赞 !
明年一定再来。
## 0xFF 附件
### 附件1
```python
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)
```
### 附件2
```cpp
//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;
}
```
### 附件3
```python
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()
```
### 附件4
- web.js
```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
```python
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)
```
### 附件5
```python
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)
```
### 附件6
流程:编译ustc.cpp后,执行getinfo.py,将信息输出到pos文件。
手动运行cpp程序,手动复制9个坐标到send.py,得到flag
- ustc.cpp
```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
```cpp
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
```python
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
```python
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
```
### 附件7
- MITM1.py
```python
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的差异在代码中注释已写明。
```python
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)
```
### 附件8
- MI.py
```python
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
```python
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()
```