Add old writeups

This commit is contained in:
Mia Steinkirch 2019-10-29 19:00:15 -07:00
parent 06365916d8
commit 1b774c9add
89 changed files with 4052 additions and 688 deletions

View file

@ -0,0 +1,53 @@
import socket
PORTc = 1432
PORTm = 1434
PORTw = 1433
HOST = 'wildwildweb.fluxfingers.net'
def peace_pipe():
""" Get the magic message from some user to calculate rm """
# create sockets
sm = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sw = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# connect to w
sw.connect((HOST, PORTw))
sw.recv(4096)
sw.send(b'makawee')
sw.recv(4096)
sec = sw.recv(4096)
tw = sec.split("did this:")[1].split("\n")[1].strip()
print "\nMagic from w to m: " + tw
# connect to m
sm.connect((HOST, PORTm))
sm.recv(4096)
sm.send(b'mrblack')
sm.recv(4096)
sec = sm.recv(4096)
tm = sec.split("did this:")[1].split("\n")[1].strip()
print "\nMagic from m to w: " + tm
# send w's magic to m's
sm.send(tw)
print sm.recv(4096)
# send m's magic to get the token
sw.send(tm)
token = sw.recv(4096)
token = token.split('\n')[1].strip()
print "Token is: " + token
# finally, send token back to m
sm.send(token)
print sm.recv(4096)
sm.close()
sw.close()
if __name__ == "__main__":
peace_pipe()

View file

