├── .gitignore
├── LICENSE
├── README.md
├── __init__.py
├── _gtkentry.py
├── handler_api.py
├── handlers.py
├── layout.py
├── model.py
├── opts_wx.py
├── profiler.sh
├── screenshots
├── sqlmap-wx1.png
├── sqlmap-wx2.png
├── sqlmap-wx3.png
├── sqlmap-wx4.png
├── sqlmap-wx5.png
├── sqlmap-wx6.png
├── sqlmap-wx7.png
├── sqlmap-wx8.png
└── sqlmap-wx9.png
├── session.py
├── sqlmap_wx.py
├── static
└── title.ico
├── tamper
└── tamper_list
├── tooltips.py
└── widgets.py
/.gitignore:
--------------------------------------------------------------------------------
1 | # Byte-compiled / optimized / DLL files
2 | __pycache__/
3 | *.py[cod]
4 | *$py.class
5 |
6 | # C extensions
7 | *.so
8 |
9 | # Distribution / packaging
10 | .Python
11 | build/
12 | develop-eggs/
13 | dist/
14 | downloads/
15 | eggs/
16 | .eggs/
17 | lib/
18 | lib64/
19 | parts/
20 | sdist/
21 | var/
22 | wheels/
23 | pip-wheel-metadata/
24 | share/python-wheels/
25 | *.egg-info/
26 | .installed.cfg
27 | *.egg
28 | MANIFEST
29 |
30 | # PyInstaller
31 | # Usually these files are written by a python script from a template
32 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
33 | *.manifest
34 | *.spec
35 |
36 | # Installer logs
37 | pip-log.txt
38 | pip-delete-this-directory.txt
39 |
40 | # Unit test / coverage reports
41 | htmlcov/
42 | .tox/
43 | .nox/
44 | .coverage
45 | .coverage.*
46 | .cache
47 | nosetests.xml
48 | coverage.xml
49 | *.cover
50 | *.py,cover
51 | .hypothesis/
52 | .pytest_cache/
53 |
54 | # Translations
55 | *.pot
56 |
57 | # Django stuff:
58 | *.log
59 | local_settings.py
60 | db.sqlite3
61 | db.sqlite3-journal
62 |
63 | # Flask stuff:
64 | instance/
65 | .webassets-cache
66 |
67 | # Scrapy stuff:
68 | .scrapy
69 |
70 | # Sphinx documentation
71 | docs/_build/
72 |
73 | # PyBuilder
74 | target/
75 |
76 | # Jupyter Notebook
77 | .ipynb_checkpoints
78 |
79 | # IPython
80 | profile_default/
81 | ipython_config.py
82 |
83 | # pyenv
84 | .python-version
85 |
86 | # pipenv
87 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
88 | # However, in case of collaboration, if having platform-specific dependencies or dependencies
89 | # having no cross-platform support, pipenv may install dependencies that don't work, or not
90 | # install all needed dependencies.
91 | #Pipfile.lock
92 |
93 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow
94 | __pypackages__/
95 |
96 | # Celery stuff
97 | celerybeat-schedule
98 | celerybeat.pid
99 |
100 | # SageMath parsed files
101 | *.sage.py
102 |
103 | # Environments
104 | .env
105 | .venv
106 | env/
107 | venv/
108 | ENV/
109 | env.bak/
110 | venv.bak/
111 |
112 | # Spyder project settings
113 | .spyderproject
114 | .spyproject
115 |
116 | # Rope project settings
117 | .ropeproject
118 |
119 | # mkdocs documentation
120 | /site
121 |
122 | # mypy
123 | .mypy_cache/
124 | .dmypy.json
125 | dmypy.json
126 |
127 | # Pyre type checker
128 | .pyre/
129 |
130 | *.lprof
131 | *.tmp
132 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | GNU GENERAL PUBLIC LICENSE
2 | Version 3, 29 June 2007
3 |
4 | Copyright (C) 2007 Free Software Foundation, Inc.
5 | Everyone is permitted to copy and distribute verbatim copies
6 | of this license document, but changing it is not allowed.
7 |
8 | Preamble
9 |
10 | The GNU General Public License is a free, copyleft license for
11 | software and other kinds of works.
12 |
13 | The licenses for most software and other practical works are designed
14 | to take away your freedom to share and change the works. By contrast,
15 | the GNU General Public License is intended to guarantee your freedom to
16 | share and change all versions of a program--to make sure it remains free
17 | software for all its users. We, the Free Software Foundation, use the
18 | GNU General Public License for most of our software; it applies also to
19 | any other work released this way by its authors. You can apply it to
20 | your programs, too.
21 |
22 | When we speak of free software, we are referring to freedom, not
23 | price. Our General Public Licenses are designed to make sure that you
24 | have the freedom to distribute copies of free software (and charge for
25 | them if you wish), that you receive source code or can get it if you
26 | want it, that you can change the software or use pieces of it in new
27 | free programs, and that you know you can do these things.
28 |
29 | To protect your rights, we need to prevent others from denying you
30 | these rights or asking you to surrender the rights. Therefore, you have
31 | certain responsibilities if you distribute copies of the software, or if
32 | you modify it: responsibilities to respect the freedom of others.
33 |
34 | For example, if you distribute copies of such a program, whether
35 | gratis or for a fee, you must pass on to the recipients the same
36 | freedoms that you received. You must make sure that they, too, receive
37 | or can get the source code. And you must show them these terms so they
38 | know their rights.
39 |
40 | Developers that use the GNU GPL protect your rights with two steps:
41 | (1) assert copyright on the software, and (2) offer you this License
42 | giving you legal permission to copy, distribute and/or modify it.
43 |
44 | For the developers' and authors' protection, the GPL clearly explains
45 | that there is no warranty for this free software. For both users' and
46 | authors' sake, the GPL requires that modified versions be marked as
47 | changed, so that their problems will not be attributed erroneously to
48 | authors of previous versions.
49 |
50 | Some devices are designed to deny users access to install or run
51 | modified versions of the software inside them, although the manufacturer
52 | can do so. This is fundamentally incompatible with the aim of
53 | protecting users' freedom to change the software. The systematic
54 | pattern of such abuse occurs in the area of products for individuals to
55 | use, which is precisely where it is most unacceptable. Therefore, we
56 | have designed this version of the GPL to prohibit the practice for those
57 | products. If such problems arise substantially in other domains, we
58 | stand ready to extend this provision to those domains in future versions
59 | of the GPL, as needed to protect the freedom of users.
60 |
61 | Finally, every program is threatened constantly by software patents.
62 | States should not allow patents to restrict development and use of
63 | software on general-purpose computers, but in those that do, we wish to
64 | avoid the special danger that patents applied to a free program could
65 | make it effectively proprietary. To prevent this, the GPL assures that
66 | patents cannot be used to render the program non-free.
67 |
68 | The precise terms and conditions for copying, distribution and
69 | modification follow.
70 |
71 | TERMS AND CONDITIONS
72 |
73 | 0. Definitions.
74 |
75 | "This License" refers to version 3 of the GNU General Public License.
76 |
77 | "Copyright" also means copyright-like laws that apply to other kinds of
78 | works, such as semiconductor masks.
79 |
80 | "The Program" refers to any copyrightable work licensed under this
81 | License. Each licensee is addressed as "you". "Licensees" and
82 | "recipients" may be individuals or organizations.
83 |
84 | To "modify" a work means to copy from or adapt all or part of the work
85 | in a fashion requiring copyright permission, other than the making of an
86 | exact copy. The resulting work is called a "modified version" of the
87 | earlier work or a work "based on" the earlier work.
88 |
89 | A "covered work" means either the unmodified Program or a work based
90 | on the Program.
91 |
92 | To "propagate" a work means to do anything with it that, without
93 | permission, would make you directly or secondarily liable for
94 | infringement under applicable copyright law, except executing it on a
95 | computer or modifying a private copy. Propagation includes copying,
96 | distribution (with or without modification), making available to the
97 | public, and in some countries other activities as well.
98 |
99 | To "convey" a work means any kind of propagation that enables other
100 | parties to make or receive copies. Mere interaction with a user through
101 | a computer network, with no transfer of a copy, is not conveying.
102 |
103 | An interactive user interface displays "Appropriate Legal Notices"
104 | to the extent that it includes a convenient and prominently visible
105 | feature that (1) displays an appropriate copyright notice, and (2)
106 | tells the user that there is no warranty for the work (except to the
107 | extent that warranties are provided), that licensees may convey the
108 | work under this License, and how to view a copy of this License. If
109 | the interface presents a list of user commands or options, such as a
110 | menu, a prominent item in the list meets this criterion.
111 |
112 | 1. Source Code.
113 |
114 | The "source code" for a work means the preferred form of the work
115 | for making modifications to it. "Object code" means any non-source
116 | form of a work.
117 |
118 | A "Standard Interface" means an interface that either is an official
119 | standard defined by a recognized standards body, or, in the case of
120 | interfaces specified for a particular programming language, one that
121 | is widely used among developers working in that language.
122 |
123 | The "System Libraries" of an executable work include anything, other
124 | than the work as a whole, that (a) is included in the normal form of
125 | packaging a Major Component, but which is not part of that Major
126 | Component, and (b) serves only to enable use of the work with that
127 | Major Component, or to implement a Standard Interface for which an
128 | implementation is available to the public in source code form. A
129 | "Major Component", in this context, means a major essential component
130 | (kernel, window system, and so on) of the specific operating system
131 | (if any) on which the executable work runs, or a compiler used to
132 | produce the work, or an object code interpreter used to run it.
133 |
134 | The "Corresponding Source" for a work in object code form means all
135 | the source code needed to generate, install, and (for an executable
136 | work) run the object code and to modify the work, including scripts to
137 | control those activities. However, it does not include the work's
138 | System Libraries, or general-purpose tools or generally available free
139 | programs which are used unmodified in performing those activities but
140 | which are not part of the work. For example, Corresponding Source
141 | includes interface definition files associated with source files for
142 | the work, and the source code for shared libraries and dynamically
143 | linked subprograms that the work is specifically designed to require,
144 | such as by intimate data communication or control flow between those
145 | subprograms and other parts of the work.
146 |
147 | The Corresponding Source need not include anything that users
148 | can regenerate automatically from other parts of the Corresponding
149 | Source.
150 |
151 | The Corresponding Source for a work in source code form is that
152 | same work.
153 |
154 | 2. Basic Permissions.
155 |
156 | All rights granted under this License are granted for the term of
157 | copyright on the Program, and are irrevocable provided the stated
158 | conditions are met. This License explicitly affirms your unlimited
159 | permission to run the unmodified Program. The output from running a
160 | covered work is covered by this License only if the output, given its
161 | content, constitutes a covered work. This License acknowledges your
162 | rights of fair use or other equivalent, as provided by copyright law.
163 |
164 | You may make, run and propagate covered works that you do not
165 | convey, without conditions so long as your license otherwise remains
166 | in force. You may convey covered works to others for the sole purpose
167 | of having them make modifications exclusively for you, or provide you
168 | with facilities for running those works, provided that you comply with
169 | the terms of this License in conveying all material for which you do
170 | not control copyright. Those thus making or running the covered works
171 | for you must do so exclusively on your behalf, under your direction
172 | and control, on terms that prohibit them from making any copies of
173 | your copyrighted material outside their relationship with you.
174 |
175 | Conveying under any other circumstances is permitted solely under
176 | the conditions stated below. Sublicensing is not allowed; section 10
177 | makes it unnecessary.
178 |
179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
180 |
181 | No covered work shall be deemed part of an effective technological
182 | measure under any applicable law fulfilling obligations under article
183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or
184 | similar laws prohibiting or restricting circumvention of such
185 | measures.
186 |
187 | When you convey a covered work, you waive any legal power to forbid
188 | circumvention of technological measures to the extent such circumvention
189 | is effected by exercising rights under this License with respect to
190 | the covered work, and you disclaim any intention to limit operation or
191 | modification of the work as a means of enforcing, against the work's
192 | users, your or third parties' legal rights to forbid circumvention of
193 | technological measures.
194 |
195 | 4. Conveying Verbatim Copies.
196 |
197 | You may convey verbatim copies of the Program's source code as you
198 | receive it, in any medium, provided that you conspicuously and
199 | appropriately publish on each copy an appropriate copyright notice;
200 | keep intact all notices stating that this License and any
201 | non-permissive terms added in accord with section 7 apply to the code;
202 | keep intact all notices of the absence of any warranty; and give all
203 | recipients a copy of this License along with the Program.
204 |
205 | You may charge any price or no price for each copy that you convey,
206 | and you may offer support or warranty protection for a fee.
207 |
208 | 5. Conveying Modified Source Versions.
209 |
210 | You may convey a work based on the Program, or the modifications to
211 | produce it from the Program, in the form of source code under the
212 | terms of section 4, provided that you also meet all of these conditions:
213 |
214 | a) The work must carry prominent notices stating that you modified
215 | it, and giving a relevant date.
216 |
217 | b) The work must carry prominent notices stating that it is
218 | released under this License and any conditions added under section
219 | 7. This requirement modifies the requirement in section 4 to
220 | "keep intact all notices".
221 |
222 | c) You must license the entire work, as a whole, under this
223 | License to anyone who comes into possession of a copy. This
224 | License will therefore apply, along with any applicable section 7
225 | additional terms, to the whole of the work, and all its parts,
226 | regardless of how they are packaged. This License gives no
227 | permission to license the work in any other way, but it does not
228 | invalidate such permission if you have separately received it.
229 |
230 | d) If the work has interactive user interfaces, each must display
231 | Appropriate Legal Notices; however, if the Program has interactive
232 | interfaces that do not display Appropriate Legal Notices, your
233 | work need not make them do so.
234 |
235 | A compilation of a covered work with other separate and independent
236 | works, which are not by their nature extensions of the covered work,
237 | and which are not combined with it such as to form a larger program,
238 | in or on a volume of a storage or distribution medium, is called an
239 | "aggregate" if the compilation and its resulting copyright are not
240 | used to limit the access or legal rights of the compilation's users
241 | beyond what the individual works permit. Inclusion of a covered work
242 | in an aggregate does not cause this License to apply to the other
243 | parts of the aggregate.
244 |
245 | 6. Conveying Non-Source Forms.
246 |
247 | You may convey a covered work in object code form under the terms
248 | of sections 4 and 5, provided that you also convey the
249 | machine-readable Corresponding Source under the terms of this License,
250 | in one of these ways:
251 |
252 | a) Convey the object code in, or embodied in, a physical product
253 | (including a physical distribution medium), accompanied by the
254 | Corresponding Source fixed on a durable physical medium
255 | customarily used for software interchange.
256 |
257 | b) Convey the object code in, or embodied in, a physical product
258 | (including a physical distribution medium), accompanied by a
259 | written offer, valid for at least three years and valid for as
260 | long as you offer spare parts or customer support for that product
261 | model, to give anyone who possesses the object code either (1) a
262 | copy of the Corresponding Source for all the software in the
263 | product that is covered by this License, on a durable physical
264 | medium customarily used for software interchange, for a price no
265 | more than your reasonable cost of physically performing this
266 | conveying of source, or (2) access to copy the
267 | Corresponding Source from a network server at no charge.
268 |
269 | c) Convey individual copies of the object code with a copy of the
270 | written offer to provide the Corresponding Source. This
271 | alternative is allowed only occasionally and noncommercially, and
272 | only if you received the object code with such an offer, in accord
273 | with subsection 6b.
274 |
275 | d) Convey the object code by offering access from a designated
276 | place (gratis or for a charge), and offer equivalent access to the
277 | Corresponding Source in the same way through the same place at no
278 | further charge. You need not require recipients to copy the
279 | Corresponding Source along with the object code. If the place to
280 | copy the object code is a network server, the Corresponding Source
281 | may be on a different server (operated by you or a third party)
282 | that supports equivalent copying facilities, provided you maintain
283 | clear directions next to the object code saying where to find the
284 | Corresponding Source. Regardless of what server hosts the
285 | Corresponding Source, you remain obligated to ensure that it is
286 | available for as long as needed to satisfy these requirements.
287 |
288 | e) Convey the object code using peer-to-peer transmission, provided
289 | you inform other peers where the object code and Corresponding
290 | Source of the work are being offered to the general public at no
291 | charge under subsection 6d.
292 |
293 | A separable portion of the object code, whose source code is excluded
294 | from the Corresponding Source as a System Library, need not be
295 | included in conveying the object code work.
296 |
297 | A "User Product" is either (1) a "consumer product", which means any
298 | tangible personal property which is normally used for personal, family,
299 | or household purposes, or (2) anything designed or sold for incorporation
300 | into a dwelling. In determining whether a product is a consumer product,
301 | doubtful cases shall be resolved in favor of coverage. For a particular
302 | product received by a particular user, "normally used" refers to a
303 | typical or common use of that class of product, regardless of the status
304 | of the particular user or of the way in which the particular user
305 | actually uses, or expects or is expected to use, the product. A product
306 | is a consumer product regardless of whether the product has substantial
307 | commercial, industrial or non-consumer uses, unless such uses represent
308 | the only significant mode of use of the product.
309 |
310 | "Installation Information" for a User Product means any methods,
311 | procedures, authorization keys, or other information required to install
312 | and execute modified versions of a covered work in that User Product from
313 | a modified version of its Corresponding Source. The information must
314 | suffice to ensure that the continued functioning of the modified object
315 | code is in no case prevented or interfered with solely because
316 | modification has been made.
317 |
318 | If you convey an object code work under this section in, or with, or
319 | specifically for use in, a User Product, and the conveying occurs as
320 | part of a transaction in which the right of possession and use of the
321 | User Product is transferred to the recipient in perpetuity or for a
322 | fixed term (regardless of how the transaction is characterized), the
323 | Corresponding Source conveyed under this section must be accompanied
324 | by the Installation Information. But this requirement does not apply
325 | if neither you nor any third party retains the ability to install
326 | modified object code on the User Product (for example, the work has
327 | been installed in ROM).
328 |
329 | The requirement to provide Installation Information does not include a
330 | requirement to continue to provide support service, warranty, or updates
331 | for a work that has been modified or installed by the recipient, or for
332 | the User Product in which it has been modified or installed. Access to a
333 | network may be denied when the modification itself materially and
334 | adversely affects the operation of the network or violates the rules and
335 | protocols for communication across the network.
336 |
337 | Corresponding Source conveyed, and Installation Information provided,
338 | in accord with this section must be in a format that is publicly
339 | documented (and with an implementation available to the public in
340 | source code form), and must require no special password or key for
341 | unpacking, reading or copying.
342 |
343 | 7. Additional Terms.
344 |
345 | "Additional permissions" are terms that supplement the terms of this
346 | License by making exceptions from one or more of its conditions.
347 | Additional permissions that are applicable to the entire Program shall
348 | be treated as though they were included in this License, to the extent
349 | that they are valid under applicable law. If additional permissions
350 | apply only to part of the Program, that part may be used separately
351 | under those permissions, but the entire Program remains governed by
352 | this License without regard to the additional permissions.
353 |
354 | When you convey a copy of a covered work, you may at your option
355 | remove any additional permissions from that copy, or from any part of
356 | it. (Additional permissions may be written to require their own
357 | removal in certain cases when you modify the work.) You may place
358 | additional permissions on material, added by you to a covered work,
359 | for which you have or can give appropriate copyright permission.
360 |
361 | Notwithstanding any other provision of this License, for material you
362 | add to a covered work, you may (if authorized by the copyright holders of
363 | that material) supplement the terms of this License with terms:
364 |
365 | a) Disclaiming warranty or limiting liability differently from the
366 | terms of sections 15 and 16 of this License; or
367 |
368 | b) Requiring preservation of specified reasonable legal notices or
369 | author attributions in that material or in the Appropriate Legal
370 | Notices displayed by works containing it; or
371 |
372 | c) Prohibiting misrepresentation of the origin of that material, or
373 | requiring that modified versions of such material be marked in
374 | reasonable ways as different from the original version; or
375 |
376 | d) Limiting the use for publicity purposes of names of licensors or
377 | authors of the material; or
378 |
379 | e) Declining to grant rights under trademark law for use of some
380 | trade names, trademarks, or service marks; or
381 |
382 | f) Requiring indemnification of licensors and authors of that
383 | material by anyone who conveys the material (or modified versions of
384 | it) with contractual assumptions of liability to the recipient, for
385 | any liability that these contractual assumptions directly impose on
386 | those licensors and authors.
387 |
388 | All other non-permissive additional terms are considered "further
389 | restrictions" within the meaning of section 10. If the Program as you
390 | received it, or any part of it, contains a notice stating that it is
391 | governed by this License along with a term that is a further
392 | restriction, you may remove that term. If a license document contains
393 | a further restriction but permits relicensing or conveying under this
394 | License, you may add to a covered work material governed by the terms
395 | of that license document, provided that the further restriction does
396 | not survive such relicensing or conveying.
397 |
398 | If you add terms to a covered work in accord with this section, you
399 | must place, in the relevant source files, a statement of the
400 | additional terms that apply to those files, or a notice indicating
401 | where to find the applicable terms.
402 |
403 | Additional terms, permissive or non-permissive, may be stated in the
404 | form of a separately written license, or stated as exceptions;
405 | the above requirements apply either way.
406 |
407 | 8. Termination.
408 |
409 | You may not propagate or modify a covered work except as expressly
410 | provided under this License. Any attempt otherwise to propagate or
411 | modify it is void, and will automatically terminate your rights under
412 | this License (including any patent licenses granted under the third
413 | paragraph of section 11).
414 |
415 | However, if you cease all violation of this License, then your
416 | license from a particular copyright holder is reinstated (a)
417 | provisionally, unless and until the copyright holder explicitly and
418 | finally terminates your license, and (b) permanently, if the copyright
419 | holder fails to notify you of the violation by some reasonable means
420 | prior to 60 days after the cessation.
421 |
422 | Moreover, your license from a particular copyright holder is
423 | reinstated permanently if the copyright holder notifies you of the
424 | violation by some reasonable means, this is the first time you have
425 | received notice of violation of this License (for any work) from that
426 | copyright holder, and you cure the violation prior to 30 days after
427 | your receipt of the notice.
428 |
429 | Termination of your rights under this section does not terminate the
430 | licenses of parties who have received copies or rights from you under
431 | this License. If your rights have been terminated and not permanently
432 | reinstated, you do not qualify to receive new licenses for the same
433 | material under section 10.
434 |
435 | 9. Acceptance Not Required for Having Copies.
436 |
437 | You are not required to accept this License in order to receive or
438 | run a copy of the Program. Ancillary propagation of a covered work
439 | occurring solely as a consequence of using peer-to-peer transmission
440 | to receive a copy likewise does not require acceptance. However,
441 | nothing other than this License grants you permission to propagate or
442 | modify any covered work. These actions infringe copyright if you do
443 | not accept this License. Therefore, by modifying or propagating a
444 | covered work, you indicate your acceptance of this License to do so.
445 |
446 | 10. Automatic Licensing of Downstream Recipients.
447 |
448 | Each time you convey a covered work, the recipient automatically
449 | receives a license from the original licensors, to run, modify and
450 | propagate that work, subject to this License. You are not responsible
451 | for enforcing compliance by third parties with this License.
452 |
453 | An "entity transaction" is a transaction transferring control of an
454 | organization, or substantially all assets of one, or subdividing an
455 | organization, or merging organizations. If propagation of a covered
456 | work results from an entity transaction, each party to that
457 | transaction who receives a copy of the work also receives whatever
458 | licenses to the work the party's predecessor in interest had or could
459 | give under the previous paragraph, plus a right to possession of the
460 | Corresponding Source of the work from the predecessor in interest, if
461 | the predecessor has it or can get it with reasonable efforts.
462 |
463 | You may not impose any further restrictions on the exercise of the
464 | rights granted or affirmed under this License. For example, you may
465 | not impose a license fee, royalty, or other charge for exercise of
466 | rights granted under this License, and you may not initiate litigation
467 | (including a cross-claim or counterclaim in a lawsuit) alleging that
468 | any patent claim is infringed by making, using, selling, offering for
469 | sale, or importing the Program or any portion of it.
470 |
471 | 11. Patents.
472 |
473 | A "contributor" is a copyright holder who authorizes use under this
474 | License of the Program or a work on which the Program is based. The
475 | work thus licensed is called the contributor's "contributor version".
476 |
477 | A contributor's "essential patent claims" are all patent claims
478 | owned or controlled by the contributor, whether already acquired or
479 | hereafter acquired, that would be infringed by some manner, permitted
480 | by this License, of making, using, or selling its contributor version,
481 | but do not include claims that would be infringed only as a
482 | consequence of further modification of the contributor version. For
483 | purposes of this definition, "control" includes the right to grant
484 | patent sublicenses in a manner consistent with the requirements of
485 | this License.
486 |
487 | Each contributor grants you a non-exclusive, worldwide, royalty-free
488 | patent license under the contributor's essential patent claims, to
489 | make, use, sell, offer for sale, import and otherwise run, modify and
490 | propagate the contents of its contributor version.
491 |
492 | In the following three paragraphs, a "patent license" is any express
493 | agreement or commitment, however denominated, not to enforce a patent
494 | (such as an express permission to practice a patent or covenant not to
495 | sue for patent infringement). To "grant" such a patent license to a
496 | party means to make such an agreement or commitment not to enforce a
497 | patent against the party.
498 |
499 | If you convey a covered work, knowingly relying on a patent license,
500 | and the Corresponding Source of the work is not available for anyone
501 | to copy, free of charge and under the terms of this License, through a
502 | publicly available network server or other readily accessible means,
503 | then you must either (1) cause the Corresponding Source to be so
504 | available, or (2) arrange to deprive yourself of the benefit of the
505 | patent license for this particular work, or (3) arrange, in a manner
506 | consistent with the requirements of this License, to extend the patent
507 | license to downstream recipients. "Knowingly relying" means you have
508 | actual knowledge that, but for the patent license, your conveying the
509 | covered work in a country, or your recipient's use of the covered work
510 | in a country, would infringe one or more identifiable patents in that
511 | country that you have reason to believe are valid.
512 |
513 | If, pursuant to or in connection with a single transaction or
514 | arrangement, you convey, or propagate by procuring conveyance of, a
515 | covered work, and grant a patent license to some of the parties
516 | receiving the covered work authorizing them to use, propagate, modify
517 | or convey a specific copy of the covered work, then the patent license
518 | you grant is automatically extended to all recipients of the covered
519 | work and works based on it.
520 |
521 | A patent license is "discriminatory" if it does not include within
522 | the scope of its coverage, prohibits the exercise of, or is
523 | conditioned on the non-exercise of one or more of the rights that are
524 | specifically granted under this License. You may not convey a covered
525 | work if you are a party to an arrangement with a third party that is
526 | in the business of distributing software, under which you make payment
527 | to the third party based on the extent of your activity of conveying
528 | the work, and under which the third party grants, to any of the
529 | parties who would receive the covered work from you, a discriminatory
530 | patent license (a) in connection with copies of the covered work
531 | conveyed by you (or copies made from those copies), or (b) primarily
532 | for and in connection with specific products or compilations that
533 | contain the covered work, unless you entered into that arrangement,
534 | or that patent license was granted, prior to 28 March 2007.
535 |
536 | Nothing in this License shall be construed as excluding or limiting
537 | any implied license or other defenses to infringement that may
538 | otherwise be available to you under applicable patent law.
539 |
540 | 12. No Surrender of Others' Freedom.
541 |
542 | If conditions are imposed on you (whether by court order, agreement or
543 | otherwise) that contradict the conditions of this License, they do not
544 | excuse you from the conditions of this License. If you cannot convey a
545 | covered work so as to satisfy simultaneously your obligations under this
546 | License and any other pertinent obligations, then as a consequence you may
547 | not convey it at all. For example, if you agree to terms that obligate you
548 | to collect a royalty for further conveying from those to whom you convey
549 | the Program, the only way you could satisfy both those terms and this
550 | License would be to refrain entirely from conveying the Program.
551 |
552 | 13. Use with the GNU Affero General Public License.
553 |
554 | Notwithstanding any other provision of this License, you have
555 | permission to link or combine any covered work with a work licensed
556 | under version 3 of the GNU Affero General Public License into a single
557 | combined work, and to convey the resulting work. The terms of this
558 | License will continue to apply to the part which is the covered work,
559 | but the special requirements of the GNU Affero General Public License,
560 | section 13, concerning interaction through a network will apply to the
561 | combination as such.
562 |
563 | 14. Revised Versions of this License.
564 |
565 | The Free Software Foundation may publish revised and/or new versions of
566 | the GNU General Public License from time to time. Such new versions will
567 | be similar in spirit to the present version, but may differ in detail to
568 | address new problems or concerns.
569 |
570 | Each version is given a distinguishing version number. If the
571 | Program specifies that a certain numbered version of the GNU General
572 | Public License "or any later version" applies to it, you have the
573 | option of following the terms and conditions either of that numbered
574 | version or of any later version published by the Free Software
575 | Foundation. If the Program does not specify a version number of the
576 | GNU General Public License, you may choose any version ever published
577 | by the Free Software Foundation.
578 |
579 | If the Program specifies that a proxy can decide which future
580 | versions of the GNU General Public License can be used, that proxy's
581 | public statement of acceptance of a version permanently authorizes you
582 | to choose that version for the Program.
583 |
584 | Later license versions may give you additional or different
585 | permissions. However, no additional obligations are imposed on any
586 | author or copyright holder as a result of your choosing to follow a
587 | later version.
588 |
589 | 15. Disclaimer of Warranty.
590 |
591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
599 |
600 | 16. Limitation of Liability.
601 |
602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
610 | SUCH DAMAGES.
611 |
612 | 17. Interpretation of Sections 15 and 16.
613 |
614 | If the disclaimer of warranty and limitation of liability provided
615 | above cannot be given local legal effect according to their terms,
616 | reviewing courts shall apply local law that most closely approximates
617 | an absolute waiver of all civil liability in connection with the
618 | Program, unless a warranty or assumption of liability accompanies a
619 | copy of the Program in return for a fee.
620 |
621 | END OF TERMS AND CONDITIONS
622 |
623 | How to Apply These Terms to Your New Programs
624 |
625 | If you develop a new program, and you want it to be of the greatest
626 | possible use to the public, the best way to achieve this is to make it
627 | free software which everyone can redistribute and change under these terms.
628 |
629 | To do so, attach the following notices to the program. It is safest
630 | to attach them to the start of each source file to most effectively
631 | state the exclusion of warranty; and each file should have at least
632 | the "copyright" line and a pointer to where the full notice is found.
633 |
634 |
635 | Copyright (C)
636 |
637 | This program is free software: you can redistribute it and/or modify
638 | it under the terms of the GNU General Public License as published by
639 | the Free Software Foundation, either version 3 of the License, or
640 | (at your option) any later version.
641 |
642 | This program is distributed in the hope that it will be useful,
643 | but WITHOUT ANY WARRANTY; without even the implied warranty of
644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
645 | GNU General Public License for more details.
646 |
647 | You should have received a copy of the GNU General Public License
648 | along with this program. If not, see .
649 |
650 | Also add information on how to contact you by electronic and paper mail.
651 |
652 | If the program does terminal interaction, make it output a short
653 | notice like this when it starts in an interactive mode:
654 |
655 | Copyright (C)
656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
657 | This is free software, and you are welcome to redistribute it
658 | under certain conditions; type `show c' for details.
659 |
660 | The hypothetical commands `show w' and `show c' should show the appropriate
661 | parts of the General Public License. Of course, your program's commands
662 | might be different; for a GUI interface, you would use an "about box".
663 |
664 | You should also get your employer (if you work as a programmer) or school,
665 | if any, to sign a "copyright disclaimer" for the program, if necessary.
666 | For more information on this, and how to apply and follow the GNU GPL, see
667 | .
668 |
669 | The GNU General Public License does not permit incorporating your program
670 | into proprietary programs. If your program is a subroutine library, you
671 | may consider it more useful to permit linking proprietary applications with
672 | the library. If this is what you want to do, use the GNU Lesser General
673 | Public License instead of this License. But first, please read
674 | .
675 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## sqlmap-wx
2 | sqlmap GUI, using wxPython4.0
3 |
4 | 此GUI(wxPython太难控制了~)虽然跨平台, 但主要在win使用.
5 | linux下建议使用[sqlmap-gtk](https://github.com/needle-wang/sqlmap-gtk).
6 | sqlmap已经移植到了python3. 来自sqlmap的FAQ:
7 | "Both Python 2 and 3 are supported from May of 2019"
8 |
9 | #### SCREENSHOT
10 | 
11 |
12 | #### HOW-TO
13 | 1. **Prerequisites**
14 | - python3.6+
15 | - [sqlmap](https://github.com/sqlmapproject/sqlmap): (choose one)
16 | - `pip3 install sqlmap`(suggestion)
17 | - `git clone https://github.com/sqlmapproject/sqlmap.git`
18 | - wxPython4.0+:
19 | - windows: `pip3 install wxPython`
20 | - linux: 到[wxPython官方](https://wxpython.org/pages/downloads/index.html)下载, 有的
21 | - requests: `pip3 install requests`
22 | 2. **Download**
23 | - `git clone https://github.com/needle-wang/sqlmap-wx.git`
24 | 3. **Run**
25 | - `./sqlmap_wx.py`
26 |
27 | #### FUNCTION
28 | - all sqlmap(1.4.12.45#dev) options(except --all, 不定时更新sqlmap选项)
29 | - sqlmapapi client
30 | - built-in mini wiki(tooltip and placeholder)
31 | - session: autosave current options before quit, autoload last used options
32 |
33 | #### ABOUT
34 | - V0.3.3.1
35 | 2021-01-31 05:12:52
36 | - use wxPython4 to recode sqlmap-gtk(driven by PyGObject)
37 | - thanks to the idea from sqm
38 | author: [KINGX](https://github.com/kxcode)(sqm UI using python2 + tkinter)
39 |
40 | #### REFERENCE
41 | - wxPython教程: https://wiki.wxpython.org/, http://zetcode.com/wxpython/
42 | - wxPython API: https://wxpython.org/Phoenix/docs/html/index.html
43 |
--------------------------------------------------------------------------------
/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/needle-wang/sqlmap-wx/747e8170538f48dd1a75c8ed1b05a6a32d81d368/__init__.py
--------------------------------------------------------------------------------
/_gtkentry.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | #
3 | # 2019-05-05 17:34:08
4 |
5 | import gi
6 | gi.require_version('Gtk', '3.0')
7 |
8 | from gi.repository import Gtk as g
9 |
10 | win = g.Window()
11 | win.connect('destroy', lambda x: g.main_quit())
12 |
13 | a = g.Entry()
14 | win.add(a)
15 |
16 | print(a.get_allocation().width, a.get_allocation().height)
17 | win.show_all()
18 | print(a.get_allocation().width, a.get_allocation().height)
19 |
20 | g.main()
21 |
--------------------------------------------------------------------------------
/handler_api.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | #
3 | # 2018-08-29 15:34:10
4 |
5 | import ast
6 | import requests
7 |
8 | from widgets import wx, btn, st, EVT_BUTTON
9 |
10 |
11 | class Api(object):
12 | def __init__(self, topwindow, m):
13 | '''
14 | topwindow: sqlmap_wx.Window
15 | m: model.Model
16 | '''
17 | self.w = topwindow
18 | self.m = m
19 |
20 | def task_new(self, event):
21 | '''
22 | rest api from https://github.com/PyxYuYu/MyBlog/issues/69
23 | @get("/task/new") 创建新任务
24 | '''
25 | _host = self.get_tc_value(self.m._page4_api_server_entry)
26 | _username = self.get_tc_value(self.m._page4_username_entry)
27 | _password = self.get_tc_value(self.m._page4_password_entry)
28 | if _host:
29 | try:
30 | _resp = requests.get(f'http://{_host}/task/new',
31 | auth = (_username, _password))
32 | if not _resp:
33 | _resp.raise_for_status()
34 |
35 | _resp = _resp.json()
36 | if _resp['success']:
37 | self.task_view_append('{}: success.'.format(_resp['taskid']))
38 | except Exception as e:
39 | self.task_view_append(e)
40 |
41 | def admin_list(self, event):
42 | '''
43 | @get("/admin//list") 查看所有任务,并显示运行状态
44 | '''
45 | _host = self.get_tc_value(self.m._page4_api_server_entry)
46 | _token = self.get_tc_value(self.m._page4_admin_token_entry)
47 | _username = self.get_tc_value(self.m._page4_username_entry)
48 | _password = self.get_tc_value(self.m._page4_password_entry)
49 | if _host and _token:
50 | try:
51 | _resp = requests.get(f'http://{_host}/admin/{_token}/list',
52 | auth = (_username, _password))
53 | if not _resp:
54 | _resp.raise_for_status()
55 |
56 | _resp = _resp.json()
57 | # print(_resp)
58 | if _resp['success']:
59 | # self.task_view_append('总任务数: %s' % _resp['tasks_num'])
60 | p = self.w._api_admin_list_rows
61 | vbox = p.GetSizer()
62 | # 清空之前的任务列表
63 | vbox.Clear(delete_windows = True)
64 | # 填充任务列表
65 | _id = 0
66 | for _taskid, _status in _resp['tasks'].items():
67 | _a_task_row = wx.BoxSizer()
68 |
69 | _task_del_btn = btn(p, label = '删除', style = wx.BU_EXACTFIT)
70 | _task_del_btn.Bind(EVT_BUTTON,
71 | lambda evt, row = _a_task_row, tid = _taskid:
72 | self.task_delete(row, tid))
73 |
74 | _scan_kill_btn = btn(p, label = '杀死', style = wx.BU_EXACTFIT)
75 | _scan_kill_btn.Bind(EVT_BUTTON,
76 | lambda evt, tid = _taskid:
77 | self.scan_kill(tid))
78 |
79 | _scan_stop_btn = btn(p, label = '停止', style = wx.BU_EXACTFIT)
80 | _scan_stop_btn.Bind(EVT_BUTTON,
81 | lambda evt, tid = _taskid:
82 | self.scan_stop(tid))
83 |
84 | _scan_start_btn = btn(p, label = '启动', style = wx.BU_EXACTFIT)
85 | _scan_start_btn.Bind(EVT_BUTTON,
86 | lambda evt, tid = _taskid:
87 | self.scan_start(tid))
88 |
89 | _scan_data_btn = btn(p, label = 'data', style = wx.BU_EXACTFIT)
90 | _scan_data_btn.Bind(EVT_BUTTON,
91 | lambda evt, tid = _taskid:
92 | self.scan_data(tid))
93 |
94 | _scan_log_btn = btn(p, label = 'log', style = wx.BU_EXACTFIT)
95 | _scan_log_btn.Bind(EVT_BUTTON,
96 | lambda evt, tid = _taskid:
97 | self.scan_log(tid))
98 |
99 | _option_list_btn = btn(p, label = '所有选项', style = wx.BU_EXACTFIT)
100 | _option_list_btn.Bind(EVT_BUTTON,
101 | lambda evt, tid = _taskid:
102 | self.option_list(tid))
103 |
104 | _option_get_btn = btn(p, label = '选项:', style = wx.BU_EXACTFIT)
105 | _option_get_btn.Bind(EVT_BUTTON,
106 | lambda evt, tid = _taskid:
107 | self.option_get(tid))
108 |
109 | _option_set_btn = btn(p, label = '设置:', style = wx.BU_EXACTFIT)
110 | _option_set_btn.Bind(EVT_BUTTON,
111 | lambda evt, tid = _taskid:
112 | self.option_set(tid))
113 |
114 | _id += 1
115 | _a_task_row.Add(st(p, label = f'{_id}. {_taskid}'), flag = wx.ALIGN_CENTER)
116 | _a_task_row.Add(st(p, label = f'({_status})'), flag = wx.ALIGN_CENTER)
117 | _a_task_row.Add(_task_del_btn, flag = wx.EXPAND)
118 | _a_task_row.Add(_scan_kill_btn, flag = wx.EXPAND)
119 | _a_task_row.Add(_scan_stop_btn, flag = wx.EXPAND)
120 | _a_task_row.Add(_scan_start_btn, flag = wx.EXPAND)
121 | _a_task_row.Add(st(p, label = '查看:('), flag = wx.ALIGN_CENTER)
122 | _a_task_row.Add(_scan_data_btn, flag = wx.EXPAND)
123 | _a_task_row.Add(_scan_log_btn, flag = wx.EXPAND)
124 | _a_task_row.Add(_option_list_btn, flag = wx.EXPAND)
125 | _a_task_row.Add(_option_get_btn, flag = wx.EXPAND)
126 | _a_task_row.Add(st(p, label = ')'), flag = wx.ALIGN_CENTER)
127 | _a_task_row.Add(_option_set_btn, flag = wx.EXPAND)
128 |
129 | vbox.Add(_a_task_row, flag = wx.EXPAND)
130 |
131 | vbox.Layout()
132 | p.SetupScrolling()
133 | except Exception as e:
134 | self.task_view_append(e)
135 | else:
136 | self.task_view_append('need API server and admin token.')
137 |
138 | def option_list(self, taskid):
139 | '''
140 | @get("/option//list") 获取指定任务的options
141 | '''
142 | _host = self.get_tc_value(self.m._page4_api_server_entry)
143 | _username = self.get_tc_value(self.m._page4_username_entry)
144 | _password = self.get_tc_value(self.m._page4_password_entry)
145 | if _host:
146 | try:
147 | _resp = requests.get('http://%s/option/%s/list' % (_host, taskid),
148 | auth = (_username, _password))
149 | if not _resp:
150 | _resp.raise_for_status()
151 |
152 | _resp = _resp.json()
153 | if _resp['success']:
154 | for _key, _value in _resp['options'].items():
155 | if _value:
156 | self.task_view_append(f'{_key}: {_value}')
157 | except Exception as e:
158 | self.task_view_append(e)
159 |
160 | def option_get(self, taskid):
161 | '''
162 | @post("/option//get") 获取指定任务的option(s)
163 | '''
164 | _host = self.get_tc_value(self.m._page4_api_server_entry)
165 | _opts_text = self.get_tc_value(self.m._page4_option_get_entry)
166 | _username = self.get_tc_value(self.m._page4_username_entry)
167 | _password = self.get_tc_value(self.m._page4_password_entry)
168 | _options = {}
169 | for _tmp in _opts_text.split():
170 | _options[_tmp] = None
171 | if _host and _options:
172 | _mesg = f'{taskid}:\n'
173 | try:
174 | _headers = {'Content-Type': 'application/json'}
175 | _resp = requests.post('http://%s/option/%s/get' % (_host, taskid),
176 | json = _options,
177 | headers = _headers,
178 | auth = (_username, _password))
179 | if not _resp:
180 | _resp.raise_for_status()
181 |
182 | _resp = _resp.json()
183 | if _resp['success']:
184 | if _resp['options'].items():
185 | for _key, _value in _resp['options'].items():
186 | _mesg += '%s: %s, ' % (_key, _value)
187 | else:
188 | _mesg += 'None'
189 | else:
190 | _mesg += _resp['message']
191 | except Exception as e:
192 | _mesg += str(e)
193 | self.task_view_append(_mesg.strip())
194 |
195 | def option_set(self, taskid):
196 | '''
197 | @post("/option//set") 设置指定任务的option(s)
198 | Warning: any option can be set, even a invalid option which
199 | is unable to remove, except deleting the task.
200 | '''
201 | _host = self.get_tc_value(self.m._page4_api_server_entry)
202 | _buffer_text = self.get_tc_value(self.m._page4_option_set_view)
203 | _username = self.get_tc_value(self.m._page4_username_entry)
204 | _password = self.get_tc_value(self.m._page4_password_entry)
205 | try:
206 | _json = ast.literal_eval(_buffer_text)
207 | except Exception as e:
208 | _json = str(e)
209 |
210 | _mesg = f'{taskid}: '
211 | if _json and isinstance(_json, dict):
212 | if _host:
213 | try:
214 | _headers = {'Content-Type': 'application/json'}
215 | # data, json参数都要求是字典类型, 而非字符串
216 | # 另外, 字典的格式比json的宽松(json不能使用单引号, 不能多个逗号)
217 | _resp = requests.post('http://%s/option/%s/set' % (_host, taskid),
218 | json = _json,
219 | headers = _headers,
220 | auth = (_username, _password))
221 | if not _resp:
222 | _resp.raise_for_status()
223 |
224 | _resp = _resp.json()
225 | if _resp['success']:
226 | _mesg += 'set success.'
227 | except Exception as e:
228 | _mesg += str(e)
229 | else:
230 | _mesg += 'need a valid python dict.'
231 |
232 | self.task_view_append(_mesg)
233 |
234 | def admin_flush(self, event):
235 | '''
236 | @get("/admin//flush") 删除所有任务
237 | '''
238 | _host = self.get_tc_value(self.m._page4_api_server_entry)
239 | _token = self.get_tc_value(self.m._page4_admin_token_entry)
240 | _username = self.get_tc_value(self.m._page4_username_entry)
241 | _password = self.get_tc_value(self.m._page4_password_entry)
242 | if _host and _token:
243 | try:
244 | _resp = requests.get('http://%s/admin/%s/flush' % (_host, _token),
245 | auth = (_username, _password))
246 | if not _resp:
247 | _resp.raise_for_status()
248 |
249 | _resp = _resp.json()
250 | if _resp['success']:
251 | self.w._api_admin_list_rows.GetSizer().Clear(delete_windows = True)
252 | self.task_view_append('flush all tasks: Done.')
253 | except Exception as e:
254 | self.task_view_append(e)
255 |
256 | def task_delete(self, row, taskid):
257 | '''
258 | @get("/task//delete") 删除指定任务
259 | '''
260 | _host = self.get_tc_value(self.m._page4_api_server_entry)
261 | _username = self.get_tc_value(self.m._page4_username_entry)
262 | _password = self.get_tc_value(self.m._page4_password_entry)
263 | if _host:
264 | try:
265 | _resp = requests.get('http://%s/task/%s/delete' % (_host, taskid),
266 | auth = (_username, _password))
267 | if not _resp:
268 | _resp.raise_for_status()
269 |
270 | _resp = _resp.json()
271 | if _resp['success']:
272 | # TODO, 要两步哈! 要查下是否真的成功了!
273 | row.Clear(delete_windows = True)
274 | self.w._api_admin_list_rows.GetSizer().Remove(row)
275 | self.task_view_append('%s: removed' % taskid)
276 | except Exception as e:
277 | self.task_view_append(e)
278 |
279 | def scan_start(self, taskid):
280 | '''
281 | @post("/scan//start") 指定任务 开始扫描
282 | 要求发送json, 会执行/option//set
283 | '''
284 | _host = self.get_tc_value(self.m._page4_api_server_entry)
285 | _username = self.get_tc_value(self.m._page4_username_entry)
286 | _password = self.get_tc_value(self.m._page4_password_entry)
287 | if _host:
288 | _mesg = '%s: ' % taskid
289 | try:
290 | _headers = {'Content-Type': 'application/json'}
291 | _resp = requests.post('http://%s/scan/%s/start' % (_host, taskid),
292 | json = {},
293 | headers = _headers,
294 | auth = (_username, _password))
295 | if not _resp:
296 | _resp.raise_for_status()
297 |
298 | _resp = _resp.json()
299 | if _resp['success']:
300 | _mesg = '%sengineid: %s' % (_mesg, _resp['engineid'])
301 | else:
302 | _mesg += _resp['message']
303 | except Exception as e:
304 | _mesg += str(e)
305 |
306 | self.task_view_append(_mesg)
307 |
308 | def scan_stop(self, taskid):
309 | '''
310 | @get("/scan//stop") 指定任务 停止扫描
311 | '''
312 | _host = self.get_tc_value(self.m._page4_api_server_entry)
313 | _username = self.get_tc_value(self.m._page4_username_entry)
314 | _password = self.get_tc_value(self.m._page4_password_entry)
315 | if _host:
316 | _mesg = '%s: ' % taskid
317 | try:
318 | _resp = requests.get('http://%s/scan/%s/stop' % (_host, taskid),
319 | auth = (_username, _password))
320 | if not _resp:
321 | _resp.raise_for_status()
322 |
323 | _resp = _resp.json()
324 | if _resp['success']:
325 | _mesg += 'ok, stoped.'
326 | else:
327 | _mesg += _resp['message']
328 | except Exception as e:
329 | _mesg += str(e)
330 | self.task_view_append(_mesg)
331 |
332 | def scan_kill(self, taskid):
333 | '''
334 | @get("/scan//kill") kill -9 指定任务
335 | '''
336 | _host = self.get_tc_value(self.m._page4_api_server_entry)
337 | _username = self.get_tc_value(self.m._page4_username_entry)
338 | _password = self.get_tc_value(self.m._page4_password_entry)
339 | if _host:
340 | _mesg = f'{taskid}: '
341 | try:
342 | _resp = requests.get('http://%s/scan/%s/kill' % (_host, taskid),
343 | auth = (_username, _password))
344 | if not _resp:
345 | _resp.raise_for_status()
346 |
347 | _resp = _resp.json()
348 | if _resp['success']:
349 | _mesg += 'ok, killed.'
350 | else:
351 | _mesg += _resp['message']
352 | except Exception as e:
353 | _mesg += str(e)
354 |
355 | self.task_view_append(_mesg)
356 |
357 | def scan_data(self, taskid):
358 | '''
359 | @get("/scan//data") 查看指定任务的扫描数据,
360 | data若有内容说明存在注入
361 | '''
362 | _host = self.get_tc_value(self.m._page4_api_server_entry)
363 | _username = self.get_tc_value(self.m._page4_username_entry)
364 | _password = self.get_tc_value(self.m._page4_password_entry)
365 | if _host:
366 | _mesg = '%s:\n' % taskid
367 | try:
368 | _resp = requests.get('http://%s/scan/%s/data' % (_host, taskid),
369 | auth = (_username, _password))
370 | if not _resp:
371 | _resp.raise_for_status()
372 |
373 | _resp = _resp.json()
374 | # print(_resp) # _resp['data'], _resp['error'] are list
375 | if _resp['success']:
376 | del[_resp['success']]
377 | _mesg = f'{_mesg}{_resp}'
378 | except Exception as e:
379 | _mesg += str(e)
380 | self.task_view_append(_mesg)
381 |
382 | def scan_log(self, taskid):
383 | '''
384 | @get("/scan//log") 查看指定任务的扫描日志
385 | '''
386 | _host = self.get_tc_value(self.m._page4_api_server_entry)
387 | _username = self.get_tc_value(self.m._page4_username_entry)
388 | _password = self.get_tc_value(self.m._page4_password_entry)
389 | if _host:
390 | _mesg = '%s:\n' % taskid
391 | try:
392 | _resp = requests.get('http://%s/scan/%s/log' % (_host, taskid),
393 | auth = (_username, _password))
394 | if not _resp:
395 | _resp.raise_for_status()
396 |
397 | _resp = _resp.json()
398 | if _resp['success']:
399 | _logs = ''
400 | for _tmp in _resp['log']:
401 | _log = '%s %s: %s\n' % (_tmp['time'], _tmp['level'], _tmp['message'])
402 | _logs = ''.join((_logs, _log))
403 | if _logs:
404 | _mesg += _logs.strip()
405 | else:
406 | _mesg += "no log."
407 | else:
408 | _mesg += _resp['message']
409 | except Exception as e:
410 | _mesg += str(e)
411 | self.task_view_append(_mesg)
412 |
413 | def get_tc_value(self, textctrl):
414 | return textctrl.GetValue().strip()
415 |
416 | def task_view_append(self, output):
417 | _task_view = self.m._page4_task_view
418 |
419 | _task_view.write(f'{output}\n')
420 |
421 | _task_view.SetFocus()
422 | _mark = _task_view.GetInsertionPoint()
423 | wx.CallAfter(_task_view.ShowPosition, _mark)
424 |
425 |
--------------------------------------------------------------------------------
/model.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | #
3 | # 2019-10-13 00:00:33
4 |
5 | from widgets import StaticBox, btn, cb, cbb, ci, nc, sl, sp, st, tc
6 |
7 |
8 | class Model(object):
9 | def __init__(self, full = True):
10 | self._core()
11 |
12 | if full:
13 | self._outer()
14 |
15 | def _outer(self):
16 | # TARGET
17 | self._url_combobox = cbb()
18 | self._burp_logfile = tc()
19 | self._burp_logfile_chooser = btn()
20 | self._request_file = tc()
21 | self._request_file_chooser = btn()
22 | self._bulkfile = tc()
23 | self._bulkfile_chooser = btn()
24 | self._configfile = tc()
25 | self._configfile_chooser = btn()
26 | self._google_dork = tc()
27 | self._direct_connect = tc()
28 | # OPTIONS(1)
29 | # collected options:
30 | self._cmd_entry = tc()
31 | # self._core()...
32 | # EXECUTION(2)
33 | # LOG(3)
34 | self._page3_log_view = tc()
35 | self._page3_read_target_btn = btn()
36 | self._page3_clear_btn = btn()
37 | self._page3_read_log_btn = btn()
38 | # SQLMAPAPI(4)
39 | self._page4_api_server_label = st()
40 | self._page4_api_server_entry = tc()
41 | self._page4_admin_token_label = st()
42 | self._page4_admin_token_entry = tc()
43 | self._page4_task_new_btn = btn()
44 | self._page4_admin_list_btn = btn()
45 | self._page4_admin_flush_btn = btn()
46 | self._page4_clear_task_view_btn = btn()
47 | self._page4_username_label = st()
48 | self._page4_username_entry = tc()
49 | self._page4_password_label = st()
50 | self._page4_password_entry = tc()
51 | self._page4_option_get_entry = tc()
52 | self._page4_option_set_view = tc()
53 | self._page4_task_view = tc()
54 | # HELP(H)
55 | self._page5_manual_view = tc()
56 | # ABOUT
57 |
58 | def _core(self):
59 | pass
60 | # Inject(Q)
61 | self._sqlmap_path_label = st()
62 | self.sqlmap_path_entry = tc()
63 | self._sqlmap_path_chooser = btn()
64 | # Injection
65 | self._inject_area = StaticBox()
66 | self._inject_area_param_ckbtn = cb()
67 | self._inject_area_param_entry = tc()
68 | self._inject_area_param_filter_ckbtn = cb()
69 | self._inject_area_param_filter_combobox = cbb()
70 | self._inject_area_skip_static_ckbtn = cb()
71 | self._inject_area_skip_ckbtn = cb()
72 | self._inject_area_skip_entry = tc()
73 | self._inject_area_param_exclude_ckbtn = cb()
74 | self._inject_area_param_exclude_entry = tc()
75 | self._inject_area_prefix_ckbtn = cb()
76 | self._inject_area_prefix_entry = tc()
77 | self._inject_area_suffix_ckbtn = cb()
78 | self._inject_area_suffix_entry = tc()
79 | self._inject_area_dbms_ckbtn = cb()
80 | self._inject_area_dbms_combobox = cbb()
81 | self._inject_area_dbms_cred_ckbtn = cb()
82 | self._inject_area_dbms_cred_entry = tc()
83 | self._inject_area_os_ckbtn = cb()
84 | self._inject_area_os_entry = tc()
85 | self._inject_area_no_cast_ckbtn = cb()
86 | self._inject_area_no_escape_ckbtn = cb()
87 | self._inject_area_invalid_bignum_ckbtn = cb()
88 | self._inject_area_invalid_logic_ckbtn = cb()
89 | self._inject_area_invalid_string_ckbtn = cb()
90 | # Detection
91 | self._detection_area = StaticBox()
92 | self._detection_area_level_ckbtn = cb()
93 | self._detection_area_level_scale = sl()
94 | self._detection_area_risk_ckbtn = cb()
95 | self._detection_area_risk_scale = sl()
96 | self._detection_area_str_ckbtn = cb()
97 | self._detection_area_str_entry = tc()
98 | self._detection_area_not_str_ckbtn = cb()
99 | self._detection_area_not_str_entry = tc()
100 | self._detection_area_re_ckbtn = cb()
101 | self._detection_area_re_entry = tc()
102 | self._detection_area_code_ckbtn = cb()
103 | self._detection_area_code_entry = nc()
104 | self._detection_area_text_only_ckbtn = cb()
105 | self._detection_area_titles_ckbtn = cb()
106 | self._detection_area_smart_ckbtn = cb()
107 | # Technique
108 | self._tech_area = StaticBox()
109 | self._tech_area_tech_ckbtn = cb()
110 | self._tech_area_tech_entry = tc()
111 | self._tech_area_time_sec_ckbtn = cb()
112 | self._tech_area_time_sec_entry = nc()
113 | self._tech_area_union_col_ckbtn = cb()
114 | self._tech_area_union_col_entry = nc()
115 | self._tech_area_union_char_ckbtn = cb()
116 | self._tech_area_union_char_entry = tc()
117 | self._tech_area_union_from_ckbtn = cb()
118 | self._tech_area_union_from_entry = tc()
119 | self._tech_area_dns_ckbtn = cb()
120 | self._tech_area_dns_entry = tc()
121 | self._tech_area_second_url_ckbtn = cb()
122 | self._tech_area_second_url_entry = tc()
123 | self._tech_area_second_req_ckbtn = cb()
124 | self._tech_area_second_req_entry = tc()
125 | self._tech_area_second_req_chooser = btn()
126 | # Tamper
127 | self._tamper_area = StaticBox()
128 | self._tamper_area_tamper_view = tc()
129 | # Optimize
130 | self._optimize_area = StaticBox()
131 | self._optimize_area_turn_all_ckbtn = cb()
132 | self._optimize_area_thread_num_ckbtn = cb()
133 | self._optimize_area_thread_num_spinbtn = sp()
134 | self._optimize_area_predict_ckbtn = cb()
135 | self._optimize_area_keep_alive_ckbtn = cb()
136 | self._optimize_area_null_connect_ckbtn = cb()
137 | # Offen
138 | self._offen_area = StaticBox()
139 | self._general_area_verbose_ckbtn = cb()
140 | self._general_area_verbose_scale = sl()
141 | self._general_area_finger_ckbtn = cb()
142 | self._general_area_hex_ckbtn = cb()
143 | self._general_area_batch_ckbtn = cb()
144 | self._misc_area_wizard_ckbtn = cb()
145 | # Hidden
146 | self._hidden_area = StaticBox()
147 | self._hidden_area_crack_ckbtn = cb()
148 | self._hidden_area_debug_ckbtn = cb()
149 | self._hidden_area_profile_ckbtn = cb()
150 | self._hidden_area_disable_precon_ckbtn = cb()
151 | self._hidden_area_disable_stats_ckbtn = cb()
152 | self._hidden_area_force_dbms_ckbtn = cb()
153 | self._hidden_area_force_dns_ckbtn = cb()
154 | self._hidden_area_force_pivoting_ckbtn = cb()
155 | self._hidden_area_smoke_test_ckbtn = cb()
156 | self._hidden_area_live_test_ckbtn = cb()
157 | self._hidden_area_vuln_test_ckbtn = cb()
158 | self._hidden_area_murphy_rate_ckbtn = cb()
159 | self._hidden_area_stop_fail_ckbtn = cb()
160 | self._hidden_area_run_case_ckbtn = cb()
161 | self._hidden_area_dummy_ckbtn = cb()
162 | self._hidden_area_api_ckbtn = cb()
163 | self._hidden_area_taskid_ckbtn = cb()
164 | self._hidden_area_database_ckbtn = cb()
165 | # Request(W)
166 | # HTTP header
167 | self._request_header_area = StaticBox()
168 | self._request_area_random_agent_ckbtn = cb()
169 | self._request_area_mobile_ckbtn = cb()
170 | self._request_area_user_agent_ckbtn = cb()
171 | self._request_area_user_agent_entry = tc()
172 | self._request_area_host_ckbtn = cb()
173 | self._request_area_host_entry = tc()
174 | self._request_area_referer_ckbtn = cb()
175 | self._request_area_referer_entry = tc()
176 | self._request_area_header_ckbtn = cb()
177 | self._request_area_header_entry = tc()
178 | self._request_area_headers_ckbtn = cb()
179 | self._request_area_headers_entry = tc()
180 | # HTTP data
181 | self._request_data_area = StaticBox()
182 | self._request_area_method_ckbtn = cb()
183 | self._request_area_method_entry = tc()
184 | self._request_area_param_del_ckbtn = cb()
185 | self._request_area_param_del_entry = tc()
186 | self._request_area_chunked_ckbtn = cb()
187 | self._request_area_post_ckbtn = cb()
188 | self._request_area_post_entry = tc()
189 | self._request_area_cookie_ckbtn = cb()
190 | self._request_area_cookie_entry = tc()
191 | self._request_area_cookie_del_ckbtn = cb()
192 | self._request_area_cookie_del_entry = tc()
193 | self._request_area_drop_set_cookie_ckbtn = cb()
194 | self._request_area_live_cookies_ckbtn = cb()
195 | self._request_area_live_cookies_entry = tc()
196 | self._request_area_live_cookies_chooser = btn()
197 | self._request_area_load_cookies_ckbtn = cb()
198 | self._request_area_load_cookies_entry = tc()
199 | self._request_area_load_cookies_chooser = btn()
200 | self._request_area_auth_type_ckbtn = cb()
201 | self._request_area_auth_type_entry = tc()
202 | self._request_area_auth_cred_ckbtn = cb()
203 | self._request_area_auth_cred_entry = tc()
204 | self._request_area_auth_file_ckbtn = cb()
205 | self._request_area_auth_file_entry = tc()
206 | self._request_area_auth_file_chooser = btn()
207 | self._request_area_csrf_method_ckbtn = cb()
208 | self._request_area_csrf_method_entry = tc()
209 | self._request_area_csrf_retries_ckbtn = cb()
210 | self._request_area_csrf_retries_entry = nc()
211 | self._request_area_csrf_token_ckbtn = cb()
212 | self._request_area_csrf_token_entry = tc()
213 | self._request_area_csrf_url_ckbtn = cb()
214 | self._request_area_csrf_url_entry = tc()
215 | # Request custom
216 | self._request_custom_area = StaticBox()
217 | self._request_area_ignore_timeouts_ckbtn = cb()
218 | self._request_area_ignore_redirects_ckbtn = cb()
219 | self._request_area_ignore_code_ckbtn = cb()
220 | self._request_area_ignore_code_entry = tc()
221 | self._request_area_skip_urlencode_ckbtn = cb()
222 | self._request_area_force_ssl_ckbtn = cb()
223 | self._request_area_hpp_ckbtn = cb()
224 | self._request_area_delay_ckbtn = cb()
225 | self._request_area_delay_entry = nc()
226 | self._request_area_timeout_ckbtn = cb()
227 | self._request_area_timeout_entry = nc()
228 | self._request_area_retries_ckbtn = cb()
229 | self._request_area_retries_entry = nc()
230 | self._request_area_randomize_ckbtn = cb()
231 | self._request_area_randomize_entry = tc()
232 | self._request_area_eval_ckbtn = cb()
233 | self._request_area_eval_entry = tc()
234 | # Anonymous/Proxy
235 | self._request_proxy_area = StaticBox()
236 | self._request_area_safe_url_ckbtn = cb()
237 | self._request_area_safe_url_entry = tc()
238 | self._request_area_safe_post_ckbtn = cb()
239 | self._request_area_safe_post_entry = tc()
240 | self._request_area_safe_req_ckbtn = cb()
241 | self._request_area_safe_req_entry = tc()
242 | self._request_area_safe_req_chooser = btn()
243 | self._request_area_safe_freq_ckbtn = cb()
244 | self._request_area_safe_freq_entry = tc()
245 | self._request_area_ignore_proxy_ckbtn = cb()
246 | self._request_area_proxy_freq_ckbtn = cb()
247 | self._request_area_proxy_freq_entry = nc()
248 | self._request_area_proxy_file_ckbtn = cb()
249 | self._request_area_proxy_file_entry = tc()
250 | self._request_area_proxy_file_chooser = btn()
251 | self._request_area_proxy_ckbtn = cb()
252 | self._request_area_proxy_ip_label = st()
253 | self._request_area_proxy_ip_entry = tc()
254 | self._request_area_proxy_port_label = st()
255 | self._request_area_proxy_port_entry = nc()
256 | self._request_area_proxy_username_label = st()
257 | self._request_area_proxy_username_entry = tc()
258 | self._request_area_proxy_password_label = st()
259 | self._request_area_proxy_password_entry = tc()
260 | self._request_area_tor_ckbtn = cb()
261 | self._request_area_tor_port_ckbtn = cb()
262 | self._request_area_tor_port_entry = nc()
263 | self._request_area_tor_type_ckbtn = cb()
264 | self._request_area_tor_type_entry = tc()
265 | self._request_area_check_tor_ckbtn = cb()
266 | # Enumerate(E)
267 | # Enumeration
268 | self._enum_area = StaticBox()
269 | # 要求要与_enum_area_enum_labels的结构一致!
270 | self._enum_area_opts_ckbtns = [[cb() for _ in range(5)] for _r in range(3)]
271 | # Dump
272 | self._dump_area = StaticBox()
273 | self._dump_area_dump_ckbtn = cb()
274 | self._dump_area_repair_ckbtn = cb()
275 | self._dump_area_statements_ckbtn = cb()
276 | self._dump_area_search_ckbtn = cb()
277 | self._dump_area_no_sys_db_ckbtn = cb()
278 | self._dump_area_dump_all_ckbtn = cb()
279 | # Limit(when dump)
280 | self._limit_area = StaticBox()
281 | self._limit_area_start_ckbtn = cb()
282 | self._limit_area_start_entry = nc()
283 | self._limit_area_stop_ckbtn = cb()
284 | self._limit_area_stop_entry = nc()
285 | # Blind inject options
286 | self._blind_area = StaticBox()
287 | self._blind_area_first_ckbtn = cb()
288 | self._blind_area_first_entry = nc()
289 | self._blind_area_last_ckbtn = cb()
290 | self._blind_area_last_entry = nc()
291 | # DB, Table, Column name...
292 | self._meta_area = StaticBox()
293 | self._meta_area_D_ckbtn = cb()
294 | self._meta_area_D_entry = tc()
295 | self._meta_area_T_ckbtn = cb()
296 | self._meta_area_T_entry = tc()
297 | self._meta_area_C_ckbtn = cb()
298 | self._meta_area_C_entry = tc()
299 | self._meta_area_U_ckbtn = cb()
300 | self._meta_area_U_entry = tc()
301 | self._meta_area_X_ckbtn = cb()
302 | self._meta_area_X_entry = tc()
303 | self._meta_area_pivot_ckbtn = cb()
304 | self._meta_area_pivot_entry = tc()
305 | self._meta_area_where_ckbtn = cb()
306 | self._meta_area_where_entry = tc()
307 | # Execute SQL
308 | self._runsql_area = StaticBox()
309 | self._runsql_area_sql_query_ckbtn = cb()
310 | self._runsql_area_sql_query_entry = tc()
311 | self._runsql_area_sql_shell_ckbtn = cb()
312 | self._runsql_area_sql_file_ckbtn = cb()
313 | self._runsql_area_sql_file_entry = tc()
314 | self._runsql_area_sql_file_chooser = btn()
315 | # Brute force
316 | self._brute_force_area = StaticBox()
317 | self._brute_force_area_common_tables_ckbtn = cb()
318 | self._brute_force_area_common_columns_ckbtn = cb()
319 | self._brute_force_area_common_files_ckbtn = cb()
320 | # File(R)
321 | # Read remote file
322 | self._file_read_area = StaticBox()
323 | self._file_read_area_file_read_ckbtn = cb()
324 | self._file_read_area_file_read_entry = tc()
325 | self._file_read_area_file_read_btn = btn()
326 | # Upload local file
327 | self._file_write_area = StaticBox()
328 | self._file_write_area_udf_ckbtn = cb()
329 | self._file_write_area_shared_lib_ckbtn = cb()
330 | self._file_write_area_shared_lib_entry = tc()
331 | self._file_write_area_shared_lib_chooser = btn()
332 | self._file_write_area_file_write_ckbtn = cb()
333 | self._file_write_area_file_write_entry = tc()
334 | self._file_write_area_file_write_chooser = btn()
335 | self._file_write_area_file_dest_ckbtn = cb()
336 | self._file_write_area_file_dest_entry = tc()
337 | # Access to the OS behind the DBMS
338 | self._os_access_area = StaticBox()
339 | self._os_access_area_os_cmd_ckbtn = cb()
340 | self._os_access_area_os_cmd_entry = tc()
341 | self._os_access_area_os_shell_ckbtn = cb()
342 | self._os_access_area_os_pwn_ckbtn = cb()
343 | self._os_access_area_os_smbrelay_ckbtn = cb()
344 | self._os_access_area_os_bof_ckbtn = cb()
345 | self._os_access_area_priv_esc_ckbtn = cb()
346 | self._os_access_area_msf_path_ckbtn = cb()
347 | self._os_access_area_msf_path_entry = tc()
348 | self._os_access_area_msf_path_chooser = btn()
349 | self._os_access_area_tmp_path_ckbtn = cb()
350 | self._os_access_area_tmp_path_entry = tc()
351 | # Access to register in remote WIN
352 | self._registry_area = StaticBox()
353 | self._registry_area_reg_ckbtn = cb()
354 | self._registry_area_reg_choice = ci()
355 | self._registry_area_reg_key_label = st()
356 | self._registry_area_reg_key_entry = tc()
357 | self._registry_area_reg_value_label = st()
358 | self._registry_area_reg_value_entry = tc()
359 | self._registry_area_reg_data_label = st()
360 | self._registry_area_reg_data_entry = tc()
361 | self._registry_area_reg_type_label = st()
362 | self._registry_area_reg_type_entry = tc()
363 | # Other(T)
364 | # General
365 | self._general_area = StaticBox()
366 | self._general_area_check_internet_ckbtn = cb()
367 | self._general_area_fresh_queries_ckbtn = cb()
368 | self._general_area_forms_ckbtn = cb()
369 | self._general_area_parse_errors_ckbtn = cb()
370 | self._misc_area_cleanup_ckbtn = cb()
371 | self._general_area_base64_ckbtn = cb()
372 | self._general_area_base64_entry = tc()
373 | self._general_area_base64_safe_ckbtn = cb()
374 | self._general_area_table_prefix_ckbtn = cb()
375 | self._general_area_table_prefix_entry = tc()
376 | self._general_area_binary_fields_ckbtn = cb()
377 | self._general_area_binary_fields_entry = tc()
378 | self._general_area_preprocess_ckbtn = cb()
379 | self._general_area_preprocess_entry = tc()
380 | self._general_area_preprocess_chooser = btn()
381 | self._general_area_postprocess_ckbtn = cb()
382 | self._general_area_postprocess_entry = tc()
383 | self._general_area_postprocess_chooser = btn()
384 | self._general_area_charset_ckbtn = cb()
385 | self._general_area_charset_entry = tc()
386 | self._general_area_encoding_ckbtn = cb()
387 | self._general_area_encoding_entry = tc()
388 | self._general_area_web_root_ckbtn = cb()
389 | self._general_area_web_root_entry = tc()
390 | self._general_area_scope_ckbtn = cb()
391 | self._general_area_scope_entry = tc()
392 | self._general_area_scope_chooser = btn()
393 | self._general_area_test_filter_ckbtn = cb()
394 | self._general_area_test_filter_entry = tc()
395 | self._general_area_test_skip_ckbtn = cb()
396 | self._general_area_test_skip_entry = tc()
397 | self._general_area_crawl_ckbtn = cb()
398 | self._general_area_crawl_entry = nc()
399 | self._general_area_crawl_exclude_ckbtn = cb()
400 | self._general_area_crawl_exclude_entry = tc()
401 | self._general_area_traffic_file_ckbtn = cb()
402 | self._general_area_traffic_file_entry = tc()
403 | self._general_area_traffic_file_chooser = btn()
404 | self._general_area_har_ckbtn = cb()
405 | self._general_area_har_entry = tc()
406 | self._general_area_har_chooser = btn()
407 | self._general_area_flush_session_ckbtn = cb()
408 | self._general_area_dump_format_ckbtn = cb()
409 | self._general_area_dump_format_entry = tc()
410 | self._general_area_csv_del_ckbtn = cb()
411 | self._general_area_csv_del_entry = tc()
412 | self._general_area_save_ckbtn = cb()
413 | self._general_area_save_entry = tc()
414 | self._general_area_save_chooser = btn()
415 | self._general_area_session_file_ckbtn = cb()
416 | self._general_area_session_file_entry = tc()
417 | self._general_area_session_file_chooser = btn()
418 | self._general_area_output_dir_ckbtn = cb()
419 | self._general_area_output_dir_entry = tc()
420 | self._general_area_output_dir_chooser = btn()
421 | # Misc
422 | self._misc_area = StaticBox()
423 | self._misc_area_skip_heuristics_ckbtn = cb()
424 | self._misc_area_skip_waf_ckbtn = cb()
425 | self._misc_area_unstable_ckbtn = cb()
426 | self._misc_area_list_tampers_ckbtn = cb()
427 | self._misc_area_sqlmap_shell_ckbtn = cb()
428 | self._misc_area_disable_color_ckbtn = cb()
429 | self._general_area_eta_ckbtn = cb()
430 | self._misc_area_gpage_ckbtn = cb()
431 | self._misc_area_gpage_spinbtn = sp()
432 | self._misc_area_beep_ckbtn = cb()
433 | self._misc_area_offline_ckbtn = cb()
434 | self._misc_area_purge_ckbtn = cb()
435 | self._misc_area_dependencies_ckbtn = cb()
436 | self._misc_area_update_ckbtn = cb()
437 | self._misc_area_alert_ckbtn = cb()
438 | self._misc_area_alert_entry = tc()
439 | self._misc_area_tmp_dir_ckbtn = cb()
440 | self._misc_area_tmp_dir_entry = tc()
441 | self._misc_area_tmp_dir_chooser = btn()
442 | self._misc_area_answers_ckbtn = cb()
443 | self._misc_area_answers_entry = tc()
444 | self._misc_area_z_ckbtn = cb()
445 | self._misc_area_z_entry = tc()
446 | self._misc_area_results_file_ckbtn = cb()
447 | self._misc_area_results_file_entry = tc()
448 | self._misc_area_results_file_chooser = btn()
449 |
450 |
451 | def main():
452 | pass
453 |
454 |
455 | if __name__ == '__main__':
456 | main()
457 |
--------------------------------------------------------------------------------
/opts_wx.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | #
3 | # 2019-05-05 20:43:40
4 |
5 | from widgets import wx, Panel, Scroll, nb, st, btn
6 | from widgets import EVT_BUTTON, EVT_CHECKBOX
7 | from layout import Layout_opts
8 |
9 |
10 | class Notebook(nb):
11 | def __init__(self, parent, model, handlers):
12 | '''
13 | m: model.Model
14 | 最大的宽应该是由最长的 request定制的第一行 决定
15 |
16 | 以"Other"标签的height作为标准高,
17 | 高于此height的标签页使用ScrolledPanel, 显示滚动条
18 | '''
19 | super().__init__(parent)
20 | self.m = model
21 | layout = Layout_opts(self, model)
22 |
23 | self._handlers = handlers
24 | # OPTIONS - Inject, Request, Enumerate, File, Other, Tamper
25 | page1_setting = self.build_page1_setting(layout)
26 | page1_request = self.build_page1_request(layout)
27 | page1_enumeration = self.build_page1_enumeration(layout)
28 | page1_file = self.build_page1_file(layout)
29 | page1_other = self.build_page1_other(layout)
30 | page1_tamper = self.build_page1_tamper(layout)
31 |
32 | self.AddPage(page1_setting, '测试(Q)')
33 | self.AddPage(page1_request, '请求(W)')
34 | self.AddPage(page1_enumeration, '枚举(E)')
35 | self.AddPage(page1_file, '文件(R)')
36 | self.AddPage(page1_other, '其他(T)')
37 | self.AddPage(page1_tamper, 'Tamper(Y)')
38 |
39 | def cb_single(self, event, checkbox):
40 | cb = event.GetEventObject()
41 | if cb.IsChecked():
42 | checkbox.SetValue(False)
43 | # 这是最后一个Bind, 要skip哈! 不然改不了颜色
44 | event.Skip()
45 |
46 | def optimize_area_controller(self, event):
47 | if self.m._optimize_area_turn_all_ckbtn.IsChecked():
48 | self.m._optimize_area_predict_ckbtn.SetValue(False)
49 | self.m._optimize_area_keep_alive_ckbtn.SetValue(False)
50 | self.m._optimize_area_null_connect_ckbtn.SetValue(False)
51 |
52 | self.m._optimize_area_predict_ckbtn.Disable()
53 | self.m._optimize_area_keep_alive_ckbtn.Disable()
54 | self.m._optimize_area_null_connect_ckbtn.Disable()
55 | else:
56 | self.m._optimize_area_predict_ckbtn.Enable()
57 | self.m._optimize_area_keep_alive_ckbtn.Enable()
58 | self.m._optimize_area_null_connect_ckbtn.Enable()
59 | # 这是最后一个Bind, 要skip哈! 不然改不了颜色
60 | event.Skip()
61 |
62 | def build_page1_setting(self, layout):
63 | p = Scroll(self)
64 | m = self.m
65 |
66 | m._sqlmap_path_label.Create(p, label = '指定sqlmap路径:')
67 | m.sqlmap_path_entry.Create(p, value = 'sqlmap')
68 | m._sqlmap_path_chooser.Create(p, label = '打开')
69 | m._sqlmap_path_chooser.Bind(
70 | EVT_BUTTON,
71 | lambda evt, data = [m.sqlmap_path_entry]:
72 | self._handlers.set_file_entry_text(evt, data))
73 |
74 | self.build_page1_setting_inject(p, m)
75 | self.build_page1_setting_detection(p, m)
76 | self.build_page1_setting_tech(p, m)
77 | self.build_page1_setting_tamper(p, m)
78 | self.build_page1_setting_optimize(p, m)
79 | self.build_page1_setting_offen(p, m)
80 | self.build_page1_setting_hidden(p, m)
81 |
82 | vbox = layout.setting_sizer()
83 | # 不能用SetSizerAndFit, Fit会自适应的, 从而没有滚动条
84 | # p.SetSizerAndFit(vbox)
85 | p.SetSizer(vbox)
86 | p.SetupScrolling(scroll_x = False, scrollIntoView = False)
87 | return p
88 |
89 | def build_page1_setting_inject(self, panel, m):
90 | _sb = m._inject_area
91 | _sb.Create(panel, label = '注入选项')
92 |
93 | _choices = ['GET', 'POST', 'URI', 'Cookie', 'User-Agent'
94 | 'Referer', 'Host', '(custom) POST', '(custom HEADER)']
95 |
96 | m._inject_area_param_ckbtn.Create(_sb, label = '仅测参数')
97 | m._inject_area_param_entry.Create(_sb)
98 | m._inject_area_param_filter_ckbtn.Create(_sb, label = '仅测范围')
99 | m._inject_area_param_filter_combobox.Create(_sb, choices = _choices)
100 | m._inject_area_skip_static_ckbtn.Create(_sb, label = '跳过不像是动态的参数')
101 | m._inject_area_skip_static_ckbtn.SetValue(True)
102 | m._inject_area_skip_ckbtn.Create(_sb, label = '忽略参数')
103 | m._inject_area_skip_entry.Create(_sb)
104 | m._inject_area_param_exclude_ckbtn.Create(_sb, label = '忽略参数(正则)')
105 | m._inject_area_param_exclude_entry.Create(_sb)
106 | m._inject_area_prefix_ckbtn.Create(_sb, label = 'payload前缀')
107 | m._inject_area_prefix_entry.Create(_sb)
108 | m._inject_area_suffix_ckbtn.Create(_sb, label = 'payload后缀')
109 | m._inject_area_suffix_entry.Create(_sb)
110 | m._inject_area_dbms_ckbtn.Create(_sb, label = '固定DBMS为')
111 | m._inject_area_dbms_combobox.Create(_sb, choices = ['mysql', 'sqlite', 'sqlserver'])
112 | m._inject_area_dbms_cred_ckbtn.Create(_sb, label = 'DB认证')
113 | m._inject_area_dbms_cred_entry.Create(_sb)
114 | m._inject_area_os_ckbtn.Create(_sb, label = '固定OS为')
115 | m._inject_area_os_entry.Create(_sb)
116 | m._inject_area_no_cast_ckbtn.Create(_sb, label = '关闭数据类型转换')
117 | m._inject_area_no_escape_ckbtn.Create(_sb, label = '关掉string转义')
118 | self._inject_area_invalid_label = st(_sb, label = 'payload\'s invalid value:')
119 | self._inject_area_invalid_label.SetToolTip('默认情况下, 要使原参数值无效时会改成相反数\n'
120 | '真: id=13 假: id=-13')
121 | m._inject_area_invalid_bignum_ckbtn.Create(_sb, label = '使用大数')
122 | m._inject_area_invalid_logic_ckbtn.Create(_sb, label = '使用布尔运算')
123 | m._inject_area_invalid_string_ckbtn.Create(_sb, label = '使用随机字串')
124 |
125 | def build_page1_setting_detection(self, panel, m):
126 | _sb = m._detection_area
127 | _sb.Create(panel, label = '探测选项')
128 |
129 | m._detection_area_level_ckbtn.Create(_sb, label = '探测等级(范围)')
130 | m._detection_area_level_scale.Create(_sb,
131 | value = 1,
132 | minValue = 1,
133 | maxValue = 5,
134 | style = wx.SL_VALUE_LABEL)
135 | m._detection_area_risk_ckbtn.Create(_sb, label = 'payload危险等级')
136 | m._detection_area_risk_scale.Create(_sb,
137 | value = 1,
138 | minValue = 1,
139 | maxValue = 3,
140 | style = wx.SL_VALUE_LABEL)
141 | m._detection_area_str_ckbtn.Create(_sb, label = '指定True时的字符串')
142 | m._detection_area_str_entry.Create(_sb)
143 | m._detection_area_not_str_ckbtn.Create(_sb, label = '指定False时的字符串')
144 | m._detection_area_not_str_entry.Create(_sb)
145 | m._detection_area_re_ckbtn.Create(_sb, label = '指定正则')
146 | m._detection_area_re_entry.Create(_sb)
147 | m._detection_area_code_ckbtn.Create(_sb, label = '指定http状态码')
148 | m._detection_area_code_entry.Create(_sb)
149 | m._detection_area_text_only_ckbtn.Create(_sb, label = '仅对比文本')
150 | m._detection_area_text_only_ckbtn.Bind(
151 | EVT_CHECKBOX,
152 | lambda evt, cbtmp = m._detection_area_titles_ckbtn:
153 | self.cb_single(evt, cbtmp))
154 |
155 | m._detection_area_titles_ckbtn.Create(_sb, label = '仅对比title')
156 | m._detection_area_titles_ckbtn.Bind(
157 | EVT_CHECKBOX,
158 | lambda evt, cbtmp = m._detection_area_text_only_ckbtn:
159 | self.cb_single(evt, cbtmp))
160 |
161 | m._detection_area_smart_ckbtn.Create(_sb, label = '寻找明显目标并测试')
162 | self._detection_area_hr = wx.StaticLine(_sb)
163 | self._detection_area_level_note = st(_sb,
164 | label = 'Level 1(默认): 所有GET, POST参数\n'
165 | 'Level 2 追加: Cookie\n'
166 | 'Level 3 追加: User-Agent/Referer\n'
167 | 'Level 4 追加: 啥?\n'
168 | 'Level 5 追加: Host报头')
169 | self._detection_area_risk_note = st(_sb,
170 | label = 'Risk 1(默认): 基本无风险\n'
171 | 'Risk 2 追加: 大量时间型盲注\n'
172 | 'Risk 3 追加: OR型布尔盲注')
173 |
174 | def build_page1_setting_tech(self, panel, m):
175 | _sb = m._tech_area
176 | _sb.Create(panel, label = '各注入技术的选项')
177 |
178 | m._tech_area_tech_ckbtn.Create(_sb, label = '注入技术')
179 | m._tech_area_tech_entry.Create(_sb)
180 | m._tech_area_tech_entry.SetInitialSize(
181 | m._tech_area_tech_entry.GetSizeFromTextSize(
182 | m._tech_area_tech_entry.GetTextExtent("a" * 15).x))
183 | m._tech_area_time_sec_ckbtn.Create(_sb, label = '指定DB延迟几秒响应')
184 | m._tech_area_time_sec_entry.Create(_sb)
185 | m._tech_area_union_col_ckbtn.Create(_sb, label = '指定最大union列数')
186 | m._tech_area_union_col_entry.Create(_sb)
187 | m._tech_area_union_char_ckbtn.Create(_sb, label = '指定枚举列数时所用字符')
188 | m._tech_area_union_char_entry.Create(_sb)
189 | m._tech_area_union_from_ckbtn.Create(_sb, label = '指定枚举列数时from的表名')
190 | m._tech_area_union_from_entry.Create(_sb)
191 | m._tech_area_dns_ckbtn.Create(_sb, label = '指定DNS')
192 | m._tech_area_dns_entry.Create(_sb)
193 | m._tech_area_second_url_ckbtn.Create(_sb, label = '指定二阶响应的url')
194 | m._tech_area_second_url_entry.Create(_sb)
195 | m._tech_area_second_req_ckbtn.Create(_sb, label = '使用含二阶HTTP请求的文件:')
196 | m._tech_area_second_req_entry.Create(_sb)
197 | m._tech_area_second_req_chooser.Create(_sb, label = '打开')
198 | m._tech_area_second_req_chooser.Bind(
199 | EVT_BUTTON,
200 | lambda evt, data = [m._tech_area_second_req_entry]:
201 | self._handlers.set_file_entry_text(evt, data))
202 |
203 | def build_page1_setting_tamper(self, panel, m):
204 | _sb = m._tamper_area
205 | _sb.Create(panel, label = 'tamper脚本')
206 |
207 | # 多行文本框的默认size太小了
208 | m._tamper_area_tamper_view.Create(_sb,
209 | size = (300, -1),
210 | style = wx.TE_MULTILINE)
211 |
212 | def build_page1_setting_optimize(self, panel, m):
213 | _sb = m._optimize_area
214 | _sb.Create(panel, label = '性能优化')
215 |
216 | m._optimize_area_turn_all_ckbtn.Create(_sb, label = '启用所有优化选项')
217 | m._optimize_area_thread_num_ckbtn.Create(_sb, label = '使用线程数:')
218 | m._optimize_area_thread_num_spinbtn.Create(_sb, value = '2', min = 2, max = 10000)
219 | m._optimize_area_predict_ckbtn.Create(_sb, label = '预测通常的查询结果')
220 | m._optimize_area_keep_alive_ckbtn.Create(_sb, label = 'http连接使用keep-alive')
221 | m._optimize_area_null_connect_ckbtn.Create(_sb, label = '只比较响应大小报头, 不获取响应主体')
222 |
223 | m._optimize_area_turn_all_ckbtn.Bind(EVT_CHECKBOX, self.optimize_area_controller)
224 |
225 | def build_page1_setting_offen(self, panel, m):
226 | _sb = m._offen_area
227 | _sb.Create(panel, label = '常用选项')
228 |
229 | m._general_area_verbose_ckbtn.Create(_sb, label = '输出详细程度')
230 | m._general_area_verbose_scale.Create(_sb,
231 | value = 1,
232 | minValue = 0,
233 | maxValue = 6,
234 | style = wx.SL_VALUE_LABEL)
235 | m._general_area_finger_ckbtn.Create(_sb, label = '精确检测DB等版本信息')
236 | m._general_area_hex_ckbtn.Create(_sb, label = '响应使用hex转换')
237 | m._general_area_batch_ckbtn.Create(_sb, label = '非交互模式, 一切皆默认')
238 | m._misc_area_wizard_ckbtn.Create(_sb, label = '新手向导')
239 |
240 | def build_page1_setting_hidden(self, panel, m):
241 | _sb = m._hidden_area
242 | _sb.Create(panel, label = 'Hidden')
243 |
244 | m._hidden_area_crack_ckbtn.Create(_sb, label = '--crack')
245 | m._hidden_area_debug_ckbtn.Create(_sb, label = '--debug')
246 | m._hidden_area_profile_ckbtn.Create(_sb, label = '--profile')
247 | m._hidden_area_disable_precon_ckbtn.Create(_sb, label = '--disable-precon')
248 | m._hidden_area_disable_stats_ckbtn.Create(_sb, label = '--disable-stats')
249 | m._hidden_area_force_dbms_ckbtn.Create(_sb, label = '--force-dbms')
250 | m._hidden_area_force_dns_ckbtn.Create(_sb, label = '--force-dns')
251 | m._hidden_area_force_pivoting_ckbtn.Create(_sb, label = '--force-pivoting')
252 | m._hidden_area_smoke_test_ckbtn.Create(_sb, label = '--smoke-test')
253 | m._hidden_area_live_test_ckbtn.Create(_sb, label = '--live-test')
254 | m._hidden_area_vuln_test_ckbtn.Create(_sb, label = '--vuln-test')
255 | m._hidden_area_murphy_rate_ckbtn.Create(_sb, label = '--murphy-rate')
256 | m._hidden_area_stop_fail_ckbtn.Create(_sb, label = '--stop-fail')
257 | m._hidden_area_run_case_ckbtn.Create(_sb, label = '--run-case')
258 | m._hidden_area_dummy_ckbtn.Create(_sb, label = '--dummy')
259 | m._hidden_area_api_ckbtn.Create(_sb, label = '--api')
260 | m._hidden_area_taskid_ckbtn.Create(_sb, label = '--taskid')
261 | m._hidden_area_database_ckbtn.Create(_sb, label = '--database')
262 |
263 | def build_page1_request(self, layout):
264 | p = Scroll(self, style = wx.BORDER_THEME)
265 | m = self.m
266 |
267 | self.build_page1_request_header(p, m)
268 | self.build_page1_request_data(p, m)
269 | self.build_page1_request_custom(p, m)
270 | self.build_page1_request_proxy(p, m)
271 |
272 | vbox = layout.request_sizer()
273 | # 不能用SetSizerAndFit, Fit会自适应的, 从而没有滚动条
274 | # p.SetSizerAndFit(vbox)
275 | p.SetSizer(vbox)
276 | p.SetupScrolling(scroll_x = False, scrollIntoView = False)
277 | return p
278 |
279 | def build_page1_request_header(self, panel, m):
280 | _sb = m._request_header_area
281 | _sb.Create(panel, label = 'HTTP header')
282 |
283 | m._request_area_random_agent_ckbtn.Create(_sb, label = '随机User-Agent头')
284 | m._request_area_random_agent_ckbtn.SetValue(True)
285 | m._request_area_mobile_ckbtn.Create(_sb, label = '模拟手机请求')
286 | m._request_area_user_agent_ckbtn.Create(_sb, label = '指定User-Agent头')
287 | m._request_area_user_agent_entry.Create(_sb)
288 | m._request_area_host_ckbtn.Create(_sb, label = 'Host头')
289 | m._request_area_host_entry.Create(_sb)
290 | m._request_area_referer_ckbtn.Create(_sb, label = 'referer头')
291 | m._request_area_referer_entry.Create(_sb)
292 | m._request_area_header_ckbtn.Create(_sb, label = '--header(-H)')
293 | m._request_area_header_entry.Create(_sb)
294 | m._request_area_headers_ckbtn.Create(_sb, label = '额外的headers')
295 | m._request_area_headers_entry.Create(_sb)
296 |
297 | def build_page1_request_data(self, panel, m):
298 | _sb = m._request_data_area
299 | _sb.Create(panel, label = 'HTTP data')
300 |
301 | m._request_area_method_ckbtn.Create(_sb, label = 'HTTP请求方式')
302 | m._request_area_method_entry.Create(_sb)
303 | m._request_area_param_del_ckbtn.Create(_sb, label = '指定--data=中的参数分隔符')
304 | m._request_area_param_del_entry.Create(_sb)
305 | m._request_area_chunked_ckbtn.Create(_sb, label = '"分块传输"发送POST请求')
306 | m._request_area_post_ckbtn.Create(_sb, label = '通过POST提交data:')
307 | self._request_data_hr1 = wx.StaticLine(_sb)
308 | m._request_area_post_entry.Create(_sb)
309 | m._request_area_cookie_ckbtn.Create(_sb, label = '要包含的Cookie:')
310 | m._request_area_cookie_entry.Create(_sb)
311 | m._request_area_cookie_del_ckbtn.Create(_sb, label = '指定cookie分隔符')
312 | m._request_area_cookie_del_entry.Create(_sb)
313 | m._request_area_drop_set_cookie_ckbtn.Create(_sb, label = '丢弃Set-Cookie头')
314 | m._request_area_live_cookies_ckbtn.Create(_sb, label = 'live_cookies')
315 | m._request_area_live_cookies_entry.Create(_sb)
316 | m._request_area_live_cookies_chooser.Create(_sb, label = '打开')
317 | m._request_area_live_cookies_chooser.Bind(
318 | EVT_BUTTON,
319 | lambda evt, data = [m._request_area_live_cookies_entry]:
320 | self._handlers.set_file_entry_text(evt, data))
321 |
322 | m._request_area_load_cookies_ckbtn.Create(_sb, label = '本地Cookie文件')
323 | m._request_area_load_cookies_entry.Create(_sb)
324 | m._request_area_load_cookies_chooser.Create(_sb, label = '打开')
325 | m._request_area_load_cookies_chooser.Bind(
326 | EVT_BUTTON,
327 | lambda evt, data = [m._request_area_load_cookies_entry]:
328 | self._handlers.set_file_entry_text(evt, data))
329 |
330 | self._request_data_hr2 = wx.StaticLine(_sb)
331 | m._request_area_auth_type_ckbtn.Create(_sb, label = 'http认证类型')
332 | m._request_area_auth_type_entry.Create(_sb)
333 | m._request_area_auth_cred_ckbtn.Create(_sb, label = 'http认证账密')
334 | m._request_area_auth_cred_entry.Create(_sb)
335 | m._request_area_auth_file_ckbtn.Create(_sb, label = 'http认证文件')
336 | m._request_area_auth_file_entry.Create(_sb)
337 | m._request_area_auth_file_chooser.Create(_sb, label = '打开')
338 | m._request_area_auth_file_chooser.Bind(
339 | EVT_BUTTON,
340 | lambda evt, data = [m._request_area_auth_file_entry]:
341 | self._handlers.set_file_entry_text(evt, data))
342 |
343 | m._request_area_csrf_method_ckbtn.Create(_sb, label = 'csrf_method')
344 | m._request_area_csrf_method_entry.Create(_sb)
345 | m._request_area_csrf_retries_ckbtn.Create(_sb, label = 'csrf_retries')
346 | m._request_area_csrf_retries_entry.Create(_sb)
347 | m._request_area_csrf_token_ckbtn.Create(_sb, label = 'csrf_token')
348 | m._request_area_csrf_token_entry.Create(_sb)
349 | m._request_area_csrf_url_ckbtn.Create(_sb, label = '获取csrf_token的url')
350 | m._request_area_csrf_url_entry.Create(_sb)
351 |
352 | def build_page1_request_custom(self, panel, m):
353 | _sb = m._request_custom_area
354 | _sb.Create(panel, label = 'request定制')
355 |
356 | m._request_area_ignore_timeouts_ckbtn.Create(_sb, label = '忽略连接超时')
357 | m._request_area_ignore_redirects_ckbtn.Create(_sb, label = '忽略重定向')
358 | m._request_area_ignore_code_ckbtn.Create(_sb, label = '忽略错误型状态码:')
359 | m._request_area_ignore_code_entry.Create(_sb, value = '401')
360 | m._request_area_ignore_code_entry.SetInitialSize(
361 | m._request_area_ignore_code_entry.GetSizeFromTextSize(
362 | m._request_area_ignore_code_entry.GetTextExtent("a" * 20).x))
363 | m._request_area_skip_urlencode_ckbtn.Create(_sb, label = 'payload不使用url编码')
364 | m._request_area_force_ssl_ckbtn.Create(_sb, label = '强制使用HTTPS')
365 | m._request_area_hpp_ckbtn.Create(_sb, label = 'HTTP参数污染')
366 | m._request_area_delay_ckbtn.Create(_sb, label = '请求间隔(秒)')
367 | m._request_area_delay_entry.Create(_sb)
368 | m._request_area_timeout_ckbtn.Create(_sb, label = '超时前等几秒')
369 | m._request_area_timeout_entry.Create(_sb, value = '30')
370 | m._request_area_retries_ckbtn.Create(_sb, label = '超时重试次数')
371 | m._request_area_retries_entry.Create(_sb, value = '3')
372 | m._request_area_randomize_ckbtn.Create(_sb, label = '指定要随机改变值的参数')
373 | m._request_area_randomize_entry.Create(_sb)
374 | m._request_area_eval_ckbtn.Create(_sb, label = '--eval=')
375 | m._request_area_eval_entry.Create(_sb)
376 |
377 | def build_page1_request_proxy(self, panel, m):
378 | _sb = m._request_proxy_area
379 | _sb.Create(panel, label = '隐匿/代理')
380 |
381 | m._request_area_safe_url_ckbtn.Create(_sb, label = '顺便掺杂地访问一个安全url')
382 | m._request_area_safe_url_entry.Create(_sb)
383 | m._request_area_safe_post_ckbtn.Create(_sb, label = '提交到安全url的post数据')
384 | m._request_area_safe_post_entry.Create(_sb)
385 | m._request_area_safe_req_ckbtn.Create(_sb, label = '从文件载入safe HTTP请求')
386 | m._request_area_safe_req_entry.Create(_sb)
387 | m._request_area_safe_req_chooser.Create(_sb, label = '打开')
388 | m._request_area_safe_req_chooser.Bind(
389 | EVT_BUTTON,
390 | lambda evt, data = [m._request_area_safe_req_entry]:
391 | self._handlers.set_file_entry_text(evt, data))
392 |
393 | m._request_area_safe_freq_ckbtn.Create(_sb, label = '访问安全url的频率')
394 | m._request_area_safe_freq_entry.Create(_sb)
395 | self._request_proxy_hr = wx.StaticLine(_sb)
396 | m._request_area_ignore_proxy_ckbtn.Create(_sb, label = '忽略系统默认代理')
397 | m._request_area_proxy_freq_ckbtn.Create(_sb, label = '--proxy-freq')
398 | m._request_area_proxy_freq_entry.Create(_sb)
399 | m._request_area_proxy_file_ckbtn.Create(_sb, label = '代理列表文件')
400 | m._request_area_proxy_file_entry.Create(_sb)
401 | m._request_area_proxy_file_chooser.Create(_sb, label = '打开')
402 | m._request_area_proxy_file_chooser.Bind(
403 | EVT_BUTTON,
404 | lambda evt, data = [m._request_area_proxy_file_entry]:
405 | self._handlers.set_file_entry_text(evt, data))
406 |
407 | m._request_area_proxy_ckbtn.Create(_sb, label = '使用代理')
408 | m._request_area_proxy_ip_label.Create(_sb, label = 'IP:')
409 | m._request_area_proxy_ip_entry.Create(_sb)
410 | m._request_area_proxy_port_label.Create(_sb, label = 'PORT:')
411 | m._request_area_proxy_port_entry.Create(_sb)
412 | m._request_area_proxy_username_label.Create(_sb, label = 'username:')
413 | m._request_area_proxy_username_entry.Create(_sb)
414 | m._request_area_proxy_password_label.Create(_sb, label = 'passwd:')
415 | m._request_area_proxy_password_entry.Create(_sb)
416 | m._request_area_tor_ckbtn.Create(_sb, label = '使用Tor匿名网络')
417 | m._request_area_tor_port_ckbtn.Create(_sb, label = 'Tor端口:')
418 | m._request_area_tor_port_entry.Create(_sb)
419 | m._request_area_tor_type_ckbtn.Create(_sb, label = 'Tor代理类型')
420 | m._request_area_tor_type_entry.Create(_sb)
421 | m._request_area_check_tor_ckbtn.Create(_sb, label = '检查Tor连接')
422 |
423 | def build_page1_enumeration(self, layout):
424 | p = Panel(self)
425 | m = self.m
426 |
427 | self.build_page1_enumeration_enum(p, m)
428 | self.build_page1_enumeration_dump(p, m)
429 | self.build_page1_enumeration_limit(p, m)
430 | self.build_page1_enumeration_blind(p, m)
431 | self.build_page1_enumeration_meta(p, m)
432 | self.build_page1_enumeration_runsql(p, m)
433 | self.build_page1_enumeration_brute_force(p, m)
434 |
435 | vbox = layout.enumeration_sizer()
436 | p.SetSizer(vbox)
437 | return p
438 |
439 | def build_page1_enumeration_enum(self, panel, m):
440 | _sb = m._enum_area
441 | _sb.Create(panel, label = '枚举')
442 | # 要与_enum_area_opts_ckbtns的结构一致!
443 | _enum_area_enum_labels = (
444 | ('DB banner', '当前用户', '当前数据库', '主机名', '是否为DBA'),
445 | ('用户', '密码', '权限', '角色', '库名'),
446 | ('表名', '列名', '架构', '行数', '备注'))
447 | for _i, _l in enumerate(m._enum_area_opts_ckbtns): # 三列
448 | for _j, _cb in enumerate(_l):
449 | _cb.Create(_sb, label = _enum_area_enum_labels[_i][_j])
450 |
451 | def build_page1_enumeration_dump(self, panel, m):
452 | _sb = m._dump_area
453 | _sb.Create(panel, label = 'Dump(转储)')
454 |
455 | m._dump_area_dump_ckbtn.Create(_sb, label = 'dump(某库某表的条目)')
456 | m._dump_area_repair_ckbtn.Create(_sb, label = '重新获取有未知符号(?)的条目')
457 | m._dump_area_statements_ckbtn.Create(_sb, label = '获取正在运行的sql语句')
458 | m._dump_area_search_ckbtn.Create(_sb, label = '搜索')
459 | m._dump_area_no_sys_db_ckbtn.Create(_sb, label = '排除系统库')
460 | m._dump_area_dump_all_ckbtn.Create(_sb, label = '全部dump(拖库)')
461 |
462 | def build_page1_enumeration_limit(self, panel, m):
463 | _sb = m._limit_area
464 | _sb.Create(panel, label = 'limit(dump时的限制)')
465 |
466 | m._limit_area_start_ckbtn.Create(_sb, label = '始于第几条')
467 | m._limit_area_start_entry.Create(_sb)
468 | m._limit_area_start_entry.SetInitialSize(
469 | m._limit_area_start_entry.GetSizeFromTextSize(
470 | m._limit_area_start_entry.GetTextExtent("a" * 15).x))
471 | # self._limit_area_start_label = st(_sb, label = '行')
472 | m._limit_area_stop_ckbtn.Create(_sb, label = '止于第几条')
473 | m._limit_area_stop_entry.Create(_sb)
474 | m._limit_area_stop_entry.SetInitialSize(
475 | m._limit_area_stop_entry.GetSizeFromTextSize(
476 | m._limit_area_stop_entry.GetTextExtent("a" * 15).x))
477 | # self._limit_area_stop_label = st(_sb, label = '行')
478 |
479 | def build_page1_enumeration_blind(self, panel, m):
480 | _sb = m._blind_area
481 | _sb.Create(panel, label = '盲注选项')
482 |
483 | m._blind_area_first_ckbtn.Create(_sb, label = '从第几个字符')
484 | m._blind_area_first_entry.Create(_sb)
485 | # self._blind_area_first_label = st(_sb, label = '个字符')
486 | m._blind_area_last_ckbtn.Create(_sb, label = '到第几个字符')
487 | m._blind_area_last_entry.Create(_sb)
488 | # self._blind_area_last_label = st(_sb, label = '个字符')
489 | # self._blind_area_note_label = st(_sb, label = '只适用于盲注,\n因为报错,union注入要求列数相同')
490 |
491 | def build_page1_enumeration_meta(self, panel, m):
492 | _sb = m._meta_area
493 | _sb.Create(panel, label = '数据库名, 表名, 列名...')
494 |
495 | m._meta_area_D_ckbtn.Create(_sb, label = '指定库名')
496 | m._meta_area_D_entry.Create(_sb)
497 | m._meta_area_T_ckbtn.Create(_sb, label = '指定表名')
498 | m._meta_area_T_entry.Create(_sb)
499 | m._meta_area_C_ckbtn.Create(_sb, label = '指定列名')
500 | m._meta_area_C_entry.Create(_sb)
501 | m._meta_area_U_ckbtn.Create(_sb, label = '指定用户')
502 | m._meta_area_U_entry.Create(_sb)
503 | m._meta_area_X_ckbtn.Create(_sb, label = '排除标志符')
504 | m._meta_area_X_entry.Create(_sb)
505 | m._meta_area_pivot_ckbtn.Create(_sb, label = '指定Pivot列名')
506 | m._meta_area_pivot_entry.Create(_sb)
507 | m._meta_area_where_ckbtn.Create(_sb, label = 'where子句')
508 | m._meta_area_where_entry.Create(_sb)
509 |
510 | def build_page1_enumeration_runsql(self, panel, m):
511 | _sb = m._runsql_area
512 | _sb.Create(panel, label = '执行SQL语句')
513 |
514 | m._runsql_area_sql_query_ckbtn.Create(_sb, label = 'SQL语句:')
515 | m._runsql_area_sql_query_entry.Create(_sb)
516 | m._runsql_area_sql_shell_ckbtn.Create(_sb, label = '打开一个SQL交互shell')
517 | m._runsql_area_sql_file_ckbtn.Create(_sb, label = '本地SQL文件:')
518 | m._runsql_area_sql_file_entry.Create(_sb)
519 | m._runsql_area_sql_file_chooser.Create(_sb, label = '打开')
520 | m._runsql_area_sql_file_chooser.Bind(
521 | EVT_BUTTON,
522 | lambda evt, data = [m._runsql_area_sql_file_entry]:
523 | self._handlers.set_file_entry_text(evt, data))
524 |
525 | def build_page1_enumeration_brute_force(self, panel, m):
526 | _sb = m._brute_force_area
527 | _sb.Create(panel, label = '暴破表名/列名')
528 |
529 | self._brute_force_area_label = st(_sb, label = 'check existence of:')
530 | m._brute_force_area_common_tables_ckbtn.Create(_sb, label = '常用表名')
531 | m._brute_force_area_common_columns_ckbtn.Create(_sb, label = '常用列名')
532 | m._brute_force_area_common_files_ckbtn.Create(_sb, label = '常用文件')
533 |
534 | def build_page1_file(self, layout):
535 | p = Panel(self)
536 | m = self.m
537 |
538 | self._page1_file_note_label = st(p,
539 | label = 'Note: only if stacked query(堆查询注入) worked, '
540 | 'these functions below can be used except udf!')
541 | self.build_page1_file_read(p, m)
542 | self.build_page1_file_write(p, m)
543 | self.build_page1_file_os_access(p, m)
544 | self.build_page1_file_registry(p, m)
545 |
546 | vbox = layout.file_sizer()
547 | p.SetSizer(vbox)
548 | return p
549 |
550 | def build_page1_file_read(self, panel, m):
551 | _sb = m._file_read_area
552 | _sb.Create(panel, label = '读取远程文件')
553 |
554 | m._file_read_area_file_read_ckbtn.Create(_sb, label = '远程文件路径(--file-read=)')
555 | m._file_read_area_file_read_entry.Create(_sb, value = '/etc/passwd')
556 | m._file_read_area_file_read_btn.Create(_sb, label = '查看')
557 |
558 | m._file_read_area_file_read_btn.Bind(EVT_BUTTON, self._handlers.read_dumped_file)
559 |
560 | def build_page1_file_write(self, panel, m):
561 | _sb = m._file_write_area
562 | _sb.Create(panel, label = '文件上传')
563 |
564 | m._file_write_area_udf_ckbtn.Create(_sb, label = '注入UDF(仅限MySQL和PostgreSQL)')
565 | m._file_write_area_shared_lib_ckbtn.Create(_sb, label = '本地共享库路径(--shared-lib=)')
566 | m._file_write_area_shared_lib_entry.Create(_sb)
567 | m._file_write_area_shared_lib_chooser.Create(_sb, label = '打开')
568 | m._file_write_area_shared_lib_chooser.Bind(
569 | EVT_BUTTON,
570 | lambda evt, data = [m._file_write_area_shared_lib_entry]:
571 | self._handlers.set_file_entry_text(evt, data))
572 |
573 | m._file_write_area_file_write_ckbtn.Create(_sb, label = '本地文件路径(--file-write=)')
574 | m._file_write_area_file_write_entry.Create(_sb)
575 | m._file_write_area_file_write_chooser.Create(_sb, label = '打开')
576 | m._file_write_area_file_write_chooser.Bind(
577 | EVT_BUTTON,
578 | lambda evt, data = [m._file_write_area_file_write_entry]:
579 | self._handlers.set_file_entry_text(evt, data))
580 |
581 | m._file_write_area_file_dest_ckbtn.Create(_sb, label = '远程文件路径(--file-dest=)')
582 | m._file_write_area_file_dest_entry.Create(_sb)
583 |
584 | def build_page1_file_os_access(self, panel, m):
585 | _sb = m._os_access_area
586 | _sb.Create(panel, label = '访问后端OS')
587 |
588 | m._os_access_area_os_cmd_ckbtn.Create(_sb, label = '执行CLI命令')
589 | m._os_access_area_os_cmd_entry.Create(_sb)
590 | m._os_access_area_os_shell_ckbtn.Create(_sb, label = '获取交互shell')
591 | self._os_access_area_for_msf_label = st(_sb, label = 'Meterpreter相关(TCP连接):')
592 | m._os_access_area_os_pwn_ckbtn.Create(_sb, label = '--os-pwn')
593 | m._os_access_area_os_smbrelay_ckbtn.Create(_sb, label = '--os-smbrelay')
594 | m._os_access_area_os_bof_ckbtn.Create(_sb, label = '--os-bof')
595 | m._os_access_area_priv_esc_ckbtn.Create(_sb, label = '--priv-esc')
596 | m._os_access_area_msf_path_ckbtn.Create(_sb, label = '本地Metasploit安装路径')
597 | m._os_access_area_msf_path_entry.Create(_sb)
598 | m._os_access_area_msf_path_chooser.Create(_sb, label = '打开')
599 | m._os_access_area_msf_path_chooser.Bind(
600 | EVT_BUTTON,
601 | lambda evt, data = [m._os_access_area_msf_path_entry, '选择 本地Metasploit安装目录']:
602 | self._handlers.set_file_entry_text(evt, data))
603 |
604 | m._os_access_area_tmp_path_ckbtn.Create(_sb, label = '远程临时目录(绝对路径)')
605 | m._os_access_area_tmp_path_entry.Create(_sb)
606 |
607 | def build_page1_file_registry(self, panel, m):
608 | _sb = m._registry_area
609 | _sb.Create(panel, label = '访问WIN下注册表')
610 |
611 | m._registry_area_reg_ckbtn.Create(_sb, label = '键值操作:')
612 | m._registry_area_reg_choice.Create(_sb, choices = ['--reg-read', '--reg-add', '--reg-del'])
613 | m._registry_area_reg_choice.SetSelection(0)
614 | m._registry_area_reg_key_label.Create(_sb, label = '键路径')
615 | m._registry_area_reg_key_entry.Create(_sb)
616 | m._registry_area_reg_value_label.Create(_sb, label = '键名')
617 | m._registry_area_reg_value_entry.Create(_sb)
618 | m._registry_area_reg_data_label.Create(_sb, label = '键值')
619 | m._registry_area_reg_data_entry.Create(_sb)
620 | m._registry_area_reg_type_label.Create(_sb, label = '键值类型')
621 | m._registry_area_reg_type_entry.Create(_sb)
622 |
623 | def build_page1_other(self, layout):
624 | p = Panel(self)
625 | # p = Scroll(self) # 总有一个标签会被掩盖widget, 只能使用_dummy
626 | m = self.m
627 |
628 | self.build_page1_other_general(p, m)
629 | self.build_page1_other_misc(p, m)
630 |
631 | vbox = layout.other_sizer()
632 | # p.SetSizerAndFit(vbox), 没用~, 最后一个widget还是会被掩盖
633 | p.SetSizer(vbox)
634 | # p.SetupScrolling(scroll_x = False)
635 | return p
636 |
637 | def build_page1_other_general(self, panel, m):
638 | _sb = m._general_area
639 | _sb.Create(panel, label = '通用项')
640 |
641 | m._general_area_check_internet_ckbtn.Create(_sb, label = '检查与目标的网络连接')
642 | m._general_area_fresh_queries_ckbtn.Create(_sb, label = '刷新此次查询')
643 | m._general_area_forms_ckbtn.Create(_sb, label = '获取form表单参数并测试')
644 | m._general_area_parse_errors_ckbtn.Create(_sb, label = '解析并显示响应中的错误信息')
645 | m._misc_area_cleanup_ckbtn.Create(_sb, label = '清理DBMS中的入侵痕迹!')
646 | m._general_area_base64_ckbtn.Create(_sb, label = '--base64')
647 | m._general_area_base64_entry.Create(_sb)
648 | m._general_area_base64_safe_ckbtn.Create(_sb, label = '--base64-safe')
649 | m._general_area_table_prefix_ckbtn.Create(_sb, label = '临时表前缀')
650 | m._general_area_table_prefix_entry.Create(_sb)
651 | # size = ()是以px为单位的, 如果想设成以字符长度为宽, 蛋疼如下~~:
652 | m._general_area_table_prefix_entry.SetInitialSize(
653 | m._general_area_table_prefix_entry.GetSizeFromTextSize(
654 | m._general_area_table_prefix_entry.GetTextExtent("a" * 16).x))
655 | m._general_area_binary_fields_ckbtn.Create(_sb, label = '有二进制值的字段')
656 | m._general_area_binary_fields_entry.Create(_sb)
657 | m._general_area_binary_fields_entry.SetInitialSize(
658 | m._general_area_binary_fields_entry.GetSizeFromTextSize(
659 | m._general_area_binary_fields_entry.GetTextExtent("a" * 16).x))
660 | m._general_area_preprocess_ckbtn.Create(_sb, label = '处理请求的脚本')
661 | m._general_area_preprocess_entry.Create(_sb)
662 | m._general_area_preprocess_chooser.Create(_sb, label = '打开')
663 | m._general_area_preprocess_chooser.Bind(
664 | EVT_BUTTON,
665 | lambda evt, data = [m._general_area_preprocess_entry]:
666 | self._handlers.set_file_entry_text(evt, data))
667 | m._general_area_postprocess_ckbtn.Create(_sb, label = '处理响应的脚本')
668 | m._general_area_postprocess_entry.Create(_sb)
669 | m._general_area_postprocess_chooser.Create(_sb, label = '打开')
670 | m._general_area_postprocess_chooser.Bind(
671 | EVT_BUTTON,
672 | lambda evt, data = [m._general_area_postprocess_entry]:
673 | self._handlers.set_file_entry_text(evt, data))
674 |
675 | m._general_area_charset_ckbtn.Create(_sb, label = '盲注所用的字符集合')
676 | m._general_area_charset_entry.Create(_sb, value = '0123456789abcdef')
677 | m._general_area_encoding_ckbtn.Create(_sb, label = '字符编码(用于数据获取)')
678 | m._general_area_encoding_entry.Create(_sb, value = 'GBK')
679 | m._general_area_web_root_ckbtn.Create(_sb, label = '远程web的根目录')
680 | m._general_area_web_root_entry.Create(_sb)
681 | m._general_area_scope_ckbtn.Create(_sb, label = '从代理日志过滤出目标(正则)')
682 | m._general_area_scope_entry.Create(_sb)
683 | m._general_area_scope_chooser.Create(_sb, label = '打开')
684 | m._general_area_scope_chooser.Bind(
685 | EVT_BUTTON,
686 | lambda evt, data = [m._general_area_scope_entry]:
687 | self._handlers.set_file_entry_text(evt, data))
688 |
689 | m._general_area_test_filter_ckbtn.Create(_sb, label = '测试过滤器(从payload/title选择)')
690 | m._general_area_test_filter_entry.Create(_sb)
691 | m._general_area_test_skip_ckbtn.Create(_sb, label = '测试跳过(从payload/title选择)')
692 | m._general_area_test_skip_entry.Create(_sb)
693 |
694 | m._general_area_crawl_ckbtn.Create(_sb, label = '爬网站(的层级/深度)')
695 | m._general_area_crawl_entry.Create(_sb)
696 | m._general_area_crawl_exclude_ckbtn.Create(_sb, label = '爬站时排除(正则)页面')
697 | m._general_area_crawl_exclude_entry.Create(_sb)
698 | self._general_area_hr = wx.StaticLine(_sb)
699 | m._general_area_traffic_file_ckbtn.Create(_sb, label = '转存所有http流量到文本')
700 | m._general_area_traffic_file_entry.Create(_sb)
701 | m._general_area_traffic_file_chooser.Create(_sb, label = '打开')
702 | m._general_area_traffic_file_chooser.Bind(
703 | EVT_BUTTON,
704 | lambda evt, data = [m._general_area_traffic_file_entry]:
705 | self._handlers.set_file_entry_text(evt, data))
706 |
707 | m._general_area_har_ckbtn.Create(_sb, label = '转存至HAR文件')
708 | m._general_area_har_entry.Create(_sb)
709 | m._general_area_har_chooser.Create(_sb, label = '打开')
710 | m._general_area_har_chooser.Bind(
711 | EVT_BUTTON,
712 | lambda evt, data = [m._general_area_har_entry]:
713 | self._handlers.set_file_entry_text(evt, data))
714 |
715 | m._general_area_flush_session_ckbtn.Create(_sb, label = '清空目标的会话文件')
716 | m._general_area_dump_format_ckbtn.Create(_sb, label = 'dump结果的文件格式')
717 | m._general_area_dump_format_entry.Create(_sb)
718 | m._general_area_csv_del_ckbtn.Create(_sb, label = '(csv文件的)分隔符')
719 | m._general_area_csv_del_entry.Create(_sb, value = ',')
720 | m._general_area_save_ckbtn.Create(_sb, label = '保存选项至INI文件')
721 | m._general_area_save_entry.Create(_sb)
722 | m._general_area_save_chooser.Create(_sb, label = '打开')
723 | m._general_area_save_chooser.Bind(
724 | EVT_BUTTON,
725 | lambda evt, data = [m._general_area_save_entry]:
726 | self._handlers.set_file_entry_text(evt, data))
727 |
728 | m._general_area_session_file_ckbtn.Create(_sb, label = '载入会话文件')
729 | m._general_area_session_file_entry.Create(_sb)
730 | m._general_area_session_file_chooser.Create(_sb, label = '打开')
731 | m._general_area_session_file_chooser.Bind(
732 | EVT_BUTTON,
733 | lambda evt, data = [m._general_area_session_file_entry]:
734 | self._handlers.set_file_entry_text(evt, data))
735 |
736 | m._general_area_output_dir_ckbtn.Create(_sb, label = '指定output目录')
737 | m._general_area_output_dir_entry.Create(_sb)
738 | m._general_area_output_dir_chooser.Create(_sb, label = '打开')
739 | m._general_area_output_dir_chooser.Bind(
740 | EVT_BUTTON,
741 | lambda evt, data = [m._general_area_output_dir_entry, '选择 结果保存在哪']:
742 | self._handlers.set_file_entry_text(evt, data))
743 |
744 | def build_page1_other_misc(self, panel, m):
745 | _sb = m._misc_area
746 | _sb.Create(panel, label = '杂项')
747 |
748 | m._misc_area_skip_heuristics_ckbtn.Create(_sb, label = '--skip-heuristics')
749 | m._misc_area_skip_waf_ckbtn.Create(_sb, label = '跳过WAF/IPS侦测')
750 | m._misc_area_unstable_ckbtn.Create(_sb, label = '--unstable')
751 | m._misc_area_list_tampers_ckbtn.Create(_sb, label = '列出可用的tamper脚本')
752 | m._misc_area_sqlmap_shell_ckbtn.Create(_sb, label = '打开sqlmap交互shell')
753 | m._misc_area_disable_color_ckbtn.Create(_sb, label = '禁用终端输出的颜色')
754 | m._general_area_eta_ckbtn.Create(_sb, label = '显示剩余时间')
755 | m._misc_area_gpage_ckbtn.Create(_sb, label = 'GOOGLEDORK时的页码')
756 | m._misc_area_gpage_spinbtn.Create(_sb, value = '1', min = 1, max = 100)
757 | m._misc_area_beep_ckbtn.Create(_sb, label = '响铃')
758 | m._misc_area_offline_ckbtn.Create(_sb, label = '离线模式(仅使用本地会话数据)')
759 | m._misc_area_purge_ckbtn.Create(_sb, label = '抹除所有本地记录!')
760 | m._misc_area_dependencies_ckbtn.Create(_sb, label = '检查丢失的(非核心的)sqlmap依赖')
761 | m._misc_area_update_ckbtn.Create(_sb, label = '更新sqlmap')
762 | m._misc_area_alert_ckbtn.Create(_sb, label = '发现注入时运行本地命令:')
763 | m._misc_area_alert_entry.Create(_sb)
764 | m._misc_area_tmp_dir_ckbtn.Create(_sb, label = '本地临时目录')
765 | m._misc_area_tmp_dir_entry.Create(_sb)
766 | m._misc_area_tmp_dir_chooser.Create(_sb, label = '打开')
767 | m._misc_area_tmp_dir_chooser.Bind(
768 | EVT_BUTTON,
769 | lambda evt, data = [m._misc_area_tmp_dir_entry, '选择 本地临时目录']:
770 | self._handlers.set_file_entry_text(evt, data))
771 |
772 | m._misc_area_answers_ckbtn.Create(_sb, label = '设置交互时的问题答案:')
773 | m._misc_area_answers_entry.Create(_sb, value = 'quit=N,follow=N')
774 | m._misc_area_z_ckbtn.Create(_sb, label = '使用短的助记符')
775 | m._misc_area_z_entry.Create(_sb, value = 'flu,bat,ban,tec=EU...')
776 | m._misc_area_results_file_ckbtn.Create(_sb, label = '--results-file')
777 | m._misc_area_results_file_entry.Create(_sb)
778 | m._misc_area_results_file_chooser.Create(_sb, label = '打开')
779 | m._misc_area_results_file_chooser.Bind(
780 | EVT_BUTTON,
781 | lambda evt, data = [m._misc_area_results_file_entry]:
782 | self._handlers.set_file_entry_text(evt, data))
783 | # win10里, 最后一行总是会变矮~, 添加一个无用的widget, 抵消一下~
784 | self._dummy = btn(_sb,
785 | label = '一个无用按钮, 如果报GTK警告, 应该是我没显示出来')
786 | self._dummy.Disable()
787 |
788 | def build_page1_tamper(self, layout):
789 | p = Scroll(self, style = wx.BORDER_THEME)
790 | m = self.m
791 |
792 | # vbox = layout.request_sizer()
793 | # p.SetSizer(vbox)
794 | p.SetupScrolling(scroll_x = False, scrollIntoView = False)
795 | return p
796 |
797 |
798 | def main():
799 | import time
800 | from widgets import EXPAND, BOTTOM
801 | from model import Model
802 | from handlers import Handler
803 |
804 | start = time.process_time()
805 | app = wx.App()
806 | # --------
807 | win = wx.Frame(None, title = 'options-wx', size = (800, 600))
808 |
809 | m = Model(False)
810 | n = Notebook(win, m, Handler(win, m))
811 |
812 | box = wx.BoxSizer()
813 | box.Add(n, proportion = 1, flag = EXPAND | BOTTOM, border = 5)
814 | win.SetSizerAndFit(box)
815 |
816 | win.Centre()
817 | win.Show()
818 | # --------
819 | end = time.process_time()
820 | print('loading cost: %.3f Seconds' % (end - start))
821 | app.MainLoop()
822 |
823 |
824 | if __name__ == '__main__':
825 | main()
826 |
--------------------------------------------------------------------------------
/profiler.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash -
2 | #
3 | # 2018-11-01 04:18:20
4 |
5 | kernprof -l -v sqlmap_wx.py
6 |
7 |
--------------------------------------------------------------------------------
/screenshots/sqlmap-wx1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/needle-wang/sqlmap-wx/747e8170538f48dd1a75c8ed1b05a6a32d81d368/screenshots/sqlmap-wx1.png
--------------------------------------------------------------------------------
/screenshots/sqlmap-wx2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/needle-wang/sqlmap-wx/747e8170538f48dd1a75c8ed1b05a6a32d81d368/screenshots/sqlmap-wx2.png
--------------------------------------------------------------------------------
/screenshots/sqlmap-wx3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/needle-wang/sqlmap-wx/747e8170538f48dd1a75c8ed1b05a6a32d81d368/screenshots/sqlmap-wx3.png
--------------------------------------------------------------------------------
/screenshots/sqlmap-wx4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/needle-wang/sqlmap-wx/747e8170538f48dd1a75c8ed1b05a6a32d81d368/screenshots/sqlmap-wx4.png
--------------------------------------------------------------------------------
/screenshots/sqlmap-wx5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/needle-wang/sqlmap-wx/747e8170538f48dd1a75c8ed1b05a6a32d81d368/screenshots/sqlmap-wx5.png
--------------------------------------------------------------------------------
/screenshots/sqlmap-wx6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/needle-wang/sqlmap-wx/747e8170538f48dd1a75c8ed1b05a6a32d81d368/screenshots/sqlmap-wx6.png
--------------------------------------------------------------------------------
/screenshots/sqlmap-wx7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/needle-wang/sqlmap-wx/747e8170538f48dd1a75c8ed1b05a6a32d81d368/screenshots/sqlmap-wx7.png
--------------------------------------------------------------------------------
/screenshots/sqlmap-wx8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/needle-wang/sqlmap-wx/747e8170538f48dd1a75c8ed1b05a6a32d81d368/screenshots/sqlmap-wx8.png
--------------------------------------------------------------------------------
/screenshots/sqlmap-wx9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/needle-wang/sqlmap-wx/747e8170538f48dd1a75c8ed1b05a6a32d81d368/screenshots/sqlmap-wx9.png
--------------------------------------------------------------------------------
/session.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | #
3 | # 2018-11-09 15:06:50
4 |
5 | from configparser import ConfigParser
6 | from widgets import cb, tc
7 |
8 | LAST_TMP = 'static/last.tmp'
9 |
10 |
11 | class Session(object):
12 | def __init__(self, m):
13 | '''
14 | m: model.Model
15 | '''
16 | self.m = m
17 |
18 | self._cfg = ConfigParser()
19 | # https://stackoverflow.com/questions/19359556/configparser-reads-capital-keys-and-make-them-lower-case
20 | # 所有选项的key, 都会传给optionxform(), 该方法会将key转成小写!
21 | # 将optionxform替换成str, 表示不做转换
22 | self._cfg.optionxform = str
23 |
24 | def save_to_tmp(self):
25 | self._save_to_tmp_target()
26 | self._save_to_tmp_ckbtn()
27 | self._save_to_tmp_entry()
28 |
29 | with open(LAST_TMP, 'w') as f:
30 | self._cfg.write(f)
31 |
32 | def load_from_tmp(self):
33 | # 如果文件不存在, 不会报错
34 | self._cfg.read(LAST_TMP, 'utf8')
35 |
36 | self._load_from_tmp_target()
37 | self._load_from_tmp_ckbtn()
38 | self._load_from_tmp_entry()
39 |
40 | def _save_to_tmp_target(self):
41 | if self._cfg.has_section('Target'):
42 | self._cfg.remove_section('Target')
43 |
44 | self._cfg.add_section('Target')
45 |
46 | _tmp_url = self.m._url_combobox.GetValue().strip()
47 |
48 | if _tmp_url:
49 | self._cfg['Target']['_url_combobox'] = _tmp_url
50 |
51 | def _save_to_tmp_ckbtn(self):
52 | if self._cfg.has_section('CheckButton'):
53 | self._cfg.remove_section('CheckButton')
54 |
55 | self._cfg.add_section('CheckButton')
56 |
57 | _checked = []
58 | for _i in dir(self.m):
59 | if _i.endswith('ckbtn'):
60 | _tmp_ckbtn = getattr(self.m, _i)
61 |
62 | if isinstance(_tmp_ckbtn, cb) and _tmp_ckbtn.IsChecked():
63 | _checked.append(_i)
64 |
65 | self._cfg['CheckButton']['checked'] = ','.join(_checked)
66 |
67 | def _save_to_tmp_entry(self):
68 | if self._cfg.has_section('Entry'):
69 | self._cfg.remove_section('Entry')
70 |
71 | self._cfg.add_section('Entry')
72 |
73 | for _i in dir(self.m):
74 | if _i.endswith('entry'):
75 | _tmp_entry = getattr(self.m, _i)
76 | _v = _tmp_entry.GetValue().strip()
77 | if isinstance(_tmp_entry, tc) and _v:
78 | self._cfg['Entry'][_i] = _v
79 |
80 | def _load_from_tmp_target(self):
81 | if not self._cfg.has_section('Target'):
82 | self._cfg.add_section('Target')
83 |
84 | for _i in self._cfg.options('Target'):
85 | if _i == '_url_combobox':
86 | # 不去手动改LAST_TMP, self.m就肯定有_i属性了
87 | _tmp_url = self.m._url_combobox
88 |
89 | if self._cfg['Target'][_i]:
90 | _tmp_url.SetValue(self._cfg['Target'][_i])
91 |
92 | break
93 |
94 | def _load_from_tmp_ckbtn(self):
95 | if not self._cfg.has_section('CheckButton'):
96 | self._cfg.add_section('CheckButton')
97 |
98 | try:
99 | _checked = self._cfg['CheckButton']['checked'].split(',')
100 | for _i in _checked:
101 | try:
102 | if _i: # _i could be ''
103 | if _i.endswith('_ckbtn'):
104 | _tmp_ckbtn = getattr(self.m, _i)
105 | _tmp_ckbtn.SetValue(True)
106 | # if _i.startswith('tamper_'):
107 | # _tampers[int(_i[len('tamper_'):])].set_active(True)
108 | else: # if _checked = [''], then use default
109 | pass
110 | except AttributeError:
111 | pass
112 | except KeyError:
113 | # if no checked button, then pass
114 | pass
115 |
116 | def _load_from_tmp_entry(self):
117 | if not self._cfg.has_section('Entry'):
118 | self._cfg.add_section('Entry')
119 |
120 | for _i in self._cfg.options('Entry'):
121 | try:
122 | _tmp_entry = getattr(self.m, _i)
123 |
124 | if isinstance(_tmp_entry, tc) and self._cfg['Entry'][_i]:
125 | # print(type(self._cfg['Entry'][_i]))
126 | _tmp_entry.SetValue(self._cfg['Entry'][_i])
127 | except AttributeError:
128 | pass
129 |
130 |
131 | def main():
132 | pass
133 |
134 |
135 | if __name__ == '__main__':
136 | main()
137 |
--------------------------------------------------------------------------------
/sqlmap_wx.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | #
3 | # 2019-05-05 14:50:15
4 |
5 | from subprocess import Popen, PIPE, STDOUT
6 | from threading import Thread
7 |
8 | from widgets import wx, Panel, Scroll, SplitterWindow, btn, cb, nb, st, tc
9 | from widgets import BoxSizer, GridSizer, StaticBoxSizer, SizerFlags, EVT_BUTTON
10 | from widgets import VERTICAL, EXPAND, ALL, TOP, BOTTOM, LEFT, RIGHT, ALIGN_CENTER
11 |
12 | from model import Model
13 | from opts_wx import Notebook
14 | from handlers import Handler, IS_POSIX
15 | from session import Session
16 | from tooltips import Widget_Mesg as INIT_MESG
17 |
18 |
19 | class Window(wx.Frame):
20 | def __init__(self, parent):
21 | super().__init__(parent, title = 'sqlmap-wx')
22 | self.SetIcon(wx.Icon('static/title.ico'))
23 |
24 | self.m = Model()
25 | self._handlers = Handler(self, self.m) # 需要先设置handler, Bind需要它
26 | self.initUI()
27 | self.make_accelerators() # 要先初始化完成后, 才能设全局键
28 | # add tooltips, placeholders
29 | INIT_MESG(self.m)
30 |
31 | self.session = Session(self.m)
32 | self.session.load_from_tmp()
33 |
34 | # @profile
35 | def initUI(self):
36 | p = Panel(self)
37 |
38 | self._target_notebook = nb(p)
39 | self.build_target_notebook(self._target_notebook)
40 |
41 | self.main_notebook = nb(p)
42 | page1 = self.build_page1(self.main_notebook)
43 | page2 = self.build_page2(self.main_notebook)
44 | page3 = self.build_page3(self.main_notebook)
45 | page4 = self.build_page4(self.main_notebook)
46 | page5 = self.build_page5(self.main_notebook)
47 | page6 = self.build_page6(self.main_notebook)
48 |
49 | self.main_notebook.AddPage(page1, '选项区(1)')
50 | self.main_notebook.AddPage(page2, '输出区(2)')
51 | self.main_notebook.AddPage(page3, '日志区(3)')
52 | self.main_notebook.AddPage(page4, 'API区(4)')
53 | self.main_notebook.AddPage(page5, '帮助(H)')
54 | self.main_notebook.AddPage(page6, '关于')
55 |
56 | vbox = BoxSizer(VERTICAL)
57 | vbox.Add(self._target_notebook, flag = EXPAND)
58 | vbox.Add(self.main_notebook, proportion = 1, flag = EXPAND)
59 | p.SetSizer(vbox)
60 |
61 | _frame_sz = BoxSizer()
62 | _frame_sz.Add(p, proportion = 1, flag = EXPAND)
63 | # 使用SetSizerAndFit方法使frame拥有最小size
64 | self.SetSizerAndFit(_frame_sz)
65 |
66 | def make_accelerators(self):
67 | '''
68 | https://www.blog.pythonlibrary.org/2017/09/28/wxpython-all-about-accelerators/
69 | 只有最后一次的SetAcceleratorTable会生效
70 | '''
71 | self.Bind(wx.EVT_CLOSE, self.onExit)
72 | self.Bind(wx.EVT_MENU, self.onCloseByAccel, id = wx.ID_EXIT)
73 | self.accel_entries = [(wx.ACCEL_CTRL, ord('Q'), wx.ID_EXIT),
74 | (wx.ACCEL_CTRL, ord('W'), wx.ID_EXIT)]
75 |
76 | main_note_ks = list('1234H')
77 | for i in range(len(main_note_ks)):
78 | pageid = self.main_notebook.GetPage(i).GetId()
79 |
80 | self.accel_entries.append((wx.ACCEL_ALT, ord(main_note_ks[i]), pageid))
81 | self.Bind(
82 | wx.EVT_MENU,
83 | lambda evt, page = i: self.main_notebook.SetSelection(page),
84 | id = pageid)
85 |
86 | _note_keys = list('QWERTY')
87 | for i in range(len(_note_keys)):
88 | pageid = self._notebook.GetPage(i).GetId()
89 |
90 | self.accel_entries.append((wx.ACCEL_ALT, ord(_note_keys[i]), pageid))
91 | self.Bind(
92 | wx.EVT_MENU,
93 | lambda evt, page = i:
94 | self._notebook.SetSelection(page)
95 | if self.main_notebook.GetSelection() == 0 else evt.Skip(),
96 | id = pageid)
97 | # win下, 若焦点没按钮上, 则不响应mnemonic, 只能在这里实现了
98 | _btn_keys = list('ASDF')
99 | btns = self.btn_grid.GetChildren()
100 | for i in range(len(btns)):
101 | btn = btns[i].GetWindow()
102 | btnid = btn.GetId()
103 |
104 | self.accel_entries.append((wx.ACCEL_ALT, ord(_btn_keys[i]), btnid))
105 | self.Bind(
106 | wx.EVT_MENU,
107 | lambda evt, _btn = btn: # 防止闭包: btn这个变量名跟lambda绑定成一体
108 | self.make_btn_accel(_btn)
109 | if self.main_notebook.GetSelection() == 0 else evt.Skip(),
110 | id = btnid)
111 |
112 | accel_tbl = wx.AcceleratorTable(self.accel_entries)
113 | self.SetAcceleratorTable(accel_tbl)
114 |
115 | def make_btn_accel(self, btn):
116 | '''
117 | https://stackoverflow.com/questions/12786471/invoking-a-wxpython-evt-button-event-programmatically
118 | https://stackoverflow.com/questions/9765718/wxpython-trigger-checkbox-event-while-setting-its-value-in-the-code
119 | '''
120 | # 手动emit事件
121 | # evt = wx.CommandEvent(wx.EVT_CHECKBOX.typeId)
122 | # evt.SetEventObject(cb) # 将该evt绑定给cb
123 | # wx.PostEvent(cb, evt)
124 | evt = wx.PyCommandEvent(EVT_BUTTON.typeId, btn.GetId())
125 | # print(evt)
126 | wx.PostEvent(btn, evt)
127 |
128 | def clear_all_entry(self, event):
129 | m = self.m
130 | for _i in dir(m):
131 | if _i.endswith('entry'):
132 | _tmp_entry = getattr(m, _i)
133 | if isinstance(_tmp_entry, tc) and _tmp_entry is not m.sqlmap_path_entry:
134 | _tmp_entry.SetValue('')
135 |
136 | self._notebook.SetFocus()
137 |
138 | def unselect_all_ckbtn(self, event):
139 | m = self.m
140 | for _i in dir(m):
141 | if _i.endswith('ckbtn'):
142 | _tmp_ckbtn = getattr(m, _i)
143 | if isinstance(_tmp_ckbtn, cb) and _tmp_ckbtn.IsChecked():
144 | _tmp_ckbtn.SetValue(False)
145 | for _i in m._enum_area_opts_ckbtns:
146 | for _j in _i:
147 | if _j.IsChecked():
148 | _j.SetValue(False)
149 |
150 | self._notebook.SetFocus()
151 |
152 | def onCloseByAccel(self, event):
153 | '''
154 | https://stackoverflow.com/questions/49454737/how-can-i-exit-out-of-a-wxpython-application-cleanly
155 | '''
156 | # print('by accelerator.')
157 | wx.CallAfter(self.Close)
158 |
159 | def onExit(self, event):
160 | '''
161 | https://www.daniweb.com/programming/software-development/code/216760/verify-exit-dialog-wxpython
162 | '''
163 | # print('by ALT- or click close button.')
164 | try:
165 | self.session.save_to_tmp()
166 | except Exception as e:
167 | raise e
168 | finally:
169 | event.Skip()
170 |
171 | def build_target_notebook(self, parent):
172 | m = self.m
173 |
174 | m._url_combobox.Create(parent, choices = ['http://www.site.com/vuln.php?id=1']) # style = wx.CB_DROPDOWN
175 |
176 | p2 = Panel(parent)
177 | hbox2 = BoxSizer()
178 | m._burp_logfile.Create(p2)
179 | m._burp_logfile_chooser.Create(p2, label = '打开')
180 | m._burp_logfile_chooser.Bind(
181 | EVT_BUTTON,
182 | lambda evt, data = [m._burp_logfile]:
183 | self._handlers.set_file_entry_text(evt, data))
184 |
185 | hbox2.Add(m._burp_logfile, proportion = 1, flag = EXPAND)
186 | hbox2.Add(m._burp_logfile_chooser, flag = EXPAND)
187 | p2.SetSizer(hbox2)
188 |
189 | p3 = Panel(parent)
190 | hbox3 = BoxSizer()
191 | m._request_file.Create(p3)
192 | m._request_file_chooser.Create(p3, label = '打开')
193 | m._request_file_chooser.Bind(
194 | EVT_BUTTON,
195 | lambda evt, data = [m._request_file]:
196 | self._handlers.set_file_entry_text(evt, data))
197 |
198 | hbox3.Add(m._request_file, proportion = 1, flag = EXPAND)
199 | hbox3.Add(m._request_file_chooser, flag = EXPAND)
200 | p3.SetSizer(hbox3)
201 |
202 | p4 = Panel(parent)
203 | hbox4 = BoxSizer()
204 | m._bulkfile.Create(p4)
205 | m._bulkfile_chooser.Create(p4, label = '打开')
206 | m._bulkfile_chooser.Bind(
207 | EVT_BUTTON,
208 | lambda evt, data = [m._bulkfile]:
209 | self._handlers.set_file_entry_text(evt, data))
210 |
211 | hbox4.Add(m._bulkfile, proportion = 1, flag = EXPAND)
212 | hbox4.Add(m._bulkfile_chooser, flag = EXPAND)
213 | p4.SetSizer(hbox4)
214 |
215 | p5 = Panel(parent)
216 | hbox5 = BoxSizer()
217 | m._configfile.Create(p5)
218 | m._configfile_chooser.Create(p5, label = '打开')
219 | m._configfile_chooser.Bind(
220 | EVT_BUTTON,
221 | lambda evt, data = [m._configfile]:
222 | self._handlers.set_file_entry_text(evt, data))
223 |
224 | hbox5.Add(m._configfile, proportion = 1, flag = EXPAND)
225 | hbox5.Add(m._configfile_chooser, flag = EXPAND)
226 | p5.SetSizer(hbox5)
227 |
228 | m._google_dork.Create(parent)
229 | m._direct_connect.Create(parent,
230 | value = 'mysql://USER:PASSWORD@DBMS_IP:DBMS_PORT/DATABASE_NAME or '
231 | 'access://DATABASE_FILEPATH')
232 |
233 | parent.AddPage(m._url_combobox, '目标url')
234 | parent.AddPage(p2, 'burp日志')
235 | parent.AddPage(p3, 'HTTP请求')
236 | parent.AddPage(p4, 'BULKFILE')
237 | parent.AddPage(p5, 'ini文件')
238 | parent.AddPage(m._google_dork, 'GOOGLEDORK')
239 | parent.AddPage(m._direct_connect, '-d DIRECT')
240 |
241 | def build_page1(self, parent):
242 | p = Panel(parent)
243 | m = self.m
244 |
245 | # sqlmap命令语句
246 | cmd_area = StaticBoxSizer(VERTICAL, p, 'A.收集选项 的结果显示在这:')
247 | _cmd_area = cmd_area.GetStaticBox()
248 |
249 | m._cmd_entry.Create(_cmd_area)
250 |
251 | cmd_area.Add(m._cmd_entry, flag = EXPAND)
252 |
253 | # 主构造区
254 | self._notebook = Notebook(p, m, self._handlers)
255 |
256 | # 构造与执行
257 | self.btn_grid = GridSizer(1, 4, 0, 0)
258 |
259 | _build_button = btn(p, label = 'A.收集选项(A)')
260 | _unselect_all_btn = btn(p, label = '反选所有复选框(S)')
261 | _clear_all_entry = btn(p, label = '清空所有输入框(D)')
262 |
263 | _build_button.Bind(EVT_BUTTON, self._handlers.build_all)
264 | _unselect_all_btn.Bind(EVT_BUTTON, self.unselect_all_ckbtn)
265 | _clear_all_entry.Bind(EVT_BUTTON, self.clear_all_entry)
266 |
267 | _run_button = btn(p, label = 'B.开始(F)')
268 | _run_button.Bind(EVT_BUTTON, self._handlers.run_cmdline)
269 |
270 | self.btn_grid.Add(_build_button, flag = ALIGN_CENTER)
271 | self.btn_grid.Add(_unselect_all_btn, flag = ALIGN_CENTER)
272 | self.btn_grid.Add(_clear_all_entry, flag = ALIGN_CENTER)
273 | self.btn_grid.Add(_run_button, flag = ALIGN_CENTER)
274 |
275 | vbox = BoxSizer(VERTICAL)
276 | vbox.Add(cmd_area, flag = EXPAND)
277 | vbox.Add(self._notebook, proportion = 1, flag = EXPAND)
278 | vbox.Add(self.btn_grid, flag = EXPAND)
279 | p.SetSizerAndFit(vbox)
280 | return p
281 |
282 | def build_page2(self, parent):
283 | p = Panel(parent)
284 | st(p, label = 'TODO')
285 | return p
286 |
287 | def build_page3(self, parent):
288 | p = Panel(parent)
289 | m = self.m
290 |
291 | # 多行文本框的默认size太小了
292 | # 默认高度太低, 不指定个高度, 会报 滚动条相关的size 警告
293 | m._page3_log_view.Create(p,
294 | size = (-1, 300),
295 | style = wx.TE_MULTILINE | wx.TE_READONLY)
296 | self._handlers.clear_log_view_buffer(None)
297 |
298 | grid = GridSizer(1, 3, 0, 0)
299 | m._page3_read_target_btn.Create(p, label = '查看target文件')
300 | m._page3_clear_btn.Create(p, label = '清空(&C)')
301 | m._page3_read_log_btn.Create(p, label = '查看log文件')
302 |
303 | m._page3_read_target_btn.Bind(EVT_BUTTON, self._handlers.read_target_file)
304 | m._page3_clear_btn.Bind(EVT_BUTTON, self._handlers.clear_log_view_buffer)
305 | m._page3_read_log_btn.Bind(EVT_BUTTON, self._handlers.read_log_file)
306 |
307 | grid.Add(m._page3_read_target_btn, flag = ALIGN_CENTER)
308 | grid.Add(m._page3_clear_btn, flag = ALIGN_CENTER)
309 | grid.Add(m._page3_read_log_btn, flag = ALIGN_CENTER)
310 |
311 | vbox = BoxSizer(VERTICAL)
312 | vbox.Add(m._page3_log_view, proportion = 1, flag = EXPAND | ALL, border = 10)
313 | vbox.Add(grid, flag = EXPAND)
314 | p.SetSizerAndFit(vbox)
315 | return p
316 |
317 | def build_page4(self, parent):
318 | p = Panel(parent)
319 | m = self.m
320 |
321 | border = SizerFlags().Border(LEFT | RIGHT, 5).Align(ALIGN_CENTER)
322 | proportion_border = SizerFlags(1).Border(LEFT | RIGHT, 5).Align(ALIGN_CENTER)
323 |
324 | row1, row2 = (BoxSizer() for _ in range(2))
325 | m._page4_api_server_label.Create(p, label = 'REST-JSON API server:')
326 | m._page4_api_server_entry.Create(p, value = '127.0.0.1:8775')
327 | m._page4_admin_token_label.Create(p, label = 'Admin (secret) token:')
328 | m._page4_admin_token_entry.Create(p)
329 | m._page4_admin_token_entry.SetMaxLength(32)
330 | row1.Add(m._page4_api_server_label, border)
331 | row1.Add(m._page4_api_server_entry, proportion_border)
332 | row1.Add(m._page4_admin_token_label, border)
333 | row1.Add(m._page4_admin_token_entry, proportion_border)
334 |
335 | m._page4_task_new_btn.Create(p, label = '创建任务')
336 | m._page4_admin_list_btn.Create(p, label = '显示任务')
337 | m._page4_admin_flush_btn.Create(p, label = '删除所有任务')
338 | m._page4_clear_task_view_btn.Create(p, label = '清空反馈的结果')
339 | m._page4_username_label.Create(p, label = '用户名:')
340 | m._page4_username_entry.Create(p)
341 | m._page4_password_label.Create(p, label = '密码:')
342 | m._page4_password_entry.Create(p)
343 |
344 | _arrow_down = wx.ArtProvider.GetBitmap(wx.ART_GO_DOWN, wx.ART_BUTTON)
345 | m._page4_admin_list_btn.SetBitmap(_arrow_down, dir = RIGHT)
346 |
347 | m._page4_task_new_btn.Bind(EVT_BUTTON, self._handlers.api.task_new)
348 | m._page4_admin_list_btn.Bind(EVT_BUTTON, self._handlers.api.admin_list)
349 | m._page4_admin_flush_btn.Bind(EVT_BUTTON, self._handlers.api.admin_flush)
350 | m._page4_clear_task_view_btn.Bind(EVT_BUTTON, self._handlers.clear_task_view_buffer)
351 |
352 | row2.Add(m._page4_task_new_btn, border)
353 | row2.Add(m._page4_admin_list_btn, border)
354 | row2.Add(m._page4_admin_flush_btn, border)
355 | row2.Add(m._page4_clear_task_view_btn, border)
356 | row2.Add(m._page4_username_label, flag = ALIGN_CENTER | LEFT, border = 200)
357 | row2.Add(m._page4_username_entry, proportion_border)
358 | row2.Add(m._page4_password_label, border)
359 | row2.Add(m._page4_password_entry, proportion_border)
360 |
361 | row3 = SplitterWindow(p, style = wx.SP_LIVE_UPDATE | wx.BORDER_SUNKEN)
362 | # 不能放在SplitVertically后面, 不然gravity会无效
363 | # row3.SetSashGravity(0.5)
364 | row3.SetMinimumPaneSize(400)
365 |
366 | lpane = Scroll(row3)
367 | self._api_admin_list_rows = lpane
368 |
369 | lpane.SetSizer(BoxSizer(VERTICAL))
370 |
371 | rpane = Panel(row3)
372 | _rbox = BoxSizer(VERTICAL)
373 |
374 | m._page4_option_get_entry.Create(rpane, value = 'url risk level')
375 | _page4_option_set_view_tip = st(rpane, label = 'check optiondict.py of sqlmap about options.')
376 | _options_example = ("{\n"
377 | " 'url': 'http://www.site.com/vuln.php?id=1',\n"
378 | " 'level': 1, 'risk': 1,\n\n"
379 | "}\n")
380 | m._page4_option_set_view.Create(rpane,
381 | value = _options_example,
382 | style = wx.TE_MULTILINE)
383 | _rbox.Add(m._page4_option_get_entry, flag = EXPAND | ALL, border = 2)
384 | _rbox.Add(_page4_option_set_view_tip, flag = ALL, border = 2)
385 | _rbox.Add(m._page4_option_set_view, proportion = 1, flag = EXPAND | ALL, border = 2)
386 | rpane.SetSizer(_rbox)
387 |
388 | row3.SplitVertically(lpane, rpane)
389 | # win下, lpane是灰色的, 将row3设下颜色, 又是兼容代码...
390 | row3.SetBackgroundColour(m._page4_option_set_view.GetBackgroundColour())
391 | row3.SetSashPosition(lpane.GetMinWidth())
392 |
393 | m._page4_task_view.Create(p, value = 'response result:\n', style = wx.TE_MULTILINE | wx.TE_READONLY)
394 |
395 | vbox = BoxSizer(VERTICAL)
396 | vbox.Add(row1, flag = EXPAND | ALL, border = 5)
397 | vbox.Add(row2, flag = EXPAND | ALL, border = 5)
398 | vbox.Add(row3, proportion = 1, flag = EXPAND | LEFT | RIGHT, border = 10)
399 | vbox.Add(m._page4_task_view, proportion = 1, flag = EXPAND | ALL, border = 10)
400 | p.SetSizerAndFit(vbox)
401 | return p
402 |
403 | def build_page5(self, parent):
404 | p = Panel(parent)
405 | m = self.m
406 |
407 | self._get_sqlmap_path_btn = btn(p, label = 'sqlmap -hh')
408 | self._get_sqlmap_path_btn.Disable()
409 | # 多行文本框的默认size太小了
410 | # 默认高度太低, 不指定个高度, gtk会报 滚动条相关的size 警告
411 | m._page5_manual_view.Create(p,
412 | size = (-1, 300),
413 | style = wx.TE_MULTILINE | wx.TE_READONLY)
414 |
415 | self._get_sqlmap_path_btn.Bind(
416 | EVT_BUTTON, lambda evt, view = m._page5_manual_view:
417 | self._make_help_thread(evt, view))
418 |
419 | self._make_help_thread(None, m._page5_manual_view)
420 |
421 | vbox = BoxSizer(VERTICAL)
422 | vbox.Add(self._get_sqlmap_path_btn, flag = TOP | LEFT | BOTTOM, border = 10)
423 | vbox.Add(m._page5_manual_view, proportion = 1, flag = EXPAND | LEFT | RIGHT, border = 10)
424 | p.SetSizerAndFit(vbox)
425 | return p
426 |
427 | def _make_help_thread(self, event, view):
428 | isClick = True if event else False
429 | # 使用线程 填充 帮助标签, 加快启动速度
430 | t = Thread(target = self._set_manual_view,
431 | args = (view, isClick))
432 | t.daemon = True # 主线程退出了, 当然守护进程也要退出
433 | t.start()
434 |
435 | def _set_manual_view(self, view, isClick):
436 | '''
437 | 不用多线程能行嘛? 想要获得输出结果就一定会有阻塞的可能!
438 | https://www.jianshu.com/p/11090e197648
439 | https://wiki.gnome.org/Projects/PyGObject/Threading
440 | needle注: 操作的共享对象有两个: _get_sqlmap_path_btn, view
441 | 原则一样, 所有对共用对象的操作都要用CallAfter
442 | 这样写是不是很丑?
443 | 另外, 如果没运行完, 主线程就退出了, 会卡住哦, 属于正常
444 | '''
445 | if isClick:
446 | wx.CallAfter(self._get_sqlmap_path_btn.Disable)
447 | wx.CallAfter(view.SetValue, '')
448 |
449 | byte_coding = 'utf8' if IS_POSIX else 'gbk'
450 |
451 | # _manual_hh = '/home/needle/bin/output_interval.sh'
452 | # win下的sqlmap -hh有Enter阻塞
453 | _manual_hh = 'echo y|%s -hh' % self._handlers.get_sqlmap_path()
454 | try:
455 | _subp = Popen(_manual_hh, stdout=PIPE, stderr=STDOUT, shell = True)
456 |
457 | for _an_bytes_line_tmp in iter(_subp.stdout.readline, b''):
458 | wx.CallAfter(view.write,
459 | _an_bytes_line_tmp.decode(byte_coding))
460 |
461 | _subp.wait()
462 | _subp.stdout.close()
463 | except FileNotFoundError as e:
464 | wx.CallAfter(view.write, str(e))
465 | except Exception as e:
466 | print(e) # 如果主线程结束太快, 会: AssertionError: No wx.App created yet
467 | finally:
468 | wx.CallAfter(self._get_sqlmap_path_btn.Enable)
469 |
470 | if isClick:
471 | # 用gtk时, 如果view不在屏幕上可见, ShowPosition会报错
472 | wx.CallAfter(view.ShowPosition, 0)
473 | wx.CallAfter(self._get_sqlmap_path_btn.SetFocus)
474 |
475 | def build_page6(self, parent):
476 | p = Panel(parent)
477 |
478 | _version = '0.3.3.1'
479 | _timestamp = '2021-01-31 05:12:52'
480 |
481 | _url_self = 'https://github.com/needle-wang/sqlmap-wx'
482 | _url_tutorial1 = 'https://wiki.wxpython.org/'
483 | _url_tutorial2 = 'http://zetcode.com/wxpython/'
484 | _url_api = 'https://wxpython.org/Phoenix/docs/html/index.html'
485 | _url_idea = 'https://github.com/kxcode'
486 | _about_str = f'''
487 | 1. Website: {_url_self}
488 | VERSION: {_version}
489 | {_timestamp}
490 | required: python3.6+, wxPython4.0+,
491 | requests, sqlmap\n
492 | 2. use wxPython4 to recode sqlmap-gtk(driven by PyGObject)
493 | 3. thanks to the idea from sqm(by python2 + tkinter),
494 | author: KINGX, {_url_idea}\n
495 | 4. wxPython tutorial: {_url_tutorial1}
496 | {_url_tutorial2}
497 | 5. wxPython API: {_url_api}
498 | '''
499 | hbox = BoxSizer()
500 | _page6_about = st(p, label = _about_str)
501 | # 完全居中!
502 | hbox.Add(_page6_about, flag = ALIGN_CENTER)
503 |
504 | vbox = BoxSizer(VERTICAL)
505 | vbox.Add(hbox, proportion = 1, flag = ALIGN_CENTER)
506 | p.SetSizerAndFit(vbox)
507 | return p
508 |
509 |
510 | def main():
511 | import time
512 | # import wx.lib.mixins.inspection as wit
513 | # app = wit.InspectableApp()
514 | start = time.process_time()
515 | app = wx.App()
516 | # --------
517 | win = Window(None)
518 | win.Centre()
519 | win.Show()
520 | # --------
521 | end = time.process_time()
522 | print('loading cost: %.3f Seconds' % (end - start))
523 | app.MainLoop()
524 |
525 |
526 | if __name__ == '__main__':
527 | main()
528 |
--------------------------------------------------------------------------------
/static/title.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/needle-wang/sqlmap-wx/747e8170538f48dd1a75c8ed1b05a6a32d81d368/static/title.ico
--------------------------------------------------------------------------------
/tamper/tamper_list:
--------------------------------------------------------------------------------
1 | 0eunion.py Replaces instances of UNION with e0UNION
2 | apostrophemask.py Replaces apostrophe character (') with its UTF-8 full width counterpart (e.g. ' -> %EF%BC%87)
3 | apostrophenullencode.py Replaces apostrophe character (') with its illegal double unicode counterpart (e.g. ' -> %00%27)
4 | appendnullbyte.py Appends (Access) NULL byte character (%00) at the end of payload
5 | base64encode.py Base64-encodes all characters in a given payload
6 | between.py Replaces greater than operator ('>') with 'NOT BETWEEN 0 AND #' and equals operator ('=') with 'BETWEEN # AND #'
7 | binary.py Injects keyword binary where possible
8 | bluecoat.py Replaces space character after SQL statement with a valid random blank character. Afterwards replace character '=' with operator LIKE
9 | chardoubleencode.py Double URL-encodes all characters in a given payload (not processing already encoded) (e.g. SELECT -> %2553%2545%254C%2545%2543%2554)
10 | charencode.py URL-encodes all characters in a given payload (not processing already encoded) (e.g. SELECT -> %53%45%4C%45%43%54)
11 | charunicodeencode.py Unicode-URL-encodes all characters in a given payload (not processing already encoded) (e.g. SELECT -> %u0053%u0045%u004C%u0045%u0043%u0054)
12 | charunicodeescape.py Unicode-escapes non-encoded characters in a given payload (not processing already encoded) (e.g. SELECT -> \u0053\u0045\u004C\u0045\u0043\u0054)
13 | commalesslimit.py Replaces (MySQL) instances like 'LIMIT M, N' with 'LIMIT N OFFSET M' counterpart
14 | commalessmid.py Replaces (MySQL) instances like 'MID(A, B, C)' with 'MID(A FROM B FOR C)' counterpart
15 | commentbeforeparentheses.py Prepends (inline) comment before parentheses (e.g. ( -> /**/()
16 | concat2concatws.py Replaces (MySQL) instances like 'CONCAT(A, B)' with 'CONCAT_WS(MID(CHAR(0), 0, 0), A, B)' counterpart
17 | dunion.py Replaces instances of UNION with DUNION
18 | equaltolike.py Replaces all occurrences of operator equal ('=') with 'LIKE' counterpart
19 | equaltorlike.py Replaces all occurrences of operator equal ('=') with 'RLIKE' counterpart
20 | escapequotes.py Slash escape single and double quotes (e.g. ' -> \')
21 | greatest.py Replaces greater than operator ('>') with 'GREATEST' counterpart
22 | halfversionedmorekeywords.py Adds (MySQL) versioned comment before each keyword
23 | hex2char.py Replaces each (MySQL) 0x encoded string with equivalent CONCAT(CHAR(),...) counterpart
24 | htmlencode.py HTML encode (using code points) all non-alphanumeric characters (e.g. ' -> ')
25 | ifnull2casewhenisnull.py Replaces instances like 'IFNULL(A, B)' with 'CASE WHEN ISNULL(A) THEN (B) ELSE (A) END' counterpart
26 | ifnull2ifisnull.py Replaces instances like 'IFNULL(A, B)' with 'IF(ISNULL(A), B, A)' counterpart
27 | informationschemacomment.py Add an inline comment (/**/) to the end of all occurrences of (MySQL) "information_schema" identifier
28 | least.py Replaces greater than operator ('>') with 'LEAST' counterpart
29 | lowercase.py Replaces each keyword character with lower case value (e.g. SELECT -> select)
30 | luanginx.py LUA-Nginx WAFs Bypass (e.g. Cloudflare)
31 | misunion.py Replaces instances of UNION with -.1UNION
32 | modsecurityversioned.py Embraces complete query with (MySQL) versioned comment
33 | modsecurityzeroversioned.py Embraces complete query with (MySQL) zero-versioned comment
34 | multiplespaces.py Adds multiple spaces (' ') around SQL keywords
35 | overlongutf8.py Converts all (non-alphanum) characters in a given payload to overlong UTF8 (not processing already encoded) (e.g. ' -> %C0%A7)
36 | overlongutf8more.py Converts all characters in a given payload to overlong UTF8 (not processing already encoded) (e.g. SELECT -> %C1%93%C1%85%C1%8C%C1%85%C1%83%C1%94)
37 | percentage.py Adds a percentage sign ('%') infront of each character (e.g. SELECT -> %S%E%L%E%C%T)
38 | plus2concat.py Replaces plus operator ('+') with (MsSQL) function CONCAT() counterpart
39 | plus2fnconcat.py Replaces plus operator ('+') with (MsSQL) ODBC function {fn CONCAT()} counterpart
40 | randomcase.py Replaces each keyword character with random case value (e.g. SELECT -> SEleCt)
41 | randomcomments.py Add random inline comments inside SQL keywords (e.g. SELECT -> S/**/E/**/LECT)
42 | schemasplit.py Splits FROM schema identifiers (e.g. 'testdb.users') with whitespace (e.g. 'testdb 9.e.users')
43 | sleep2getlock.py Replaces instances like 'SLEEP(5)' with (e.g.) "GET_LOCK('ETgP',5)"
44 | sp_password.py Appends (MsSQL) function 'sp_password' to the end of the payload for automatic obfuscation from DBMS logs
45 | space2comment.py Replaces space character (' ') with comments '/**/'
46 | space2dash.py Replaces space character (' ') with a dash comment ('--') followed by a random string and a new line ('\n')
47 | space2hash.py Replaces (MySQL) instances of space character (' ') with a pound character ('#') followed by a random string and a new line ('\n')
48 | space2morecomment.py Replaces (MySQL) instances of space character (' ') with comments '/**_**/'
49 | space2morehash.py Replaces (MySQL) instances of space character (' ') with a pound character ('#') followed by a random string and a new line ('\n')
50 | space2mssqlblank.py Replaces (MsSQL) instances of space character (' ') with a random blank character from a valid set of alternate characters
51 | space2mssqlhash.py Replaces space character (' ') with a pound character ('#') followed by a new line ('\n')
52 | space2mysqlblank.py Replaces (MySQL) instances of space character (' ') with a random blank character from a valid set of alternate characters
53 | space2mysqldash.py Replaces space character (' ') with a dash comment ('--') followed by a new line ('\n')
54 | space2plus.py Replaces space character (' ') with plus ('+')
55 | space2randomblank.py Replaces space character (' ') with a random blank character from a valid set of alternate characters
56 | substring2leftright.py Replaces PostgreSQL SUBSTRING with LEFT and RIGHT
57 | symboliclogical.py Replaces AND and OR logical operators with their symbolic counterparts (&& and ||)
58 | unionalltounion.py Replaces instances of UNION ALL SELECT with UNION SELECT counterpart
59 | unmagicquotes.py Replaces quote character (') with a multi-byte combo %BF%27 together with generic comment at the end (to make it work)
60 | uppercase.py Replaces each keyword character with upper case value (e.g. select -> SELECT)
61 | varnish.py Appends a HTTP header 'X-originating-IP' to bypass Varnish Firewall
62 | versionedkeywords.py Encloses each non-function keyword with (MySQL) versioned comment
63 | versionedmorekeywords.py Encloses each keyword with (MySQL) versioned comment
64 | xforwardedfor.py Append a fake HTTP header 'X-Forwarded-For' (and alike)
65 |
--------------------------------------------------------------------------------
/tooltips.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | #
3 | # 2018-10-23 05:24:32
4 |
5 |
6 | class Widget_Mesg(object):
7 | def __init__(self, m):
8 | '''
9 | m: model.Model
10 | '''
11 | self.set_all_tooltips(m)
12 | self.set_all_placeholders(m)
13 |
14 | def set_all_placeholders(self, m):
15 | # 0.Target
16 | self._set_placeholder('通常是从 目标url/burp日志/HTTP请求... 中任选一项',
17 | m._url_combobox)
18 | self._set_placeholder('-l: Burp或WebScarab代理的日志文件路径(用来解析目标)',
19 | m._burp_logfile)
20 | self._set_placeholder('-r: 包含HTTP请求的的文件路径(如从fiddler中得来的)',
21 | m._request_file)
22 | self._set_placeholder('-m: 给定一个包含多个目标的文本路径',
23 | m._bulkfile)
24 | self._set_placeholder('-c: 从一个本地ini配置文件载入选项',
25 | m._configfile)
26 | self._set_placeholder('-g: 将google dork的结果作为目标url',
27 | m._google_dork)
28 | # OPTIONS(page1)
29 | # 1.Inject(Q)
30 | self._set_placeholder('id,user-agent',
31 | m._inject_area_param_entry)
32 | self._set_placeholder('user-agent,referer',
33 | m._inject_area_skip_entry)
34 | self._set_placeholder('token|session',
35 | m._inject_area_param_exclude_entry)
36 | self._set_placeholder('用于闭合',
37 | m._inject_area_prefix_entry)
38 | self._set_placeholder('user:password',
39 | m._inject_area_dbms_cred_entry)
40 | self._set_placeholder('查询为真时页面出现的字串',
41 | m._detection_area_str_entry)
42 | self._set_placeholder('查询为假时的',
43 | m._detection_area_not_str_entry)
44 | self._set_placeholder('正则匹配查询为真时的字串',
45 | m._detection_area_re_entry)
46 | self._set_placeholder('查询为真时的',
47 | m._detection_area_code_entry)
48 | self._set_placeholder('BEUSTQ',
49 | m._tech_area_tech_entry)
50 | self._set_placeholder('5',
51 | m._tech_area_time_sec_entry)
52 | self._set_placeholder('10',
53 | m._tech_area_union_col_entry)
54 | self._set_placeholder('NULL',
55 | m._tech_area_union_char_entry)
56 | self._set_placeholder('有效表名',
57 | m._tech_area_union_from_entry)
58 | self._set_placeholder('DNS exfiltration',
59 | m._tech_area_dns_entry)
60 | # 2.Request(W)
61 | self._set_placeholder('X-Forwarded-For: 127.0.0.1',
62 | m._request_area_header_entry)
63 | self._set_placeholder('Accept-Language: fr\\nETag: 123',
64 | m._request_area_headers_entry)
65 | self._set_placeholder('post',
66 | m._request_area_method_entry)
67 | self._set_placeholder('&',
68 | m._request_area_param_del_entry)
69 | self._set_placeholder('query=foobar&id=1',
70 | m._request_area_post_entry)
71 | self._set_placeholder('AU=233;SESSIONID=AABBCCDDEEFF;',
72 | m._request_area_cookie_entry)
73 | self._set_placeholder(';',
74 | m._request_area_cookie_del_entry)
75 | self._set_placeholder('Basic, Digest, NTLM or PKI',
76 | m._request_area_auth_type_entry)
77 | self._set_placeholder('name:password',
78 | m._request_area_auth_cred_entry)
79 | self._set_placeholder('PEM cert/private key file',
80 | m._request_area_auth_file_entry)
81 | self._set_placeholder('post',
82 | m._request_area_csrf_method_entry)
83 | self._set_placeholder('token字段名',
84 | m._request_area_csrf_token_entry)
85 | self._set_placeholder('import hashlib;id2=hashlib.md5(id).hexdigest()',
86 | m._request_area_eval_entry)
87 | # 3.Enumerate(E)
88 | self._set_placeholder('不包含该行',
89 | m._limit_area_start_entry)
90 | self._set_placeholder('包含该行',
91 | m._limit_area_stop_entry)
92 | self._set_placeholder('id<3',
93 | m._meta_area_where_entry)
94 | # 4.File(R)
95 | self._set_placeholder('配合 Meterpreter相关 使用',
96 | m._os_access_area_msf_path_entry)
97 | # 5.Other(T)
98 | self._set_placeholder('sqlmap',
99 | m._general_area_table_prefix_entry)
100 | self._set_placeholder('/var/www',
101 | m._general_area_web_root_entry)
102 | self._set_placeholder(r'(www)?\.target\.(com|net|org)',
103 | m._general_area_scope_entry)
104 | self._set_placeholder('ROW',
105 | m._general_area_test_filter_entry)
106 | self._set_placeholder('BENCHMARK',
107 | m._general_area_test_skip_entry)
108 | self._set_placeholder('CSV',
109 | m._general_area_dump_format_entry)
110 |
111 | def set_all_tooltips(self, m):
112 | '''
113 | m: model.Model
114 | gtk3.24: tooltip of row which contained scale causes flicker.(GTK3's bug?)
115 | '''
116 | # 0.target
117 | self._set_tooltip('必填项, 从 目标url/burp日志/HTTP请求... 任选一项',
118 | m._url_combobox)
119 | self._set_tooltip('-l: Burp或WebScarab代理的日志文件路径(用来解析目标)',
120 | m._burp_logfile)
121 | self._set_tooltip('-r: 包含HTTP请求的的文件路径(如从fiddler中得来的)',
122 | m._request_file)
123 | self._set_tooltip('-m: 给定一个包含多个目标的文本路径',
124 | m._bulkfile)
125 | self._set_tooltip('-c: 从一个本地ini配置文件载入选项',
126 | m._configfile)
127 | self._set_tooltip('-g: 将google dork的结果作为目标url',
128 | m._google_dork)
129 | # OPTIONS(page1)
130 | # 0._cmd_entry
131 | self._set_tooltip('1.勾选, 填写所需的 选项\n2.点击 收集选项\n3.点击 开始',
132 | m._cmd_entry)
133 | # 1.Inject(Q)
134 | self._set_tooltip('-p\n逗号分隔, 与--level不兼容',
135 | m._inject_area_param_ckbtn,
136 | m._inject_area_param_entry)
137 | self._set_tooltip('--param-filter=P.. Select testable parameter(s) by place (e.g. "POST")',
138 | m._inject_area_param_filter_ckbtn,
139 | m._inject_area_param_filter_combobox)
140 | self._set_tooltip('--skip-static\n'
141 | '另外: sqlmap不会针对(伪)静态网页(/param1/value1/),\n'
142 | '在任意(get/post/header等)可能的注入参数后加*即可',
143 | m._inject_area_skip_static_ckbtn)
144 | self._set_tooltip('--skip=...,...\tSkip testing for given parameter(s)',
145 | m._inject_area_skip_ckbtn,
146 | m._inject_area_skip_entry)
147 | self._set_tooltip('--param-exclude=.. Regexp to exclude parameters from testing',
148 | m._inject_area_param_exclude_ckbtn,
149 | m._inject_area_param_exclude_entry)
150 | self._set_tooltip('--prefix=PREFIX\n'
151 | '当情况复杂(如注入点位于嵌套JOIN查询中)时, 需要手动处理',
152 | m._inject_area_prefix_ckbtn,
153 | m._inject_area_prefix_entry)
154 | self._set_tooltip('--suffix=SUFFIX',
155 | m._inject_area_suffix_ckbtn,
156 | m._inject_area_suffix_entry)
157 | self._set_tooltip('--dbms=DBMS\n很确定是哪种DBMS时使用',
158 | m._inject_area_dbms_ckbtn,
159 | m._inject_area_dbms_combobox)
160 | self._set_tooltip('--dbms-cred=DBMS.. DBMS authentication credentials (user:password)',
161 | m._inject_area_dbms_cred_ckbtn,
162 | m._inject_area_dbms_cred_entry)
163 | self._set_tooltip('--os=OS\n仅在确定知道DBMS所在OS名称时使用',
164 | m._inject_area_os_ckbtn,
165 | m._inject_area_os_entry)
166 | self._set_tooltip('--no-cast\n'
167 | '检索结果时, 默认会将条目cast为字符串类型(优化检索),\n'
168 | '若数据检索有问题(如某些老版本mysql), 才勾选',
169 | m._inject_area_no_cast_ckbtn)
170 | self._set_tooltip('--no-escape\n'
171 | '注: 默认 select \'foobar\'会变成 select char(102)+char(111)...\n'
172 | ' 优点: 转义引号, 绕过; 缺点: 长度变长',
173 | m._inject_area_no_escape_ckbtn)
174 | self._set_tooltip('--invalid-bignum\n'
175 | '真: id=13 假: id=99999999',
176 | m._inject_area_invalid_bignum_ckbtn)
177 | self._set_tooltip('--invalid-logical\n'
178 | '真: id=13 假: id=13 AND 18=19',
179 | m._inject_area_invalid_logic_ckbtn)
180 | self._set_tooltip('--invalid-string\n'
181 | '真: id=13 假: id=akewmc',
182 | m._inject_area_invalid_string_ckbtn)
183 | self._set_tooltip('--string=STRING',
184 | m._detection_area_str_ckbtn,
185 | m._detection_area_str_entry)
186 | self._set_tooltip('--not-string=NOT..',
187 | m._detection_area_not_str_ckbtn,
188 | m._detection_area_not_str_entry)
189 | self._set_tooltip('--regexp=',
190 | m._detection_area_re_ckbtn,
191 | m._detection_area_re_entry)
192 | self._set_tooltip('--code=',
193 | m._detection_area_code_ckbtn,
194 | m._detection_area_code_entry)
195 | self._set_tooltip('--text-only\n'
196 | '有的响应正文包含大量其他内容(如js脚本)\n'
197 | '勾选, 可让sqlmap只关注text文件',
198 | m._detection_area_text_only_ckbtn)
199 | self._set_tooltip('--titles',
200 | m._detection_area_titles_ckbtn)
201 | self._set_tooltip('--smart\n'
202 | '用于批量扫描(如-m时), 快速粗略地寻找明显目标,\n'
203 | '再对 可引发DBMS错误的参数 进一步扫描',
204 | m._detection_area_smart_ckbtn)
205 | self._set_tooltip('--technique=B: Boolean-based blind\n'
206 | ' E: Error-based\n'
207 | ' U: Union query-based\n'
208 | ' S: Stacked queries\n'
209 | ' T: Time-based blind\n'
210 | ' Q: Inline queries',
211 | m._tech_area_tech_ckbtn,
212 | m._tech_area_tech_entry)
213 | self._set_tooltip('--time-sec=默认5秒\n时间盲注时',
214 | m._tech_area_time_sec_ckbtn,
215 | m._tech_area_time_sec_entry)
216 | self._set_tooltip('--union-cols=默认10列\nunion查询时\n'
217 | '提高level, 可增加至50列;\n'
218 | '填12-16表示使用12到16列',
219 | m._tech_area_union_col_ckbtn,
220 | m._tech_area_union_col_entry)
221 | self._set_tooltip('--union-char=默认使用NULL\nunion查询时\n'
222 | '提高level, 会使用随机数\n'
223 | '如--union-char=001',
224 | m._tech_area_union_char_ckbtn,
225 | m._tech_area_union_char_entry)
226 | self._set_tooltip('--union-from=\nunion查询时',
227 | m._tech_area_union_from_ckbtn,
228 | m._tech_area_union_from_entry)
229 | self._set_tooltip('--dns-domain=\n'
230 | '如果控制了目标url的DNS服务器, 才可使用此选项\n'
231 | '这样做只是用来加快数据检索',
232 | m._tech_area_dns_ckbtn,
233 | m._tech_area_dns_entry)
234 | self._set_tooltip('--second-url=',
235 | m._tech_area_second_url_ckbtn,
236 | m._tech_area_second_url_entry)
237 | self._set_tooltip('--second-req=',
238 | m._tech_area_second_req_ckbtn,
239 | m._tech_area_second_req_entry)
240 | self._set_tooltip('sqlmap只会对CHAR()字符串进行混淆,\n'
241 | '不会对其他的payload进行任何混淆.\n'
242 | '要绕过IPS设备或Web应用防火墙(WAF)时, 使用此选项\n'
243 | '此处填写要使用的tamper脚本名\n'
244 | '详见: sqlmap --list-tamper\n回车或逗号拼接',
245 | m._tamper_area_tamper_view)
246 | self._set_tooltip('-o, 开启后会默认:\n'
247 | ' --keep-alive\n --null-connection\n --threads=3',
248 | m._optimize_area_turn_all_ckbtn)
249 | self._set_tooltip('--threads=\n默认为1, 最大为10',
250 | m._optimize_area_thread_num_ckbtn)
251 | self._set_tooltip('--predict-output\n'
252 | '此开关与--threads不兼容',
253 | m._optimize_area_predict_ckbtn)
254 | self._set_tooltip('--keep-alive\n'
255 | '此开关与--proxy不兼容',
256 | m._optimize_area_keep_alive_ckbtn)
257 | self._set_tooltip('--null-connection\n'
258 | '有的请求类型可用来获取响应大小而不用获取响应主体\n'
259 | '两种NULL连接技术: Range和HEAD\n'
260 | '此开关与--text-only不兼容',
261 | m._optimize_area_null_connect_ckbtn)
262 | # -v:
263 | # 0: 只显示Python回源(tracebacks), 错误(error)和关键(criticle)信息。
264 | # 1: 同时显示信息(info)和警告信息(warning)(默认为1)
265 | # 2: 同时显示调试信息(debug)
266 | # 3: 同时显示注入的有效载荷(payloads)
267 | # 4: 同时显示http请求
268 | # 5: 同时显示http响应头
269 | # 6: 同时显示http响应内容
270 | # self._set_tooltip('-v 默认为1',
271 | # m._general_area_verbose_ckbtn)
272 | self._set_tooltip('--fingerprint\n'
273 | '默认就会自动指纹DB,\n'
274 | '开启此开关后, 会发送更多请求, 以确定更精确的DB/OS等版本信息',
275 | m._general_area_finger_ckbtn)
276 | self._set_tooltip('--hex\n'
277 | '响应中的非ASCII数据不准确(如乱码)时, 会将其先编码成16进制格式',
278 | m._general_area_hex_ckbtn)
279 | self._set_tooltip('--batch',
280 | m._general_area_batch_ckbtn)
281 | self._set_tooltip('--wizard(其他选项可不选)',
282 | m._misc_area_wizard_ckbtn)
283 | # 2.请求页面
284 | self._set_tooltip('--random-agent\n'
285 | '默认, User-Agent: sqlmap/1.0-dev, 建议开启!',
286 | m._request_area_random_agent_ckbtn)
287 | self._set_tooltip('--mobile',
288 | m._request_area_mobile_ckbtn)
289 | self._set_tooltip('--user-agent=',
290 | m._request_area_user_agent_ckbtn,
291 | m._request_area_user_agent_entry)
292 | self._set_tooltip('--host=',
293 | m._request_area_host_ckbtn,
294 | m._request_area_host_entry)
295 | self._set_tooltip('--referer=\n'
296 | '默认情况下(即不加此参数)不会发送Referer报头',
297 | m._request_area_referer_ckbtn,
298 | m._request_area_referer_entry)
299 | self._set_tooltip('--header=',
300 | m._request_area_header_ckbtn,
301 | m._request_area_header_entry)
302 | self._set_tooltip('--headers=',
303 | m._request_area_headers_ckbtn,
304 | m._request_area_headers_entry)
305 | self._set_tooltip('--method=',
306 | m._request_area_method_ckbtn,
307 | m._request_area_method_entry)
308 | self._set_tooltip('--param-del=',
309 | m._request_area_param_del_ckbtn,
310 | m._request_area_param_del_entry)
311 | self._set_tooltip('--chunked',
312 | m._request_area_chunked_ckbtn)
313 | self._set_tooltip('--data=\n'
314 | '默认情况下sqlmap发送的是GET请求, 若使用此参数, 会将数据post到目标\n'
315 | '比如搜索框, 表单等会通过post方式发送数据',
316 | m._request_area_post_ckbtn,
317 | m._request_area_post_entry)
318 | self._set_tooltip('--cookie=',
319 | m._request_area_cookie_ckbtn,
320 | m._request_area_cookie_entry)
321 | self._set_tooltip('--cookie-del=',
322 | m._request_area_cookie_del_ckbtn,
323 | m._request_area_cookie_del_entry)
324 | self._set_tooltip('--drop-set-cookie=',
325 | m._request_area_drop_set_cookie_ckbtn)
326 | self._set_tooltip('--live-cookies=',
327 | m._request_area_live_cookies_ckbtn,
328 | m._request_area_live_cookies_entry)
329 | self._set_tooltip('--load-cookies=',
330 | m._request_area_load_cookies_ckbtn,
331 | m._request_area_load_cookies_entry)
332 | self._set_tooltip('--auth-type=Basic, Digest, NTLM or PKI',
333 | m._request_area_auth_type_ckbtn,
334 | m._request_area_auth_type_entry)
335 | self._set_tooltip('--auth-cred=',
336 | m._request_area_auth_cred_ckbtn,
337 | m._request_area_auth_cred_entry)
338 | self._set_tooltip('--auth-file=\n'
339 | 'PEM格式的key_file, 包含你的证书和私钥',
340 | m._request_area_auth_file_ckbtn,
341 | m._request_area_auth_file_entry)
342 | self._set_tooltip('--csrf-method=',
343 | m._request_area_csrf_method_ckbtn,
344 | m._request_area_csrf_method_entry)
345 | self._set_tooltip('--csrf-retries=',
346 | m._request_area_csrf_retries_ckbtn,
347 | m._request_area_csrf_retries_entry)
348 | self._set_tooltip('--csrf-token=\n'
349 | '有的表单中含有隐藏的随机token字段, 来防止csrf攻击',
350 | m._request_area_csrf_token_ckbtn,
351 | m._request_area_csrf_token_entry)
352 | self._set_tooltip('--csrf-url=\n'
353 | '若目标url没有token字段, 则指定有token字段的url',
354 | m._request_area_csrf_url_ckbtn,
355 | m._request_area_csrf_url_entry)
356 | self._set_tooltip('--ignore-timeouts',
357 | m._request_area_ignore_timeouts_ckbtn)
358 | self._set_tooltip('--ignore-redirects',
359 | m._request_area_ignore_redirects_ckbtn)
360 | self._set_tooltip('--ignore-code=',
361 | m._request_area_ignore_code_ckbtn,
362 | m._request_area_ignore_code_entry)
363 | self._set_tooltip('--skip-urlencode\n'
364 | '有的server只接受未编码的参数',
365 | m._request_area_skip_urlencode_ckbtn)
366 | self._set_tooltip('--force-ssl',
367 | m._request_area_force_ssl_ckbtn)
368 | self._set_tooltip('--hpp\n'
369 | '绕过WAF/IP/IDS的一种方法, 对ASP/IIS, ASP.NET/IIS特别有效',
370 | m._request_area_hpp_ckbtn)
371 | self._set_tooltip('--delay=隔几秒发送一个HTTP请求',
372 | m._request_area_delay_ckbtn,
373 | m._request_area_delay_entry)
374 | self._set_tooltip('--timeout=',
375 | m._request_area_timeout_ckbtn,
376 | m._request_area_timeout_entry)
377 | self._set_tooltip('--retries=连接超时后的重连次数',
378 | m._request_area_retries_ckbtn,
379 | m._request_area_retries_entry)
380 | self._set_tooltip('--randomize=',
381 | m._request_area_randomize_ckbtn,
382 | m._request_area_randomize_entry)
383 | self._set_tooltip('--eval=发送请求前先进行额外的处理(python code), 如:\n'
384 | 'import hashlib;id2=hashlib.md5(id).hexdigest()',
385 | m._request_area_eval_ckbtn,
386 | m._request_area_eval_entry)
387 | self._set_tooltip('--safe-url=\n'
388 | '避免错误请求过多而被屏蔽',
389 | m._request_area_safe_url_ckbtn,
390 | m._request_area_safe_url_entry)
391 | self._set_tooltip('--safe-post=',
392 | m._request_area_safe_post_ckbtn,
393 | m._request_area_safe_post_entry)
394 | self._set_tooltip('--safe-req=',
395 | m._request_area_safe_req_ckbtn,
396 | m._request_area_safe_req_entry)
397 | self._set_tooltip('--safe-freq=SAFE.. Test requests between two visits to a given safe URL',
398 | m._request_area_safe_freq_ckbtn,
399 | m._request_area_safe_freq_entry)
400 | self._set_tooltip('--ignore-proxy',
401 | m._request_area_ignore_proxy_ckbtn)
402 | self._set_tooltip('--proxy=',
403 | m._request_area_proxy_ckbtn,
404 | m._request_area_proxy_ip_label,
405 | m._request_area_proxy_ip_entry,
406 | m._request_area_proxy_port_label,
407 | m._request_area_proxy_port_entry)
408 | self._set_tooltip('--proxy-freq=',
409 | m._request_area_proxy_freq_ckbtn,
410 | m._request_area_proxy_freq_entry)
411 | self._set_tooltip('--proxy-file=',
412 | m._request_area_proxy_file_ckbtn,
413 | m._request_area_proxy_file_entry)
414 | self._set_tooltip('--proxy-cred=',
415 | m._request_area_proxy_username_label,
416 | m._request_area_proxy_username_entry,
417 | m._request_area_proxy_password_label,
418 | m._request_area_proxy_password_entry)
419 | self._set_tooltip('--tor',
420 | m._request_area_tor_ckbtn)
421 | self._set_tooltip('--tor-port=',
422 | m._request_area_tor_port_ckbtn,
423 | m._request_area_tor_port_entry)
424 | self._set_tooltip('--tor-type=',
425 | m._request_area_tor_type_ckbtn,
426 | m._request_area_tor_type_entry)
427 | self._set_tooltip('--check-tor',
428 | m._request_area_check_tor_ckbtn)
429 | # 3.Enumerate(E)
430 | self._set_tooltip('-b\t获取version()/@@version',
431 | m._enum_area_opts_ckbtns[0][0])
432 | self._set_tooltip('--current-user',
433 | m._enum_area_opts_ckbtns[0][1])
434 | self._set_tooltip('--current-db',
435 | m._enum_area_opts_ckbtns[0][2])
436 | self._set_tooltip('--hostname',
437 | m._enum_area_opts_ckbtns[0][3])
438 | self._set_tooltip('--is-dba',
439 | m._enum_area_opts_ckbtns[0][4])
440 | self._set_tooltip('--users',
441 | m._enum_area_opts_ckbtns[1][0])
442 | self._set_tooltip('--passwords',
443 | m._enum_area_opts_ckbtns[1][1])
444 | self._set_tooltip('--privileges\n'
445 | 'sql server会显示每个用户是否为dba, 而不是所有用户的权限列表',
446 | m._enum_area_opts_ckbtns[1][2])
447 | self._set_tooltip('--roles 仅限oracle可用',
448 | m._enum_area_opts_ckbtns[1][3])
449 | self._set_tooltip('--dbs',
450 | m._enum_area_opts_ckbtns[1][4])
451 | self._set_tooltip('--tables\n'
452 | '若不指定-D, 会枚举所有库的表名',
453 | m._enum_area_opts_ckbtns[2][0])
454 | self._set_tooltip('--columns\n'
455 | '所有列及数据类型, 可与-D, -T, -C配合\n'
456 | '若未指定-D, 则默认为当前库\n'
457 | 'PostgreSQL: 需提供 public 或系统库的名称, 因为不可能枚举其他数据库表',
458 | m._enum_area_opts_ckbtns[2][1])
459 | self._set_tooltip('--schema\n'
460 | '将枚举所有库, 表, 列及其各自类型\n'
461 | '建议配合--exclude-sysdbs, 数据量可能很大!',
462 | m._enum_area_opts_ckbtns[2][2])
463 | self._set_tooltip('--count\n'
464 | '表的条目数',
465 | m._enum_area_opts_ckbtns[2][3])
466 | self._set_tooltip('--comments',
467 | m._enum_area_opts_ckbtns[2][4])
468 | self._set_tooltip('--dump',
469 | m._dump_area_dump_ckbtn)
470 | self._set_tooltip('--repair',
471 | m._dump_area_repair_ckbtn)
472 | self._set_tooltip('--statements',
473 | m._dump_area_statements_ckbtn)
474 | self._set_tooltip('--search 需配合以下选项使用:\n'
475 | ' -C=逗号分隔的列名: 将在所有DB中的所有表中 搜索指定列名\n'
476 | ' -T=逗号分隔的表名: 将在所有DB中 搜索指定表名\n'
477 | ' -D=逗号分隔的数据库名: 将 搜索指定库名\n',
478 | m._dump_area_search_ckbtn)
479 | self._set_tooltip('--exclude-sysdbs\n注: sql server上master库不视为系统库',
480 | m._dump_area_no_sys_db_ckbtn)
481 | self._set_tooltip('--dump-all',
482 | m._dump_area_dump_all_ckbtn)
483 | self._set_tooltip('--start=',
484 | m._limit_area_start_ckbtn,
485 | m._limit_area_start_entry)
486 | self._set_tooltip('--stop=',
487 | m._limit_area_stop_ckbtn,
488 | m._limit_area_stop_entry)
489 | self._set_tooltip('--first=',
490 | m._blind_area_first_ckbtn,
491 | m._blind_area_first_entry)
492 | self._set_tooltip('--last=',
493 | m._blind_area_last_ckbtn,
494 | m._blind_area_last_entry)
495 | self._set_tooltip('-D DB\n'
496 | 'Oracle: 应指定TABLESPACE_NAME',
497 | m._meta_area_D_ckbtn,
498 | m._meta_area_D_entry)
499 | self._set_tooltip('-T TBL',
500 | m._meta_area_T_ckbtn,
501 | m._meta_area_T_entry)
502 | self._set_tooltip('-C COL',
503 | m._meta_area_C_ckbtn,
504 | m._meta_area_C_entry)
505 | self._set_tooltip('-U USER',
506 | m._meta_area_U_ckbtn,
507 | m._meta_area_U_entry)
508 | self._set_tooltip('-X EXCLUDE',
509 | m._meta_area_X_ckbtn,
510 | m._meta_area_X_entry)
511 | self._set_tooltip('--pivot-column=P\n'
512 | '导出表数据时, 会自动选择合适的具有唯一值的列,一般是主键\n'
513 | '当自动选择的privot列不正确时使用此项',
514 | m._meta_area_pivot_ckbtn,
515 | m._meta_area_pivot_entry)
516 | self._set_tooltip('--where=',
517 | m._meta_area_where_ckbtn,
518 | m._meta_area_where_entry)
519 | self._set_tooltip('--sql-query=QUERY\n'
520 | '如果是select语句, 会返回输出;\n'
521 | '如果目标支持多语句查询, 会使用堆查询技术',
522 | m._runsql_area_sql_query_ckbtn,
523 | m._runsql_area_sql_query_entry)
524 | self._set_tooltip('--sql-shell\n支持TAB补全, 历史记录',
525 | m._runsql_area_sql_shell_ckbtn)
526 | self._set_tooltip('--sql-file=SQLFILE',
527 | m._runsql_area_sql_file_ckbtn,
528 | m._runsql_area_sql_file_entry)
529 | self._set_tooltip('--common-tables\n'
530 | '有时--tables会失败, 通常原因如下:\n'
531 | ' 1.MySQL<5.0: information_schema不存在\n'
532 | ' 2.Access: 系统表(MSysObjects)默认不可读\n'
533 | ' 3.--current-user没有 读取系统表的 权限\n'
534 | ' 1和2的情况才能使用此选项(txt/common-tables.txt)',
535 | m._brute_force_area_common_tables_ckbtn)
536 | self._set_tooltip('--common-columns(见--common-tables)',
537 | m._brute_force_area_common_columns_ckbtn)
538 | self._set_tooltip('--common-files',
539 | m._brute_force_area_common_files_ckbtn)
540 | # 4.File(R)
541 | self._set_tooltip('远程DB所在主机上的文件路径\n'
542 | '前提: 1.MySQL, PostgreSQL或Microsoft SQL Server\n'
543 | ' 2.当前用户有 读取文件的 相关权限',
544 | m._file_read_area_file_read_ckbtn,
545 | m._file_read_area_file_read_entry)
546 | self._set_tooltip('只能查看已下载到本地的文件',
547 | m._file_read_area_file_read_btn)
548 | self._set_tooltip('--udf-inject\tUDF即user-defined function\n'
549 | '将共享库上传到DB所在文件系统上, 来创建用户自定义的函数以供使用',
550 | m._file_write_area_udf_ckbtn)
551 | self._set_tooltip('与--udf-inject配套使用, 可选',
552 | m._file_write_area_shared_lib_ckbtn,
553 | m._file_write_area_shared_lib_entry)
554 | self._set_tooltip('若使用此选项, 则--file-dest为必选项\n'
555 | '前提: 1.MySQL, PostgreSQL或Microsoft SQL Server\n'
556 | ' 2.当前用户有 使用特定函数上传文件的 相关权限',
557 | m._file_write_area_file_write_ckbtn,
558 | m._file_write_area_file_write_entry)
559 | self._set_tooltip('上传到DB服务器中的文件名, 要求是绝对路径, 构造后会有引号!\n'
560 | '与本地文件路径配套使用, 单独勾选无意义',
561 | m._file_write_area_file_dest_ckbtn,
562 | m._file_write_area_file_dest_entry)
563 | self._set_tooltip('--os-cmd=\n'
564 | '前提: 1.MySQL, PostgreSQL或Microsoft SQL Server\n'
565 | ' 2.当前用户有相关权限\n'
566 | 'MySQL或PostgreSQL: 上传包含sys_exec和sys_eval函数的共享库\n'
567 | 'SQL Server: 使用xp_cmdshell存储过程, 若被禁用(>=2005), 就启用它;\n'
568 | ' 若不存在, 就从新创建它',
569 | m._os_access_area_os_cmd_ckbtn,
570 | m._os_access_area_os_cmd_entry)
571 | self._set_tooltip('--os-shell\n支持TAB补全, 历史记录\n'
572 | '若不支持堆查询(如asp/php + MySQL), 且是MySQL(库站未分离!):\n'
573 | ' 会使用SELECT子句INTO OUTFILE在可写目录创建一个web后门来执行命令\n'
574 | ' 支持的web后门类型有: ASP, ASP.NET, JSP, PHP',
575 | m._os_access_area_os_shell_ckbtn)
576 | self._set_tooltip('MySQL和PostgreSQL:\n'
577 | ' 1.通过UDF中的sys_bineval函数 执行Metasploit的shellcode\n'
578 | ' 2.通过UDF中的sys_exec函数 上传并执行Metasploit的stand-alone payload stager\n'
579 | 'Microsoft SQL Server:\n'
580 | ' 1.通过xp_cmdshell储存过程 上传并执行Metasploit的stand-alone payload stager\n',
581 | m._os_access_area_os_pwn_ckbtn)
582 | self._set_tooltip('前提: 最高权限(linux: uid=0, windows: Administrator)\n'
583 | ' 且目标 数据库以Windows管理员身份运行时\n'
584 | ' 通过SMB攻击(MS08-068) 执行Metasploit的shellcode',
585 | m._os_access_area_os_smbrelay_ckbtn)
586 | self._set_tooltip('SQL Server 2000, 2005:\n'
587 | ' 通过sp_replwritetovarbin存储过程(MS09-004)溢出漏洞 执行Metasploit的payload\n'
588 | ' sqlmap用自带的exploit自动绕过DEP内存保护来触发漏洞, 但它依赖Metasploit来生成shellcode, 以便在成功利用后执行',
589 | m._os_access_area_os_bof_ckbtn)
590 | self._set_tooltip('使用Metasploit的getsystem命令来提权\n'
591 | '注: windows:\n'
592 | ' MySQL: 默认以SYSTEM身份运行\n'
593 | ' Server 2000: 默认以SYSTEM身份运行\n'
594 | ' Server 2005-2008: 多数以NETWORK SERVICE, 少数以LOCAL SERVICE身份运行\n'
595 | ' PostgreSQL: 默认以低权限的用户postgres运行\n'
596 | ' linux:\n'
597 | ' PostgreSQL: 默认以低权限的用户postgres运行',
598 | m._os_access_area_priv_esc_ckbtn)
599 | self._set_tooltip('--msf-path=',
600 | m._os_access_area_msf_path_ckbtn,
601 | m._os_access_area_msf_path_entry)
602 | self._set_tooltip('--tmp-path=TMPPATH Remote absolute path of temporary files directory',
603 | m._os_access_area_tmp_path_ckbtn,
604 | m._os_access_area_tmp_path_entry)
605 | self._set_tooltip('--reg-key=',
606 | m._registry_area_reg_key_label,
607 | m._registry_area_reg_key_entry)
608 | self._set_tooltip('--reg-value=',
609 | m._registry_area_reg_value_label,
610 | m._registry_area_reg_value_entry)
611 | self._set_tooltip('--reg-data=',
612 | m._registry_area_reg_data_label,
613 | m._registry_area_reg_data_entry)
614 | self._set_tooltip('--reg-type=',
615 | m._registry_area_reg_type_label,
616 | m._registry_area_reg_type_entry)
617 | # 5.Other(T)
618 | self._set_tooltip('--check-internet',
619 | m._general_area_check_internet_ckbtn)
620 | self._set_tooltip('--fresh-queries',
621 | m._general_area_fresh_queries_ckbtn)
622 | self._set_tooltip('--forms\n'
623 | '若想对 form表单参数 测试:\n'
624 | ' 1.通过某些方式得到请求文件或表单参数\n'
625 | ' 2.可用-r读取请求文件或--data指定表单参数\n'
626 | '但--forms开关: 可让sqlmap自行获取url响应中的表单参数 再做测试\n'
627 | '注: 是所有的表单, 及所有表单参数',
628 | m._general_area_forms_ckbtn)
629 | self._set_tooltip('--parse-errors',
630 | m._general_area_parse_errors_ckbtn)
631 | self._set_tooltip('--cleanup\n'
632 | '清理 DBMS(如临时表sqlmapoutput, udf)及文件系统',
633 | m._misc_area_cleanup_ckbtn)
634 | self._set_tooltip('Parameter(s) containing Base64 encoded data',
635 | m._general_area_base64_ckbtn,
636 | m._general_area_base64_entry)
637 | self._set_tooltip('Use URL and filename safe Base64 alphabet (RFC 4648)',
638 | m._general_area_base64_safe_ckbtn)
639 | self._set_tooltip('--table-prefix=',
640 | m._general_area_table_prefix_ckbtn,
641 | m._general_area_table_prefix_entry)
642 | self._set_tooltip('--binary-fields=\n'
643 | '指定有二进制值的列, 获取该列数据时, 会转成16进制输出',
644 | m._general_area_binary_fields_ckbtn,
645 | m._general_area_binary_fields_entry)
646 | self._set_tooltip('--preprocess=',
647 | m._general_area_preprocess_ckbtn,
648 | m._general_area_preprocess_entry)
649 | self._set_tooltip('--postprocess=',
650 | m._general_area_postprocess_ckbtn,
651 | m._general_area_postprocess_entry)
652 | self._set_tooltip('--charset= 如获取SHA1密文时, 请求数可减小30%',
653 | m._general_area_charset_ckbtn,
654 | m._general_area_charset_entry)
655 | self._set_tooltip('--encoding=',
656 | m._general_area_encoding_ckbtn,
657 | m._general_area_encoding_entry)
658 | self._set_tooltip('--web-root=WEBROOT Web server document root directory (e.g. "/var/www")',
659 | m._general_area_web_root_ckbtn,
660 | m._general_area_web_root_entry)
661 | self._set_tooltip('--scope=SCOPE Regexp to filter targets from provided proxy log',
662 | m._general_area_scope_ckbtn,
663 | m._general_area_scope_entry)
664 | self._set_tooltip('--test-filter=TE.. Select tests by payloads and/or titles (e.g. ROW)',
665 | m._general_area_test_filter_ckbtn,
666 | m._general_area_test_filter_entry)
667 | self._set_tooltip('--test-skip=TEST.. Skip tests by payloads and/or titles (e.g. BENCHMARK)',
668 | m._general_area_test_skip_ckbtn,
669 | m._general_area_test_skip_entry)
670 | self._set_tooltip('--crawl= 并且会收集有漏洞url',
671 | m._general_area_crawl_ckbtn,
672 | m._general_area_crawl_entry)
673 | self._set_tooltip('--crawl-exclude=',
674 | m._general_area_crawl_exclude_ckbtn,
675 | m._general_area_crawl_exclude_entry)
676 | self._set_tooltip('-t TRAFFICFILE Log all HTTP traffic into a textual file',
677 | m._general_area_traffic_file_ckbtn,
678 | m._general_area_traffic_file_entry)
679 | self._set_tooltip('--har=HARFILE Log all HTTP traffic into a HAR file',
680 | m._general_area_har_ckbtn,
681 | m._general_area_har_entry)
682 | self._set_tooltip('--flush-session',
683 | m._general_area_flush_session_ckbtn)
684 | self._set_tooltip('--dump-format=\nCSV(默认), HTML or SQLITE',
685 | m._general_area_dump_format_ckbtn,
686 | m._general_area_dump_format_entry)
687 | self._set_tooltip('--csv-del=',
688 | m._general_area_csv_del_ckbtn,
689 | m._general_area_csv_del_entry)
690 | self._set_tooltip('--save=SAVECONFIG Save options to a configuration INI file',
691 | m._general_area_save_ckbtn,
692 | m._general_area_save_entry)
693 | self._set_tooltip('-s SESSIONFILE Load session from a stored (.sqlite) file',
694 | m._general_area_session_file_ckbtn,
695 | m._general_area_session_file_entry)
696 | self._set_tooltip('--output-dir=',
697 | m._general_area_output_dir_ckbtn,
698 | m._general_area_output_dir_entry)
699 | self._set_tooltip('--skip-heuristics',
700 | m._misc_area_skip_heuristics_ckbtn)
701 | self._set_tooltip('--skip-waf\n'
702 | '默认情况, 会发送一个可疑的payload(所以有时明显没有防护还报警告)\n'
703 | '勾选以禁用此默认机制',
704 | m._misc_area_skip_waf_ckbtn)
705 | self._set_tooltip('--unstable',
706 | m._misc_area_unstable_ckbtn)
707 | self._set_tooltip('--list-tampers',
708 | m._misc_area_list_tampers_ckbtn)
709 | self._set_tooltip('--sqlmap-shell',
710 | m._misc_area_sqlmap_shell_ckbtn)
711 | self._set_tooltip('--disable-coloring',
712 | m._misc_area_disable_color_ckbtn)
713 | self._set_tooltip('--eta',
714 | m._general_area_eta_ckbtn)
715 | self._set_tooltip('--gpage=\n'
716 | '默认使用-g时, 会使用google的前100个URLs',
717 | m._misc_area_gpage_ckbtn)
718 | self._set_tooltip('--beep',
719 | m._misc_area_beep_ckbtn)
720 | self._set_tooltip('--offline',
721 | m._misc_area_offline_ckbtn)
722 | self._set_tooltip('--purge 抹除$HOME/.sqlmap目录',
723 | m._misc_area_purge_ckbtn)
724 | self._set_tooltip('--dependencies',
725 | m._misc_area_dependencies_ckbtn)
726 | self._set_tooltip('--update',
727 | m._misc_area_update_ckbtn)
728 | self._set_tooltip('--alert=ALERT Run host OS command(s) when SQL injection is found',
729 | m._misc_area_alert_ckbtn,
730 | m._misc_area_alert_entry)
731 | self._set_tooltip('--tmp-dir=TMPDIR Local directory for storing temporary files',
732 | m._misc_area_tmp_dir_ckbtn,
733 | m._misc_area_tmp_dir_entry)
734 | self._set_tooltip('--answers=ANSWERS Set question answers(e.g. "quit=N,follow=N")',
735 | m._misc_area_answers_ckbtn,
736 | m._misc_area_answers_entry)
737 | self._set_tooltip('-z MNEMONICS Use short mnemonics (e.g. "flu,bat,ban,tec=EU")',
738 | m._misc_area_z_ckbtn,
739 | m._misc_area_z_entry)
740 | self._set_tooltip('--results-file=R.. Location of CSV results file in multiple targets mode',
741 | m._misc_area_results_file_ckbtn,
742 | m._misc_area_results_file_entry)
743 | # LOG(page3)
744 | self._set_tooltip('不会修改文件',
745 | m._page3_clear_btn)
746 | # SQLMAPAPI(page4)
747 | self._set_tooltip('必填项, 不要加http://',
748 | m._page4_api_server_label,
749 | m._page4_api_server_entry)
750 | self._set_tooltip('必填项, 32位的token',
751 | m._page4_admin_token_label,
752 | m._page4_admin_token_entry)
753 | self._set_tooltip('此处填写要查看的选项(空格分隔), 如: url risk level',
754 | m._page4_option_get_entry)
755 | _api_usage = '''sqlampapi使用步骤:
756 | 1. 在本地或远程运行: ./sqlmapapi.py -s
757 | 2. 填写API区第一行的server和token
758 | 3. 点击 创建任务
759 | 4. 点击 显示任务 后, 下方窗格中会显示任务列表
760 | 5. 在本窗格中填写 python dict类型的选项如:
761 | {
762 | 'url': 'http://www.site.com/vuln.php?id=1',
763 | 'level': 1, 'risk': 1,
764 | }
765 | 6. 点击 设置:(会发送 本窗格的选项dict)
766 | 7. 点击 启动 (设置了选项才有意义)
767 | 注: 1.要查看任务的状态, 点击 显示任务 进行刷新
768 | 2.sqlmapapi支持的选项与sqlmap不兼容,
769 | 且其进行选项设置时, 没有检查选项!
770 | 如果设置了无效的选项, 只能删除任务!
771 | '''
772 | self._set_tooltip(_api_usage,
773 | m._page4_option_set_view)
774 |
775 | def _set_placeholder(self, placeholder, *widgets):
776 | '''
777 | wx.TextEntry.SetHint
778 | widgets: 应该都是entry吧?
779 | '''
780 | for _widget in widgets:
781 | _widget.SetHint(placeholder)
782 |
783 | def _set_tooltip(self, tooltip, *widgets):
784 | '''
785 | wx.Window.SetToolTip
786 | '''
787 | for _widget in widgets:
788 | _widget.SetToolTip(tooltip)
789 |
790 |
791 | def main():
792 | pass
793 |
794 |
795 | if __name__ == '__main__':
796 | main()
797 |
--------------------------------------------------------------------------------
/widgets.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | #
3 | # 2019-05-05 21:09:49
4 | import string
5 | import wx
6 | import wx.lib.agw.flatnotebook as FNB
7 | from wx.lib.scrolledpanel import ScrolledPanel
8 |
9 |
10 | class Notebook(FNB.FlatNotebook):
11 | def __init__(self, *args, **kwargs):
12 | # emulate the old wx.Notebook style
13 | _bookStyle = FNB.FNB_NO_X_BUTTON | FNB.FNB_NO_NAV_BUTTONS | FNB.FNB_NODRAG
14 | # 标签不能有焦点, 不然win7下ScrolledPanel不响应滚轮,
15 | # ScrolledPanel needs focus inside to response wheel
16 | # use ribbon style
17 | _bookStyle |= FNB.FNB_NO_TAB_FOCUS | FNB.FNB_RIBBON_TABS
18 | super().__init__(*args, agwStyle=_bookStyle, **kwargs)
19 | self.SetBackgroundColour(wx.WHITE)
20 |
21 |
22 | class CheckBox(wx.CheckBox):
23 | def __init__(self, *args, **kwargs):
24 | super().__init__(*args, **kwargs)
25 | # 一步构造, 不能调用Create
26 | if args or kwargs:
27 | self._set_win_color()
28 |
29 | def Create(self, *args, **kwargs):
30 | # Create方法用于两步构造
31 | super().Create(*args, **kwargs)
32 | self._set_win_color()
33 |
34 | def _set_win_color(self):
35 | # only for win, 背景(240, 240, 240, 255)是灰色, 却要重新设一遍前景才能去灰~
36 | # 侮辱智商! 脑子都搞蒙了
37 | self.SetForegroundColour(self.GetForegroundColour())
38 |
39 | self.origin_bgcolor = wx.SystemSettings.GetColour(wx.SYS_COLOUR_WINDOW)
40 | self.Bind(wx.EVT_CHECKBOX, self.set_color)
41 |
42 | def set_color(self, event):
43 | if self.IsChecked():
44 | # 跟sqlmap-gtk一样: #f6d488
45 | self.SetBackgroundColour(wx.Colour(246, 212, 136))
46 | else:
47 | self.SetBackgroundColour(self.origin_bgcolor)
48 | # 这里调不调skip无所谓吧~
49 | if event:
50 | event.Skip()
51 |
52 | def SetValue(self, state):
53 | super().SetValue(state)
54 | self.set_color(None)
55 |
56 |
57 | class NumCtrl(wx.TextCtrl):
58 | '''
59 | 正整数
60 | https://stackoverflow.com/questions/1369086/is-it-possible-to-limit-textctrl-to-accept-numbers-only-in-wxpython
61 | '''
62 | def __init__(self, *args, **kwargs):
63 | super().__init__(*args, **kwargs)
64 | self.Bind(wx.EVT_CHAR, self.onChar)
65 |
66 | def onChar(self, event):
67 | keycode = event.GetKeyCode()
68 | obj = event.GetEventObject()
69 | val = self.GetValue()
70 | # filter unicode characters
71 | if keycode == wx.WXK_NONE:
72 | pass
73 | # allow digits
74 | elif chr(keycode) in string.digits:
75 | event.Skip()
76 | # allow special, non-printable keycodes
77 | elif chr(keycode) not in string.printable:
78 | event.Skip() # allow all other special keycode
79 | return
80 |
81 |
82 | class FloatCtrl(wx.TextCtrl):
83 | '''
84 | https://stackoverflow.com/questions/1369086/is-it-possible-to-limit-textctrl-to-accept-numbers-only-in-wxpython
85 | '''
86 | def __init__(self, *args, **kwargs):
87 | super().__init__(*args, **kwargs)
88 | self.Bind(wx.EVT_CHAR, self.onChar)
89 |
90 | def onChar(self, event):
91 | keycode = event.GetKeyCode()
92 | obj = event.GetEventObject()
93 | val = super().GetValue()
94 | # filter unicode characters
95 | if keycode == wx.WXK_NONE:
96 | pass
97 | # allow digits
98 | elif chr(keycode) in string.digits:
99 | event.Skip()
100 | # allow special, non-printable keycodes
101 | elif chr(keycode) not in string.printable:
102 | event.Skip() # allow all other special keycode
103 | # allow '-' for negative numbers
104 | elif chr(keycode) == '-':
105 | # 负号只能是开头
106 | if '-' not in val:
107 | obj.SetValue('-' + val) # 如果是首次输入"-", 则放在开头
108 | obj.SetInsertionPointEnd()
109 | else:
110 | obj.SetValue(val[1:]) # 如果已存在"-", 则去掉
111 | obj.SetInsertionPointEnd()
112 | # allow '.' for float numbers
113 | elif chr(keycode) == '.' and '.' not in val:
114 | event.Skip()
115 | return
116 |
117 | def GetValue(self):
118 | try:
119 | return float(super().GetValue())
120 | except Exception as e:
121 | return 0.0
122 |
123 |
124 | EVT_BUTTON = wx.EVT_BUTTON
125 | EVT_CHECKBOX = wx.EVT_CHECKBOX
126 |
127 | # nb = wx.Notebook # awful widget, don't use
128 | nb = Notebook
129 | Panel = wx.Panel
130 | StaticBox = wx.StaticBox
131 | SplitterWindow = wx.SplitterWindow
132 | Scroll = ScrolledPanel
133 |
134 | btn = wx.Button
135 | cb = CheckBox
136 | cbb = wx.ComboBox
137 | ci = wx.Choice
138 | nc = NumCtrl
139 | sl = wx.Slider
140 | sp = wx.SpinCtrl
141 | st = wx.StaticText
142 | tc = wx.TextCtrl
143 |
144 | VERTICAL = wx.VERTICAL
145 | HORIZONTAL = wx.HORIZONTAL
146 |
147 | BoxSizer = wx.BoxSizer
148 | GridSizer = wx.GridSizer
149 | StaticBoxSizer = wx.StaticBoxSizer
150 | FlexGridSizer = wx.FlexGridSizer
151 |
152 | EXPAND = wx.EXPAND
153 | ALL = wx.ALL
154 | TOP = wx.TOP
155 | BOTTOM = wx.BOTTOM
156 | LEFT = wx.LEFT
157 | RIGHT = wx.RIGHT
158 | ALIGN_RIGHT = wx.ALIGN_RIGHT
159 | ALIGN_CENTER = wx.ALIGN_CENTER
160 |
161 | SizerFlags = wx.SizerFlags
162 |
163 |
164 | def main():
165 | pass
166 |
167 |
168 | if __name__ == '__main__':
169 | main()
170 |
--------------------------------------------------------------------------------