Photo by Towfiqu barbhuiya on Unsplash
Python for Ethical Hackers - A Practical Approach
Cyber Security
Python remains the dominant language in the world of information security, even if the debate over your preferred language can sometimes resemble a religious war.
Python-based tools include fuzzers, proxy servers, and even the occasional exploit. Python is used to write exploit frameworks such as CANVAS, as well as more obscure tools such as Sulley and PyEmu.
In this article, we are going to review the vast uses of python in hacking and cyber security. One significant difference between a script kiddie and a professional is that one uses other peoples' tools while the other writes out their own tools.
some of the python2 syntax in this article is used conservatively and has no problem running on python3 releases.
There will not be too much definitions this time, just a deep dive into action.
Prerequisites
Intermediary skills in Python programming.
Integrated Development Environment (IDE eg Pycharm) - VS Code works as well
Internet connection
Computer - Linux Distribution
The Network
An attacker arguably can do the most with a simple network access. They can inject packets, sniff data, scan for hosts, remotely exploit hosts and a lot more making it a haven for someone determined to gain access.
We are going to use a python module called socket
to work for us. This module exposes all of the necessary pieces to quickly write TCP and UDP clients and servers and use raw sockets.
A simple TCP client
import socket
host = "www.google.com"
port = 80
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# connect our client
client.connect((host, port))
# send data
client.send(b"GET / HTTP/1.1\r\nHost: google.com\r\n\r\n")
# receive data in formatted response
response = client.recv(4096)
print(response)
Having our values for the host and port target, we're going to create a socket object using the AF_INET
and SOCK_STREAM
.
The AF_INET
says the we are going to use the standard IPv4 address or host while the SOCK_STREAM
says that the connection is going to be a TCP connection.
There are some assumptions about the sockets we're handling here in this example that you need to know and prepare for while writing more complex socket exploits;
- The connection will always succeed.
- The server will always grant a response set of data in a timely manner.
A Simple UDP Client
For a UDP client we'll only need to make two changes to be able to send packets in UDP form.
import socket
host = "127.0.0.1"
port = 80
# create a socket object
client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# send some data
client.sendto(b"AAABBBCCC",(host, port))
# receive some data
data, addr = client.recvfrom(4096)
The difference here is that the socket type is changed to SOCK_DGRAM
. Next is to pass the data we're going to send into the function sendto()
and receive the UDP data block using the recvfrom()
.
Other than creating a TCP or UDP client, you may also need to create a server using said protocolos. That may run outside the scope of this article. You may request for that in the comments.
Acquiring Credentials Through a Network
Scapy
Notice the soft terms. Acquiring may as well be stealing. Let us get into Scapy's interface for sniffing packets and dissecting their contents. You may also forge network packets using this module. First we're going to create a sniffer the captures packets and dumps its contents to us. Later you will find that you can filter through the data received.
from scapy.all import *
# the packet callback
def packet_callback(packet):
print packet.show()
# initialize the sniffer
sniff(prn=packet_callback,count=1)
The packet callback here receives all the packets then we've just told scapy to sniff through with no filtering. Output:
$ python scapy_sniffer.py
WARNING: No route found for IPv6 destination :: (no default route?)
###[ Ethernet ]###
dst = 10:40:f3:ab:71:02
src = 00:18:e7:ff:5c:f8
type = 0x800
###[ IP ]###
version = 4L
ihl = 5L
tos = 0x0
len = 52
id = 35232
flags = DF
frag = 0L
ttl = 51
proto = tcp
chksum = 0x4a51
src = 195.91.239.8
dst = 192.168.0.198
\options \
###[ TCP ]###
sport = etlservicemgr
dport = 54000
seq = 4154787032
ack = 2619128538
dataofs = 8L
reserved = 0L
flags = A
window = 330
chksum = 0x80a2
urgptr = 0
options = [('NOP', None), ('NOP', None),
('Timestamp', (1960913461, 764897985))]
None
When the first packet is received on the network, the callback function in the code above uses the function packet.show()
to display the packet contents and to separate some of the protocol information. Using the show()
method is a useful way to debug the script we're creating as we go to ensure we are capturing the output you intended.
This is just a basic sniffer using Scapy. Read the docs to discover the various filters that you can add to your packets to get useful data.
Windows Processes
Process Monitoring using WMI
Using WMI API, a programmer has the ability to monitor certain events and receive callbacks when these events happen. We will prompt this interface to receive callbacks each time a process is created. When a process gets created;
- we’re going to trap some valuable information:
- The time the process was created
- The user that spawned the process
- The executable that was launched and its command-line arguments
- The process ID
- The parent process ID.
This should show us any processes started by higher-privilege accounts, as well as any processes that call external files like batch scripts. We'll also assess what permissions are allowed on the process tokens once we have all of this information.
Sometimes we might be lucky or unlucky depending on the recipient of the whip and find processes that were give higher privileges on Windows making it possible to gain more control. We must also take note of the privileges enabled on the process tokens.
Let's start by writing a simple monitoring script.
import win32con
import win32api
import win32security
import wmi
import sys
import os
def log_to_file(message):
fd = open("process_monitor_log.csv", "ab")
fd.write(b"%s\r\n" % message)
fd.close()
return
# create a log file header
log_to_file(b"Time,User,Executable,CommandLine,PID,Parent PID,Privileges")
# instantiate the WMI interface
c = wmi.WMI()
# create our process monitor
process_watcher = c.Win32_Process.watch_for("creation")
while True:
try:
new_process = process_watcher()
proc_owner = new_process.GetOwner()
proc_owner = "%s\\%s" % (proc_owner[0],proc_owner[2])
create_date = new_process.CreationDate
executable = new_process.ExecutablePath
cmdline = new_process.CommandLine
pid = new_process.ProcessId
parent_pid = new_process.ParentProcessId
privileges = "N/A"
process_log_message = "%s,%s,%s,%s,%s,%s,%s\r\n" % (create_date,
proc_owner, executable, cmdline, pid, parent_pid, privileges)
print(process_log_message)
log_to_file(process_log_message)
except:
pass
To get information about privileged users' processes, you'll need to run the script as an Administator unlike the example below.
Output:
To begin, we instantiate the WMI class and tell it to monitor for the process creation event. We can monitor process creation and deletion events by using the methods described in the Python WMI documentation, which I will demonstrate in a moment.
If you decide that you want to closely monitor process events, you can use the operation, which will alert you of every single event that occurs during the process. We then enter a loop, which will continue until process_watcher returns a new process event.
The new process event is a WMI class called Win32_Process
that contains all of the relevant information that we are after.
One of the class functions is "'GetOwner," which we use to find out who spawned the process, and from there we collect all of the process information we need, output it to the screen, and log it to a file.
You may wonder - why do I need to monitor processes?
If we use the process ID to obtain a handle to a target process. We could crack open the process token, and then request the token information for that process. We can instruct the API call to hand back all of the privilege information for that process.
That's jackpot if you ask me.
Conclusion
Oh well, I am not really creative with the catchy conclusions so I usually dread this part. I just end up having something awkward and making you uncomfortable is an honor, lol. Umm I'm pretty easy to find online so just drop me a text and we may have a good chat. This content is purely for ethical use.
Credit to Justin Seitz