@ -0,0 +1,257 @@
# The Peace Pipe at Hack.lu's Final CTF 2014
## Understanding the Problem
The problem starts with this weird story:
After a long day, you sit around a campfire in the wild wild web with a few Sioux you met today.
To celebrate friendship one of them takes out his wooden peace pipe and minutes later everyone seems to be pretty dizzy.
You remember that their war chief "Makawee" started something to say about a secret tipi filled with fire-water (the good stuff). But when he noticed your interest he immediately stopped talking.
You recall that "Makawee" spoke with "Wahkoowah" about that issue, but it ended with a fight.
Since then Makawee wouldn't talk to Wahkoowah anymore. While they argued "Chapawee" wrote something down.
Maybe you can exploit their dizzyness to find out the location of the tipi.
Then it gives us three *ports* in the *host*. With the first one, we talk to **Chapawee**:
wildwildweb.fluxfingers.net 1432
With the second, we talk to **Wankoowah**:
wildwildweb.fluxfingers.net 1433
Finally, with the third, we talk to **Makawee**:
wildwildweb.fluxfingers.net 1434
It was obvious that this game was about fooling our fellow *stoned* native-Americans.
### A Dialogue with Chapawee
When we *netcat* to **Chapawee** he answers:
```sh
$ nc wildwildweb.fluxfingers.net 1432
Hi I'm Chapawee. I know the truth about the stars
Say stars for more
```
We answer *stars* and get a funny menu:
```sh
I can tell you the truth about
* constellation
* namestar [starname] [key_of_truth] Adds a public key to a user.
Existing users cannot be
overwritten. Input is
[a-f0-9]{1,700}.
* showstar [starname] Reads the public key from the
database.
```
The first option *constellation*, shows a very interesting scheme:
![cyber](http://i.imgur.com/OzVjrVh.png)
Choosing the options **namestar** we are able to pick a (new) name to add a key. Picking the option **showstar** we are able to see the key for some name (for example, for Wahkoowar, Makawee, or any new name we had added before).
So, from the above scheme, we know:
1. How a **message** (t) is created with someone's public key, a **random rational number** (r_w), and a given **modulo number** (p). The only unknown here is r_w, which is a rational number (Q). This mean that any plans to brute force the messages wouldn't work (however, if r_w was an integer, this task could be achieved).
2. Everyone has a private key that is modulo p. We never learn anything about anyone's private keys. We just know that they could be of the order of p (which is a really large number, ~1E2048).
3. Wahkoowah and Makawee have a shared secret key. The way they share this key without knowing each other's private key is by this tricky transformation:
![cyber](http://i.imgur.com/TwxShK9.jpg)
Notice that we can move the multiplications' modulo operation to the end, due to [this propriety](http://en.wikipedia.org/wiki/Modular_arithmetic#Congruence_relation).
In conclusion, all we need to do is to convince Wahkoowah that we are Makawee (by telling him we are Makawee, so he can use his public key, and by sending him a correct *t_m*). If this works, he will give us a token. Then, if we send this token to Makawee, we get our flag.
### A Dialogue with Wankoowah
Now, let's see what Wankoowah has to say:
```sh
$ nc wildwildweb.fluxfingers.net 1433
Hi, I'm Wahkoowah. Who are you? Too foggy...
```
We try a couple of possibilities to check the outputs:
```sh
$ nc wildwildweb.fluxfingers.net 1433
Hi, I'm Wahkoowah. Who are you? Too foggy...
noone
Hi noone
Cannot find it...
Ncat: Broken pipe.
$ nc wildwildweb.fluxfingers.net 1433
Hi, I'm Wahkoowah. Who are you? Too foggy...
makawee
Oh its you, Im so sorry. Can we talk now?
This is your key of truth
50e7e1957c1786a9442f0c9f372ec19f74f52839e9e38849b47438153f9d2483213a43ad2d988fab4a8707922060aaefe6504a70637596fbcf9d58362b23e5d5e2177fd4e919b80437bab51eda931e065b6d66fce343d7cb2b7c1ca26214792d461895095ae58354af0dec6e63869007e23835892f26aabc96fe3d9084a829b4d6c5b92c6f3e0dd9a70cbd5c72d6434f2b94d21c3b0c58a288c140642b813ffb1b632bc358b3a6af0124902acd8792202c848de7f9d5d98bee51ca69040c8a2457ad3fa6276d6510701b9a875df612e035322cad06579a0a11f5e7cb4ebb7b69171c38585fc0f4fe07b0c889442397029d05dc801026a0648d7aa8c847420e9c
With magic I did this:
922a7f4b150eb83eab929e2a44bcbbb45435851262a6e7b84d2777d995ffbc315a2e57a580f4982797b45efde6d30b493880ecea33fe26e6c8ff636b75b7cb3f647f0c6f606249bc48ef09bd20738cf472bf47c7f52b9e11afcefc1548155637b0d2054d37cd74301e534208408074938ae4e7b54ef50fa0a39cb090dd34de7a4040024ba2394bac62262ccda529d2d69effe24338f0ec1b842539d2b89b081fa77a266a7c9f62c25d2a1ee1af3da8054d79d87ae88da61b8333e1fc195d2957341458700a3be70c98e1a8ab35bfe527ff6a2f255c66d753d03c59404993f1ed295a722bf1d0241eec9c01efe06e3cd5b845e84de3d29de17f9b68351bdc2d65
We continue our conversation, right?
```
The *magic* is the message *t_w*, created with Makawee's public key. Wahkoowah then ask for *t_m*...
### A Dialogue with Makawee
Let's see what Makawee has to say:
```sh
$ nc wildwildweb.fluxfingers.net 1434
Hi, I'm, Makawee, and you are? Too bright here...
noone
noone ... do I know you?
Cannot find it...
Ncat: Broken pipe.
$ nc wildwildweb.fluxfingers.net 1434
Hi, I'm, Makawee, and you are? Too bright here...
wahkoowah
I dont talk to you anymore. That thing with my daughter...
Ncat: Broken pipe.
```
Mmmm, we need to make Makawee use Wankoowah's key without him knowing it!
Since Chapawee allows us to add keys to names, let's create some name with Wahkoowah's key (say "mrwhite") and send this to Makawee:
```sh
$ nc wildwildweb.fluxfingers.net 1432
Hi I'm Chapawee. I know the truth about the stars
Say stars for more
stars
I can tell you the truth about
* stars
* constellation
* namestar [starname] [key_of_truth] Adds a public key to a user.
Existing users cannot be
overwritten. Input is
[a-f0-9]{1,700}.
* showstar [starname] Reads the public key from the
database.
namestar mrwhite 218b783ec5676cbddd378ceb724820444599f22cdcfda0a5a195b3a8fbf4ab5c915703420ad3b84531c54b838b23858fb84fcaf04d4932d4b9ef861c7ae9b635c9d3f56dfb100aa47297afcd94df41efa9f5ecba6483c5328e43ec457027ee4efcecefa094a83945106d7da1878c1f47516c2f2578170eeb36955d8bd16e0d106f9e2effe9debff41e551db4ac2e87bc8a9378d8eadb042bee18f4ad72ab721833a27154a7318b8cbe6f98fb3c82da32d1688fdcdb718fb15d9d5e6276b037cef62d953c09b23ebe90d0b13f61cd1643e5e1b0a433d5e2522ec5a028817891b6df444e983e1e0ff2356044fea67c616dce6b4bd53b17ea8bc51ef816ab8f2d9e
Add the star to the sky...
Set the star for mrwhite: 218b783ec5676cbddd378ceb724820444599f22cdcfda0a5a195b3a8fbf4ab5c915703420ad3b84531c54b838b23858fb84fcaf04d4932d4b9ef861c7ae9b635c9d3f56dfb100aa47297afcd94df41efa9f5ecba6483c5328e43ec457027ee4efcecefa094a83945106d7da1878c1f47516c2f2578170eeb36955d8bd16e0d106f9e2effe9debff41e551db4ac2e87bc8a9378d8eadb042bee18f4ad72ab721833a27154a7318b8cbe6f98fb3c82da32d1688fdcdb718fb15d9d5e6276b037cef62d953c09b23ebe90d0b13f61cd1643e5e1b0a433d5e2522ec5a028817891b6df444e983e1e0ff2356044fea67c616dce6b4bd53b17ea8bc51ef816ab8f2d9e
```
Sending it to Makawee:
```sh
$ nc wildwildweb.fluxfingers.net 1434
Hi, I'm, Makawee, and you are? Too bright here...
mrwhite
mrwhite ... do I know you?
Disguise does not help
```
Oh no, the plan did not work! We can't send **exactly** Wahkoowah's key! We need to be even more tricky...
## Crafting a Solution
### Master in Disguising
Every key in this problem is given by *mudulus p*. This means that we have infinite values that map to the same original key. My first attempt was to multiply the original key by p, so that, when it receives the modulo operation, it circles once more returning to the original value.
It didn't work. The reason is that p is too large. When multiplied by the key (that is large itself) we loose precision and we don't go back to the original value. We need to keep the values in the same scale!
Let's take a look again at the way the messages are generated:
![cyber](http://i.imgur.com/Hz5uf7X.jpg)
We notice that the public key is exponentiated by r_m. It means that, if r_m is an even number, two values of the public key are mapped to the same value of the final message: +pubk and -pubk.
That's all we need! We are going to disguise Makawee by creating a *star* with the negative value of Wahkoowah's key.
### Automatizing the Process and getting the Flag!
All right, now we know how to make Wahkoowah and Makawee talk and how to get *t_m* and *t_w*. We are ready to generate the token that will lead us to the flag.
Notice again that since these messages are generated with random numbers, they will differ each time. However, we know from above that they carry unique information that leads to a common key (and the flag). I wrote the following script to automatize the process:
```python
import socket
PORTm = 1434
PORTw = 1433
HOST = 'wildwildweb.fluxfingers.net'
def peace_pipe():
""" Get the magic message from some user to calculate rm """
# create sockets
sm = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sw = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# connect to w
sw.connect((HOST, PORTw))
sw.recv(4096)
sw.send(b'makawee')
sw.recv(4096)
sec = sw.recv(4096)
tw = sec.split("did this:")[1].split("\n")[1].strip()
print "\nMagic from w to m: " + tw
# connect to m
sm.connect((HOST, PORTm))
sm.recv(4096)
sm.send(b'mrblack')
sm.recv(4096)
sec = sm.recv(4096)
tm = sec.split("did this:")[1].split("\n")[1].strip()
print "\nMagic from m to w: " + tm
# send w's magic to m's
sm.send(tw)
print sm.recv(4096)
# send m's magic to get the token
sw.send(tm)
token = sw.recv(4096)
token = token.split('\n')[1].strip()
print "Token is: " + token
# finally, send token back to m
sm.send(token)
print sm.recv(4096)
sm.close()
sw.close()
if __name__ == "__main__":
peace_pipe()
```
Running it leads us to the flag:
```sh
python 300_peace_pipe.py
Magic from w to m: 2f2f5d280871947836e9b5665986c1b75e732d88ae3d464b65d24ea7e41c33c491060379ac4f3dc4a7231f43d6a11b5bfd3a780d8ac46bd1a4cfd99ac041434cb82c5941f17e68a4f180101ece166a1b4da6ea32d62455bd7472892ed9b67fe2122e0b331048e4a11d98422f04ec3063a3652a0e1a90e13a740905bb3a22c9b5e39d1e0fa97f10bff34d76243b9211afd1131b0f6e33d4d99c8069c462677ce67401214c943fee13252060aa02b8b1525ed0af8c9aa5ad5dee64dbb0c275dd6147754c7dfaf3218caf35d7837925215a04bb315e91441306ef0d29f0da733b7e4ac92b500dc522de11c5f5af58248ed5f762b854f40f0adf4b681a937d17a1c0
Magic from m to w: e9eedf64931d5f77f5d061a0f411f9d385144f33fe1419905fdb24a0537cc205a7f99e083f37f98af8553795f1a71f83b7924620790845c3a48bb71a9b70a0f9e5ab95dda40ec4e229bc6a6cd146779de74b7237e42d01e2538c093407165afc79776bbd9bcdefa1d9af27a39f17610b4b9060c2b0ca5203457061facdc68257433253366937cef469261492ac81c177f42f10beea386ddfa09069a5fa2ae2e39a41eeecebdba622b79231cd5f206d0a70c71aa3eb5f706a16c99173f79f97e7f3408b544df556e3779f6d49441c04d33438b9604392f90bca6c2a8c3181b12ec5d492ef2184b9db69fdd1b6247150e3b55f8ee65d113c5350b4b097abadddc9
Bit more truth is missing
Token is: 5QAWhcwSaQicM8LitDGz6To69sBtsO8ASL27zxql8hW8aziveW0B0epJz2PKIFo/K4A=
I knew you are able to see IT. Lets get drunk, I tell you where
flag{FreeBoozeForEverone-Party!}
```

View file

@ -0,0 +1,337 @@
#!/usr/bin/env python
import random
import gmpy
import os
import asyncio
import base64
import shutil
import traceback
import tempfile
import argparse
import aiopg
import logging
import collections
import pyasn1_modules.rfc3447
import pyasn1.codec.ber.encoder
import concurrent.futures
TARGET_USERNAME = "deputies"
DB = {'database': 'wiener', 'user': TARGET_USERNAME}
ADMIN_NAME = "sheriff"
AUTH_KEYS_PATH = os.path.join(
"/", "home", TARGET_USERNAME, ".ssh", "authorized_keys")
EXECUTOR = concurrent.futures.ProcessPoolExecutor()
auth_keys_lock = asyncio.Lock()
logging.getLogger('asyncio').setLevel(logging.ERROR)
prng = random.SystemRandom()
messages = {
'welcome': ("Well if it isn't another one of those shave tails again. "
"Don't you dare think this is gonna be an easy job here, we "
"take no coffee boilers just so ya' know. If you're sure you "
"want to join our deputy ranks, just apply here. If you got "
"any problems just lemme know by typing 'h'."),
'access': ('Oh and you can find all lockers by going '
'to the "Secure Sheriff\'s Huddle" with the number 1427 on the '
'door and tell the doorman you are a "deputies". Of course you '
'are not a "sheriff"!'),
'new_private_key': ("Here is your locker code. Don't you dare loose it or "
"I'm gonna knock you galley west!"),
'new_public_key': "And that's your lock.",
'key_validity': ("Your locker code is only valid for 30 minutes. If you "
"don't need it, I'm gonna trash your lock, boy!"),
'new_username': ("I'm gonna call you %s from now on. I don't wanna hear "
"any bellyaching about it!"),
'get_public_get': "Here this is %s's lock. Why do you need it, hmm?",
'get_pubkey_query': "So whose lock do you wanna see? ",
'invalid_user': "Don't know him, get lost!",
'cmd_unknwown': "What? No way you get THAT!",
'unkown_error': "We seem to be having some problems here. We'll fix it.",
'help_prefix': "These are the questions you can ask me:",
}
def get_message(key, *params, with_newline=True):
nl = '\n' if with_newline else ''
return ((messages[key] % params) + nl).encode('utf-8')
#
# Actions
#
@asyncio.coroutine
def do_help(reader, writer, conn):
"""
Ask the sheriff for help. He might not react too friendly...
"""
writer.write(get_message('help_prefix'))
out = []
for key, handler in actions.items():
out.append("%s: %s" % (key, handler.__doc__.strip()))
writer.writelines([(s + '\n').encode("utf-8") for s in out])
@asyncio.coroutine
def do_register(reader, writer, conn):
"""
Get a lock and a locker code. This way you can also unlock the shared locker for everyone!
"""
uname, id_ = yield from new_username(conn)
priv_key, pub_key = yield from get_keypair(uname)
with (yield from auth_keys_lock):
with open(AUTH_KEYS_PATH, "ab") as f:
f.seek(0, 2)
f.write(pub_key + b'\n')
writer.write(get_message('new_private_key'))
writer.write(priv_key)
writer.write(get_message('new_public_key'))
writer.write(pub_key + b"\n")
writer.write(get_message('new_username', uname.lower()))
writer.write(get_message('key_validity'))
writer.write(get_message('access'))
cur = yield from conn.cursor()
try:
yield from cur.execute(
'UPDATE users SET public_key=%s, username=%s WHERE id=%s',
(pub_key.decode("utf-8"), uname, id_))
finally:
cur.close()
@asyncio.coroutine
def do_list(reader, writer, conn):
"""
Get a list of all guys that have locks.
"""
cur = yield from conn.cursor()
out = []
try:
yield from cur.execute('SELECT username FROM users')
for username, in (yield from cur.fetchall()):
out.append(("- %s\n" % username).encode("utf-8"))
finally:
cur.close()
writer.write(b"".join(out))
@asyncio.coroutine
def do_get_pubkey(reader, writer, conn):
"""
Get the lock for a particular guy. Why would you need that?
"""
writer.write(get_message('get_pubkey_query', with_newline=False))
uname = (yield from reader.readline()).decode("utf-8").strip().lower()
cur = yield from conn.cursor()
try:
yield from cur.execute(
'SELECT public_key FROM users WHERE username=%s',
(uname,))
result = yield from cur.fetchone()
finally:
cur.close()
if result:
pub_key, = result
writer.write(get_message('get_public_get', uname))
writer.write((pub_key + '\n').encode("utf-8"))
else:
writer.write(get_message('invalid_user'))
actions = collections.OrderedDict()
actions['h'] = do_help
actions['r'] = do_register
actions['l'] = do_list
actions['p'] = do_get_pubkey
#
# Helpers
#
@asyncio.coroutine
def new_username(conn):
cur = yield from conn.cursor()
try:
yield from cur.execute(
'INSERT INTO users DEFAULT VALUES RETURNING id')
new_id = yield from cur.fetchone()
new_user = 'user%d' % new_id
finally:
cur.close()
return new_user, new_id
def asn1_encode_priv_key(N, e, d, p, q):
key = pyasn1_modules.rfc3447.RSAPrivateKey()
dp = d % (p - 1)
dq = d % (q - 1)
qInv = gmpy.invert(q, p)
assert (qInv * q) % p == 1
key.setComponentByName('version', 0)
key.setComponentByName('modulus', N)
key.setComponentByName('publicExponent', e)
key.setComponentByName('privateExponent', d)
key.setComponentByName('prime1', p)
key.setComponentByName('prime2', q)
key.setComponentByName('exponent1', dp)
key.setComponentByName('exponent2', dq)
key.setComponentByName('coefficient', qInv)
ber_key = pyasn1.codec.ber.encoder.encode(key)
pem_key = base64.b64encode(ber_key).decode("ascii")
out = ['-----BEGIN RSA PRIVATE KEY-----']
out += [pem_key[i:i + 64] for i in range(0, len(pem_key), 64)]
out.append('-----END RSA PRIVATE KEY-----\n')
out = "\n".join(out)
return out.encode("ascii")
@asyncio.coroutine
def ssh_encode_pub_key(keypath, uname):
p = yield from asyncio.create_subprocess_exec(
"ssh-keygen", "-y", "-f", keypath, stdout=asyncio.subprocess.PIPE)
out = yield from p.stdout.read()
return out.strip() + b' ' + uname.encode("ascii")
def get_prime(size):
while True:
val = prng.getrandbits(size)
if gmpy.is_prime(val):
return val
def test_key(N, e, d):
msg = (N - 1) >> 1
c = pow(msg, e, N)
if pow(c, d, N) != msg:
return False
else:
return True
def create_parameters(size=2048):
p = get_prime(size // 2)
q = get_prime(size // 2)
N = p * q
phi_N = (p - 1) * (q - 1)
while True:
d = prng.getrandbits(size // 5)
e = int(gmpy.invert(d, phi_N))
if (e * d) % phi_N == 1:
break
assert test_key(N, e, d)
return N, e, d, p, q
@asyncio.coroutine
def get_keypair(uname):
loop = asyncio.get_event_loop()
params_coro = loop.run_in_executor(EXECUTOR, create_parameters)
N, e, d, p, q = yield from params_coro
priv_key = asn1_encode_priv_key(N, e, d, p, q)
with tempfile.NamedTemporaryFile() as priv_file:
priv_file.write(priv_key)
priv_file.flush()
pub_key = yield from ssh_encode_pub_key(priv_file.name, uname)
return priv_key, pub_key
@asyncio.coroutine
def cleanup_old_users(conn):
print("Cleanup task is running now.")
while True:
cur = yield from conn.cursor()
yield from cur.execute("BEGIN")
try:
yield from cur.execute('SELECT COUNT(*) FROM users')
old_count, = yield from cur.fetchone()
yield from cur.execute(
"DELETE FROM users WHERE creation_date < "
"CURRENT_TIMESTAMP - interval '30 minutes' "
"AND username != %s OR public_key IS NULL",
(ADMIN_NAME,))
yield from cur.execute('SELECT COUNT(*) FROM users')
new_count, = yield from cur.fetchone()
yield from cur.execute(
'SELECT public_key FROM users WHERE username != %s',
(ADMIN_NAME,))
with (yield from auth_keys_lock):
AUTH_KEYS_PATH_NEW = AUTH_KEYS_PATH + '.new'
with open(AUTH_KEYS_PATH_NEW, "wb") as f:
for public_key, in (yield from cur.fetchall()):
f.write(public_key.encode("utf-8"))
f.write(b'\n')
shutil.move(AUTH_KEYS_PATH_NEW, AUTH_KEYS_PATH)
print("Deleted %d old keys" % (old_count - new_count))
except Exception:
yield from cur.execute("ROLLBACK")
raise
else:
yield from cur.execute("COMMIT")
finally:
cur.close()
yield from asyncio.sleep(15 * 60)
def cleanup_done(t, conn):
POOL.release(conn)
e = t.exception()
if e:
traceback.print_exception(e.__class__, e, e.__traceback__)
@asyncio.coroutine
def handle(reader, writer):
conn = yield from POOL.acquire()
cur = yield from conn.cursor()
yield from cur.execute("BEGIN")
try:
writer.write(get_message('welcome'))
while True:
writer.write(b"Command: ")
cmd = (yield from reader.readline()).decode("utf-8").strip()
if not cmd and reader.at_eof():
writer.close()
break
try:
yield from (actions[cmd](reader, writer, conn))
except KeyError:
writer.write(get_message('cmd_unknwown'))
except Exception as e:
writer.write(get_message('unkown_error'))
traceback.print_exception(e.__class__, e, e.__traceback__)
except Exception:
yield from cur.execute("ROLLBACK")
else:
yield from cur.execute("COMMIT")
finally:
cur.close()
POOL.release(conn)
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument('--port', '-p', metavar='PORT', type=int,
required=True)
args = parser.parse_args()
server = asyncio.start_server(handle, port=args.port)
server_task = asyncio.Task(server)
loop = asyncio.get_event_loop()
# Initialize connection pool
POOL = loop.run_until_complete(aiopg.create_pool(maxsize=100, **DB))
# Cleanup task setup
cleanup_conn = loop.run_until_complete(POOL.acquire())
cleaner_task = asyncio.Task(cleanup_old_users(cleanup_conn))
cleaner_task.add_done_callback(lambda t: cleanup_done(t, cleanup_conn))
try:
print("Starting main loop, accepting connections now.")
loop.run_forever()
finally:
EXECUTOR.shutdown()
server.close()
loop.run_until_complete(POOL.clear())