Skip to content
Browse files

initial commit, moving to git

  • Loading branch information...
0 parents commit 6fffc6f7cc6b0134be33f1de56f736a27528a112 @dakrone committed
Showing with 25,551 additions and 0 deletions.
  1. +130 −0 CHANGELOG
  2. +150 −0 LGPL.license
  3. +18 −0 LICENSE
  4. +1 −0 README
  5. +96 −0 TODO
  6. BIN docs/NSM-Console.pdf
  7. +15 −0 files
  8. +6 −0 gentags
  9. +16 −0 lib/colors.rb
  10. +55 −0 lib/command_manager.rb
  11. +912 −0 lib/commands.rb
  12. +137 −0 lib/encodelib.rb
  13. +18 −0 lib/history.rb
  14. +63 −0 lib/logging.rb
  15. +65 −0 lib/nsm_alias.rb
  16. +43 −0 lib/nsm_category.rb
  17. +157 −0 lib/nsm_console.rb
  18. +361 −0 lib/nsm_helper.rb
  19. +156 −0 lib/nsm_module.rb
  20. +174 −0 lib/pcaplib.rb
  21. +173 −0 lib/pcapparser.rb
  22. +1 −0 logs/logsgohere
  23. +57 −0 logs/nsm-log.2008107.log
  24. +4 −0 logs/nsm-log.2008828.log
  25. +43 −0 modules/README
  26. +1 −0 modules/aimsnarf.module/aimsnarf
  27. +1 −0 modules/aimsnarf.module/defaults
  28. +1 −0 modules/aimsnarf.module/description
  29. +7 −0 modules/aimsnarf.module/info
  30. +5 −0 modules/argus-basic.module/argus-basic
  31. +10 −0 modules/argus-basic.module/defaults
  32. +1 −0 modules/argus-basic.module/description
  33. +22 −0 modules/argus-basic.module/info
  34. +2 −0 modules/argus3-pcap2flow.module/argus3-pcap2flow
  35. +6 −0 modules/argus3-pcap2flow.module/defaults
  36. +1 −0 modules/argus3-pcap2flow.module/description
  37. +12 −0 modules/argus3-pcap2flow.module/info
  38. +14 −0 modules/argus3-ramon.module/argus3-ramon
  39. +11 −0 modules/argus3-ramon.module/defaults
  40. +1 −0 modules/argus3-ramon.module/description
  41. +23 −0 modules/argus3-ramon.module/info
  42. +4 −0 modules/argus3-ramon.module/racluster-HostProto.conf
  43. +4 −0 modules/argus3-ramon.module/racluster-HostSvc.conf
  44. +4 −0 modules/argus3-ramon.module/racluster-Matrix.conf
  45. +4 −0 modules/argus3-ramon.module/racluster-Svc.conf
  46. +4 −0 modules/argus3-ramon.module/racluster-TopN.conf
  47. +2 −0 modules/bro-ids-conn.module/bro-ids-conn
  48. +171 −0 modules/bro-ids-conn.module/bro.cfg
  49. 0 modules/bro-ids-conn.module/defaults
  50. +1 −0 modules/bro-ids-conn.module/description
  51. +4 −0 modules/bro-ids-conn.module/info
  52. +1 −0 modules/bro-ids-protocol.module/bro-ids-protocol
  53. +171 −0 modules/bro-ids-protocol.module/bro.cfg
  54. +1 −0 modules/bro-ids-protocol.module/defaults
  55. +1 −0 modules/bro-ids-protocol.module/description
  56. +6 −0 modules/bro-ids-protocol.module/info
  57. +2 −0 modules/bro-ids-stream.module/bro-ids-stream
  58. +171 −0 modules/bro-ids-stream.module/bro.cfg
  59. 0 modules/bro-ids-stream.module/defaults
  60. +1 −0 modules/bro-ids-stream.module/description
  61. +4 −0 modules/bro-ids-stream.module/info
  62. +1 −0 modules/capinfos.module/capinfos
  63. +1 −0 modules/capinfos.module/defaults
  64. +1 −0 modules/capinfos.module/description
  65. +7 −0 modules/capinfos.module/info
  66. +3 −0 modules/categories/IDS
  67. +7 −0 modules/categories/flow
  68. +10 −0 modules/categories/forensics
  69. 0 modules/categories/nsm
  70. +5 −0 modules/categories/statistics
  71. +1 −0 modules/chaosreader.module/chaosreader
  72. +1 −0 modules/chaosreader.module/defaults
  73. +1 −0 modules/chaosreader.module/description
  74. +8 −0 modules/chaosreader.module/info
  75. +1 −0 modules/clamscan.module/clamscan
  76. +2 −0 modules/clamscan.module/defaults
  77. +1 −0 modules/clamscan.module/description
  78. +10 −0 modules/clamscan.module/info
  79. +4 −0 modules/dnstop.module/defaults
  80. +1 −0 modules/dnstop.module/description
  81. +1 −0 modules/dnstop.module/dnstop
  82. +9 −0 modules/dnstop.module/info
  83. +2 −0 modules/fl0p.module/defaults
  84. +1 −0 modules/fl0p.module/description
  85. +1 −0 modules/fl0p.module/fl0p
  86. +7 −0 modules/fl0p.module/info
  87. 0 modules/flowtag.module/defaults
  88. +1 −0 modules/flowtag.module/description
  89. +1 −0 modules/flowtag.module/flowtag
  90. +5 −0 modules/flowtag.module/info
  91. +3 −0 modules/flowtime.module/defaults
  92. +1 −0 modules/flowtime.module/description
  93. +1 −0 modules/flowtime.module/flowtime
  94. +12 −0 modules/flowtime.module/info
  95. +2 −0 modules/foremost.module/defaults
  96. +1 −0 modules/foremost.module/description
  97. +1 −0 modules/foremost.module/foremost
  98. +7 −0 modules/foremost.module/info
  99. +1 −0 modules/harimau.module/defaults
  100. +1 −0 modules/harimau.module/description
  101. +1 −0 modules/harimau.module/harimau
  102. +59 −0 modules/harimau.module/harimau.rb
  103. +7 −0 modules/harimau.module/info
  104. +106 −0 modules/harimau.module/pcapparser.rb
  105. 0 modules/hash.module/defaults
  106. +1 −0 modules/hash.module/description
  107. +2 −0 modules/hash.module/hash
  108. +4 −0 modules/hash.module/info
  109. +2 −0 modules/honeysnap.module/defaults
  110. +1 −0 modules/honeysnap.module/description
  111. +1 −0 modules/honeysnap.module/honeysnap
  112. +87 −0 modules/honeysnap.module/honeysnap.cfg
  113. +8 −0 modules/honeysnap.module/info
  114. +1 −0 modules/httpry.module/defaults
  115. +1 −0 modules/httpry.module/description
  116. +1 −0 modules/httpry.module/httpry
  117. +7 −0 modules/httpry.module/info
  118. +1 −0 modules/ip2asn.module/defaults
  119. +1 −0 modules/ip2asn.module/description
  120. +6 −0 modules/ip2asn.module/info
  121. +1 −0 modules/ip2asn.module/ip2asn
  122. +53 −0 modules/ip2asn.module/ip2asn.rb
  123. +172 −0 modules/ip2asn.module/pcapparser.rb
  124. +1 −0 modules/iploc.module/defaults
  125. +1 −0 modules/iploc.module/description
  126. +11 −0 modules/iploc.module/info
  127. +1 −0 modules/iploc.module/iploc
  128. +1 −0 modules/ngrep.module/description
  129. +3 −0 modules/ngrep.module/info
  130. +9 −0 modules/ngrep.module/ngrep
  131. +2 −0 modules/p0f.module/defaults
  132. +1 −0 modules/p0f.module/description
  133. +8 −0 modules/p0f.module/info
  134. +1 −0 modules/p0f.module/p0f
  135. +1 −0 modules/pads.module/defaults
  136. +1 −0 modules/pads.module/description
  137. +6 −0 modules/pads.module/info
  138. +1 −0 modules/pads.module/pads
  139. +66 −0 modules/snort.module/classification.config
  140. +3 −0 modules/snort.module/defaults
  141. +1 −0 modules/snort.module/description
  142. +8 −0 modules/snort.module/info
  143. +14 −0 modules/snort.module/reference.config
  144. +340 −0 modules/snort.module/rules/LICENSE
  145. +128 −0 modules/snort.module/rules/bleeding-attack_response.rules
  146. +58 −0 modules/snort.module/rules/bleeding-botcc-BLOCK.rules
  147. +22 −0 modules/snort.module/rules/bleeding-botcc.excluded
  148. +58 −0 modules/snort.module/rules/bleeding-botcc.rules
  149. +40 −0 modules/snort.module/rules/bleeding-compromised-BLOCK.rules
  150. +40 −0 modules/snort.module/rules/bleeding-compromised.rules
  151. +106 −0 modules/snort.module/rules/bleeding-dos.rules
  152. +47 −0 modules/snort.module/rules/bleeding-drop-BLOCK.rules
  153. +47 −0 modules/snort.module/rules/bleeding-drop.rules
  154. +35 −0 modules/snort.module/rules/bleeding-dshield-BLOCK.rules
  155. +35 −0 modules/snort.module/rules/bleeding-dshield.rules
  156. +751 −0 modules/snort.module/rules/bleeding-exploit.rules
  157. +98 −0 modules/snort.module/rules/bleeding-game.rules
  158. +66 −0 modules/snort.module/rules/bleeding-inappropriate.rules
  159. +1,586 −0 modules/snort.module/rules/bleeding-malware.rules
  160. +155 −0 modules/snort.module/rules/bleeding-p2p.rules
  161. +1,358 −0 modules/snort.module/rules/bleeding-policy.rules
  162. +92 −0 modules/snort.module/rules/bleeding-rbn-BLOCK.rules
  163. +91 −0 modules/snort.module/rules/bleeding-rbn.rules
  164. +130 −0 modules/snort.module/rules/bleeding-scan.rules
  165. +6,274 −0 modules/snort.module/rules/bleeding-sid-msg.map
  166. +1,138 −0 modules/snort.module/rules/bleeding-virus.rules
  167. +49 −0 modules/snort.module/rules/bleeding-voip.rules
  168. +332 −0 modules/snort.module/rules/bleeding-web.rules
  169. +4,572 −0 modules/snort.module/rules/bleeding-web_sql_injection.rules
  170. +55 −0 modules/snort.module/rules/bleeding.conf
  171. +82 −0 modules/snort.module/rules/bleeding.rules
  172. +117 −0 modules/snort.module/rules/community-bot.rules
  173. +7 −0 modules/snort.module/rules/community-deleted.rules
  174. +16 −0 modules/snort.module/rules/community-dos.rules
  175. +11 −0 modules/snort.module/rules/community-exploit.rules
  176. +4 −0 modules/snort.module/rules/community-ftp.rules
  177. +10 −0 modules/snort.module/rules/community-game.rules
  178. +8 −0 modules/snort.module/rules/community-icmp.rules
  179. +15 −0 modules/snort.module/rules/community-imap.rules
  180. +8 −0 modules/snort.module/rules/community-inappropriate.rules
  181. +4 −0 modules/snort.module/rules/community-mail-client.rules
  182. +48 −0 modules/snort.module/rules/community-misc.rules
  183. +6 −0 modules/snort.module/rules/community-nntp.rules
  184. +6 −0 modules/snort.module/rules/community-oracle.rules
  185. +11 −0 modules/snort.module/rules/community-policy.rules
  186. +19 −0 modules/snort.module/rules/community-sip.rules
  187. +13 −0 modules/snort.module/rules/community-smtp.rules
  188. +15 −0 modules/snort.module/rules/community-sql-injection.rules
  189. +21 −0 modules/snort.module/rules/community-virus.rules
  190. +10 −0 modules/snort.module/rules/community-web-attacks.rules
  191. +22 −0 modules/snort.module/rules/community-web-cgi.rules
  192. +25 −0 modules/snort.module/rules/community-web-client.rules
  193. +5 −0 modules/snort.module/rules/community-web-dos.rules
  194. +10 −0 modules/snort.module/rules/community-web-iis.rules
  195. +215 −0 modules/snort.module/rules/community-web-misc.rules
  196. +474 −0 modules/snort.module/rules/community-web-php.rules
  197. +1 −0 modules/snort.module/snort
  198. +1,035 −0 modules/snort.module/snort.conf
  199. +104 −0 modules/snort.module/unicode.map
  200. +1 −0 modules/tcpdstat.module/defaults
  201. +1 −0 modules/tcpdstat.module/description
  202. +7 −0 modules/tcpdstat.module/info
  203. +1 −0 modules/tcpdstat.module/tcpdstat
  204. +1 −0 modules/tcpflow.module/defaults
  205. +1 −0 modules/tcpflow.module/description
  206. +7 −0 modules/tcpflow.module/info
  207. +1 −0 modules/tcpflow.module/tcpflow
  208. +4 −0 modules/tcpick.module/defaults
  209. +1 −0 modules/tcpick.module/description
  210. +9 −0 modules/tcpick.module/info
  211. +3 −0 modules/tcpick.module/tcpick
  212. +4 −0 modules/tcptrace.module/defaults
  213. +1 −0 modules/tcptrace.module/description
  214. +15 −0 modules/tcptrace.module/info
  215. +5 −0 modules/tcptrace.module/tcptrace
  216. +1 −0 modules/tcpxtract.module/defaults
  217. +1 −0 modules/tcpxtract.module/description
  218. +6 −0 modules/tcpxtract.module/info
  219. +122 −0 modules/tcpxtract.module/rp-tcpxtract.conf
  220. +1 −0 modules/tcpxtract.module/tcpxtract
  221. +95 −0 modules/tcpxtract.module/tcpxtract.conf
  222. +2 −0 modules/trace-summary.module/defaults
  223. +1 −0 modules/trace-summary.module/description
  224. +7 −0 modules/trace-summary.module/info
  225. +1 −0 modules/trace-summary.module/trace-summary
  226. +884 −0 modules/trace-summary.module/trace-summary.py
  227. +2 −0 modules/tshark.module/defaults
  228. +1 −0 modules/tshark.module/description
  229. +8 −0 modules/tshark.module/info
  230. +1 −0 modules/tshark.module/tshark
  231. +1 −0 modules/yahsnarf.module/defaults
  232. +1 −0 modules/yahsnarf.module/description
  233. +6 −0 modules/yahsnarf.module/info
  234. +12 −0 modules/yahsnarf.module/lib/bit-struct.rb
