ronin-support 0.4.1 → 0.5.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (108) hide show
  1. data/ChangeLog.md +75 -32
  2. data/Gemfile +17 -18
  3. data/README.md +9 -10
  4. data/Rakefile +10 -2
  5. data/gemspec.yml +1 -1
  6. data/lib/ronin/binary.rb +21 -0
  7. data/lib/ronin/binary/hexdump.rb +20 -0
  8. data/lib/ronin/binary/hexdump/parser.rb +411 -0
  9. data/lib/ronin/binary/struct.rb +579 -0
  10. data/lib/ronin/binary/template.rb +437 -0
  11. data/lib/ronin/extensions/ip_addr.rb +17 -13
  12. data/lib/ronin/extensions/regexp.rb +45 -0
  13. data/lib/ronin/extensions/string.rb +3 -3
  14. data/lib/ronin/formatting/extensions/binary.rb +1 -0
  15. data/lib/ronin/formatting/extensions/binary/array.rb +63 -0
  16. data/lib/ronin/formatting/extensions/binary/base64.rb +106 -0
  17. data/lib/ronin/formatting/extensions/binary/file.rb +39 -6
  18. data/lib/ronin/formatting/extensions/binary/float.rb +65 -0
  19. data/lib/ronin/formatting/extensions/binary/integer.rb +56 -43
  20. data/lib/ronin/formatting/extensions/binary/string.rb +75 -187
  21. data/lib/ronin/formatting/extensions/text/string.rb +61 -0
  22. data/lib/ronin/fuzzing/extensions/string.rb +21 -8
  23. data/lib/ronin/fuzzing/fuzzing.rb +19 -17
  24. data/lib/ronin/network.rb +2 -1
  25. data/lib/ronin/network/dns.rb +57 -15
  26. data/lib/ronin/network/extensions.rb +0 -1
  27. data/lib/ronin/network/ftp.rb +145 -0
  28. data/lib/ronin/network/http/http.rb +13 -14
  29. data/lib/ronin/network/imap.rb +11 -10
  30. data/lib/ronin/network/mixins.rb +1 -0
  31. data/lib/ronin/network/mixins/ftp.rb +155 -0
  32. data/lib/ronin/network/mixins/ssl.rb +1 -1
  33. data/lib/ronin/network/mixins/tcp.rb +39 -6
  34. data/lib/ronin/network/mixins/udp.rb +121 -1
  35. data/lib/ronin/network/mixins/unix.rb +279 -0
  36. data/lib/ronin/network/pop3.rb +5 -5
  37. data/lib/ronin/network/proxy.rb +578 -0
  38. data/lib/ronin/network/smtp/email.rb +1 -1
  39. data/lib/ronin/network/smtp/smtp.rb +7 -8
  40. data/lib/ronin/network/ssl.rb +1 -6
  41. data/lib/ronin/network/tcp.rb +2 -305
  42. data/lib/ronin/network/tcp/proxy.rb +377 -0
  43. data/lib/ronin/network/tcp/tcp.rb +435 -0
  44. data/lib/ronin/network/telnet.rb +27 -23
  45. data/lib/ronin/network/udp.rb +2 -266
  46. data/lib/ronin/network/udp/proxy.rb +169 -0
  47. data/lib/ronin/network/udp/udp.rb +442 -0
  48. data/lib/ronin/network/unix.rb +287 -0
  49. data/lib/ronin/path.rb +2 -2
  50. data/lib/ronin/spec/ui/output.rb +1 -7
  51. data/lib/ronin/support.rb +1 -0
  52. data/lib/ronin/support/inflector.rb +3 -7
  53. data/lib/ronin/support/support.rb +2 -1
  54. data/lib/ronin/support/version.rb +1 -1
  55. data/lib/ronin/ui/output/helpers.rb +13 -15
  56. data/lib/ronin/ui/output/output.rb +2 -2
  57. data/lib/ronin/ui/output/terminal/color.rb +10 -4
  58. data/lib/ronin/wordlist.rb +92 -17
  59. data/ronin-support.gemspec +38 -109
  60. data/spec/binary/hexdump/helpers/hexdumps.rb +13 -0
  61. data/spec/{formatting/binary → binary/hexdump}/helpers/hexdumps/ascii.bin +0 -0
  62. data/spec/{formatting/binary → binary/hexdump}/helpers/hexdumps/hexdump_decimal_shorts.txt +0 -0
  63. data/spec/{formatting/binary → binary/hexdump}/helpers/hexdumps/hexdump_hex_bytes.txt +0 -0
  64. data/spec/{formatting/binary → binary/hexdump}/helpers/hexdumps/hexdump_hex_shorts.txt +0 -0
  65. data/spec/{formatting/binary → binary/hexdump}/helpers/hexdumps/hexdump_octal_bytes.txt +0 -0
  66. data/spec/{formatting/binary → binary/hexdump}/helpers/hexdumps/hexdump_octal_shorts.txt +0 -0
  67. data/spec/{formatting/binary → binary/hexdump}/helpers/hexdumps/hexdump_repeated.txt +0 -0
  68. data/spec/{formatting/binary → binary/hexdump}/helpers/hexdumps/od_decimal_bytes.txt +0 -0
  69. data/spec/{formatting/binary → binary/hexdump}/helpers/hexdumps/od_decimal_ints.txt +0 -0
  70. data/spec/{formatting/binary → binary/hexdump}/helpers/hexdumps/od_decimal_quads.txt +0 -0
  71. data/spec/{formatting/binary → binary/hexdump}/helpers/hexdumps/od_decimal_shorts.txt +0 -0
  72. data/spec/binary/hexdump/helpers/hexdumps/od_doubles.txt +17 -0
  73. data/spec/binary/hexdump/helpers/hexdumps/od_floats.txt +17 -0
  74. data/spec/{formatting/binary → binary/hexdump}/helpers/hexdumps/od_hex_bytes.txt +0 -0
  75. data/spec/{formatting/binary → binary/hexdump}/helpers/hexdumps/od_hex_ints.txt +0 -0
  76. data/spec/{formatting/binary → binary/hexdump}/helpers/hexdumps/od_hex_quads.txt +0 -0
  77. data/spec/{formatting/binary → binary/hexdump}/helpers/hexdumps/od_hex_shorts.txt +0 -0
  78. data/spec/binary/hexdump/helpers/hexdumps/od_named_chars.txt +17 -0
  79. data/spec/{formatting/binary → binary/hexdump}/helpers/hexdumps/od_octal_bytes.txt +0 -0
  80. data/spec/{formatting/binary → binary/hexdump}/helpers/hexdumps/od_octal_ints.txt +0 -0
  81. data/spec/{formatting/binary → binary/hexdump}/helpers/hexdumps/od_octal_quads.txt +0 -0
  82. data/spec/{formatting/binary → binary/hexdump}/helpers/hexdumps/od_octal_shorts.txt +0 -0
  83. data/spec/{formatting/binary → binary/hexdump}/helpers/hexdumps/od_repeated.txt +0 -0
  84. data/spec/{formatting/binary → binary/hexdump}/helpers/hexdumps/repeated.bin +0 -0
  85. data/spec/binary/hexdump/parser_spec.rb +302 -0
  86. data/spec/binary/struct_spec.rb +496 -0
  87. data/spec/binary/template_spec.rb +400 -0
  88. data/spec/extensions/ip_addr_spec.rb +58 -32
  89. data/spec/extensions/regexp_spec.rb +60 -0
  90. data/spec/extensions/string_spec.rb +1 -1
  91. data/spec/formatting/binary/array_spec.rb +22 -0
  92. data/spec/formatting/binary/base64_spec.rb +50 -0
  93. data/spec/formatting/binary/float_spec.rb +30 -0
  94. data/spec/formatting/binary/integer_spec.rb +54 -40
  95. data/spec/formatting/binary/string_spec.rb +69 -182
  96. data/spec/formatting/text/string_spec.rb +30 -0
  97. data/spec/network/dns_spec.rb +64 -0
  98. data/spec/network/ftp_spec.rb +65 -0
  99. data/spec/network/proxy_spec.rb +121 -0
  100. data/spec/network/shared/unix_server.rb +31 -0
  101. data/spec/network/tcp/proxy_spec.rb +116 -0
  102. data/spec/network/{tcp_spec.rb → tcp/tcp_spec.rb} +24 -1
  103. data/spec/network/telnet_spec.rb +67 -0
  104. data/spec/network/{udp_spec.rb → udp/udp_spec.rb} +24 -1
  105. data/spec/network/unix_spec.rb +183 -0
  106. data/spec/wordlist_spec.rb +74 -13
  107. metadata +129 -85
  108. data/spec/formatting/binary/helpers/hexdumps.rb +0 -16
