watobo 0.9.8.677

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (260) hide show
  1. data/bin/watobo_gui.rb +39 -0
  2. data/certificates/cert.pem +19 -0
  3. data/certificates/privkey.pem +15 -0
  4. data/certificates/watobo_dh.key +5 -0
  5. data/config/datastore.yml +5 -0
  6. data/config/forwarding_proxy.yml +12 -0
  7. data/config/general.yml +4 -0
  8. data/config/gui.yml +23 -0
  9. data/config/interceptor.yml +16 -0
  10. data/config/scan_policy.yml +13 -0
  11. data/config/scanner.yml +34 -0
  12. data/icons/Add.ico +0 -0
  13. data/icons/Add_24x24.ico +0 -0
  14. data/icons/Bandwidth.ico +0 -0
  15. data/icons/Bandwidth_24x24.ico +0 -0
  16. data/icons/Mr. Bomb.ico +0 -0
  17. data/icons/Mr. Bomb_16x16.ico +0 -0
  18. data/icons/Mr. Bomb_24x24.ico +0 -0
  19. data/icons/Orange Ball.ico +0 -0
  20. data/icons/Orange Ball_16x16.ico +0 -0
  21. data/icons/Orange Ball_24x24.ico +0 -0
  22. data/icons/Pause.ico +0 -0
  23. data/icons/Play.ico +0 -0
  24. data/icons/Play_24x24.ico +0 -0
  25. data/icons/Red Ball.ico +0 -0
  26. data/icons/Red Ball_16x16.ico +0 -0
  27. data/icons/Red Ball_24x24.ico +0 -0
  28. data/icons/Run.ico +0 -0
  29. data/icons/Stop.ico +0 -0
  30. data/icons/Stop_24x24.ico +0 -0
  31. data/icons/Terminal.ico +0 -0
  32. data/icons/Transfer.ico +0 -0
  33. data/icons/Transfer_16x16.ico +0 -0
  34. data/icons/User.ico +0 -0
  35. data/icons/User_16x16.ico +0 -0
  36. data/icons/User_24x24.ico +0 -0
  37. data/icons/Web Browser.ico +0 -0
  38. data/icons/Web Browser_16x16.ico +0 -0
  39. data/icons/Write Document.ico +0 -0
  40. data/icons/Yellow Ball.ico +0 -0
  41. data/icons/Yellow Ball_16x16.ico +0 -0
  42. data/icons/Yellow Ball_24x24.ico +0 -0
  43. data/icons/advanced.ico +0 -0
  44. data/icons/advanced_16x16.ico +0 -0
  45. data/icons/advanced_24x24.ico +0 -0
  46. data/icons/applications.ico +0 -0
  47. data/icons/applications_16x16.ico +0 -0
  48. data/icons/applications_24x24.ico +0 -0
  49. data/icons/browser_16x16.ico +0 -0
  50. data/icons/browser_24x24.ico +0 -0
  51. data/icons/burn.ico +0 -0
  52. data/icons/burn_16x16.ico +0 -0
  53. data/icons/burn_24x24.ico +0 -0
  54. data/icons/calculator.ico +0 -0
  55. data/icons/calculator_24x24.ico +0 -0
  56. data/icons/cb_checked.ico +0 -0
  57. data/icons/cb_checked_orange.ico +0 -0
  58. data/icons/cb_unchecked.ico +0 -0
  59. data/icons/coin_24x24.ico +0 -0
  60. data/icons/conversation.ico +0 -0
  61. data/icons/conversation_24x24.ico +0 -0
  62. data/icons/engine.ico +0 -0
  63. data/icons/filter.ico +0 -0
  64. data/icons/folder.ico +0 -0
  65. data/icons/folder_16x16.ico +0 -0
  66. data/icons/fuzzer_16x16.ico +0 -0
  67. data/icons/fuzzer_24x24.ico +0 -0
  68. data/icons/go-down_16x16.png +0 -0
  69. data/icons/go-up_16x16.png +0 -0
  70. data/icons/help.ico +0 -0
  71. data/icons/help_16x16.ico +0 -0
  72. data/icons/help_24x24.ico +0 -0
  73. data/icons/iChat.ico +0 -0
  74. data/icons/iChat_16x16.ico +0 -0
  75. data/icons/iChat_24x24.ico +0 -0
  76. data/icons/icons.txt +3 -0
  77. data/icons/info.ico +0 -0
  78. data/icons/info_16x16.ico +0 -0
  79. data/icons/info_24x24.ico +0 -0
  80. data/icons/interceptor_24x24.ico +0 -0
  81. data/icons/lock.ico +0 -0
  82. data/icons/lock_12x12.ico +0 -0
  83. data/icons/lock_16x16.ico +0 -0
  84. data/icons/monitor.ico +0 -0
  85. data/icons/plugin.ico +0 -0
  86. data/icons/plugin_24x24.ico +0 -0
  87. data/icons/scan_16x16.png +0 -0
  88. data/icons/send.ico +0 -0
  89. data/icons/server.ico +0 -0
  90. data/icons/server_16x16.ico +0 -0
  91. data/icons/siberas_logo_x24.gif +0 -0
  92. data/icons/tag_blue_32x32.ico +0 -0
  93. data/icons/watobo-48x48.png +0 -0
  94. data/icons/watobo-logo.png +0 -0
  95. data/icons/watobo.ico +0 -0
  96. data/lib/watobo/adapters/data_store.rb +38 -0
  97. data/lib/watobo/adapters/file/file_store.rb +211 -0
  98. data/lib/watobo/adapters/session_store.rb +27 -0
  99. data/lib/watobo/adapters.rb +26 -0
  100. data/lib/watobo/config.rb +143 -0
  101. data/lib/watobo/constants.rb +92 -0
  102. data/lib/watobo/core/active_check.rb +404 -0
  103. data/lib/watobo/core/cookie.rb +69 -0
  104. data/lib/watobo/core/fuzz_gen.rb +160 -0
  105. data/lib/watobo/core/http_socket.rb +142 -0
  106. data/lib/watobo/core/interceptor.rb +729 -0
  107. data/lib/watobo/core/passive_check.rb +141 -0
  108. data/lib/watobo/core/project.rb +1058 -0
  109. data/lib/watobo/core/scanner.rb +396 -0
  110. data/lib/watobo/core/session.rb +1320 -0
  111. data/lib/watobo/core/simple_ca.rb +393 -0
  112. data/lib/watobo/core.rb +34 -0
  113. data/lib/watobo/defaults.rb +40 -0
  114. data/lib/watobo/external/diff/lcs/array.rb +42 -0
  115. data/lib/watobo/external/diff/lcs/block.rb +72 -0
  116. data/lib/watobo/external/diff/lcs/callbacks.rb +343 -0
  117. data/lib/watobo/external/diff/lcs/change.rb +190 -0
  118. data/lib/watobo/external/diff/lcs/hunk.rb +279 -0
  119. data/lib/watobo/external/diff/lcs/ldiff.rb +247 -0
  120. data/lib/watobo/external/diff/lcs/string.rb +40 -0
  121. data/lib/watobo/external/diff/lcs.rb +1124 -0
  122. data/lib/watobo/external/ntlm/ntlm.rb +797 -0
  123. data/lib/watobo/externals.rb +28 -0
  124. data/lib/watobo/framework/create_project.rb +55 -0
  125. data/lib/watobo/framework/init.rb +149 -0
  126. data/lib/watobo/framework/init_modules.rb +116 -0
  127. data/lib/watobo/framework/license_text.rb +50 -0
  128. data/lib/watobo/framework.rb +26 -0
  129. data/lib/watobo/gui/about_watobo.rb +68 -0
  130. data/lib/watobo/gui/browser_preview.rb +460 -0
  131. data/lib/watobo/gui/certificate_dialog.rb +132 -0
  132. data/lib/watobo/gui/chat_diff.rb +415 -0
  133. data/lib/watobo/gui/chatviewer_frame.rb +427 -0
  134. data/lib/watobo/gui/checkboxtree.rb +221 -0
  135. data/lib/watobo/gui/checks_policy_frame.rb +123 -0
  136. data/lib/watobo/gui/client_cert_dialog.rb +227 -0
  137. data/lib/watobo/gui/confirm_scan_dialog.rb +67 -0
  138. data/lib/watobo/gui/conversation_table.rb +386 -0
  139. data/lib/watobo/gui/conversation_table_ctrl.rb +175 -0
  140. data/lib/watobo/gui/csrf_token_dialog.rb +446 -0
  141. data/lib/watobo/gui/dashboard.rb +341 -0
  142. data/lib/watobo/gui/define_scope_frame.rb +380 -0
  143. data/lib/watobo/gui/edit_comment.rb +70 -0
  144. data/lib/watobo/gui/edit_scope_dialog.rb +69 -0
  145. data/lib/watobo/gui/finding_info.rb +212 -0
  146. data/lib/watobo/gui/findings_tree.rb +459 -0
  147. data/lib/watobo/gui/full_scan_dialog.rb +269 -0
  148. data/lib/watobo/gui/fuzzer_gui.rb +1522 -0
  149. data/lib/watobo/gui/hex_viewer.rb +106 -0
  150. data/lib/watobo/gui/interceptor_gui.rb +994 -0
  151. data/lib/watobo/gui/interceptor_settings_dialog.rb +201 -0
  152. data/lib/watobo/gui/log_viewer.rb +97 -0
  153. data/lib/watobo/gui/login_wizzard.rb +301 -0
  154. data/lib/watobo/gui/main_window.rb +1815 -0
  155. data/lib/watobo/gui/manual_request_editor.rb +1105 -0
  156. data/lib/watobo/gui/master_pw_dialog.rb +142 -0
  157. data/lib/watobo/gui/password_policy_dialog.rb +98 -0
  158. data/lib/watobo/gui/plugin/base.rb +82 -0
  159. data/lib/watobo/gui/plugin_board.rb +95 -0
  160. data/lib/watobo/gui/preferences_dialog.rb +116 -0
  161. data/lib/watobo/gui/progress_window.rb +102 -0
  162. data/lib/watobo/gui/project_wizzard.rb +369 -0
  163. data/lib/watobo/gui/proxy_dialog.rb +550 -0
  164. data/lib/watobo/gui/quick_scan_dialog.rb +242 -0
  165. data/lib/watobo/gui/request_editor.rb +480 -0
  166. data/lib/watobo/gui/save_chat_dialog.rb +158 -0
  167. data/lib/watobo/gui/scanner_settings_dialog.rb +360 -0
  168. data/lib/watobo/gui/select_chat_dialog.rb +169 -0
  169. data/lib/watobo/gui/session_management_dialog.rb +688 -0
  170. data/lib/watobo/gui/sites_tree.rb +347 -0
  171. data/lib/watobo/gui/status_bar.rb +88 -0
  172. data/lib/watobo/gui/table_editor.rb +445 -0
  173. data/lib/watobo/gui/tagless_viewer.rb +62 -0
  174. data/lib/watobo/gui/templates/plugin.rb +80 -0
  175. data/lib/watobo/gui/templates/plugin2.rb +103 -0
  176. data/lib/watobo/gui/text_viewer.rb +247 -0
  177. data/lib/watobo/gui/transcoder_window.rb +215 -0
  178. data/lib/watobo/gui/utils/gui_utils.rb +129 -0
  179. data/lib/watobo/gui/utils/init_icons.rb +106 -0
  180. data/lib/watobo/gui/utils/load_icons.rb +54 -0
  181. data/lib/watobo/gui/utils/load_plugins.rb +94 -0
  182. data/lib/watobo/gui/utils/master_password.rb +90 -0
  183. data/lib/watobo/gui/utils/save_default_settings.rb +99 -0
  184. data/lib/watobo/gui/utils/save_project_settings.rb +21 -0
  185. data/lib/watobo/gui/utils/save_proxy_settings.rb +45 -0
  186. data/lib/watobo/gui/utils/save_session_settings.rb +21 -0
  187. data/lib/watobo/gui/utils/session_history.rb +134 -0
  188. data/lib/watobo/gui/workspace_dialog.rb +89 -0
  189. data/lib/watobo/gui/www_auth_dialog.rb +348 -0
  190. data/lib/watobo/gui/xml_viewer_frame.rb +114 -0
  191. data/lib/watobo/gui.rb +139 -0
  192. data/lib/watobo/mixins/httpparser.rb +664 -0
  193. data/lib/watobo/mixins/request_parser.rb +210 -0
  194. data/lib/watobo/mixins/shapers.rb +345 -0
  195. data/lib/watobo/mixins/transcoders.rb +88 -0
  196. data/lib/watobo/mixins.rb +32 -0
  197. data/lib/watobo/utils/check_regex.rb +36 -0
  198. data/lib/watobo/utils/copy_object.rb +29 -0
  199. data/lib/watobo/utils/crypto.rb +74 -0
  200. data/lib/watobo/utils/expand_range.rb +45 -0
  201. data/lib/watobo/utils/file_management.rb +73 -0
  202. data/lib/watobo/utils/load_chat.rb +219 -0
  203. data/lib/watobo/utils/load_icon.rb +47 -0
  204. data/lib/watobo/utils/print_debug.rb +34 -0
  205. data/lib/watobo/utils/response_hash.rb +143 -0
  206. data/lib/watobo/utils/secure_eval.rb +57 -0
  207. data/lib/watobo/utils/text2request.rb +96 -0
  208. data/lib/watobo/utils.rb +32 -0
  209. data/lib/watobo.rb +76 -0
  210. data/modules/active/Apache/mod_status.rb +123 -0
  211. data/modules/active/Flash/crossdomain.rb +102 -0
  212. data/modules/active/directories/dirwalker.rb +89 -0
  213. data/modules/active/discovery/fileextensions.rb +151 -0
  214. data/modules/active/discovery/http_methods.rb +135 -0
  215. data/modules/active/domino/domino_db.lst +164 -0
  216. data/modules/active/domino/domino_db.rb +128 -0
  217. data/modules/active/fileinclusion/lfi_simple.rb +134 -0
  218. data/modules/active/jboss/jboss_basic.rb +119 -0
  219. data/modules/active/sap/business_objects.rb +73 -0
  220. data/modules/active/sap/its_commands.rb +101 -0
  221. data/modules/active/sap/its_service_parameter.rb +105 -0
  222. data/modules/active/sap/its_services.rb +103 -0
  223. data/modules/active/sap/its_xss.rb +98 -0
  224. data/modules/active/sqlinjection/sql_boolean.rb +262 -0
  225. data/modules/active/sqlinjection/sqli_simple.rb +205 -0
  226. data/modules/active/xss/xss_simple.rb +179 -0
  227. data/modules/passive/cookie_options.rb +97 -0
  228. data/modules/passive/cookie_xss.rb +85 -0
  229. data/modules/passive/detect_code.rb +89 -0
  230. data/modules/passive/detect_fileupload.rb +80 -0
  231. data/modules/passive/detect_infrastructure.rb +98 -0
  232. data/modules/passive/detect_one_time_tokens.rb +86 -0
  233. data/modules/passive/dirindexing.rb +81 -0
  234. data/modules/passive/disclosure_emails.rb +82 -0
  235. data/modules/passive/disclosure_ipaddr.rb +87 -0
  236. data/modules/passive/filename_as_parameter.rb +85 -0
  237. data/modules/passive/form_spotter.rb +75 -0
  238. data/modules/passive/hotspots.rb +86 -0
  239. data/modules/passive/in_script_parameter.rb +92 -0
  240. data/modules/passive/multiple_server_headers.rb +98 -0
  241. data/modules/passive/possible_login.rb +134 -0
  242. data/modules/passive/redirect_url.rb +88 -0
  243. data/modules/passive/redirectionz.rb +96 -0
  244. data/modules/passive/xss_dom.rb +91 -0
  245. data/plugins/catalog/catalog.ico +0 -0
  246. data/plugins/catalog/catalog.rb +726 -0
  247. data/plugins/catalog/db_tests +6483 -0
  248. data/plugins/catalog/db_variables +29 -0
  249. data/plugins/filefinder/dbs/hbci.db +12 -0
  250. data/plugins/filefinder/filefinder.rb +602 -0
  251. data/plugins/sslchecker/cli/sslchecker_cli.rb +21 -0
  252. data/plugins/sslchecker/gui/cipher_table.rb +260 -0
  253. data/plugins/sslchecker/gui/gui.rb +245 -0
  254. data/plugins/sslchecker/gui/sslchecker.rb +26 -0
  255. data/plugins/sslchecker/icons/green_16x16.ico +0 -0
  256. data/plugins/sslchecker/icons/grey_16x16.ico +0 -0
  257. data/plugins/sslchecker/icons/red_16x16.ico +0 -0
  258. data/plugins/sslchecker/icons/sslchecker.ico +0 -0
  259. data/plugins/sslchecker/lib/check.rb +117 -0
  260. metadata +317 -0