Sorry, we could not display the entire diff because it was too big.
130 CHANGELOG
@@ -0,0 +1,130 @@
+Version 0.7
+DONE - \x33\x55 etc, done - decode hex now supports this automatically
+DONE - Allow encode/decode to work on files instead of just a textstring
+DONE - From Scholar: IP->ASN mapping, a module (ip2asn)
+DONE - From Scholar: IP->ASN mapping, a command (ip2asn)
+DONE - Upgrade revision of pcapparser library (support flags)
+DONE - 'print' command should print TCP flags using newer revision of pcapparser library
+SEMI-DONE - From Scholar: Some way to extract a list of IPs from a pcap (iplist)
+DONE - Change "run" so you can use "run aimsnarf" to run the aimsnarf module without toggling, etc
+DONE - Path error for modules when relative path is used, the full path to a file is now used (Grzegorz)
+DONE - add 'iplist' command to get a list of IP addresses, sorted by numbers
+DONE - Add yahsnarf module (extract yahoo IM conversations)
+DONE - Need pipes into commands and files, this includes but is not limited to: > < >> | (All except for < are done)
+DONE - Pipe redirection requires an extra enter to get a prompt, figure out why and fix it.
+DONE - Tempfile problems with gzip'd pcap files, use a regular file instead
+DONE - Add encoding method of just "hex" instead of hex_LSB and hex_MSB
+DONE - 'decode hex' should work on space delineated strings
+DONE - Default encode/decode for 'binary' is little-endian
+DONE - geek00l committed bro-ids-connection information module
+DONE - Automatic updating over SVN of NSM-Console
+
+Version 0.6
+DONE - rot13 encode/decode
+DONE - Fix error with an alias handling arguments
+DONE - Add 'dump' command, similar to print, dump binary payload of packet(s) to a file
+DONE - Warning when file doesn't exist
+DONE - Harimau attempts to use wget if it can, since it's about 10 times faster than Net::HTTP
+DONE - Argus rdns lookups were killing the speed. Added '-n' so it doesn't do that by default
+DONE - checkip tried to use wget if it's installed, should be much much faster
+DONE - tcptrace doesn't do rdns lookups because it was dying, -n is the default now
+DONE - fixed a typo in urlescape (en|de)coding, thanks John!
+DONE - Add clamscan module
+DONE - Use rawpacket's tcpxtract.conf instead of the regular one. (extract many many more types)
+DONE - Add foremost module
+DONE - let the clamscan module select which extraction dir it wants to look in (foremost? tcpxtract?)
+DONE - Need to add "color on", instead of just off and toggle
+DONE - Auto gunzip pcap files on the fly (only for .gz extensions) (doesn't work for directories)
+DONE - Clean up the autogunzipping
+DONE - Create the temp file in the NSM-Console directory, file is cleaned up on exit
+DONE - Directories support gzip'd files for modules, print and dump
+DONE (N/A)- dump doesn't like temp files, fix this -- doesn't matter any more, since gunzip the file once by default
+DONE - gunzip once, not every time, silly me.
+DONE - Separate the bro alarms and extracting the bro contents
+DONE - Update Snort rules (community and emerging)
+DONE - add "-f" tag to dump command to allow for full dumping of selected packets
+DONE - Add the trace-summary module (http://www.icir.org/robin/trace-summary/)
+DONE - Fixed a serious bug with argument parsing for dump -f
+
+
+Version 0.5
+DONE - Alias command!
+DONE - Change license of pcapparser
+DONE - Add flowtime module
+DONE - Make 'help' more readable
+DONE - Allow 'help' to take argument so you specify help for what you want
+DONE - Redirect error output to STDERR
+DONE - Read ~/.nsmcrc much quieter :)
+DONE - Alias handles concatinating of arguments (bugfix)
+DONE - Add license to header in nsm file
+DONE - Add aliases to tab completion without killing current completion
+DONE - (bugfix) Aliases without arguments casting nil to string
+DONE - Integrate IP checking with Mel's http://watchlist.security.org.my/ inline (instead of scriptable)
+DONE - Add the 'checkip' command (check the Harimau watchlist)
+DONE - Add harimau module
+DONE - Make checkip command use Ruby modules (Net::HTTP) instead of wget
+DONE - Give bro-ids option for user-settable cfg file
+DONE - Make bro-ids do more things (like actually produce alerts :P)
+DONE - Add some modules to better categories
+DONE - Toggle handle space-separated module names
+
+
+Version 0.4
+DONE - uuencode/decode
+DONE - Octal (just decoding so far)
+DONE - Char # encoding
+DONE - 'print #' shows packet # in tcpdump -X format, specify range, etc lots of options
+DONE - print support directories
+DONE - Fix "~" support (file support ~)
+DONE - 'output' command support ~ also
+DONE - Color terminal text whee!
+DONE - Read .nsmcrc on startup
+DONE - Fixed ^C usable for long packet prints works
+DONE - Finally caught ^C at the command line, so it doesn't die like crazy
+DONE - Trap SIGTERM
+DONE - print supports commas: p 1,20-25,101
+DONE - Add tcptrace module
+DONE - 'color' command to toggle color on and off
+DONE - Add tcpick module
+DONE - Screencast: creating a module for nsm-console
+
+
+Version 0.3
+DONE - Strip whitespace from the end of the command
+DONE - Allow "set" to handle whitespace between words/characters
+DONE (NoMethodFound error caught)- Better handling of "Command not found"
+DONE - Ability to specify a different log file
+DONE - Category dies completely if it can't read the file (fix this)
+DONE (I think) - Better error catching
+DONE - Fix 'help' command spacing
+DONE - "exec" command logs
+DONE - "exec" command will do replacement for ${PCAP_FILE}, ${PCAP_BASE}, ${MODULE_DIR} and ${OUTPUT_DIR}
+DONE - Add iploc module
+DONE - fl0p module
+DONE - Add website reference to each module's info file
+DONE - Log regular nsm-console commands
+DONE - Add "history" command
+DONE - Transition into a more OO-based structure to promote future development
+DONE - Log exit status of modules running
+DONE - Do replacement in outputdir (so ${PCAP_FILE} can be used)
+DONE - Add 'argus' module with many ra commands from the flow
+DONE - Snort emerging-threats rules? Should I replace the community rules with these?
+DONE - Default output ${PCAP_BASE}-output
+DONE - Licensing BSD vs GPLv2, BSD
+DONE - Add "e" command as shortcut for exec
+DONE - Add eval command to eval line of ruby
+DONE - Add encode/decode methods to tab completion
+DONE - Add PCAP_* to tab completion
+DONE - Add 'credits' command :)
+DONE - "encode" command
+DONE - "decode" command
+DONE - base64
+DONE - md5
+DONE - sha256
+DONE - url escape
+DONE - hex? LSB and MSB
+DONE - binary? LSB and MSB
+
+
+Version 0.2
+No changelog before this
150 LGPL.license
@@ -0,0 +1,150 @@
+GNU Lesser General Public License
+
+Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ [This is the first released version of the Lesser GPL. It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+Preamble
+
+The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users.
+
+This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below.
+
+When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things.
+
+To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it.
+
+For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights.
+
+We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library.
+
+To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others.
+
+Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license.
+
+Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs.
+
+When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library.
+
+We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances.
+
+For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License.
+
+In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system.
+
+Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library.
+
+The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run.
+TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you".
+
+A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables.
+
+The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".)
+
+"Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library.
+
+Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does.
+
+1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library.
+
+You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee.
+
+2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.)
+
+ These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it.
+
+ Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library.
+
+ In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License.
+
+3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices.
+
+Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy.
+
+This option is useful when you wish to copy part of the code of the Library into a program that is not a library.
+
+4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange.
+
+If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code.
+
+5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License.
+
+However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables.
+
+When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law.
+
+If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.)
+
+Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself.
+
+6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications.
+
+You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things:
+
+ a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.)
+
+ b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with.
+
+ c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution.
+
+ d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place.
+
+ e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy.
+
+For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable.
+
+It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute.
+
+7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above.
+
+ b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work.
+
+8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance.
+
+9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it.
+
+10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License.
+
+11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice.
+
+This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License.
+
+12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License.
+
+13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation.
+
+14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally.
+
+NO WARRANTY
+
+15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+END OF TERMS AND CONDITIONS
18 LICENSE
@@ -0,0 +1,18 @@
+NSM-Console - A framework for performing network security monitoring
+Copyright (C) 2007 Matthew Lee Hinman
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+See the LGPL.license file for a full copy of the license
1 README
@@ -0,0 +1 @@
+See http://writequit.org/projects/nsm-console
96 TODO
@@ -0,0 +1,96 @@
+- More modules (always)
+- Fix bugs (always :)
+- Different logging levels
+- morse code -.--...-.- .-- .-..-.. ---..-- encode/decode
+- leet? Whoops, I mean "l337" encode
+- NTLM v1 & v2 encode
+- LANMAN? encode
+- CHAP? encode
+- Piglatin :P encode/decode
+- Rainbow tables encode/decode (Enhanced is working on this)
+- Ruby module for generating traffic graphs? (gruff)
+- Blog post/tutorial: putting a module in a category for nsm-console
+- Screencast: creating a command for nsm-console
+- Context-sensative tab completion
+- Create coherent code. Comment things (big project)
+- Some kind of unified output structure (?)
+N/A - Guti - run -h addition to help run (not doing this because 'help' command is enable in my opinion)
+- make clamscan module do the tcpxtract itself, or write some way to include dependencies
+- perhaps implement scruby integration? (or scapy, if nothing else)
+- Add a class to handle option variables, like "NSM_Option", instead of using global variables
+- Extend pcapparser to support ARP
+- Extend pcapparser to support ICMP
+- From Scholar: readline tab-completion for filenames
+- Extend 'iplist' command to handle directories of files
+- Perhaps add an additional option for what to do with the list? (ip2asn, harimau)
+- Add 'stats' command for some generic pcap stats
+- Piping something into 'less' gives a broken pipe when you exit
+- Transition Argus modules to be 3, or 2, or both, 3 is preferred.
+- SiLKtools integration (see below)
+- Improve the prompt (show basename of the pcap being worked on)
+DONE - pcapparser supports NULL ethernet types (thanks bsdjunkie)
+DONE - Fix very serious p -x bug where hex output was truncated.
+- make 'update' work correctly
+DONE - Add '-f' flag to print command to display full packet, not just payload
+DONE - Fix p -x formatting on truncated strings
+- Make EVERYTHING work on directories of files
+- Ability to print arbitrary fields of packets (or a range thereof)
+DONE - 'list' command can filter things out, like "list all" and "list enabled" and "list disabled" ('list en' and 'list dis' shorthand)
+DONE - Add dnstop module
+- Add unicode encoding support
+DONE - Fix weird alias problem ("ll en" w/my ./nsmcrc)
+- Ability to "install" NSM-Console, and run it from a different directory
+DONE - Add ability to use -q to start nsm console quietly
+DONE - Fix 'dump * file' (have to use "dump 1-* file" right now)
+DONE - Abstract alias resolving to the NSM_Alias class
+DONE - Abstract logging methods into Logger class
+DONE - Small amount of code cleanup and reorganization to make code more readable
+- Add "HOME_NET" declaration for modules that would support that sort of value.
+ Modules:
+- Make nsm-console work with ruby 1.8 and 1.9
+DONE - vim modelines
+DONE - "dump" command supports directories
+- Allow "dump -f" to dump packets regardless of supported protocol or not
+DONE - "iplist" command needs to support directories of pcap files
+- Rewrite pcapparser to use Ruby's builtin BinData so it's easier to extend
+
+
+IDEAS:
+==================
+iplist mode, entered using an "iplist" command, so it would follow:
+
+nsm> iplist
+nsm (iplist)>
+nsm (iplist)> cidr (to get cidr masks)
+nsm (iplist)> list [file] (list them to stdout or a file)
+nsm (iplist)> harimau (check against harimau)
+nsm (iplist)> asn (map IPs to asn)
+nsm (iplist)> stats (show rudimentary statistics)
+nsm (iplist)> end
+nsm>
+
+caching the list of ips generated using pcapparser, so that data could be exported to different
+tools, without regeneration. Give optional filename to save to a file and also show on stdout.
+
+P.S. This was/is Scholar's idea, he gets credit
+
+==================
+For silktools integration, I propose a moded implementation, similar to the
+iplist idea or IOS configure modes:
+
+nsm> file data.pcap
+... loads file ...
+nsm> silk
+Generating silk flow file...done.
+nsm (silk)> stats
+... print overall statistics ...
+nsm (silk)> stats -sport 2
+(rwstats -sport --percentage 2 data.silk)
+... etc, etc, etc ...
+nsm (silk)> end
+nsm>
+
+Need to implement this in a unified fashion, so it makes conceptual sense. This
+will probably also be difficult to implement. It should be separated so that
+not having silktools installed will still allow all other functionality (other
+than silk)
BIN docs/NSM-Console.pdf
Binary file not shown.
15 files
@@ -0,0 +1,15 @@
+nsm
+lib/colors.rb
+lib/command_manager.rb
+lib/commands.rb
+lib/encodelib.rb
+lib/history.rb
+lib/logging.rb
+lib/nsm_alias.rb
+lib/nsm_category.rb
+lib/nsm_console.rb
+lib/nsm_helper.rb
+lib/nsm_module.rb
+lib/pcaplib.rb
+lib/pcapparser.rb
+
6 gentags
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+## This script is intended to be used in conjuction with exuberant-ctags:
+## http://ctags.sourceforge.net/
+
+/usr/local/bin/ctags -L files -f tags --verbose=yes
16 lib/colors.rb
@@ -0,0 +1,16 @@
+# vim: set ts=2 sw=2 tw=80
+## Escape sequences for colors
+## Misc
+$RESET = "\033[0m"
+$BOLD = "\033[1m"
+$BLINK = "\033[5m"
+
+## Foreground colors
+$BLACK = "\033[30m"
+$RED = "\033[31m"
+$GREEN = "\033[32m"
+$BROWN = "\033[33m"
+$BLUE = "\033[34m"
+$MAGENTA = "\033[35m"
+$CYAN = "\033[36m"
+$WHITE = "\033[37m"
55 lib/command_manager.rb
@@ -0,0 +1,55 @@
+# vim: set ts=2 sw=2 tw=80
+# Command Manager handles all the 'registered' commands in the commands.rb file
+# This makes for a much cleaner way to add methods without having to 'eval'
+# everything
+class CommandManager
+ ## The list of our commands
+ @@commands = {}
+
+ def CommandManager.add(command)
+ @@commands[command.exec] = command
+ end
+
+ def CommandManager.execute(exec, *args)
+ @@commands[exec].execute args
+ end
+
+ def CommandManager.get_commands
+ return @@commands
+ end
+
+ def CommandManager.get_commands_as_array
+ cmds = []
+ i = 0
+ CommandManager.get_commands.each { |k, val|
+ cmds[i] = val.exec.to_s
+ i += 1
+ }
+ return cmds
+ end
+
+end
+
+# Class encapsulating an NSM-Console "command"
+class Command
+ attr_reader :desc, :exec
+
+ def initialize (desc, exec, block)
+ @desc, @exec, @block = desc, exec, block
+ end
+
+ ## Actually call the block of code
+ def execute (*args)
+ @block.call args
+ end
+end
+
+# Override the kernel commands to add 'command', which let's us declare new
+# commands in block syntax
+module Kernel
+ ## In the kernel module, we redefine "command" so we can use it to declare commands
+ def command (desc, exec, &block)
+ CommandManager.add(Command.new(desc, exec, block))
+ end
+end
+
912 lib/commands.rb
@@ -0,0 +1,912 @@
+# vim: set ts=2 sw=2 tw=80
+##################################################################
+##
+## This file is for declaring the NSM pseudo-shell commands
+## Please put them in block syntax like the following:
+##
+## command "<description>", "<command>", do |<argument_name>|
+## <command execution>
+## end
+##
+## The <description> is used when the 'help' command is called.
+## <argument_name> is an array passed in by the commands args.
+##
+##################################################################
+
+## Help command
+command "Display commands and command usage. 'help <cmd>' for more detail",
+"help" do |args|
+ args = args[0].to_s
+
+ if args.length < 1
+ puts "\nUse 'help <cmd>' to get more detail about a command"
+ puts "\nAvailable Commands:"
+ puts "-" * 70
+ CommandManager.get_commands.sort.each { |k, val|
+ print " #{val.exec}"
+ }
+ print "\n\n"
+ return
+ end
+ puts " Commands matching '#{args}':"
+ puts "-" * 70
+ CommandManager.get_commands.each { |k, val|
+ if val.exec =~ /#{args}/i or args == "all"
+ print " #{val.exec}"
+ print " " * (15 - val.exec.length)
+ print "- #{val.desc}\n"
+ end
+ }
+ print "\n"
+
+end
+
+## Quit/q command
+command "Quit the program.", "quit" do |args|
+ puts "Goodbye!"
+ exit
+end
+command "Quit the program.", "q" do |args|
+ puts "Goodbye!"
+ exit
+end
+
+## List command
+command "List all modules and their enabled or disabled states", "list" do |args|
+ args = args[0].to_s
+
+ puts "\nCategories:"
+ $categories.each { |cat|
+ if (args =~ /en/)
+ cat.dump if cat.enabled?
+ elsif (args =~ /dis/)
+ cat.dump unless cat.enabled?
+ else
+ cat.dump
+ end
+ }
+ puts "--------------------------"
+ puts "\nModules:"
+ $modules.each { |mod|
+ if (args =~ /en/)
+ mod.dump if mod.enabled?
+ elsif (args =~ /dis/)
+ mod.dump unless mod.enabled?
+ else
+ mod.dump
+ end
+ }
+ puts "--------------------------"
+ puts $color ? "#{$GREEN}+ = Enabled#{$RESET}\n#{$RED}- = Disabled#{$RESET}" : "+ = Enabled\n- = Disabled"
+end
+
+## Toggle command
+command "Toggle a module on or off\n\t\tUsage: toggle <module name>\n\t\tYou can also use \
+'toggle all' and 'toggle none' to enable/disable all modules",
+"toggle" do |name|
+ name = name[0].to_s
+
+ if name.length < 1
+ puts "Need a module or category name"
+ return
+ end
+
+ # Split by space, toggling each module
+ mods = name.split(" ")
+
+ mods.each { |name|
+ toggle_module(name)
+ }
+ return
+end
+
+## Options command
+command "Display global options. If <module> is given, display that module's \n\t\t\
+options as well (ex: 'options hash'). 'options' will also display the commands \n\t\t\
+that will be run (before substitution) for that module.",
+"options" do |name|
+ puts "\nGlobal options:"
+ puts "-" * 35
+ if File.directory?($datafile)
+ puts "PCAP DIRECTORY: #{$datafile}"
+ puts "Pcap basename will be determined individually"
+ else
+ puts $color ? "${#{$MAGENTA}PCAP_FILE#{$RESET}}: #{$datafile}" : "${PCAP_FILE}: #{$datafile}"
+ puts $color ? "${#{$MAGENTA}PCAP_BASE#{$RESET}}: #{$basefile}" : "${PCAP_BASE}: #{$basefile}"
+ end
+ puts $color ? "${#{$MAGENTA}OUTPUT_DIR#{$RESET}}: #{$outputdir}" : "${OUTPUT_DIR}: #{$outputdir}"
+ puts $color ? "${#{$MAGENTA}MODULE_DIR#{$RESET}}: #{$moduledir}" : "${MODULE_DIR}: #{$moduledir}"
+ print "\n"
+
+ name = name[0].to_s
+
+ return if name.length < 1
+
+ mod = get_mod_by_name(name)
+ if mod.nil?
+ puts "Unknown module #{name}"
+ return
+ end
+ # Get the default values for a module
+ defs = mod.get_defaults
+ puts "Options for module #{name}:"
+ puts "-" * 35
+ defs.each_pair { |d, val|
+ puts $color ? "${#{$GREEN}#{d}#{$RESET}} = #{val}" : "${#{d}} = #{val}"
+ }
+ # Get the command-list to show what will be run
+ cmds = mod.get_commands
+ puts "\nCommand(s) to be executed for module #{name}:"
+ puts "-" * 35
+ cmds.each { |c| puts c }
+ print "\n"
+end
+
+## File command
+command "Set the ${PCAP_FILE} filename (the file to be analyzed).", "file" do |name|
+ name = name[0][0]
+
+ puts "name: #{name}"
+
+ if name.length < 1
+ puts "Need a pcap filename"
+ return
+ end
+ $datafile = name
+ #$datafile.gsub!(/~/,"#{ENV['HOME']}")
+ if $datafile =~ /\.gz$/i
+ begin
+ puts "Attempting decompression..."
+ # Attempt to do zlib decompression on the pcap file
+ require 'tempfile'
+ require 'zlib'
+ # Get handle for a new ungzip'd file, we want the full path
+ nfname = Dir.pwd + "/" + `basename #{$datafile}`.chomp.delete(".gz")
+ f = File.new(nfname,"w")
+ File.open($datafile) do |file|
+ gz = Zlib::GzipReader.new(file)
+ # Write to a new file
+ f.write(gz.read)
+ gz.close
+ end
+ $datafile = f.path
+ puts "New datafile: #{$datafile}"
+ f.close
+ rescue
+ STDERR.puts "Error decompressing: #{$!}"
+ end
+ end
+
+ # Fully expand the path of the datafile
+ $datafile = File.expand_path(File.dirname($datafile)) + "/" + `basename #{$datafile}`.chomp
+ puts "[!] WARNING: File doesn't exit!" if !File.exist?($datafile)
+ if File.directory?($datafile)
+ puts "PCAP DIRECTORY: #{$datafile}"
+ puts "Pcap basename will be determined by individual files."
+ else
+ puts $color ? "Setting ${#{$MAGENTA}PCAP_FILE#{$RESET}} = #{$datafile}" : "Setting ${PCAP_FILE} = #{$datafile}"
+ end
+ $basefile = `basename #{$datafile}`.chomp
+ puts $color ? "Setting ${#{$MAGENTA}PCAP_BASE#{$RESET}} = #{$basefile}" : "Setting ${PCAP_BASE} = #{$basefile}"
+ print "\n"
+end
+
+## Output command
+command "Set the ${OUTPUT_DIR} output directory.", "output" do |name|
+ name = name[0].to_s
+
+ if name.length < 1
+ puts "Need a output directory name"
+ return
+ end
+ # Replace '~' in the output path
+ name.gsub!(/~/,"#{ENV['HOME']}")
+ puts $color ? "Setting ${#{$MAGENTA}OUTPUT_DIR#{$RESET}} = #{name}" : "Setting ${OUTPUT_DIR} = #{name}"
+ $outputdir = name
+end
+
+## Run command
+command "Run enabled analysis files on the data (pcap) file. Use run <modname> to run a single module without toggling it.", "run" do |args|
+ args = args.to_s
+
+ if $datafile == ""
+ puts "Error: no pcap datafile has been specified"
+ puts "specify one with 'file <file.pcap>'"
+ return
+ end
+
+ if !File.exist?($datafile)
+ puts "ERROR: #{$datafile} does not exist. Please set file using 'file <filename>'."
+ return
+ end
+
+ fnames = []
+ if File.directory?($datafile)
+ puts "#{$datafile} is a directory, processing sub-files..."
+ fnames = get_filelist($datafile,true)
+ puts fnames
+ else
+ fnames << $datafile
+ end
+
+ # If an argument is specified, just run that and return
+ if (args.length > 1)
+ mod = get_mod_by_name(args)
+ if mod.nil?
+ puts "No module by that name loaded."
+ return
+ end
+
+ puts "===> module #{mod.get_name} running..."
+ fnames.each { |file|
+ mod.run_commands(get_uncompressed_filename(file))
+ }
+ return
+ end
+
+ puts "\nExecuting analysis...\n\n"
+
+ $modules.each { |mod|
+ if mod.enabled?
+ puts "===> module #{mod.get_name} running..."
+ fnames.each {
+ |file|
+ mod.run_commands(get_uncompressed_filename(file))
+ }
+ puts "===> module #{mod.get_name} finished."
+ else
+ puts "===> module #{mod.get_name} skipped."
+ end
+ print "\n"
+ }
+end
+
+## Info command
+command "Show detailed module information.", "info" do |name|
+ name = name[0].to_s
+
+ mod = get_mod_by_name(name)
+ if mod.nil?
+ puts "Module not found."
+ return
+ end
+ mod.print_info
+ print "\n"
+end
+
+## Set command
+command "Usage: set <mod> <opt> <val>\n\t\tSet the <mod> module's option \n\t\t\
+'<opt>' to have the value <val>. (ex: 'set aimsnarf OUTPUT_FILE ${PCAP_BASE}.aim.txt').",
+"set" do |args|
+ args = args[0].to_s
+
+ if args.length < 1
+ puts "Need a module name."
+ return
+ end
+ arglist = args.split(/ /, 3)
+ mod = get_mod_by_name(arglist[0])
+ if mod.nil?
+ puts "Module #{arglist[0]} not found."
+ return
+ end
+ if arglist[1].nil?
+ puts "Need variable name (ex: OUTPUT_DIR)"
+ return
+ end
+ if arglist[2].nil?
+ puts "Need variable value (ex: file.pcap)"
+ return
+ end
+ mod.update_option(arglist[1],arglist[2])
+end
+
+## Modload command
+command "Load the modules from the given directory. Note that this replaces \n\t\t\
+the currently loaded modules.",
+"modload" do |dir|
+ dir = dir[0].to_s
+
+ if dir.length < 1
+ puts "Please specify a module directory."
+ return
+ end
+
+ if !File.directory?(dir)
+ puts "#{dir} is not a directory."
+ return
+ end
+
+ $moduledir = dir
+ load_modules($moduledir)
+
+ load_categories($moduledir)
+
+end
+
+## Exec command
+command "Execute an external command", "exec" do |args|
+ args = args[0].to_s
+
+ if args.length < 1
+ puts "Need a program to execute."
+ return
+ end
+
+ cmd = args.gsub(/\$\{PCAP_FILE\}/i,$datafile)
+ cmd.gsub!(/\$\{PCAP_BASE\}/i,$basefile)
+ cmd.gsub!(/\$\{MODULE_DIR\}/i,$moduledir)
+ cmd.gsub!(/\$\{OUTPUT_DIR\}/i,$outputdir)
+
+ puts "Executing: #{cmd}"
+
+ system(cmd)
+ Logger.write("[exit: #{$?}] #{cmd.to_s}\n")
+ puts "Exit status: #{$?}"
+end
+command "Execute an external command","e" do |args|
+ CommandManager.execute("exec",args)
+end
+
+## Logfile command
+command "Set the file to log commands to", "logfile" do |file|
+ file = file[0].to_s
+
+ if file.length < 1
+ puts "Need a new logfile name."
+ print "\n"
+ puts "Currently logging to:"
+ puts Logger.get_log_filename
+ return
+ end
+
+ if File.directory?(file)
+ puts "#{file} is a directory, can't log to that file."
+ return
+ end
+
+ puts "New logfile is: #{file}"
+ Logger.new(file)
+
+ Logger.write("-" * 80)
+ Logger.write("\n")
+ Logger.write("Log for nsm-console begun at #{Time.now.year}-#{Time.now.month}-#{Time.now.day} #{Time.now.hour}:#{Time.now.min}:#{Time.now.sec}\n")
+ Logger.write("-" * 80)
+ Logger.write("\n")
+
+end
+
+## History command
+command "Display command history", "history" do |args|
+ History.print()
+end
+
+## Encode command
+command "Encode value or file into different form\n\t\tRun without any options to see \
+usage",
+"encode" do |args|
+ args = args[0].to_s
+
+ if args.length < 2
+ puts "\nUsage:\n\n"
+ puts "encode [-f] <type> [file|string]"
+ puts "Use -f to specify a file"
+ puts "\nAvailable encoding:"
+ puts "-" * 30
+ Encoder.get_encode_list.each { |e| puts e; }
+ return
+ end
+
+ if (args =~ /-f/)
+ arglist = args.split(/ /, 3)
+ type = arglist[1].to_s
+ str = File.open("#{arglist[2]}").readlines
+ else
+ arglist = args.split(/ /, 2)
+ type = arglist[0].to_s
+ str = arglist[1].to_s.chomp
+ end
+
+ output = ""
+
+ print "\n"
+ puts "Encoding ascii --> #{type}..."
+ puts "Output ([]'s added to show beginning and end):\n\n"
+
+ begin
+ cmd = "Encoder.encode_#{type}(\"#{str}\")"
+ output = output + eval(cmd)
+ rescue NoMethodError
+ puts "Encoding not found."
+ rescue
+ STDERR.puts "Error: #{$!}"
+ return
+ end
+
+ print "["
+ print output
+ print "]\n\n"
+
+end
+
+## Decode command
+command "Decode value or file into different ascii\n\t\tRun without any options to see \
+usage",
+"decode" do |args|
+
+ args = args[0].to_s
+
+ if args.length < 1
+ puts "\nUsage:\n\n"
+ puts "decode [-f] <type> [file|string]"
+ puts "Use -f to specify a file"
+ puts "\nAvailable decoding:"
+ puts "-" * 30
+ Encoder.get_decode_list.each { |d| puts d; }
+ return
+ end
+
+ if (args =~ /-f/)
+ arglist = args.split(/ /, 3)
+ type = arglist[1].to_s
+ str = File.open("#{arglist[2]}").readlines
+ # Get rid of line-breaks
+ str.collect! { |n| n.gsub!(/\n/,"") }
+ else
+ arglist = args.split(/ /, 2)
+ type = arglist[0].to_s
+ str = arglist[1].to_s.chomp
+ end
+
+ output = ""
+
+ print "\n"
+ puts "Decoding #{type} --> ascii..."
+ puts "Output ([]'s added to show beginning and end):\n\n"
+
+ begin
+ cmd = "Encoder.decode_#{type}(\"#{str}\")"
+ output = eval(cmd)
+ rescue NoMethodError
+ puts "Decoding not found."
+ STDERR.puts "Error: #{$!}"
+ rescue
+ STDERR.puts "Error: #{$!}"
+ return
+ end
+
+ print "["
+ print output
+ print "]\n\n"
+
+end
+
+## Eval command
+command "Evaluate a single line in Ruby","eval" do |args|
+ args = args[0].to_s
+ if args.length < 1
+ puts "Need a line to eval."
+ return
+ end
+
+ print "=> "
+ begin
+ ret = eval("#{args}")
+ rescue
+ STDERR.puts "Caught error: #{$!}"
+ end
+ puts "#{ret}"
+end
+
+## Credits command :D
+command "Display program credits","credits" do |args|
+ print "\n"
+
+ puts "Original design and development:"
+ puts "-" * 40
+ puts "Matthew Lee Hinman - matthew [dot] hinman [at] gmail [dot] com"
+ puts "Scholar - PcapParser library, flowtag module (thanks scholar!)"
+ puts "JohnQPublic - Clamscan module"
+
+ print "\n"
+ puts "Ideas:"
+ puts "-" * 40
+ puts "Geek00l, Enhanced, Scholar"
+
+ print "\n"
+end
+
+## Print command
+command "Display a packet's information and payload.\n\t\tUse with no arguments to see usage.",
+"print" do |args|
+ args = args[0].to_s
+
+ if args.length < 1
+ puts "Usage:"
+ puts "\nprint <option> #|#-#|*"
+ puts "Options:"
+ puts "-f Display entire packet, not just payload"
+ puts "-x Display packet payload in hex and ascii, similar to -X option for tcpdump"
+ puts "-a Display packet payload as ascii"
+ puts "-h Display packet payload in hex"
+ puts "No option will print only connection information"
+ puts "\nExamples:"
+ puts "'p 1-10' print out connection information for packets 1 through 10"
+ puts "'p -x 101' print packet 101's payload in tcpdump -X format"
+ puts "'p -a 1000-*' print packet 1000 through the end in ascii format"
+ puts "'p *' print all the connection streams"
+ print "\n"
+ return
+ end
+
+ if !File.exist?($datafile)
+ puts "File #{$datafile} does not exist or no file specified."
+ return
+ end
+
+ #puts "Args: #{args}"
+ opts = "list"
+
+ full = false
+ if args =~ /-f/i
+ full = true
+ puts "Printing full packet"
+ args.gsub!(/\s*-f\s*/i,"")
+ end
+
+ if args =~ /-x/i
+ opts = "full"
+ args.gsub!(/\s*-x\s*/i,"")
+ elsif args =~ /-a/i
+ opts = "ascii"
+ args.gsub!(/\s*-a\s*/i,"")
+ elsif args =~ /-h/i
+ opts = "hex"
+ args.gsub!(/\s*-h\s*/i,"")
+ end
+
+ if args =~ /,/i
+ ranges = args.split(/,/)
+ sranges = ranges[0,ranges.length-1]
+ opt = ""
+ opt = "-x " if opts == "full"
+ opt = "-a " if opts == "ascii"
+ opt = "-h " if opts == "hex"
+ newrange = sranges.join(",")
+ newrange = opt + newrange
+ CommandManager.execute("print",newrange)
+ print "\n"
+ args = ranges[ranges.length-1]
+ end
+
+ min = max = 1
+ if args =~ /(\d+)\s*-\s*(\d+)/
+ min = $1.to_i
+ max = $2.to_i
+ elsif args =~ /(\d+)\s*-\s*\*/
+ min = $1.to_i
+ max = "*"
+ elsif args == "*"
+ max = "*"
+ else
+ min = args.to_i
+ max = min
+ end
+
+ if File.directory?($datafile)
+ fnames = get_filelist($datafile,true)
+ fnames.each { |file|
+ file = get_uncompressed_filename(file)
+ puts "\nFile: #{file}\n\n"
+ print_pkt_range(file,min,max,opts,full)
+ }
+ else
+ print_pkt_range(get_uncompressed_filename($datafile),min,max,opts,full)
+ end
+end
+command "An alias for the 'print' command.", "p" do |args|
+ CommandManager.execute("print",args)
+end
+
+## Color command
+command "Toggle the terminal color output on or off","color" do |args|
+ args = args[0].to_s
+ if args =~ /off/i
+ puts "Color is now off."
+ $color = false
+ elsif args =~ /on/i
+ puts "#{$CYAN}C#{$RED}o#{$GREEN}l#{$BROWN}o#{$MAGENTA}r#{$RESET} is now #{$BLUE}on!#{$RESET}"
+ $color = true
+ elsif $color
+ puts "Color is now off."
+ $color = false
+ else
+ puts "#{$CYAN}C#{$RED}o#{$GREEN}l#{$BROWN}o#{$MAGENTA}r#{$RESET} is now #{$BLUE}on!#{$RESET}"
+ $color = true
+ end
+end
+
+## Alias command
+command "Create an alias for a command, Usage: alias <cmd> = <newcmd(s)>",
+"alias" do |args|
+ args = args.to_s
+ if args.length < 1
+ puts "Current aliases:"
+ puts "-" * 30
+ ## Print aliases
+ a = NSM_Alias.get_aliases()
+ a.each { |k,v|
+ puts "#{k}\t\t- #{v}"
+ }
+ print "\n"
+ return
+ end
+
+ args = args.chomp.split("=",2)
+ if (args.length < 2) or args[1].length < 1
+ puts "Usage: alias <cmd>='<newcmd>'"
+ return
+ end
+
+ ## Strip our whitespace so you can space out the commands
+ args[0] = args[0].strip
+ args[1] = args[1].strip
+
+ ## Strip out any surrounding '', if they're used to GNU alias
+ puts "Aliasing '#{args[0]}' to #{args[1]}"
+ args[1] =~ /\'(.*)\'/
+ cmd = $1.nil? ? args[1] : $1
+ NSM_Alias.set_alias(args[0],cmd)
+
+end
+
+## Unalias command
+command "Unalias a command, Usage: 'unalias <name>'","unalias" do |name|
+ name = name.to_s
+
+ if name.length < 1
+ puts "Please specify an alias to unalias"
+ end
+
+ result = NSM_Alias.del_alias(name)
+ unless result.nil?
+ puts "'#{name}' successfully unaliased"
+ else
+ puts "There is no #{name} alias."
+ end
+end
+
+## CheckIP command
+command "Check an IP address against the Harimau watchlist","checkip" do |addr|
+ addr = addr.to_s
+
+ if addr.length < 1
+ puts "Need an IP address to query"
+ return
+ end
+
+ truncaddr = String.new(addr)
+ truncaddr =~ /(\d{1,3}\.\d{1,3}\.\d{1,3})\./
+ truncaddr = String.new($1)
+ if system("which wget 2>&1 > /dev/null")
+ out = `wget -q -O - http://watchlist.security.org.my/watchlist/show?ip=#{addr} | grep '#{truncaddr}'`
+ if out.length < 1
+ puts "#{addr}: No records"
+ else
+ puts out.chomp
+ end
+ else
+ require 'net/http'
+
+ url = URI.parse("http://watchlist.security.org.my/watchlist/show?ip=#{addr}")
+ req = Net::HTTP::Get.new(url.path)
+ res = Net::HTTP.start(url.host, url.port) {|http|
+ http.request(req)
+ }
+ found = false
+ res.body.each_line { |line|
+ if line =~ /#{truncaddr}/i
+ puts line.chomp
+ found = true
+ end
+ }
+ if found == false
+ puts "#{addr}: No records found"
+ end
+ end
+end
+
+## Dump command
+command "Dump the specified packet contents to a file, run without arguments for usage",
+"dump" do |args|
+ args = args[0].to_s
+
+ if args.length < 2
+ puts "Usage:"
+ puts "\ndump [-f] #|#-#|* <filename>"
+ puts "\nExamples:"
+ puts "'dump 1-10 a.out' - Dump the payloads of packets 1-10 into a.out"
+ puts "'dump 1,5,7-9 a.out' - Dump the payloads of packets 1,5,7,8,9 into a.out"
+ puts "'dump 1000-* a.out' - Dump packets 1000 through the end into a.out"
+ puts "'dump * a.out' - Dump all the packet payloads into a.out"
+ print "\n"
+ puts "The '-f' flag dumps the ENTIRE packet, not just the payload"
+ print "\n"
+ return
+ end
+
+ if !File.exist?($datafile)
+ puts "File #{$datafile} does not exist or no file specified."
+ return
+ end
+
+ fulldump = false
+ if args =~ /^-f /
+ args = args[3,args.length]
+ puts "New args: #{args}"
+ puts "Dumping full packet, not just payload..."
+ fulldump = true
+ end
+
+ outputfile = String.new(args.strip)
+ ## hack hack hack, but I wanted to do it in one line
+ outputfile = outputfile.reverse.split(/ /,2)[0].reverse
+ args.gsub!(/#{outputfile}/,"")
+
+ if args =~ /,/i
+ ranges = args.split(/,/)
+ sranges = ranges[0,ranges.length-1]
+ newrange = sranges.join(",")
+ newrange = newrange + " " + outputfile
+ CommandManager.execute("dump",newrange)
+ args = ranges[ranges.length-1]
+ end
+
+ min = max = 1
+ if args =~ /(\d+)\s*-\s*(\d+)/
+ min = $1.to_i
+ max = $2.to_i
+ elsif args =~ /(\d+)\s*-\s*\*/
+ min = $1.to_i
+ max = "*"
+ elsif args =~ /\*/
+ min = 1
+ max = "*"
+ else
+ min = args.to_i
+ max = min
+ end
+
+ # Interate through the files in the directory if we were given a directory
+ # instead of a single file.
+ if File.directory?($datafile)
+ fnames = get_filelist($datafile,true)
+ fnames.each { |file|
+ file = get_uncompressed_filename(file)
+ puts "\nFile: #{file}\n\n"
+ rawwrite_pkt_range(file,min,max,outputfile,fulldump)
+ }
+ else
+ ## Uncompressing doesn't work yet, hopefully soon
+ rawwrite_pkt_range(get_uncompressed_filename($datafile),min,max,outputfile,fulldump)
+ end
+
+end
+
+
+## The ip2asn command
+command "Find the ASN for a given IP address","ip2asn" do |addr|
+
+ addr = addr.to_s.chomp
+
+ if addr.length < 1
+ puts "Need an IP address to query"
+ return
+ end
+
+ begin
+ require 'socket'
+ # Use the cymru team's ip->asn server
+ s = TCPSocket.new('whois.cymru.com',43)
+ s.write("begin\n")
+ s.write(addr)
+ s.write("\n")
+ s.write("end\n")
+
+ while line = s.gets
+ print line
+ end
+ s.close
+ print "\n"
+ rescue
+ puts "Encountered error: #{$!}"
+ end
+
+end
+
+
+## The iplist command
+command "Generate a list of all the IPs in a file. Usage: iplist [file] (if no file is specified, stdout is used)","iplist" do |file|
+ file = file.to_s.chomp
+
+ iplist = {}
+
+ # Helper method to generate hash list key=ip, value=number
+ iplist = gen_list_from_pcap()
+
+ # Sort the list backwards by packet count
+ iplist = iplist.sort {|a,b| b[1]<=>a[1]}
+
+ if file.length > 1
+ puts "Dumping iplist to #{file}..."
+ begin
+ # Append to file
+ fd = File.open(file, "a")
+ fd.puts "=== IP list for #{$basefile} ==="
+ iplist.each { |ip, pnum|
+ addr = [ip].pack("N").unpack("C4").join(".")
+ fd.print addr
+ fd.print "\t"
+ fd.puts pnum
+ }
+ rescue
+ STDERR.puts "Error writing to file: #{$!}"
+ end
+ else
+ if File.directory?($datafile)
+ print "=== IP list for "
+ fnames = get_filelist($datafile,true)
+ fnames.each { |f| print f; print " " }
+ puts "==="
+ else
+ puts "=== IP list for #{$basefile} ==="
+ end
+ iplist.each { |ip, pnum|
+ addr = [ip].pack("N").unpack("C4").join(".")
+ print addr
+ print "\t"
+ puts pnum
+ }
+ end
+
+end
+
+
+## The update command
+command "Update NSM-Console to the latest version from SVN, use -v for verbose", "update" do |args|
+ puts "Updating NSM-Console from svn..."
+ args = args.to_s.chomp
+ verbose = args =~ /-v/ ? true : false
+
+ unless system("which svn 2>&1 > /dev/null")
+ STDERR.puts "svn not found, please install subversion and try again."
+ end
+
+# puts "Generating update files..." if verbose
+# `mkdir -p /tmp/nsmc-update` unless File.directory?("/tmp/nsmc-update")
+#
+# svnconf = File.open("/tmp/nsmc-update/config","w")
+# svnconf.puts "[auth]"
+# svnconf.puts "[helpers]"
+# svnconf.puts "[tunnels]"
+# svnconf.puts "ssh = ssh -p 1337"
+# svnconf.puts "[miscellany]"
+# svnconf.puts "[auto-props]"
+# svnconf.close
+
+ puts "Fetching newest revision from svn..." if verbose
+
+ puts "svn co --non-interactive http://svn.security.org.my/trunk/rawpacket-root/usr/home/analyzt/rp-NSM/nsm-console ." if verbose
+
+ system("svn co --non-interactive http://svn.security.org.my/trunk/rawpacket-root/usr/home/analyzt/rp-NSM/nsm-console .")
+
+ puts "Return status: #{$?}" if verbose
+
+ if $? != 0
+ STDERR.puts "\nThere was an error while updating, email lee [at] writequit [dot] org"
+ else
+ STDERR.puts "\nDone. Restart NSM-Console to use new version"
+ end
+
+end
+
137 lib/encodelib.rb
@@ -0,0 +1,137 @@
+# vim: set ts=2 sw=2 tw=80
+## Class encapsulating all the encode/decode methods
+class Encoder
+ def Encoder.get_encode_list
+ ["base64","md5","sha256","urlescape","binary","binary_MSB","binary_LSB","hex","hex_MSB","hex_LSB","uuencode","rot13"]
+ end
+ def Encoder.get_decode_list
+ ["base64","urlescape","binary","binary_MSB","binary_LSB","hex","char","uudecode","octal","rot13"]
+ end
+
+ ## Encoder methods
+ def Encoder.encode_base64(str)
+ require 'base64'
+ return Base64.encode64(str)
+ end
+
+ def Encoder.encode_md5(str)
+ require 'digest/md5'
+ return Digest::MD5.hexdigest(str)
+ end
+
+ def Encoder.encode_sha256(str)
+ require 'digest/sha2'
+ return Digest::SHA256.hexdigest(str)
+ end
+
+ def Encoder.encode_urlescape(str)
+ require 'cgi'
+ return CGI.escape(str)
+ end
+
+ def Encoder.encode_binary(str)
+ return str.unpack('B*').to_s
+ end
+ def Encoder.encode_binary_MSB(str)
+ return str.unpack('B*').to_s
+ end
+ def Encoder.encode_binary_LSB(str)
+ return str.unpack('b*').to_s
+ end
+
+ # Note that the default "hex" encoding is little-endian, if you're using
+ # NSM-Console on SPARC or PPC, uhhh...
+ def Encoder.encode_hex(str)
+ return str.unpack('H*').to_s
+ end
+ def Encoder.encode_hex_LSB(str)
+ return str.unpack('h*').to_s
+ end
+ def Encoder.encode_hex_MSB(str)
+ return str.unpack('H*').to_s
+ end
+
+ def Encoder.encode_uuencode(str)
+ return [str].pack('u*').to_s
+ end
+
+ def Encoder.encode_rot13(str)
+ return str.downcase.rot13
+ end
+
+ ## Decoder methods
+ def Encoder.decode_base64(str)
+ require 'base64'
+ return Base64.decode64(str)
+ end
+
+ def Encoder.decode_urlescape(str)
+ require 'cgi'
+ return CGI.unescape(str)
+ end
+
+ def Encoder.decode_binary(str)
+ return str.to_a.pack('B*')
+ end
+ def Encoder.decode_binary_MSB(str)
+ return str.to_a.pack('B*')
+ end
+ def Encoder.decode_binary_LSB(str)
+ return str.to_a.pack('b*')
+ end
+
+ def Encoder.decode_hex(str)
+ out = ""
+ # Check for space-delineated and kill the spaces if it is
+ if str =~ / /
+ str.delete!(" ")
+ end
+
+ # Here I do some fancy checking to make sure that the string isn't already
+ # delineated by \x, which would automatically translate the string in ruby
+ str.scan(/../).each { |h|
+ c = h.hex.chr
+ d = c.to_s.unpack("C*")[0].to_i
+ if ((d < 32) || (d > 127))
+ out += h
+ else
+ out += h.hex.chr
+ end
+ }
+ return out
+ end
+
+ def Encoder.decode_char(str)
+ out = ""
+ str.split(/ /).each { |c|
+ out = out + c.to_i.chr.to_s
+ }
+ return out
+ end
+
+ def Encoder.decode_uudecode(str)
+ return str.unpack('u*').to_s
+ end
+
+ def Encoder.decode_octal(str)
+ out = ""
+ str.scan(/.../).each { |o|
+ out = out + o.oct.chr
+ }
+ return out
+ end
+
+ def Encoder.decode_rot13(str)
+ return str.downcase.rot13
+ end
+
+end
+
+## Add methods to tab completion
+enclist = Encoder.get_encode_list()
+declist = Encoder.get_decode_list()
+list = enclist.concat(declist)
+list.uniq!
+list.each { |l|
+ $tabstrings.push(l.to_s)
+}
18 lib/history.rb
@@ -0,0 +1,18 @@
+# vim: set ts=2 sw=2 tw=80
+# Class used to keep track of commands for the 'history' command
+class History
+ @@history = []
+
+ def History.write(line)
+ @@history.push(line.to_s)
+ end
+
+ def History.print
+ i = 1
+ @@history.each { |h|
+ puts "#{i}\t- #{h.to_s}"
+ i = i + 1
+ }
+ end
+
+end
63 lib/logging.rb
@@ -0,0 +1,63 @@
+# vim: set ts=2 sw=2 tw=80
+# NSM-Console logging to a text file
+class Logger
+ @@logfile = nil
+
+ def initialize(name)
+ @@logfile = name.to_s
+ end
+
+ def Logger.write(line)
+ if @@logfile.nil?
+ puts "Error. No logfile specified."
+ return
+ end
+
+ if !File.exist?(@@logfile)
+ begin
+ system("touch #{@@logfile}")
+ rescue
+ STDERR.puts "Error creating logfile #{@@logfile}: #{$!}"
+ exit
+ end
+ end
+
+ begin
+ File.open(@@logfile, "a") do |f|
+ f.write(line)
+ end
+ rescue
+ STDERR.puts "Error writing to logfile: #{$!}"
+ end
+
+ end
+
+ # Accessor for log filename
+ def Logger.get_log_filename
+ @@logfile
+ end
+
+ # Initialize logging given a filename
+ def Logger.start_logging(logfilename)
+ puts "Logging to #{logfilename}\n\n"
+ Logger.new(logfilename)
+ ## Write initial entry
+ Logger.write("-" * 80)
+ Logger.write("\n")
+ Logger.write("Log for nsm-console begun at #{Time.now.year}\
+ -#{Time.now.month}-#{Time.now.day} #{Time.now.hour}\
+ :#{Time.now.min}:#{Time.now.sec}\n")
+ Logger.write("-" * 80)
+ Logger.write("\n")
+ end
+
+ def Logger.get_def_log_file
+ logfilename = "logs/nsm-log."
+ logfilename.concat(Time.now.year.to_s)
+ logfilename.concat(Time.now.month.to_s)
+ logfilename.concat(Time.now.day.to_s)
+ logfilename.concat(".log")
+ return logfilename
+ end
+
+end
65 lib/nsm_alias.rb
@@ -0,0 +1,65 @@
+# vim: set ts=2 sw=2 tw=80
+## The NSM_Alias class simply keeps track of all the
+## defined aliases and provides methods to update, add
+## delete, query or unalias an alias
+
+class NSM_Alias
+ ## Retreive an alias by it's name
+ def NSM_Alias.get_alias(name)
+ @aliases = {} if @aliases.nil?
+ return @aliases[name]
+ end
+
+ ## Set a new alias or update an existing one
+ def NSM_Alias.set_alias(name,val)
+ @aliases = {} if @aliases.nil?
+ @aliases[name.to_s] = val.to_s
+ end
+
+ ## Delete an alias
+ def NSM_Alias.del_alias(name)
+ @aliases = {} if @aliases.nil?
+ @aliases.delete(name)
+ end
+
+ ## Get a hash of the current aliases
+ def NSM_Alias.get_aliases
+ @aliases = {} if @aliases.nil?
+ return @aliases
+ end
+
+ ## Return an array of alias names
+ def NSM_Alias.get_alias_names
+ results = []
+ @aliases.each { |k,v|
+ results.push(k)
+ }
+ return results
+ end
+
+ ## Generate a new command and arguments (resolve alias)
+ # returns: cmd, args
+ def NSM_Alias.resolve(cmd, args)
+ a = self.get_alias(cmd)
+ unless a.nil?
+ newcmd = String.new(a)
+ newcmd.gsub!(/(\w)\s([\s\S]*)/) { $1 }
+ newcmd.chomp!
+ ## We concatinate our old args with the args from the alias
+ unless args.nil?
+ unless $2.nil?
+ newargs = $2 + " " + args
+ else
+ newargs = args
+ end
+ newargs.strip!
+ return newcmd, newargs
+ else
+ return newcmd, $2.to_s.strip
+ end
+ end
+ # just return what we already have if it doesn't have an alias
+ return cmd, args
+ end
+
+end
43 lib/nsm_category.rb
@@ -0,0 +1,43 @@
+# vim: set ts=2 sw=2 tw=80
+class NSM_Category
+
+ def initialize(name,mods)
+ @cat_name = name
+ @enabled = false
+ @modules = mods
+ end
+
+ def get_name
+ return @cat_name
+ end
+
+ def enabled?
+ return @enabled
+ end
+
+ def dump
+ if self.enabled?
+ print $color ? "#{$GREEN}[+]#{$RESET} " : "[+] "
+ else
+ print $color ? "#{$RED}[-]#{$RESET} " : "[-] "
+ end
+ puts $color ? "#{$BROWN}#{@cat_name}#{$RESET}" : "#{@cat_name}"
+ end
+
+ def get_modules
+ return @modules
+ end
+
+ def set_enabled_mods(en)
+ if en
+ @enabled = true
+ else
+ @enabled = false
+ end
+ @modules.each { |mod|
+ m = get_mod_by_name(mod)
+ m.set_enabled(en) unless m.nil?
+ }
+ end
+
+end
157 lib/nsm_console.rb
@@ -0,0 +1,157 @@
+# vim: set ts=2 sw=2 tw=80
+class NSM_Console
+ $PROMPT = "nsm> "
+ $CPROMPT = "\033[32mnsm\033[0m> "
+
+ # Save our default standard out
+ $DEF_STDOUT = STDOUT.dup
+
+ def initialize(args)
+
+ # flag to redirect stdout for startup
+ quiet_startup = false
+
+ if (args.include?("-q"))
+ # Remove -q from the arguments
+ args.delete_at(0)
+ quiet_startup = true
+ end
+
+ if quiet_startup
+ # Save the current STDOUT so we can reopen it
+ saved_stdout = STDOUT.dup
+ # reopen /dev/null (or NUL) to quiet output
+ STDOUT.reopen( RUBY_PLATFORM =~ /mswin/ ? "NUL" : "/dev/null" )
+ end
+
+ ## Print the lobster
+ print_banner()
+ puts "NSM Console version #{$NSM_VERSION}"
+ print "\n"
+
+ ## Set {$PCAP_FILE} if passed in as an argument
+ CommandManager.execute("file",args[0]) if args.length > 0
+
+ ## Load modules
+ load_modules($moduledir)
+ load_categories($moduledir)
+
+ ## Initialize logging
+ logfile = Logger.get_def_log_file
+ Logger.start_logging(logfile)
+
+ puts $color ? "Default ${#{$MAGENTA}OUTPUT_DIR#{$RESET}} is '#{$outputdir}'" : "Default ${OUTPUT_DIR} is '#{$outputdir}'"
+ puts $color ? "Default ${#{$MAGENTA}MODULE_DIR#{$RESET}} is '#{$moduledir}'" : "Default ${MODULE_DIR} is '#{$moduledir}'"
+
+ cmd = ""
+
+ print "\n"
+
+ ## Read ~/.nsmcrc
+ rcfile = ENV['HOME']
+ rcfile += "/.nsmcrc"
+ if File.exist?(rcfile)
+ print "Reading ~/.nsmcrc..."
+ if !quiet_startup
+ old_stdout = STDOUT.dup
+ STDOUT.reopen( RUBY_PLATFORM =~ /mswin/ ? "NUL" : "/dev/null" )
+ end
+ read_dotnsmcrc(rcfile)
+ if !quiet_startup
+ STDOUT.reopen(old_stdout)
+ end
+ print "done.\n\n"
+ end
+
+ if quiet_startup
+ # reopen stdout so we can write output
+ STDOUT.reopen(saved_stdout)
+ end
+ end
+
+ def run
+ ## Print the welcome message
+ print_welcome_message()
+
+ ## Command loop until quit
+ loop {
+
+ ## New method uses readline so we can use tab-completion
+ begin
+ # I put this line in because after piping the prompt wouldn't show up
+ if STDOUT != $DEF_STDOUT
+ print "\n"
+ end
+
+ p = $color ? $CPROMPT : $PROMPT
+ cmd = readline("#{p}", TRUE)
+ rescue Interrupt
+ puts "Caught ^C, use 'quit' or 'q' to exit"
+ rescue
+ STDERR.puts "Error encountered: #{$!}"
+ end
+