watobo 0.9.8.677

Sign up to get free protection for your applications and to get access to all the features.
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