151 lines
81 KiB
HTML
151 lines
81 KiB
HTML
|
|
<!DOCTYPE html><html lang="en-US"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=Edge"><link rel="shortcut icon" href="/assets/images/favicon.png" type="image/x-icon"><link rel="stylesheet" href="/assets/css/just-the-docs-default.css"> <script async src="https://www.googletagmanager.com/gtag/js?id=UA-4622520-7"></script> <script> window.dataLayer = window.dataLayer || []; function gtag(){dataLayer.push(arguments);} gtag('js', new Date()); gtag('config', 'UA-4622520-7', { 'anonymize_ip': true }); </script> <script type="text/javascript" src="/assets/js/vendor/lunr.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/mermaid@10.8.0/dist/mermaid.min.js"></script> <script type="text/javascript" src="/assets/js/just-the-docs.js"></script><meta name="viewport" content="width=device-width, initial-scale=1"><title>Writing Python Modules | Metasploit Documentation Penetration Testing Software, Pen Testing Security</title><meta name="generator" content="Jekyll v4.3.4" /><meta property="og:title" content="Writing Python Modules" /><meta property="og:locale" content="en_US" /><meta name="description" content="View Metasploit Framework Documentation" /><meta property="og:description" content="View Metasploit Framework Documentation" /><link rel="canonical" href="https://rapid7.github.io/metasploit-framework/docs/development/developing-modules/external-modules/writing-external-python-modules.html" /><meta property="og:url" content="https://rapid7.github.io/metasploit-framework/docs/development/developing-modules/external-modules/writing-external-python-modules.html" /><meta property="og:site_name" content="Metasploit Documentation Penetration Testing Software, Pen Testing Security" /><meta property="og:type" content="website" /><meta name="twitter:card" content="summary" /><meta property="twitter:title" content="Writing Python Modules" /> <script type="application/ld+json"> {"@context":"https://schema.org","@type":"WebPage","description":"View Metasploit Framework Documentation","headline":"Writing Python Modules","publisher":{"@type":"Organization","logo":{"@type":"ImageObject","url":"https://rapid7.github.io/metasploit-framework/assets/images/favicon.png"}},"url":"https://rapid7.github.io/metasploit-framework/docs/development/developing-modules/external-modules/writing-external-python-modules.html"}</script><body> <svg xmlns="http://www.w3.org/2000/svg" style="display: none;"> <symbol id="svg-link" viewBox="0 0 24 24"><title>Link</title><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-link"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path> </svg> </symbol> <symbol id="svg-search" viewBox="0 0 24 24"><title>Search</title><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-search"> <circle cx="11" cy="11" r="8"></circle><line x1="21" y1="21" x2="16.65" y2="16.65"></line> </svg> </symbol> <symbol id="svg-menu" viewBox="0 0 24 24"><title>Menu</title><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-menu"><line x1="3" y1="12" x2="21" y2="12"></line><line x1="3" y1="6" x2="21" y2="6"></line><line x1="3" y1="18" x2="21" y2="18"></line> </svg> </symbol> <symbol id="svg-arrow-right" viewBox="0 0 24 24"><title>Expand</title><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-chevron-right"><polyline points="9 18 15 12 9 6"></polyline> </svg> </symbol> <symbol id="svg-doc" viewBox="0 0 24 24"><title>Doc
|
|||
|
|
</code></pre></div></div><p>The location of the <a href="https://github.com/rapid7/metasploit-framework/tree/master/lib/msf/core/modules/external/python">metasploit library</a> is automatically added to the <code class="language-plaintext highlighter-rouge">PYTHONPATH</code> environment variable before the Python module is executed.</p><h2 id="describe-yourself"> <a href="#describe-yourself" class="anchor-heading" aria-labelledby="describe-yourself"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Describe Yourself</h2><p>Metasploit modules include information about authors of the modules, references to other sources with information about the vulnerabilities, descriptions of the modules, options, etc.</p><p>Python modules need to include this metadata information as well. The structure of the data is similar to modules written in Ruby. The following is an example template of metadata information:</p><div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">metadata</span> <span class="o">=</span> <span class="p">{</span>
|
|||
|
|
<span class="sh">'</span><span class="s">name</span><span class="sh">'</span><span class="p">:</span> <span class="sh">'</span><span class="s"><name></span><span class="sh">'</span><span class="p">,</span>
|
|||
|
|
<span class="sh">'</span><span class="s">description</span><span class="sh">'</span><span class="p">:</span> <span class="sh">'''</span><span class="s">
|
|||
|
|
<description>
|
|||
|
|
</span><span class="sh">'''</span><span class="p">,</span>
|
|||
|
|
<span class="sh">'</span><span class="s">authors</span><span class="sh">'</span><span class="p">:</span> <span class="p">[</span>
|
|||
|
|
<span class="sh">'</span><span class="s"><author></span><span class="sh">'</span><span class="p">,</span>
|
|||
|
|
<span class="sh">'</span><span class="s"><author></span><span class="sh">'</span>
|
|||
|
|
<span class="p">],</span>
|
|||
|
|
<span class="sh">'</span><span class="s">date</span><span class="sh">'</span><span class="p">:</span> <span class="sh">'</span><span class="s">YYYY-MM-DD</span><span class="sh">'</span><span class="p">,</span>
|
|||
|
|
<span class="sh">'</span><span class="s">license</span><span class="sh">'</span><span class="p">:</span> <span class="sh">'</span><span class="s"><license></span><span class="sh">'</span><span class="p">,</span>
|
|||
|
|
<span class="sh">'</span><span class="s">references</span><span class="sh">'</span><span class="p">:</span> <span class="p">[</span>
|
|||
|
|
<span class="p">{</span><span class="sh">'</span><span class="s">type</span><span class="sh">'</span><span class="p">:</span> <span class="sh">'</span><span class="s">url</span><span class="sh">'</span><span class="p">,</span> <span class="sh">'</span><span class="s">ref</span><span class="sh">'</span><span class="p">:</span> <span class="sh">'</span><span class="s"><url></span><span class="sh">'</span><span class="p">},</span>
|
|||
|
|
<span class="p">{</span><span class="sh">'</span><span class="s">type</span><span class="sh">'</span><span class="p">:</span> <span class="sh">'</span><span class="s">cve</span><span class="sh">'</span><span class="p">,</span> <span class="sh">'</span><span class="s">ref</span><span class="sh">'</span><span class="p">:</span> <span class="sh">'</span><span class="s">YYYY-#</span><span class="sh">'</span><span class="p">},</span>
|
|||
|
|
<span class="p">{</span><span class="sh">'</span><span class="s">type</span><span class="sh">'</span><span class="p">:</span> <span class="sh">'</span><span class="s">edb</span><span class="sh">'</span><span class="p">,</span> <span class="sh">'</span><span class="s">ref</span><span class="sh">'</span><span class="p">:</span> <span class="sh">'</span><span class="s">#</span><span class="sh">'</span><span class="p">},</span>
|
|||
|
|
<span class="p">{</span><span class="sh">'</span><span class="s">type</span><span class="sh">'</span><span class="p">:</span> <span class="sh">'</span><span class="s">aka</span><span class="sh">'</span><span class="p">,</span> <span class="sh">'</span><span class="s">ref</span><span class="sh">'</span><span class="p">:</span> <span class="sh">'</span><span class="s"><name></span><span class="sh">'</span><span class="p">}</span>
|
|||
|
|
<span class="p">],</span>
|
|||
|
|
<span class="sh">'</span><span class="s">type</span><span class="sh">'</span><span class="p">:</span> <span class="sh">'</span><span class="s"><module type></span><span class="sh">'</span><span class="p">,</span>
|
|||
|
|
<span class="sh">'</span><span class="s">options</span><span class="sh">'</span><span class="p">:</span> <span class="p">{</span>
|
|||
|
|
<span class="sh">'</span><span class="s"><name></span><span class="sh">'</span><span class="p">:</span> <span class="p">{</span><span class="sh">'</span><span class="s">type</span><span class="sh">'</span><span class="p">:</span> <span class="sh">'</span><span class="s">address</span><span class="sh">'</span><span class="p">,</span> <span class="sh">'</span><span class="s">description</span><span class="sh">'</span><span class="p">:</span> <span class="sh">'</span><span class="s"><description></span><span class="sh">'</span><span class="p">,</span> <span class="sh">'</span><span class="s">required</span><span class="sh">'</span><span class="p">:</span> <span class="o"><</span><span class="bp">True</span><span class="o">/</span><span class="bp">False</span><span class="o">></span><span class="p">,</span> <span class="sh">'</span><span class="s">default</span><span class="sh">'</span><span class="p">:</span> <span class="bp">None</span><span class="p">},</span>
|
|||
|
|
<span class="sh">'</span><span class="s"><name></span><span class="sh">'</span><span class="p">:</span> <span class="p">{</span><span class="sh">'</span><span class="s">type</span><span class="sh">'</span><span class="p">:</span> <span class="sh">'</span><span class="s">string</span><span class="sh">'</span><span class="p">,</span> <span class="sh">'</span><span class="s">description</span><span class="sh">'</span><span class="p">:</span> <span class="sh">'</span><span class="s"><description></span><span class="sh">'</span><span class="p">,</span> <span class="sh">'</span><span class="s">required</span><span class="sh">'</span><span class="p">:</span> <span class="o"><</span><span class="bp">True</span><span class="o">/</span><span class="bp">False</span><span class="o">></span><span class="p">,</span> <span class="sh">'</span><span class="s">default</span><span class="sh">'</span><span class="p">:</span> <span class="bp">None</span><span class="p">},</span>
|
|||
|
|
<span class="sh">'</span><span class="s"><name></span><span class="sh">'</span><span class="p">:</span> <span class="p">{</span><span class="sh">'</span><span class="s">type</span><span class="sh">'</span><span class="p">:</span> <span class="sh">'</span><span class="s">string</span><span class="sh">'</span><span class="p">,</span> <span class="sh">'</span><span class="s">description</span><span class="sh">'</span><span class="p">:</span> <span class="sh">'</span><span class="s"><description></span><span class="sh">'</span><span class="p">,</span> <span class="sh">'</span><span class="s">required</span><span class="sh">'</span><span class="p">:</span> <span class="o"><</span><span class="bp">True</span><span class="o">/</span><span class="bp">False</span><span class="o">></span><span class="p">,</span> <span class="sh">'</span><span class="s">default</span><span class="sh">'</span><span class="p">:</span> <span class="bp">None</span><span class="p">}</span>
|
|||
|
|
<span class="p">}</span>
|
|||
|
|
<span class="p">}</span>
|
|||
|
|
</code></pre></div></div><h3 id="module-type"> <a href="#module-type" class="anchor-heading" aria-labelledby="module-type"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Module Type</h3><p>As shown in the metadata template information, a <code class="language-plaintext highlighter-rouge">type</code> is also include for the module. The module type is used to select an ERB template, which generates a Ruby document for the module. The ERB templates can be found <a href="https://github.com/rapid7/metasploit-framework/tree/master/lib/msf/core/modules/external/templates">here</a>. The following templates are currently available:</p><div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>remote_exploit_cmd_stager
|
|||
|
|
capture_server
|
|||
|
|
dos
|
|||
|
|
single_scanner
|
|||
|
|
multi_scanner
|
|||
|
|
</code></pre></div></div><p>The <code class="language-plaintext highlighter-rouge">remote_exploit_cmd_stager</code> module type is used when writing an exploit for command execution or code injection vulnerabilities and provides the command to inject into the vulnerable code based on the <a href="/docs/development/developing-modules/guides/how-to-use-command-stagers.html">flavor</a> specified for the command stager.</p><p>The <code class="language-plaintext highlighter-rouge">capture_server</code> module type is used when a module is designed to simulate a service to capture credentials for connecting clients.</p><p>The <code class="language-plaintext highlighter-rouge">dos</code> module type is used when the module will send packets to a remote service that will crash the service or put it in an unusable state.</p><p>The <code class="language-plaintext highlighter-rouge">single_scanner</code> module type is used when creating a module to scan hosts without batching.</p><p>The <code class="language-plaintext highlighter-rouge">multi_scanner</code> module type is used for modules that are going to scan hosts in batches. The <code class="language-plaintext highlighter-rouge">batch_size</code> option is registered in the mutli_scanner ERB template with a default of 200.</p><h3 id="options"> <a href="#options" class="anchor-heading" aria-labelledby="options"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Options</h3><p>The <code class="language-plaintext highlighter-rouge">options</code> dictionary in the metadata are the options that will be available in msfconsole when the module is loaded. The options can be required (necessary for the module to run) or not (provide additional functionality).</p><h3 id="communication"> <a href="#communication" class="anchor-heading" aria-labelledby="communication"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Communication</h3><p>To pass the metadata information, as well as the starting function of your Python module, to msfconsole, use the <code class="language-plaintext highlighter-rouge">module.run()</code> function. The <code class="language-plaintext highlighter-rouge">module.run()</code> function takes two arguments, the first is the metadata and the second is the callback function to use when executing the module from msfconsole. The code snippet will look like the following:</p><div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">run</span><span class="p">(</span><span class="n">args</span><span class="p">):</span>
|
|||
|
|
<span class="c1"># Your code here
|
|||
|
|
</span> <span class="k">pass</span>
|
|||
|
|
|
|||
|
|
|
|||
|
|
<span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="sh">'</span><span class="s">__main__</span><span class="sh">'</span><span class="p">:</span>
|
|||
|
|
<span class="n">module</span><span class="p">.</span><span class="nf">run</span><span class="p">(</span><span class="n">metadata</span><span class="p">,</span> <span class="n">run</span><span class="p">)</span>
|
|||
|
|
</code></pre></div></div><p>When msfconsole sends a <code class="language-plaintext highlighter-rouge">describe</code> request to the Python module, the metadata information is returned. When msfconsole sends a <code class="language-plaintext highlighter-rouge">run</code> request to the module, the callback function, <code class="language-plaintext highlighter-rouge">run</code> in this example, will be called with the arguments provided to msfconsole.</p><p>A <a href="https://github.com/rapid7/metasploit-framework/pull/9739">LogHandler</a> can be setup and used to communicate status information back to framework during execution of the Python module. Here is code snippet that uses the LogHandler:</p><div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="n">logging</span>
|
|||
|
|
<span class="kn">from</span> <span class="n">metasploit</span> <span class="kn">import</span> <span class="n">module</span>
|
|||
|
|
|
|||
|
|
<span class="n">module</span><span class="p">.</span><span class="n">LogHandler</span><span class="p">.</span><span class="nf">setup</span><span class="p">(</span><span class="n">msg_prefix</span><span class="o">=</span><span class="sh">'</span><span class="s">logging test: </span><span class="sh">'</span><span class="p">)</span>
|
|||
|
|
<span class="n">logging</span><span class="p">.</span><span class="nf">info</span><span class="p">(</span><span class="sh">'</span><span class="s">info</span><span class="sh">'</span><span class="p">)</span>
|
|||
|
|
<span class="n">logging</span><span class="p">.</span><span class="nf">error</span><span class="p">(</span><span class="sh">'</span><span class="s">error</span><span class="sh">'</span><span class="p">)</span>
|
|||
|
|
<span class="n">logging</span><span class="p">.</span><span class="nf">warning</span><span class="p">(</span><span class="sh">'</span><span class="s">warning</span><span class="sh">'</span><span class="p">)</span>
|
|||
|
|
<span class="n">logging</span><span class="p">.</span><span class="nf">debug</span><span class="p">(</span><span class="sh">'</span><span class="s">debug</span><span class="sh">'</span><span class="p">)</span>
|
|||
|
|
</code></pre></div></div><p>The <code class="language-plaintext highlighter-rouge">module.LogHandler.setup()</code> function is used the create a Handler and Formatter that will call <code class="language-plaintext highlighter-rouge">module.log()</code> with the appropriate log level.</p><h2 id="full-example"> <a href="#full-example" class="anchor-heading" aria-labelledby="full-example"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Full Example</h2><div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">#!/usr/bin/env python3
|
|||
|
|
# -*- coding: utf-8 -*-
|
|||
|
|
</span>
|
|||
|
|
<span class="c1"># standard modules
|
|||
|
|
</span><span class="kn">import</span> <span class="n">logging</span>
|
|||
|
|
|
|||
|
|
<span class="c1"># extra modules
|
|||
|
|
</span><span class="n">dependencies_missing</span> <span class="o">=</span> <span class="bp">False</span>
|
|||
|
|
<span class="k">try</span><span class="p">:</span>
|
|||
|
|
<span class="kn">import</span> <span class="n">requests</span>
|
|||
|
|
<span class="k">except</span> <span class="nb">ImportError</span><span class="p">:</span>
|
|||
|
|
<span class="n">dependencies_missing</span> <span class="o">=</span> <span class="bp">True</span>
|
|||
|
|
|
|||
|
|
<span class="kn">from</span> <span class="n">metasploit</span> <span class="kn">import</span> <span class="n">module</span>
|
|||
|
|
|
|||
|
|
|
|||
|
|
<span class="n">metadata</span> <span class="o">=</span> <span class="p">{</span>
|
|||
|
|
<span class="sh">'</span><span class="s">name</span><span class="sh">'</span><span class="p">:</span> <span class="sh">'</span><span class="s">Python Module Example</span><span class="sh">'</span><span class="p">,</span>
|
|||
|
|
<span class="sh">'</span><span class="s">description</span><span class="sh">'</span><span class="p">:</span> <span class="sh">'''</span><span class="s">
|
|||
|
|
Python communication with msfconsole.
|
|||
|
|
</span><span class="sh">'''</span><span class="p">,</span>
|
|||
|
|
<span class="sh">'</span><span class="s">authors</span><span class="sh">'</span><span class="p">:</span> <span class="p">[</span>
|
|||
|
|
<span class="sh">'</span><span class="s">Jacob Robles</span><span class="sh">'</span>
|
|||
|
|
<span class="p">],</span>
|
|||
|
|
<span class="sh">'</span><span class="s">date</span><span class="sh">'</span><span class="p">:</span> <span class="sh">'</span><span class="s">2018-03-22</span><span class="sh">'</span><span class="p">,</span>
|
|||
|
|
<span class="sh">'</span><span class="s">license</span><span class="sh">'</span><span class="p">:</span> <span class="sh">'</span><span class="s">MSF_LICENSE</span><span class="sh">'</span><span class="p">,</span>
|
|||
|
|
<span class="sh">'</span><span class="s">references</span><span class="sh">'</span><span class="p">:</span> <span class="p">[</span>
|
|||
|
|
<span class="p">{</span><span class="sh">'</span><span class="s">type</span><span class="sh">'</span><span class="p">:</span> <span class="sh">'</span><span class="s">url</span><span class="sh">'</span><span class="p">,</span> <span class="sh">'</span><span class="s">ref</span><span class="sh">'</span><span class="p">:</span> <span class="sh">'</span><span class="s">https://blog.rapid7.com/2017/12/28/regifting-python-in-metasploit/</span><span class="sh">'</span><span class="p">},</span>
|
|||
|
|
<span class="p">{</span><span class="sh">'</span><span class="s">type</span><span class="sh">'</span><span class="p">:</span> <span class="sh">'</span><span class="s">aka</span><span class="sh">'</span><span class="p">,</span> <span class="sh">'</span><span class="s">ref</span><span class="sh">'</span><span class="p">:</span> <span class="sh">'</span><span class="s">Coldstone</span><span class="sh">'</span><span class="p">}</span>
|
|||
|
|
<span class="p">],</span>
|
|||
|
|
<span class="sh">'</span><span class="s">type</span><span class="sh">'</span><span class="p">:</span> <span class="sh">'</span><span class="s">single_scanner</span><span class="sh">'</span><span class="p">,</span>
|
|||
|
|
<span class="sh">'</span><span class="s">options</span><span class="sh">'</span><span class="p">:</span> <span class="p">{</span>
|
|||
|
|
<span class="sh">'</span><span class="s">targeturi</span><span class="sh">'</span><span class="p">:</span> <span class="p">{</span><span class="sh">'</span><span class="s">type</span><span class="sh">'</span><span class="p">:</span> <span class="sh">'</span><span class="s">string</span><span class="sh">'</span><span class="p">,</span> <span class="sh">'</span><span class="s">description</span><span class="sh">'</span><span class="p">:</span> <span class="sh">'</span><span class="s">The base path</span><span class="sh">'</span><span class="p">,</span> <span class="sh">'</span><span class="s">required</span><span class="sh">'</span><span class="p">:</span> <span class="bp">True</span><span class="p">,</span> <span class="sh">'</span><span class="s">default</span><span class="sh">'</span><span class="p">:</span> <span class="sh">'</span><span class="s">/</span><span class="sh">'</span><span class="p">},</span>
|
|||
|
|
<span class="sh">'</span><span class="s">rhost</span><span class="sh">'</span><span class="p">:</span> <span class="p">{</span><span class="sh">'</span><span class="s">type</span><span class="sh">'</span><span class="p">:</span> <span class="sh">'</span><span class="s">address</span><span class="sh">'</span><span class="p">,</span> <span class="sh">'</span><span class="s">description</span><span class="sh">'</span><span class="p">:</span> <span class="sh">'</span><span class="s">Target address</span><span class="sh">'</span><span class="p">,</span> <span class="sh">'</span><span class="s">required</span><span class="sh">'</span><span class="p">:</span> <span class="bp">True</span><span class="p">,</span> <span class="sh">'</span><span class="s">default</span><span class="sh">'</span><span class="p">:</span> <span class="bp">None</span><span class="p">}</span>
|
|||
|
|
<span class="p">}</span>
|
|||
|
|
<span class="p">}</span>
|
|||
|
|
|
|||
|
|
|
|||
|
|
<span class="k">def</span> <span class="nf">run</span><span class="p">(</span><span class="n">args</span><span class="p">):</span>
|
|||
|
|
<span class="n">module</span><span class="p">.</span><span class="n">LogHandler</span><span class="p">.</span><span class="nf">setup</span><span class="p">(</span><span class="n">msg_prefix</span><span class="o">=</span><span class="sh">'</span><span class="s">{} - </span><span class="sh">'</span><span class="p">.</span><span class="nf">format</span><span class="p">(</span><span class="n">args</span><span class="p">[</span><span class="sh">'</span><span class="s">rhost</span><span class="sh">'</span><span class="p">]))</span>
|
|||
|
|
<span class="k">if</span> <span class="n">dependencies_missing</span><span class="p">:</span>
|
|||
|
|
<span class="n">logging</span><span class="p">.</span><span class="nf">error</span><span class="p">(</span><span class="sh">'</span><span class="s">Module dependency (requests) is missing, cannot continue</span><span class="sh">'</span><span class="p">)</span>
|
|||
|
|
<span class="k">return</span>
|
|||
|
|
|
|||
|
|
<span class="c1"># Your code here
|
|||
|
|
</span> <span class="k">try</span><span class="p">:</span>
|
|||
|
|
<span class="n">r</span> <span class="o">=</span> <span class="n">requests</span><span class="p">.</span><span class="nf">get</span><span class="p">(</span><span class="sh">'</span><span class="s">https://{}/{}</span><span class="sh">'</span><span class="p">.</span><span class="nf">format</span><span class="p">(</span><span class="n">args</span><span class="p">[</span><span class="sh">'</span><span class="s">rhost</span><span class="sh">'</span><span class="p">],</span> <span class="n">args</span><span class="p">[</span><span class="sh">'</span><span class="s">targeturi</span><span class="sh">'</span><span class="p">]),</span> <span class="n">verify</span><span class="o">=</span><span class="bp">False</span><span class="p">)</span>
|
|||
|
|
<span class="k">except</span> <span class="n">requests</span><span class="p">.</span><span class="n">exceptions</span><span class="p">.</span><span class="n">RequestException</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
|
|||
|
|
<span class="n">logging</span><span class="p">.</span><span class="nf">error</span><span class="p">(</span><span class="sh">'</span><span class="s">{}</span><span class="sh">'</span><span class="p">.</span><span class="nf">format</span><span class="p">(</span><span class="n">e</span><span class="p">))</span>
|
|||
|
|
<span class="k">return</span>
|
|||
|
|
|
|||
|
|
<span class="n">logging</span><span class="p">.</span><span class="nf">info</span><span class="p">(</span><span class="sh">'</span><span class="s">{}...</span><span class="sh">'</span><span class="p">.</span><span class="nf">format</span><span class="p">(</span><span class="n">r</span><span class="p">.</span><span class="n">text</span><span class="p">[</span><span class="mi">0</span><span class="p">:</span><span class="mi">50</span><span class="p">]))</span>
|
|||
|
|
|
|||
|
|
|
|||
|
|
<span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="sh">'</span><span class="s">__main__</span><span class="sh">'</span><span class="p">:</span>
|
|||
|
|
<span class="n">module</span><span class="p">.</span><span class="nf">run</span><span class="p">(</span><span class="n">metadata</span><span class="p">,</span> <span class="n">run</span><span class="p">)</span>
|
|||
|
|
</code></pre></div></div><p>The example sends a get request to the given <code class="language-plaintext highlighter-rouge">rhost</code> and <code class="language-plaintext highlighter-rouge">targeturi</code>, then calls <code class="language-plaintext highlighter-rouge">logging.info()</code> on the result to have the output displayed in msfconsole.</p><h3 id="debugging-python-modules"> <a href="#debugging-python-modules" class="anchor-heading" aria-labelledby="debugging-python-modules"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Debugging Python modules</h3><p>If you want to run an external module as a standalone program from your metasploit-framework folder just specify the Python path to include the Metasploit library support and run the module directly:</p><div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ PYTHONPATH=./lib/msf/core/modules/external/python:$PYTHONPATH python3 ./modules/auxiliary/scanner/wproxy/att_open_proxy.py
|
|||
|
|
</code></pre></div></div><p>The Python module will wait for stdin to receive JSON-RPC input. Entering the request to run the module:</p><pre><code class="language-jsonl">{ "jsonrpc": "2.0", "id": "1337", "method": "run", "params": { "rhosts": ["127.0.0.1"], "rport": "49152" } }
|
|||
|
|
</code></pre><p>You will see the JSON-RPC responses printed to stdout:</p><pre><code class="language-jsonl">{"jsonrpc": "2.0", "method": "message", "params": {"level": "debug", "message": "127.0.0.1:49152 - Connected"}}
|
|||
|
|
{"jsonrpc": "2.0", "method": "message", "params": {"level": "debug", "message": "127.0.0.1:49152 - Received 5 bytes"}}
|
|||
|
|
{"jsonrpc": "2.0", "method": "message", "params": {"level": "info", "message": "127.0.0.1:49152 - Does not match"}}
|
|||
|
|
{"jsonrpc": "2.0", "method": "message", "params": {"level": "debug", "message": "127.0.0.1:49152 - Does not match with: bytearray(b'xxxxx')"}}
|
|||
|
|
</code></pre><p>You can pipe the JSON-RPC request as well for automation purposes:</p><div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>echo '{ "jsonrpc": "2.0", "id": "1337", "method": "run", "params": { "rhosts": ["127.0.0.1"], "rport": "49152" } }' | PYTHONPATH=./lib/msf/core/modules/external/python:$PYTHONPATH python3 ./modules/auxiliary/scanner/wproxy/att_open_proxy.py
|
|||
|
|
</code></pre></div></div><p>The Python external modules can be run directly with command line options:</p><div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ PYTHONPATH=./lib/msf/core/modules/external/python:$PYTHONPATH python3.9 ./modules/auxiliary/scanner/wproxy/att_open_proxy.py --help
|
|||
|
|
usage: att_open_proxy.py [-h] --rhosts RHOSTS [--rport RPORT] [ACTION]
|
|||
|
|
|
|||
|
|
The Arris NVG589 and NVG599 routers configured with AT&T U-verse firmware 9.2.2h0d83 expose an un-authenticated proxy that allows connecting from WAN to LAN by MAC address.
|
|||
|
|
|
|||
|
|
positional arguments:
|
|||
|
|
ACTION The action to take (['run'])
|
|||
|
|
|
|||
|
|
optional arguments:
|
|||
|
|
-h, --help show this help message and exit
|
|||
|
|
--rport RPORT The target port, (default: 49152)
|
|||
|
|
|
|||
|
|
required arguments:
|
|||
|
|
--rhosts RHOSTS The target address
|
|||
|
|
</code></pre></div></div><p>For example:</p><div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>PYTHONPATH=./lib/msf/core/modules/external/python:$PYTHONPATH python3 ./modules/auxiliary/scanner/wproxy/att_open_proxy.py --rhosts 127.0.0.1 --rport 49152
|
|||
|
|
</code></pre></div></div><p>For exploit modules, the payload is encoded encoded using Base64 and specified in a top level <code class="language-plaintext highlighter-rouge">payload_encoded</code> key, implemented <a href="https://github.com/rapid7/metasploit-framework/blob/668735e4185968405c0073465f9aafbf62930538/lib/msf/core/modules/external/templates/remote_exploit.erb#L36-L39">here</a>. Below is an example of the (<a href="https://github.com/rapid7/metasploit-framework/pull/15217">now deleted</a>) <a href="https://github.com/rapid7/metasploit-framework/blob/6dd298ebb76a1617e24da5e4c73e43a46b226a23/modules/exploits/windows/smb/ms17_010_eternalblue_win8.py">ms17_010_eternalblue_win8.py</a> module running:</p><div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ cat options.json
|
|||
|
|
{
|
|||
|
|
"jsonrpc": "2.0",
|
|||
|
|
"id": "1337",
|
|||
|
|
"method": "run",
|
|||
|
|
"params": {
|
|||
|
|
"VERBOSE": true,
|
|||
|
|
"RHOST": "192.168.144.131",
|
|||
|
|
"RPORT": "445",
|
|||
|
|
"GroomAllocations": 13,
|
|||
|
|
"ProcessName": "spoolsv.exe",
|
|||
|
|
"SMBUser": "test",
|
|||
|
|
"SMBPass": "123456",
|
|||
|
|
"payload_encoded": "/EiD5PDozAAA...etc...==="
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
$ cat options.json | PYTHONPATH=./lib/msf/core/modules/external/python:$PYTHONPATH python3 modules/exploits/windows/smb/ms17_010_eternalblue_win8.py
|
|||
|
|
{"jsonrpc": "2.0", "method": "message", "params": {"level": "info", "message": "shellcode size: 1221"}}
|
|||
|
|
{"jsonrpc": "2.0", "method": "message", "params": {"level": "info", "message": "numGroomConn: 13"}}
|
|||
|
|
{"jsonrpc": "2.0", "method": "message", "params": {"level": "info", "message": "Target OS: Windows 10 Pro 10240"}}
|
|||
|
|
{"jsonrpc": "2.0", "method": "message", "params": {"level": "info", "message": "got good NT Trans response"}}
|
|||
|
|
{"jsonrpc": "2.0", "method": "message", "params": {"level": "info", "message": "got good NT Trans response"}}
|
|||
|
|
{"jsonrpc": "2.0", "method": "message", "params": {"level": "info", "message": "SMB1 session setup allocate nonpaged pool success"}}
|
|||
|
|
{"jsonrpc": "2.0", "method": "message", "params": {"level": "info", "message": "SMB1 session setup allocate nonpaged pool success"}}
|
|||
|
|
</code></pre></div></div><p>To add breakpoints to your Python code, add the below code snippet. Note that the interactive breakpoints will only work when running the external modules as standalone Python scripts, and won’t work when running from msfconsole:</p><div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="n">pdb</span><span class="p">;</span> <span class="n">pdb</span><span class="p">.</span><span class="n">pry</span>
|
|||
|
|
</code></pre></div></div><h2 id="coding-with-style"> <a href="#coding-with-style" class="anchor-heading" aria-labelledby="coding-with-style"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Coding with Style</h2><p>All the Python code in Metasploit aims to be <a href="https://www.python.org/dev/peps/pep-0008/">PEP 8</a> compliant. The biggest differences coming from Metasploit’s Ruby style:</p><ul><li>Two lines between functions (but not class methods)<li>Two lines between different types of code (like imports and the metadata, see above)<li>Four spaces for indenting</ul><p>Some coding choices to think about when writing your module:</p><ul><li>Prefer <code class="language-plaintext highlighter-rouge">"foo {}".format('bar')</code> over interpolation with <code class="language-plaintext highlighter-rouge">%</code><li>Keep your callback methods short and readable. If it gets cluttered, break out sub-tasks into well-named functions<li>Variable names should be descriptive, readable, and short (<a href="http://journal.stuffwithstuff.com/2016/06/16/long-names-are-long">a guide</a>)<li>If you really need Python3 features in your module, use <code class="language-plaintext highlighter-rouge">#!/usr/bin/env python3</code> for the shebang<li>If you have a lot of legacy code in 2.7 or need a 2.7 library, use <code class="language-plaintext highlighter-rouge">#!/usr/bin/env python2.7</code> (macOS in particular does not ship with a <code class="language-plaintext highlighter-rouge">python2</code> executable by default)<li>If possible, have your module compatible with both and use <code class="language-plaintext highlighter-rouge">#!/usr/bin/env python</code></ul><h2 id="potentially-common-questions"> <a href="#potentially-common-questions" class="anchor-heading" aria-labelledby="potentially-common-questions"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> (Potentially) Common Questions</h2><h3 id="why-doesnt-the-module-appear-when-i-search-for-it-in-msfconsole"> <a href="#why-doesnt-the-module-appear-when-i-search-for-it-in-msfconsole" class="anchor-heading" aria-labelledby="why-doesnt-the-module-appear-when-i-search-for-it-in-msfconsole"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Why doesn’t the module appear when I search for it in msfconsole?</h3><p>The module may have errors and fail to load inside of msfconsole. Check the framework log file, <code class="language-plaintext highlighter-rouge">~/.msf4/logs/framework.log</code>, for error messages. Also, <strong>if the module is not marked as executable, then it will not show up when you search for it in msfconsole</strong>.</p><h3 id="why-is-the-output-from-the-python-module-not-showing-up-in-msfconsole"> <a href="#why-is-the-output-from-the-python-module-not-showing-up-in-msfconsole" class="anchor-heading" aria-labelledby="why-is-the-output-from-the-python-module-not-showing-up-in-msfconsole"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Why is the output from the Python module not showing up in msfconsole?</h3><p>The external modules communicate with framework via JSON-RPC. If your Python module contains <code class="language-plaintext highlighter-rouge">print</code> statements, framework may not recognize those as JSON-RPC requests. Use the <code class="language-plaintext highlighter-rouge">LogHandler</code> or <code class="language-plaintext highlighter-rouge">module.log()</code> to send status information, which will be displayed in msfconsole.</p><h2 id="additional-resources"> <a href="#additional-resources" class="anchor-heading" aria-labelledby="additional-resources"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Additional Resources</h2><p><a href="https://blog.rapid7.com/2017/12/28/regifting-python-in-metasploit/">Rapid7 Blog: Regifting Python in Metasploit</a></p><p><a href="https://blog.rapid7.com/2018/09/05/external-metasploit-modules-the-gift-that-keeps
|