data/ChangeLog.md CHANGED
@@ -1,19 +1,62 @@
1
- ### 0.4.1 / 2012-04-01
1
+ ### 0.5.0 / 2012-05-28
2
2
 
3
- * Added "WARNING" messages for when ronin-support cannot load `openssl` or
4
- `zlib`.
5
- * Added YARD `@see` tags to all methods defined in {Ronin::Network::Mixins}.
6
- * Use `$stdout`, `$stderr` instead of `STDOUT`, `STDERR`, respectively.
7
- * Included {Ronin::Network::DNS} into {Net} as well.
8
- * Included {Ronin::Network::TCP} into {Ronin::Network::SSL}.
9
- * Require `ronin/network/ssl` in `ronin/network`.
10
- * Require `ronin/network/extensions/ssl` in `ronin/network/extensions`.
11
- * Included {Ronin::Network::SSL} into {Ronin::Support}.
12
- * Default all `local_port` variables to `0` instead of `nil`. Workaround
13
- for JRuby bug [#6574](http://jira.codehaus.org/browse/JRUBY-6574).
14
- * Fixed a major syntax error in `ronin/network/ssl`, that caused the `ssl_*`
15
- methods to not be defined in {Ronin::Network::SSL}.
16
- * Fixed YARD `@see` tags in the {Ronin::Network} modules.
3
+ * Added {Float#pack}.
4
+ * Added {Regexp::WORD}.
5
+ * Added {Regexp::PHONE_NUMBER}.
6
+ * Added {Ronin::Binary::Template}.
7
+ * Added {Ronin::Binary::Struct}.
8
+ * Added {Ronin::Binary::Hexdump::Parser}.
9
+ * Added {Ronin::Wordlist.create}.
10
+ * Added {Ronin::Wordlist#path} and {Ronin::Wordlist#words}.
11
+ * Added {Ronin::Wordlist#save}.
12
+ * Added {Ronin::Network::Proxy}, {Ronin::Network::TCP::Proxy} and
13
+ {Ronin::Network::UDP::Proxy}.
14
+ * Added {Ronin::Network::TCP#tcp_open?}.
15
+ * Added {Ronin::Network::TCP#tcp_server_loop}.
16
+ * Added {Ronin::Network::UDP#udp_open?}.
17
+ * Added {Ronin::Network::UDP#udp_server_loop}.
18
+ * Added {Ronin::Network::Mixins::TCP#tcp_open?}.
19
+ * Added {Ronin::Network::Mixins::UDP#udp_open?}.
20
+ * Added {Ronin::Network::Mixins::UDP#udp_server_loop}.
21
+ * Added {Ronin::Network::Mixins::UDP#udp_recv}.
22
+ * Added {Ronin::Network::FTP}.
23
+ * Added {Ronin::Network::UNIX}.
24
+ * Added {Ronin::Network::Mixins::FTP}.
25
+ * Added {Ronin::Network::Mixins::UNIX}.
26
+ * Aliased {String#escape} to {String#dump}.
27
+ * Renamed {String#hex_unescape} to {String#unescape}.
28
+ * Aliased {String#hex_unescape} to {String#unescape}.
29
+ * Renamed {Ronin::Network::TCP#tcp_single_server} to
30
+ {Ronin::Network::TCP#tcp_accept}.
31
+ * Renamed {Ronin::Network::UDP#udp_single_server} to
32
+ {Ronin::Network::UDP#udp_recv}.
33
+ * Deprecated {Ronin::Network::TCP#tcp_single_server}.
34
+ * Deprecated {Ronin::Network::UDP#udp_single_server}.
35
+ * Backported Ruby 1.9 only {Base64} methods.
36
+ * Allow {Integer#pack} to accept a type from {Ronin::Binary::Template::TYPES}.
37
+ * Allow {Array#pack} to accept types from {Ronin::Binary::Template::TYPES}.
38
+ * Allow {String#unpack} to accept types from {Ronin::Binary::Template::TYPES}.
39
+ * Support nmap-style `i,j-k` globbed IP address ranges in {IPAddr.each}.
40
+ * Moved {String#unhexdump} logic into {Ronin::Binary::Hexdump::Parser}.
41
+ * Added the `:named_chars` option.
42
+ * Improved the parsing of `od` hexdumps.
43
+ * Support unhexdumping specific endianness.
44
+ * Support unhexdumping floats / doubles.
45
+ * Allow {String#mutate} to accept Symbols that map to {Ronin::Fuzzing}
46
+ generator methods.
47
+ * Use `module_function` in {Ronin::Fuzzing}, so the generator methods can be
48
+ included into other Classes/Modules.
49
+ * Require uri-query_params ~> 0.6.
50
+ * Use `$stdout` instead of calling `Kernel.puts` or `STDOUT`.
51
+ Prevents infinite recursion if another library overrides `Kernel.puts`.
52
+ * Allow {Ronin::Network::DNS} methods to yield resolved addresses.
53
+ * Inject {Ronin::Network::DNS} into {Net} for backwards compatibility.
54
+ * Allow {Ronin::Network::TCP#tcp_server} to accept a `backlog` argument.
55
+ * Default the server host to `0.0.0.0` in
56
+ {Ronin::Network::TCP#tcp_accept}.
57
+ * No longer honor the `VERBOSE` environment variable for enabling verbose output
58
+ in {Ronin::UI::Output}. Use `ruby -w` or `ruby -d` instead.
59
+ * No longer support loading `extlib` in `ronin/support/inflector`.
17
60
 
18
61
  ### 0.4.0 / 2012-02-12
19
62
 
@@ -40,23 +83,23 @@
40
83
  * Added {String#mutate}.
41
84
  * Added {Ronin::Fuzzing}.
42
85
  * Added {Ronin::Fuzzing.[]}.
43
- * Added {Ronin::Fuzzing.bad_strings}.
44
- * Added {Ronin::Fuzzing.format_strings}.
45
- * Added {Ronin::Fuzzing.bad_paths}.
46
- * Added {Ronin::Fuzzing.bit_fields}.
47
- * Added {Ronin::Fuzzing.signed_bit_fields}.
48
- * Added {Ronin::Fuzzing.uint8}.
49
- * Added {Ronin::Fuzzing.uint16}.
50
- * Added {Ronin::Fuzzing.uint32}.
51
- * Added {Ronin::Fuzzing.uint64}.
52
- * Added {Ronin::Fuzzing.int8}.
53
- * Added {Ronin::Fuzzing.int16}.
54
- * Added {Ronin::Fuzzing.int32}.
55
- * Added {Ronin::Fuzzing.int64}.
56
- * Added {Ronin::Fuzzing.sint8}.
57
- * Added {Ronin::Fuzzing.sint16}.
58
- * Added {Ronin::Fuzzing.sint32}.
59
- * Added {Ronin::Fuzzing.sint64}.
86
+ * Added `Ronin::Fuzzing.bad_strings`.
87
+ * Added `Ronin::Fuzzing.format_strings`.
88
+ * Added `Ronin::Fuzzing.bad_paths`.
89
+ * Added `Ronin::Fuzzing.bit_fields`.
90
+ * Added `Ronin::Fuzzing.signed_bit_fields`.
91
+ * Added `Ronin::Fuzzing.uint8`.
92
+ * Added `Ronin::Fuzzing.uint16`.
93
+ * Added `Ronin::Fuzzing.uint32`.
94
+ * Added `Ronin::Fuzzing.uint64`.
95
+ * Added `Ronin::Fuzzing.int8`.
96
+ * Added `Ronin::Fuzzing.int16`.
97
+ * Added `Ronin::Fuzzing.int32`.
98
+ * Added `Ronin::Fuzzing.int64`.
99
+ * Added `Ronin::Fuzzing.sint8`.
100
+ * Added `Ronin::Fuzzing.sint16`.
101
+ * Added `Ronin::Fuzzing.sint32`.
102
+ * Added `Ronin::Fuzzing.sint64`.
60
103
  * Added {Ronin::Wordlist}.
61
104
  * Added {Ronin::Network::DNS}.
62
105
  * Added {Ronin::Network::Mixins::Mixin}.
data/Gemfile CHANGED
@@ -2,29 +2,28 @@ source 'https://rubygems.org'
2
2
 
3
3
  gemspec
4
4
 
5
- platforms :jruby do
6
- gem 'jruby-openssl', '~> 0.7'
7
- end
5
+ gem 'jruby-openssl', '~> 0.7.0', :platforms => :jruby
8
6
 
9
7
  group :development do
10
- gem 'rake', '~> 0.8'
8
+ gem 'rake', '~> 0.8'
9
+ gem 'rubygems-tasks', '~> 0.1'
10
+ gem 'rspec', '~> 2.8'
11
11
 
12
- gem 'ore-tasks', '~> 0.4'
13
- gem 'rspec', '~> 2.8'
12
+ gem 'ripl', '~> 0.3'
13
+ gem 'ripl-multi_line', '~> 0.2'
14
+ gem 'ripl-auto_indent', '~> 0.1'
15
+ gem 'ripl-color_result', '~> 0.3'
14
16
 
15
- gem 'kramdown', '~> 0.12'
17
+ gem 'kramdown', '~> 0.12'
16
18
  end
17
19
 
18
20
  group :test do
19
- gem 'i18n', '~> 0.4'
20
- gem 'tzinfo', '~> 0.3'
21
-
22
- INFLECTORS = {
23
- 'activesupport' => '~> 3.0',
24
- 'dm-core' => '~> 1.0',
25
- 'extlib' => '~> 0.9'
26
- }
27
-
28
- inflector = ENV.fetch('INFLECTOR','dm-core')
29
- gem(inflector,INFLECTORS[inflector])
21
+ case ENV['INFLECTOR']
22
+ when 'activesupport'
23
+ gem 'i18n', '~> 0.4'
24
+ gem 'tzinfo', '~> 0.3.0'
25
+ gem 'activesupport', '~> 3.0.0'
26
+ else
27
+ gem 'dm-core', '~> 1.0'
28
+ end
30
29
  end
data/README.md CHANGED
@@ -1,8 +1,8 @@
1
1
  # Ronin Support
2
2
 
3
- * [Source](https://github.com/ronin-ruby/ronin-support)
4
- * [Issues](https://github.com/ronin-ruby/ronin-support/issues)
5
- * [Documentation](http://ronin-ruby.github.com/docs/ronin-support/frames)
3
+ * [Source](http://github.com/ronin-ruby/ronin-support)
4
+ * [Issues](http://github.com/ronin-ruby/ronin-support/issues)
5
+ * [Documentation](http://rubydoc.info/gems/ronin-support/frames)
6
6
  * [Mailing List](http://groups.google.com/group/ronin-ruby)
7
7
  * [irc.freenode.net #ronin](http://webchat.freenode.net/?channels=ronin&uio=Mj10cnVldd)
8
8
 
@@ -31,7 +31,6 @@ or payloads over many common Source-Code-Management (SCM) systems.
31
31
  * DNS
32
32
  * TCP
33
33
  * UDP
34
- * SSL
35
34
  * SMTP / ESMTP
36
35
  * POP3
37
36
  * Imap
@@ -58,17 +57,17 @@ please see [Everyday Ronin](http://ronin-ruby.github.com/guides/everyday_ronin.h
58
57
  ## Requirements
59
58
 
60
59
  * [Ruby](http://www.ruby-lang.org/) >= 1.8.7
61
- * [chars](https://github.com/postmodern/chars#readme)
60
+ * [chars](http://github.com/postmodern/chars#readme)
62
61
  ~> 0.2
63
- * [hexdump](https://github.com/postmodern/hexdump#readme)
62
+ * [hexdump](http://github.com/postmodern/hexdump#readme)
64
63
  ~> 0.1
65
- * [combinatorics](https://github.com/postmodern/combinatorics#readme)
64
+ * [combinatorics](http://github.com/postmodern/combinatorics#readme)
66
65
  ~> 0.4
67
- * [uri-query_params](https://github.com/postmodern/uri-query_params#readme)
66
+ * [uri-query_params](http://github.com/postmodern/uri-query_params#readme)
68
67
  ~> 0.6
69
- * [data_paths](https://github.com/postmodern/data_paths#readme)
68
+ * [data_paths](http://github.com/postmodern/data_paths#readme)
70
69
  ~> 0.3
71
- * [parameters](https://github.com/postmodern/parameters#readme)
70
+ * [parameters](http://github.com/postmodern/parameters#readme)
72
71
  ~> 0.4
73
72
 
74
73
  ## Install
data/Rakefile CHANGED
@@ -18,8 +18,16 @@ end
18
18
 
19
19
  require 'rake'
20
20
 
21
- require 'ore/tasks'
22
- Ore::Tasks.new
21
+ require 'rubygems/tasks'
22
+ Gem::Tasks.new(:sign => {:checksum => true, :pgp => true}) do |tasks|
23
+ tasks.scm.tag.format = 'v%s'
24
+ tasks.console.command = 'ripl'
25
+ tasks.console.options = %w[
26
+ -rripl/multi_line
27
+ -rripl/auto_indent
28
+ -rripl/color_result
29
+ ]
30
+ end
23
31
 
24
32
  require 'rspec/core/rake_task'
25
33
  RSpec::Core::RakeTask.new
data/gemspec.yml CHANGED
@@ -22,5 +22,5 @@ dependencies:
22
22
 
23
23
  development_dependencies:
24
24
  bundler: ~> 1.0
25
- yard: ~> 0.7
25
+ yard: ~> 0.8
26
26
  yard-parameters: ~> 0.1
@@ -0,0 +1,21 @@
1
+ #
2
+ # Copyright (c) 2006-2012 Hal Brodigan (postmodern.mod3 at gmail.com)
3
+ #
4
+ # This file is part of Ronin Support.
5
+ #
6
+ # Ronin Support is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU Lesser General Public License as published
8
+ # by the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # Ronin Support is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU Lesser General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU Lesser General Public License
17
+ # along with Ronin Support. If not, see <http://www.gnu.org/licenses/>.
18
+ #
19
+
20
+ require 'ronin/binary/template'
21
+ require 'ronin/binary/struct'
@@ -0,0 +1,20 @@
1
+ #
2
+ # Copyright (c) 2006-2012 Hal Brodigan (postmodern.mod3 at gmail.com)
3
+ #
4
+ # This file is part of Ronin Support.
5
+ #
6
+ # Ronin Support is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU Lesser General Public License as published
8
+ # by the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # Ronin Support is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU Lesser General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU Lesser General Public License
17
+ # along with Ronin Support. If not, see <http://www.gnu.org/licenses/>.
18
+ #
19
+
20
+ require 'ronin/binary/hexdump/parser'
@@ -0,0 +1,411 @@
1
+ #
2
+ # Copyright (c) 2006-2012 Hal Brodigan (postmodern.mod3 at gmail.com)
3
+ #
4
+ # This file is part of Ronin Support.
5
+ #
6
+ # Ronin Support is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU Lesser General Public License as published
8
+ # by the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # Ronin Support is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU Lesser General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU Lesser General Public License
17
+ # along with Ronin Support. If not, see <http://www.gnu.org/licenses/>.
18
+ #
19
+
20
+ require 'chars'
21
+
22
+ module Ronin
23
+ module Binary
24
+ module Hexdump
25
+ #
26
+ # @since 0.5.0
27
+ #
28
+ # @api semipublic
29
+ #
30
+ class Parser
31
+
32
+ # Bases for various encodings
33
+ BASES = {
34
+ :binary => 2,
35
+ :octal => 8,
36
+ :octal_bytes => 8,
37
+ :octal_shorts => 8,
38
+ :octal_ints => 8,
39
+ :octal_quads => 8,
40
+ :decimal => 10,
41
+ :decimal_bytes => 10,
42
+ :decimal_shorts => 10,
43
+ :decimal_ints => 10,
44
+ :decimal_quads => 10,
45
+ :hex => 16,
46
+ :hex_bytes => 16,
47
+ :hex_shorts => 16,
48
+ :hex_ints => 16,
49
+ :hex_quads => 16,
50
+ :named_chars => 16,
51
+ :floats => 10,
52
+ :doubles => 10
53
+ }
54
+
55
+ # Word-sizes for various encodings
56
+ WORD_SIZES = {
57
+ :binary => 1,
58
+ :octal_bytes => 1,
59
+ :decimal_bytes => 1,
60
+ :hex_bytes => 1,
61
+ :hex_chars => 1,
62
+ :named_chars => 1,
63
+ :octal_shorts => 2,
64
+ :decimal_shorts => 2,
65
+ :hex_shorts => 2,
66
+ :octal_ints => 4,
67
+ :decimal_ints => 4,
68
+ :hex_ints => 4,
69
+ :octal_quads => 8,
70
+ :decimal_quads => 8,
71
+ :hex_quads => 8,
72
+ :floats => 4,
73
+ :doubles => 8
74
+ }
75
+
76
+ # The format to parse (`:hexdump` / `:od`)
77
+ attr_reader :format
78
+
79
+ # The encoding of the hexdump data
80
+ attr_reader :encoding
81
+
82
+ # The type of data to parse (`:integer` / `:float`)
83
+ attr_reader :type
84
+
85
+ # The endianness of data to parse (`:little`, `:big`, `:network`)
86
+ attr_reader :endian
87
+
88
+ # The size of words to parse
89
+ attr_reader :word_size
90
+
91
+ # The base of all addresses to parse
92
+ attr_reader :address_base
93
+
94
+ # The base of all words to parse
95
+ attr_reader :base
96
+
97
+ #
98
+ # Initializes the hexdump parser.
99
+ #
100
+ # @param [Hash] options
101
+ # Additional options.
102
+ #
103
+ # @option options [Symbol] :format
104
+ # The expected format of the hexdump. Must be either `:od` or
105
+ # `:hexdump`.
106
+ #
107
+ # @option options [Symbol] :encoding
108
+ # Denotes the encoding used for the bytes within the hexdump.
109
+ # Must be one of the following:
110
+ #
111
+ # * `:binary`
112
+ # * `:octal`
113
+ # * `:octal_bytes`
114
+ # * `:octal_shorts`
115
+ # * `:octal_ints`
116
+ # * `:octal_quads` (Ruby 1.9 only)
117
+ # * `:decimal`
118
+ # * `:decimal_bytes`
119
+ # * `:decimal_shorts`
120
+ # * `:decimal_ints`
121
+ # * `:decimal_quads` (Ruby 1.9 only)
122
+ # * `:hex`
123
+ # * `:hex_chars`
124
+ # * `:hex_bytes`
125
+ # * `:hex_shorts`
126
+ # * `:hex_ints`
127
+ # * `:hex_quads` (Ruby 1.9 only)
128
+ # * `:named_chars`
129
+ # * `:floats`
130
+ # * `:doubles`
131
+ #
132
+ # @option options [:little, :big, :network] :endian (:little)
133
+ # The endianness of the words.
134
+ #
135
+ def initialize(options={})
136
+ @format = options[:format]
137
+ @encoding = options[:encoding]
138
+
139
+ @type = case @encoding
140
+ when :floats, :doubles
141
+ :float
142
+ else
143
+ :integer
144
+ end
145
+ @endian = options.fetch(:endian,:little)
146
+
147
+ case @format
148
+ when :od
149
+ @address_base = 8
150
+ @base = 8
151
+ @word_size = 2
152
+ when :hexdump
153
+ @address_base = 16
154
+ @base = 16
155
+ @word_size = 2
156
+ else
157
+ @address_base = 16
158
+ @base = 16
159
+ @word_size = 1
160
+ end
161
+
162
+ if @encoding
163
+ @base = BASES.fetch(options[:encoding])
164
+ @word_size = WORD_SIZES.fetch(options[:encoding])
165
+ end
166
+
167
+ case @encoding
168
+ when :hex_chars
169
+ @chars = CHARS.merge(ESCAPED_CHARS)
170
+ when :named_chars
171
+ @chars = CHARS.merge(NAMED_CHARS)
172
+ end
173
+ end
174
+
175
+ #
176
+ # Parses a hexdump.
177
+ #
178
+ # @param [#each_line] hexdump
179
+ # The hexdump output.
180
+ #
181
+ # @return [String]
182
+ # The raw-data from the hexdump.
183
+ #
184
+ def parse(hexdump)
185
+ current_addr = last_addr = first_addr = nil
186
+ repeated = false
187
+
188
+ segment = ''
189
+ buffer = ''
190
+
191
+ hexdump.each_line do |line|
192
+ if @format == :hexdump
193
+ line = line.gsub(/\s+\|.+\|\s*$/,'')
194
+ end
195
+
196
+ words = line.split
197
+
198
+ if words.first == '*'
199
+ repeated = true
200
+ elsif words.length > 0
201
+ current_addr = parse_address(words.shift)
202
+ first_addr ||= current_addr
203
+
204
+ if repeated
205
+ (((current_addr - last_addr) / segment.length) - 1).times do
206
+ buffer << segment
207
+ end
208
+
209
+ repeated = false
210
+ end
211
+
212
+ segment = pack(words.map { |word| parse_word(word) })
213
+
214
+ buffer << segment
215
+ last_addr = current_addr
216
+ end
217
+ end
218
+
219
+ return buffer[0,last_addr - first_addr]
220
+ end
221
+
222
+ protected
223
+
224
+ # Visible characters
225
+ CHARS = Hash[Chars::VISIBLE.chars.sort.zip(Chars::VISIBLE.bytes.sort)]
226
+
227
+ # Escaped characters
228
+ ESCAPED_CHARS = {
229
+ '\0' => 0x00,
230
+ '\a' => 0x07,
231
+ '\b' => 0x08,
232
+ '\t' => 0x09,
233
+ '\n' => 0x0a,
234
+ '\v' => 0x0b,
235
+ '\f' => 0x0c,
236
+ '\r' => 0x0d
237
+ }
238
+
239
+ # od named characters
240
+ NAMED_CHARS = {
241
+ 'nul' => 0x00,
242
+ 'soh' => 0x01,
243
+ 'stx' => 0x02,
244
+ 'etx' => 0x03,
245
+ 'eot' => 0x04,
246
+ 'enq' => 0x05,
247
+ 'ack' => 0x06,
248
+ 'bel' => 0x07,
249
+ 'bs' => 0x08,
250
+ 'ht' => 0x09,
251
+ 'lf' => 0x0a,
252
+ 'nl' => 0x0a,
253
+ 'vt' => 0x0b,
254
+ 'ff' => 0x0c,
255
+ 'cr' => 0x0d,
256
+ 'so' => 0x0e,
257
+ 'si' => 0x0f,
258
+ 'dle' => 0x10,
259
+ 'dc1' => 0x11,
260
+ 'dc2' => 0x12,
261
+ 'dc3' => 0x13,
262
+ 'dc4' => 0x14,
263
+ 'nak' => 0x15,
264
+ 'syn' => 0x16,
265
+ 'etb' => 0x17,
266
+ 'can' => 0x18,
267
+ 'em' => 0x19,
268
+ 'sub' => 0x1a,
269
+ 'esc' => 0x1b,
270
+ 'fs' => 0x1c,
271
+ 'gs' => 0x1d,
272
+ 'rs' => 0x1e,
273
+ 'us' => 0x1f,
274
+ 'sp' => 0x20,
275
+ 'del' => 0x7f
276
+ }
277
+
278
+ # `Array#pack` codes for various types/endianness/word-sizes
279
+ FORMATS = {
280
+ :integer => {
281
+ :little => {
282
+ 1 => 'C',
283
+ 2 => (RUBY_VERSION > '1.9.' ? 'S<' : 'v'),
284
+ 4 => (RUBY_VERSION > '1.9.' ? 'L<' : 'V'),
285
+ 8 => 'Q<' # Ruby 1.9 only
286
+ },
287
+
288
+ :big => {
289
+ 1 => 'C',
290
+ 2 => (RUBY_VERSION > '1.9.' ? 'S>' : 'n'),
291
+ 4 => (RUBY_VERSION > '1.9.' ? 'L>' : 'N'),
292
+ 8 => 'Q>' # Ruby 1.9 only
293
+ }
294
+ },
295
+
296
+ :float => {
297
+ :little => {
298
+ 4 => 'e',
299
+ 8 => 'E'
300
+ },
301
+
302
+ :big => {
303
+ 4 => 'g',
304
+ 8 => 'G'
305
+ }
306
+ }
307
+ }
308
+
309
+ # alias network endianness to big endian
310
+ FORMATS[:integer][:network] = FORMATS[:integer][:big]
311
+ FORMATS[:float][:network] = FORMATS[:float][:big]
312
+
313
+ #
314
+ # Parses an address.
315
+ #
316
+ # @param [String] address
317
+ # The text of the address.
318
+ #
319
+ # @return [Integer]
320
+ # The parsed address.
321
+ #
322
+ # @api private
323
+ #
324
+ def parse_address(address)
325
+ address.to_i(@address_base)
326
+ end
327
+
328
+ #
329
+ # Parses a character or hex-byte.
330
+ #
331
+ # @param [String] char
332
+ # The character to parse.
333
+ #
334
+ # @return [Integer]
335
+ # The parsed byte.
336
+ #
337
+ def parse_char(char)
338
+ @chars.fetch(char) do |hex_byte|
339
+ hex_byte.to_i(16)
340
+ end
341
+ end
342
+
343
+ #
344
+ # Parses an Integer.
345
+ #
346
+ # @param [String] int
347
+ # The text of the Integer.
348
+ #
349
+ # @return [Integer]
350
+ # The parsed word.
351
+ #
352
+ # @api private
353
+ #
354
+ def parse_int(int)
355
+ if @chars
356
+ parse_char(int)
357
+ else
358
+ int.to_i(@base)
359
+ end
360
+ end
361
+
362
+ #
363
+ # Parses a float.
364
+ #
365
+ # @param [String] float
366
+ # The text of the float.
367
+ #
368
+ # @return [Float]
369
+ # The parsed float.
370
+ #
371
+ def parse_float(float)
372
+ float.to_f
373
+ end
374
+
375
+ #
376
+ # Parses a word within a segment.
377
+ #
378
+ # @param [String] word
379
+ # The word to parse.
380
+ #
381
+ # @return [Integer, Float]
382
+ # The value of the word.
383
+ #
384
+ def parse_word(word)
385
+ case @type
386
+ when :integer
387
+ parse_int(word)
388
+ when :float
389
+ parse_float(word)
390
+ end
391
+ end
392
+
393
+ #
394
+ # Packs a segment back into bytes.
395
+ #
396
+ # @param [Array<Integer, Float>] values
397
+ # A segment of words.
398
+ #
399
+ # @return [String]
400
+ # The packed segment.
401
+ #
402
+ # @api private
403
+ #
404
+ def pack(values)
405
+ values.pack(FORMATS[@type][@endian][@word_size] * values.length)
406
+ end
407
+
408
+ end
409
+ end
410
+ end
411
+ end