Package: omniserver
OmniserverConnections for all occasionsOmniserveris a Python module designed for quickly creating highly customizable server/client objects, and to provide maximum flexibility using as little boilerplate code as possible. Common uses include prototyping/replicating malicious network communication methods, intercepting/controlling the traffic of "Command and Control"-type malware, or simply being a shortcut for general networking activities.At its core,omniserveris essentially just a wrapper around Python's built-insocketservermodule (which itself is just a wrapper aroundsocket). The goal ofomniserveris to extendsocketserverby providing a wider variety of functions, and perhaps a simpler API. All ofomniserver's RequestHandler and Server objects are compatible withsocketserver, and can basically be used in the same way as described in their documentation.Basic UsageSeedocumentationTheomniservermodule can be used to initiate and control client and server objects. Current varieties include TCP, UDP, HTTP, and DNS (TCP or UDP). TLS/SSL can also be enabled on any TCP-based client or server object.ClientsConnections can be established with remote servers usingclientobjects. After succesfully connecting to a server using theconnect()orbeacon()methods, TCP and UDP communications are primarily controlled using thesend()andrecv()methods. Additionally, DNS and HTTP clients provide thequery()andget()methods (respectively), which handle both the sending and recieving of their more specialized data structures.importomniserverasomniwithomni.udp_client(("192.168.1.40",7896))asudp_client:# 'with' keyword calls connect() and close()udp_client.send("Akon")udp_client.recv()udp_client.send("All on the floor")tcp_client=omni.tcp_client(("192.168.1.40",6547))iftcp_client.beacon(freq=3,tries=5):# Try to connect 5 times, 3 seconds apart, before quitingtcp_client.send("whoami")tcp_client.recv()tcp_client.send("dir")tcp_client.recv()tcp_client.close()# Good practice, but not necessarily requiredip=omni.dns_client(("10.10.10.100",53)).query("fraggle-rock.com")# query() returns the resolved IP as a stringwithomni.http_client((ip,8181))ashttp_client:http_client.get("/test.txt")ServersConnections from remote clients can be accepted on a listening socket usingserverobjects. They are threaded by default, and can be run all at once or indivdually. Allserverobjects provide the same methods as theirsocketservercounterparts, with the addition ofstart(),wait(), andstop()methods.Omniserveralso provides thestart_all(),wait_all(), andstop_all()functions, which affect all the currently initialized servers objects at once. Server processes/threads can be exited with CTRL-C.omni.tcp_server(7896)omni.udp_server(3214)omni.http_server(8181)# Works basically the same as http.serveromni.dns_server(default_ip="192.168.1.40")# Will respond to all IPv4 queries with default IPomni.servers.start_all()tcp=omni.tcp_server.start()# Non-blockingomni.udp_server().serve_forever()# Random high port, blockingtcp.stop()# Shutdown tcp server after udp_server exitsCustomizing Request Handler ClassesClientandserverhandler classes can be subclassed the same way as described insocketserver's documentation. All data which flows throughomniserverobjects is passed through theincoming()andoutgoing()methods, so overriding them provides a convenient way to deal with encypted communications, as shown in the following example:importdynabyteclassC2Handler(omni.TCPHandler):defincoming(self,data):returnArray(data).XOR("Secret_key").ADD(0xA1).ROR(5)# The encryption scheme, backwordsdefoutgoing(self,resp):# Encode responsereturnbytes(Array(resp).ROL(5).SUB(0xA1).XOR("Secret_key"))# ROL/SUB/XOR'ing all sent datadefresponse(self,data):ifdata=="name":return"Don Cheadle"elifdata=="real name":return"Tiger Woods"else:return"default"classC2Client(omni.TCPClient):defincoming(self,data):# incoming() and outgoing() are called within recv() and send(), respectivelyreturnArray(data).XOR("Secret_key").ADD(0xA1).ROR(5)defoutgoing(self,data):# Called whenever send() isreturnbytes(Array(data).ROL(5).SUB(0xA1).XOR("Secret_key"))# Start serveromni.tcp_server(6547,RequestHandler=C2Handler).start()withomni.tcp_client(("10.10.10.100",6547),Handler=C2Client)astcp:tcp.send("name")tcp.recv()tcp.send("real name")tcp.recv()tcp.send("didgeridoo")tcp.recv()Request handler classes operate basically the same way as their socketserver counterparts, handle(), setup(), finish() etc. can be overriden as you see fit.TLS/SSLTCP-based servers and clients are TLS/SSL compatible.Omniserverprovides functions for generating SSL certs, but they are currently only available when used on Linux.cert,key=omni.certs.create_cert_key(CN="booberry.edu")# Returns absolute path to CA cert and private keycontext=omni.certs.create_server_context(certfile=cert,keyfile=key)omni.tcp_server(6547,sslcontext=context).start().wait()On the client side, you'll need the CA of the server you plan to connect to, or cert checking can simply be disabled.# No cert requiredwithomni.tcp_client(("10.10.10.50",6547))asclient:client.enable_ssl(cert_required=False)client.send("Secret TLS message (didn't check the cert)")client.recv()# Cert requiredclient=omni.tcp_client(("10.10.10.50",6547),hostname="booberry.edu")client.enable_ssl(omni.certs.create_client_context(ca_cert="./cert.crt"))ifclient.connect():client.send("Secret TLS message")client.recv()client.close()InstallationInstall from PyPIpip install omniserverKnown Issues & TODOCurrently cannot easily create SSL certificates on WindowsGenerating the cert/key with OpenSSL on Linux and moving them over works, if you truly need the TLS/SSL server on WindowsAdd function for signing certificates with CAHTTP server and client arn't very fleshed out, it's kinda just easier to use requestsDNS over TCP is in there, but I haven't tested it extensivelyTCP servers sometimes do a weird retransmission of FIN, ACK packet**kwargs in client.enable_ssl(), for creating contextFinish documentation