Files
metasploit-gs/api/Msf/Post/Linux/F5Mcp.html
T
jenkins-metasploit c3f5bd3de2 Reboot gh-pages
2026-05-08 17:08:43 +00:00

1271 lines
76 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>
Module: Msf::Post::Linux::F5Mcp
&mdash; Documentation by YARD 0.9.37
</title>
<link rel="stylesheet" href="../../../css/style.css" type="text/css" />
<link rel="stylesheet" href="../../../css/common.css" type="text/css" />
<script type="text/javascript">
pathId = "Msf::Post::Linux::F5Mcp";
relpath = '../../../';
</script>
<script type="text/javascript" charset="utf-8" src="../../../js/jquery.js"></script>
<script type="text/javascript" charset="utf-8" src="../../../js/app.js"></script>
</head>
<body>
<div class="nav_wrap">
<iframe id="nav" src="../../../class_list.html?1"></iframe>
<div id="resizer"></div>
</div>
<div id="main" tabindex="-1">
<div id="header">
<div id="menu">
<a href="../../../_index.html">Index (F)</a> &raquo;
<span class='title'><span class='object_link'><a href="../../../Msf.html" title="Msf (module)">Msf</a></span></span> &raquo; <span class='title'><span class='object_link'><a href="../../Post.html" title="Msf::Post (class)">Post</a></span></span> &raquo; <span class='title'><span class='object_link'><a href="../Linux.html" title="Msf::Post::Linux (module)">Linux</a></span></span>
&raquo;
<span class="title">F5Mcp</span>
</div>
<div id="search">
<a class="full_list_link" id="class_list_link"
href="../../../class_list.html">
<svg width="24" height="24">
<rect x="0" y="4" width="24" height="4" rx="1" ry="1"></rect>
<rect x="0" y="12" width="24" height="4" rx="1" ry="1"></rect>
<rect x="0" y="20" width="24" height="4" rx="1" ry="1"></rect>
</svg>
</a>
</div>
<div class="clear"></div>
</div>
<div id="content"><h1>Module: Msf::Post::Linux::F5Mcp
</h1>
<div class="box_info">
<dl>
<dt>Defined in:</dt>
<dd>lib/msf/core/post/linux/f5_mcp.rb</dd>
</dl>
</div>
<h2>Overview</h2><div class="docstring">
<div class="discussion">
<p>This mixin lets you programmatically interact with F5s “mcp” service, which is a database service on a variety of F5s devices, including BIG-IP and BIG-IQ.</p>
<p>mcp uses a UNIX domain socket @ /var/run/mcp for all communications. As of writing this module, its world-accessible, so anybody can query or write to it. We implemented a few interesting things as modules, and your best bet for learning how to work this is to look at those modules, but this will document it briefly.</p>
<p>Data is read and written by serializing a TLV-style structure and writing it to that socket, then parsing the response.</p>
<p>If youre just reading data, you can use mcp_simple_query()` to build a query that fetches everything under a given name, and get a Hash of data back. Thats by far the easiest way to handle things.</p>
<p>To create a more complex query, youll need to use mcp_build(), which serializes a message. You can generate a single message, or an array of them. Then use mcp_send_recv() to write it/them to the socket. Additionally, mcp_send_recv() automatically parses them and returns a whole big nested array of data.</p>
<p>To actually use that data without going crazy, I suggest using either mcp_get_single(tagname) to fetch a single tag, or mcp_get_multiple(tagname) if multiple of the same tag can be returned. Finally, the response from that can be passed to mcp_to_h() to convert the response to a hash (note that if there are multiple of the same tag, map_to_h() will only keep one of them).</p>
<p>Obviously, this is all way more complex than mcp_simple_query(). You can see this in action in the module linux/local/f5_create_user`.</p>
</div>
</div>
<div class="tags">
</div>
<h2>
Instance Method Summary
<small><a href="#" class="summary_toggle">collapse</a></small>
</h2>
<ul class="summary">
<li class="public ">
<span class="summary_signature">
<a href="#initialize-instance_method" title="#initialize (instance method)">#<strong>initialize</strong>(info = {}) &#x21d2; Object </a>
</span>
<span class="summary_desc"><div class='inline'>
<p>rubocop:disable Metrics/ModuleLength.</p>
</div></span>
</li>
<li class="public ">
<span class="summary_signature">
<a href="#mcp_build-instance_method" title="#mcp_build (instance method)">#<strong>mcp_build</strong>(tag, type, data) &#x21d2; Object </a>
</span>
<span class="summary_desc"><div class='inline'>
<p>Build an mcp message.</p>
</div></span>
</li>
<li class="public ">
<span class="summary_signature">
<a href="#mcp_get_multiple-instance_method" title="#mcp_get_multiple (instance method)">#<strong>mcp_get_multiple</strong>(hash, name) &#x21d2; Object </a>
</span>
<span class="summary_desc"><div class='inline'>
<p>Pull an array of tags with the same name out of a tag/value structure.</p>
</div></span>
</li>
<li class="public ">
<span class="summary_signature">
<a href="#mcp_get_single-instance_method" title="#mcp_get_single (instance method)">#<strong>mcp_get_single</strong>(hash, name) &#x21d2; Object </a>
</span>
<span class="summary_desc"><div class='inline'>
<p>Pull a single value out of a tag/value structure (ie, the thing returned by mcp_parse()).</p>
</div></span>
</li>
<li class="public ">
<span class="summary_signature">
<a href="#mcp_parse-instance_method" title="#mcp_parse (instance method)">#<strong>mcp_parse</strong>(stream) &#x21d2; Object </a>
</span>
<span class="summary_desc"><div class='inline'>
<p>Recursively parse an mcp message from a binary stream into an object.</p>
</div></span>
</li>
<li class="public ">
<span class="summary_signature">
<a href="#mcp_parse_responses-instance_method" title="#mcp_parse_responses (instance method)">#<strong>mcp_parse_responses</strong>(incoming_data) &#x21d2; Object </a>
</span>
<span class="summary_desc"><div class='inline'>
<p>Parse one or more packets (including headers) into an array of packets.</p>
</div></span>
</li>
<li class="public ">
<span class="summary_signature">
<a href="#mcp_send_recv-instance_method" title="#mcp_send_recv (instance method)">#<strong>mcp_send_recv</strong>(messages) &#x21d2; Object </a>
</span>
<span class="summary_desc"><div class='inline'></div></span>
</li>
<li class="public ">
<span class="summary_signature">
<a href="#mcp_simple_query-instance_method" title="#mcp_simple_query (instance method)">#<strong>mcp_simple_query</strong>(querytype) &#x21d2; Object </a>
</span>
<span class="summary_desc"><div class='inline'>
<p>Do a query_all request for something that will reply with a single query result.</p>
</div></span>
</li>
<li class="public ">
<span class="summary_signature">
<a href="#mcp_to_h-instance_method" title="#mcp_to_h (instance method)">#<strong>mcp_to_h</strong>(array) &#x21d2; Object </a>
</span>
<span class="summary_desc"><div class='inline'>
<p>Take an array of results from an mcp query, and change them from an array of tag=&gt;value into a hash.</p>
</div></span>
</li>
</ul>
<div id="instance_method_details" class="method_details_list">
<h2>Instance Method Details</h2>
<div class="method_details first">
<h3 class="signature first" id="initialize-instance_method">
#<strong>initialize</strong>(info = {}) &#x21d2; <tt>Object</tt>
</h3><div class="docstring">
<div class="discussion">
<p>rubocop:disable Metrics/ModuleLength</p>
</div>
</div>
<div class="tags">
</div><table class="source_code">
<tr>
<td>
<pre class="lines">
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63</pre>
</td>
<td>
<pre class="code"><span class="info file"># File 'lib/msf/core/post/linux/f5_mcp.rb', line 39</span>
<span class='kw'>def</span> <span class='id identifier rubyid_initialize'>initialize</span><span class='lparen'>(</span><span class='id identifier rubyid_info'>info</span> <span class='op'>=</span> <span class='lbrace'>{</span><span class='rbrace'>}</span><span class='rparen'>)</span>
<span class='id identifier rubyid_file'>file</span> <span class='op'>=</span> <span class='op'>::</span><span class='const'>File</span><span class='period'>.</span><span class='id identifier rubyid_join'>join</span><span class='lparen'>(</span><span class='const'><span class='object_link'><a href="../../../Msf.html" title="Msf (module)">Msf</a></span></span><span class='op'>::</span><span class='const'><span class='object_link'><a href="../../Config.html" title="Msf::Config (class)">Config</a></span></span><span class='period'>.</span><span class='id identifier rubyid_data_directory'><span class='object_link'><a href="../../Config.html#data_directory-class_method" title="Msf::Config.data_directory (method)">data_directory</a></span></span><span class='comma'>,</span> <span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>f5-mcp-objects.txt</span><span class='tstring_end'>&#39;</span></span><span class='rparen'>)</span>
<span class='id identifier rubyid_objects'>objects</span> <span class='op'>=</span> <span class='op'>::</span><span class='const'>File</span><span class='period'>.</span><span class='id identifier rubyid_read'>read</span><span class='lparen'>(</span><span class='id identifier rubyid_file'>file</span><span class='rparen'>)</span>
<span class='id identifier rubyid_raise'>raise</span><span class='lparen'>(</span><span class='tstring'><span class='tstring_beg'>&quot;</span><span class='tstring_content'>Could not load </span><span class='embexpr_beg'>#{</span><span class='id identifier rubyid_file'>file</span><span class='embexpr_end'>}</span><span class='tstring_content'>!</span><span class='tstring_end'>&quot;</span></span><span class='rparen'>)</span> <span class='kw'>unless</span> <span class='id identifier rubyid_objects'>objects</span>
<span class='ivar'>@tags_by_id</span> <span class='op'>=</span>
<span class='id identifier rubyid_objects'>objects</span>
<span class='period'>.</span><span class='id identifier rubyid_split'>split</span><span class='lparen'>(</span><span class='tstring'><span class='tstring_beg'>&quot;</span><span class='tstring_content'>\n</span><span class='tstring_end'>&quot;</span></span><span class='rparen'>)</span>
<span class='period'>.</span><span class='id identifier rubyid_reject'>reject</span> <span class='lbrace'>{</span> <span class='op'>|</span><span class='id identifier rubyid_o'>o</span><span class='op'>|</span> <span class='id identifier rubyid_o'>o</span><span class='period'>.</span><span class='id identifier rubyid_start_with?'>start_with?</span><span class='lparen'>(</span><span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>#</span><span class='tstring_end'>&#39;</span></span><span class='rparen'>)</span> <span class='rbrace'>}</span>
<span class='period'>.</span><span class='id identifier rubyid_map'>map</span><span class='lparen'>(</span><span class='op'>&amp;</span><span class='symbol'>:strip</span><span class='rparen'>)</span>
<span class='period'>.</span><span class='id identifier rubyid_map'>map</span> <span class='kw'>do</span> <span class='op'>|</span><span class='id identifier rubyid_o'>o</span><span class='op'>|</span>
<span class='id identifier rubyid_value'>value</span><span class='comma'>,</span> <span class='id identifier rubyid_tag'>tag</span> <span class='op'>=</span> <span class='id identifier rubyid_o'>o</span><span class='period'>.</span><span class='id identifier rubyid_split'>split</span><span class='lparen'>(</span><span class='tstring'><span class='regexp_beg'>/</span><span class='tstring_content'> </span><span class='regexp_end'>/</span></span><span class='comma'>,</span> <span class='int'>2</span><span class='rparen'>)</span>
<span class='id identifier rubyid_raise'>raise</span><span class='lparen'>(</span><span class='tstring'><span class='tstring_beg'>&quot;</span><span class='tstring_content'>Invalid line in </span><span class='embexpr_beg'>#{</span><span class='id identifier rubyid_file'>file</span><span class='embexpr_end'>}</span><span class='tstring_content'>: </span><span class='embexpr_beg'>#{</span><span class='id identifier rubyid_o'>o</span><span class='embexpr_end'>}</span><span class='tstring_end'>&quot;</span></span><span class='rparen'>)</span> <span class='kw'>if</span> <span class='id identifier rubyid_tag'>tag</span><span class='period'>.</span><span class='id identifier rubyid_nil?'>nil?</span>
<span class='lbracket'>[</span><span class='id identifier rubyid_value'>value</span><span class='period'>.</span><span class='id identifier rubyid_to_i'>to_i</span><span class='lparen'>(</span><span class='int'>16</span><span class='rparen'>)</span><span class='comma'>,</span> <span class='id identifier rubyid_tag'>tag</span><span class='rbracket'>]</span>
<span class='kw'>end</span>
<span class='period'>.</span><span class='id identifier rubyid_to_h'>to_h</span>
<span class='period'>.</span><span class='id identifier rubyid_freeze'>freeze</span>
<span class='ivar'>@tags_by_name</span> <span class='op'>=</span> <span class='ivar'>@tags_by_id</span><span class='period'>.</span><span class='id identifier rubyid_invert'>invert</span><span class='period'>.</span><span class='id identifier rubyid_freeze'>freeze</span>
<span class='kw'>super</span><span class='lparen'>(</span><span class='id identifier rubyid_info'>info</span><span class='rparen'>)</span>
<span class='kw'>end</span></pre>
</td>
</tr>
</table>
</div>
<div class="method_details ">
<h3 class="signature " id="mcp_build-instance_method">
#<strong>mcp_build</strong>(tag, type, data) &#x21d2; <tt>Object</tt>
</h3><div class="docstring">
<div class="discussion">
<p>Build an mcp message</p>
<p>Adapted from <a href="https://github.com/rbowes-r7/refreshing-mcp-tool/blob/main/mcp-builder.rb">github.com/rbowes-r7/refreshing-mcp-tool/blob/main/mcp-builder.rb</a></p>
</div>
</div>
<div class="tags">
</div><table class="source_code">
<tr>
<td>
<pre class="lines">
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326</pre>
</td>
<td>
<pre class="code"><span class="info file"># File 'lib/msf/core/post/linux/f5_mcp.rb', line 292</span>
<span class='kw'>def</span> <span class='id identifier rubyid_mcp_build'>mcp_build</span><span class='lparen'>(</span><span class='id identifier rubyid_tag'>tag</span><span class='comma'>,</span> <span class='id identifier rubyid_type'>type</span><span class='comma'>,</span> <span class='id identifier rubyid_data'>data</span><span class='rparen'>)</span>
<span class='kw'>if</span> <span class='ivar'>@tags_by_name</span><span class='lbracket'>[</span><span class='id identifier rubyid_tag'>tag</span><span class='rbracket'>]</span><span class='period'>.</span><span class='id identifier rubyid_nil?'>nil?</span>
<span class='id identifier rubyid_raise'>raise</span> <span class='tstring'><span class='tstring_beg'>&quot;</span><span class='tstring_content'>Invalid mcp tag: </span><span class='embexpr_beg'>#{</span><span class='id identifier rubyid_tag'>tag</span><span class='embexpr_end'>}</span><span class='tstring_end'>&quot;</span></span>
<span class='kw'>end</span>
<span class='kw'>if</span> <span class='ivar'>@tags_by_name</span><span class='lbracket'>[</span><span class='id identifier rubyid_type'>type</span><span class='rbracket'>]</span><span class='period'>.</span><span class='id identifier rubyid_nil?'>nil?</span>
<span class='id identifier rubyid_raise'>raise</span> <span class='tstring'><span class='tstring_beg'>&quot;</span><span class='tstring_content'>Invalid mcp type: </span><span class='embexpr_beg'>#{</span><span class='id identifier rubyid_type'>type</span><span class='embexpr_end'>}</span><span class='tstring_end'>&quot;</span></span>
<span class='kw'>end</span>
<span class='id identifier rubyid_out'>out</span> <span class='op'>=</span> <span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_end'>&#39;</span></span>
<span class='kw'>if</span> <span class='id identifier rubyid_type'>type</span> <span class='op'>==</span> <span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>structure</span><span class='tstring_end'>&#39;</span></span>
<span class='id identifier rubyid_out'>out</span> <span class='op'>=</span> <span class='lbracket'>[</span><span class='id identifier rubyid_data'>data</span><span class='period'>.</span><span class='id identifier rubyid_join'>join</span><span class='period'>.</span><span class='id identifier rubyid_length'>length</span><span class='comma'>,</span> <span class='id identifier rubyid_data'>data</span><span class='period'>.</span><span class='id identifier rubyid_join'>join</span><span class='rbracket'>]</span><span class='period'>.</span><span class='id identifier rubyid_pack'>pack</span><span class='lparen'>(</span><span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>Na*</span><span class='tstring_end'>&#39;</span></span><span class='rparen'>)</span>
<span class='kw'>elsif</span> <span class='id identifier rubyid_type'>type</span> <span class='op'>==</span> <span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>string</span><span class='tstring_end'>&#39;</span></span>
<span class='id identifier rubyid_out'>out</span> <span class='op'>=</span> <span class='lbracket'>[</span><span class='id identifier rubyid_data'>data</span><span class='period'>.</span><span class='id identifier rubyid_length'>length</span> <span class='op'>+</span> <span class='int'>2</span><span class='comma'>,</span> <span class='id identifier rubyid_data'>data</span><span class='period'>.</span><span class='id identifier rubyid_length'>length</span><span class='comma'>,</span> <span class='id identifier rubyid_data'>data</span><span class='rbracket'>]</span><span class='period'>.</span><span class='id identifier rubyid_pack'>pack</span><span class='lparen'>(</span><span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>Nna*</span><span class='tstring_end'>&#39;</span></span><span class='rparen'>)</span>
<span class='kw'>elsif</span> <span class='id identifier rubyid_type'>type</span> <span class='op'>==</span> <span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>uquad</span><span class='tstring_end'>&#39;</span></span>
<span class='id identifier rubyid_out'>out</span> <span class='op'>=</span> <span class='lbracket'>[</span><span class='id identifier rubyid_data'>data</span><span class='rbracket'>]</span><span class='period'>.</span><span class='id identifier rubyid_pack'>pack</span><span class='lparen'>(</span><span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>Q&gt;</span><span class='tstring_end'>&#39;</span></span><span class='rparen'>)</span>
<span class='kw'>elsif</span> <span class='id identifier rubyid_type'>type</span> <span class='op'>==</span> <span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>ulong</span><span class='tstring_end'>&#39;</span></span>
<span class='id identifier rubyid_out'>out</span> <span class='op'>=</span> <span class='lbracket'>[</span><span class='id identifier rubyid_data'>data</span><span class='rbracket'>]</span><span class='period'>.</span><span class='id identifier rubyid_pack'>pack</span><span class='lparen'>(</span><span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>N</span><span class='tstring_end'>&#39;</span></span><span class='rparen'>)</span>
<span class='kw'>elsif</span> <span class='id identifier rubyid_type'>type</span> <span class='op'>==</span> <span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>uword</span><span class='tstring_end'>&#39;</span></span>
<span class='id identifier rubyid_out'>out</span> <span class='op'>=</span> <span class='lbracket'>[</span><span class='id identifier rubyid_data'>data</span><span class='rbracket'>]</span><span class='period'>.</span><span class='id identifier rubyid_pack'>pack</span><span class='lparen'>(</span><span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>n</span><span class='tstring_end'>&#39;</span></span><span class='rparen'>)</span>
<span class='kw'>elsif</span> <span class='id identifier rubyid_type'>type</span> <span class='op'>==</span> <span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>long</span><span class='tstring_end'>&#39;</span></span>
<span class='id identifier rubyid_out'>out</span> <span class='op'>=</span> <span class='lbracket'>[</span><span class='id identifier rubyid_data'>data</span><span class='rbracket'>]</span><span class='period'>.</span><span class='id identifier rubyid_pack'>pack</span><span class='lparen'>(</span><span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>N</span><span class='tstring_end'>&#39;</span></span><span class='rparen'>)</span>
<span class='kw'>elsif</span> <span class='id identifier rubyid_type'>type</span> <span class='op'>==</span> <span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>tag</span><span class='tstring_end'>&#39;</span></span>
<span class='id identifier rubyid_out'>out</span> <span class='op'>=</span> <span class='lbracket'>[</span><span class='ivar'>@tags_by_name</span><span class='lbracket'>[</span><span class='id identifier rubyid_data'>data</span><span class='rbracket'>]</span><span class='rbracket'>]</span><span class='period'>.</span><span class='id identifier rubyid_pack'>pack</span><span class='lparen'>(</span><span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>n</span><span class='tstring_end'>&#39;</span></span><span class='rparen'>)</span>
<span class='kw'>elsif</span> <span class='id identifier rubyid_type'>type</span> <span class='op'>==</span> <span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>byte</span><span class='tstring_end'>&#39;</span></span>
<span class='id identifier rubyid_out'>out</span> <span class='op'>=</span> <span class='lbracket'>[</span><span class='id identifier rubyid_data'>data</span><span class='rbracket'>]</span><span class='period'>.</span><span class='id identifier rubyid_pack'>pack</span><span class='lparen'>(</span><span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>C</span><span class='tstring_end'>&#39;</span></span><span class='rparen'>)</span>
<span class='kw'>elsif</span> <span class='id identifier rubyid_type'>type</span> <span class='op'>==</span> <span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>mac</span><span class='tstring_end'>&#39;</span></span>
<span class='id identifier rubyid_out'>out</span> <span class='op'>=</span> <span class='lbracket'>[</span><span class='id identifier rubyid_data'>data</span><span class='rbracket'>]</span><span class='period'>.</span><span class='id identifier rubyid_pack'>pack</span><span class='lparen'>(</span><span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>a6</span><span class='tstring_end'>&#39;</span></span><span class='rparen'>)</span>
<span class='kw'>else</span>
<span class='id identifier rubyid_raise'>raise</span> <span class='tstring'><span class='tstring_beg'>&quot;</span><span class='tstring_content'>Unknown type: </span><span class='embexpr_beg'>#{</span><span class='id identifier rubyid_type'>type</span><span class='embexpr_end'>}</span><span class='tstring_end'>&quot;</span></span>
<span class='kw'>end</span>
<span class='id identifier rubyid_out'>out</span> <span class='op'>=</span> <span class='lbracket'>[</span><span class='ivar'>@tags_by_name</span><span class='lbracket'>[</span><span class='id identifier rubyid_tag'>tag</span><span class='rbracket'>]</span><span class='comma'>,</span> <span class='ivar'>@tags_by_name</span><span class='lbracket'>[</span><span class='id identifier rubyid_type'>type</span><span class='rbracket'>]</span><span class='comma'>,</span> <span class='id identifier rubyid_out'>out</span><span class='rbracket'>]</span><span class='period'>.</span><span class='id identifier rubyid_pack'>pack</span><span class='lparen'>(</span><span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>nna*</span><span class='tstring_end'>&#39;</span></span><span class='rparen'>)</span>
<span class='kw'>return</span> <span class='id identifier rubyid_out'>out</span>
<span class='kw'>end</span></pre>
</td>
</tr>
</table>
</div>
<div class="method_details ">
<h3 class="signature " id="mcp_get_multiple-instance_method">
#<strong>mcp_get_multiple</strong>(hash, name) &#x21d2; <tt>Object</tt>
</h3><div class="docstring">
<div class="discussion">
<p>Pull an array of tags with the same name out of a tag/value structure. For example, when you perform a query for userdb_entry`, it returns multiple tags with the same name.</p>
<p>The result is:</p>
<ul><li>
<p>If there are no values, return an empty array</p>
</li><li>
<p>If there are one or more values, return them as an array</p>
</li></ul>
</div>
</div>
<div class="tags">
</div><table class="source_code">
<tr>
<td>
<pre class="lines">
274
275
276</pre>
</td>
<td>
<pre class="code"><span class="info file"># File 'lib/msf/core/post/linux/f5_mcp.rb', line 274</span>
<span class='kw'>def</span> <span class='id identifier rubyid_mcp_get_multiple'>mcp_get_multiple</span><span class='lparen'>(</span><span class='id identifier rubyid_hash'>hash</span><span class='comma'>,</span> <span class='id identifier rubyid_name'>name</span><span class='rparen'>)</span>
<span class='id identifier rubyid_hash'>hash</span><span class='period'>.</span><span class='id identifier rubyid_select'>select</span> <span class='lbrace'>{</span> <span class='op'>|</span><span class='id identifier rubyid_entry'>entry</span><span class='op'>|</span> <span class='id identifier rubyid_entry'>entry</span><span class='lbracket'>[</span><span class='symbol'>:tag</span><span class='rbracket'>]</span> <span class='op'>==</span> <span class='id identifier rubyid_name'>name</span> <span class='rbrace'>}</span><span class='period'>.</span><span class='id identifier rubyid_map'>map</span> <span class='lbrace'>{</span> <span class='op'>|</span><span class='id identifier rubyid_entry'>entry</span><span class='op'>|</span> <span class='id identifier rubyid_entry'>entry</span><span class='lbracket'>[</span><span class='symbol'>:value</span><span class='rbracket'>]</span> <span class='rbrace'>}</span>
<span class='kw'>end</span></pre>
</td>
</tr>
</table>
</div>
<div class="method_details ">
<h3 class="signature " id="mcp_get_single-instance_method">
#<strong>mcp_get_single</strong>(hash, name) &#x21d2; <tt>Object</tt>
</h3><div class="docstring">
<div class="discussion">
<p>Pull a single value out of a tag/value structure (ie, the thing returned by mcp_parse()). The result is:</p>
<ul><li>
<p>If there are no values with that tag name, return nil</p>
</li><li>
<p>If theres a single value with that tag name, return it</p>
</li><li>
<p>If there are multiple values with that tag name, print an error and return nil</p>
</li></ul>
</div>
</div>
<div class="tags">
</div><table class="source_code">
<tr>
<td>
<pre class="lines">
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265</pre>
</td>
<td>
<pre class="code"><span class="info file"># File 'lib/msf/core/post/linux/f5_mcp.rb', line 250</span>
<span class='kw'>def</span> <span class='id identifier rubyid_mcp_get_single'>mcp_get_single</span><span class='lparen'>(</span><span class='id identifier rubyid_hash'>hash</span><span class='comma'>,</span> <span class='id identifier rubyid_name'>name</span><span class='rparen'>)</span>
<span class='comment'># Get all the entries
</span> <span class='id identifier rubyid_entries'>entries</span> <span class='op'>=</span> <span class='id identifier rubyid_mcp_get_multiple'>mcp_get_multiple</span><span class='lparen'>(</span><span class='id identifier rubyid_hash'>hash</span><span class='comma'>,</span> <span class='id identifier rubyid_name'>name</span><span class='rparen'>)</span>
<span class='kw'>if</span> <span class='id identifier rubyid_entries'>entries</span><span class='period'>.</span><span class='id identifier rubyid_empty?'>empty?</span>
<span class='comment'># If there are none, return nil
</span> <span class='kw'>return</span> <span class='kw'>nil</span>
<span class='kw'>elsif</span> <span class='id identifier rubyid_entries'>entries</span><span class='period'>.</span><span class='id identifier rubyid_length'>length</span> <span class='op'>==</span> <span class='int'>1</span>
<span class='comment'># If there&#39;s one, return it
</span> <span class='kw'>return</span> <span class='id identifier rubyid_entries'>entries</span><span class='period'>.</span><span class='id identifier rubyid_pop'>pop</span>
<span class='kw'>else</span>
<span class='comment'># If there are multiple entries, print a warning and return nil
</span> <span class='id identifier rubyid_print_error'>print_error</span><span class='lparen'>(</span><span class='tstring'><span class='tstring_beg'>&quot;</span><span class='tstring_content'>Query for mcp type </span><span class='embexpr_beg'>#{</span><span class='id identifier rubyid_name'>name</span><span class='embexpr_end'>}</span><span class='tstring_content'> was supposed to have one response but had </span><span class='embexpr_beg'>#{</span><span class='id identifier rubyid_entries'>entries</span><span class='period'>.</span><span class='id identifier rubyid_length'>length</span><span class='embexpr_end'>}</span><span class='tstring_end'>&quot;</span></span><span class='rparen'>)</span>
<span class='kw'>return</span> <span class='kw'>nil</span>
<span class='kw'>end</span>
<span class='kw'>end</span></pre>
</td>
</tr>
</table>
</div>
<div class="method_details ">
<h3 class="signature " id="mcp_parse-instance_method">
#<strong>mcp_parse</strong>(stream) &#x21d2; <tt>Object</tt>
</h3><div class="docstring">
<div class="discussion">
<p>Recursively parse an mcp message from a binary stream into an object</p>
<p>Adapted from <a href="https://github.com/rbowes-r7/refreshing-mcp-tool/blob/main/mcp-parser.rb">github.com/rbowes-r7/refreshing-mcp-tool/blob/main/mcp-parser.rb</a></p>
</div>
</div>
<div class="tags">
</div><table class="source_code">
<tr>
<td>
<pre class="lines">
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241</pre>
</td>
<td>
<pre class="code"><span class="info file"># File 'lib/msf/core/post/linux/f5_mcp.rb', line 142</span>
<span class='kw'>def</span> <span class='id identifier rubyid_mcp_parse'>mcp_parse</span><span class='lparen'>(</span><span class='id identifier rubyid_stream'>stream</span><span class='rparen'>)</span>
<span class='comment'># Reminder: this has to be an array, not a hash, because there are
</span> <span class='comment'># often duplicate entries (like multiple userdb_entry results when a
</span> <span class='comment'># query is performed).
</span> <span class='id identifier rubyid_result'>result</span> <span class='op'>=</span> <span class='lbracket'>[</span><span class='rbracket'>]</span>
<span class='comment'># Make a Hash of parsers. Some of them are recursive, which is fun!
</span> <span class='comment'>#
</span> <span class='comment'># They all take the stream as an input argument, and return
</span> <span class='comment'># [value, stream]
</span> <span class='id identifier rubyid_parsers'>parsers</span> <span class='op'>=</span> <span class='lbrace'>{</span>
<span class='comment'># The easy stuff - simple values
</span> <span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>ulong</span><span class='tstring_end'>&#39;</span></span> <span class='op'>=&gt;</span> <span class='id identifier rubyid_proc'>proc</span> <span class='lbrace'>{</span> <span class='op'>|</span><span class='id identifier rubyid_s'>s</span><span class='op'>|</span> <span class='id identifier rubyid_s'>s</span><span class='period'>.</span><span class='id identifier rubyid_unpack'>unpack</span><span class='lparen'>(</span><span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>Na*</span><span class='tstring_end'>&#39;</span></span><span class='rparen'>)</span> <span class='rbrace'>}</span><span class='comma'>,</span>
<span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>long</span><span class='tstring_end'>&#39;</span></span> <span class='op'>=&gt;</span> <span class='id identifier rubyid_proc'>proc</span> <span class='lbrace'>{</span> <span class='op'>|</span><span class='id identifier rubyid_s'>s</span><span class='op'>|</span> <span class='id identifier rubyid_s'>s</span><span class='period'>.</span><span class='id identifier rubyid_unpack'>unpack</span><span class='lparen'>(</span><span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>Na*</span><span class='tstring_end'>&#39;</span></span><span class='rparen'>)</span> <span class='rbrace'>}</span><span class='comma'>,</span>
<span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>uquad</span><span class='tstring_end'>&#39;</span></span> <span class='op'>=&gt;</span> <span class='id identifier rubyid_proc'>proc</span> <span class='lbrace'>{</span> <span class='op'>|</span><span class='id identifier rubyid_s'>s</span><span class='op'>|</span> <span class='id identifier rubyid_s'>s</span><span class='period'>.</span><span class='id identifier rubyid_unpack'>unpack</span><span class='lparen'>(</span><span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>Q&gt;a*</span><span class='tstring_end'>&#39;</span></span><span class='rparen'>)</span> <span class='rbrace'>}</span><span class='comma'>,</span>
<span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>uword</span><span class='tstring_end'>&#39;</span></span> <span class='op'>=&gt;</span> <span class='id identifier rubyid_proc'>proc</span> <span class='lbrace'>{</span> <span class='op'>|</span><span class='id identifier rubyid_s'>s</span><span class='op'>|</span> <span class='id identifier rubyid_s'>s</span><span class='period'>.</span><span class='id identifier rubyid_unpack'>unpack</span><span class='lparen'>(</span><span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>na*</span><span class='tstring_end'>&#39;</span></span><span class='rparen'>)</span> <span class='rbrace'>}</span><span class='comma'>,</span>
<span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>byte</span><span class='tstring_end'>&#39;</span></span> <span class='op'>=&gt;</span> <span class='id identifier rubyid_proc'>proc</span> <span class='lbrace'>{</span> <span class='op'>|</span><span class='id identifier rubyid_s'>s</span><span class='op'>|</span> <span class='id identifier rubyid_s'>s</span><span class='period'>.</span><span class='id identifier rubyid_unpack'>unpack</span><span class='lparen'>(</span><span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>Ca*</span><span class='tstring_end'>&#39;</span></span><span class='rparen'>)</span> <span class='rbrace'>}</span><span class='comma'>,</span>
<span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>service</span><span class='tstring_end'>&#39;</span></span> <span class='op'>=&gt;</span> <span class='id identifier rubyid_proc'>proc</span> <span class='lbrace'>{</span> <span class='op'>|</span><span class='id identifier rubyid_s'>s</span><span class='op'>|</span> <span class='id identifier rubyid_s'>s</span><span class='period'>.</span><span class='id identifier rubyid_unpack'>unpack</span><span class='lparen'>(</span><span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>na*</span><span class='tstring_end'>&#39;</span></span><span class='rparen'>)</span> <span class='rbrace'>}</span><span class='comma'>,</span>
<span class='comment'># Parse &#39;time&#39; as a time
</span> <span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>time</span><span class='tstring_end'>&#39;</span></span> <span class='op'>=&gt;</span> <span class='id identifier rubyid_proc'>proc</span> <span class='kw'>do</span> <span class='op'>|</span><span class='id identifier rubyid_s'>s</span><span class='op'>|</span>
<span class='id identifier rubyid_value'>value</span><span class='comma'>,</span> <span class='id identifier rubyid_s'>s</span> <span class='op'>=</span> <span class='id identifier rubyid_s'>s</span><span class='period'>.</span><span class='id identifier rubyid_unpack'>unpack</span><span class='lparen'>(</span><span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>Na*</span><span class='tstring_end'>&#39;</span></span><span class='rparen'>)</span>
<span class='lbracket'>[</span><span class='const'>Time</span><span class='period'>.</span><span class='id identifier rubyid_at'>at</span><span class='lparen'>(</span><span class='id identifier rubyid_value'>value</span><span class='rparen'>)</span><span class='comma'>,</span> <span class='id identifier rubyid_s'>s</span><span class='rbracket'>]</span>
<span class='kw'>end</span><span class='comma'>,</span>
<span class='comment'># Look up &#39;tag&#39; values
</span> <span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>tag</span><span class='tstring_end'>&#39;</span></span> <span class='op'>=&gt;</span> <span class='id identifier rubyid_proc'>proc</span> <span class='kw'>do</span> <span class='op'>|</span><span class='id identifier rubyid_s'>s</span><span class='op'>|</span>
<span class='id identifier rubyid_value'>value</span><span class='comma'>,</span> <span class='id identifier rubyid_s'>s</span> <span class='op'>=</span> <span class='id identifier rubyid_s'>s</span><span class='period'>.</span><span class='id identifier rubyid_unpack'>unpack</span><span class='lparen'>(</span><span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>na*</span><span class='tstring_end'>&#39;</span></span><span class='rparen'>)</span>
<span class='lbracket'>[</span><span class='ivar'>@tags_by_id</span><span class='lbracket'>[</span><span class='id identifier rubyid_value'>value</span><span class='rbracket'>]</span><span class='comma'>,</span> <span class='id identifier rubyid_s'>s</span><span class='rbracket'>]</span>
<span class='kw'>end</span><span class='comma'>,</span>
<span class='comment'># Parse MAC addresses
</span> <span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>mac</span><span class='tstring_end'>&#39;</span></span> <span class='op'>=&gt;</span> <span class='id identifier rubyid_proc'>proc</span> <span class='kw'>do</span> <span class='op'>|</span><span class='id identifier rubyid_s'>s</span><span class='op'>|</span>
<span class='id identifier rubyid_value'>value</span><span class='comma'>,</span> <span class='id identifier rubyid_s'>s</span> <span class='op'>=</span> <span class='id identifier rubyid_s'>s</span><span class='period'>.</span><span class='id identifier rubyid_unpack'>unpack</span><span class='lparen'>(</span><span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>a6a*</span><span class='tstring_end'>&#39;</span></span><span class='rparen'>)</span>
<span class='lbracket'>[</span><span class='id identifier rubyid_value'>value</span><span class='period'>.</span><span class='id identifier rubyid_bytes'>bytes</span><span class='period'>.</span><span class='id identifier rubyid_map'>map</span> <span class='lbrace'>{</span> <span class='op'>|</span><span class='id identifier rubyid_b'>b</span><span class='op'>|</span> <span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>%02x</span><span class='tstring_end'>&#39;</span></span><span class='period'>.</span><span class='id identifier rubyid_format'>format</span><span class='lparen'>(</span><span class='id identifier rubyid_b'>b</span><span class='rparen'>)</span> <span class='rbrace'>}</span><span class='period'>.</span><span class='id identifier rubyid_join'><span class='object_link'><a href="../../../top-level-namespace.html#join-instance_method" title="#join (method)">join</a></span></span><span class='lparen'>(</span><span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>:</span><span class='tstring_end'>&#39;</span></span><span class='rparen'>)</span><span class='comma'>,</span> <span class='id identifier rubyid_s'>s</span><span class='rbracket'>]</span>
<span class='kw'>end</span><span class='comma'>,</span>
<span class='comment'># &#39;string&#39; is prefixed by two length values
</span> <span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>string</span><span class='tstring_end'>&#39;</span></span> <span class='op'>=&gt;</span> <span class='id identifier rubyid_proc'>proc</span> <span class='kw'>do</span> <span class='op'>|</span><span class='id identifier rubyid_s'>s</span><span class='op'>|</span>
<span class='id identifier rubyid_length'>length</span><span class='comma'>,</span> <span class='id identifier rubyid_otherlength'>otherlength</span><span class='comma'>,</span> <span class='id identifier rubyid_s'>s</span> <span class='op'>=</span> <span class='id identifier rubyid_s'>s</span><span class='period'>.</span><span class='id identifier rubyid_unpack'>unpack</span><span class='lparen'>(</span><span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>Nna*</span><span class='tstring_end'>&#39;</span></span><span class='rparen'>)</span>
<span class='comment'># I&#39;m sure the two length values have a semantic difference, but just check for sanity
</span> <span class='kw'>if</span> <span class='id identifier rubyid_otherlength'>otherlength</span> <span class='op'>+</span> <span class='int'>2</span> <span class='op'>!=</span> <span class='id identifier rubyid_length'>length</span>
<span class='id identifier rubyid_raise'>raise</span> <span class='tstring'><span class='tstring_beg'>&quot;</span><span class='tstring_content'>Inconsistent string lengths: </span><span class='embexpr_beg'>#{</span><span class='id identifier rubyid_length'>length</span><span class='embexpr_end'>}</span><span class='tstring_content'> + </span><span class='embexpr_beg'>#{</span><span class='id identifier rubyid_otherlength'>otherlength</span><span class='embexpr_end'>}</span><span class='tstring_end'>&quot;</span></span>
<span class='kw'>end</span>
<span class='id identifier rubyid_s'>s</span><span class='period'>.</span><span class='id identifier rubyid_unpack'>unpack</span><span class='lparen'>(</span><span class='tstring'><span class='tstring_beg'>&quot;</span><span class='tstring_content'>a</span><span class='embexpr_beg'>#{</span><span class='id identifier rubyid_otherlength'>otherlength</span><span class='embexpr_end'>}</span><span class='tstring_content'>a*</span><span class='tstring_end'>&quot;</span></span><span class='rparen'>)</span>
<span class='kw'>end</span><span class='comma'>,</span>
<span class='comment'># &#39;structure&#39; is recursive
</span> <span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>structure</span><span class='tstring_end'>&#39;</span></span> <span class='op'>=&gt;</span> <span class='id identifier rubyid_proc'>proc</span> <span class='kw'>do</span> <span class='op'>|</span><span class='id identifier rubyid_s'>s</span><span class='op'>|</span>
<span class='id identifier rubyid_length'>length</span><span class='comma'>,</span> <span class='id identifier rubyid_s'>s</span> <span class='op'>=</span> <span class='id identifier rubyid_s'>s</span><span class='period'>.</span><span class='id identifier rubyid_unpack'>unpack</span><span class='lparen'>(</span><span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>Na*</span><span class='tstring_end'>&#39;</span></span><span class='rparen'>)</span>
<span class='id identifier rubyid_struct'>struct</span><span class='comma'>,</span> <span class='id identifier rubyid_s'>s</span> <span class='op'>=</span> <span class='id identifier rubyid_s'>s</span><span class='period'>.</span><span class='id identifier rubyid_unpack'>unpack</span><span class='lparen'>(</span><span class='tstring'><span class='tstring_beg'>&quot;</span><span class='tstring_content'>a</span><span class='embexpr_beg'>#{</span><span class='id identifier rubyid_length'>length</span><span class='embexpr_end'>}</span><span class='tstring_content'>a*</span><span class='tstring_end'>&quot;</span></span><span class='rparen'>)</span>
<span class='lbracket'>[</span><span class='id identifier rubyid_mcp_parse'>mcp_parse</span><span class='lparen'>(</span><span class='id identifier rubyid_struct'>struct</span><span class='rparen'>)</span><span class='comma'>,</span> <span class='id identifier rubyid_s'>s</span><span class='rbracket'>]</span>
<span class='kw'>end</span><span class='comma'>,</span>
<span class='comment'># &#39;array&#39; is a bunch of consecutive values of the same type, which
</span> <span class='comment'># means we need to index back into this same parser array
</span> <span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>array</span><span class='tstring_end'>&#39;</span></span> <span class='op'>=&gt;</span> <span class='id identifier rubyid_proc'>proc</span> <span class='kw'>do</span> <span class='op'>|</span><span class='id identifier rubyid_s'>s</span><span class='op'>|</span>
<span class='id identifier rubyid_length'>length</span><span class='comma'>,</span> <span class='id identifier rubyid_s'>s</span> <span class='op'>=</span> <span class='id identifier rubyid_s'>s</span><span class='period'>.</span><span class='id identifier rubyid_unpack'>unpack</span><span class='lparen'>(</span><span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>Na*</span><span class='tstring_end'>&#39;</span></span><span class='rparen'>)</span>
<span class='id identifier rubyid_array'>array</span><span class='comma'>,</span> <span class='id identifier rubyid_s'>s</span> <span class='op'>=</span> <span class='id identifier rubyid_s'>s</span><span class='period'>.</span><span class='id identifier rubyid_unpack'>unpack</span><span class='lparen'>(</span><span class='tstring'><span class='tstring_beg'>&quot;</span><span class='tstring_content'>a</span><span class='embexpr_beg'>#{</span><span class='id identifier rubyid_length'>length</span><span class='embexpr_end'>}</span><span class='tstring_content'>a*</span><span class='tstring_end'>&quot;</span></span><span class='rparen'>)</span>
<span class='id identifier rubyid_type'>type</span><span class='comma'>,</span> <span class='id identifier rubyid_elements'>elements</span><span class='comma'>,</span> <span class='id identifier rubyid_array'>array</span> <span class='op'>=</span> <span class='id identifier rubyid_array'>array</span><span class='period'>.</span><span class='id identifier rubyid_unpack'>unpack</span><span class='lparen'>(</span><span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>nNa*</span><span class='tstring_end'>&#39;</span></span><span class='rparen'>)</span>
<span class='id identifier rubyid_type'>type</span> <span class='op'>=</span> <span class='ivar'>@tags_by_id</span><span class='lbracket'>[</span><span class='id identifier rubyid_type'>type</span><span class='rbracket'>]</span> <span class='op'>||</span> <span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>&lt;unknown type 0x%04x&gt;</span><span class='tstring_end'>&#39;</span></span><span class='period'>.</span><span class='id identifier rubyid_format'>format</span><span class='lparen'>(</span><span class='id identifier rubyid_type'>type</span><span class='rparen'>)</span>
<span class='id identifier rubyid_array_results'>array_results</span> <span class='op'>=</span> <span class='lbracket'>[</span><span class='rbracket'>]</span>
<span class='id identifier rubyid_elements'>elements</span><span class='period'>.</span><span class='id identifier rubyid_times'>times</span> <span class='kw'>do</span>
<span class='id identifier rubyid_array_result'>array_result</span><span class='comma'>,</span> <span class='id identifier rubyid_array'>array</span> <span class='op'>=</span> <span class='id identifier rubyid_parsers'>parsers</span><span class='lbracket'>[</span><span class='id identifier rubyid_type'>type</span><span class='rbracket'>]</span><span class='period'>.</span><span class='id identifier rubyid_call'>call</span><span class='lparen'>(</span><span class='id identifier rubyid_array'>array</span><span class='rparen'>)</span>
<span class='id identifier rubyid_array_results'>array_results</span> <span class='op'>&lt;&lt;</span> <span class='id identifier rubyid_array_result'>array_result</span>
<span class='kw'>end</span>
<span class='lbracket'>[</span><span class='id identifier rubyid_array_results'>array_results</span><span class='comma'>,</span> <span class='id identifier rubyid_s'>s</span><span class='rbracket'>]</span>
<span class='kw'>end</span>
<span class='rbrace'>}</span>
<span class='kw'>begin</span>
<span class='kw'>while</span> <span class='id identifier rubyid_stream'>stream</span><span class='period'>.</span><span class='id identifier rubyid_length'>length</span> <span class='op'>&gt;</span> <span class='int'>2</span>
<span class='id identifier rubyid_tag'>tag</span><span class='comma'>,</span> <span class='id identifier rubyid_type'>type</span><span class='comma'>,</span> <span class='id identifier rubyid_stream'>stream</span> <span class='op'>=</span> <span class='id identifier rubyid_stream'>stream</span><span class='period'>.</span><span class='id identifier rubyid_unpack'>unpack</span><span class='lparen'>(</span><span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>nna*</span><span class='tstring_end'>&#39;</span></span><span class='rparen'>)</span>
<span class='id identifier rubyid_tag'>tag</span> <span class='op'>=</span> <span class='ivar'>@tags_by_id</span><span class='lbracket'>[</span><span class='id identifier rubyid_tag'>tag</span><span class='rbracket'>]</span> <span class='op'>||</span> <span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>&lt;unknown tag 0x%04x&gt;</span><span class='tstring_end'>&#39;</span></span><span class='period'>.</span><span class='id identifier rubyid_format'>format</span><span class='lparen'>(</span><span class='id identifier rubyid_tag'>tag</span><span class='rparen'>)</span>
<span class='id identifier rubyid_type'>type</span> <span class='op'>=</span> <span class='ivar'>@tags_by_id</span><span class='lbracket'>[</span><span class='id identifier rubyid_type'>type</span><span class='rbracket'>]</span> <span class='op'>||</span> <span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>&lt;unknown type 0x%04x&gt;</span><span class='tstring_end'>&#39;</span></span><span class='period'>.</span><span class='id identifier rubyid_format'>format</span><span class='lparen'>(</span><span class='id identifier rubyid_type'>type</span><span class='rparen'>)</span>
<span class='kw'>if</span> <span class='id identifier rubyid_parsers'>parsers</span><span class='lbracket'>[</span><span class='id identifier rubyid_type'>type</span><span class='rbracket'>]</span>
<span class='id identifier rubyid_value'>value</span><span class='comma'>,</span> <span class='id identifier rubyid_stream'>stream</span> <span class='op'>=</span> <span class='id identifier rubyid_parsers'>parsers</span><span class='lbracket'>[</span><span class='id identifier rubyid_type'>type</span><span class='rbracket'>]</span><span class='period'>.</span><span class='id identifier rubyid_call'>call</span><span class='lparen'>(</span><span class='id identifier rubyid_stream'>stream</span><span class='rparen'>)</span>
<span class='id identifier rubyid_result'>result</span> <span class='op'>&lt;&lt;</span> <span class='lbrace'>{</span>
<span class='label'>tag:</span> <span class='id identifier rubyid_tag'>tag</span><span class='comma'>,</span>
<span class='label'>value:</span> <span class='id identifier rubyid_value'>value</span>
<span class='rbrace'>}</span>
<span class='kw'>else</span>
<span class='id identifier rubyid_raise'>raise</span> <span class='tstring'><span class='tstring_beg'>&quot;</span><span class='tstring_content'>Tried to parse unknown mcp type (skipping): type = </span><span class='embexpr_beg'>#{</span><span class='id identifier rubyid_type'>type</span><span class='embexpr_end'>}</span><span class='tstring_content'>, tag = </span><span class='embexpr_beg'>#{</span><span class='id identifier rubyid_tag'>tag</span><span class='embexpr_end'>}</span><span class='tstring_end'>&quot;</span></span>
<span class='kw'>end</span>
<span class='kw'>end</span>
<span class='kw'>rescue</span> <span class='const'>StandardError</span> <span class='op'>=&gt;</span> <span class='id identifier rubyid_e'>e</span>
<span class='comment'># If we fail somewhere, print a warning but return what we have
</span> <span class='id identifier rubyid_print_warning'>print_warning</span><span class='lparen'>(</span><span class='tstring'><span class='tstring_beg'>&quot;</span><span class='tstring_content'>Parsing mcp data failed: </span><span class='embexpr_beg'>#{</span><span class='id identifier rubyid_e'>e</span><span class='period'>.</span><span class='id identifier rubyid_message'>message</span><span class='embexpr_end'>}</span><span class='tstring_end'>&quot;</span></span><span class='rparen'>)</span>
<span class='kw'>end</span>
<span class='id identifier rubyid_result'>result</span>
<span class='kw'>end</span></pre>
</td>
</tr>
</table>
</div>
<div class="method_details ">
<h3 class="signature " id="mcp_parse_responses-instance_method">
#<strong>mcp_parse_responses</strong>(incoming_data) &#x21d2; <tt>Object</tt>
</h3><div class="docstring">
<div class="discussion">
<p>Parse one or more packets (including headers) into an array of packets.</p>
</div>
</div>
<div class="tags">
</div><table class="source_code">
<tr>
<td>
<pre class="lines">
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88</pre>
</td>
<td>
<pre class="code"><span class="info file"># File 'lib/msf/core/post/linux/f5_mcp.rb', line 67</span>
<span class='kw'>def</span> <span class='id identifier rubyid_mcp_parse_responses'>mcp_parse_responses</span><span class='lparen'>(</span><span class='id identifier rubyid_incoming_data'>incoming_data</span><span class='rparen'>)</span>
<span class='id identifier rubyid_replies'>replies</span> <span class='op'>=</span> <span class='lbracket'>[</span><span class='rbracket'>]</span>
<span class='kw'>while</span> <span class='id identifier rubyid_incoming_data'>incoming_data</span><span class='period'>.</span><span class='id identifier rubyid_length'>length</span> <span class='op'>&gt;</span> <span class='int'>16</span>
<span class='comment'># Grab the length and remove the header from the incoming data
</span> <span class='id identifier rubyid_expected_length'>expected_length</span><span class='comma'>,</span> <span class='id identifier rubyid__'>_</span><span class='comma'>,</span> <span class='id identifier rubyid_incoming_data'>incoming_data</span> <span class='op'>=</span> <span class='id identifier rubyid_incoming_data'>incoming_data</span><span class='period'>.</span><span class='id identifier rubyid_unpack'>unpack</span><span class='lparen'>(</span><span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>Na12a*</span><span class='tstring_end'>&#39;</span></span><span class='rparen'>)</span>
<span class='comment'># Read the packet
</span> <span class='id identifier rubyid_packet'>packet</span><span class='comma'>,</span> <span class='id identifier rubyid_incoming_data'>incoming_data</span> <span class='op'>=</span> <span class='id identifier rubyid_incoming_data'>incoming_data</span><span class='period'>.</span><span class='id identifier rubyid_unpack'>unpack</span><span class='lparen'>(</span><span class='tstring'><span class='tstring_beg'>&quot;</span><span class='tstring_content'>a</span><span class='embexpr_beg'>#{</span><span class='id identifier rubyid_expected_length'>expected_length</span><span class='embexpr_end'>}</span><span class='tstring_content'>a*</span><span class='tstring_end'>&quot;</span></span><span class='rparen'>)</span>
<span class='comment'># Sanity check
</span> <span class='kw'>if</span> <span class='id identifier rubyid_packet'>packet</span><span class='period'>.</span><span class='id identifier rubyid_length'>length</span> <span class='op'>!=</span> <span class='id identifier rubyid_expected_length'>expected_length</span>
<span class='id identifier rubyid_print_warning'>print_warning</span><span class='lparen'>(</span><span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>mcp message is truncated!</span><span class='tstring_end'>&#39;</span></span><span class='rparen'>)</span>
<span class='kw'>return</span> <span class='id identifier rubyid_replies'>replies</span>
<span class='kw'>end</span>
<span class='comment'># Parse it
</span> <span class='id identifier rubyid_replies'>replies</span> <span class='op'>&lt;&lt;</span> <span class='id identifier rubyid_mcp_parse'>mcp_parse</span><span class='lparen'>(</span><span class='id identifier rubyid_packet'>packet</span><span class='rparen'>)</span>
<span class='kw'>end</span>
<span class='kw'>return</span> <span class='id identifier rubyid_replies'>replies</span>
<span class='kw'>end</span></pre>
</td>
</tr>
</table>
</div>
<div class="method_details ">
<h3 class="signature " id="mcp_send_recv-instance_method">
#<strong>mcp_send_recv</strong>(messages) &#x21d2; <tt>Object</tt>
</h3><table class="source_code">
<tr>
<td>
<pre class="lines">
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137</pre>
</td>
<td>
<pre class="code"><span class="info file"># File 'lib/msf/core/post/linux/f5_mcp.rb', line 90</span>
<span class='kw'>def</span> <span class='id identifier rubyid_mcp_send_recv'>mcp_send_recv</span><span class='lparen'>(</span><span class='id identifier rubyid_messages'>messages</span><span class='rparen'>)</span>
<span class='comment'># Attach headers to each message and combine them
</span> <span class='id identifier rubyid_message'>message</span> <span class='op'>=</span> <span class='id identifier rubyid_messages'>messages</span><span class='period'>.</span><span class='id identifier rubyid_map'>map</span> <span class='kw'>do</span> <span class='op'>|</span><span class='id identifier rubyid_m'>m</span><span class='op'>|</span>
<span class='lbracket'>[</span><span class='id identifier rubyid_m'>m</span><span class='period'>.</span><span class='id identifier rubyid_length'>length</span><span class='comma'>,</span> <span class='int'>0</span><span class='comma'>,</span> <span class='int'>0</span><span class='comma'>,</span> <span class='int'>0</span><span class='comma'>,</span> <span class='id identifier rubyid_m'>m</span><span class='rbracket'>]</span><span class='period'>.</span><span class='id identifier rubyid_pack'>pack</span><span class='lparen'>(</span><span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>NNNNa*</span><span class='tstring_end'>&#39;</span></span><span class='rparen'>)</span>
<span class='kw'>end</span><span class='period'>.</span><span class='id identifier rubyid_join'><span class='object_link'><a href="../../../top-level-namespace.html#join-instance_method" title="#join (method)">join</a></span></span><span class='lparen'>(</span><span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_end'>&#39;</span></span><span class='rparen'>)</span>
<span class='comment'># Encode as base64 so we can pass it on the commandline
</span> <span class='id identifier rubyid_message'>message</span> <span class='op'>=</span> <span class='const'><span class='object_link'><a href="../../../Rex.html" title="Rex (module)">Rex</a></span></span><span class='op'>::</span><span class='const'>Text</span><span class='period'>.</span><span class='id identifier rubyid_encode_base64'>encode_base64</span><span class='lparen'>(</span><span class='id identifier rubyid_message'>message</span><span class='rparen'>)</span>
<span class='comment'># Sometimes, the service doesn&#39;t respond with a complete packet, but
</span> <span class='comment'># instead truncates it. This only seems to happen on very long replies,
</span> <span class='comment'># and seems to happen ~50% of the time, so running this loop 5 times
</span> <span class='comment'># gives a pretty high chance of it working
</span> <span class='comment'>#
</span> <span class='comment'># This isn&#39;t a problem with Metasploit, it even happens when I use
</span> <span class='comment'># socat directly.. I think it&#39;s just because we don&#39;t have AF_UNIX.
</span> <span class='comment'># In this example, 559604 is right and 548160 is truncated:
</span> <span class='comment'>#
</span> <span class='comment'># # echo &#39;AAAAEAAAAAAAAAAAAAAAAAtlAA0AAAAICEoADQAAAAA=&#39; | base64 -d | socat -t100 - UNIX-CONNECT:/var/run/mcp | wc -c
</span> <span class='comment'># 559604
</span> <span class='comment'># # echo &#39;AAAAEAAAAAAAAAAAAAAAAAtlAA0AAAAICEoADQAAAAA=&#39; | base64 -d | socat -t100 - UNIX-CONNECT:/var/run/mcp | wc -c
</span> <span class='comment'># 548160
</span> <span class='comment'>#
</span> <span class='comment'># This loop is the best we can do without having access to an AF_UNIX
</span> <span class='comment'># socket (or doing something much, much more complex)
</span> <span class='int'>0</span><span class='period'>.</span><span class='id identifier rubyid_upto'>upto</span><span class='lparen'>(</span><span class='int'>4</span><span class='rparen'>)</span> <span class='kw'>do</span>
<span class='comment'># Send the request messages(s) to the socket
</span> <span class='id identifier rubyid_incoming_data'>incoming_data</span> <span class='op'>=</span> <span class='id identifier rubyid_cmd_exec'>cmd_exec</span><span class='lparen'>(</span><span class='tstring'><span class='tstring_beg'>&quot;</span><span class='tstring_content'>echo &#39;</span><span class='embexpr_beg'>#{</span><span class='id identifier rubyid_message'>message</span><span class='embexpr_end'>}</span><span class='tstring_content'>&#39; | base64 -d | socat -t100 - UNIX-CONNECT:/var/run/mcp</span><span class='tstring_end'>&quot;</span></span><span class='rparen'>)</span>
<span class='comment'># Fail if we got no response or no header
</span> <span class='kw'>if</span> <span class='op'>!</span><span class='id identifier rubyid_incoming_data'>incoming_data</span> <span class='op'>||</span> <span class='id identifier rubyid_incoming_data'>incoming_data</span><span class='period'>.</span><span class='id identifier rubyid_length'>length</span> <span class='op'>&lt;</span> <span class='int'>16</span>
<span class='id identifier rubyid_print_error'>print_error</span><span class='lparen'>(</span><span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>Request to /var/run/mcp socket failed</span><span class='tstring_end'>&#39;</span></span><span class='rparen'>)</span>
<span class='kw'>return</span> <span class='kw'>nil</span>
<span class='kw'>end</span>
<span class='comment'># Get the expected length and make sure the full response is at least
</span> <span class='comment'># that long
</span> <span class='id identifier rubyid_expected_length'>expected_length</span> <span class='op'>=</span> <span class='id identifier rubyid_incoming_data'>incoming_data</span><span class='period'>.</span><span class='id identifier rubyid_unpack'>unpack</span><span class='lparen'>(</span><span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>N</span><span class='tstring_end'>&#39;</span></span><span class='rparen'>)</span><span class='period'>.</span><span class='id identifier rubyid_pop'>pop</span>
<span class='kw'>if</span> <span class='id identifier rubyid_incoming_data'>incoming_data</span><span class='period'>.</span><span class='id identifier rubyid_length'>length</span> <span class='op'>&lt;</span> <span class='id identifier rubyid_expected_length'>expected_length</span>
<span class='id identifier rubyid_vprint_warning'>vprint_warning</span><span class='lparen'>(</span><span class='tstring'><span class='tstring_beg'>&quot;</span><span class='tstring_content'>mcp responded with </span><span class='embexpr_beg'>#{</span><span class='id identifier rubyid_incoming_data'>incoming_data</span><span class='period'>.</span><span class='id identifier rubyid_length'>length</span><span class='embexpr_end'>}</span><span class='tstring_content'> bytes instead of the promised </span><span class='embexpr_beg'>#{</span><span class='id identifier rubyid_expected_length'>expected_length</span><span class='embexpr_end'>}</span><span class='tstring_content'> bytes! Trying again...</span><span class='tstring_end'>&quot;</span></span><span class='rparen'>)</span>
<span class='kw'>else</span>
<span class='kw'>return</span> <span class='id identifier rubyid_mcp_parse_responses'>mcp_parse_responses</span><span class='lparen'>(</span><span class='id identifier rubyid_incoming_data'>incoming_data</span><span class='rparen'>)</span>
<span class='kw'>end</span>
<span class='kw'>end</span>
<span class='id identifier rubyid_print_error'>print_error</span><span class='lparen'>(</span><span class='tstring'><span class='tstring_beg'>&quot;</span><span class='tstring_content'>mcp isn&#39;t responding with a full message, giving up</span><span class='tstring_end'>&quot;</span></span><span class='rparen'>)</span>
<span class='kw'>nil</span>
<span class='kw'>end</span></pre>
</td>
</tr>
</table>
</div>
<div class="method_details ">
<h3 class="signature " id="mcp_simple_query-instance_method">
#<strong>mcp_simple_query</strong>(querytype) &#x21d2; <tt>Object</tt>
</h3><div class="docstring">
<div class="discussion">
<p>Do a query_all request for something that will reply with a single query result.</p>
<p>Attempts to abstract away all the messiness in the protocol, instead we just query for a type and get all the responses as an array of hashes</p>
</div>
</div>
<div class="tags">
</div><table class="source_code">
<tr>
<td>
<pre class="lines">
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372</pre>
</td>
<td>
<pre class="code"><span class="info file"># File 'lib/msf/core/post/linux/f5_mcp.rb', line 334</span>
<span class='kw'>def</span> <span class='id identifier rubyid_mcp_simple_query'>mcp_simple_query</span><span class='lparen'>(</span><span class='id identifier rubyid_querytype'>querytype</span><span class='rparen'>)</span>
<span class='comment'># Get the raw result
</span> <span class='id identifier rubyid_result'>result</span> <span class='op'>=</span> <span class='id identifier rubyid_mcp_send_recv'>mcp_send_recv</span><span class='lparen'>(</span><span class='lbracket'>[</span>
<span class='id identifier rubyid_mcp_build'>mcp_build</span><span class='lparen'>(</span><span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>query_all</span><span class='tstring_end'>&#39;</span></span><span class='comma'>,</span> <span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>structure</span><span class='tstring_end'>&#39;</span></span><span class='comma'>,</span> <span class='lbracket'>[</span>
<span class='id identifier rubyid_mcp_build'>mcp_build</span><span class='lparen'>(</span><span class='id identifier rubyid_querytype'>querytype</span><span class='comma'>,</span> <span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>structure</span><span class='tstring_end'>&#39;</span></span><span class='comma'>,</span> <span class='lbracket'>[</span><span class='rbracket'>]</span><span class='rparen'>)</span>
<span class='rbracket'>]</span><span class='rparen'>)</span>
<span class='rbracket'>]</span><span class='rparen'>)</span>
<span class='comment'># Error handling
</span> <span class='kw'>unless</span> <span class='id identifier rubyid_result'>result</span>
<span class='id identifier rubyid_print_error'>print_error</span><span class='lparen'>(</span><span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>mcp_send_recv failed</span><span class='tstring_end'>&#39;</span></span><span class='rparen'>)</span>
<span class='kw'>return</span> <span class='kw'>nil</span>
<span class='kw'>end</span>
<span class='comment'># Sanity check - we only expect one result
</span> <span class='kw'>if</span> <span class='id identifier rubyid_result'>result</span><span class='period'>.</span><span class='id identifier rubyid_length'>length</span> <span class='op'>!=</span> <span class='int'>1</span>
<span class='id identifier rubyid_print_error'>print_error</span><span class='lparen'>(</span><span class='tstring'><span class='tstring_beg'>&quot;</span><span class='tstring_content'>mcp_send_recv query was supposed to return one result, but returned </span><span class='embexpr_beg'>#{</span><span class='id identifier rubyid_result'>result</span><span class='period'>.</span><span class='id identifier rubyid_length'>length</span><span class='embexpr_end'>}</span><span class='tstring_content'> results instead</span><span class='tstring_end'>&quot;</span></span><span class='rparen'>)</span>
<span class='kw'>return</span> <span class='kw'>nil</span>
<span class='kw'>end</span>
<span class='comment'># Get that result
</span> <span class='id identifier rubyid_result'>result</span> <span class='op'>=</span> <span class='id identifier rubyid_result'>result</span><span class='period'>.</span><span class='id identifier rubyid_pop'>pop</span>
<span class='comment'># Get the reply
</span> <span class='id identifier rubyid_result'>result</span> <span class='op'>=</span> <span class='id identifier rubyid_mcp_get_single'>mcp_get_single</span><span class='lparen'>(</span><span class='id identifier rubyid_result'>result</span><span class='comma'>,</span> <span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>query_reply</span><span class='tstring_end'>&#39;</span></span><span class='rparen'>)</span>
<span class='kw'>if</span> <span class='id identifier rubyid_result'>result</span><span class='period'>.</span><span class='id identifier rubyid_nil?'>nil?</span>
<span class='id identifier rubyid_print_error'>print_error</span><span class='lparen'>(</span><span class='tstring'><span class='tstring_beg'>&quot;</span><span class='tstring_content'>mcp didn&#39;t return a query_reply to our query</span><span class='tstring_end'>&quot;</span></span><span class='rparen'>)</span>
<span class='kw'>return</span> <span class='kw'>nil</span>
<span class='kw'>end</span>
<span class='comment'># Get all the fields for the querytype
</span> <span class='id identifier rubyid_result'>result</span> <span class='op'>=</span> <span class='id identifier rubyid_mcp_get_multiple'>mcp_get_multiple</span><span class='lparen'>(</span><span class='id identifier rubyid_result'>result</span><span class='comma'>,</span> <span class='id identifier rubyid_querytype'>querytype</span><span class='rparen'>)</span>
<span class='comment'># Convert each result to a hash
</span> <span class='id identifier rubyid_result'>result</span> <span class='op'>=</span> <span class='id identifier rubyid_result'>result</span><span class='period'>.</span><span class='id identifier rubyid_map'>map</span> <span class='kw'>do</span> <span class='op'>|</span><span class='id identifier rubyid_single_result'>single_result</span><span class='op'>|</span>
<span class='id identifier rubyid_mcp_to_h'>mcp_to_h</span><span class='lparen'>(</span><span class='id identifier rubyid_single_result'>single_result</span><span class='rparen'>)</span>
<span class='kw'>end</span>
<span class='id identifier rubyid_result'>result</span>
<span class='kw'>end</span></pre>
</td>
</tr>
</table>
</div>
<div class="method_details ">
<h3 class="signature " id="mcp_to_h-instance_method">
#<strong>mcp_to_h</strong>(array) &#x21d2; <tt>Object</tt>
</h3><div class="docstring">
<div class="discussion">
<p>Take an array of results from an mcp query, and change them from an array of tag=&gt;value into a hash.</p>
<p>Note! If there are multiple fields with the same tag, this will only return one of them!</p>
</div>
</div>
<div class="tags">
</div><table class="source_code">
<tr>
<td>
<pre class="lines">
283
284
285
286
287</pre>
</td>
<td>
<pre class="code"><span class="info file"># File 'lib/msf/core/post/linux/f5_mcp.rb', line 283</span>
<span class='kw'>def</span> <span class='id identifier rubyid_mcp_to_h'>mcp_to_h</span><span class='lparen'>(</span><span class='id identifier rubyid_array'>array</span><span class='rparen'>)</span>
<span class='id identifier rubyid_array'>array</span><span class='period'>.</span><span class='id identifier rubyid_map'>map</span> <span class='kw'>do</span> <span class='op'>|</span><span class='id identifier rubyid_r'>r</span><span class='op'>|</span>
<span class='lbracket'>[</span><span class='id identifier rubyid_r'>r</span><span class='lbracket'>[</span><span class='symbol'>:tag</span><span class='rbracket'>]</span><span class='comma'>,</span> <span class='id identifier rubyid_r'>r</span><span class='lbracket'>[</span><span class='symbol'>:value</span><span class='rbracket'>]</span><span class='rbracket'>]</span>
<span class='kw'>end</span><span class='period'>.</span><span class='id identifier rubyid_to_h'>to_h</span>
<span class='kw'>end</span></pre>
</td>
</tr>
</table>
</div>
</div>
</div>
<div id="footer">
Generated on Fri May 8 17:01:16 2026 by
<a href="https://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
0.9.37 (ruby-3.1.5).
</div>
</div>
</body>
</html>