@@ -0,0 +1,1522 @@
1
+ # .
2
+ # fuzzer_gui.rb
3
+ #
4
+ # Copyright 2012 by siberas, http://www.siberas.de
5
+ #
6
+ # This file is part of WATOBO (Web Application Tool Box)
7
+ # http://watobo.sourceforge.com
8
+ #
9
+ # WATOBO is free software; you can redistribute it and/or modify
10
+ # it under the terms of the GNU General Public License as published by
11
+ # the Free Software Foundation version 2 of the License.
12
+ #
13
+ # WATOBO is distributed in the hope that it will be useful,
14
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
+ # GNU General Public License for more details.
17
+ #
18
+ # You should have received a copy of the GNU General Public License
19
+ # along with WATOBO; if not, write to the Free Software
20
+ # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21
+ # .
22
+ require 'watobo/gui/request_editor.rb'
23
+ module Watobo
24
+
25
+
26
+ module Gui
27
+
28
+ class FuzzerCheck < Watobo::ActiveCheck
29
+
30
+ def initialize(project, fuzzer_list, filter_list, requestEditor, prefs={} )
31
+ super(project.object_id, prefs)
32
+ @fuzzer_list = fuzzer_list
33
+ @requestEditor = requestEditor
34
+ @filter_list = filter_list
35
+ @prefs = prefs
36
+ end
37
+
38
+ def fuzzels(fuzzers, index=0, result=nil)
39
+ begin
40
+ unless fuzzers[index].nil?
41
+ fuzzers[index].run(result) do |fuzz|
42
+ if index < fuzzers.length - 1
43
+ fuzzels(fuzzers, index+1, fuzz) do |sr|
44
+ yield sr
45
+ end
46
+ else
47
+ yield fuzz
48
+ end
49
+ end
50
+ end
51
+ rescue => bang
52
+ puts bang
53
+ puts bang.backtrace if $DEBUG
54
+ end
55
+ end
56
+
57
+
58
+
59
+ def reset()
60
+
61
+ end
62
+
63
+ def generateChecks(chat)
64
+ unless @fuzzer_list.empty?
65
+ fuzzels(@fuzzer_list) do |fuzzle|
66
+ checker = proc{
67
+ test_fuzzle = Hash.new
68
+ test_fuzzle.update fuzzle
69
+
70
+ fuzz_request = @requestEditor.parseRequest(test_fuzzle)
71
+ fuzz_request.extend Watobo::Mixin::Shaper::Web10
72
+ fuzz_request.extend Watobo::Mixin::Parser::Web10
73
+ fuzz_request.extend Watobo::Mixin::Parser::Url
74
+
75
+ test_request, test_response = doRequest(fuzz_request, @prefs)
76
+
77
+ notify(:fuzzer_match, test_fuzzle, test_request, test_response, test_response.join) if @filter_list.empty?
78
+
79
+ @filter_list.each do |f|
80
+ matches = f.func.call(test_response) if f.func.respond_to? :call
81
+ matches.each do |match|
82
+ notify(:fuzzer_match, test_fuzzle, test_request, test_response, match)
83
+ end
84
+ end
85
+
86
+ [ test_request, test_response ]
87
+ }
88
+ yield checker
89
+ end
90
+ end
91
+ end
92
+ end
93
+
94
+ class FuzzerTag
95
+
96
+ attr :name
97
+ attr :generators
98
+ attr :collector
99
+ attr :trigger
100
+
101
+ def is_tag?()
102
+ true
103
+ end
104
+
105
+ def addGenerator(gen)
106
+ @generators.push gen
107
+ end
108
+
109
+ def deleteGenerator(gen)
110
+ @generators.delete(gen)
111
+ end
112
+
113
+ def run(result)
114
+ @generators.each do |g|
115
+ g.run(result) { |x| yield x }
116
+ end
117
+ end
118
+
119
+ def initialize(name)
120
+ @name = name
121
+ @generators = []
122
+ @collector = nil
123
+ @trigger = nil
124
+ end
125
+ end
126
+
127
+
128
+
129
+ class CreateFuzzerDlg < FXDialogBox
130
+
131
+ def tag
132
+ @tag_dt.value
133
+ end
134
+
135
+ def initialize(owner)
136
+ super(owner, "Create New Tag", DECOR_TITLE|DECOR_BORDER)
137
+ main = FXVerticalFrame.new(self, :opts => LAYOUT_FILL_X|LAYOUT_FILL_Y)
138
+ frame = FXHorizontalFrame.new(main, :opts => LAYOUT_FILL_X)
139
+ FXLabel.new(frame, "Enter Label For Tag:")
140
+ input = FXHorizontalFrame.new(main, :opts => LAYOUT_FILL_X)
141
+ @tag_dt = FXDataTarget.new('')
142
+ @tag_text = FXTextField.new(input, 1, :target => @tag_dt, :selector => FXDataTarget::ID_VALUE,
143
+ :opts => TEXTFIELD_NORMAL|LAYOUT_FILL_X|LAYOUT_FILL_COLUMN)
144
+
145
+ FXLabel.new(main, "Note:\nTo define the position in the request enclose the tag name\nbetween '%%', eg. '%%tag%%'.\nIt will turn green if the given tag name is correct.\n" +
146
+ "Don't forget to specify a generator!").justify = JUSTIFY_LEFT
147
+
148
+ @tag_text.setFocus()
149
+ @tag_text.setDefault()
150
+
151
+ @tag_dt.connect(SEL_COMMAND) {
152
+ @accept_btn.setFocus()
153
+ @accept_btn.setDefault()
154
+ }
155
+ buttons = FXHorizontalFrame.new(main, :opts => LAYOUT_SIDE_BOTTOM|LAYOUT_FILL_X|PACK_UNIFORM_WIDTH,
156
+ :padLeft => 40, :padRight => 40, :padTop => 20, :padBottom => 20)
157
+ # Accept
158
+ @accept_btn = FXButton.new(buttons, "&Accept", nil, self, ID_ACCEPT, FRAME_RAISED|FRAME_THICK|LAYOUT_RIGHT|LAYOUT_CENTER_Y)
159
+
160
+ # Cancel
161
+ FXButton.new(buttons, "&Cancel", nil, self, ID_CANCEL, FRAME_RAISED|FRAME_THICK|LAYOUT_RIGHT|LAYOUT_CENTER_Y)
162
+ end
163
+ end
164
+
165
+ class CreateActionDlg < FXDialogBox
166
+
167
+ def getAction()
168
+ return @actionSelection.createAction()
169
+ end
170
+
171
+ def initialize(owner)
172
+ super(owner, "Create Action", DECOR_TITLE|DECOR_BORDER, :width => 300, :height => 500)
173
+ main = FXVerticalFrame.new(self, :opts => LAYOUT_FILL_X|LAYOUT_FILL_Y)
174
+
175
+ @actionSelection = ActionSelect.new(main, self, :opts => LAYOUT_FILL_X|LAYOUT_FILL_Y|FRAME_NONE, :padding => 0)
176
+
177
+ buttons = FXHorizontalFrame.new(main, :opts => LAYOUT_SIDE_BOTTOM|LAYOUT_FILL_X|PACK_UNIFORM_WIDTH,:padLeft => 40, :padRight => 40, :padTop => 20, :padBottom => 20)
178
+ # Accept
179
+ accept = FXButton.new(buttons, "&Accept", nil, self, ID_ACCEPT, FRAME_RAISED|FRAME_THICK|LAYOUT_RIGHT|LAYOUT_CENTER_Y)
180
+
181
+ # Cancel
182
+ FXButton.new(buttons, "&Cancel", nil, self, ID_CANCEL, FRAME_RAISED|FRAME_THICK|LAYOUT_RIGHT|LAYOUT_CENTER_Y)
183
+ end
184
+ end
185
+
186
+ class CreateGeneratorDlg < FXDialogBox
187
+
188
+ def getGenerator(fuzzer)
189
+ return @fuzzerSelection.createGenerator(fuzzer)
190
+ end
191
+
192
+ def initialize(owner)
193
+ super(owner, "Create Generator", DECOR_TITLE|DECOR_BORDER)
194
+ main = FXVerticalFrame.new(self, :opts => LAYOUT_FILL_X|LAYOUT_FILL_Y|FRAME_NONE, :padding => 0)
195
+
196
+ @fuzzerSelection = FuzzerGenSelect.new(main, self, :opts => LAYOUT_FILL_X|LAYOUT_FILL_Y|FRAME_NONE, :padding => 0)
197
+
198
+ buttons = FXHorizontalFrame.new(main, :opts => LAYOUT_SIDE_BOTTOM|LAYOUT_FILL_X|PACK_UNIFORM_WIDTH,
199
+ :padLeft => 40, :padRight => 40, :padTop => 20, :padBottom => 20)
200
+ # Accept
201
+ accept = FXButton.new(buttons, "&Accept", nil, self, ID_ACCEPT,
202
+ FRAME_RAISED|FRAME_THICK|LAYOUT_RIGHT|LAYOUT_CENTER_Y)
203
+
204
+ # Cancel
205
+ FXButton.new(buttons, "&Cancel", nil, self, ID_CANCEL,
206
+ FRAME_RAISED|FRAME_THICK|LAYOUT_RIGHT|LAYOUT_CENTER_Y)
207
+ end
208
+ end
209
+
210
+ class CreateFilterDlg < FXDialogBox
211
+
212
+ def filter()
213
+ return @filterFrame.selection()
214
+ end
215
+
216
+ def initialize(owner, project)
217
+ super(owner, "Create Filter", DECOR_TITLE|DECOR_BORDER)
218
+ main = FXVerticalFrame.new(self, :opts => LAYOUT_FILL_X|LAYOUT_FILL_Y|FRAME_NONE, :padding => 0)
219
+
220
+ @filterFrame = FilterFrame.new(main, project.getSidPatterns, :opts => LAYOUT_FILL_X|LAYOUT_FILL_Y|FRAME_NONE, :padding => 0)
221
+
222
+ buttons = FXHorizontalFrame.new(main, :opts => LAYOUT_SIDE_BOTTOM|LAYOUT_FILL_X|PACK_UNIFORM_WIDTH,
223
+ :padLeft => 40, :padRight => 40, :padTop => 20, :padBottom => 20)
224
+ # Accept
225
+ accept = FXButton.new(buttons, "&Accept", nil, self, ID_ACCEPT,
226
+ FRAME_RAISED|FRAME_THICK|LAYOUT_RIGHT|LAYOUT_CENTER_Y)
227
+
228
+ # Cancel
229
+ FXButton.new(buttons, "&Cancel", nil, self, ID_CANCEL,
230
+ FRAME_RAISED|FRAME_THICK|LAYOUT_RIGHT|LAYOUT_CENTER_Y)
231
+ end
232
+ end
233
+
234
+ class FuzzRequestEditor < Watobo::Gui::RequestEditor
235
+
236
+ def highlight(pattern)
237
+ sindex = nil
238
+ eindex = nil
239
+
240
+ dummy = @textbox.to_s
241
+ @textbox.setText(dummy)
242
+
243
+ pos = 0
244
+ @pattern_matches.clear
245
+
246
+ loop do
247
+
248
+ sindex, eindex = @textbox.findText(pattern, pos, SEARCH_EXACT|SEARCH_IGNORECASE|SEARCH_FORWARD)
249
+ # puts sindex
250
+ sindex, eindex = @textbox.findText(pattern, pos, :flags => SEARCH_REGEX|SEARCH_IGNORECASE|SEARCH_FORWARD) if not sindex
251
+ # puts sindex
252
+ sindex, eindex = @textbox.findText(Regexp.quote(pattern), pos, :flags => SEARCH_REGEX|SEARCH_IGNORECASE|SEARCH_FORWARD) if not sindex
253
+
254
+ break if not sindex or sindex.length == 0
255
+
256
+
257
+ pos = eindex.last+1
258
+
259
+ sindex.length.times do |i|
260
+ start = sindex[i]
261
+ len = eindex[i] - sindex[i]
262
+ @pattern_matches.push [ start, len] if start >= 0
263
+
264
+ end
265
+
266
+ break if sindex.last < 0
267
+ # puts sindex
268
+
269
+ end
270
+
271
+ # puts "* found pattern #{pattern} #{@pattern_matches.length} times"
272
+
273
+ @pattern_matches.each do |start, len|
274
+ begin
275
+ style = @style
276
+ match = @textbox.to_s.slice(start, len)
277
+ # puts "#{match}/#{start}/#{len}"
278
+ match.gsub!(/%%/, '')
279
+ style = @tags.include?(match) ? 1 : 2
280
+
281
+ @textbox.changeStyle(start, len, style)
282
+ rescue => bang
283
+ puts "outch"
284
+ puts bang
285
+ end
286
+ end
287
+ return @pattern_matches
288
+ end
289
+
290
+
291
+
292
+ def parseRequest(fuzzels)
293
+ begin
294
+ new_request = nil
295
+ if fuzzels then
296
+ new_request = @textbox.to_s
297
+ fuzzels.each do |marker, value|
298
+ new_request.gsub!(/%%#{marker}%%/, value.to_s)
299
+ end
300
+ end
301
+
302
+ return Watobo::Utils.text2request(new_request)
303
+ rescue => bang
304
+ puts bang
305
+ puts bang.backtrace if $DEBUG
306
+ end
307
+ return nil
308
+ end
309
+
310
+ def addTag(tag)
311
+ @tags.push tag
312
+ end
313
+
314
+ def removeTag(tag)
315
+ @tags.delete(tag)
316
+ end
317
+
318
+ def highlightTags()
319
+ highlight("(%%[^%]*%%)")
320
+ end
321
+
322
+ def initialize(owner, opts)
323
+ super(owner, opts)
324
+
325
+ @tags = []
326
+
327
+ end
328
+ end
329
+
330
+ class Action
331
+ attr :action_type
332
+ attr :func
333
+ attr :info
334
+
335
+ def is_action?
336
+ true
337
+ end
338
+
339
+ def initialize(action_proc, prefs)
340
+ @func = action_proc
341
+ @action_type = prefs[:action_type] || "undefined"
342
+ @info = prefs[:info] || "undefined"
343
+ end
344
+ end
345
+
346
+ class Filter
347
+ attr :func
348
+ attr :filter_type
349
+ attr :value
350
+ attr :info
351
+
352
+ def is_filter?
353
+ true
354
+ end
355
+
356
+ def initialize(filter_proc, prefs)
357
+ @filter_type = prefs[:filter_type] || "undefined"
358
+ @value = prefs[:value] || "undefined"
359
+ @func = filter_proc
360
+ @info = prefs[:info] || "undefined"
361
+ end
362
+ end
363
+
364
+ class StatisticsFrame < FXVerticalFrame
365
+
366
+ def clearView()
367
+ @count_total = 0
368
+ clearResponseCodeTable()
369
+ clearResponseLengthTable()
370
+ end
371
+
372
+ def addResponse(response)
373
+
374
+ return nil unless response.respond_to? :status
375
+
376
+ @lock.synchronize {
377
+ cstatus = response.status
378
+ count_item = nil
379
+ @response_code_tbl.getNumRows.times do |i|
380
+ rc_item = @response_code_tbl.getItem(i, 0)
381
+ count_item = @response_code_tbl.getItem(i, 1) if rc_item.text == response.status
382
+ break unless count_item.nil?
383
+ end
384
+
385
+ if count_item.nil?
386
+ lastRowIndex = @response_code_tbl.getNumRows
387
+ @response_code_tbl.appendRows(1)
388
+ @response_code_tbl.setItemText(lastRowIndex, 0, cstatus)
389
+ @response_code_tbl.setItemText(lastRowIndex, 1, "1")
390
+ count_item = @response_code_tbl.getItem(lastRowIndex, 1)
391
+ else
392
+ c = count_item.text.to_i
393
+ count_item.text = ( c + 1 ).to_s
394
+ end
395
+ }
396
+
397
+ end
398
+
399
+ def clearResponseCodeTable()
400
+ @response_code_tbl.clearItems()
401
+ @response_code_tbl.setTableSize(0, 2)
402
+
403
+ @response_code_tbl.setColumnText( 0, "STATUS" )
404
+ @response_code_tbl.setColumnText( 1, "COUNT" )
405
+
406
+ @response_code_tbl.rowHeader.width = 0
407
+ @response_code_tbl.setColumnWidth(0, 70)
408
+
409
+ @response_code_tbl.setColumnWidth(1, 70)
410
+
411
+
412
+ end
413
+
414
+ def clearResponseLengthTable()
415
+ @response_length_tbl.clearItems()
416
+ @response_length_tbl.setTableSize(0, 2)
417
+ @response_length_tbl.columnHeader.height = 0
418
+ @response_length_tbl.rowHeader.width = 0
419
+ @response_length_tbl.setColumnWidth(0, 40)
420
+ @response_length_tbl.setColumnWidth(1, 40)
421
+
422
+ lastRowIndex = @response_length_tbl.getNumRows
423
+
424
+ %w( MIN MAX AVRG ).each do |i|
425
+ lastRowIndex = @response_length_tbl.getNumRows
426
+ @response_length_tbl.appendRows(1)
427
+ @response_length_tbl.setItemText(lastRowIndex, 0, i)
428
+ @response_length_tbl.setItemText(lastRowIndex, 1, "0")
429
+ @response_length_tbl.getItem(lastRowIndex, 0).justify = FXTableItem::LEFT
430
+ @response_length_tbl.getItem(lastRowIndex, 1).justify = FXTableItem::LEFT
431
+ end
432
+ end
433
+
434
+ def initialize(parent, opts)
435
+ super(parent, opts)
436
+
437
+ @lock = Mutex.new
438
+
439
+ @count_total = 0
440
+ counter_frame = FXHorizontalFrame.new(self, :opts => LAYOUT_FILL_X|LAYOUT_FILL_Y)
441
+ response_code_gb = FXGroupBox.new(counter_frame, "Response Codes", LAYOUT_SIDE_BOTTOM|FRAME_GROOVE|LAYOUT_FILL_X|LAYOUT_FILL_Y, 0, 0, 0, 0)
442
+ frame = FXVerticalFrame.new(response_code_gb, :opts => LAYOUT_FILL_X|LAYOUT_FILL_Y )
443
+ sunken = FXVerticalFrame.new(frame, :opts => LAYOUT_FILL_X|LAYOUT_FILL_Y|FRAME_SUNKEN|FRAME_THICK, :padding => 0)
444
+ @response_code_tbl = FXTable.new(sunken, :opts => FRAME_SUNKEN|TABLE_COL_SIZABLE|TABLE_ROW_SIZABLE|LAYOUT_FILL_X|LAYOUT_FILL_Y|TABLE_READONLY|LAYOUT_SIDE_TOP, :padding => 2)
445
+ @response_code_tbl.columnHeader.connect(SEL_COMMAND) { }
446
+ clearResponseCodeTable()
447
+
448
+ response_length_gb = FXGroupBox.new(counter_frame, "Response Length", LAYOUT_SIDE_BOTTOM|FRAME_GROOVE|LAYOUT_FILL_Y, 0, 0, 0, 0)
449
+ frame = FXVerticalFrame.new(response_length_gb, :opts => LAYOUT_FILL_X|LAYOUT_FILL_Y )
450
+ sunken = FXVerticalFrame.new(frame, :opts => LAYOUT_FILL_X|LAYOUT_FILL_Y|FRAME_SUNKEN|FRAME_THICK, :padding => 0)
451
+ @response_length_tbl = FXTable.new(sunken, :opts => FRAME_SUNKEN|TABLE_COL_SIZABLE|TABLE_ROW_SIZABLE|LAYOUT_FILL_X|LAYOUT_FILL_Y|TABLE_READONLY|LAYOUT_SIDE_TOP, :padding => 2)
452
+ @response_length_tbl.columnHeader.connect(SEL_COMMAND) { }
453
+ clearResponseLengthTable()
454
+ end
455
+ end
456
+
457
+ class FilterFrame < FXVerticalFrame
458
+
459
+ def selection()
460
+ filter = case @filter_dt.value
461
+ when 0
462
+ index = @patternCombo.currentItem
463
+ if @patternCombo.getItemText(index)
464
+ func = proc { |response|
465
+ pattern = @patternCombo.getItemText(index)
466
+ matchlist = []
467
+ response.each do |line|
468
+ if line =~ /#{pattern}/i then
469
+ match = $2
470
+ matchlist.push "#{match}"
471
+ end
472
+ end
473
+ matchlist
474
+ }
475
+ Filter.new(func, :filter_type => "SID", :value => "#{filter}", :info => "#{@patternCombo.getItemText(index)}" )
476
+ else
477
+ nil
478
+ end
479
+
480
+ when 1
481
+
482
+ if @regex_filter_dt.value != '' then
483
+ func = proc { |response|
484
+ pattern = @regex_filter_dt.value
485
+ matchlist = []
486
+ # puts "...regex (#{pattern})..."
487
+ # puts response
488
+ #response.each do |line|
489
+ #if line =~ /#{pattern}/i then
490
+ if @negate_regex_cb.checked?
491
+ puts "* filter negate regex"
492
+ unless response.join =~ /#{pattern}/i then
493
+ match = $1
494
+ puts "* #{match}"
495
+ match = "#{response.join}" unless match
496
+ matchlist.push "#{match}"
497
+ end
498
+ else
499
+ if response.join =~ /#{pattern}/i then
500
+ match = $1
501
+ puts "* #{match}"
502
+ match = "#{response.join}" unless match
503
+ matchlist.push "#{match}"
504
+ end
505
+ end
506
+ #end
507
+ matchlist
508
+ }
509
+ Filter.new(func, :filter_type => "Regex", :value => "#{filter}", :info => "#{@regex_filter_dt.value}")
510
+ else
511
+ nil
512
+ end
513
+ end
514
+ return filter
515
+ end
516
+
517
+
518
+ def initialize(owner, sidpatterns, opts)
519
+ @sid_patterns = sidpatterns
520
+ super(owner, opts)
521
+
522
+ @filter_dt = FXDataTarget.new(0)
523
+ group_box = FXGroupBox.new(self, "Filter", LAYOUT_SIDE_TOP|FRAME_GROOVE|LAYOUT_FILL_X, 0, 0, 0, 0)
524
+ sid_frame = FXHorizontalFrame.new(group_box, :opts => LAYOUT_FILL_X)
525
+ @sid_rb = FXRadioButton.new(sid_frame, "Session-ID", @filter_dt, FXDataTarget::ID_OPTION)
526
+
527
+ regex_frame = FXHorizontalFrame.new(group_box, :opts => LAYOUT_FILL_X)
528
+ @regex_rb = FXRadioButton.new(regex_frame, "Regex", @filter_dt, FXDataTarget::ID_OPTION + 1)
529
+ @regex_filter_dt = FXDataTarget.new('')
530
+ @regex_filter = FXTextField.new(regex_frame, 1, :target => @regex_filter_dt, :selector => FXDataTarget::ID_VALUE,
531
+ :opts => TEXTFIELD_NORMAL|LAYOUT_FILL_X|LAYOUT_FILL_COLUMN)
532
+ @negate_regex_cb = FXCheckButton.new(group_box, "negate", nil, 0, ICON_BEFORE_TEXT|LAYOUT_SIDE_TOP|LAYOUT_RIGHT|LAYOUT_FILL_Y)
533
+ # group_box = FXGroupBox.new(self, "Collection",LAYOUT_SIDE_TOP|FRAME_GROOVE|LAYOUT_FILL_X|LAYOUT_FILL_Y, 0, 0, 0, 0)
534
+ # frame = FXVerticalFrame.new(group_box, :opts => LAYOUT_FILL_X|LAYOUT_FILL_Y|FRAME_SUNKEN|FRAME_GROOVE)
535
+ # @collectionList = FXList.new(frame, :opts => LIST_EXTENDEDSELECT|LAYOUT_FILL_X|LAYOUT_FILL_Y)
536
+ @filter_dt.connect(SEL_COMMAND) {
537
+ @sid_rb.handle(self, FXSEL(SEL_UPDATE, 0), nil)
538
+ @regex_rb.handle(self, FXSEL(SEL_UPDATE, 0), nil)
539
+ }
540
+
541
+ if @sid_patterns then
542
+ @patternCombo = FXComboBox.new(sid_frame, @sid_patterns.length, nil, 0,
543
+ :opts => COMBOBOX_INSERT_LAST|FRAME_SUNKEN|FRAME_THICK|LAYOUT_SIDE_TOP|LAYOUT_FILL_X)
544
+ @patternCombo.numVisible = @sid_patterns.length
545
+ @sid_patterns.each do |pattern|
546
+ @patternCombo.appendItem(pattern, nil)
547
+ end
548
+ else
549
+ FXLabel.new(sid_frame, "NO SID PATTERNS DEFINED!")
550
+ @sid_rb.disable
551
+ @filter_dt.value = 1
552
+ @regex_rb.handle(self, FXSEL(SEL_UPDATE, 0), nil)
553
+ end
554
+
555
+ @sid_rb.handle(self, FXSEL(SEL_UPDATE, 0), nil)
556
+ @regex_rb.handle(self, FXSEL(SEL_UPDATE, 0), nil)
557
+ # group_box = FXGroupBox.new(self, "Test", LAYOUT_SIDE_TOP|FRAME_GROOVE|LAYOUT_FILL_X, 0, 0, 0, 0)
558
+ # @sample_count_dt = FXDataTarget.new('')
559
+ # frame = FXHorizontalFrame.new(group_box, :opts => LAYOUT_FILL_X)
560
+ # @sample_count = FXTextField.new(frame, 3, :target => @sample_count_dt, :selector => FXDataTarget::ID_VALUE,
561
+ # :opts => TEXTFIELD_NORMAL|LAYOUT_FILL_COLUMN)
562
+ # button = FXButton.new(frame, "Sample", nil, nil, 0, FRAME_RAISED|FRAME_THICK)
563
+ # button.connect(SEL_COMMAND) do |sender, sel, ptr|
564
+ # @interface.startSample()
565
+ # end
566
+ # frame = FXHorizontalFrame.new(group_box, :opts => LAYOUT_FILL_X)
567
+ # FXLabel.new(frame, "Matched:")
568
+
569
+
570
+ end
571
+ end
572
+
573
+ class FuzzerGenSelect < FXVerticalFrame
574
+
575
+ include Watobo
576
+
577
+ def updateFields
578
+ @file_rb.handle(self, FXSEL(SEL_UPDATE, 0), nil)
579
+ @gen_rb.handle(self, FXSEL(SEL_UPDATE, 0), nil)
580
+ @list_rb.handle(self, FXSEL(SEL_UPDATE, 0), nil)
581
+ @sourceFileText.handle(self, FXSEL(SEL_UPDATE, 0), nil)
582
+ @cstartText.handle(self, FXSEL(SEL_UPDATE, 0), nil)
583
+ @cstopText.handle(self, FXSEL(SEL_UPDATE, 0), nil)
584
+ @cstepText.handle(self, FXSEL(SEL_UPDATE, 0), nil)
585
+ end
586
+
587
+ def selectFile(sender, sel, ptr)
588
+ filename = FXFileDialog.getOpenFilename(self, "Select Source File", @source_file.value)
589
+ if filename != "" then
590
+ if File.exists?(filename) then
591
+ @source_file.value = filename
592
+ @sourceFileText.handle(self, FXSEL(SEL_UPDATE, 0), nil)
593
+ end
594
+
595
+ end
596
+ end
597
+
598
+ def onValueSelect(sender, sel, selected)
599
+ item = @valueList.currentItem
600
+ if item >= 0 then
601
+ @new_list_item_dt.value = @valueList.getItemText(item)
602
+ end
603
+ end
604
+
605
+ def removeValue(sender, sel, ptr)
606
+ item = @valueList.currentItem
607
+ if item >= 0 then
608
+ @valueList.removeItem(item)
609
+ end
610
+ end
611
+
612
+ def addValue(sender, sel, ptr)
613
+ if @new_list_item_dt.value != '' then
614
+ index = @valueList.appendItem(@new_list_item_dt.value )
615
+ @valueList.makeItemVisible(index)
616
+ @new_list_item_dt.value = ''
617
+ @new_list_item.handle(self, FXSEL(SEL_UPDATE, 0), nil)
618
+ end
619
+ end
620
+
621
+ def createGenerator(fuzzer)
622
+ gen = case @source_dt.value
623
+ when 0
624
+ #puts "File Generator Selected"
625
+ Watobo::FuzzFile.new(fuzzer,
626
+ @source_file.value)
627
+ when 1
628
+ # counter selected
629
+ Watobo::FuzzCounter.new(fuzzer,
630
+ :start => @cstart.value.to_i,
631
+ :stop => @cstop.value.to_i,
632
+ #:count => @ccount.value.to_i,
633
+ :step => @cstep.value.to_i)
634
+ when 2
635
+
636
+ list = []
637
+ @valueList.each do |item|
638
+ # puts item
639
+ list.push item.text
640
+ end
641
+ Watobo::FuzzList.new(fuzzer, list)
642
+ end
643
+
644
+ return gen
645
+ end
646
+
647
+ def disableFrame(frame)
648
+ frame.children.each do |c|
649
+ c.children.each do |sc|
650
+ sc.disable
651
+ sc.selBackColor = sc.parent.backColor if sc.respond_to? :selBackColor
652
+ end
653
+ c.disable
654
+ c.selBackColor = c.parent.backColor if c.respond_to? :selBackColor
655
+ end
656
+ end
657
+
658
+ def enableFrame(frame)
659
+ frame.children.each do |c|
660
+ c.children.each do |sc|
661
+ sc.enable
662
+ sc.selBackColor = FXColor::White if sc.respond_to? :selBackColor
663
+ end
664
+ c.enable
665
+ c.selBackColor = FXColor::White if c.respond_to? :selBackColor
666
+ end
667
+ end
668
+
669
+ def initialize(owner, interface, opts)
670
+ super(owner, opts)
671
+
672
+ @interface = interface
673
+
674
+ group_box = FXGroupBox.new(self, "Select Source", LAYOUT_SIDE_TOP|FRAME_GROOVE|LAYOUT_FILL_X|LAYOUT_FILL_Y, 0, 0, 0, 0)
675
+ @source_dt = FXDataTarget.new(0)
676
+
677
+ @source_dt.connect(SEL_COMMAND) do
678
+ case @source_dt.value
679
+ when 0
680
+ # puts "File"
681
+ enableFrame(@file_select_frame)
682
+ disableFrame(@counter_frame)
683
+ disableFrame(@list_frame)
684
+ when 1
685
+ disableFrame(@file_select_frame)
686
+ disableFrame(@list_frame)
687
+ enableFrame(@counter_frame)
688
+ # puts "Generator"
689
+ when 2
690
+ disableFrame(@counter_frame)
691
+ enableFrame(@list_frame)
692
+ disableFrame(@file_select_frame)
693
+ # puts "List"
694
+ end
695
+ @file_rb.handle(self, FXSEL(SEL_UPDATE, 0), nil)
696
+ @gen_rb.handle(self, FXSEL(SEL_UPDATE, 0), nil)
697
+ @list_rb.handle(self, FXSEL(SEL_UPDATE, 0), nil)
698
+ end
699
+ file_rb_frame = FXHorizontalFrame.new(group_box, :opts => LAYOUT_FILL_X)
700
+ @file_rb = FXRadioButton.new(file_rb_frame, "File", @source_dt, FXDataTarget::ID_OPTION)
701
+
702
+ @file_select_frame = FXHorizontalFrame.new(group_box, :opts => LAYOUT_FILL_X, :padding => 0)
703
+ @source_file = FXDataTarget.new('')
704
+ @sourceFileText = FXTextField.new(@file_select_frame, 1, :target => @source_file, :selector => FXDataTarget::ID_VALUE,
705
+ :opts => TEXTFIELD_NORMAL|LAYOUT_FILL_X|LAYOUT_FILL_COLUMN)
706
+ button = FXButton.new(@file_select_frame, "Select")
707
+ button.connect(SEL_COMMAND, method(:selectFile) )
708
+
709
+ counter_rb_frame = FXHorizontalFrame.new(group_box, LAYOUT_FILL_X)
710
+ @gen_rb = FXRadioButton.new(counter_rb_frame, "Counter", @source_dt, FXDataTarget::ID_OPTION + 1)
711
+ @counter_frame = FXHorizontalFrame.new(group_box, LAYOUT_FILL_X, :padding => 0 )
712
+
713
+ @cstep = FXDataTarget.new(0)
714
+ @cstepText = FXTextField.new(@counter_frame, 3, :target => @cstep, :selector => FXDataTarget::ID_VALUE,
715
+ :opts => TEXTFIELD_NORMAL|LAYOUT_FILL_COLUMN|LAYOUT_RIGHT)
716
+ FXLabel.new(@counter_frame, "Step",nil, :opts => LAYOUT_RIGHT)
717
+
718
+
719
+
720
+ @cstop = FXDataTarget.new(0)
721
+ @cstopText = FXTextField.new(@counter_frame, 3, :target => @cstop, :selector => FXDataTarget::ID_VALUE,
722
+ :opts => TEXTFIELD_NORMAL|LAYOUT_FILL_COLUMN|LAYOUT_RIGHT)
723
+ FXLabel.new(@counter_frame, "Stop",nil, :opts => LAYOUT_RIGHT)
724
+
725
+
726
+ @cstart = FXDataTarget.new(0)
727
+ @cstartText = FXTextField.new(@counter_frame, 3, :target => @cstart, :selector => FXDataTarget::ID_VALUE,
728
+ :opts => TEXTFIELD_NORMAL|LAYOUT_FILL_COLUMN|LAYOUT_RIGHT)
729
+ FXLabel.new(@counter_frame, "Start",nil, :opts => LAYOUT_RIGHT)
730
+
731
+ list_rb_frame = FXHorizontalFrame.new(group_box, :opts => LAYOUT_FILL_X|LAYOUT_FILL_Y)
732
+ @list_rb = FXRadioButton.new(list_rb_frame, "List", @source_dt, FXDataTarget::ID_OPTION + 2)
733
+ @list_frame = FXVerticalFrame.new(list_rb_frame, :opts => LAYOUT_FILL_X|LAYOUT_FILL_Y, :padding => 0)
734
+ frame = FXHorizontalFrame.new(@list_frame, :opts => LAYOUT_FILL_X, :padding => 0)
735
+
736
+ @new_list_item_dt = FXDataTarget.new('')
737
+ @new_list_item = FXTextField.new(frame, 10,
738
+ :target => @new_list_item_dt, :selector => FXDataTarget::ID_VALUE,
739
+ :opts => TEXTFIELD_NORMAL|LAYOUT_SIDE_LEFT|LAYOUT_FILL_X)
740
+ # FXLabel.new(frame, "Value: ")
741
+ @addButton = FXButton.new(frame, "Add", nil, nil, 0, :opts => FRAME_RAISED|FRAME_THICK)
742
+ @addButton.connect(SEL_COMMAND, method(:addValue))
743
+ @remButton = FXButton.new(frame, "Remove", nil, nil, 0, :opts => FRAME_RAISED|FRAME_THICK)
744
+ @remButton.connect(SEL_COMMAND, method(:removeValue))
745
+
746
+ list_border = FXVerticalFrame.new(@list_frame, :opts => LAYOUT_FILL_X|LAYOUT_FILL_Y|FRAME_SUNKEN|FRAME_GROOVE, :padding => 0)
747
+ @valueList = FXList.new(list_border, :opts => LIST_EXTENDEDSELECT|LAYOUT_FILL_X|LAYOUT_FILL_Y)
748
+ @valueList.numVisible = 4
749
+
750
+ @valueList.connect(SEL_COMMAND, method(:onValueSelect))
751
+
752
+ enableFrame(@file_select_frame)
753
+ disableFrame(@counter_frame)
754
+ disableFrame(@list_frame)
755
+
756
+ updateFields()
757
+
758
+ end
759
+ end
760
+
761
+ class ActionSelect < FXVerticalFrame
762
+ include Watobo
763
+
764
+ def updateFields
765
+ @b64_rb.handle(self, FXSEL(SEL_UPDATE, 0), nil)
766
+ @url_rb.handle(self, FXSEL(SEL_UPDATE, 0), nil)
767
+ @md5_rb.handle(self, FXSEL(SEL_UPDATE, 0), nil)
768
+ @ruby_proc_rb.handle(self, FXSEL(SEL_UPDATE, 0), nil)
769
+
770
+ end
771
+
772
+ def createAction()
773
+ action = case @source_dt.value
774
+ when 0
775
+ action_proc = proc{ |input| Base64.encode64(input)}
776
+ Action.new(action_proc, :action_type => 'Encode: Base64')
777
+ when 1
778
+ action_proc = proc{ |input| CGI::escape(input)}
779
+ Action.new(action_proc, :action_type => 'Encode: URL')
780
+ when 2
781
+ action_proc = proc{ |input| Digest::MD5.hexdigest(input)}
782
+ Action.new(action_proc, :action_type => 'Hash: MD5')
783
+ when 3
784
+ begin
785
+ # puts "* Action: Proc"
786
+ # puts @textbox.to_s
787
+ code = @textbox.to_s
788
+ action_proc = eval(code)
789
+ # puts action_proc
790
+
791
+ rescue SyntaxError => bang
792
+ puts bang
793
+ puts code
794
+ rescue LocalJumpError => bang
795
+ puts bang
796
+ puts code
797
+ rescue SecurityError => bang
798
+ puts "desired functionality forbidden. it may harm your system!"
799
+ puts code
800
+ rescue => bang
801
+ puts bang
802
+ puts code
803
+
804
+ end
805
+ if action_proc
806
+ Action.new(action_proc, :action_type => "Ruby: Proc", :info => "#{@textbox.to_s}")
807
+ else
808
+ nil
809
+ end
810
+ end
811
+
812
+ return action
813
+ end
814
+
815
+
816
+ def initialize(owner, interface, opts)
817
+ super(owner, opts)
818
+
819
+ @interface = interface
820
+
821
+ group_box = FXGroupBox.new(self, "Select Action", LAYOUT_FILL_X|LAYOUT_FILL_Y, 0, 0, 0, 0)
822
+ @source_dt = FXDataTarget.new(0)
823
+
824
+ @source_dt.connect(SEL_COMMAND) do
825
+ @b64_rb.handle(self, FXSEL(SEL_UPDATE, 0), nil)
826
+ @url_rb.handle(self, FXSEL(SEL_UPDATE, 0), nil)
827
+ @md5_rb.handle(self, FXSEL(SEL_UPDATE, 0), nil)
828
+ @ruby_proc_rb.handle(self, FXSEL(SEL_UPDATE, 0), nil)
829
+ if @source_dt.value != 3
830
+ @textbox.enabled = false
831
+ @textbox.backColor = FXColor::LightGrey
832
+ else
833
+ @textbox.enabled = true
834
+ @textbox.backColor = FXColor::White
835
+ end
836
+
837
+ end
838
+
839
+ begin
840
+ frame = FXVerticalFrame.new(group_box, LAYOUT_FILL_X)
841
+ @b64_rb = FXRadioButton.new(frame, "Encode Base64", @source_dt, FXDataTarget::ID_OPTION)
842
+
843
+ frame = FXVerticalFrame.new(group_box, LAYOUT_FILL_X)
844
+ @url_rb = FXRadioButton.new(frame, "Encode URL", @source_dt, FXDataTarget::ID_OPTION + 1)
845
+ # @textbox = FXText.new(frame, :opts => LAYOUT_FILL_X|LAYOUT_FILL_Y, :width => 100, :height => 100)
846
+
847
+ frame = FXHorizontalFrame.new(group_box, :opts => LAYOUT_FILL_X)
848
+ @md5_rb = FXRadioButton.new(frame, "Hash MD5", @source_dt, FXDataTarget::ID_OPTION + 2)
849
+
850
+ frame = FXVerticalFrame.new(group_box, :opts => LAYOUT_FILL_X|LAYOUT_FILL_Y)
851
+ @ruby_proc_rb = FXRadioButton.new(frame, "Ruby Proc", @source_dt, FXDataTarget::ID_OPTION + 3)
852
+ text_frame = FXVerticalFrame.new(frame, :opts => LAYOUT_FILL_X|LAYOUT_FILL_Y|FRAME_THICK|FRAME_SUNKEN, :padding => 0)
853
+ @textbox = FXText.new(text_frame, :opts => LAYOUT_FILL_X|LAYOUT_FILL_Y, :width => 100, :height => 100)
854
+ proc_skeleton = "proc { |input|\n# place your code betweenhere\n# e.g. 'input + \"TAIL\"\n\n\n# and here\n}"
855
+ @textbox.setText(proc_skeleton)
856
+ @textbox.enabled = false
857
+ @textbox.backColor = FXColor::LightGrey
858
+
859
+
860
+
861
+ # @textbox.editable = true
862
+ rescue => bang
863
+ puts "AAAAAA"
864
+ puts bang
865
+ end
866
+ updateFields()
867
+
868
+ end
869
+ end
870
+
871
+
872
+ class FuzzerGui < FXDialogBox
873
+
874
+ include Watobo::Gui::Utils
875
+ include Watobo::Gui::Icons
876
+ include Watobo::Constants
877
+
878
+ def onRequestReset(sender,sel,item)
879
+ @requestEditor.setText(@request)
880
+ end
881
+
882
+ def hide()
883
+ @scanner.cancel() if @scanner
884
+ self.destroy
885
+ end
886
+
887
+ def listTags()
888
+ tags = []
889
+ tags.concat @sourceSelect.getTags()
890
+ return tags
891
+ end
892
+
893
+ def initTable(table)
894
+ table.clearItems()
895
+ table.setTableSize(0, 2)
896
+ table.visibleRows = 20
897
+ table.rowHeader.width = 0
898
+ table.setColumnText( 0, "Tag/Value" )
899
+ table.setColumnText( 1, "Match" )
900
+ end
901
+
902
+ def selectLogDirectory(sender, sel, item)
903
+ workspace_dt = FXFileDialog.getOpenDirectory(self, "Select Log Directory", @log_dir_dt.value)
904
+ if workspace_dt != "" then
905
+ if File.exists?(workspace_dt) then
906
+ @log_dir_dt.value = workspace_dt
907
+ @log_dir_text.handle(self, FXSEL(SEL_UPDATE, 0), nil)
908
+ end
909
+ end
910
+ end
911
+
912
+ def saveMatches(sender, sel, ptr)
913
+ begin
914
+ # puts @project.settings[:session_path]
915
+ # path = @project.settings[:session_path]+"/"
916
+ filename = FXFileDialog.getSaveFilename(self, "Save file", nil, "All Files (*)")
917
+ if filename != ""
918
+ if File.exists?(filename)
919
+ response = FXMessageBox.question(self, MBOX_YES_NO, "File exists", "Overwrite existing file?")
920
+ return 0 if response != MBOX_CLICKED_YES
921
+
922
+ end
923
+ fh = File.new(filename, "w")
924
+ @matchTable.numRows.times do |i|
925
+ #puts items[1].to_s
926
+ data = @matchTable.getItemData(i,1)
927
+ fh.puts data.strip if data
928
+ end
929
+ fh.close
930
+ end
931
+ rescue => bang
932
+ puts bang
933
+ puts bang.backtrace if $DEBUG
934
+ end
935
+ end
936
+
937
+ def startSample(count)
938
+ #TODO: Create and viewer for sample requests
939
+ end
940
+
941
+ def filterResponse(response, fuzzle)
942
+
943
+ @filters.each do |f|
944
+ matches = f.func.call(response) if f.func.respond_to? :call
945
+ if matches.length > 0
946
+
947
+ matches.each do |m|
948
+ yield fuzzle, m
949
+ end
950
+
951
+ end
952
+ end
953
+
954
+ end
955
+
956
+ def updateStatistics(request, response)
957
+
958
+ end
959
+
960
+ def addMatch(fuzzle, match)
961
+ s = []
962
+ fuzzle.each_pair do |k, v|
963
+ s.push "#{k}=#{v}"
964
+ end
965
+ lastRowIndex = @matchTable.getNumRows
966
+ @matchTable.appendRows(1)
967
+ @matchTable.setItemText(lastRowIndex, 0, s.join("\n"))
968
+ @matchTable.getItem(lastRowIndex, 0).justify = FXTableItem::LEFT
969
+ @matchTable.fitRowsToContents(lastRowIndex)
970
+ cell_text = match.gsub(/(\n+|\r+)/, " ")
971
+ cell_text = ( cell_text.slice(0..150) + "..." ).strip if match.length > 150
972
+ @matchTable.setItemText(lastRowIndex, 1, cell_text)
973
+ @matchTable.setItemData(lastRowIndex, 1, match)
974
+ @matchTable.getItem(lastRowIndex, 1).justify = FXTableItem::LEFT
975
+ end
976
+
977
+
978
+ def startFuzzing()
979
+ initTable(@matchTable)
980
+
981
+ @log_viewer.log(LOG_INFO,"Prepare Fuzzing: Generators")
982
+ check_list = []
983
+ check_list << FuzzerCheck.new(@project, @fuzzer_tags, @filters, @requestEditor)
984
+
985
+ # create dummy chat, not needed for fuzzing
986
+ chat_list = []
987
+ chat_list << Watobo::Chat.new(@chat.request, @chat.response, :source => CHAT_SOURCE_FUZZER, :id => 0 )
988
+
989
+
990
+
991
+
992
+ scan_prefs = @project.getScanPreferences
993
+ # we don't want logout detection in manual requests ... yet
994
+ scan_prefs[:logout_signatures] = []
995
+ # scan_prefs[:csrf_requests] = @csrf_requests
996
+ scan_prefs[:check_online] = false
997
+ # check if logging all scan chat
998
+
999
+ if @logScanChats.checked? and File.exist?(@log_dir_dt.value)
1000
+ new_dir = File.join(@log_dir_dt.value, "fuzzer-" + Time.now.to_f.to_s )
1001
+ Dir.mkdir(new_dir)
1002
+ scan_prefs[:scanlog_dir] = new_dir
1003
+ end
1004
+
1005
+ @scanner = Watobo::Scanner2.new(chat_list, check_list, @project.passive_checks, scan_prefs)
1006
+ @pbar.total = @scanner.numTotalChecks
1007
+ @pbar.progress = 0
1008
+ @pbar.barColor = 'red'
1009
+
1010
+ @scanner.subscribe(:progress) { |m|
1011
+ @pbar.increment(1)
1012
+ }
1013
+
1014
+ check_list.first.subscribe(:fuzzer_match) { |fuzzle, request, response, match|
1015
+ @stat_viewer.addResponse(response)
1016
+ addMatch(fuzzle, match)
1017
+
1018
+ }
1019
+
1020
+ Thread.new {
1021
+ begin
1022
+ m = "start fuzzing..."
1023
+ @log_viewer.log(LOG_INFO,m)
1024
+ scan_prefs = Hash.new
1025
+ scan_prefs[:update_session] = @updateSession.checked?
1026
+ scan_prefs[:run_passive_checks] = false
1027
+ scan_prefs[:update_content_length] = @updateContentLength.checked?
1028
+
1029
+ puts scan_prefs.to_yaml
1030
+ puts "run scanner"
1031
+ @scanner.run(scan_prefs)
1032
+ @fuzz_button.text = "Start"
1033
+ @pbar.total = 0
1034
+ @pbar.progress = 0
1035
+ @pbar.barColor = 'grey'
1036
+ m = "finished fuzzing!"
1037
+ @log_viewer.log(LOG_INFO,m)
1038
+ rescue => bang
1039
+ puts bang
1040
+ puts bang.backtrace if $DEBUG
1041
+ end
1042
+ }
1043
+
1044
+ end
1045
+
1046
+
1047
+ def initialize(owner, project, chat)
1048
+ # Invoke base class initialize function first
1049
+ super(owner, "Fuzzer", :opts => DECOR_ALL,:width=>800, :height=>600)
1050
+ self.icon = ICON_FUZZER
1051
+ @project = project
1052
+ @chat = chat
1053
+ @request = chat.request.dup
1054
+ @fuzzing_paused = false
1055
+ @fuzzing_started = false
1056
+
1057
+ # @scan_prefs = @project.getScanPreferences()
1058
+
1059
+ @numRunningChecks = 0
1060
+
1061
+ @fuzzer_tags = []
1062
+ @filters = []
1063
+ @scanner = nil
1064
+
1065
+ # @fuzzels = FXDataTarget.new()
1066
+
1067
+ mr_splitter = FXSplitter.new(self, LAYOUT_FILL_X|LAYOUT_FILL_Y|SPLITTER_VERTICAL|SPLITTER_REVERSED|SPLITTER_TRACKING)
1068
+ # top = FXHorizontalFrame.new(mr_splitter, :opts => LAYOUT_FILL_X|LAYOUT_FILL_Y|LAYOUT_SIDE_BOTTOM)
1069
+ top_frame = FXVerticalFrame.new(mr_splitter, :opts => LAYOUT_FILL_X|LAYOUT_FILL_Y||LAYOUT_FIX_HEIGHT|LAYOUT_BOTTOM,:height => 500)
1070
+ top_splitter = FXSplitter.new(top_frame, LAYOUT_FILL_X|SPLITTER_HORIZONTAL|LAYOUT_FILL_Y|SPLITTER_TRACKING)
1071
+
1072
+ log_frame = FXVerticalFrame.new(mr_splitter, :opts => LAYOUT_FILL_X|LAYOUT_SIDE_BOTTOM,:height => 100)
1073
+
1074
+ #LAYOUT_FILL_X in combination with LAYOUT_FIX_WIDTH
1075
+
1076
+ req_editor = FXVerticalFrame.new(top_splitter, :opts => LAYOUT_FILL_X|LAYOUT_FIX_WIDTH|LAYOUT_FILL_Y|FRAME_GROOVE,:width => 400, :height => 500)
1077
+
1078
+
1079
+
1080
+ req_edit_header = FXHorizontalFrame.new(req_editor, :opts => LAYOUT_FILL_X)
1081
+ FXLabel.new(req_edit_header, "Request:" )
1082
+ req_viewer = FXVerticalFrame.new(req_editor, :opts => LAYOUT_FILL_X|LAYOUT_FILL_Y|FRAME_SUNKEN|FRAME_THICK, :padding => 0)
1083
+ req_reset_button = FXButton.new(req_edit_header, "Reset", nil, nil, 0, FRAME_RAISED|FRAME_THICK|LAYOUT_RIGHT)
1084
+ req_reset_button.connect(SEL_COMMAND, method(:onRequestReset))
1085
+
1086
+
1087
+ frame = FXHorizontalFrame.new(req_editor, :opts => LAYOUT_FILL_X|FRAME_GROOVE)
1088
+ @fuzz_button = FXButton.new(frame, "Start", nil, nil, 0, FRAME_RAISED|FRAME_THICK)
1089
+ @fuzz_button.connect(SEL_COMMAND) { |sender, sel, data|
1090
+ if sender.text =~ /cancel/i then
1091
+ @fuzz_button.text = "Start"
1092
+ @log_viewer.log(LOG_INFO,"Fuzzing canceled!")
1093
+ @scanner.cancel if @scanner
1094
+ @pbar.progress = 0
1095
+ @pbar.total = 0
1096
+ @pbar.barColor=0
1097
+ @pbar.barColor = 'grey' #FXRGB(255,0,0)
1098
+ else
1099
+ @fuzz_button.text = "Cancel"
1100
+ startFuzzing()
1101
+ @fuzz_button.text = "Start" if @scanner.nil?
1102
+ end
1103
+ }
1104
+
1105
+ @pbar = FXProgressBar.new(frame, nil, 0, LAYOUT_FILL_X|LAYOUT_FILL_Y|FRAME_SUNKEN|FRAME_THICK|PROGRESSBAR_HORIZONTAL)
1106
+
1107
+ @pbar.progress = 0
1108
+ @pbar.total = 0
1109
+ @pbar.barColor=0
1110
+ @pbar.barColor = 'grey' #FXRGB(255,0,0)
1111
+ @requestEditor = FuzzRequestEditor.new(req_viewer, :opts => LAYOUT_FILL_X|LAYOUT_FILL_Y)
1112
+ @requestEditor.setText(@request)
1113
+
1114
+ # req_options = FXVerticalFrame.new(req_editor, :opts => LAYOUT_FILL_X|LAYOUT_FILL_Y)
1115
+ #eq_options = FXVerticalFrame.new(frame, :opts => LAYOUT_FILL_X|LAYOUT_SIDE_BOTTOM)
1116
+ opt = FXGroupBox.new(req_editor, "Fuzzing Options", LAYOUT_SIDE_BOTTOM|FRAME_GROOVE|LAYOUT_FILL_X, 0, 0, 0, 0)
1117
+
1118
+ # opt = FXVerticalFrame.new(frame,:opts => LAYOUT_FILL_X|LAYOUT_FILL_Y, :padding => 0)
1119
+ # btn = FXVerticalFrame.new(frame,:opts => LAYOUT_FILL_X|LAYOUT_FILL_Y, :padding => 0)
1120
+ #FXCheckButton.new(rob, "URL Encoding", nil, 0, ICON_BEFORE_TEXT|LAYOUT_SIDE_TOP)
1121
+ @updateContentLength = FXCheckButton.new(opt, "Update Content-Length", nil, 0, ICON_BEFORE_TEXT|LAYOUT_SIDE_TOP)
1122
+ @updateContentLength.checkState = true
1123
+
1124
+ @updateSession = FXCheckButton.new(opt, "Update Session Information", nil, 0, JUSTIFY_LEFT|JUSTIFY_TOP|ICON_BEFORE_TEXT|LAYOUT_SIDE_TOP)
1125
+ @updateSession.checkState = true
1126
+
1127
+ #@updateSession.connect(SEL_COMMAND) do |sender, sel, item|
1128
+ # @runLogin.enabled = @updateSession.checked?
1129
+ #end
1130
+ # @runLogin = FXCheckButton.new(opt, "Run Login", nil, 0, JUSTIFY_LEFT|JUSTIFY_TOP|ICON_BEFORE_TEXT|LAYOUT_SIDE_TOP)
1131
+ # @runLogin.checkState = false
1132
+
1133
+ @logScanChats = FXCheckButton.new(opt, "Log Scan", nil, 0, JUSTIFY_LEFT|JUSTIFY_TOP|ICON_BEFORE_TEXT|LAYOUT_SIDE_TOP)
1134
+ @logScanChats.checkState = false
1135
+ @logScanChats.connect(SEL_COMMAND) do |sender, sel, item|
1136
+ if @logScanChats.checked? then
1137
+ @log_dir_text.enabled = true
1138
+ @log_dir_label.enabled = true
1139
+ @log_dir_btn.enable
1140
+ else
1141
+ @log_dir_text.enabled = false
1142
+ @log_dir_label.enabled = false
1143
+ @log_dir_btn.disable
1144
+ end
1145
+ end
1146
+
1147
+
1148
+ @log_dir_dt = FXDataTarget.new('')
1149
+ # @log_dir_dt.value = @project.scanLogDirectory() if File.exist?(@project.scanLogDirectory())
1150
+ @log_dir_label = FXLabel.new(opt, "Scan-Log Directory:" )
1151
+ scanlog_frame = FXHorizontalFrame.new(opt,:opts => LAYOUT_FILL_X|LAYOUT_SIDE_TOP)
1152
+ @log_dir_text = FXTextField.new(scanlog_frame, 20,
1153
+ :target => @log_dir_dt, :selector => FXDataTarget::ID_VALUE,
1154
+ :opts => TEXTFIELD_NORMAL|LAYOUT_FILL_COLUMN)
1155
+ @log_dir_text.handle(self, FXSEL(SEL_UPDATE, 0), nil)
1156
+ @log_dir_btn = FXButton.new(scanlog_frame, "Change")
1157
+ # @log_dir_btn.connect(SEL_COMMAND, method(:selectLogDirectory))
1158
+
1159
+ @log_dir_text.enabled = false
1160
+ @log_dir_label.enabled = false
1161
+ @log_dir_btn.disable
1162
+
1163
+
1164
+
1165
+
1166
+ fuzz_setup_frame = FXVerticalFrame.new(top_splitter, :opts => LAYOUT_FILL_X|LAYOUT_FILL_Y|FRAME_GROOVE|LAYOUT_FIX_WIDTH, :width => 400)
1167
+
1168
+ @tabBook = FXTabBook.new(fuzz_setup_frame, nil, 0, :opts => LAYOUT_FILL_X|LAYOUT_FILL_Y|LAYOUT_RIGHT)
1169
+
1170
+ FXTabItem.new(@tabBook, "Settings", nil)
1171
+ rframe = FXVerticalFrame.new(@tabBook, :opts => LAYOUT_FILL_X|LAYOUT_FILL_Y|FRAME_RAISED)
1172
+ frame = FXVerticalFrame.new(rframe, :opts => LAYOUT_FILL_X|LAYOUT_FILL_Y|FRAME_SUNKEN, :padding => 0)
1173
+ @fuzzer_tree = FuzzerTree.new(frame, @project)
1174
+
1175
+ @fuzzer_tree.subscribe(:new_tag) do |tag|
1176
+ @fuzzer_tags.push tag
1177
+ @requestEditor.addTag(tag.name)
1178
+ @requestEditor.highlightTags()
1179
+ end
1180
+
1181
+ @fuzzer_tree.subscribe(:remove_tag) do |tag|
1182
+ @fuzzer_tags.delete(tag)
1183
+ @requestEditor.removeTag(tag.name)
1184
+ @requestEditor.highlightTags()
1185
+ end
1186
+
1187
+ @fuzzer_tree.subscribe(:new_filter) do |filter|
1188
+ @filters.push filter
1189
+ end
1190
+
1191
+ @fuzzer_tree.subscribe(:remove_filter) do |filter|
1192
+ @filters.delete(filter)
1193
+ end
1194
+
1195
+ FXTabItem.new(@tabBook, "Results", nil)
1196
+ rframe = FXVerticalFrame.new(@tabBook, :opts => LAYOUT_FILL_X|LAYOUT_FILL_Y|FRAME_RAISED)
1197
+ frame = FXVerticalFrame.new(rframe, :opts => LAYOUT_FILL_X|LAYOUT_FILL_Y|FRAME_SUNKEN, :padding => 0)
1198
+ @matchTable = FXTable.new(frame, :opts => TABLE_COL_SIZABLE|TABLE_ROW_SIZABLE|LAYOUT_FILL_X|LAYOUT_FILL_Y|FRAME_SUNKEN|TABLE_READONLY|LAYOUT_SIDE_TOP, :padding => 2)
1199
+ initTable(@matchTable)
1200
+
1201
+ btnframe = FXHorizontalFrame.new(rframe, :opts => LAYOUT_FILL_X|FRAME_SUNKEN)
1202
+ button = FXButton.new(btnframe, "Save Matches", nil, nil, 0, FRAME_RAISED|FRAME_THICK)
1203
+
1204
+ button.connect(SEL_COMMAND, method(:saveMatches))
1205
+
1206
+ FXTabItem.new(@tabBook, "Statistics", nil)
1207
+ statframe = FXVerticalFrame.new(@tabBook, :opts => LAYOUT_FILL_X|LAYOUT_FILL_Y|FRAME_RAISED)
1208
+ @stat_viewer = StatisticsFrame.new(statframe, :opts => LAYOUT_FILL_X|LAYOUT_FILL_Y|FRAME_RAISED, :padding => 0)
1209
+ FXVerticalFrame.new(statframe, :opts => LAYOUT_FILL_X|LAYOUT_FIX_HEIGHT|FRAME_NONE, :height => 250)
1210
+
1211
+ log_frame_header = FXHorizontalFrame.new(log_frame, :opts => LAYOUT_FILL_X)
1212
+ FXLabel.new(log_frame_header, "Logs:" )
1213
+ log_text_frame = FXVerticalFrame.new(log_frame, LAYOUT_FILL_X|LAYOUT_FILL_Y|FRAME_SUNKEN|FRAME_GROOVE, :padding=>0)
1214
+ @log_viewer = LogViewer.new(log_text_frame, :opts => LAYOUT_FILL_X|LAYOUT_FILL_Y)
1215
+
1216
+ end
1217
+ end
1218
+
1219
+ class FuzzerTree < FXTreeList
1220
+ attr :fuzzTags
1221
+ include Watobo::Gui::Icons
1222
+
1223
+ def setup_listeners
1224
+ @event_dispatcher_listeners = {}
1225
+
1226
+ end
1227
+
1228
+ def subscribe(event, &callback)
1229
+ (@event_dispatcher_listeners[event] ||= []) << callback
1230
+ end
1231
+
1232
+ def notify(event, *args)
1233
+ if @event_dispatcher_listeners[event]
1234
+ @event_dispatcher_listeners[event].each do |m|
1235
+ m.call(*args) if m.respond_to? :call
1236
+ end
1237
+ end
1238
+ end
1239
+
1240
+
1241
+ def addFilterItem(filter)
1242
+
1243
+ filter_root = self.findItem("Filters", nil, SEARCH_FORWARD|SEARCH_IGNORECASE)
1244
+
1245
+ filter_item = self.appendItem(filter_root, "Filter: #{filter.filter_type}")
1246
+ self.setItemData(filter_item, filter)
1247
+ self.appendItem(filter_item, filter.info)
1248
+ end
1249
+
1250
+
1251
+ def addTag()
1252
+ dlg = Watobo::Gui::CreateFuzzerDlg.new(self)
1253
+ if dlg.execute != 0 then
1254
+ tag = dlg.tag
1255
+ tag_is_valid = true
1256
+ @fuzzTags.each do |f|
1257
+ tag_is_valid = false if f.name == tag
1258
+ end
1259
+ if tag_is_valid and tag != ""
1260
+ new_fuzz_tag = FuzzerTag.new(tag)
1261
+ @fuzzTags.push new_fuzz_tag
1262
+ notify(:new_tag, new_fuzz_tag)
1263
+ refresh()
1264
+ else
1265
+ puts "!!! Could not create empty/used tag !!!"
1266
+ end
1267
+ end
1268
+ end
1269
+
1270
+ def addTagItem(tag)
1271
+
1272
+ tag_root = self.findItem("Tags", nil, SEARCH_FORWARD|SEARCH_IGNORECASE)
1273
+
1274
+ item = self.findItem(tag.name, tag_root, SEARCH_FORWARD|SEARCH_IGNORECASE)
1275
+
1276
+ return nil if item
1277
+ tag_item = self.appendItem(tag_root, "Tag: #{tag.name}")
1278
+ self.setItemData(tag_item, tag)
1279
+
1280
+ # item = self.appendItem(fuzz_item, "Generator", ICON_VULN, ICON_VULN)
1281
+ # self.setItemData(item, :generator)
1282
+
1283
+ tag.generators.each do |gen|
1284
+ addGeneratorItem(tag_item, gen)
1285
+ end
1286
+
1287
+
1288
+ end
1289
+
1290
+ def initTree()
1291
+ fuzz_item = self.appendItem(nil, "Tags", ICON_FUZZ_TAG, ICON_FUZZ_TAG)
1292
+ self.setItemData(fuzz_item, :tags)
1293
+
1294
+ item = self.appendItem(nil, "Filters", ICON_FUZZ_FILTER, ICON_FUZZ_FILTER)
1295
+ self.setItemData(item, :filter)
1296
+
1297
+ #item = self.appendItem(nil, "Collector", ICON_INFO, ICON_INFO)
1298
+ #self.setItemData(item, :collector)
1299
+ end
1300
+
1301
+ def addAction(generator)
1302
+ dlg = Watobo::Gui::CreateActionDlg.new(self)
1303
+ if dlg.execute != 0 then
1304
+ puts "new action"
1305
+ new_action = dlg.getAction()
1306
+ generator.addAction(new_action) if new_action
1307
+ refresh()
1308
+ end
1309
+ end
1310
+
1311
+ def addGeneratorItem(tag_item, generator)
1312
+ begin
1313
+ item = self.appendItem(tag_item, generator.genType, ICON_FUZZ_GENERATOR, ICON_FUZZ_GENERATOR)
1314
+ self.setItemData(item, generator)
1315
+ self.appendItem(item, generator.info)
1316
+
1317
+ generator.actions.each do |a|
1318
+ action_item = self.appendItem(item, a.action_type, ICON_FUZZER, ICON_FUZZER)
1319
+ self.setItemData(action_item, a)
1320
+ self.appendItem(action_item, a.info)
1321
+ end
1322
+ self.expandTree(item)
1323
+ rescue => bang
1324
+ puts "!ERROR: could not add GeneratorItem"
1325
+ puts bang
1326
+ end
1327
+ end
1328
+
1329
+ def expandSubtree(item=nil)
1330
+ if item
1331
+ self.expandTree(item)
1332
+ item.each do |child|
1333
+ expandSubtree(child)
1334
+ end
1335
+ end
1336
+ end
1337
+
1338
+ def expandSettings(item=nil)
1339
+ self.each do |root_item|
1340
+ expandSubtree(root_item)
1341
+ end
1342
+ end
1343
+
1344
+ def refresh()
1345
+ self.clearItems()
1346
+ initTree()
1347
+ @fuzzTags.each do |f|
1348
+ addTagItem(f)
1349
+ end
1350
+
1351
+ @filters.each do |f|
1352
+ addFilterItem(f)
1353
+ end
1354
+
1355
+ expandSettings()
1356
+ end
1357
+
1358
+ def initialize(owner, project)
1359
+ super(owner, :opts => LAYOUT_FILL_X|LAYOUT_FILL_Y|LAYOUT_TOP|LAYOUT_RIGHT|TREELIST_SHOWS_LINES|TREELIST_SHOWS_BOXES|TREELIST_ROOT_BOXES|TREELIST_EXTENDEDSELECT)
1360
+ # f = Fuzzer.new("FUZZ")
1361
+ @fuzzTags = []
1362
+ @project = project
1363
+ @filters = []
1364
+
1365
+ setup_listeners()
1366
+
1367
+ refresh()
1368
+
1369
+
1370
+ self.connect(SEL_COMMAND) do |sender, sel, item|
1371
+ if self.itemLeaf?(item)
1372
+ getApp().beginWaitCursor do
1373
+ begin
1374
+ if item.data
1375
+ if item.data.is_a? Finding
1376
+ @interface.show_vuln(item.data)
1377
+ end
1378
+ end
1379
+ rescue => bang
1380
+ puts "!!! Error: could not show selected finding"
1381
+ puts bang
1382
+ end
1383
+ end
1384
+ elsif item.data == :title then
1385
+ @interface.show_vuln(item.first.data) if item.first.data
1386
+ end
1387
+ end
1388
+
1389
+ self.connect(SEL_DOUBLECLICKED) do |sender, sel, item|
1390
+ if self.itemLeaf?(item)
1391
+ begin
1392
+ if item.data and item.data.is_a? Symbol then
1393
+ case item.data
1394
+ when :tags
1395
+ addTag()
1396
+ when :filter
1397
+ dlg = Watobo::Gui::CreateFilterDlg.new(self, @project)
1398
+ if dlg.execute != 0 then
1399
+ f = dlg.filter
1400
+ notify(:new_filter, f)
1401
+ @filters.push f
1402
+ refresh()
1403
+ end
1404
+ end
1405
+ elsif item.data.respond_to? :is_tag?
1406
+ dlg = Watobo::Gui::CreateGeneratorDlg.new(self)
1407
+ if dlg.execute != 0 then
1408
+ # puts "new generator"
1409
+ fuzzer = item.data
1410
+ gen = dlg.getGenerator(fuzzer)
1411
+ fuzzer.addGenerator(gen)
1412
+ refresh()
1413
+ end
1414
+ elsif item.data.respond_to? :is_generator?
1415
+ gen = item.data
1416
+ addAction(gen)
1417
+
1418
+ else
1419
+ puts "Unknown Object: #{item.data.class}"
1420
+ end
1421
+
1422
+ rescue => bang
1423
+ puts "!!! Error: could not show selected finding"
1424
+ puts bang
1425
+ end
1426
+ end
1427
+ end
1428
+
1429
+ self.connect(SEL_RIGHTBUTTONRELEASE) do |sender, sel, event|
1430
+ unless event.moved?
1431
+ item = sender.getItemAt(event.win_x, event.win_y)
1432
+
1433
+ FXMenuPane.new(self) do |menu_pane|
1434
+ data = item ? self.getItemData(item) : nil
1435
+ if data.is_a? Symbol
1436
+ case data
1437
+ when :tags
1438
+
1439
+ m = FXMenuCommand.new(menu_pane, "Add Tag.." )
1440
+ m.connect(SEL_COMMAND) {
1441
+ addTag()
1442
+ }
1443
+
1444
+ when :filter
1445
+
1446
+ m = FXMenuCommand.new(menu_pane, "Add Filter.." )
1447
+ m.connect(SEL_COMMAND) {
1448
+ dlg = Watobo::Gui::CreateFilterDlg.new(self, @project)
1449
+ if dlg.execute != 0 then
1450
+ f = dlg.filter
1451
+ notify(:new_filter, f)
1452
+ @filters.push f
1453
+ refresh()
1454
+ end
1455
+ }
1456
+ end
1457
+ elsif data.respond_to? :is_tag?
1458
+ m = FXMenuCommand.new(menu_pane, "Add Generator.." )
1459
+ m.connect(SEL_COMMAND) {
1460
+ dlg = Watobo::Gui::CreateGeneratorDlg.new(self)
1461
+ if dlg.execute != 0 then
1462
+ # puts "new generator"
1463
+ fuzzer = data
1464
+ gen = dlg.getGenerator(fuzzer)
1465
+ fuzzer.addGenerator(gen)
1466
+ refresh()
1467
+ end
1468
+ }
1469
+ m = FXMenuCommand.new(menu_pane, "Remove Tag" )
1470
+ m.connect(SEL_COMMAND) {
1471
+ # puts "Removing Tag [#{data.name}]"
1472
+ if @fuzzTags.include?(data)
1473
+ # puts "...found tag"
1474
+ @fuzzTags.delete(data)
1475
+ end
1476
+ notify(:remove_tag, data)
1477
+ refresh()
1478
+ }
1479
+ elsif data.respond_to? :is_generator?
1480
+ m = FXMenuCommand.new(menu_pane, "Add Action.." )
1481
+ m.connect(SEL_COMMAND) {
1482
+ gen = self.getItemData(item)
1483
+ addAction(gen)
1484
+ }
1485
+ m = FXMenuCommand.new(menu_pane, "Remove Generator" )
1486
+ m.connect(SEL_COMMAND) {
1487
+ tag = self.getItemData(item.parent)
1488
+ tag.deleteGenerator(data)
1489
+ refresh()
1490
+ }
1491
+ elsif data.respond_to? :is_action?
1492
+ m = FXMenuCommand.new(menu_pane, "Remove Action" )
1493
+ m.connect(SEL_COMMAND) {
1494
+ gen = self.getItemData(item.parent)
1495
+ gen.removeAction(data)
1496
+ refresh()
1497
+ }
1498
+ elsif data.respond_to? :is_filter?
1499
+ m = FXMenuCommand.new(menu_pane, "Remove Filter" )
1500
+ m.connect(SEL_COMMAND) {
1501
+ @filters.delete(data)
1502
+ notify(:remove_filter, data)
1503
+ refresh()
1504
+ }
1505
+ else
1506
+ puts "Unknown Object: #{data.class}"
1507
+ end
1508
+
1509
+ menu_pane.create
1510
+ menu_pane.popup(nil, event.root_x, event.root_y)
1511
+
1512
+
1513
+ app.runModalWhileShown(menu_pane)
1514
+ end
1515
+ end
1516
+ end
1517
+ end
1518
+ end
1519
+ # namespace end
1520
+ end
1521
+
1522
+ end