No One Can Stop Me Now

This commit is contained in:
DigiJ
2026-03-13 23:48:47 -07:00
parent 4d3570781e
commit 1a138a2bd0
428 changed files with 519668 additions and 259 deletions

BIN
Output/AUTARCH_Setup.exe Normal file

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

View File

@@ -0,0 +1,151 @@
[llama]
model_path = C:\she\autarch\models\darkHal.gguf
n_ctx = 2048
n_threads = 4
n_gpu_layers = -1
temperature = 0.7
top_p = 0.9
top_k = 40
repeat_penalty = 1.1
max_tokens = 1024
seed = -1
n_batch = 512
rope_scaling_type = 0
mirostat_mode = 0
mirostat_tau = 5.0
mirostat_eta = 0.1
flash_attn = false
gpu_backend = vulkan
[autarch]
first_run = false
modules_path = modules
verbose = false
llm_backend = local
quiet = false
no_banner = false
[msf]
host = 127.0.0.1
port = 55553
username = msf
password = msdf
ssl = true
[osint]
max_threads = 8
timeout = 8
include_nsfw = true
[transformers]
model_path = C:\she\autarch\models\Lily-Cybersecurity-7B-v0.2
device = xpu
torch_dtype = auto
load_in_8bit = false
load_in_4bit = true
trust_remote_code = false
max_tokens = 1024
temperature = 0.7
top_p = 0.9
top_k = 40
repetition_penalty = 1.1
use_fast_tokenizer = true
padding_side = left
do_sample = true
num_beams = 1
llm_int8_enable_fp32_cpu_offload = false
device_map = auto
[claude]
api_key =
model = claude-sonnet-4-20250514
max_tokens = 4096
temperature = 0.7
[pentest]
max_pipeline_steps = 50
output_chunk_size = 2000
auto_execute = false
save_raw_output = true
[rsf]
install_path =
enabled = true
default_target =
default_port = 80
execution_timeout = 120
[upnp]
enabled = true
internal_ip = 10.0.0.26
refresh_hours = 12
mappings = 443:TCP,51820:UDP,8080:TCP
[wireguard]
enabled = true
config_path = /etc/wireguard/wg0.conf
interface = wg0
subnet = 10.1.0.0/24
server_address = 10.1.0.1
listen_port = 51820
default_dns = 1.1.1.1, 8.8.8.8
default_allowed_ips = 0.0.0.0/0, ::/0
[huggingface]
api_key =
model = mistralai/Mistral-7B-Instruct-v0.3
endpoint =
max_tokens = 1024
temperature = 0.7
top_p = 0.9
[discovery]
enabled = true
mdns_enabled = true
bluetooth_enabled = true
bt_require_security = true
[web]
host = 0.0.0.0
port = 8181
secret_key = 23088243f11ce0b135c64413073c8c9fc0ecf83711d5f892b68f95b348a54007
mcp_port = 8081
[revshell]
enabled = true
host = 0.0.0.0
port = 17322
auto_start = false
[slm]
enabled = true
backend = local
model_path =
n_ctx = 512
n_gpu_layers = -1
n_threads = 2
[sam]
enabled = true
backend = local
model_path =
n_ctx = 2048
n_gpu_layers = -1
n_threads = 4
[lam]
enabled = true
backend = local
model_path =
n_ctx = 4096
n_gpu_layers = -1
n_threads = 4
[autonomy]
enabled = false
monitor_interval = 3
rule_eval_interval = 5
max_concurrent_agents = 3
threat_threshold_auto_respond = 40
log_max_entries = 1000

View File

@@ -0,0 +1,82 @@
Metadata-Version: 2.4
Name: click
Version: 8.2.1
Summary: Composable command line interface toolkit
Maintainer-email: Pallets <contact@palletsprojects.com>
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-Expression: BSD-3-Clause
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python
Classifier: Typing :: Typed
License-File: LICENSE.txt
Requires-Dist: colorama; platform_system == 'Windows'
Project-URL: Changes, https://click.palletsprojects.com/page/changes/
Project-URL: Chat, https://discord.gg/pallets
Project-URL: Documentation, https://click.palletsprojects.com/
Project-URL: Donate, https://palletsprojects.com/donate
Project-URL: Source, https://github.com/pallets/click/
# $ click_
Click is a Python package for creating beautiful command line interfaces
in a composable way with as little code as necessary. It's the "Command
Line Interface Creation Kit". It's highly configurable but comes with
sensible defaults out of the box.
It aims to make the process of writing command line tools quick and fun
while also preventing any frustration caused by the inability to
implement an intended CLI API.
Click in three points:
- Arbitrary nesting of commands
- Automatic help page generation
- Supports lazy loading of subcommands at runtime
## A Simple Example
```python
import click
@click.command()
@click.option("--count", default=1, help="Number of greetings.")
@click.option("--name", prompt="Your name", help="The person to greet.")
def hello(count, name):
"""Simple program that greets NAME for a total of COUNT times."""
for _ in range(count):
click.echo(f"Hello, {name}!")
if __name__ == '__main__':
hello()
```
```
$ python hello.py --count=3
Your name: Click
Hello, Click!
Hello, Click!
Hello, Click!
```
## Donate
The Pallets organization develops and supports Click and other popular
packages. In order to grow the community of contributors and users, and
allow the maintainers to devote more time to the projects, [please
donate today][].
[please donate today]: https://palletsprojects.com/donate
## Contributing
See our [detailed contributing documentation][contrib] for many ways to
contribute, including reporting issues, requesting features, asking or answering
questions, and making PRs.
[contrib]: https://palletsprojects.com/contributing/

View File

@@ -0,0 +1,38 @@
click-8.2.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
click-8.2.1.dist-info/METADATA,sha256=dI1MbhHTLoKD2tNCCGnx9rK2gok23HDNylFeLKdLSik,2471
click-8.2.1.dist-info/RECORD,,
click-8.2.1.dist-info/WHEEL,sha256=G2gURzTEtmeR8nrdXUJfNiB3VYVxigPQ-bEQujpNiNs,82
click-8.2.1.dist-info/licenses/LICENSE.txt,sha256=morRBqOU6FO_4h9C9OctWSgZoigF2ZG18ydQKSkrZY0,1475
click/__init__.py,sha256=6YyS1aeyknZ0LYweWozNZy0A9nZ_11wmYIhv3cbQrYo,4473
click/__pycache__/__init__.cpython-313.pyc,,
click/__pycache__/_compat.cpython-313.pyc,,
click/__pycache__/_termui_impl.cpython-313.pyc,,
click/__pycache__/_textwrap.cpython-313.pyc,,
click/__pycache__/_winconsole.cpython-313.pyc,,
click/__pycache__/core.cpython-313.pyc,,
click/__pycache__/decorators.cpython-313.pyc,,
click/__pycache__/exceptions.cpython-313.pyc,,
click/__pycache__/formatting.cpython-313.pyc,,
click/__pycache__/globals.cpython-313.pyc,,
click/__pycache__/parser.cpython-313.pyc,,
click/__pycache__/shell_completion.cpython-313.pyc,,
click/__pycache__/termui.cpython-313.pyc,,
click/__pycache__/testing.cpython-313.pyc,,
click/__pycache__/types.cpython-313.pyc,,
click/__pycache__/utils.cpython-313.pyc,,
click/_compat.py,sha256=v3xBZkFbvA1BXPRkFfBJc6-pIwPI7345m-kQEnpVAs4,18693
click/_termui_impl.py,sha256=ASXhLi9IQIc0Js9KQSS-3-SLZcPet3VqysBf9WgbbpI,26712
click/_textwrap.py,sha256=BOae0RQ6vg3FkNgSJyOoGzG1meGMxJ_ukWVZKx_v-0o,1400
click/_winconsole.py,sha256=_vxUuUaxwBhoR0vUWCNuHY8VUefiMdCIyU2SXPqoF-A,8465
click/core.py,sha256=gUhpNS9cFBGdEXXdisGVG-eRvGf49RTyFagxulqwdFw,117343
click/decorators.py,sha256=5P7abhJtAQYp_KHgjUvhMv464ERwOzrv2enNknlwHyQ,18461
click/exceptions.py,sha256=1rdtXgHJ1b3OjGkN-UpXB9t_HCBihJvh_DtpmLmwn9s,9891
click/formatting.py,sha256=Bhqx4QXdKQ9W4WKknIwj5KPKFmtduGOuGq1yw_THLZ8,9726
click/globals.py,sha256=gM-Nh6A4M0HB_SgkaF5M4ncGGMDHc_flHXu9_oh4GEU,1923
click/parser.py,sha256=nU1Ah2p11q29ul1vNdU9swPo_PUuKrxU6YXToi71q1c,18979
click/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
click/shell_completion.py,sha256=CQSGdjgun4ORbOZrXP0CVhEtPx4knsufOkRsDiK64cM,19857
click/termui.py,sha256=vAYrKC2a7f_NfEIhAThEVYfa__ib5XQbTSCGtJlABRA,30847
click/testing.py,sha256=2eLdAaCJCGToP5Tw-XN8JjrDb3wbJIfARxg3d0crW5M,18702
click/types.py,sha256=KBTRxN28cR1VZ5mb9iJX98MQSw_p9SGzljqfEI8z5Tw,38389
click/utils.py,sha256=b1Mm-usEDBHtEwcPltPIn3zSK4nw2KTp5GC7_oSTlLo,20245

View File

@@ -0,0 +1,4 @@
Wheel-Version: 1.0
Generator: flit 3.12.0
Root-Is-Purelib: true
Tag: py3-none-any

View File

@@ -0,0 +1,28 @@
Copyright 2014 Pallets
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@@ -0,0 +1,139 @@
Metadata-Version: 2.4
Name: cryptography
Version: 46.0.5
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: Natural Language :: English
Classifier: Operating System :: MacOS :: MacOS X
Classifier: Operating System :: POSIX
Classifier: Operating System :: POSIX :: BSD
Classifier: Operating System :: POSIX :: Linux
Classifier: Operating System :: Microsoft :: Windows
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Programming Language :: Python :: Implementation :: CPython
Classifier: Programming Language :: Python :: Implementation :: PyPy
Classifier: Programming Language :: Python :: Free Threading :: 3 - Stable
Classifier: Topic :: Security :: Cryptography
Requires-Dist: cffi>=1.14 ; python_full_version == '3.8.*' and platform_python_implementation != 'PyPy'
Requires-Dist: cffi>=2.0.0 ; python_full_version >= '3.9' and platform_python_implementation != 'PyPy'
Requires-Dist: typing-extensions>=4.13.2 ; python_full_version < '3.11'
Requires-Dist: bcrypt>=3.1.5 ; extra == 'ssh'
Requires-Dist: nox[uv]>=2024.4.15 ; extra == 'nox'
Requires-Dist: cryptography-vectors==46.0.5 ; extra == 'test'
Requires-Dist: pytest>=7.4.0 ; extra == 'test'
Requires-Dist: pytest-benchmark>=4.0 ; extra == 'test'
Requires-Dist: pytest-cov>=2.10.1 ; extra == 'test'
Requires-Dist: pytest-xdist>=3.5.0 ; extra == 'test'
Requires-Dist: pretend>=0.7 ; extra == 'test'
Requires-Dist: certifi>=2024 ; extra == 'test'
Requires-Dist: pytest-randomly ; extra == 'test-randomorder'
Requires-Dist: sphinx>=5.3.0 ; extra == 'docs'
Requires-Dist: sphinx-rtd-theme>=3.0.0 ; extra == 'docs'
Requires-Dist: sphinx-inline-tabs ; extra == 'docs'
Requires-Dist: pyenchant>=3 ; extra == 'docstest'
Requires-Dist: readme-renderer>=30.0 ; extra == 'docstest'
Requires-Dist: sphinxcontrib-spelling>=7.3.1 ; extra == 'docstest'
Requires-Dist: build>=1.0.0 ; extra == 'sdist'
Requires-Dist: ruff>=0.11.11 ; extra == 'pep8test'
Requires-Dist: mypy>=1.14 ; extra == 'pep8test'
Requires-Dist: check-sdist ; extra == 'pep8test'
Requires-Dist: click>=8.0.1 ; extra == 'pep8test'
Provides-Extra: ssh
Provides-Extra: nox
Provides-Extra: test
Provides-Extra: test-randomorder
Provides-Extra: docs
Provides-Extra: docstest
Provides-Extra: sdist
Provides-Extra: pep8test
License-File: LICENSE
License-File: LICENSE.APACHE
License-File: LICENSE.BSD
Summary: cryptography is a package which provides cryptographic recipes and primitives to Python developers.
Author-email: The Python Cryptographic Authority and individual contributors <cryptography-dev@python.org>
License-Expression: Apache-2.0 OR BSD-3-Clause
Requires-Python: >=3.8, !=3.9.0, !=3.9.1
Description-Content-Type: text/x-rst; charset=UTF-8
Project-URL: homepage, https://github.com/pyca/cryptography
Project-URL: documentation, https://cryptography.io/
Project-URL: source, https://github.com/pyca/cryptography/
Project-URL: issues, https://github.com/pyca/cryptography/issues
Project-URL: changelog, https://cryptography.io/en/latest/changelog/
pyca/cryptography
=================
.. image:: https://img.shields.io/pypi/v/cryptography.svg
:target: https://pypi.org/project/cryptography/
:alt: Latest Version
.. image:: https://readthedocs.org/projects/cryptography/badge/?version=latest
:target: https://cryptography.io
:alt: Latest Docs
.. image:: https://github.com/pyca/cryptography/actions/workflows/ci.yml/badge.svg
:target: https://github.com/pyca/cryptography/actions/workflows/ci.yml?query=branch%3Amain
``cryptography`` is a package which provides cryptographic recipes and
primitives to Python developers. Our goal is for it to be your "cryptographic
standard library". It supports Python 3.8+ and PyPy3 7.3.11+.
``cryptography`` includes both high level recipes and low level interfaces to
common cryptographic algorithms such as symmetric ciphers, message digests, and
key derivation functions. For example, to encrypt something with
``cryptography``'s high level symmetric encryption recipe:
.. code-block:: pycon
>>> from cryptography.fernet import Fernet
>>> # Put this somewhere safe!
>>> key = Fernet.generate_key()
>>> f = Fernet(key)
>>> token = f.encrypt(b"A really secret message. Not for prying eyes.")
>>> token
b'...'
>>> f.decrypt(token)
b'A really secret message. Not for prying eyes.'
You can find more information in the `documentation`_.
You can install ``cryptography`` with:
.. code-block:: console
$ pip install cryptography
For full details see `the installation documentation`_.
Discussion
~~~~~~~~~~
If you run into bugs, you can file them in our `issue tracker`_.
We maintain a `cryptography-dev`_ mailing list for development discussion.
You can also join ``#pyca`` on ``irc.libera.chat`` to ask questions or get
involved.
Security
~~~~~~~~
Need to report a security issue? Please consult our `security reporting`_
documentation.
.. _`documentation`: https://cryptography.io/
.. _`the installation documentation`: https://cryptography.io/en/latest/installation/
.. _`issue tracker`: https://github.com/pyca/cryptography/issues
.. _`cryptography-dev`: https://mail.python.org/mailman/listinfo/cryptography-dev
.. _`security reporting`: https://cryptography.io/en/latest/security/

View File

@@ -0,0 +1,180 @@
cryptography-46.0.5.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
cryptography-46.0.5.dist-info/METADATA,sha256=aOYB9_B-Ccske76ncMz-w9c_VnzYihv_7kxZlt2i2WQ,5748
cryptography-46.0.5.dist-info/RECORD,,
cryptography-46.0.5.dist-info/WHEEL,sha256=8hEf8NzM1FnmM77AjVt5h8nDuYkN3UqZ79LoIAHXeRE,95
cryptography-46.0.5.dist-info/licenses/LICENSE,sha256=Pgx8CRqUi4JTO6mP18u0BDLW8amsv4X1ki0vmak65rs,197
cryptography-46.0.5.dist-info/licenses/LICENSE.APACHE,sha256=qsc7MUj20dcRHbyjIJn2jSbGRMaBOuHk8F9leaomY_4,11360
cryptography-46.0.5.dist-info/licenses/LICENSE.BSD,sha256=YCxMdILeZHndLpeTzaJ15eY9dz2s0eymiSMqtwCPtPs,1532
cryptography/__about__.py,sha256=GWg4NAxg4vsSKUwmDy1HjUeAOhqTA46wIhiY6i03NSU,445
cryptography/__init__.py,sha256=mthuUrTd4FROCpUYrTIqhjz6s6T9djAZrV7nZ1oMm2o,364
cryptography/__pycache__/__about__.cpython-313.pyc,,
cryptography/__pycache__/__init__.cpython-313.pyc,,
cryptography/__pycache__/exceptions.cpython-313.pyc,,
cryptography/__pycache__/fernet.cpython-313.pyc,,
cryptography/__pycache__/utils.cpython-313.pyc,,
cryptography/exceptions.py,sha256=835EWILc2fwxw-gyFMriciC2SqhViETB10LBSytnDIc,1087
cryptography/fernet.py,sha256=3Cvxkh0KJSbX8HbnCHu4wfCW7U0GgfUA3v_qQ8a8iWc,6963
cryptography/hazmat/__init__.py,sha256=5IwrLWrVp0AjEr_4FdWG_V057NSJGY_W4egNNsuct0g,455
cryptography/hazmat/__pycache__/__init__.cpython-313.pyc,,
cryptography/hazmat/__pycache__/_oid.cpython-313.pyc,,
cryptography/hazmat/_oid.py,sha256=p8ThjwJB56Ci_rAIrjyJ1f8VjgD6e39es2dh8JIUBOw,17240
cryptography/hazmat/asn1/__init__.py,sha256=hS_EWx3wVvZzfbCcNV8hzcDnyMM8H-BhIoS1TipUosk,293
cryptography/hazmat/asn1/__pycache__/__init__.cpython-313.pyc,,
cryptography/hazmat/asn1/__pycache__/asn1.cpython-313.pyc,,
cryptography/hazmat/asn1/asn1.py,sha256=eMEThEXa19LQjcyVofgHsW6tsZnjp3ddH7bWkkcxfLM,3860
cryptography/hazmat/backends/__init__.py,sha256=O5jvKFQdZnXhKeqJ-HtulaEL9Ni7mr1mDzZY5kHlYhI,361
cryptography/hazmat/backends/__pycache__/__init__.cpython-313.pyc,,
cryptography/hazmat/backends/openssl/__init__.py,sha256=p3jmJfnCag9iE5sdMrN6VvVEu55u46xaS_IjoI0SrmA,305
cryptography/hazmat/backends/openssl/__pycache__/__init__.cpython-313.pyc,,
cryptography/hazmat/backends/openssl/__pycache__/backend.cpython-313.pyc,,
cryptography/hazmat/backends/openssl/backend.py,sha256=tV5AxBoFJ2GfA0DMWSY-0TxQJrpQoexzI9R4Kybb--4,10215
cryptography/hazmat/bindings/__init__.py,sha256=s9oKCQ2ycFdXoERdS1imafueSkBsL9kvbyfghaauZ9Y,180
cryptography/hazmat/bindings/__pycache__/__init__.cpython-313.pyc,,
cryptography/hazmat/bindings/_rust.pyd,sha256=knGoVIXvM_YJK_uAE8So79A94TE14UB_CTtgTk71420,9110528
cryptography/hazmat/bindings/_rust/__init__.pyi,sha256=KhqLhXFPArPzzJ7DYO9Fl8FoXB_BagAd_r4Dm_Ze9Xo,1257
cryptography/hazmat/bindings/_rust/_openssl.pyi,sha256=mpNJLuYLbCVrd5i33FBTmWwL_55Dw7JPkSLlSX9Q7oI,230
cryptography/hazmat/bindings/_rust/asn1.pyi,sha256=BrGjC8J6nwuS-r3EVcdXJB8ndotfY9mbQYOfpbPG0HA,354
cryptography/hazmat/bindings/_rust/declarative_asn1.pyi,sha256=2ECFmYue1EPkHEE2Bm7aLwkjB0mSUTpr23v9MN4pri4,892
cryptography/hazmat/bindings/_rust/exceptions.pyi,sha256=exXr2xw_0pB1kk93cYbM3MohbzoUkjOms1ZMUi0uQZE,640
cryptography/hazmat/bindings/_rust/ocsp.pyi,sha256=VPVWuKHI9EMs09ZLRYAGvR0Iz0mCMmEzXAkgJHovpoM,4020
cryptography/hazmat/bindings/_rust/openssl/__init__.pyi,sha256=iOAMDyHoNwwCSZfZzuXDr64g4GpGUeDgEN-LjXqdrBM,1522
cryptography/hazmat/bindings/_rust/openssl/aead.pyi,sha256=4Nddw6-ynzIB3w2W86WvkGKTLlTDk_6F5l54RHCuy3E,2688
cryptography/hazmat/bindings/_rust/openssl/ciphers.pyi,sha256=LhPzHWSXJq4grAJXn6zSvSSdV-aYIIscHDwIPlJGGPs,1315
cryptography/hazmat/bindings/_rust/openssl/cmac.pyi,sha256=nPH0X57RYpsAkRowVpjQiHE566ThUTx7YXrsadmrmHk,564
cryptography/hazmat/bindings/_rust/openssl/dh.pyi,sha256=Z3TC-G04-THtSdAOPLM1h2G7ml5bda1ElZUcn5wpuhk,1564
cryptography/hazmat/bindings/_rust/openssl/dsa.pyi,sha256=qBtkgj2albt2qFcnZ9UDrhzoNhCVO7HTby5VSf1EXMI,1299
cryptography/hazmat/bindings/_rust/openssl/ec.pyi,sha256=zJy0pRa5n-_p2dm45PxECB_-B6SVZyNKfjxFDpPqT38,1691
cryptography/hazmat/bindings/_rust/openssl/ed25519.pyi,sha256=VXfXd5G6hUivg399R1DYdmW3eTb0EebzDTqjRC2gaRw,532
cryptography/hazmat/bindings/_rust/openssl/ed448.pyi,sha256=Yx49lqdnjsD7bxiDV1kcaMrDktug5evi5a6zerMiy2s,514
cryptography/hazmat/bindings/_rust/openssl/hashes.pyi,sha256=OWZvBx7xfo_HJl41Nc--DugVyCVPIprZ3HlOPTSWH9g,984
cryptography/hazmat/bindings/_rust/openssl/hmac.pyi,sha256=BXZn7NDjL3JAbYW0SQ8pg1iyC5DbQXVhUAiwsi8DFR8,702
cryptography/hazmat/bindings/_rust/openssl/kdf.pyi,sha256=xXfFBb9QehHfDtEaxV_65Z0YK7NquOVIChpTLkgAs_k,2029
cryptography/hazmat/bindings/_rust/openssl/keys.pyi,sha256=teIt8M6ZEMJrn4s3W0UnW0DZ-30Jd68WnSsKKG124l0,912
cryptography/hazmat/bindings/_rust/openssl/poly1305.pyi,sha256=_SW9NtQ5FDlAbdclFtWpT4lGmxKIKHpN-4j8J2BzYfQ,585
cryptography/hazmat/bindings/_rust/openssl/rsa.pyi,sha256=2OQCNSXkxgc-3uw1xiCCloIQTV6p9_kK79Yu0rhZgPc,1364
cryptography/hazmat/bindings/_rust/openssl/x25519.pyi,sha256=ewn4GpQyb7zPwE-ni7GtyQgMC0A1mLuqYsSyqv6nI_s,523
cryptography/hazmat/bindings/_rust/openssl/x448.pyi,sha256=juTZTmli8jO_5Vcufg-vHvx_tCyezmSLIh_9PU3TczI,505
cryptography/hazmat/bindings/_rust/pkcs12.pyi,sha256=vEEd5wDiZvb8ZGFaziLCaWLzAwoG_tvPUxLQw5_uOl8,1605
cryptography/hazmat/bindings/_rust/pkcs7.pyi,sha256=txGBJijqZshEcqra6byPNbnisIdlxzOSIHP2hl9arPs,1601
cryptography/hazmat/bindings/_rust/test_support.pyi,sha256=PPhld-WkO743iXFPebeG0LtgK0aTzGdjcIsay1Gm5GE,757
cryptography/hazmat/bindings/_rust/x509.pyi,sha256=n9X0IQ6ICbdIi-ExdCFZoBgeY6njm3QOVAVZwDQdnbk,9784
cryptography/hazmat/bindings/openssl/__init__.py,sha256=s9oKCQ2ycFdXoERdS1imafueSkBsL9kvbyfghaauZ9Y,180
cryptography/hazmat/bindings/openssl/__pycache__/__init__.cpython-313.pyc,,
cryptography/hazmat/bindings/openssl/__pycache__/_conditional.cpython-313.pyc,,
cryptography/hazmat/bindings/openssl/__pycache__/binding.cpython-313.pyc,,
cryptography/hazmat/bindings/openssl/_conditional.py,sha256=DMOpA_XN4l70zTc5_J9DpwlbQeUBRTWpfIJ4yRIn1-U,5791
cryptography/hazmat/bindings/openssl/binding.py,sha256=x8eocEmukO4cm7cHqfVmOoYY7CCXdoF1v1WhZQt9neo,4610
cryptography/hazmat/decrepit/__init__.py,sha256=wHCbWfaefa-fk6THSw9th9fJUsStJo7245wfFBqmduA,216
cryptography/hazmat/decrepit/__pycache__/__init__.cpython-313.pyc,,
cryptography/hazmat/decrepit/ciphers/__init__.py,sha256=wHCbWfaefa-fk6THSw9th9fJUsStJo7245wfFBqmduA,216
cryptography/hazmat/decrepit/ciphers/__pycache__/__init__.cpython-313.pyc,,
cryptography/hazmat/decrepit/ciphers/__pycache__/algorithms.cpython-313.pyc,,
cryptography/hazmat/decrepit/ciphers/algorithms.py,sha256=YrKgHS4MfwWaMmPBYRymRRlC0phwWp9ycICFezeJPGk,2595
cryptography/hazmat/primitives/__init__.py,sha256=s9oKCQ2ycFdXoERdS1imafueSkBsL9kvbyfghaauZ9Y,180
cryptography/hazmat/primitives/__pycache__/__init__.cpython-313.pyc,,
cryptography/hazmat/primitives/__pycache__/_asymmetric.cpython-313.pyc,,
cryptography/hazmat/primitives/__pycache__/_cipheralgorithm.cpython-313.pyc,,
cryptography/hazmat/primitives/__pycache__/_serialization.cpython-313.pyc,,
cryptography/hazmat/primitives/__pycache__/cmac.cpython-313.pyc,,
cryptography/hazmat/primitives/__pycache__/constant_time.cpython-313.pyc,,
cryptography/hazmat/primitives/__pycache__/hashes.cpython-313.pyc,,
cryptography/hazmat/primitives/__pycache__/hmac.cpython-313.pyc,,
cryptography/hazmat/primitives/__pycache__/keywrap.cpython-313.pyc,,
cryptography/hazmat/primitives/__pycache__/padding.cpython-313.pyc,,
cryptography/hazmat/primitives/__pycache__/poly1305.cpython-313.pyc,,
cryptography/hazmat/primitives/_asymmetric.py,sha256=RhgcouUB6HTiFDBrR1LxqkMjpUxIiNvQ1r_zJjRG6qQ,532
cryptography/hazmat/primitives/_cipheralgorithm.py,sha256=Eh3i7lwedHfi0eLSsH93PZxQKzY9I6lkK67vL4V5tOc,1522
cryptography/hazmat/primitives/_serialization.py,sha256=chgPCSF2jxI2Cr5gB-qbWXOvOfupBh4CARS0KAhv9AM,5123
cryptography/hazmat/primitives/asymmetric/__init__.py,sha256=s9oKCQ2ycFdXoERdS1imafueSkBsL9kvbyfghaauZ9Y,180
cryptography/hazmat/primitives/asymmetric/__pycache__/__init__.cpython-313.pyc,,
cryptography/hazmat/primitives/asymmetric/__pycache__/dh.cpython-313.pyc,,
cryptography/hazmat/primitives/asymmetric/__pycache__/dsa.cpython-313.pyc,,
cryptography/hazmat/primitives/asymmetric/__pycache__/ec.cpython-313.pyc,,
cryptography/hazmat/primitives/asymmetric/__pycache__/ed25519.cpython-313.pyc,,
cryptography/hazmat/primitives/asymmetric/__pycache__/ed448.cpython-313.pyc,,
cryptography/hazmat/primitives/asymmetric/__pycache__/padding.cpython-313.pyc,,
cryptography/hazmat/primitives/asymmetric/__pycache__/rsa.cpython-313.pyc,,
cryptography/hazmat/primitives/asymmetric/__pycache__/types.cpython-313.pyc,,
cryptography/hazmat/primitives/asymmetric/__pycache__/utils.cpython-313.pyc,,
cryptography/hazmat/primitives/asymmetric/__pycache__/x25519.cpython-313.pyc,,
cryptography/hazmat/primitives/asymmetric/__pycache__/x448.cpython-313.pyc,,
cryptography/hazmat/primitives/asymmetric/dh.py,sha256=0v_vEFFz5pQ1QG-FkWDyvgv7IfuVZSH5Q6LyFI5A8rg,3645
cryptography/hazmat/primitives/asymmetric/dsa.py,sha256=Ld_bbbqQFz12dObHxIkzEQzX0SWWP41RLSWkYSaKhqE,4213
cryptography/hazmat/primitives/asymmetric/ec.py,sha256=dj0ZR_jTVI1wojjipjbXNVccPSIRObWxSZcTGQKGbHc,13437
cryptography/hazmat/primitives/asymmetric/ed25519.py,sha256=jZW5cs472wXXV3eB0sE1b8w64gdazwwU0_MT5UOTiXs,3700
cryptography/hazmat/primitives/asymmetric/ed448.py,sha256=yAetgn2f2JYf0BO8MapGzXeThsvSMG5LmUCrxVOidAA,3729
cryptography/hazmat/primitives/asymmetric/padding.py,sha256=vQ6l6gOg9HqcbOsvHrSiJRVLdEj9L4m4HkRGYziTyFA,2854
cryptography/hazmat/primitives/asymmetric/rsa.py,sha256=ZnKOo2f34MCCOupC03Y1uR-_jiSG5IrelHEmxaME3D4,8303
cryptography/hazmat/primitives/asymmetric/types.py,sha256=LnsOJym-wmPUJ7Knu_7bCNU3kIiELCd6krOaW_JU08I,2996
cryptography/hazmat/primitives/asymmetric/utils.py,sha256=DPTs6T4F-UhwzFQTh-1fSEpQzazH2jf2xpIro3ItF4o,790
cryptography/hazmat/primitives/asymmetric/x25519.py,sha256=_4nQeZ3yJ3Lg0RpXnaqA-1yt6vbx1F-wzLcaZHwSpeE,3613
cryptography/hazmat/primitives/asymmetric/x448.py,sha256=WKBLtuVfJqiBRro654fGaQAlvsKbqbNkK7c4A_ZCdV0,3642
cryptography/hazmat/primitives/ciphers/__init__.py,sha256=eyEXmjk6_CZXaOPYDr7vAYGXr29QvzgWL2-4CSolLFs,680
cryptography/hazmat/primitives/ciphers/__pycache__/__init__.cpython-313.pyc,,
cryptography/hazmat/primitives/ciphers/__pycache__/aead.cpython-313.pyc,,
cryptography/hazmat/primitives/ciphers/__pycache__/algorithms.cpython-313.pyc,,
cryptography/hazmat/primitives/ciphers/__pycache__/base.cpython-313.pyc,,
cryptography/hazmat/primitives/ciphers/__pycache__/modes.cpython-313.pyc,,
cryptography/hazmat/primitives/ciphers/aead.py,sha256=Fzlyx7w8KYQakzDp1zWgJnIr62zgZrgVh1u2h4exB54,634
cryptography/hazmat/primitives/ciphers/algorithms.py,sha256=Q7ZJwcsx83Mgxv5y7r6CyJKSdsOwC-my-5A67-ma2vw,3407
cryptography/hazmat/primitives/ciphers/base.py,sha256=aBC7HHBBoixebmparVr0UlODs3VD0A7B6oz_AaRjDv8,4253
cryptography/hazmat/primitives/ciphers/modes.py,sha256=20stpwhDtbAvpH0SMf9EDHIciwmTF-JMBUOZ9bU8WiQ,8318
cryptography/hazmat/primitives/cmac.py,sha256=sz_s6H_cYnOvx-VNWdIKhRhe3Ymp8z8J0D3CBqOX3gg,338
cryptography/hazmat/primitives/constant_time.py,sha256=xdunWT0nf8OvKdcqUhhlFKayGp4_PgVJRU2W1wLSr_A,422
cryptography/hazmat/primitives/hashes.py,sha256=M8BrlKB3U6DEtHvWTV5VRjpteHv1kS3Zxm_Bsk04cr8,5184
cryptography/hazmat/primitives/hmac.py,sha256=RpB3z9z5skirCQrm7zQbtnp9pLMnAjrlTUvKqF5aDDc,423
cryptography/hazmat/primitives/kdf/__init__.py,sha256=4XibZnrYq4hh5xBjWiIXzaYW6FKx8hPbVaa_cB9zS64,750
cryptography/hazmat/primitives/kdf/__pycache__/__init__.cpython-313.pyc,,
cryptography/hazmat/primitives/kdf/__pycache__/argon2.cpython-313.pyc,,
cryptography/hazmat/primitives/kdf/__pycache__/concatkdf.cpython-313.pyc,,
cryptography/hazmat/primitives/kdf/__pycache__/hkdf.cpython-313.pyc,,
cryptography/hazmat/primitives/kdf/__pycache__/kbkdf.cpython-313.pyc,,
cryptography/hazmat/primitives/kdf/__pycache__/pbkdf2.cpython-313.pyc,,
cryptography/hazmat/primitives/kdf/__pycache__/scrypt.cpython-313.pyc,,
cryptography/hazmat/primitives/kdf/__pycache__/x963kdf.cpython-313.pyc,,
cryptography/hazmat/primitives/kdf/argon2.py,sha256=UFDNXG0v-rw3DqAQTB1UQAsQC2M5Ejg0k_6OCyhLKus,460
cryptography/hazmat/primitives/kdf/concatkdf.py,sha256=Ua8KoLXXnzgsrAUmHpyKymaPt8aPRP0EHEaBz7QCQ9I,3737
cryptography/hazmat/primitives/kdf/hkdf.py,sha256=M0lAEfRoc4kpp4-nwDj9yB-vNZukIOYEQrUlWsBNn9o,543
cryptography/hazmat/primitives/kdf/kbkdf.py,sha256=oZepvo4evhKkkJQWRDwaPoIbyTaFmDc5NPimxg6lfKg,9165
cryptography/hazmat/primitives/kdf/pbkdf2.py,sha256=1WIwhELR0w8ztTpTu8BrFiYWmK3hUfJq08I79TxwieE,1957
cryptography/hazmat/primitives/kdf/scrypt.py,sha256=XyWUdUUmhuI9V6TqAPOvujCSMGv1XQdg0a21IWCmO-U,590
cryptography/hazmat/primitives/kdf/x963kdf.py,sha256=zLTcF665QFvXX2f8TS7fmBZTteXpFjKahzfjjQcCJyw,1999
cryptography/hazmat/primitives/keywrap.py,sha256=XV4Pj2fqSeD-RqZVvY2cA3j5_7RwJSFygYuLfk2ujCo,5650
cryptography/hazmat/primitives/padding.py,sha256=QT-U-NvV2eQGO1wVPbDiNGNSc9keRDS-ig5cQOrLz0E,1865
cryptography/hazmat/primitives/poly1305.py,sha256=P5EPQV-RB_FJPahpg01u0Ts4S_PnAmsroxIGXbGeRRo,355
cryptography/hazmat/primitives/serialization/__init__.py,sha256=Q7uTgDlt7n3WfsMT6jYwutC6DIg_7SEeoAm1GHZ5B5E,1705
cryptography/hazmat/primitives/serialization/__pycache__/__init__.cpython-313.pyc,,
cryptography/hazmat/primitives/serialization/__pycache__/base.cpython-313.pyc,,
cryptography/hazmat/primitives/serialization/__pycache__/pkcs12.cpython-313.pyc,,
cryptography/hazmat/primitives/serialization/__pycache__/pkcs7.cpython-313.pyc,,
cryptography/hazmat/primitives/serialization/__pycache__/ssh.cpython-313.pyc,,
cryptography/hazmat/primitives/serialization/base.py,sha256=ikq5MJIwp_oUnjiaBco_PmQwOTYuGi-XkYUYHKy8Vo0,615
cryptography/hazmat/primitives/serialization/pkcs12.py,sha256=mS9cFNG4afzvseoc5e1MWoY2VskfL8N8Y_OFjl67luY,5104
cryptography/hazmat/primitives/serialization/pkcs7.py,sha256=5OR_Tkysxaprn4FegvJIfbep9rJ9wok6FLWvWwQ5-Mg,13943
cryptography/hazmat/primitives/serialization/ssh.py,sha256=hPV5obFznz0QhFfXFPOeQ8y6MsurA0xVMQiLnLESEs8,53700
cryptography/hazmat/primitives/twofactor/__init__.py,sha256=tmMZGB-g4IU1r7lIFqASU019zr0uPp_wEBYcwdDCKCA,258
cryptography/hazmat/primitives/twofactor/__pycache__/__init__.cpython-313.pyc,,
cryptography/hazmat/primitives/twofactor/__pycache__/hotp.cpython-313.pyc,,
cryptography/hazmat/primitives/twofactor/__pycache__/totp.cpython-313.pyc,,
cryptography/hazmat/primitives/twofactor/hotp.py,sha256=ivZo5BrcCGWLsqql4nZV0XXCjyGPi_iHfDFltGlOJwk,3256
cryptography/hazmat/primitives/twofactor/totp.py,sha256=m5LPpRL00kp4zY8gTjr55Hfz9aMlPS53kHmVkSQCmdY,1652
cryptography/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
cryptography/utils.py,sha256=nFHkPQZycOQGeBtBRkWSA4WjOHFo7pwummQt-PPSkZc,4349
cryptography/x509/__init__.py,sha256=xloN0swseNx-m2WFZmCA17gOoxQWqeU82UVjEdJBePQ,8257
cryptography/x509/__pycache__/__init__.cpython-313.pyc,,
cryptography/x509/__pycache__/base.cpython-313.pyc,,
cryptography/x509/__pycache__/certificate_transparency.cpython-313.pyc,,
cryptography/x509/__pycache__/extensions.cpython-313.pyc,,
cryptography/x509/__pycache__/general_name.cpython-313.pyc,,
cryptography/x509/__pycache__/name.cpython-313.pyc,,
cryptography/x509/__pycache__/ocsp.cpython-313.pyc,,
cryptography/x509/__pycache__/oid.cpython-313.pyc,,
cryptography/x509/__pycache__/verification.cpython-313.pyc,,
cryptography/x509/base.py,sha256=OrmTw3y8B6AE_nGXQPN8x9kq-d7rDWeH13gCq6T6D6U,27997
cryptography/x509/certificate_transparency.py,sha256=JqoOIDhlwInrYMFW6IFn77WJ0viF-PB_rlZV3vs9MYc,797
cryptography/x509/extensions.py,sha256=QxYrqR6SF1qzR9ZraP8wDiIczlEVlAFuwDRVcltB6Tk,77724
cryptography/x509/general_name.py,sha256=sP_rV11Qlpsk4x3XXGJY_Mv0Q_s9dtjeLckHsjpLQoQ,7836
cryptography/x509/name.py,sha256=ty0_xf0LnHwZAdEf-d8FLO1K4hGqx_7DsD3CHwoLJiY,15101
cryptography/x509/ocsp.py,sha256=Yey6NdFV1MPjop24Mj_VenjEpg3kUaMopSWOK0AbeBs,12699
cryptography/x509/oid.py,sha256=BUzgXXGVWilkBkdKPTm9R4qElE9gAGHgdYPMZAp7PJo,931
cryptography/x509/verification.py,sha256=gR2C2c-XZQtblZhT5T5vjSKOtCb74ef2alPVmEcwFlM,958

View File

@@ -0,0 +1,4 @@
Wheel-Version: 1.0
Generator: maturin (1.9.4)
Root-Is-Purelib: false
Tag: cp311-abi3-win_amd64

View File

@@ -0,0 +1,3 @@
This software is made available under the terms of *either* of the licenses
found in LICENSE.APACHE or LICENSE.BSD. Contributions to cryptography are made
under the terms of *both* these licenses.

View File

@@ -0,0 +1,202 @@
Apache License
Version 2.0, January 2004
https://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@@ -0,0 +1,27 @@
Copyright (c) Individual contributors.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of PyCA Cryptography nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@@ -0,0 +1,12 @@
# AUTARCH Adult Site Scanner - Bulk Import File
# Add one domain per line (without http:// or https://)
# Lines starting with # are comments
#
# Example:
# example.com
# another-site.net
# subdomain.site.org
#
# After adding domains, run Bulk Import [B] again
# and provide a test username that exists on these sites.

View File

@@ -0,0 +1,11 @@
{
"active": true,
"tier": 2,
"protections": {
"private_dns": "adguard",
"ad_opt_out": true,
"location_accuracy": true,
"diagnostics": true
},
"activated_at": "2026-02-21T02:55:28.439016"
}

View File

@@ -0,0 +1,19 @@
-----BEGIN CERTIFICATE-----
MIIDKTCCAhGgAwIBAgIUfA3Sef+54+/zn/axqGK99cxqyYkwDQYJKoZIhvcNAQEL
BQAwJDEQMA4GA1UEAwwHQVVUQVJDSDEQMA4GA1UECgwHZGFya0hhbDAeFw0yNjAy
MjExMTAyMTVaFw0zNjAyMTkxMTAyMTVaMCQxEDAOBgNVBAMMB0FVVEFSQ0gxEDAO
BgNVBAoMB2RhcmtIYWwwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC5
2L7xG2kZLj8u1aA0qFd9Xohxa0XG1K0xhTkWJmNOjgRdRO9RejWhKvpa2DJNTO9L
LyEO8bRH56zKcgFofAJRe4GjCSk3OefBcuCKHBWN+hB1YRu+7spaoTxZ1m5dRP1o
DvsRe/nSA69xGsEbX8Zuc/ROCsaV4LACOBYSMQkOKTWWpTu2cLJyuW/sqHn5REzp
Bndw1sp5p+TCc2+Pf+dCEx1V2lXCt2sWC5jTHvPzwGgy9jNXi+CtKMJRlGrHUmBW
a9woL3caOdAp1i9t6VmXeRO3PBYsByeyuGJoREVRThHu+ZhzQkz3oHGFO5YJbu/o
OKWwWJ9mQUl6jF1uwNTtAgMBAAGjUzBRMB0GA1UdDgQWBBS3bxJnHddd56q+WltD
VsbewxdDVDAfBgNVHSMEGDAWgBS3bxJnHddd56q+WltDVsbewxdDVDAPBgNVHRMB
Af8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQCceD5savXA4dhGUss0D8DPIvSg
DS3mjnJtaD7SFqfDmyqM8W9ocQK7yrzdQiywZT+dI8dCnVm1hB5e5l3lTZwTLU41
XLq4WdHBeimwWIuZl+pKKvXcQUHUkK4epJFrt6mj0onExNSDNI4i7Xk+XnMVIu35
VrF6IhLrD2AznQyOqY0WeLGmoXe3FT5caUiTm5Kg28xTJC9m7hDOFE34d0Aqb+U1
U4GFlmXor+MdNKYTEJJy3pslxEZOiRNiiLKWjecYrcKfSk0LY/8TkqVB44pZBQZB
6naQfFuuxDtEa6bHM0q+P/6HM35tpEu6TEJ1eU/yRrejhySFIHfKTjy/WXsm
-----END CERTIFICATE-----

View File

@@ -0,0 +1,20 @@
-----BEGIN CERTIFICATE-----
MIIDWTCCAkGgAwIBAgIUOzmq7jW+wmCJdR9vdQNaC7/DJCwwDQYJKoZIhvcNAQEL
BQAwPDEYMBYGA1UEAwwPbWFpbC5nb29nbGUuY29tMRMwEQYDVQQKDApHb29nbGUg
TExDMQswCQYDVQQGEwJVUzAeFw0yNjAzMDMxMjA2MDFaFw0yNzAzMDMxMjA2MDFa
MDwxGDAWBgNVBAMMD21haWwuZ29vZ2xlLmNvbTETMBEGA1UECgwKR29vZ2xlIExM
QzELMAkGA1UEBhMCVVMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCO
dJygnzih+j44Z7O08n8lWfIpkEBFQtLeoWWbUhi66uIGnISw0x41LxQRSa0pM/cK
1dkQV9olBxOcmFY6XaT8YP7AXt5NkvH0Y/3vE2JHRJpxw0W8ug2tX4pwWCXMkJn2
/Ih2d/VBzDLKp4UK+KTse+2qrFRsvReoOuWzXBqpLC2Ch4pvz1skmjA/hsH7OiWx
ADeBrtphh+1vHhMM27x6D0i3K0tSvhoZBamjXt7qzjPtPGj7dXlHB+S6LkAJC5pF
vL5GYTc5gSceoUzgBFWVVfLP2TYYyDpss/LFnWnvWMqqrvsW8WNaMmHeOI9RA+Q+
rcOjxi7VwDmjm6iwvWFNAgMBAAGjUzBRMB0GA1UdDgQWBBQzYwznwTj7ZM89NikD
ty1B33oAlDAfBgNVHSMEGDAWgBQzYwznwTj7ZM89NikDty1B33oAlDAPBgNVHRMB
Af8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQBhp5GxpRz0lw4uRhJvw3ewhPX6
UHBnWqMb3g4e3zc7RVWqcN4gj9j4ZTFoJxOs2Hw+VfO1i+x3/f4CSxmFrd6FcqNl
B7rRl1+9zup6Me2EQ+XM6mS4Xwf6gmjSvetpcpJAk42c52JdiXq29zZgAPG9n7iz
DrHN70wsB/xGbA2XqcwsOuy3uoBR3TSj9ka3gzrRC1JkP0phcKxlxUYigWaBB/uH
pl5APHqN5fvPyXkiTdX0YQpnRGONm+aMO/LUutIZj4dghQdpJBdDQgv7r3MZl5Z5
Q1UWqnkFwgO4/sjd7yU7u7DODV5/QIzJ9BWRyhIOXiTArU1+M80SP79WJHKa
-----END CERTIFICATE-----

View File

@@ -0,0 +1,8 @@
{
"enabled": false,
"auto_block_top_talkers": true,
"auto_enable_syn_cookies": true,
"connection_threshold": 100,
"syn_threshold": 50,
"updated": "2026-03-02T23:30:44.437461"
}

View File

@@ -0,0 +1,10 @@
{
"listen_dns": "10.0.0.56:53",
"listen_api": "127.0.0.1:5380",
"api_token": "5ed79350fed2490d2aca6f3b29776365",
"upstream": [],
"cache_ttl": 300,
"zones_dir": "C:\\she\\autarch\\data\\dns\\zones",
"dnssec_keys_dir": "C:\\she\\autarch\\data\\dns\\keys",
"log_queries": true
}

View File

@@ -0,0 +1,53 @@
{
"domain": "autarch.local",
"soa": {
"primary_ns": "ns1.autarch.local",
"admin_email": "admin.autarch.local",
"serial": 1772537115,
"refresh": 3600,
"retry": 600,
"expire": 86400,
"min_ttl": 300
},
"records": [
{
"id": "ns1",
"type": "NS",
"name": "autarch.local.",
"value": "ns1.autarch.local.",
"ttl": 3600
},
{
"id": "mx1",
"type": "MX",
"name": "autarch.local.",
"value": "mx.autarch.local.",
"ttl": 3600,
"priority": 10
},
{
"id": "spf1",
"type": "TXT",
"name": "autarch.local.",
"value": "v=spf1 ip4:127.0.0.1 -all",
"ttl": 3600
},
{
"id": "dmarc1",
"type": "TXT",
"name": "_dmarc.autarch.local.",
"value": "v=DMARC1; p=none; rua=mailto:dmarc@autarch.local",
"ttl": 3600
},
{
"id": "r1772537722879235900",
"type": "A",
"name": "https://autarch.local",
"value": "10.0.0.56:8181",
"ttl": 300
}
],
"dnssec": true,
"created_at": "2026-03-03T11:25:07Z",
"updated_at": "2026-03-03T12:24:00Z"
}

View File

@@ -0,0 +1,2 @@
Site,URL,Category,Status,Confidence
GitHub,https://github.com/test,,good,85
1 Site URL Category Status Confidence
2 GitHub https://github.com/test good 85

View File

@@ -0,0 +1,13 @@
{
"query": "testuser",
"exported": "2026-02-14T04:18:34.669640",
"total_results": 1,
"results": [
{
"name": "GitHub",
"url": "https://github.com/test",
"status": "good",
"rate": 85
}
]
}

View File

@@ -0,0 +1,98 @@
You are Hal, the AI agent powering Project AUTARCH — an autonomous security platform built by darkHal Security Group.
## Your Capabilities
You can read files, write files, execute shell commands, search the codebase, and create new AUTARCH modules on demand. When a user asks you to build a tool or module, you build it.
## AUTARCH Codebase Structure
- `modules/` — Plugin modules (Python files). Each one is a standalone tool.
- `core/` — Framework internals (llm.py, agent.py, tools.py, config.py, wireshark.py, etc.)
- `web/` — Flask web dashboard (routes/, templates/, static/)
- `data/` — Databases, configs, JSON files
- `models/` — LLM model files (GGUF)
## Module Categories
| Category | Color | Purpose |
|----------|-------|---------|
| defense | Blue | Security hardening, monitoring, firewalls |
| offense | Red | Penetration testing, exploitation |
| counter | Purple | Counter-intelligence, threat response |
| analyze | Cyan | Analysis, forensics, packet inspection |
| osint | Green | Open source intelligence gathering |
| simulate | Yellow | Attack simulation, red team exercises |
## How to Create a Module
Every module in `modules/` MUST have these attributes and a `run()` function:
```python
"""
Module description docstring
"""
import os
import sys
import subprocess
from pathlib import Path
# Module metadata — REQUIRED
DESCRIPTION = "What this module does"
AUTHOR = "darkHal"
VERSION = "1.0"
CATEGORY = "defense" # One of: defense, offense, counter, analyze, osint, simulate
sys.path.insert(0, str(Path(__file__).parent.parent))
from core.banner import Colors, clear_screen, display_banner
class ModuleClassName:
"""Main class for this module."""
def print_status(self, message, status="info"):
colors = {"info": Colors.CYAN, "success": Colors.GREEN, "warning": Colors.YELLOW, "error": Colors.RED}
symbols = {"info": "*", "success": "+", "warning": "!", "error": "X"}
print(f"{colors.get(status, Colors.WHITE)}[{symbols.get(status, '*')}] {message}{Colors.RESET}")
def run_cmd(self, cmd, timeout=30):
try:
r = subprocess.run(cmd, shell=True, capture_output=True, text=True, timeout=timeout)
return r.returncode == 0, r.stdout.strip()
except Exception as e:
return False, str(e)
# Add your methods here...
def run():
"""Entry point for CLI mode."""
mod = ModuleClassName()
# Interactive menu or direct execution
```
## Important Rules
1. Use the `create_module` tool to write modules — it validates and saves them automatically
2. Always include the metadata: DESCRIPTION, AUTHOR, VERSION, CATEGORY
3. Always include a `run()` function
4. Use `subprocess.run()` for system commands — support both Windows (PowerShell/netsh) and Linux (bash)
5. Import from `core.banner` for Colors
6. Module filenames should be lowercase with underscores (e.g., `port_scanner.py`)
7. Study existing modules with `read_file` if you need to understand patterns
8. The web dashboard discovers modules automatically from the `modules/` directory
## Platform
This system runs on Windows. Use PowerShell commands where appropriate, but also support Linux fallbacks.
## Existing Modules (for reference)
- defender.py — System hardening checks (CATEGORY: defense)
- defender_windows.py — Windows-native security checks (CATEGORY: defense)
- defender_monitor.py — Real-time threat monitoring (CATEGORY: defense)
- recon.py — Network reconnaissance (CATEGORY: offense)
- counter.py — Counter-intelligence tools (CATEGORY: counter)
- adultscan.py — Adult content scanner (CATEGORY: analyze)
- agent_hal.py — AI security automation (CATEGORY: core)
- wireshark.py — Packet analysis (CATEGORY: analyze)
- hardware_local.py — Hardware interaction (CATEGORY: hardware)
## How You Should Respond
- For simple questions: answer directly
- For module creation requests: use the create_module tool
- For system queries: use the shell tool
- For code exploration: use read_file and search_files
- Always explain what you're doing and why

View File

@@ -0,0 +1,129 @@
{
"session_id": "10_0_0_56_20260214_010220",
"target": "10.0.0.56",
"state": "completed",
"created_at": "2026-02-14T01:02:20.746609",
"updated_at": "2026-02-14T01:12:20.951316",
"notes": "",
"step_count": 0,
"tree": {
"target": "10.0.0.56",
"created_at": "2026-02-14T01:02:20.746597",
"updated_at": "2026-02-14T01:02:20.746742",
"root_nodes": [
"e0d00dbc",
"cf120ead",
"6f4a664c",
"814f0376",
"5b602881",
"4d2e70e8"
],
"nodes": {
"e0d00dbc": {
"id": "e0d00dbc",
"label": "Reconnaissance",
"node_type": "reconnaissance",
"status": "todo",
"parent_id": null,
"children": [],
"details": "Information gathering and target enumeration",
"tool_output": null,
"findings": [],
"priority": 1,
"created_at": "2026-02-14T01:02:20.746668",
"updated_at": "2026-02-14T01:02:20.746668"
},
"cf120ead": {
"id": "cf120ead",
"label": "Initial Access",
"node_type": "initial_access",
"status": "todo",
"parent_id": null,
"children": [],
"details": "Gaining initial foothold on target",
"tool_output": null,
"findings": [],
"priority": 2,
"created_at": "2026-02-14T01:02:20.746685",
"updated_at": "2026-02-14T01:02:20.746685"
},
"6f4a664c": {
"id": "6f4a664c",
"label": "Privilege Escalation",
"node_type": "privilege_escalation",
"status": "todo",
"parent_id": null,
"children": [],
"details": "Escalating from initial access to higher privileges",
"tool_output": null,
"findings": [],
"priority": 3,
"created_at": "2026-02-14T01:02:20.746699",
"updated_at": "2026-02-14T01:02:20.746699"
},
"814f0376": {
"id": "814f0376",
"label": "Lateral Movement",
"node_type": "lateral_movement",
"status": "todo",
"parent_id": null,
"children": [],
"details": "Moving to other systems in the network",
"tool_output": null,
"findings": [],
"priority": 4,
"created_at": "2026-02-14T01:02:20.746711",
"updated_at": "2026-02-14T01:02:20.746711"
},
"5b602881": {
"id": "5b602881",
"label": "Credential Access",
"node_type": "credential_access",
"status": "todo",
"parent_id": null,
"children": [],
"details": "Obtaining credentials and secrets",
"tool_output": null,
"findings": [],
"priority": 3,
"created_at": "2026-02-14T01:02:20.746726",
"updated_at": "2026-02-14T01:02:20.746726"
},
"4d2e70e8": {
"id": "4d2e70e8",
"label": "Persistence",
"node_type": "persistence",
"status": "todo",
"parent_id": null,
"children": [],
"details": "Maintaining access to compromised systems",
"tool_output": null,
"findings": [],
"priority": 5,
"created_at": "2026-02-14T01:02:20.746739",
"updated_at": "2026-02-14T01:02:20.746739"
}
}
},
"events": [
{
"timestamp": "2026-02-14T01:02:20.746747",
"event_type": "state_change",
"data": {
"from": "idle",
"to": "running"
}
},
{
"timestamp": "2026-02-14T01:12:20.951316",
"event_type": "state_change",
"data": {
"from": "running",
"to": "completed",
"summary": ""
}
}
],
"findings": [],
"pipeline_history": []
}

View File

@@ -0,0 +1,120 @@
{
"session_id": "192_168_1_100_20260127_202421",
"target": "192.168.1.100",
"state": "running",
"created_at": "2026-01-27T20:24:21.604010",
"updated_at": "2026-01-27T20:24:21.604098",
"notes": "",
"step_count": 0,
"tree": {
"target": "192.168.1.100",
"created_at": "2026-01-27T20:24:21.604003",
"updated_at": "2026-01-27T20:24:21.604091",
"root_nodes": [
"4be13ed9",
"8dc38740",
"22ee2768",
"2c45477f",
"6f793ae8",
"778fc896"
],
"nodes": {
"4be13ed9": {
"id": "4be13ed9",
"label": "Reconnaissance",
"node_type": "reconnaissance",
"status": "todo",
"parent_id": null,
"children": [],
"details": "Information gathering and target enumeration",
"tool_output": null,
"findings": [],
"priority": 1,
"created_at": "2026-01-27T20:24:21.604032",
"updated_at": "2026-01-27T20:24:21.604032"
},
"8dc38740": {
"id": "8dc38740",
"label": "Initial Access",
"node_type": "initial_access",
"status": "todo",
"parent_id": null,
"children": [],
"details": "Gaining initial foothold on target",
"tool_output": null,
"findings": [],
"priority": 2,
"created_at": "2026-01-27T20:24:21.604044",
"updated_at": "2026-01-27T20:24:21.604044"
},
"22ee2768": {
"id": "22ee2768",
"label": "Privilege Escalation",
"node_type": "privilege_escalation",
"status": "todo",
"parent_id": null,
"children": [],
"details": "Escalating from initial access to higher privileges",
"tool_output": null,
"findings": [],
"priority": 3,
"created_at": "2026-01-27T20:24:21.604056",
"updated_at": "2026-01-27T20:24:21.604056"
},
"2c45477f": {
"id": "2c45477f",
"label": "Lateral Movement",
"node_type": "lateral_movement",
"status": "todo",
"parent_id": null,
"children": [],
"details": "Moving to other systems in the network",
"tool_output": null,
"findings": [],
"priority": 4,
"created_at": "2026-01-27T20:24:21.604066",
"updated_at": "2026-01-27T20:24:21.604066"
},
"6f793ae8": {
"id": "6f793ae8",
"label": "Credential Access",
"node_type": "credential_access",
"status": "todo",
"parent_id": null,
"children": [],
"details": "Obtaining credentials and secrets",
"tool_output": null,
"findings": [],
"priority": 3,
"created_at": "2026-01-27T20:24:21.604077",
"updated_at": "2026-01-27T20:24:21.604077"
},
"778fc896": {
"id": "778fc896",
"label": "Persistence",
"node_type": "persistence",
"status": "todo",
"parent_id": null,
"children": [],
"details": "Maintaining access to compromised systems",
"tool_output": null,
"findings": [],
"priority": 5,
"created_at": "2026-01-27T20:24:21.604088",
"updated_at": "2026-01-27T20:24:21.604088"
}
}
},
"events": [
{
"timestamp": "2026-01-27T20:24:21.604098",
"event_type": "state_change",
"data": {
"from": "idle",
"to": "running"
}
}
],
"findings": [],
"pipeline_history": []
}

View File

@@ -0,0 +1,120 @@
{
"session_id": "192_168_50_78_20260130_133833",
"target": "192.168.50.78",
"state": "running",
"created_at": "2026-01-30T13:38:33.830336",
"updated_at": "2026-01-30T13:38:33.830464",
"notes": "",
"step_count": 0,
"tree": {
"target": "192.168.50.78",
"created_at": "2026-01-30T13:38:33.830323",
"updated_at": "2026-01-30T13:38:33.830460",
"root_nodes": [
"e4c40c28",
"ddd63828",
"b3f2634d",
"9c162c78",
"aa40d5a3",
"0c50a23d"
],
"nodes": {
"e4c40c28": {
"id": "e4c40c28",
"label": "Reconnaissance",
"node_type": "reconnaissance",
"status": "todo",
"parent_id": null,
"children": [],
"details": "Information gathering and target enumeration",
"tool_output": null,
"findings": [],
"priority": 1,
"created_at": "2026-01-30T13:38:33.830390",
"updated_at": "2026-01-30T13:38:33.830390"
},
"ddd63828": {
"id": "ddd63828",
"label": "Initial Access",
"node_type": "initial_access",
"status": "todo",
"parent_id": null,
"children": [],
"details": "Gaining initial foothold on target",
"tool_output": null,
"findings": [],
"priority": 2,
"created_at": "2026-01-30T13:38:33.830408",
"updated_at": "2026-01-30T13:38:33.830408"
},
"b3f2634d": {
"id": "b3f2634d",
"label": "Privilege Escalation",
"node_type": "privilege_escalation",
"status": "todo",
"parent_id": null,
"children": [],
"details": "Escalating from initial access to higher privileges",
"tool_output": null,
"findings": [],
"priority": 3,
"created_at": "2026-01-30T13:38:33.830421",
"updated_at": "2026-01-30T13:38:33.830421"
},
"9c162c78": {
"id": "9c162c78",
"label": "Lateral Movement",
"node_type": "lateral_movement",
"status": "todo",
"parent_id": null,
"children": [],
"details": "Moving to other systems in the network",
"tool_output": null,
"findings": [],
"priority": 4,
"created_at": "2026-01-30T13:38:33.830433",
"updated_at": "2026-01-30T13:38:33.830433"
},
"aa40d5a3": {
"id": "aa40d5a3",
"label": "Credential Access",
"node_type": "credential_access",
"status": "todo",
"parent_id": null,
"children": [],
"details": "Obtaining credentials and secrets",
"tool_output": null,
"findings": [],
"priority": 3,
"created_at": "2026-01-30T13:38:33.830445",
"updated_at": "2026-01-30T13:38:33.830445"
},
"0c50a23d": {
"id": "0c50a23d",
"label": "Persistence",
"node_type": "persistence",
"status": "todo",
"parent_id": null,
"children": [],
"details": "Maintaining access to compromised systems",
"tool_output": null,
"findings": [],
"priority": 5,
"created_at": "2026-01-30T13:38:33.830457",
"updated_at": "2026-01-30T13:38:33.830457"
}
}
},
"events": [
{
"timestamp": "2026-01-30T13:38:33.830464",
"event_type": "state_change",
"data": {
"from": "idle",
"to": "running"
}
}
],
"findings": [],
"pipeline_history": []
}

View File

@@ -0,0 +1,120 @@
{
"session_id": "example_com_20260128_192244",
"target": "example.com",
"state": "running",
"created_at": "2026-01-28T19:22:44.670292",
"updated_at": "2026-01-28T19:22:44.670428",
"notes": "test",
"step_count": 0,
"tree": {
"target": "example.com",
"created_at": "2026-01-28T19:22:44.670279",
"updated_at": "2026-01-28T19:22:44.670423",
"root_nodes": [
"466dcf04",
"55991daa",
"e3209082",
"af036f87",
"633c0eeb",
"8584f7fc"
],
"nodes": {
"466dcf04": {
"id": "466dcf04",
"label": "Reconnaissance",
"node_type": "reconnaissance",
"status": "todo",
"parent_id": null,
"children": [],
"details": "Information gathering and target enumeration",
"tool_output": null,
"findings": [],
"priority": 1,
"created_at": "2026-01-28T19:22:44.670353",
"updated_at": "2026-01-28T19:22:44.670353"
},
"55991daa": {
"id": "55991daa",
"label": "Initial Access",
"node_type": "initial_access",
"status": "todo",
"parent_id": null,
"children": [],
"details": "Gaining initial foothold on target",
"tool_output": null,
"findings": [],
"priority": 2,
"created_at": "2026-01-28T19:22:44.670371",
"updated_at": "2026-01-28T19:22:44.670371"
},
"e3209082": {
"id": "e3209082",
"label": "Privilege Escalation",
"node_type": "privilege_escalation",
"status": "todo",
"parent_id": null,
"children": [],
"details": "Escalating from initial access to higher privileges",
"tool_output": null,
"findings": [],
"priority": 3,
"created_at": "2026-01-28T19:22:44.670384",
"updated_at": "2026-01-28T19:22:44.670384"
},
"af036f87": {
"id": "af036f87",
"label": "Lateral Movement",
"node_type": "lateral_movement",
"status": "todo",
"parent_id": null,
"children": [],
"details": "Moving to other systems in the network",
"tool_output": null,
"findings": [],
"priority": 4,
"created_at": "2026-01-28T19:22:44.670397",
"updated_at": "2026-01-28T19:22:44.670397"
},
"633c0eeb": {
"id": "633c0eeb",
"label": "Credential Access",
"node_type": "credential_access",
"status": "todo",
"parent_id": null,
"children": [],
"details": "Obtaining credentials and secrets",
"tool_output": null,
"findings": [],
"priority": 3,
"created_at": "2026-01-28T19:22:44.670408",
"updated_at": "2026-01-28T19:22:44.670408"
},
"8584f7fc": {
"id": "8584f7fc",
"label": "Persistence",
"node_type": "persistence",
"status": "todo",
"parent_id": null,
"children": [],
"details": "Maintaining access to compromised systems",
"tool_output": null,
"findings": [],
"priority": 5,
"created_at": "2026-01-28T19:22:44.670420",
"updated_at": "2026-01-28T19:22:44.670420"
}
}
},
"events": [
{
"timestamp": "2026-01-28T19:22:44.670428",
"event_type": "state_change",
"data": {
"from": "idle",
"to": "running"
}
}
],
"findings": [],
"pipeline_history": []
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,97 @@
#!/usr/bin/env python3
"""AUTARCH LoRA Training Script (Transformers + PEFT)"""
import json
import torch
from datasets import Dataset
from transformers import (
AutoModelForCausalLM, AutoTokenizer, TrainingArguments,
BitsAndBytesConfig,
)
from peft import LoraConfig, get_peft_model, prepare_model_for_kbit_training
from trl import SFTTrainer
# Quantization config
bnb_config = BitsAndBytesConfig(
load_in_4bit=True,
bnb_4bit_quant_type="nf4",
bnb_4bit_compute_dtype=torch.float16,
bnb_4bit_use_double_quant=True,
) if True else None
print("Loading base model: models/Hal_v2.gguf")
model = AutoModelForCausalLM.from_pretrained(
"models/Hal_v2.gguf",
quantization_config=bnb_config,
device_map="auto",
trust_remote_code=False,
)
tokenizer = AutoTokenizer.from_pretrained("models/Hal_v2.gguf", trust_remote_code=False)
if tokenizer.pad_token is None:
tokenizer.pad_token = tokenizer.eos_token
if True:
model = prepare_model_for_kbit_training(model)
# LoRA config
lora_config = LoraConfig(
r=16,
lora_alpha=32,
lora_dropout=0.05,
target_modules=["q_proj", "k_proj", "v_proj", "o_proj",
"gate_proj", "up_proj", "down_proj"],
bias="none",
task_type="CAUSAL_LM",
)
model = get_peft_model(model, lora_config)
model.print_trainable_parameters()
# Load dataset
samples = []
with open("C:\she\autarch\data\training\autarch_dataset_20260302_202634.jsonl", "r") as f:
for line in f:
samples.append(json.loads(line))
def format_sample(sample):
if "conversations" in sample:
msgs = sample["conversations"]
text = ""
for msg in msgs:
role = "user" if msg["from"] == "human" else "assistant"
text += f"<|im_start|>{role}\n{msg['value']}<|im_end|>\n"
return {"text": text}
else:
return {"text": f"<|im_start|>user\n{sample['instruction']}\n{sample.get('input','')}<|im_end|>\n<|im_start|>assistant\n{sample['output']}<|im_end|>\n"}
dataset = Dataset.from_list([format_sample(s) for s in samples])
print(f"Dataset: {len(dataset)} samples")
# Train
trainer = SFTTrainer(
model=model,
tokenizer=tokenizer,
train_dataset=dataset,
dataset_text_field="text",
max_seq_length=2048,
args=TrainingArguments(
output_dir="C:\she\autarch\data\training\output",
num_train_epochs=3,
per_device_train_batch_size=4,
gradient_accumulation_steps=4,
learning_rate=0.0002,
warmup_ratio=0.03,
save_steps=50,
logging_steps=10,
fp16=True,
optim="adamw_8bit",
report_to="none",
),
)
print("Starting training...")
trainer.train()
print("Training complete!")
# Save
model.save_pretrained("C:\she\autarch\data\training\output/lora_adapter")
tokenizer.save_pretrained("C:\she\autarch\data\training\output/lora_adapter")
print(f"LoRA adapter saved to C:\she\autarch\data\training\output/lora_adapter")

View File

@@ -0,0 +1,14 @@
C:\she\autarch\data\training\train_lora.py:50: SyntaxWarning: invalid escape sequence '\s'
with open("C:\she\autarch\data\training\autarch_dataset_20260302_202634.jsonl", "r") as f:
C:\she\autarch\data\training\train_lora.py:76: SyntaxWarning: invalid escape sequence '\s'
output_dir="C:\she\autarch\data\training\output",
C:\she\autarch\data\training\train_lora.py:95: SyntaxWarning: invalid escape sequence '\s'
model.save_pretrained("C:\she\autarch\data\training\output/lora_adapter")
C:\she\autarch\data\training\train_lora.py:96: SyntaxWarning: invalid escape sequence '\s'
tokenizer.save_pretrained("C:\she\autarch\data\training\output/lora_adapter")
C:\she\autarch\data\training\train_lora.py:97: SyntaxWarning: invalid escape sequence '\s'
print(f"LoRA adapter saved to C:\she\autarch\data\training\output/lora_adapter")
Traceback (most recent call last):
File "C:\she\autarch\data\training\train_lora.py", line 5, in <module>
from datasets import Dataset
ModuleNotFoundError: No module named 'datasets'

View File

@@ -0,0 +1,5 @@
{
"username": "admin",
"password": "admin",
"force_change": true
}

View File

@@ -0,0 +1,91 @@
Metadata-Version: 2.4
Name: Flask
Version: 3.1.3
Summary: A simple framework for building complex web applications.
Maintainer-email: Pallets <contact@palletsprojects.com>
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-Expression: BSD-3-Clause
Classifier: Development Status :: 5 - Production/Stable
Classifier: Environment :: Web Environment
Classifier: Framework :: Flask
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python
Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
Classifier: Topic :: Internet :: WWW/HTTP :: WSGI
Classifier: Topic :: Internet :: WWW/HTTP :: WSGI :: Application
Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
Classifier: Typing :: Typed
License-File: LICENSE.txt
Requires-Dist: blinker>=1.9.0
Requires-Dist: click>=8.1.3
Requires-Dist: importlib-metadata>=3.6.0; python_version < '3.10'
Requires-Dist: itsdangerous>=2.2.0
Requires-Dist: jinja2>=3.1.2
Requires-Dist: markupsafe>=2.1.1
Requires-Dist: werkzeug>=3.1.0
Requires-Dist: asgiref>=3.2 ; extra == "async"
Requires-Dist: python-dotenv ; extra == "dotenv"
Project-URL: Changes, https://flask.palletsprojects.com/page/changes/
Project-URL: Chat, https://discord.gg/pallets
Project-URL: Documentation, https://flask.palletsprojects.com/
Project-URL: Donate, https://palletsprojects.com/donate
Project-URL: Source, https://github.com/pallets/flask/
Provides-Extra: async
Provides-Extra: dotenv
<div align="center"><img src="https://raw.githubusercontent.com/pallets/flask/refs/heads/stable/docs/_static/flask-name.svg" alt="" height="150"></div>
# Flask
Flask is a lightweight [WSGI] web application framework. It is designed
to make getting started quick and easy, with the ability to scale up to
complex applications. It began as a simple wrapper around [Werkzeug]
and [Jinja], and has become one of the most popular Python web
application frameworks.
Flask offers suggestions, but doesn't enforce any dependencies or
project layout. It is up to the developer to choose the tools and
libraries they want to use. There are many extensions provided by the
community that make adding new functionality easy.
[WSGI]: https://wsgi.readthedocs.io/
[Werkzeug]: https://werkzeug.palletsprojects.com/
[Jinja]: https://jinja.palletsprojects.com/
## A Simple Example
```python
# save this as app.py
from flask import Flask
app = Flask(__name__)
@app.route("/")
def hello():
return "Hello, World!"
```
```
$ flask run
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
```
## Donate
The Pallets organization develops and supports Flask and the libraries
it uses. In order to grow the community of contributors and users, and
allow the maintainers to devote more time to the projects, [please
donate today].
[please donate today]: https://palletsprojects.com/donate
## Contributing
See our [detailed contributing documentation][contrib] for many ways to
contribute, including reporting issues, requesting features, asking or answering
questions, and making PRs.
[contrib]: https://palletsprojects.com/contributing/

View File

@@ -0,0 +1,58 @@
../../Scripts/flask.exe,sha256=_mabYvHWmDHkSxw_t4DPmbl08U6onGV1eQJ0z8Tx9HY,108357
flask-3.1.3.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
flask-3.1.3.dist-info/METADATA,sha256=qmdg7W9UVwRHTXBzPkpjp_FIHjdpc-3IlqE9AqciTHw,3167
flask-3.1.3.dist-info/RECORD,,
flask-3.1.3.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
flask-3.1.3.dist-info/WHEEL,sha256=G2gURzTEtmeR8nrdXUJfNiB3VYVxigPQ-bEQujpNiNs,82
flask-3.1.3.dist-info/entry_points.txt,sha256=bBP7hTOS5fz9zLtC7sPofBZAlMkEvBxu7KqS6l5lvc4,40
flask-3.1.3.dist-info/licenses/LICENSE.txt,sha256=SJqOEQhQntmKN7uYPhHg9-HTHwvY-Zp5yESOf_N9B-o,1475
flask/__init__.py,sha256=mHvJN9Swtl1RDtjCqCIYyIniK_SZ_l_hqUynOzgpJ9o,2701
flask/__main__.py,sha256=bYt9eEaoRQWdejEHFD8REx9jxVEdZptECFsV7F49Ink,30
flask/__pycache__/__init__.cpython-313.pyc,,
flask/__pycache__/__main__.cpython-313.pyc,,
flask/__pycache__/app.cpython-313.pyc,,
flask/__pycache__/blueprints.cpython-313.pyc,,
flask/__pycache__/cli.cpython-313.pyc,,
flask/__pycache__/config.cpython-313.pyc,,
flask/__pycache__/ctx.cpython-313.pyc,,
flask/__pycache__/debughelpers.cpython-313.pyc,,
flask/__pycache__/globals.cpython-313.pyc,,
flask/__pycache__/helpers.cpython-313.pyc,,
flask/__pycache__/logging.cpython-313.pyc,,
flask/__pycache__/sessions.cpython-313.pyc,,
flask/__pycache__/signals.cpython-313.pyc,,
flask/__pycache__/templating.cpython-313.pyc,,
flask/__pycache__/testing.cpython-313.pyc,,
flask/__pycache__/typing.cpython-313.pyc,,
flask/__pycache__/views.cpython-313.pyc,,
flask/__pycache__/wrappers.cpython-313.pyc,,
flask/app.py,sha256=k7tW8LHRSldUi6zKsFKK7Axa_WL4zu1e2wPNthIsu7o,61719
flask/blueprints.py,sha256=p5QE2lY18GItbdr_RKRpZ8Do17g0PvQGIgZkSUDhX2k,4541
flask/cli.py,sha256=Pfh72-BxlvoH0QHCDOc1HvXG7Kq5Xetf3zzNz2kNSHk,37184
flask/config.py,sha256=PiqF0DPam6HW0FH4CH1hpXTBe30NSzjPEOwrz1b6kt0,13219
flask/ctx.py,sha256=oMe0TRsScW0qdaIqavVsk8P9qiEvAY5VHn1FAgkX8nk,15521
flask/debughelpers.py,sha256=PGIDhStW_efRjpaa3zHIpo-htStJOR41Ip3OJWPYBwo,6080
flask/globals.py,sha256=XdQZmStBmPIs8t93tjx6pO7Bm3gobAaONWkFcUHaGas,1713
flask/helpers.py,sha256=rJZge7_J288J1UQv5-kNf4oEaw332PP8NTW0QRIBbXE,23517
flask/json/__init__.py,sha256=hLNR898paqoefdeAhraa5wyJy-bmRB2k2dV4EgVy2Z8,5602
flask/json/__pycache__/__init__.cpython-313.pyc,,
flask/json/__pycache__/provider.cpython-313.pyc,,
flask/json/__pycache__/tag.cpython-313.pyc,,
flask/json/provider.py,sha256=5imEzY5HjV2HoUVrQbJLqXCzMNpZXfD0Y1XqdLV2XBA,7672
flask/json/tag.py,sha256=DhaNwuIOhdt2R74oOC9Y4Z8ZprxFYiRb5dUP5byyINw,9281
flask/logging.py,sha256=8sM3WMTubi1cBb2c_lPkWpN0J8dMAqrgKRYLLi1dCVI,2377
flask/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
flask/sansio/README.md,sha256=-0X1tECnilmz1cogx-YhNw5d7guK7GKrq_DEV2OzlU0,228
flask/sansio/__pycache__/app.cpython-313.pyc,,
flask/sansio/__pycache__/blueprints.cpython-313.pyc,,
flask/sansio/__pycache__/scaffold.cpython-313.pyc,,
flask/sansio/app.py,sha256=whGURQDkN0jmhS4CHO7DQ96GGlZS0kETkKkAkoRjl4U,38106
flask/sansio/blueprints.py,sha256=Tqe-7EkZ-tbWchm8iDoCfD848f0_3nLv6NNjeIPvHwM,24637
flask/sansio/scaffold.py,sha256=wSASXYdFRWJmqcL0Xq-T7N-PDVUSiFGvjO9kPZg58bk,30371
flask/sessions.py,sha256=eywRqmytTmYnX_EC78-YBGJoTc5XD_lRphQG5LbN1d0,14969
flask/signals.py,sha256=V7lMUww7CqgJ2ThUBn1PiatZtQanOyt7OZpu2GZI-34,750
flask/templating.py,sha256=vbIkwYAxsSEfDxQID1gKRvBQQcGWEuWYCnH0XK3EqOI,7678
flask/testing.py,sha256=zzC7XxhBWOP9H697IV_4SG7Lg3Lzb5PWiyEP93_KQXE,10117
flask/typing.py,sha256=L-L5t2jKgS0aOmVhioQ_ylqcgiVFnA6yxO-RLNhq-GU,3293
flask/views.py,sha256=xzJx6oJqGElThtEghZN7ZQGMw5TDFyuRxUkecwRuAoA,6962
flask/wrappers.py,sha256=jUkv4mVek2Iq4hwxd4RvqrIMb69Bv0PElDgWLmd5ORo,9406

View File

@@ -0,0 +1,4 @@
Wheel-Version: 1.0
Generator: flit 3.12.0
Root-Is-Purelib: true
Tag: py3-none-any

View File

@@ -0,0 +1,3 @@
[console_scripts]
flask=flask.cli:main

View File

@@ -0,0 +1,28 @@
Copyright 2010 Pallets
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@@ -0,0 +1,133 @@
Metadata-Version: 2.4
Name: importlib_metadata
Version: 8.7.1
Summary: Read metadata from Python packages
Author-email: "Jason R. Coombs" <jaraco@jaraco.com>
License-Expression: Apache-2.0
Project-URL: Source, https://github.com/python/importlib_metadata
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Requires-Python: >=3.9
Description-Content-Type: text/x-rst
License-File: LICENSE
Requires-Dist: zipp>=3.20
Provides-Extra: test
Requires-Dist: pytest!=8.1.*,>=6; extra == "test"
Requires-Dist: packaging; extra == "test"
Requires-Dist: pyfakefs; extra == "test"
Requires-Dist: flufl.flake8; extra == "test"
Requires-Dist: pytest-perf>=0.9.2; extra == "test"
Requires-Dist: jaraco.test>=5.4; extra == "test"
Provides-Extra: doc
Requires-Dist: sphinx>=3.5; extra == "doc"
Requires-Dist: jaraco.packaging>=9.3; extra == "doc"
Requires-Dist: rst.linker>=1.9; extra == "doc"
Requires-Dist: furo; extra == "doc"
Requires-Dist: sphinx-lint; extra == "doc"
Requires-Dist: jaraco.tidelift>=1.4; extra == "doc"
Provides-Extra: perf
Requires-Dist: ipython; extra == "perf"
Provides-Extra: check
Requires-Dist: pytest-checkdocs>=2.4; extra == "check"
Requires-Dist: pytest-ruff>=0.2.1; sys_platform != "cygwin" and extra == "check"
Provides-Extra: cover
Requires-Dist: pytest-cov; extra == "cover"
Provides-Extra: enabler
Requires-Dist: pytest-enabler>=3.4; extra == "enabler"
Provides-Extra: type
Requires-Dist: pytest-mypy>=1.0.1; extra == "type"
Requires-Dist: mypy<1.19; platform_python_implementation == "PyPy" and extra == "type"
Dynamic: license-file
.. image:: https://img.shields.io/pypi/v/importlib_metadata.svg
:target: https://pypi.org/project/importlib_metadata
.. image:: https://img.shields.io/pypi/pyversions/importlib_metadata.svg
.. image:: https://github.com/python/importlib_metadata/actions/workflows/main.yml/badge.svg
:target: https://github.com/python/importlib_metadata/actions?query=workflow%3A%22tests%22
:alt: tests
.. image:: https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json
:target: https://github.com/astral-sh/ruff
:alt: Ruff
.. image:: https://readthedocs.org/projects/importlib-metadata/badge/?version=latest
:target: https://importlib-metadata.readthedocs.io/en/latest/?badge=latest
.. image:: https://img.shields.io/badge/skeleton-2025-informational
:target: https://blog.jaraco.com/skeleton
.. image:: https://tidelift.com/badges/package/pypi/importlib-metadata
:target: https://tidelift.com/subscription/pkg/pypi-importlib-metadata?utm_source=pypi-importlib-metadata&utm_medium=readme
Library to access the metadata for a Python package.
This package supplies third-party access to the functionality of
`importlib.metadata <https://docs.python.org/3/library/importlib.metadata.html>`_
including improvements added to subsequent Python versions.
Compatibility
=============
New features are introduced in this third-party library and later merged
into CPython. The following table indicates which versions of this library
were contributed to different versions in the standard library:
.. list-table::
:header-rows: 1
* - importlib_metadata
- stdlib
* - 7.0
- 3.13
* - 6.5
- 3.12
* - 4.13
- 3.11
* - 4.6
- 3.10
* - 1.4
- 3.8
Usage
=====
See the `online documentation <https://importlib-metadata.readthedocs.io/>`_
for usage details.
`Finder authors
<https://docs.python.org/3/reference/import.html#finders-and-loaders>`_ can
also add support for custom package installers. See the above documentation
for details.
Caveats
=======
This project primarily supports third-party packages installed by PyPA
tools (or other conforming packages). It does not support:
- Packages in the stdlib.
- Packages installed without metadata.
Project details
===============
* Project home: https://github.com/python/importlib_metadata
* Report bugs at: https://github.com/python/importlib_metadata/issues
* Code hosting: https://github.com/python/importlib_metadata
* Documentation: https://importlib-metadata.readthedocs.io/
For Enterprise
==============
Available as part of the Tidelift Subscription.
This project and the maintainers of thousands of other packages are working with Tidelift to deliver one enterprise subscription that covers all of the open source you use.
`Learn more <https://tidelift.com/subscription/pkg/pypi-importlib-metadata?utm_source=pypi-importlib-metadata&utm_medium=referral&utm_campaign=github>`_.

View File

@@ -0,0 +1,33 @@
importlib_metadata-8.7.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
importlib_metadata-8.7.1.dist-info/METADATA,sha256=o-OLnuQyYonUhkcE8w4pnudp4jCc6fSnXw3hpQrQo1Y,4670
importlib_metadata-8.7.1.dist-info/RECORD,,
importlib_metadata-8.7.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
importlib_metadata-8.7.1.dist-info/licenses/LICENSE,sha256=RYUC4S2Xu_ZEOGBqIARKqF6wX7CoqAe7NdvsJT_R_AQ,10278
importlib_metadata-8.7.1.dist-info/top_level.txt,sha256=CO3fD9yylANiXkrMo4qHLV_mqXL2sC5JFKgt1yWAT-A,19
importlib_metadata/__init__.py,sha256=u7Ew4-UkpzNY-ka6k-WRkDhQZS1akkLMfWs2eEnUmGo,37734
importlib_metadata/__pycache__/__init__.cpython-313.pyc,,
importlib_metadata/__pycache__/_adapters.cpython-313.pyc,,
importlib_metadata/__pycache__/_collections.cpython-313.pyc,,
importlib_metadata/__pycache__/_compat.cpython-313.pyc,,
importlib_metadata/__pycache__/_functools.cpython-313.pyc,,
importlib_metadata/__pycache__/_itertools.cpython-313.pyc,,
importlib_metadata/__pycache__/_meta.cpython-313.pyc,,
importlib_metadata/__pycache__/_text.cpython-313.pyc,,
importlib_metadata/__pycache__/_typing.cpython-313.pyc,,
importlib_metadata/__pycache__/diagnose.cpython-313.pyc,,
importlib_metadata/_adapters.py,sha256=r5i8XLrKT6xmrpoREZhZrfczOYDmrVZeJBW5u0HzIGU,3797
importlib_metadata/_collections.py,sha256=CxAhzlF3g1rwu_fMiB53JtRQiUFh0RgiMpoOvmK_ocg,760
importlib_metadata/_compat.py,sha256=VC5ZDLlT-BcshauCShdFJvMNLntJJfZzNK1meGa-enw,1313
importlib_metadata/_functools.py,sha256=0pA2OoiVK6wnsGq8HvVIzgdkvLiZ0nfnfw7IsndjoHk,3510
importlib_metadata/_itertools.py,sha256=nMvp9SfHAQ_JYwK4L2i64lr3GRXGlYlikGTVzWbys_E,5351
importlib_metadata/_meta.py,sha256=EtHyiJ5kGzWFDfKyQ2XQp6Vu113CeadKW1Vf6aGc1B4,1765
importlib_metadata/_text.py,sha256=HCsFksZpJLeTP3NEk_ngrAeXVRRtTrtyh9eOABoRP4A,2166
importlib_metadata/_typing.py,sha256=EQKhhsEgz_Sa-FnePI-faC72rNOOQwopjA1i5pG8FDU,367
importlib_metadata/compat/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
importlib_metadata/compat/__pycache__/__init__.cpython-313.pyc,,
importlib_metadata/compat/__pycache__/py311.cpython-313.pyc,,
importlib_metadata/compat/__pycache__/py39.cpython-313.pyc,,
importlib_metadata/compat/py311.py,sha256=uqm-K-uohyj1042TH4a9Er_I5o7667DvulcD-gC_fSA,608
importlib_metadata/compat/py39.py,sha256=J3W7PUVRPNYMmcvT12RF8ndBU9e8_T0Ac4U87Bsrq70,1187
importlib_metadata/diagnose.py,sha256=nkSRMiowlmkhLYhKhvCg9glmt_11Cox-EmLzEbqYTa8,379
importlib_metadata/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0

View File

@@ -0,0 +1,5 @@
Wheel-Version: 1.0
Generator: setuptools (80.9.0)
Root-Is-Purelib: true
Tag: py3-none-any

View File

@@ -0,0 +1,73 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files.
"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions:
(a) You must give any other recipients of the Work or Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License.
You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives.
Copyright 2025 [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@@ -0,0 +1,28 @@
Copyright 2011 Pallets
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@@ -0,0 +1,60 @@
Metadata-Version: 2.1
Name: itsdangerous
Version: 2.2.0
Summary: Safely pass data to untrusted environments and back.
Maintainer-email: Pallets <contact@palletsprojects.com>
Requires-Python: >=3.8
Description-Content-Type: text/markdown
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: BSD License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python
Classifier: Typing :: Typed
Project-URL: Changes, https://itsdangerous.palletsprojects.com/changes/
Project-URL: Chat, https://discord.gg/pallets
Project-URL: Documentation, https://itsdangerous.palletsprojects.com/
Project-URL: Donate, https://palletsprojects.com/donate
Project-URL: Source, https://github.com/pallets/itsdangerous/
# ItsDangerous
... so better sign this
Various helpers to pass data to untrusted environments and to get it
back safe and sound. Data is cryptographically signed to ensure that a
token has not been tampered with.
It's possible to customize how data is serialized. Data is compressed as
needed. A timestamp can be added and verified automatically while
loading a token.
## A Simple Example
Here's how you could generate a token for transmitting a user's id and
name between web requests.
```python
from itsdangerous import URLSafeSerializer
auth_s = URLSafeSerializer("secret key", "auth")
token = auth_s.dumps({"id": 5, "name": "itsdangerous"})
print(token)
# eyJpZCI6NSwibmFtZSI6Iml0c2Rhbmdlcm91cyJ9.6YP6T0BaO67XP--9UzTrmurXSmg
data = auth_s.loads(token)
print(data["name"])
# itsdangerous
```
## Donate
The Pallets organization develops and supports ItsDangerous and other
popular packages. In order to grow the community of contributors and
users, and allow the maintainers to devote more time to the projects,
[please donate today][].
[please donate today]: https://palletsprojects.com/donate

View File

@@ -0,0 +1,22 @@
itsdangerous-2.2.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
itsdangerous-2.2.0.dist-info/LICENSE.txt,sha256=Y68JiRtr6K0aQlLtQ68PTvun_JSOIoNnvtfzxa4LCdc,1475
itsdangerous-2.2.0.dist-info/METADATA,sha256=0rk0-1ZwihuU5DnwJVwPWoEI4yWOyCexih3JyZHblhE,1924
itsdangerous-2.2.0.dist-info/RECORD,,
itsdangerous-2.2.0.dist-info/WHEEL,sha256=EZbGkh7Ie4PoZfRQ8I0ZuP9VklN_TvcZ6DSE5Uar4z4,81
itsdangerous/__init__.py,sha256=4SK75sCe29xbRgQE1ZQtMHnKUuZYAf3bSpZOrff1IAY,1427
itsdangerous/__pycache__/__init__.cpython-313.pyc,,
itsdangerous/__pycache__/_json.cpython-313.pyc,,
itsdangerous/__pycache__/encoding.cpython-313.pyc,,
itsdangerous/__pycache__/exc.cpython-313.pyc,,
itsdangerous/__pycache__/serializer.cpython-313.pyc,,
itsdangerous/__pycache__/signer.cpython-313.pyc,,
itsdangerous/__pycache__/timed.cpython-313.pyc,,
itsdangerous/__pycache__/url_safe.cpython-313.pyc,,
itsdangerous/_json.py,sha256=wPQGmge2yZ9328EHKF6gadGeyGYCJQKxtU-iLKE6UnA,473
itsdangerous/encoding.py,sha256=wwTz5q_3zLcaAdunk6_vSoStwGqYWe307Zl_U87aRFM,1409
itsdangerous/exc.py,sha256=Rr3exo0MRFEcPZltwecyK16VV1bE2K9_F1-d-ljcUn4,3201
itsdangerous/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
itsdangerous/serializer.py,sha256=PmdwADLqkSyQLZ0jOKAgDsAW4k_H0TlA71Ei3z0C5aI,15601
itsdangerous/signer.py,sha256=YO0CV7NBvHA6j549REHJFUjUojw2pHqwcUpQnU7yNYQ,9647
itsdangerous/timed.py,sha256=6RvDMqNumGMxf0-HlpaZdN9PUQQmRvrQGplKhxuivUs,8083
itsdangerous/url_safe.py,sha256=az4e5fXi_vs-YbWj8YZwn4wiVKfeD--GEKRT5Ueu4P4,2505

View File

@@ -0,0 +1,4 @@
Wheel-Version: 1.0
Generator: flit 3.9.0
Root-Is-Purelib: true
Tag: py3-none-any

View File

@@ -0,0 +1,74 @@
Metadata-Version: 2.4
Name: MarkupSafe
Version: 3.0.3
Summary: Safely add untrusted strings to HTML/XML markup.
Maintainer-email: Pallets <contact@palletsprojects.com>
License-Expression: BSD-3-Clause
Project-URL: Donate, https://palletsprojects.com/donate
Project-URL: Documentation, https://markupsafe.palletsprojects.com/
Project-URL: Changes, https://markupsafe.palletsprojects.com/page/changes/
Project-URL: Source, https://github.com/pallets/markupsafe/
Project-URL: Chat, https://discord.gg/pallets
Classifier: Development Status :: 5 - Production/Stable
Classifier: Environment :: Web Environment
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python
Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
Classifier: Topic :: Text Processing :: Markup :: HTML
Classifier: Typing :: Typed
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE.txt
Dynamic: license-file
<div align="center"><img src="https://raw.githubusercontent.com/pallets/markupsafe/refs/heads/stable/docs/_static/markupsafe-name.svg" alt="" height="150"></div>
# MarkupSafe
MarkupSafe implements a text object that escapes characters so it is
safe to use in HTML and XML. Characters that have special meanings are
replaced so that they display as the actual characters. This mitigates
injection attacks, meaning untrusted user input can safely be displayed
on a page.
## Examples
```pycon
>>> from markupsafe import Markup, escape
>>> # escape replaces special characters and wraps in Markup
>>> escape("<script>alert(document.cookie);</script>")
Markup('&lt;script&gt;alert(document.cookie);&lt;/script&gt;')
>>> # wrap in Markup to mark text "safe" and prevent escaping
>>> Markup("<strong>Hello</strong>")
Markup('<strong>hello</strong>')
>>> escape(Markup("<strong>Hello</strong>"))
Markup('<strong>hello</strong>')
>>> # Markup is a str subclass
>>> # methods and operators escape their arguments
>>> template = Markup("Hello <em>{name}</em>")
>>> template.format(name='"World"')
Markup('Hello <em>&#34;World&#34;</em>')
```
## Donate
The Pallets organization develops and supports MarkupSafe and other
popular packages. In order to grow the community of contributors and
users, and allow the maintainers to devote more time to the projects,
[please donate today][].
[please donate today]: https://palletsprojects.com/donate
## Contributing
See our [detailed contributing documentation][contrib] for many ways to
contribute, including reporting issues, requesting features, asking or answering
questions, and making PRs.
[contrib]: https://palletsprojects.com/contributing/

View File

@@ -0,0 +1,14 @@
markupsafe-3.0.3.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
markupsafe-3.0.3.dist-info/METADATA,sha256=8K5duwnVD7X3Yyw9U_AiCZXvdgGeWJLgpUV0ATak48s,2764
markupsafe-3.0.3.dist-info/RECORD,,
markupsafe-3.0.3.dist-info/WHEEL,sha256=qV0EIPljj1XC_vuSatRWjn02nZIz3N1t8jsZz7HBr2U,101
markupsafe-3.0.3.dist-info/licenses/LICENSE.txt,sha256=RjHsDbX9kKVH4zaBcmTGeYIUM4FG-KyUtKV_lu6MnsQ,1503
markupsafe-3.0.3.dist-info/top_level.txt,sha256=qy0Plje5IJuvsCBjejJyhDCjEAdcDLK_2agVcex8Z6U,11
markupsafe/__init__.py,sha256=ut2LXj-6sqkIVUdSAx-dboB5crAaRG5y7EO447hmaro,13644
markupsafe/__pycache__/__init__.cpython-313.pyc,,
markupsafe/__pycache__/_native.cpython-313.pyc,,
markupsafe/_native.py,sha256=2ptkJ40yCcp9kq3L1NqpgjfpZB-obniYKFFKUOkHh4Q,218
markupsafe/_speedups.c,sha256=efc6azc50WbKxSNinxV4rktIX2xzWfKsLvncC8Z3I_w,4527
markupsafe/_speedups.cp313-win_amd64.pyd,sha256=pEBLb45Lqy54Kzc1B6MKt7cTDIiH9ivw5OSptl0K3TA,13312
markupsafe/_speedups.pyi,sha256=LSDmXYOefH4HVpAXuL8sl7AttLw0oXh1njVoVZp2wqQ,42
markupsafe/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0

View File

@@ -0,0 +1,5 @@
Wheel-Version: 1.0
Generator: setuptools (80.9.0)
Root-Is-Purelib: false
Tag: cp313-cp313-win_amd64

View File

@@ -0,0 +1,28 @@
Copyright 2010 Pallets
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@@ -0,0 +1 @@
# AUTARCH Modules

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,847 @@
"""
AUTARCH Adult Site Scanner Module
Username OSINT for adult-oriented platforms
Searches usernames across adult content sites, fanfiction platforms,
and related communities.
"""
import sys
import subprocess
import re
import json
from pathlib import Path
from urllib.parse import quote
from concurrent.futures import ThreadPoolExecutor, as_completed
# Module metadata
DESCRIPTION = "Adult site username OSINT scanner"
AUTHOR = "darkHal"
VERSION = "1.3"
CATEGORY = "osint"
sys.path.insert(0, str(Path(__file__).parent.parent))
from core.banner import Colors, clear_screen, display_banner
from core.config import get_config
# Custom sites storage file
from core.paths import get_app_dir as _app_dir
CUSTOM_SITES_FILE = _app_dir() / "custom_adultsites.json"
# Bulk import file
BULK_IMPORT_FILE = _app_dir() / "custom_sites.inf"
# Common username URL patterns for auto-detection
COMMON_PATTERNS = [
'/user/{}',
'/users/{}',
'/u/{}',
'/profile/{}',
'/profiles/{}',
'/member/{}',
'/members/{}',
'/@{}',
'/{}',
'/people/{}',
'/account/{}',
'/id/{}',
'/{}/profile',
'/user/{}/profile',
'/channel/{}',
'/c/{}',
'/p/{}',
]
class AdultScanner:
"""Username scanner for adult-oriented sites."""
# Default site definitions: (name, url_template, method)
# method: 'status' = check HTTP status, 'content' = check page content
DEFAULT_SITES = {
# Fanfiction & Story Sites
'fanfiction': [
('Archive of Our Own', 'https://archiveofourown.org/users/{}/profile', 'status'),
('FanFiction.net', 'https://www.fanfiction.net/u/0/{}', 'content'),
('FimFiction', 'https://www.fimfiction.net/user/{}', 'status'),
('Wattpad', 'https://www.wattpad.com/user/{}', 'status'),
('Literotica', 'https://www.literotica.com/stories/memberpage.php?uid=0&username={}', 'content'),
('Adult-FanFiction', 'http://members.adult-fanfiction.org/profile.php?no=0&uname={}', 'content'),
('Hentai Foundry', 'https://www.hentai-foundry.com/user/{}/profile', 'status'),
('SoFurry', 'https://www.sofurry.com/browse/user/{}', 'status'),
('Inkbunny', 'https://inkbunny.net/{}', 'status'),
],
# Art & Creative
'art': [
('DeviantArt', 'https://www.deviantart.com/{}', 'status'),
('Fur Affinity', 'https://www.furaffinity.net/user/{}/', 'status'),
('Newgrounds', 'https://{}.newgrounds.com', 'status'),
('Pixiv', 'https://www.pixiv.net/en/users/{}', 'content'),
('Rule34', 'https://rule34.xxx/index.php?page=account&s=profile&uname={}', 'content'),
('e621', 'https://e621.net/users?name={}', 'content'),
('Derpibooru', 'https://derpibooru.org/profiles/{}', 'status'),
('Twitter/X', 'https://twitter.com/{}', 'status'),
('Tumblr', 'https://{}.tumblr.com', 'status'),
('Pillowfort', 'https://www.pillowfort.social/{}', 'status'),
],
# Video & Streaming
'video': [
('Pornhub', 'https://www.pornhub.com/users/{}', 'status'),
('XVideos', 'https://www.xvideos.com/profiles/{}', 'status'),
('xHamster', 'https://xhamster.com/users/{}', 'status'),
('Chaturbate', 'https://chaturbate.com/{}/', 'status'),
('OnlyFans', 'https://onlyfans.com/{}', 'status'),
('Fansly', 'https://fansly.com/{}', 'status'),
('ManyVids', 'https://www.manyvids.com/Profile/0/{}/', 'content'),
('PocketStars', 'https://pocketstars.com/{}', 'status'),
],
# Forums & Communities
'forums': [
('Reddit', 'https://www.reddit.com/user/{}', 'status'),
('F-List', 'https://www.f-list.net/c/{}', 'status'),
('FetLife', 'https://fetlife.com/users/{}', 'content'),
('Kink.com', 'https://www.kink.com/model/{}', 'content'),
('BDSMLR', 'https://{}.bdsmlr.com', 'status'),
('CollarSpace', 'https://www.collarspace.com/view/{}', 'content'),
],
# Dating & Social
'dating': [
('AdultFriendFinder', 'https://adultfriendfinder.com/p/{}', 'content'),
('Ashley Madison', 'https://www.ashleymadison.com/{}', 'content'),
('Grindr', 'https://www.grindr.com/{}', 'content'),
('Scruff', 'https://www.scruff.com/{}', 'content'),
('Recon', 'https://www.recon.com/{}', 'content'),
],
# Gaming Related (with adult content)
'gaming': [
('F95zone', 'https://f95zone.to/members/?username={}', 'content'),
('LoversLab', 'https://www.loverslab.com/profile/?name={}', 'content'),
('ULMF', 'https://ulmf.org/member.php?username={}', 'content'),
('Nutaku', 'https://www.nutaku.net/user/{}/', 'content'),
],
}
def __init__(self):
self.results = []
self.config = get_config()
osint_settings = self.config.get_osint_settings()
self.timeout = osint_settings['timeout']
self.max_threads = osint_settings['max_threads']
# Copy default sites and add custom sites
self.sites = {k: list(v) for k, v in self.DEFAULT_SITES.items()}
self.sites['custom'] = []
self.load_custom_sites()
def load_custom_sites(self):
"""Load custom sites from JSON file."""
if CUSTOM_SITES_FILE.exists():
try:
with open(CUSTOM_SITES_FILE, 'r') as f:
data = json.load(f)
self.sites['custom'] = [tuple(site) for site in data.get('sites', [])]
except Exception as e:
self.sites['custom'] = []
def save_custom_sites(self):
"""Save custom sites to JSON file."""
try:
data = {'sites': [list(site) for site in self.sites['custom']]}
with open(CUSTOM_SITES_FILE, 'w') as f:
json.dump(data, f, indent=2)
return True
except Exception as e:
return False
def add_custom_site(self):
"""Interactively add a custom site."""
print(f"\n{Colors.BOLD}Add Custom Site{Colors.RESET}")
print(f"{Colors.DIM}{'' * 50}{Colors.RESET}")
print()
print(f"{Colors.CYAN}URL Pattern Format:{Colors.RESET}")
print(f" Use {Colors.YELLOW}*{Colors.RESET} where the username should go")
print(f" Example: {Colors.DIM}https://example.com/user/*{Colors.RESET}")
print(f" Example: {Colors.DIM}https://example.com/profile?name=*{Colors.RESET}")
print()
# Get site name
name = input(f"{Colors.WHITE}Site name: {Colors.RESET}").strip()
if not name:
self.print_status("Cancelled - no name provided", "warning")
return
# Get URL pattern
url_pattern = input(f"{Colors.WHITE}URL pattern (use * for username): {Colors.RESET}").strip()
if not url_pattern:
self.print_status("Cancelled - no URL provided", "warning")
return
if '*' not in url_pattern:
self.print_status("URL must contain * for username placeholder", "error")
return
# Convert * to {} for internal format
url_template = url_pattern.replace('*', '{}')
# Ensure URL has protocol
if not url_template.startswith('http://') and not url_template.startswith('https://'):
url_template = 'https://' + url_template
# Get detection method
print()
print(f"{Colors.CYAN}Detection Method:{Colors.RESET}")
print(f" {Colors.GREEN}[1]{Colors.RESET} Status code (default) - Check HTTP response code")
print(f" {Colors.GREEN}[2]{Colors.RESET} Content - For sites with custom 404 pages")
method_choice = input(f"{Colors.WHITE}Select [1]: {Colors.RESET}").strip() or "1"
method = 'content' if method_choice == '2' else 'status'
# Add to custom sites
new_site = (name, url_template, method)
self.sites['custom'].append(new_site)
# Save to file
if self.save_custom_sites():
self.print_status(f"Added '{name}' to custom sites", "success")
print(f"{Colors.DIM} URL: {url_template.replace('{}', '<username>')}{Colors.RESET}")
else:
self.print_status("Failed to save custom sites", "error")
def manage_custom_sites(self):
"""View and manage custom sites."""
while True:
clear_screen()
display_banner()
print(f"{Colors.BOLD}Manage Custom Sites{Colors.RESET}")
print(f"{Colors.DIM}{'' * 50}{Colors.RESET}")
print()
custom = self.sites.get('custom', [])
if not custom:
print(f"{Colors.YELLOW}No custom sites added yet.{Colors.RESET}")
print()
print(f" {Colors.GREEN}[1]{Colors.RESET} Add New Site")
print(f" {Colors.DIM}[0]{Colors.RESET} Back")
print()
choice = input(f"{Colors.WHITE}Select: {Colors.RESET}").strip()
if choice == "1":
self.add_custom_site()
else:
break
else:
print(f"{Colors.CYAN}Custom Sites ({len(custom)}):{Colors.RESET}")
print()
for i, (name, url, method) in enumerate(custom, 1):
display_url = url.replace('{}', '*')
method_tag = f"[{method}]"
print(f" {Colors.GREEN}[{i}]{Colors.RESET} {name:25} {Colors.DIM}{method_tag}{Colors.RESET}")
print(f" {Colors.DIM}{display_url}{Colors.RESET}")
print()
print(f" {Colors.GREEN}[A]{Colors.RESET} Add New Site")
print(f" {Colors.RED}[R]{Colors.RESET} Remove Site")
print(f" {Colors.DIM}[0]{Colors.RESET} Back")
print()
choice = input(f"{Colors.WHITE}Select: {Colors.RESET}").strip().upper()
if choice == "0":
break
elif choice == "A":
self.add_custom_site()
elif choice == "R":
self.remove_custom_site()
def remove_custom_site(self):
"""Remove a custom site."""
custom = self.sites.get('custom', [])
if not custom:
self.print_status("No custom sites to remove", "warning")
return
print()
idx_input = input(f"{Colors.WHITE}Enter site number to remove: {Colors.RESET}").strip()
try:
idx = int(idx_input) - 1
if 0 <= idx < len(custom):
removed = custom.pop(idx)
if self.save_custom_sites():
self.print_status(f"Removed '{removed[0]}'", "success")
else:
self.print_status("Failed to save changes", "error")
else:
self.print_status("Invalid selection", "error")
except ValueError:
self.print_status("Invalid number", "error")
input(f"\n{Colors.WHITE}Press Enter to continue...{Colors.RESET}")
def auto_detect_site(self):
"""Auto-detect URL pattern for a domain."""
print(f"\n{Colors.BOLD}Auto-Detect Site Pattern{Colors.RESET}")
print(f"{Colors.DIM}{'' * 50}{Colors.RESET}")
print()
print(f"{Colors.CYAN}Enter just the domain name and we'll find the pattern.{Colors.RESET}")
print(f"{Colors.DIM}Example: example.com or www.example.com{Colors.RESET}")
print()
# Get domain
domain = input(f"{Colors.WHITE}Domain: {Colors.RESET}").strip()
if not domain:
self.print_status("Cancelled - no domain provided", "warning")
return
# Clean up domain
domain = domain.replace('https://', '').replace('http://', '').rstrip('/')
# Get test username
print()
print(f"{Colors.CYAN}We need a known username to test patterns.{Colors.RESET}")
print(f"{Colors.DIM}Enter a username that you know EXISTS on this site.{Colors.RESET}")
test_user = input(f"{Colors.WHITE}Test username: {Colors.RESET}").strip()
if not test_user:
self.print_status("Cancelled - no test username provided", "warning")
return
print(f"\n{Colors.CYAN}Testing {len(COMMON_PATTERNS)} common URL patterns...{Colors.RESET}\n")
# Test each pattern
working_patterns = []
for i, pattern in enumerate(COMMON_PATTERNS):
url = f"https://{domain}{pattern}".format(test_user)
print(f"\r{Colors.DIM} Testing pattern {i+1}/{len(COMMON_PATTERNS)}: {pattern}{' ' * 20}{Colors.RESET}", end="")
cmd = f"curl -sI -o /dev/null -w '%{{http_code}}' -L --max-time 5 '{url}' 2>/dev/null"
success, output, _ = self.run_cmd(cmd, 7)
if success:
status_code = output.strip()
if status_code in ['200', '301', '302']:
working_patterns.append((pattern, status_code, url))
print(f"\r{' ' * 80}\r", end="") # Clear line
if not working_patterns:
print(f"{Colors.YELLOW}No working patterns found.{Colors.RESET}")
print(f"{Colors.DIM}The site may use a non-standard URL format.{Colors.RESET}")
print(f"{Colors.DIM}Try using manual add [A] with the correct URL pattern.{Colors.RESET}")
return
# Display working patterns
print(f"{Colors.GREEN}Found {len(working_patterns)} working pattern(s):{Colors.RESET}\n")
for i, (pattern, status, url) in enumerate(working_patterns, 1):
status_info = "OK" if status == '200' else f"redirect ({status})"
print(f" {Colors.GREEN}[{i}]{Colors.RESET} {pattern:20} {Colors.DIM}({status_info}){Colors.RESET}")
print(f" {Colors.DIM}{url}{Colors.RESET}")
print()
# Let user select
print(f" {Colors.DIM}[0]{Colors.RESET} Cancel")
print()
choice = input(f"{Colors.WHITE}Select pattern to add: {Colors.RESET}").strip()
try:
idx = int(choice) - 1
if 0 <= idx < len(working_patterns):
selected_pattern, status, _ = working_patterns[idx]
url_template = f"https://{domain}{selected_pattern}"
# Get site name
default_name = domain.split('.')[0].title()
name = input(f"{Colors.WHITE}Site name [{default_name}]: {Colors.RESET}").strip() or default_name
# Determine method based on status
method = 'status' if status == '200' else 'content'
# Add to custom sites
new_site = (name, url_template, method)
self.sites['custom'].append(new_site)
if self.save_custom_sites():
self.print_status(f"Added '{name}' to custom sites", "success")
print(f"{Colors.DIM} Pattern: {url_template.replace('{}', '*')}{Colors.RESET}")
else:
self.print_status("Failed to save custom sites", "error")
elif choice != "0":
self.print_status("Cancelled", "warning")
except ValueError:
if choice != "0":
self.print_status("Invalid selection", "error")
def probe_domain(self, domain: str, test_user: str, quiet: bool = False) -> list:
"""Probe a domain for working URL patterns. Returns list of (pattern, status_code, url)."""
domain = domain.replace('https://', '').replace('http://', '').rstrip('/')
working_patterns = []
for i, pattern in enumerate(COMMON_PATTERNS):
url = f"https://{domain}{pattern}".format(test_user)
if not quiet:
print(f"\r{Colors.DIM} Testing {domain}: pattern {i+1}/{len(COMMON_PATTERNS)}{' ' * 20}{Colors.RESET}", end="")
cmd = f"curl -sI -o /dev/null -w '%{{http_code}}' -L --max-time 5 '{url}' 2>/dev/null"
success, output, _ = self.run_cmd(cmd, 7)
if success:
status_code = output.strip()
if status_code in ['200', '301', '302']:
working_patterns.append((pattern, status_code, url))
# For bulk mode, take first working pattern and stop
if quiet:
break
if not quiet:
print(f"\r{' ' * 80}\r", end="")
return working_patterns
def bulk_import(self):
"""Bulk import sites from custom_sites.inf file."""
print(f"\n{Colors.BOLD}Bulk Import Sites{Colors.RESET}")
print(f"{Colors.DIM}{'' * 50}{Colors.RESET}")
print()
# Check if file exists, create template if not
if not BULK_IMPORT_FILE.exists():
print(f"{Colors.YELLOW}Bulk import file not found.{Colors.RESET}")
print(f"{Colors.DIM}Creating template at: {BULK_IMPORT_FILE}{Colors.RESET}")
print()
create = input(f"{Colors.WHITE}Create template file? (y/n): {Colors.RESET}").strip().lower()
if create == 'y':
template = """# AUTARCH Adult Site Scanner - Bulk Import File
# Add one domain per line (without http:// or https://)
# Lines starting with # are comments
#
# Example:
# example.com
# another-site.net
# subdomain.site.org
#
# After adding domains, run Bulk Import [B] again
# and provide a test username that exists on these sites.
"""
with open(BULK_IMPORT_FILE, 'w') as f:
f.write(template)
self.print_status(f"Created {BULK_IMPORT_FILE}", "success")
print(f"{Colors.DIM}Edit this file and add domains, then run Bulk Import again.{Colors.RESET}")
return
# Read domains from file
domains = []
with open(BULK_IMPORT_FILE, 'r') as f:
for line in f:
line = line.strip()
# Skip empty lines and comments
if line and not line.startswith('#'):
# Clean up domain
domain = line.replace('https://', '').replace('http://', '').rstrip('/')
if domain:
domains.append(domain)
if not domains:
print(f"{Colors.YELLOW}No domains found in {BULK_IMPORT_FILE.name}{Colors.RESET}")
print(f"{Colors.DIM}Add domains (one per line) and try again.{Colors.RESET}")
return
print(f"{Colors.CYAN}Found {len(domains)} domain(s) in {BULK_IMPORT_FILE.name}:{Colors.RESET}")
for d in domains[:10]:
print(f" {Colors.DIM}-{Colors.RESET} {d}")
if len(domains) > 10:
print(f" {Colors.DIM}... and {len(domains) - 10} more{Colors.RESET}")
print()
# Check which domains are already added
existing_domains = set()
for name, url, method in self.sites.get('custom', []):
# Extract domain from URL template
try:
from urllib.parse import urlparse
parsed = urlparse(url.replace('{}', 'test'))
existing_domains.add(parsed.netloc.lower())
except:
pass
new_domains = [d for d in domains if d.lower() not in existing_domains]
skipped = len(domains) - len(new_domains)
if skipped > 0:
print(f"{Colors.YELLOW}Skipping {skipped} already-added domain(s){Colors.RESET}")
if not new_domains:
print(f"{Colors.GREEN}All domains already added!{Colors.RESET}")
return
print(f"{Colors.CYAN}Will scan {len(new_domains)} new domain(s){Colors.RESET}")
print()
# Get test username
print(f"{Colors.CYAN}We need a test username to probe URL patterns.{Colors.RESET}")
print(f"{Colors.DIM}Use a common username that likely exists on most sites.{Colors.RESET}")
print(f"{Colors.DIM}Example: admin, test, user, john, etc.{Colors.RESET}")
print()
test_user = input(f"{Colors.WHITE}Test username: {Colors.RESET}").strip()
if not test_user:
self.print_status("Cancelled - no test username provided", "warning")
return
print(f"\n{Colors.CYAN}Scanning {len(new_domains)} domains...{Colors.RESET}\n")
# Scan each domain
added = 0
failed = []
for i, domain in enumerate(new_domains):
print(f"{Colors.DIM}[{i+1}/{len(new_domains)}] Scanning {domain}...{Colors.RESET}")
# Use quiet mode to get first working pattern
patterns = self.probe_domain(domain, test_user, quiet=True)
if patterns:
pattern, status, url = patterns[0]
url_template = f"https://{domain}{pattern}"
name = domain.split('.')[0].title()
method = 'status' if status == '200' else 'content'
# Add to custom sites
new_site = (name, url_template, method)
self.sites['custom'].append(new_site)
added += 1
print(f" {Colors.GREEN}[+]{Colors.RESET} Added {name}: {pattern}")
else:
failed.append(domain)
print(f" {Colors.RED}[X]{Colors.RESET} No pattern found")
# Save results
if added > 0:
if self.save_custom_sites():
print(f"\n{Colors.GREEN}Successfully added {added} site(s){Colors.RESET}")
else:
print(f"\n{Colors.RED}Failed to save custom sites{Colors.RESET}")
if failed:
print(f"\n{Colors.YELLOW}Failed to detect patterns for {len(failed)} domain(s):{Colors.RESET}")
for d in failed[:5]:
print(f" {Colors.DIM}-{Colors.RESET} {d}")
if len(failed) > 5:
print(f" {Colors.DIM}... and {len(failed) - 5} more{Colors.RESET}")
print(f"{Colors.DIM}Try adding these manually with [A] or [D]{Colors.RESET}")
# Offer to clear the import file
print()
clear_file = input(f"{Colors.WHITE}Clear import file? (y/n): {Colors.RESET}").strip().lower()
if clear_file == 'y':
# Keep the header comments
header = """# AUTARCH Adult Site Scanner - Bulk Import File
# Add one domain per line (without http:// or https://)
# Lines starting with # are comments
"""
with open(BULK_IMPORT_FILE, 'w') as f:
f.write(header)
self.print_status("Import file cleared", "success")
def print_status(self, message: str, status: str = "info"):
colors = {"info": Colors.CYAN, "success": Colors.GREEN, "warning": Colors.YELLOW, "error": Colors.RED}
symbols = {"info": "*", "success": "+", "warning": "!", "error": "X"}
print(f"{colors.get(status, Colors.WHITE)}[{symbols.get(status, '*')}] {message}{Colors.RESET}")
def run_cmd(self, cmd: str, timeout: int = 10) -> tuple:
try:
result = subprocess.run(cmd, shell=True, capture_output=True, text=True, timeout=timeout)
return result.returncode == 0, result.stdout.strip(), result.stderr.strip()
except subprocess.TimeoutExpired:
return False, "", "timeout"
except Exception as e:
return False, "", str(e)
def check_site(self, site_info: tuple, username: str) -> dict:
"""Check if username exists on a site."""
name, url_template, method = site_info
# Handle special URL formats
if '{}' in url_template:
url = url_template.format(username)
else:
url = url_template + username
result = {
'site': name,
'url': url,
'found': False,
'status': 'unknown'
}
# Use curl to check
cmd = f"curl -sI -o /dev/null -w '%{{http_code}}' -L --max-time {self.timeout} '{url}' 2>/dev/null"
success, output, _ = self.run_cmd(cmd, self.timeout + 2)
if success:
status_code = output.strip()
if method == 'status':
# Check HTTP status code
if status_code == '200':
result['found'] = True
result['status'] = 'found'
elif status_code in ['301', '302']:
result['found'] = True
result['status'] = 'redirect'
elif status_code == '404':
result['status'] = 'not_found'
else:
result['status'] = f'http_{status_code}'
else:
# For content-based checks, we need to fetch the page
if status_code == '200':
# Could do content analysis here
result['found'] = True
result['status'] = 'possible'
elif status_code == '404':
result['status'] = 'not_found'
else:
result['status'] = f'http_{status_code}'
else:
result['status'] = 'error'
return result
def scan_username(self, username: str, categories: list = None):
"""Scan username across selected site categories."""
if categories is None:
categories = list(self.sites.keys())
# Collect all sites to scan
sites_to_scan = []
for cat in categories:
if cat in self.sites:
sites_to_scan.extend(self.sites[cat])
print(f"\n{Colors.CYAN}Scanning {len(sites_to_scan)} sites for username: {username}{Colors.RESET}")
print(f"{Colors.DIM}This may take a few minutes...{Colors.RESET}\n")
self.results = []
found_count = 0
# Use thread pool for parallel scanning
with ThreadPoolExecutor(max_workers=self.max_threads) as executor:
futures = {executor.submit(self.check_site, site, username): site for site in sites_to_scan}
for i, future in enumerate(as_completed(futures)):
result = future.result()
self.results.append(result)
# Display progress
if result['found']:
found_count += 1
status_color = Colors.GREEN if result['status'] == 'found' else Colors.YELLOW
print(f" {status_color}[+]{Colors.RESET} {result['site']:25} {result['url']}")
else:
# Show progress indicator
print(f"\r{Colors.DIM} Checked {i+1}/{len(sites_to_scan)} sites, found {found_count}...{Colors.RESET}", end="")
print(f"\r{' ' * 60}\r", end="") # Clear progress line
return self.results
def display_results(self):
"""Display scan results."""
found = [r for r in self.results if r['found']]
not_found = [r for r in self.results if not r['found']]
print(f"\n{Colors.BOLD}{'' * 60}{Colors.RESET}")
print(f"{Colors.BOLD}Scan Results{Colors.RESET}")
print(f"{Colors.BOLD}{'' * 60}{Colors.RESET}\n")
if found:
print(f"{Colors.GREEN}Found ({len(found)} sites):{Colors.RESET}\n")
for r in found:
status_note = f" ({r['status']})" if r['status'] not in ['found'] else ""
print(f" {Colors.GREEN}+{Colors.RESET} {r['site']:25} {r['url']}{Colors.DIM}{status_note}{Colors.RESET}")
else:
print(f"{Colors.YELLOW}No profiles found.{Colors.RESET}")
print(f"\n{Colors.DIM}Total sites checked: {len(self.results)}{Colors.RESET}")
print(f"{Colors.DIM}Profiles found: {len(found)}{Colors.RESET}")
def export_results(self, filename: str):
"""Export results to file."""
found = [r for r in self.results if r['found']]
with open(filename, 'w') as f:
f.write(f"Username OSINT Results\n")
f.write(f"{'=' * 50}\n\n")
f.write(f"Found Profiles ({len(found)}):\n\n")
for r in found:
f.write(f"{r['site']}: {r['url']}\n")
self.print_status(f"Results exported to {filename}", "success")
def show_menu(self):
"""Display main menu."""
clear_screen()
display_banner()
print(f"{Colors.GREEN}{Colors.BOLD} Adult Site Scanner{Colors.RESET}")
print(f"{Colors.DIM} Username OSINT for adult platforms{Colors.RESET}")
print(f"{Colors.DIM} {'' * 50}{Colors.RESET}")
print()
# Show category counts
total = sum(len(sites) for sites in self.sites.values())
custom_count = len(self.sites.get('custom', []))
print(f"{Colors.DIM} Sites in database: {total} ({custom_count} custom){Colors.RESET}")
print()
print(f" {Colors.CYAN}Scan Categories:{Colors.RESET}")
print(f" {Colors.GREEN}[1]{Colors.RESET} Full Scan (all categories)")
print(f" {Colors.GREEN}[2]{Colors.RESET} Fanfiction & Story Sites")
print(f" {Colors.GREEN}[3]{Colors.RESET} Art & Creative Sites")
print(f" {Colors.GREEN}[4]{Colors.RESET} Video & Streaming Sites")
print(f" {Colors.GREEN}[5]{Colors.RESET} Forums & Communities")
print(f" {Colors.GREEN}[6]{Colors.RESET} Dating & Social Sites")
print(f" {Colors.GREEN}[7]{Colors.RESET} Gaming Related Sites")
print(f" {Colors.GREEN}[8]{Colors.RESET} Custom Sites Only")
print(f" {Colors.GREEN}[9]{Colors.RESET} Custom Category Selection")
print()
print(f" {Colors.CYAN}Site Management:{Colors.RESET}")
print(f" {Colors.GREEN}[A]{Colors.RESET} Add Custom Site (manual)")
print(f" {Colors.GREEN}[D]{Colors.RESET} Auto-Detect Site Pattern")
print(f" {Colors.GREEN}[B]{Colors.RESET} Bulk Import from File")
print(f" {Colors.GREEN}[M]{Colors.RESET} Manage Custom Sites")
print(f" {Colors.GREEN}[L]{Colors.RESET} List All Sites")
print()
print(f" {Colors.DIM}[0]{Colors.RESET} Back")
print()
def select_categories(self) -> list:
"""Let user select multiple categories."""
print(f"\n{Colors.BOLD}Select Categories (comma-separated):{Colors.RESET}")
print()
cat_list = list(self.sites.keys())
for i, cat in enumerate(cat_list, 1):
count = len(self.sites[cat])
print(f" [{i}] {cat.title():20} ({count} sites)")
print()
selection = input(f"{Colors.WHITE}Enter numbers (e.g., 1,2,3): {Colors.RESET}").strip()
selected = []
try:
for num in selection.split(','):
idx = int(num.strip()) - 1
if 0 <= idx < len(cat_list):
selected.append(cat_list[idx])
except:
pass
return selected if selected else None
def list_sites(self):
"""List all sites in database."""
clear_screen()
display_banner()
print(f"{Colors.BOLD}Site Database{Colors.RESET}")
print(f"{Colors.DIM}{'' * 60}{Colors.RESET}\n")
for category, sites in self.sites.items():
if not sites:
continue
color = Colors.YELLOW if category == 'custom' else Colors.GREEN
print(f"{color}{category.upper()} ({len(sites)} sites){Colors.RESET}")
for name, url, method in sites:
if category == 'custom':
display_url = url.replace('{}', '*')
print(f" {Colors.DIM}-{Colors.RESET} {name} {Colors.DIM}({display_url}){Colors.RESET}")
else:
print(f" {Colors.DIM}-{Colors.RESET} {name}")
print()
input(f"{Colors.WHITE}Press Enter to continue...{Colors.RESET}")
def run_scan(self, categories: list = None):
"""Run a scan with given categories."""
username = input(f"\n{Colors.WHITE}Enter username to search: {Colors.RESET}").strip()
if not username:
return
self.scan_username(username, categories)
self.display_results()
# Export option
export = input(f"\n{Colors.WHITE}Export results to file? (y/n): {Colors.RESET}").strip().lower()
if export == 'y':
filename = f"{username}_adultscan.txt"
self.export_results(filename)
def run(self):
"""Main loop."""
while True:
self.show_menu()
try:
choice = input(f"{Colors.WHITE} Select: {Colors.RESET}").strip().upper()
if choice == "0":
break
elif choice == "1":
self.run_scan() # All categories
elif choice == "2":
self.run_scan(['fanfiction'])
elif choice == "3":
self.run_scan(['art'])
elif choice == "4":
self.run_scan(['video'])
elif choice == "5":
self.run_scan(['forums'])
elif choice == "6":
self.run_scan(['dating'])
elif choice == "7":
self.run_scan(['gaming'])
elif choice == "8":
if self.sites.get('custom'):
self.run_scan(['custom'])
else:
self.print_status("No custom sites added yet. Use [A] to add sites.", "warning")
input(f"\n{Colors.WHITE}Press Enter to continue...{Colors.RESET}")
continue
elif choice == "9":
cats = self.select_categories()
if cats:
self.run_scan(cats)
elif choice == "A":
self.add_custom_site()
input(f"\n{Colors.WHITE}Press Enter to continue...{Colors.RESET}")
continue
elif choice == "D":
self.auto_detect_site()
input(f"\n{Colors.WHITE}Press Enter to continue...{Colors.RESET}")
continue
elif choice == "B":
self.bulk_import()
input(f"\n{Colors.WHITE}Press Enter to continue...{Colors.RESET}")
continue
elif choice == "M":
self.manage_custom_sites()
continue
elif choice == "L":
self.list_sites()
continue
if choice in ["1", "2", "3", "4", "5", "6", "7", "8", "9"]:
input(f"\n{Colors.WHITE}Press Enter to continue...{Colors.RESET}")
except (EOFError, KeyboardInterrupt):
break
def run():
AdultScanner().run()
if __name__ == "__main__":
run()

View File

@@ -0,0 +1,181 @@
"""
AUTARCH Agent Module
Interactive interface for running autonomous agent tasks
This module provides an interface to give tasks to the autonomous agent
and watch it work through them step by step.
"""
import sys
from pathlib import Path
# Module metadata
DESCRIPTION = "Autonomous agent for task execution"
AUTHOR = "darkHal"
VERSION = "1.0"
CATEGORY = "core"
# Add parent directory to path
sys.path.insert(0, str(Path(__file__).parent.parent))
from core.agent import Agent, AgentState, AgentStep, AgentResult
from core.tools import get_tool_registry
from core.llm import get_llm, LLMError
from core.banner import Colors, clear_screen, display_banner
class AgentInterface:
"""Interactive interface for the AUTARCH agent."""
def __init__(self):
self.agent = None
self.llm = get_llm()
self.tools = get_tool_registry()
def print_status(self, message: str, status: str = "info"):
"""Print a status message."""
colors = {"info": Colors.CYAN, "success": Colors.GREEN, "warning": Colors.YELLOW, "error": Colors.RED}
symbols = {"info": "*", "success": "+", "warning": "!", "error": "X"}
print(f"{colors.get(status, Colors.WHITE)}[{symbols.get(status, '*')}] {message}{Colors.RESET}")
def print_header(self, text: str):
"""Print a section header."""
print(f"\n{Colors.BOLD}{Colors.WHITE}{text}{Colors.RESET}")
print(f"{Colors.DIM}{'' * 50}{Colors.RESET}")
def show_tools(self):
"""Display available tools."""
self.print_header("Available Tools")
tools = self.tools.list_tools()
for tool in tools:
print(f"\n {Colors.CYAN}{tool.name}{Colors.RESET} [{tool.category}]")
print(f" {Colors.DIM}{tool.description}{Colors.RESET}")
if tool.parameters:
for param in tool.parameters:
req = "*" if param.required else ""
print(f" - {param.name}{req}: {param.description}")
def on_step_callback(self, step: AgentStep):
"""Callback for when agent completes a step."""
print(f"\n{Colors.DIM}{'' * 40}{Colors.RESET}")
def on_state_callback(self, state: AgentState):
"""Callback for agent state changes."""
state_colors = {
AgentState.IDLE: Colors.WHITE,
AgentState.THINKING: Colors.MAGENTA,
AgentState.EXECUTING: Colors.BLUE,
AgentState.WAITING_USER: Colors.YELLOW,
AgentState.COMPLETE: Colors.GREEN,
AgentState.ERROR: Colors.RED,
}
color = state_colors.get(state, Colors.WHITE)
# Only show state for key transitions
if state in [AgentState.COMPLETE, AgentState.ERROR]:
print(f"{color}[State: {state.value}]{Colors.RESET}")
def run_task(self, task: str) -> AgentResult:
"""Run a task through the agent.
Args:
task: Task description.
Returns:
AgentResult with execution details.
"""
self.agent = Agent(
llm=self.llm,
tools=self.tools,
max_steps=20,
verbose=True
)
self.agent.on_step = self.on_step_callback
self.agent.on_state_change = self.on_state_callback
return self.agent.run(task)
def interactive_loop(self):
"""Run interactive task input loop."""
self.print_header("Agent Interface")
print(f"\n{Colors.WHITE}Enter a task for the agent to complete.")
print(f"Type 'tools' to see available tools.")
print(f"Type 'exit' to return to main menu.{Colors.RESET}\n")
while True:
try:
print(f"{Colors.DIM}{'' * 50}{Colors.RESET}")
task = input(f"\n{Colors.GREEN}Task:{Colors.RESET} ").strip()
if not task:
continue
if task.lower() == 'exit':
break
if task.lower() == 'tools':
self.show_tools()
continue
if task.lower() == 'help':
print(f"\n{Colors.WHITE}Commands:{Colors.RESET}")
print(f" {Colors.CYAN}tools{Colors.RESET} - Show available tools")
print(f" {Colors.CYAN}exit{Colors.RESET} - Return to main menu")
print(f" {Colors.CYAN}help{Colors.RESET} - Show this help")
print(f"\n{Colors.WHITE}Or enter a task description for the agent.{Colors.RESET}")
continue
# Run the task
print(f"\n{Colors.CYAN}[*] Starting agent...{Colors.RESET}\n")
result = self.run_task(task)
# Show result summary
print(f"\n{Colors.DIM}{'' * 50}{Colors.RESET}")
if result.success:
print(f"{Colors.GREEN}[+] Task completed successfully{Colors.RESET}")
print(f"\n{Colors.WHITE}Summary:{Colors.RESET} {result.summary}")
else:
print(f"{Colors.RED}[X] Task failed{Colors.RESET}")
if result.error:
print(f"{Colors.RED}Error:{Colors.RESET} {result.error}")
if result.summary:
print(f"{Colors.WHITE}Summary:{Colors.RESET} {result.summary}")
print(f"\n{Colors.DIM}Steps taken: {len(result.steps)}{Colors.RESET}")
except (EOFError, KeyboardInterrupt):
print(f"\n\n{Colors.YELLOW}[!] Interrupted{Colors.RESET}")
break
def run(self):
"""Module entry point."""
clear_screen()
display_banner()
print(f"{Colors.BOLD}{Colors.WHITE} AUTARCH Autonomous Agent{Colors.RESET}")
print(f"{Colors.DIM} {'' * 50}{Colors.RESET}")
# Check if model is loaded
if not self.llm.is_loaded:
self.print_status("Loading model...", "info")
try:
self.llm.load_model(verbose=True)
except LLMError as e:
self.print_status(f"Failed to load model: {e}", "error")
self.print_status("Please run setup to configure a model.", "warning")
input(f"\n{Colors.WHITE}Press Enter to continue...{Colors.RESET}")
return
self.interactive_loop()
def run():
"""Module entry point."""
interface = AgentInterface()
interface.run()
if __name__ == "__main__":
run()

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,417 @@
"""
AUTARCH Analyze Module
Forensics and analysis tools
File analysis, hash generation, string extraction, and more.
"""
import os
import sys
import subprocess
import hashlib
import re
try:
import magic
except ImportError:
magic = None
from pathlib import Path
from datetime import datetime
# Module metadata
DESCRIPTION = "Forensics & file analysis tools"
AUTHOR = "darkHal"
VERSION = "1.0"
CATEGORY = "analyze"
sys.path.insert(0, str(Path(__file__).parent.parent))
from core.banner import Colors, clear_screen, display_banner
class Analyzer:
"""Forensics and analysis tools."""
def __init__(self):
pass
def print_status(self, message: str, status: str = "info"):
colors = {"info": Colors.CYAN, "success": Colors.GREEN, "warning": Colors.YELLOW, "error": Colors.RED}
symbols = {"info": "*", "success": "+", "warning": "!", "error": "X"}
print(f"{colors.get(status, Colors.WHITE)}[{symbols.get(status, '*')}] {message}{Colors.RESET}")
def run_cmd(self, cmd: str) -> tuple:
try:
result = subprocess.run(cmd, shell=True, capture_output=True, text=True, timeout=60)
return result.returncode == 0, result.stdout.strip()
except:
return False, ""
def get_file_hashes(self, filepath: str) -> dict:
"""Calculate various hashes for a file."""
p = Path(filepath)
if not p.exists() or not p.is_file():
return {}
hashes = {}
with open(p, 'rb') as f:
content = f.read()
hashes['md5'] = hashlib.md5(content).hexdigest()
hashes['sha1'] = hashlib.sha1(content).hexdigest()
hashes['sha256'] = hashlib.sha256(content).hexdigest()
return hashes
def analyze_file(self):
"""Comprehensive file analysis."""
print(f"\n{Colors.BOLD}File Analysis{Colors.RESET}")
filepath = input(f"{Colors.WHITE}Enter file path: {Colors.RESET}").strip()
if not filepath:
return
p = Path(filepath).expanduser()
if not p.exists():
self.print_status(f"File not found: {filepath}", "error")
return
print(f"\n{Colors.CYAN}{'' * 50}{Colors.RESET}")
print(f"{Colors.BOLD}File: {p.name}{Colors.RESET}")
print(f"{Colors.CYAN}{'' * 50}{Colors.RESET}\n")
# Basic info
stat = p.stat()
print(f"{Colors.CYAN}Basic Info:{Colors.RESET}")
print(f" Path: {p.absolute()}")
print(f" Size: {stat.st_size:,} bytes")
print(f" Modified: {datetime.fromtimestamp(stat.st_mtime)}")
print(f" Created: {datetime.fromtimestamp(stat.st_ctime)}")
print(f" Mode: {oct(stat.st_mode)}")
# File type
print(f"\n{Colors.CYAN}File Type:{Colors.RESET}")
try:
file_magic = magic.Magic(mime=True)
mime_type = file_magic.from_file(str(p))
print(f" MIME: {mime_type}")
file_magic = magic.Magic()
file_desc = file_magic.from_file(str(p))
print(f" Type: {file_desc}")
except:
success, output = self.run_cmd(f"file '{p}'")
if success:
print(f" Type: {output.split(':', 1)[-1].strip()}")
# Hashes
print(f"\n{Colors.CYAN}Hashes:{Colors.RESET}")
hashes = self.get_file_hashes(str(p))
for algo, value in hashes.items():
print(f" {algo.upper():8} {value}")
# Check if executable
if p.suffix in ['.exe', '.dll', '.so', '.elf', ''] or stat.st_mode & 0o111:
self.analyze_executable(str(p))
def analyze_executable(self, filepath: str):
"""Additional analysis for executables."""
print(f"\n{Colors.CYAN}Executable Analysis:{Colors.RESET}")
# Strings
success, output = self.run_cmd(f"strings '{filepath}' 2>/dev/null | head -50")
if success and output:
# Look for interesting strings
interesting = []
patterns = [
r'https?://[^\s]+', # URLs
r'\d+\.\d+\.\d+\.\d+', # IPs
r'password|passwd|secret|key|token', # Credentials
r'/bin/sh|/bin/bash|cmd\.exe', # Shells
]
for line in output.split('\n'):
for pattern in patterns:
if re.search(pattern, line, re.I):
interesting.append(line.strip())
break
if interesting:
print(f" {Colors.YELLOW}Interesting strings found:{Colors.RESET}")
for s in interesting[:10]:
print(f" {s[:80]}")
# Check for packing
success, output = self.run_cmd(f"readelf -h '{filepath}' 2>/dev/null")
if success:
if 'Entry point' in output:
print(f" ELF executable detected")
def extract_strings(self):
"""Extract strings from file."""
print(f"\n{Colors.BOLD}String Extraction{Colors.RESET}")
filepath = input(f"{Colors.WHITE}Enter file path: {Colors.RESET}").strip()
if not filepath:
return
p = Path(filepath).expanduser()
if not p.exists():
self.print_status(f"File not found", "error")
return
min_len = input(f"{Colors.WHITE}Minimum string length [4]: {Colors.RESET}").strip() or "4"
print(f"\n{Colors.CYAN}Extracting strings...{Colors.RESET}\n")
success, output = self.run_cmd(f"strings -n {min_len} '{p}' 2>/dev/null")
if success:
lines = output.split('\n')
print(f"Found {len(lines)} strings\n")
# Categorize
urls = [l for l in lines if re.search(r'https?://', l)]
ips = [l for l in lines if re.search(r'\b\d+\.\d+\.\d+\.\d+\b', l)]
paths = [l for l in lines if re.search(r'^/[a-z]', l, re.I)]
emails = [l for l in lines if re.search(r'[\w.-]+@[\w.-]+', l)]
if urls:
print(f"{Colors.CYAN}URLs ({len(urls)}):{Colors.RESET}")
for u in urls[:10]:
print(f" {u}")
if ips:
print(f"\n{Colors.CYAN}IP Addresses ({len(ips)}):{Colors.RESET}")
for ip in ips[:10]:
print(f" {ip}")
if emails:
print(f"\n{Colors.CYAN}Emails ({len(emails)}):{Colors.RESET}")
for e in emails[:10]:
print(f" {e}")
if paths:
print(f"\n{Colors.CYAN}Paths ({len(paths)}):{Colors.RESET}")
for p in paths[:10]:
print(f" {p}")
# Save option
save = input(f"\n{Colors.WHITE}Save all strings to file? (y/n): {Colors.RESET}").strip().lower()
if save == 'y':
outfile = f"{p.stem}_strings.txt"
with open(outfile, 'w') as f:
f.write(output)
self.print_status(f"Saved to {outfile}", "success")
def hash_lookup(self):
"""Look up hash in threat intel."""
print(f"\n{Colors.BOLD}Hash Lookup{Colors.RESET}")
hash_input = input(f"{Colors.WHITE}Enter hash (MD5/SHA1/SHA256): {Colors.RESET}").strip()
if not hash_input:
return
# Determine hash type
hash_len = len(hash_input)
if hash_len == 32:
hash_type = "MD5"
elif hash_len == 40:
hash_type = "SHA1"
elif hash_len == 64:
hash_type = "SHA256"
else:
self.print_status("Invalid hash length", "error")
return
print(f"\n{Colors.CYAN}Hash Type: {hash_type}{Colors.RESET}")
print(f"{Colors.CYAN}Hash: {hash_input}{Colors.RESET}\n")
# VirusTotal URL
print(f"{Colors.DIM}VirusTotal: https://www.virustotal.com/gui/file/{hash_input}{Colors.RESET}")
print(f"{Colors.DIM}Hybrid Analysis: https://www.hybrid-analysis.com/search?query={hash_input}{Colors.RESET}")
def analyze_log(self):
"""Analyze log files for anomalies."""
print(f"\n{Colors.BOLD}Log Analysis{Colors.RESET}")
print(f"{Colors.DIM}Common logs: /var/log/auth.log, /var/log/syslog, /var/log/apache2/access.log{Colors.RESET}\n")
filepath = input(f"{Colors.WHITE}Enter log file path: {Colors.RESET}").strip()
if not filepath:
return
p = Path(filepath).expanduser()
if not p.exists():
self.print_status(f"File not found", "error")
return
print(f"\n{Colors.CYAN}Analyzing {p.name}...{Colors.RESET}\n")
# Read log
try:
with open(p, 'r', errors='ignore') as f:
lines = f.readlines()
except Exception as e:
self.print_status(f"Error reading file: {e}", "error")
return
print(f"Total lines: {len(lines)}")
# Extract IPs
all_ips = []
for line in lines:
ips = re.findall(r'\b(\d+\.\d+\.\d+\.\d+)\b', line)
all_ips.extend(ips)
if all_ips:
from collections import Counter
ip_counts = Counter(all_ips)
print(f"\n{Colors.CYAN}Top IP Addresses:{Colors.RESET}")
for ip, count in ip_counts.most_common(10):
print(f" {ip:20} {count:>6} occurrences")
# Look for error patterns
errors = [l for l in lines if re.search(r'error|fail|denied|invalid', l, re.I)]
if errors:
print(f"\n{Colors.YELLOW}Error/Failure entries: {len(errors)}{Colors.RESET}")
print(f"{Colors.DIM}Recent errors:{Colors.RESET}")
for e in errors[-5:]:
print(f" {e.strip()[:100]}")
# Timestamps
timestamps = []
for line in lines:
match = re.search(r'(\w{3}\s+\d+\s+\d+:\d+:\d+)', line)
if match:
timestamps.append(match.group(1))
if timestamps:
print(f"\n{Colors.CYAN}Time Range:{Colors.RESET}")
print(f" First: {timestamps[0]}")
print(f" Last: {timestamps[-1]}")
def hex_dump(self):
"""Create hex dump of file."""
print(f"\n{Colors.BOLD}Hex Dump{Colors.RESET}")
filepath = input(f"{Colors.WHITE}Enter file path: {Colors.RESET}").strip()
if not filepath:
return
p = Path(filepath).expanduser()
if not p.exists():
self.print_status(f"File not found", "error")
return
offset = input(f"{Colors.WHITE}Start offset [0]: {Colors.RESET}").strip() or "0"
length = input(f"{Colors.WHITE}Length [256]: {Colors.RESET}").strip() or "256"
try:
offset = int(offset, 0) # Support hex input
length = int(length, 0)
except:
self.print_status("Invalid offset/length", "error")
return
print(f"\n{Colors.CYAN}Hex dump of {p.name} (offset={hex(offset)}, length={length}):{Colors.RESET}\n")
with open(p, 'rb') as f:
f.seek(offset)
data = f.read(length)
# Format hex dump
for i in range(0, len(data), 16):
chunk = data[i:i+16]
hex_part = ' '.join(f'{b:02x}' for b in chunk)
ascii_part = ''.join(chr(b) if 32 <= b < 127 else '.' for b in chunk)
print(f" {offset+i:08x} {hex_part:<48} {ascii_part}")
def compare_files(self):
"""Compare two files."""
print(f"\n{Colors.BOLD}File Comparison{Colors.RESET}")
file1 = input(f"{Colors.WHITE}First file: {Colors.RESET}").strip()
file2 = input(f"{Colors.WHITE}Second file: {Colors.RESET}").strip()
if not file1 or not file2:
return
p1 = Path(file1).expanduser()
p2 = Path(file2).expanduser()
if not p1.exists() or not p2.exists():
self.print_status("One or both files not found", "error")
return
print(f"\n{Colors.CYAN}Comparing files...{Colors.RESET}\n")
# Size comparison
s1, s2 = p1.stat().st_size, p2.stat().st_size
print(f"File 1 size: {s1:,} bytes")
print(f"File 2 size: {s2:,} bytes")
print(f"Difference: {abs(s1-s2):,} bytes")
# Hash comparison
h1 = self.get_file_hashes(str(p1))
h2 = self.get_file_hashes(str(p2))
print(f"\n{Colors.CYAN}Hash Comparison:{Colors.RESET}")
for algo in ['md5', 'sha256']:
match = h1.get(algo) == h2.get(algo)
status = f"{Colors.GREEN}MATCH{Colors.RESET}" if match else f"{Colors.RED}DIFFERENT{Colors.RESET}"
print(f" {algo.upper()}: {status}")
if h1.get('sha256') != h2.get('sha256'):
# Show diff if text files
success, output = self.run_cmd(f"diff '{p1}' '{p2}' 2>/dev/null | head -30")
if success and output:
print(f"\n{Colors.CYAN}Differences (first 30 lines):{Colors.RESET}")
print(output)
def show_menu(self):
clear_screen()
display_banner()
print(f"{Colors.CYAN}{Colors.BOLD} Analysis & Forensics{Colors.RESET}")
print(f"{Colors.DIM} File analysis and forensics tools{Colors.RESET}")
print(f"{Colors.DIM} {'' * 50}{Colors.RESET}")
print()
print(f" {Colors.CYAN}[1]{Colors.RESET} Analyze File")
print(f" {Colors.CYAN}[2]{Colors.RESET} Extract Strings")
print(f" {Colors.CYAN}[3]{Colors.RESET} Hash Lookup")
print(f" {Colors.CYAN}[4]{Colors.RESET} Analyze Log")
print(f" {Colors.CYAN}[5]{Colors.RESET} Hex Dump")
print(f" {Colors.CYAN}[6]{Colors.RESET} Compare Files")
print()
print(f" {Colors.DIM}[0]{Colors.RESET} Back")
print()
def run(self):
while True:
self.show_menu()
try:
choice = input(f"{Colors.WHITE} Select: {Colors.RESET}").strip()
if choice == "0":
break
elif choice == "1":
self.analyze_file()
elif choice == "2":
self.extract_strings()
elif choice == "3":
self.hash_lookup()
elif choice == "4":
self.analyze_log()
elif choice == "5":
self.hex_dump()
elif choice == "6":
self.compare_files()
if choice in ["1", "2", "3", "4", "5", "6"]:
input(f"\n{Colors.WHITE}Press Enter to continue...{Colors.RESET}")
except (EOFError, KeyboardInterrupt):
break
def run():
Analyzer().run()
if __name__ == "__main__":
run()

View File

@@ -0,0 +1,380 @@
"""
Android Advanced Exploits - Network, app manipulation, system control, data exfil
"""
DESCRIPTION = "Android advanced exploits (network, apps, system, data extraction)"
AUTHOR = "AUTARCH"
VERSION = "1.0"
CATEGORY = "offense"
import sys
from pathlib import Path
sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
class AndroidAdvanced:
"""Interactive menu for advanced Android exploits."""
def __init__(self):
from core.android_exploit import get_exploit_manager
from core.hardware import get_hardware_manager
self.mgr = get_exploit_manager()
self.hw = get_hardware_manager()
self.serial = None
def _select_device(self):
devices = self.hw.adb_devices()
if not devices:
print(" No ADB devices connected.")
return
if len(devices) == 1:
self.serial = devices[0]['serial']
print(f" Selected: {self.serial}")
return
print("\n Select device:")
for i, d in enumerate(devices, 1):
print(f" {i}) {d['serial']} {d.get('model','')}")
try:
choice = int(input(" > ").strip())
if 1 <= choice <= len(devices):
self.serial = devices[choice - 1]['serial']
except (ValueError, EOFError, KeyboardInterrupt):
pass
def _ensure_device(self):
if not self.serial:
self._select_device()
return self.serial is not None
def show_menu(self):
print(f"\n{'='*60}")
print(" Advanced Android Exploits")
print(f"{'='*60}")
print(f" Device: {self.serial or '(none)'}")
print()
print(" ── Data Exfiltration ──")
print(" [1] Clipboard Content")
print(" [2] Notifications")
print(" [3] Location Data")
print(" [4] List Media Files")
print(" [5] Pull Media Folder")
print(" [6] WhatsApp DB [ROOT]")
print(" [7] Telegram DB [ROOT]")
print(" [8] Signal DB [ROOT]")
print(" [9] Dump Settings (all)")
print(" [10] Device Fingerprint")
print(" [11] Dump Any Database [ROOT]")
print()
print(" ── Network ──")
print(" [20] Network Info")
print(" [21] Set Proxy (MITM)")
print(" [22] Clear Proxy")
print(" [23] Set DNS [ROOT]")
print(" [24] WiFi Scan")
print(" [25] WiFi Connect")
print(" [26] WiFi On/Off")
print(" [27] Enable Hotspot")
print(" [28] Capture Traffic [ROOT]")
print(" [29] Port Forward")
print(" [30] ADB over WiFi")
print()
print(" ── App Manipulation ──")
print(" [40] Grant Permission")
print(" [41] Revoke Permission")
print(" [42] List App Permissions")
print(" [43] Disable App")
print(" [44] Enable App")
print(" [45] Clear App Data")
print(" [46] Force Stop App")
print(" [47] Launch App")
print(" [48] Launch Activity")
print(" [49] Send Broadcast")
print(" [50] Content Query")
print(" [51] Enable Overlay")
print()
print(" ── System ──")
print(" [60] SELinux Permissive [ROOT]")
print(" [61] Remount /system RW [ROOT]")
print(" [62] Logcat Sensitive Data")
print(" [63] Deploy Frida Server [ROOT]")
print(" [64] Running Processes")
print(" [65] Open Ports")
print(" [66] Modify Setting")
print()
print(" [s] Select Device")
print(" [0] Back")
print()
def _print_result(self, r):
import json
if isinstance(r, dict):
for k, v in r.items():
if isinstance(v, (list, dict)) and len(str(v)) > 200:
print(f" {k}: [{len(v)} items]" if isinstance(v, list) else f" {k}: [dict]")
else:
val = str(v)
if len(val) > 120:
val = val[:120] + '...'
print(f" {k}: {val}")
def run_interactive(self):
while True:
self.show_menu()
try:
choice = input(" Select > ").strip().lower()
except (EOFError, KeyboardInterrupt):
break
if choice == '0':
break
elif choice == 's':
self._select_device()
continue
if not self._ensure_device():
continue
try:
self._dispatch(choice)
except (EOFError, KeyboardInterrupt):
continue
def _dispatch(self, choice):
s = self.serial
m = self.mgr
# Data Exfil
if choice == '1':
self._print_result(m.extract_clipboard(s))
elif choice == '2':
r = m.dump_notifications(s)
print(f" {r.get('count', 0)} notifications:")
for n in r.get('notifications', [])[:20]:
print(f" [{n.get('package','')}] {n.get('title','')} - {n.get('text','')}")
elif choice == '3':
self._print_result(m.extract_location(s))
elif choice == '4':
t = input(" Type (photos/downloads/screenshots/whatsapp_media): ").strip() or 'photos'
r = m.extract_media_list(s, media_type=t)
print(f" {r['count']} files in {r['path']}:")
for f in r['files'][:30]:
print(f" {f}")
elif choice == '5':
t = input(" Type (photos/downloads/screenshots): ").strip() or 'photos'
lim = input(" Limit [50]: ").strip()
r = m.pull_media_folder(s, media_type=t, limit=int(lim) if lim else 50)
print(f" Pulled {r['count']} files to {r.get('output_dir','')}")
elif choice == '6':
r = m.extract_whatsapp_db(s)
self._print_result(r)
elif choice == '7':
r = m.extract_telegram_db(s)
self._print_result(r)
elif choice == '8':
r = m.extract_signal_db(s)
self._print_result(r)
elif choice == '9':
r = m.dump_all_settings(s)
for ns, entries in r.get('settings', {}).items():
print(f"\n [{ns}] ({len(entries)} entries)")
for k, v in list(entries.items())[:10]:
print(f" {k}={v}")
if len(entries) > 10:
print(f" ... and {len(entries)-10} more")
elif choice == '10':
fp = m.get_device_fingerprint(s)
print("\n Device Fingerprint:")
for k, v in fp.items():
print(f" {k:<25} {v}")
elif choice == '11':
db_path = input(" Database path on device: ").strip()
table = input(" Table name (or Enter to list tables): ").strip() or None
r = m.dump_database(s, db_path, table=table)
if r['success']:
print(f" Tables: {', '.join(r['tables'])}")
if r['rows']:
for row in r['rows'][:10]:
print(f" {row}")
else:
print(f" Error: {r['error']}")
# Network
elif choice == '20':
info = m.get_network_info(s)
for k, v in info.items():
val = str(v)[:200]
print(f" {k}: {val}")
elif choice == '21':
host = input(" Proxy host: ").strip()
port = input(" Proxy port: ").strip()
if host and port:
r = m.set_proxy(s, host, port)
print(f" Proxy set: {r.get('proxy')}")
elif choice == '22':
m.clear_proxy(s)
print(" Proxy cleared.")
elif choice == '23':
dns1 = input(" DNS1: ").strip()
dns2 = input(" DNS2 (optional): ").strip()
if dns1:
m.set_dns(s, dns1, dns2)
print(f" DNS set: {dns1} {dns2}")
elif choice == '24':
r = m.wifi_scan(s)
print(r.get('output', 'No results'))
elif choice == '25':
ssid = input(" SSID: ").strip()
pwd = input(" Password (Enter for open): ").strip()
if ssid:
r = m.wifi_connect(s, ssid, pwd)
print(f" {r.get('output', 'Done')}")
elif choice == '26':
action = input(" Enable or disable? [e/d]: ").strip().lower()
if action == 'd':
m.wifi_disconnect(s)
print(" WiFi disabled.")
else:
m.wifi_enable(s)
print(" WiFi enabled.")
elif choice == '27':
ssid = input(" Hotspot SSID [AUTARCH_AP]: ").strip() or 'AUTARCH_AP'
pwd = input(" Password [autarch123]: ").strip() or 'autarch123'
r = m.enable_hotspot(s, ssid, pwd)
print(f" Hotspot: {ssid}")
elif choice == '28':
iface = input(" Interface [any]: ").strip() or 'any'
dur = input(" Duration seconds [30]: ").strip()
filt = input(" Filter (optional): ").strip()
r = m.capture_traffic(s, iface, int(dur) if dur else 30, filt)
if r['success']:
print(f" PCAP saved: {r['path']} ({r['size']} bytes)")
else:
print(f" Error: {r['error']}")
elif choice == '29':
lp = input(" Local port: ").strip()
rp = input(" Remote port: ").strip()
if lp and rp:
r = m.port_forward(s, lp, rp)
print(f" Forward: localhost:{lp} -> device:{rp}")
elif choice == '30':
port = input(" Port [5555]: ").strip() or '5555'
r = m.enable_adb_wifi(s, int(port))
print(f" ADB WiFi: {r.get('connect_cmd', '?')}")
# App Manipulation
elif choice == '40':
pkg = input(" Package: ").strip()
perm = input(" Permission (e.g. android.permission.CAMERA): ").strip()
if pkg and perm:
r = m.grant_permission(s, pkg, perm)
print(f" {r.get('output', 'Done')}")
elif choice == '41':
pkg = input(" Package: ").strip()
perm = input(" Permission: ").strip()
if pkg and perm:
r = m.revoke_permission(s, pkg, perm)
print(f" {r.get('output', 'Done')}")
elif choice == '42':
pkg = input(" Package: ").strip()
if pkg:
r = m.list_permissions(s, pkg)
print(f" Granted ({len(r['granted'])}):")
for p in r['granted'][:20]:
print(f" + {p}")
print(f" Denied ({len(r['denied'])}):")
for p in r['denied'][:10]:
print(f" - {p}")
elif choice == '43':
pkg = input(" Package to disable: ").strip()
if pkg:
r = m.disable_app(s, pkg)
print(f" {r.get('output', 'Done')}")
elif choice == '44':
pkg = input(" Package to enable: ").strip()
if pkg:
r = m.enable_app(s, pkg)
print(f" {r.get('output', 'Done')}")
elif choice == '45':
pkg = input(" Package to clear: ").strip()
if pkg:
confirm = input(f" Clear ALL data for {pkg}? [y/N]: ").strip().lower()
if confirm == 'y':
r = m.clear_app_data(s, pkg)
print(f" {r.get('output', 'Done')}")
elif choice == '46':
pkg = input(" Package to force stop: ").strip()
if pkg:
m.force_stop_app(s, pkg)
print(f" Force stopped {pkg}")
elif choice == '47':
pkg = input(" Package to launch: ").strip()
if pkg:
m.launch_app(s, pkg)
print(f" Launched {pkg}")
elif choice == '48':
comp = input(" Component (com.pkg/.Activity): ").strip()
extras = input(" Extras (optional am flags): ").strip()
if comp:
r = m.launch_activity(s, comp, extras)
print(f" {r.get('output', 'Done')}")
elif choice == '49':
action = input(" Broadcast action: ").strip()
extras = input(" Extras (optional): ").strip()
if action:
r = m.send_broadcast(s, action, extras)
print(f" {r.get('output', 'Done')}")
elif choice == '50':
uri = input(" Content URI: ").strip()
proj = input(" Projection (col1:col2 or Enter): ").strip()
where = input(" Where clause (or Enter): ").strip()
if uri:
r = m.content_query(s, uri, proj, where)
print(f" {r['count']} rows:")
for row in r['rows'][:20]:
print(f" {row}")
elif choice == '51':
pkg = input(" Package for overlay: ").strip()
if pkg:
m.overlay_attack_enable(s, pkg)
print(f" Overlay enabled for {pkg}")
# System
elif choice == '60':
r = m.set_selinux(s, 'permissive')
print(f" SELinux: {r.get('mode', '?')}")
elif choice == '61':
r = m.remount_system(s)
print(f" /system remounted {r.get('mode')}: {r.get('output','')}")
elif choice == '62':
dur = input(" Scan duration [10]: ").strip()
r = m.logcat_sensitive(s, int(dur) if dur else 10)
print(f" Found {r['count']} sensitive lines:")
for line in r['lines'][:20]:
print(f" {line[:120]}")
elif choice == '63':
path = input(" Frida server binary path: ").strip()
if path:
r = m.deploy_frida(s, path)
if r['success']:
print(f" Frida running, PID: {r['pid']}")
else:
print(f" Error: {r.get('error')}")
elif choice == '64':
r = m.get_running_processes(s)
print(f" {r['count']} processes:")
for p in r['processes'][:30]:
print(f" {p.get('pid','?'):>6} {p.get('user',''):>12} {p.get('name','')}")
elif choice == '65':
r = m.get_open_ports(s)
print(f" {r['count']} listening ports:")
for p in r['ports']:
print(f" {p}")
elif choice == '66':
ns = input(" Namespace (system/secure/global): ").strip()
key = input(" Key: ").strip()
val = input(" Value: ").strip()
if ns and key and val:
r = m.modify_setting(s, ns, key, val)
print(f" {ns}.{key} = {r.get('value','?')}")
else:
print(" Invalid choice.")
def run():
m = AndroidAdvanced()
m.run_interactive()

View File

@@ -0,0 +1,165 @@
"""
Android App Extraction - Pull APKs, app data, shared preferences
"""
DESCRIPTION = "Android app extraction (APK pull, app data, shared prefs)"
AUTHOR = "AUTARCH"
VERSION = "1.0"
CATEGORY = "hardware"
import sys
from pathlib import Path
sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
class AndroidApps:
"""Interactive menu for Android app extraction."""
def __init__(self):
from core.android_exploit import get_exploit_manager
from core.hardware import get_hardware_manager
self.mgr = get_exploit_manager()
self.hw = get_hardware_manager()
self.serial = None
def _select_device(self):
devices = self.hw.adb_devices()
if not devices:
print(" No ADB devices connected.")
return
if len(devices) == 1:
self.serial = devices[0]['serial']
print(f" Selected: {self.serial}")
return
print("\n Select device:")
for i, d in enumerate(devices, 1):
model = d.get('model', '')
print(f" {i}) {d['serial']} {model}")
try:
choice = int(input(" > ").strip())
if 1 <= choice <= len(devices):
self.serial = devices[choice - 1]['serial']
except (ValueError, EOFError, KeyboardInterrupt):
pass
def _ensure_device(self):
if not self.serial:
self._select_device()
return self.serial is not None
def show_menu(self):
print(f"\n{'='*50}")
print(" App Extraction")
print(f"{'='*50}")
print(f" Device: {self.serial or '(none)'}")
print()
print(" [1] List Packages")
print(" [2] Pull APK")
print(" [3] Pull App Data (root/debuggable)")
print(" [4] Extract Shared Prefs")
print(" [s] Select Device")
print(" [0] Back")
print()
def list_packages(self):
if not self._ensure_device():
return
try:
inc = input(" Include system apps? [y/N]: ").strip().lower() == 'y'
except (EOFError, KeyboardInterrupt):
return
result = self.mgr.list_packages(self.serial, include_system=inc)
if 'error' in result:
print(f" Error: {result['error']}")
return
print(f"\n Found {result['count']} packages:")
for pkg in result['packages']:
flag = ' [SYS]' if pkg['is_system'] else ''
print(f" {pkg['package']}{flag}")
print(f" {pkg['path']}")
def pull_apk(self):
if not self._ensure_device():
return
try:
package = input(" Package name: ").strip()
except (EOFError, KeyboardInterrupt):
return
if not package:
return
print(f" Pulling APK for {package}...")
result = self.mgr.pull_apk(self.serial, package)
if result['success']:
size_mb = result['size'] / (1024 * 1024)
print(f" Saved: {result['local_path']} ({size_mb:.1f} MB)")
else:
print(f" Error: {result['error']}")
def pull_app_data(self):
if not self._ensure_device():
return
try:
package = input(" Package name: ").strip()
except (EOFError, KeyboardInterrupt):
return
if not package:
return
print(f" Pulling app data for {package}...")
result = self.mgr.pull_app_data(self.serial, package)
if result['success']:
print(f" Output dir: {result['output_dir']}")
for f in result['files']:
print(f" {f}")
else:
print(" No data extracted (need debuggable app or root).")
def extract_prefs(self):
if not self._ensure_device():
return
try:
package = input(" Package name: ").strip()
except (EOFError, KeyboardInterrupt):
return
if not package:
return
print(f" Extracting shared prefs for {package}...")
result = self.mgr.extract_shared_prefs(self.serial, package)
if result['success']:
print(f" Found {result['count']} pref files:")
for name, content in result['prefs'].items():
print(f"\n --- {name} ---")
# Show first 20 lines
lines = content.split('\n')[:20]
for line in lines:
print(f" {line}")
if len(content.split('\n')) > 20:
print(" ...")
else:
print(f" Error: {result.get('error', 'Failed')}")
def run_interactive(self):
while True:
self.show_menu()
try:
choice = input(" Select > ").strip().lower()
except (EOFError, KeyboardInterrupt):
break
if choice == '0':
break
elif choice == '1':
self.list_packages()
elif choice == '2':
self.pull_apk()
elif choice == '3':
self.pull_app_data()
elif choice == '4':
self.extract_prefs()
elif choice == 's':
self._select_device()
else:
print(" Invalid choice.")
def run():
m = AndroidApps()
m.run_interactive()

View File

@@ -0,0 +1,203 @@
"""
Android Boot / Recovery Exploit - Bootloader unlock, flash, dm-verity
"""
DESCRIPTION = "Android boot/recovery exploits (flash, unlock, verity bypass)"
AUTHOR = "AUTARCH"
VERSION = "1.0"
CATEGORY = "offense"
import sys
from pathlib import Path
sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
class AndroidBoot:
"""Interactive menu for boot/recovery operations."""
def __init__(self):
from core.android_exploit import get_exploit_manager
from core.hardware import get_hardware_manager
self.mgr = get_exploit_manager()
self.hw = get_hardware_manager()
self.serial = None
def _select_device(self):
"""Select from fastboot devices (boot ops need fastboot mostly)."""
fb_devices = self.hw.fastboot_devices()
adb_devices = self.hw.adb_devices()
all_devs = []
for d in fb_devices:
all_devs.append({'serial': d['serial'], 'mode': 'fastboot'})
for d in adb_devices:
all_devs.append({'serial': d['serial'], 'mode': 'adb'})
if not all_devs:
print(" No devices found (ADB or fastboot).")
return
if len(all_devs) == 1:
self.serial = all_devs[0]['serial']
print(f" Selected: {self.serial} ({all_devs[0]['mode']})")
return
print("\n Select device:")
for i, d in enumerate(all_devs, 1):
print(f" {i}) {d['serial']} [{d['mode']}]")
try:
choice = int(input(" > ").strip())
if 1 <= choice <= len(all_devs):
self.serial = all_devs[choice - 1]['serial']
except (ValueError, EOFError, KeyboardInterrupt):
pass
def _ensure_device(self):
if not self.serial:
self._select_device()
return self.serial is not None
def show_menu(self):
print(f"\n{'='*50}")
print(" Boot / Recovery Exploit")
print(f"{'='*50}")
print(" !! WARNING: Can BRICK device / WIPE data !!")
print(f" Device: {self.serial or '(none)'}")
print()
print(" [1] Bootloader Info")
print(" [2] Backup Boot Image")
print(" [3] Unlock Bootloader [WIPES DATA]")
print(" [4] Flash Custom Recovery")
print(" [5] Flash Boot Image")
print(" [6] Disable dm-verity/AVB")
print(" [7] Temp Boot (no flash)")
print(" [s] Select Device")
print(" [0] Back")
print()
def bootloader_info(self):
if not self._ensure_device():
return
print(" Querying bootloader...")
info = self.mgr.get_bootloader_info(self.serial)
if not info:
print(" No info returned (device might not be in fastboot mode).")
return
print(f"\n Bootloader Variables:")
for k, v in info.items():
print(f" {k:<25} {v}")
def backup_boot(self):
if not self._ensure_device():
return
print(" Backing up boot image (requires root via ADB)...")
result = self.mgr.backup_boot_image(self.serial)
if result['success']:
size_mb = result['size'] / (1024 * 1024)
print(f" Saved: {result['local_path']} ({size_mb:.1f} MB)")
else:
print(f" Error: {result.get('error', 'Failed')}")
def unlock_bootloader(self):
if not self._ensure_device():
return
print("\n !! WARNING: This will WIPE ALL DATA on the device !!")
try:
confirm = input(" Type 'YES' to proceed: ").strip()
except (EOFError, KeyboardInterrupt):
return
if confirm != 'YES':
print(" Cancelled.")
return
print(" Unlocking bootloader...")
result = self.mgr.unlock_bootloader(self.serial)
if result['success']:
print(" Bootloader unlocked (or confirmation pending on device).")
else:
print(f" Result: {result.get('output', 'Unknown')}")
def flash_recovery(self):
if not self._ensure_device():
return
try:
img = input(" Recovery image path: ").strip()
except (EOFError, KeyboardInterrupt):
return
if not img:
return
print(" Flashing recovery...")
result = self.mgr.flash_recovery(self.serial, img)
if result.get('success'):
print(f" Flash started (op: {result.get('op_id', '?')})")
else:
print(f" Error: {result.get('error', 'Failed')}")
def flash_boot(self):
if not self._ensure_device():
return
try:
img = input(" Boot image path: ").strip()
except (EOFError, KeyboardInterrupt):
return
if not img:
return
print(" Flashing boot...")
result = self.mgr.flash_boot(self.serial, img)
if result.get('success'):
print(f" Flash started (op: {result.get('op_id', '?')})")
else:
print(f" Error: {result.get('error', 'Failed')}")
def disable_verity(self):
if not self._ensure_device():
return
try:
vbmeta = input(" vbmeta image path (optional, Enter to skip): ").strip() or None
except (EOFError, KeyboardInterrupt):
return
print(" Disabling dm-verity/AVB...")
result = self.mgr.disable_verity(self.serial, vbmeta)
print(f" Result: {result.get('output', 'Done')}")
print(f" Method: {result.get('method', '?')}")
def temp_boot(self):
if not self._ensure_device():
return
try:
img = input(" Boot image path: ").strip()
except (EOFError, KeyboardInterrupt):
return
if not img:
return
print(" Temp-booting image (no permanent flash)...")
result = self.mgr.boot_temp(self.serial, img)
if result['success']:
print(" Device booting from temporary image.")
else:
print(f" Error: {result.get('output', 'Failed')}")
def run_interactive(self):
while True:
self.show_menu()
try:
choice = input(" Select > ").strip().lower()
except (EOFError, KeyboardInterrupt):
break
if choice == '0':
break
actions = {
'1': self.bootloader_info,
'2': self.backup_boot,
'3': self.unlock_bootloader,
'4': self.flash_recovery,
'5': self.flash_boot,
'6': self.disable_verity,
'7': self.temp_boot,
's': self._select_device,
}
action = actions.get(choice)
if action:
action()
else:
print(" Invalid choice.")
def run():
m = AndroidBoot()
m.run_interactive()

View File

@@ -0,0 +1,191 @@
"""
Android Payload Deployment - Deploy binaries, reverse shells, persistence
"""
DESCRIPTION = "Android payload deployment (binaries, reverse shells, persistence)"
AUTHOR = "AUTARCH"
VERSION = "1.0"
CATEGORY = "offense"
import sys
from pathlib import Path
sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
class AndroidPayload:
"""Interactive menu for Android payload deployment."""
def __init__(self):
from core.android_exploit import get_exploit_manager
from core.hardware import get_hardware_manager
self.mgr = get_exploit_manager()
self.hw = get_hardware_manager()
self.serial = None
def _select_device(self):
devices = self.hw.adb_devices()
if not devices:
print(" No ADB devices connected.")
return
if len(devices) == 1:
self.serial = devices[0]['serial']
print(f" Selected: {self.serial}")
return
print("\n Select device:")
for i, d in enumerate(devices, 1):
model = d.get('model', '')
print(f" {i}) {d['serial']} {model}")
try:
choice = int(input(" > ").strip())
if 1 <= choice <= len(devices):
self.serial = devices[choice - 1]['serial']
except (ValueError, EOFError, KeyboardInterrupt):
pass
def _ensure_device(self):
if not self.serial:
self._select_device()
return self.serial is not None
def show_menu(self):
print(f"\n{'='*50}")
print(" Payload Deployment")
print(f"{'='*50}")
print(f" Device: {self.serial or '(none)'}")
print()
print(" [1] Deploy Binary")
print(" [2] Execute Payload")
print(" [3] Setup Reverse Shell")
print(" [4] Install Persistence [ROOT]")
print(" [5] List Running Payloads")
print(" [6] Kill Payload")
print(" [s] Select Device")
print(" [0] Back")
print()
def deploy_binary(self):
if not self._ensure_device():
return
try:
local = input(" Local binary path: ").strip()
remote = input(" Remote path [/data/local/tmp/]: ").strip() or '/data/local/tmp/'
except (EOFError, KeyboardInterrupt):
return
if not local:
return
print(" Deploying...")
result = self.mgr.deploy_binary(self.serial, local, remote)
if result['success']:
print(f" Deployed to: {result['remote_path']}")
else:
print(f" Error: {result['error']}")
def execute_payload(self):
if not self._ensure_device():
return
try:
remote = input(" Remote path: ").strip()
args = input(" Arguments []: ").strip()
bg = input(" Background? [Y/n]: ").strip().lower() != 'n'
except (EOFError, KeyboardInterrupt):
return
if not remote:
return
print(" Executing...")
result = self.mgr.execute_payload(self.serial, remote, args=args, background=bg)
if result['success']:
if result['background']:
print(f" Running in background, PID: {result['pid']}")
else:
print(f" Output:\n{result['output']}")
else:
print(f" Error: {result.get('output', 'Failed')}")
def reverse_shell(self):
if not self._ensure_device():
return
try:
lhost = input(" LHOST (your IP): ").strip()
lport = input(" LPORT: ").strip()
print(" Methods: nc, bash, python")
method = input(" Method [nc]: ").strip() or 'nc'
except (EOFError, KeyboardInterrupt):
return
if not lhost or not lport:
return
print(f" Setting up {method} reverse shell to {lhost}:{lport}...")
result = self.mgr.setup_reverse_shell(self.serial, lhost, int(lport), method)
if result['success']:
print(f" Reverse shell initiated ({method})")
print(f" Catch with: nc -lvnp {lport}")
else:
print(f" Error: {result.get('error', 'Failed')}")
def persistence(self):
if not self._ensure_device():
return
try:
method = input(" Method [init.d]: ").strip() or 'init.d'
except (EOFError, KeyboardInterrupt):
return
print(" Installing persistence (requires root)...")
result = self.mgr.install_persistence(self.serial, method)
if result['success']:
print(f" Installed at: {result['path']}")
else:
print(f" Error: {result.get('error', 'Failed')}")
def list_payloads(self):
if not self._ensure_device():
return
result = self.mgr.list_running_payloads(self.serial)
if not result['success']:
print(f" Error: {result.get('error', 'Failed')}")
return
if not result['payloads']:
print(" No running payloads found in /data/local/tmp/")
return
print(f"\n Found {result['count']} running payloads:")
for p in result['payloads']:
print(f" PID {p['pid']}: {p['command']}")
def kill_payload(self):
if not self._ensure_device():
return
try:
pid = input(" PID to kill: ").strip()
except (EOFError, KeyboardInterrupt):
return
if not pid:
return
result = self.mgr.kill_payload(self.serial, pid)
print(f" Kill signal sent to PID {pid}")
def run_interactive(self):
while True:
self.show_menu()
try:
choice = input(" Select > ").strip().lower()
except (EOFError, KeyboardInterrupt):
break
if choice == '0':
break
actions = {
'1': self.deploy_binary,
'2': self.execute_payload,
'3': self.reverse_shell,
'4': self.persistence,
'5': self.list_payloads,
'6': self.kill_payload,
's': self._select_device,
}
action = actions.get(choice)
if action:
action()
else:
print(" Invalid choice.")
def run():
m = AndroidPayload()
m.run_interactive()

View File

@@ -0,0 +1,936 @@
"""
Android Protection Shield - Anti-stalkerware & anti-spyware defense
Detect, analyze, and remove stalkerware and government-grade spyware from Android devices.
"""
DESCRIPTION = "Android anti-stalkerware/spyware shield"
AUTHOR = "AUTARCH"
VERSION = "1.0"
CATEGORY = "defense"
class AndroidProtect:
"""Interactive Android protection menu."""
def __init__(self):
from core.android_protect import get_android_protect_manager
from core.hardware import get_hardware_manager
self.mgr = get_android_protect_manager()
self.hw = get_hardware_manager()
self.serial = None
def _pick_device(self):
"""Select an ADB device."""
devices = self.hw.adb_devices()
if not devices:
print(" No ADB devices connected.")
return None
if len(devices) == 1:
self.serial = devices[0]['serial']
return self.serial
print("\n Select device:")
for i, d in enumerate(devices, 1):
model = d.get('model', '')
print(f" {i}) {d['serial']} {model}")
try:
choice = int(input(" > ").strip())
if 1 <= choice <= len(devices):
self.serial = devices[choice - 1]['serial']
return self.serial
except (ValueError, EOFError, KeyboardInterrupt):
pass
return None
def _ensure_device(self):
"""Ensure we have a selected device."""
if self.serial:
return self.serial
return self._pick_device()
def _print_severity(self, sev):
"""Color indicator for severity."""
markers = {
'critical': '[!!!]',
'high': '[!! ]',
'medium': '[! ]',
'low': '[ ]',
}
return markers.get(sev, '[? ]')
def show_menu(self):
status = self.hw.get_status()
serial_str = self.serial or 'None selected'
# Shizuku/Shield info
shizuku_str = 'N/A'
shield_str = 'N/A'
if self.serial:
try:
sz = self.mgr.check_shizuku(self.serial)
if sz['installed']:
shizuku_str = f"{'Running' if sz['running'] else 'Stopped'}"
if sz['version']:
shizuku_str += f" v{sz['version']}"
else:
shizuku_str = 'Not installed'
sh = self.mgr.check_shield_app(self.serial)
shield_str = f"v{sh['version']}" if sh['installed'] else 'Not installed'
except Exception:
pass
sig_stats = self.mgr.get_signature_stats()
print(f"\n{'='*60}")
print(" Android Protection Shield")
print(f"{'='*60}")
print(f" ADB: {'Available' if status['adb'] else 'Not found'}")
print(f" Device: {serial_str}")
print(f" Shizuku: {shizuku_str} | Shield: {shield_str}")
print(f" DB: {sig_stats['stalkerware_packages']} packages, "
f"{sig_stats['government_spyware']} govt spyware")
print()
print(" -- Quick Actions --")
print(" 1) Quick Scan (fast)")
print(" 2) Full Protection Scan")
print(" 3) Export Scan Report")
print()
print(" -- Detection --")
print(" 10) Scan Stalkerware")
print(" 11) Scan Hidden Apps")
print(" 12) Scan Device Admins")
print(" 13) Scan Accessibility Services")
print(" 14) Scan Notification Listeners")
print(" 15) Scan Spyware Indicators (Pegasus/Predator)")
print(" 16) Scan System Integrity")
print(" 17) Scan Suspicious Processes")
print(" 18) Scan Certificates (MITM)")
print(" 19) Scan Network Config")
print(" 20) Scan Developer Options")
print()
print(" -- Permission Analysis --")
print(" 30) Find Dangerous Apps")
print(" 31) Analyze App Permissions")
print(" 32) Permission Heatmap")
print()
print(" -- Remediation --")
print(" 40) Disable Threat")
print(" 41) Uninstall Threat")
print(" 42) Revoke Dangerous Permissions")
print(" 43) Remove Device Admin")
print(" 44) Remove Rogue CA Cert")
print(" 45) Clear Proxy Settings")
print()
print(" -- Shizuku & Shield --")
print(" 50) Shizuku Status")
print(" 51) Install Shizuku")
print(" 52) Start Shizuku Service")
print(" 53) Install Shield App")
print(" 54) Configure Shield")
print(" 55) Grant Shield Permissions")
print()
print(" -- Database --")
print(" 60) Signature Stats")
print(" 61) Update Signatures")
print()
print(" -- Tracking Honeypot --")
print(" 70) Honeypot Status")
print(" 71) Scan Tracker Apps")
print(" 72) Scan Tracker Permissions")
print(" 73) View Ad Tracking Settings")
print()
print(" 74) Reset Advertising ID")
print(" 75) Opt Out of Ad Tracking")
print(" 76) Set Ad-Blocking DNS")
print(" 77) Disable Location Scanning")
print()
print(" 78) Deploy Hosts Blocklist (root)")
print(" 79) Setup Traffic Redirect (root)")
print(" 80) Set Fake Location (root)")
print(" 81) Random Fake Location (root)")
print(" 82) Rotate Device Identity (root)")
print(" 83) Generate Fake Fingerprint (root)")
print()
print(" 84) Activate Honeypot (all tiers)")
print(" 85) Deactivate Honeypot")
print()
print(" 86) Tracker Domain Stats")
print(" 87) Update Tracker Domains")
print()
print(" [s] Select Device")
print(" 0) Back")
print()
# ── Quick Actions ───────────────────────────────────────────────
def do_quick_scan(self):
if not self._ensure_device():
return
print(f"\n Running quick scan on {self.serial}...")
result = self.mgr.quick_scan(self.serial)
summary = result.get('summary', {})
print(f"\n {'='*50}")
print(f" Quick Scan Results")
print(f" {'='*50}")
print(f" Threats found: {summary.get('threats_found', 0)}")
print(f" Stalkerware: {summary.get('stalkerware', 0)}")
print(f" Suspicious admins: {summary.get('suspicious_admins', 0)}")
print(f" Malicious accessibility: {summary.get('malicious_accessibility', 0)}")
found = result.get('stalkerware', {}).get('found', [])
if found:
print(f"\n Stalkerware Detected:")
for f in found:
print(f" {self._print_severity(f['severity'])} {f['name']} ({f['package']})")
print(f" {f['description']}")
def do_full_scan(self):
if not self._ensure_device():
return
print(f"\n Running full protection scan on {self.serial}...")
print(" This may take a few minutes...")
result = self.mgr.full_protection_scan(self.serial)
summary = result.get('summary', {})
print(f"\n {'='*50}")
print(f" Full Scan Results")
print(f" {'='*50}")
print(f" Total threats: {summary.get('threats_found', 0)}")
print(f" System integrity: {summary.get('system_integrity', 'N/A')}")
print(f" Hidden apps: {summary.get('hidden_apps', 0)}")
print(f" Dangerous apps: {summary.get('dangerous_apps', 0)}")
print(f" User CA certs: {summary.get('user_ca_certs', 0)}")
found = result.get('stalkerware', {}).get('found', [])
if found:
print(f"\n Stalkerware:")
for f in found:
print(f" {self._print_severity(f['severity'])} {f['name']} ({f['package']})")
spyware = result.get('spyware_indicators', {}).get('findings', [])
if spyware:
print(f"\n Government Spyware Indicators:")
for s in spyware:
print(f" {self._print_severity(s['severity'])} {s['name']}")
for ind in s.get('indicators_matched', []):
print(f" {ind['type']}: {ind['value']}")
def do_export_report(self):
if not self._ensure_device():
return
print(f"\n Running full scan and exporting...")
scan = self.mgr.full_protection_scan(self.serial)
result = self.mgr.export_scan_report(self.serial, scan)
if result.get('ok'):
print(f" Report saved: {result['path']}")
else:
print(f" Error: {result.get('error', 'Unknown')}")
# ── Detection ───────────────────────────────────────────────────
def do_scan_stalkerware(self):
if not self._ensure_device():
return
print(f"\n Scanning for stalkerware...")
result = self.mgr.scan_stalkerware(self.serial)
if result.get('error'):
print(f" Error: {result['error']}")
return
print(f" Scanned {result['total']} packages, {result['clean_count']} clean")
found = result.get('found', [])
if found:
print(f"\n Found {len(found)} threats:")
for f in found:
print(f" {self._print_severity(f['severity'])} {f['name']}")
print(f" Package: {f['package']}")
print(f" {f['description']}")
else:
print(" No stalkerware detected.")
def do_scan_hidden(self):
if not self._ensure_device():
return
print(f"\n Scanning for hidden apps...")
result = self.mgr.scan_hidden_apps(self.serial)
apps = result.get('hidden_apps', [])
print(f" Found {len(apps)} hidden apps (no launcher icon):")
for app in apps:
print(f" - {app}")
def do_scan_admins(self):
if not self._ensure_device():
return
print(f"\n Scanning device admins...")
result = self.mgr.scan_device_admins(self.serial)
admins = result.get('admins', [])
print(f" Found {len(admins)} device admins:")
for a in admins:
marker = " [SUSPICIOUS]" if a.get('suspicious') else ""
print(f" - {a['package']}{marker}")
def do_scan_accessibility(self):
if not self._ensure_device():
return
print(f"\n Scanning accessibility services...")
result = self.mgr.scan_accessibility_services(self.serial)
services = result.get('services', [])
if not services:
print(" No accessibility services enabled.")
return
for s in services:
status = s.get('status', 'unknown')
marker = {'legitimate': '[OK]', 'malicious': '[BAD]', 'unknown': '[??]'}
print(f" {marker.get(status, '[??]')} {s['package']}")
def do_scan_listeners(self):
if not self._ensure_device():
return
print(f"\n Scanning notification listeners...")
result = self.mgr.scan_notification_listeners(self.serial)
listeners = result.get('listeners', [])
if not listeners:
print(" No notification listeners enabled.")
return
for l in listeners:
marker = " [SUSPICIOUS]" if l.get('suspicious') else ""
print(f" - {l['package']}{marker}")
def do_scan_spyware(self):
if not self._ensure_device():
return
print(f"\n Scanning for government spyware indicators...")
print(" Checking Pegasus, Predator, Hermit, FinSpy, etc...")
result = self.mgr.scan_spyware_indicators(self.serial)
print(f" Checked {result.get('spyware_checked', 0)} spyware families")
findings = result.get('findings', [])
if findings:
print(f"\n ALERT: Found {len(findings)} indicators:")
for f in findings:
print(f" {self._print_severity(f['severity'])} {f['name']}")
print(f" {f.get('description', '')}")
for ind in f.get('indicators_matched', []):
print(f" {ind['type']}: {ind['value']}")
else:
print(" No government spyware indicators found.")
def do_scan_integrity(self):
if not self._ensure_device():
return
print(f"\n Checking system integrity...")
result = self.mgr.scan_system_integrity(self.serial)
print(f" Passed: {result['ok_count']}/{result['total']}")
for name, check in result.get('checks', {}).items():
status = "[OK]" if check['ok'] else "[!!]"
print(f" {status} {check['description']}: {check['value']}")
def do_scan_processes(self):
if not self._ensure_device():
return
print(f"\n Scanning for suspicious processes...")
result = self.mgr.scan_suspicious_processes(self.serial)
findings = result.get('findings', [])
if findings:
print(f" Found {len(findings)} suspicious items:")
for f in findings:
print(f" [{f['severity'].upper()}] {f['type']}: {f['detail']}")
else:
print(" No suspicious processes found.")
def do_scan_certs(self):
if not self._ensure_device():
return
print(f"\n Scanning certificates...")
result = self.mgr.scan_certificates(self.serial)
certs = result.get('certs', [])
if certs:
print(f" Found {len(certs)} user-installed CA certs:")
for c in certs:
print(f" - {c['hash']}: {c['detail']}")
else:
print(" No user-installed CA certificates.")
def do_scan_network(self):
if not self._ensure_device():
return
print(f"\n Scanning network configuration...")
result = self.mgr.scan_network_config(self.serial)
for name, check in result.get('checks', {}).items():
status = "[OK]" if check.get('ok', True) else "[!!]"
desc = check.get('description', name)
print(f" {status} {desc}: {check['value']}")
def do_scan_devopt(self):
if not self._ensure_device():
return
print(f"\n Scanning developer options...")
result = self.mgr.scan_developer_options(self.serial)
for name, check in result.get('checks', {}).items():
marker = "[ON] " if check.get('enabled') else "[OFF]"
print(f" {marker} {check['description']}: {check['value']}")
# ── Permission Analysis ─────────────────────────────────────────
def do_dangerous_apps(self):
if not self._ensure_device():
return
print(f"\n Finding apps with dangerous permission combos...")
print(" This may take a while...")
result = self.mgr.find_dangerous_apps(self.serial)
dangerous = result.get('dangerous', [])
if dangerous:
print(f"\n Found {len(dangerous)} dangerous apps:")
for d in dangerous:
print(f" {self._print_severity(d['severity'])} {d['package']}")
print(f" Pattern: {d['combo']}")
print(f" Perms: {', '.join(d['matched_perms'])}")
else:
print(" No apps with dangerous permission combos found.")
def do_analyze_perms(self):
if not self._ensure_device():
return
try:
package = input(" Package name: ").strip()
except (EOFError, KeyboardInterrupt):
return
if not package:
return
result = self.mgr.analyze_app_permissions(self.serial, package)
if result.get('error'):
print(f" Error: {result['error']}")
return
perms = result.get('permissions', {})
info = result.get('info', {})
print(f"\n {package}")
if info:
for k, v in info.items():
print(f" {k}: {v}")
print(f"\n Granted ({len(perms.get('granted', []))}):")
for p in perms.get('granted', []):
print(f" + {p}")
print(f" Denied ({len(perms.get('denied', []))}):")
for p in perms.get('denied', []):
print(f" - {p}")
def do_perm_heatmap(self):
if not self._ensure_device():
return
print(f"\n Building permission heatmap...")
print(" This scans all non-system apps, may take a while...")
result = self.mgr.permission_heatmap(self.serial)
matrix = result.get('matrix', [])
perm_names = result.get('permission_names', [])
if not matrix:
print(" No apps with dangerous permissions found.")
return
# Print header
short = [p[:8] for p in perm_names]
header = f" {'Package':<35} " + " ".join(f"{s:<8}" for s in short)
print(f"\n{header}")
print(f" {'-'*len(header)}")
for row in matrix[:30]: # Limit display
pkg = row['package'][:34]
perms = row['permissions']
cells = " ".join(
f"{' X ' if perms.get(p) else ' . '}"
for p in perm_names
)
print(f" {pkg:<35} {cells}")
if len(matrix) > 30:
print(f" ... and {len(matrix) - 30} more apps")
# ── Remediation ─────────────────────────────────────────────────
def _get_package_input(self, prompt=" Package to target: "):
try:
return input(prompt).strip()
except (EOFError, KeyboardInterrupt):
return ''
def do_disable(self):
if not self._ensure_device():
return
pkg = self._get_package_input()
if not pkg:
return
result = self.mgr.disable_threat(self.serial, pkg)
if result.get('ok'):
print(f" Disabled: {pkg}")
else:
print(f" Error: {result.get('error', 'Failed')}")
def do_uninstall(self):
if not self._ensure_device():
return
pkg = self._get_package_input()
if not pkg:
return
try:
confirm = input(f" Uninstall {pkg}? (y/N): ").strip().lower()
except (EOFError, KeyboardInterrupt):
return
if confirm != 'y':
print(" Cancelled.")
return
result = self.mgr.uninstall_threat(self.serial, pkg)
if result.get('ok'):
print(f" Uninstalled: {pkg}")
else:
print(f" Error: {result.get('error', 'Failed')}")
def do_revoke(self):
if not self._ensure_device():
return
pkg = self._get_package_input()
if not pkg:
return
result = self.mgr.revoke_dangerous_perms(self.serial, pkg)
print(f" Revoked: {', '.join(result['revoked'])}")
if result['failed']:
print(f" Failed: {', '.join(result['failed'])}")
def do_remove_admin(self):
if not self._ensure_device():
return
pkg = self._get_package_input()
if not pkg:
return
result = self.mgr.remove_device_admin(self.serial, pkg)
if result.get('ok'):
print(f" Removed device admin: {result.get('message', pkg)}")
else:
print(f" Error: {result.get('error', 'Failed')}")
def do_remove_cert(self):
if not self._ensure_device():
return
# List certs first
certs = self.mgr.scan_certificates(self.serial).get('certs', [])
if not certs:
print(" No user CA certs to remove.")
return
print(" User CA certificates:")
for i, c in enumerate(certs, 1):
print(f" {i}) {c['hash']}: {c['detail']}")
try:
choice = int(input(" Remove #: ").strip())
if 1 <= choice <= len(certs):
result = self.mgr.remove_ca_cert(self.serial, certs[choice - 1]['hash'])
if result.get('ok'):
print(f" Removed.")
else:
print(f" Error: {result.get('error')}")
except (ValueError, EOFError, KeyboardInterrupt):
pass
def do_clear_proxy(self):
if not self._ensure_device():
return
result = self.mgr.clear_proxy(self.serial)
for r in result.get('results', []):
status = "OK" if r['ok'] else "FAIL"
print(f" [{status}] {r['setting']}")
# ── Shizuku & Shield ────────────────────────────────────────────
def do_shizuku_status(self):
if not self._ensure_device():
return
result = self.mgr.shizuku_status(self.serial)
print(f"\n Shizuku Status:")
print(f" Installed: {result['installed']}")
print(f" Running: {result.get('running', False)}")
print(f" Version: {result.get('version', 'N/A')}")
def do_install_shizuku(self):
if not self._ensure_device():
return
try:
apk = input(" Shizuku APK path: ").strip()
except (EOFError, KeyboardInterrupt):
return
if not apk:
return
result = self.mgr.install_shizuku(self.serial, apk)
if result.get('ok'):
print(f" {result['message']}")
else:
print(f" Error: {result.get('error')}")
def do_start_shizuku(self):
if not self._ensure_device():
return
result = self.mgr.start_shizuku(self.serial)
if result.get('ok'):
print(f" Shizuku started: {result.get('output', '')}")
else:
print(f" Error: {result.get('error')}")
def do_install_shield(self):
if not self._ensure_device():
return
try:
apk = input(" Shield APK path: ").strip()
except (EOFError, KeyboardInterrupt):
return
if not apk:
return
result = self.mgr.install_shield_app(self.serial, apk)
if result.get('ok'):
print(f" {result['message']}")
else:
print(f" Error: {result.get('error')}")
def do_configure_shield(self):
if not self._ensure_device():
return
print(" Shield Configuration (JSON):")
try:
config_str = input(" > ").strip()
config = json.loads(config_str)
except (EOFError, KeyboardInterrupt):
return
except json.JSONDecodeError:
print(" Invalid JSON.")
return
result = self.mgr.configure_shield(self.serial, config)
if result.get('ok'):
print(f" Config sent: {result.get('output', '')}")
else:
print(f" Error: {result.get('output', 'Failed')}")
def do_grant_shield_perms(self):
if not self._ensure_device():
return
result = self.mgr.grant_shield_permissions(self.serial)
for p in result.get('granted', []):
print(f" [OK] {p}")
for f in result.get('failed', []):
print(f" [!!] {f['perm']}: {f['error']}")
# ── Tracking Honeypot ─────────────────────────────────────────
def do_honeypot_status(self):
if not self._ensure_device():
return
print(f"\n Checking honeypot status...")
result = self.mgr.honeypot_status(self.serial)
print(f"\n Honeypot Status:")
print(f" Active: {result.get('active', False)}")
print(f" Tier: {result.get('tier', 0)}")
print(f" Ad tracking: {'limited' if result.get('ad_tracking_limited') else 'not limited'}")
print(f" Private DNS: {result.get('private_dns_mode', 'off')}")
if result.get('private_dns_host'):
print(f" DNS host: {result['private_dns_host']}")
protections = result.get('protections', {})
if protections:
print(f" Protections:")
for k, v in protections.items():
print(f" {k}: {v}")
def do_scan_tracker_apps(self):
if not self._ensure_device():
return
print(f"\n Scanning for tracker apps...")
result = self.mgr.scan_tracker_apps(self.serial)
if result.get('error'):
print(f" Error: {result['error']}")
return
found = result.get('found', [])
print(f" Found {len(found)} tracker packages out of {result.get('total', 0)} installed:")
for pkg in found:
print(f" - {pkg}")
if not found:
print(" No known tracker apps found.")
def do_scan_tracker_perms(self):
if not self._ensure_device():
return
print(f"\n Scanning for tracking permissions...")
result = self.mgr.scan_tracker_permissions(self.serial)
apps = result.get('apps', [])
if apps:
print(f" {len(apps)} apps have tracking permissions:")
for app in apps[:30]:
print(f" {app['package']}: {', '.join(app['permissions'])}")
if len(apps) > 30:
print(f" ... and {len(apps) - 30} more")
else:
print(" No apps with tracking permissions found.")
def do_ad_settings(self):
if not self._ensure_device():
return
print(f"\n Ad Tracking Settings:")
result = self.mgr.get_tracking_settings(self.serial)
for name, info in result.items():
print(f" {info.get('description', name)}: {info['value']}")
def do_reset_ad_id(self):
if not self._ensure_device():
return
result = self.mgr.reset_advertising_id(self.serial)
if result.get('ok'):
print(f" {result['message']}")
else:
print(f" Error: {result.get('error', 'Failed')}")
def do_opt_out_tracking(self):
if not self._ensure_device():
return
result = self.mgr.opt_out_ad_tracking(self.serial)
if result.get('ok'):
print(f" {result['message']}")
else:
print(f" Error: {result.get('error', 'Failed')}")
def do_set_dns(self):
if not self._ensure_device():
return
print(" Available DNS providers:")
db = self.mgr._load_tracker_domains()
providers = db.get('dns_providers', {})
for name, info in providers.items():
print(f" {name}: {info.get('description', info.get('hostname', ''))}")
try:
provider = input(" Provider name: ").strip()
except (EOFError, KeyboardInterrupt):
return
if not provider:
return
result = self.mgr.set_private_dns(self.serial, provider)
if result.get('ok'):
print(f" {result['message']}")
else:
print(f" Error: {result.get('error', 'Failed')}")
def do_disable_location(self):
if not self._ensure_device():
return
result = self.mgr.disable_location_accuracy(self.serial)
if result.get('ok'):
print(" WiFi and Bluetooth scanning disabled.")
else:
print(" Some settings failed:")
for r in result.get('results', []):
status = "OK" if r['ok'] else "FAIL"
print(f" [{status}] {r['setting']}")
def do_deploy_hosts(self):
if not self._ensure_device():
return
print(" Deploying hosts blocklist (requires root)...")
result = self.mgr.deploy_hosts_blocklist(self.serial)
if result.get('ok'):
print(f" {result['message']}")
else:
print(f" Error: {result.get('error', 'Failed')}")
def do_setup_iptables(self):
if not self._ensure_device():
return
try:
port_str = input(" Redirect port [9040]: ").strip()
except (EOFError, KeyboardInterrupt):
return
port = int(port_str) if port_str else 9040
result = self.mgr.setup_iptables_redirect(self.serial, port)
if result.get('ok'):
print(f" {result['message']}")
else:
print(f" Error: {result.get('error', 'Failed')}")
def do_set_fake_location(self):
if not self._ensure_device():
return
try:
lat = float(input(" Latitude: ").strip())
lon = float(input(" Longitude: ").strip())
except (ValueError, EOFError, KeyboardInterrupt):
print(" Invalid coordinates.")
return
result = self.mgr.set_fake_location(self.serial, lat, lon)
if result.get('ok'):
print(f" {result['message']}")
else:
print(f" Error: {result.get('error', 'Failed')}")
def do_random_location(self):
if not self._ensure_device():
return
result = self.mgr.set_random_fake_location(self.serial)
if result.get('ok'):
print(f" {result['message']}")
if result.get('location_name'):
print(f" Location: {result['location_name']}")
else:
print(f" Error: {result.get('error', 'Failed')}")
def do_rotate_identity(self):
if not self._ensure_device():
return
result = self.mgr.rotate_device_identity(self.serial)
if result.get('ok'):
print(f" {result['message']}")
for c in result.get('changes', []):
status = "OK" if c['ok'] else "FAIL"
print(f" [{status}] {c['setting']}: {c['value']}")
else:
print(f" Error: {result.get('error', 'Failed')}")
def do_fake_fingerprint(self):
if not self._ensure_device():
return
result = self.mgr.generate_fake_fingerprint(self.serial)
if result.get('ok'):
print(f" {result['message']}")
else:
print(f" Error: {result.get('error', 'Failed')}")
def do_activate_honeypot(self):
if not self._ensure_device():
return
print(" Select protection tier:")
print(" 1) ADB only (no root)")
print(" 2) ADB + Shizuku")
print(" 3) Full (ADB + Shizuku + Root)")
try:
tier = int(input(" Tier [1]: ").strip() or '1')
except (ValueError, EOFError, KeyboardInterrupt):
return
if tier not in (1, 2, 3):
print(" Invalid tier.")
return
print(f"\n Activating Tier {tier} honeypot...")
result = self.mgr.honeypot_activate(self.serial, tier)
print(f" {result.get('summary', 'Done')}")
for action in result.get('actions', []):
r = action['result']
status = "OK" if r.get('ok', False) else "FAIL"
msg = r.get('message', r.get('error', ''))
print(f" [{status}] {action['name']}: {msg}")
def do_deactivate_honeypot(self):
if not self._ensure_device():
return
print(" Deactivating honeypot...")
result = self.mgr.honeypot_deactivate(self.serial)
for action in result.get('actions', []):
r = action['result']
status = "OK" if r.get('ok', False) else "FAIL"
print(f" [{status}] {action['name']}")
print(" Honeypot deactivated.")
def do_tracker_stats(self):
stats = self.mgr.get_tracker_stats()
print(f"\n Tracker Domain Database:")
print(f" Version: {stats['version']}")
print(f" Total domains: {stats['total_domains']}")
print(f" Companies: {stats['companies']}")
print(f" Tracker pkgs: {stats['packages']}")
print(f" DNS providers: {', '.join(stats.get('dns_providers', []))}")
print(f" Categories:")
for cat, count in stats.get('categories', {}).items():
print(f" {cat}: {count} domains")
def do_update_trackers(self):
print(" Updating tracker domains...")
result = self.mgr.update_tracker_domains()
if result.get('ok'):
print(f" Updated: merged {result['merged']} new domains")
else:
print(f" Error: {result.get('error')}")
# ── Database ────────────────────────────────────────────────────
def do_sig_stats(self):
stats = self.mgr.get_signature_stats()
print(f"\n Signature Database Stats:")
print(f" Version: {stats['version']}")
print(f" Last updated: {stats['last_updated']}")
print(f" Stalkerware families: {stats['stalkerware_families']}")
print(f" Stalkerware packages: {stats['stalkerware_packages']}")
print(f" Government spyware: {stats['government_spyware']}")
print(f" Permission combos: {stats['permission_combos']}")
def do_update_sigs(self):
print(" Updating signatures from GitHub...")
result = self.mgr.update_signatures()
if result.get('ok'):
print(f" Updated: merged {result['merged']} new packages")
else:
print(f" Error: {result.get('error')}")
# ── Main Loop ───────────────────────────────────────────────────
def run_interactive(self):
import json
while True:
self.show_menu()
try:
choice = input(" Select > ").strip()
except (EOFError, KeyboardInterrupt):
break
if choice == '0':
break
actions = {
'1': self.do_quick_scan,
'2': self.do_full_scan,
'3': self.do_export_report,
'10': self.do_scan_stalkerware,
'11': self.do_scan_hidden,
'12': self.do_scan_admins,
'13': self.do_scan_accessibility,
'14': self.do_scan_listeners,
'15': self.do_scan_spyware,
'16': self.do_scan_integrity,
'17': self.do_scan_processes,
'18': self.do_scan_certs,
'19': self.do_scan_network,
'20': self.do_scan_devopt,
'30': self.do_dangerous_apps,
'31': self.do_analyze_perms,
'32': self.do_perm_heatmap,
'40': self.do_disable,
'41': self.do_uninstall,
'42': self.do_revoke,
'43': self.do_remove_admin,
'44': self.do_remove_cert,
'45': self.do_clear_proxy,
'50': self.do_shizuku_status,
'51': self.do_install_shizuku,
'52': self.do_start_shizuku,
'53': self.do_install_shield,
'54': self.do_configure_shield,
'55': self.do_grant_shield_perms,
'60': self.do_sig_stats,
'61': self.do_update_sigs,
'70': self.do_honeypot_status,
'71': self.do_scan_tracker_apps,
'72': self.do_scan_tracker_perms,
'73': self.do_ad_settings,
'74': self.do_reset_ad_id,
'75': self.do_opt_out_tracking,
'76': self.do_set_dns,
'77': self.do_disable_location,
'78': self.do_deploy_hosts,
'79': self.do_setup_iptables,
'80': self.do_set_fake_location,
'81': self.do_random_location,
'82': self.do_rotate_identity,
'83': self.do_fake_fingerprint,
'84': self.do_activate_honeypot,
'85': self.do_deactivate_honeypot,
'86': self.do_tracker_stats,
'87': self.do_update_trackers,
's': self._pick_device,
}
action = actions.get(choice)
if action:
action()
else:
print(" Invalid choice.")
def run():
ap = AndroidProtect()
ap.run_interactive()

View File

@@ -0,0 +1,221 @@
"""
Android Device Reconnaissance - Extract device data, accounts, messages, history
"""
DESCRIPTION = "Android device reconnaissance (data extraction, accounts, logs)"
AUTHOR = "AUTARCH"
VERSION = "1.0"
CATEGORY = "offense"
import sys
from pathlib import Path
sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
class AndroidRecon:
"""Interactive menu for Android device reconnaissance."""
def __init__(self):
from core.android_exploit import get_exploit_manager
from core.hardware import get_hardware_manager
self.mgr = get_exploit_manager()
self.hw = get_hardware_manager()
self.serial = None
def _select_device(self):
devices = self.hw.adb_devices()
if not devices:
print(" No ADB devices connected.")
return
if len(devices) == 1:
self.serial = devices[0]['serial']
print(f" Selected: {self.serial}")
return
print("\n Select device:")
for i, d in enumerate(devices, 1):
model = d.get('model', '')
print(f" {i}) {d['serial']} {model}")
try:
choice = int(input(" > ").strip())
if 1 <= choice <= len(devices):
self.serial = devices[choice - 1]['serial']
except (ValueError, EOFError, KeyboardInterrupt):
pass
def _ensure_device(self):
if not self.serial:
self._select_device()
return self.serial is not None
def show_menu(self):
print(f"\n{'='*50}")
print(" Device Reconnaissance")
print(f"{'='*50}")
print(f" Device: {self.serial or '(none)'}")
print()
print(" [1] Full Device Dump")
print(" [2] Installed Accounts")
print(" [3] WiFi Passwords [ROOT]")
print(" [4] Call Logs")
print(" [5] SMS Messages")
print(" [6] Contacts")
print(" [7] Browser History [ROOT]")
print(" [8] Saved Credentials [ROOT]")
print(" [9] Export Full Report")
print(" [s] Select Device")
print(" [0] Back")
print()
def device_dump(self):
if not self._ensure_device():
return
print(" Running full device dump...")
dump = self.mgr.full_device_dump(self.serial)
print(f"\n SELinux: {dump.get('selinux', 'unknown')}")
print(f" Kernel: {dump.get('kernel', 'unknown')}")
print(f" Fingerprint: {dump.get('fingerprint', 'unknown')}")
print(f" Packages: {dump.get('package_count', '?')}")
info = dump.get('device_info', {})
if info:
print(f"\n Device Info:")
for k, v in info.items():
print(f" {k:<20} {v}")
def accounts(self):
if not self._ensure_device():
return
result = self.mgr.get_accounts(self.serial)
if not result['success']:
print(f" Error: {result.get('error', 'Failed')}")
return
print(f"\n Found {result['count']} accounts:")
for a in result['accounts']:
print(f" {a['name']} ({a['type']})")
def wifi_passwords(self):
if not self._ensure_device():
return
print(" Extracting WiFi passwords (requires root)...")
result = self.mgr.get_wifi_passwords(self.serial)
if not result['success']:
print(f" Error: {result.get('error', 'Failed')}")
return
print(f"\n Found {result['count']} saved networks:")
for w in result['passwords']:
print(f" SSID: {w['ssid']}")
print(f" PSK: {w['password']}")
print()
def call_logs(self):
if not self._ensure_device():
return
result = self.mgr.extract_call_logs(self.serial)
if not result['success']:
print(f" Error: {result.get('error', 'Failed')}")
return
print(f"\n Found {result['count']} call log entries:")
print(f" {'Number':<20} {'Type':<12} {'Duration'}")
print(f" {'-'*50}")
for c in result['calls'][:50]:
print(f" {c.get('number','?'):<20} {c.get('type_label','?'):<12} {c.get('duration','?')}s")
def sms_messages(self):
if not self._ensure_device():
return
result = self.mgr.extract_sms(self.serial)
if not result['success']:
print(f" Error: {result.get('error', 'Failed')}")
return
print(f"\n Found {result['count']} SMS messages:")
for m in result['messages'][:30]:
print(f"\n [{m.get('type_label','?')}] {m.get('address','?')}")
body = m.get('body', '')
if len(body) > 100:
body = body[:100] + '...'
print(f" {body}")
def contacts(self):
if not self._ensure_device():
return
result = self.mgr.extract_contacts(self.serial)
if not result['success']:
print(f" Error: {result.get('error', 'Failed')}")
return
print(f"\n Found {result['count']} contacts:")
print(f" {'Name':<25} {'Number'}")
print(f" {'-'*45}")
for c in result['contacts']:
print(f" {c.get('display_name','?'):<25} {c.get('number','?')}")
def browser_history(self):
if not self._ensure_device():
return
print(" Extracting browser history (requires root)...")
result = self.mgr.extract_browser_history(self.serial)
if not result['success']:
print(f" Error: {result.get('error', 'Failed')}")
return
print(f"\n Found {result['count']} history entries:")
for h in result['history'][:30]:
title = h.get('title', '')[:50]
print(f" {title}")
print(f" {h['url']}")
def saved_credentials(self):
if not self._ensure_device():
return
print(" Extracting saved credentials (requires root)...")
result = self.mgr.extract_saved_credentials(self.serial)
if not result['success']:
print(f" Error: {result.get('error', 'Failed')}")
return
print(f"\n Found {result['count']} saved credentials:")
for c in result['credentials']:
print(f" URL: {c['url']}")
print(f" User: {c['username']}")
print(f" Pass: {'[encrypted]' if c['password_encrypted'] else '[empty]'}")
print()
def export_report(self):
if not self._ensure_device():
return
print(" Generating full recon report...")
result = self.mgr.export_recon_report(self.serial)
if result['success']:
print(f" Report saved: {result['report_path']}")
print(f" Sections: {', '.join(result['sections'])}")
else:
print(f" Error: {result.get('error', 'Failed')}")
def run_interactive(self):
while True:
self.show_menu()
try:
choice = input(" Select > ").strip().lower()
except (EOFError, KeyboardInterrupt):
break
actions = {
'0': None,
'1': self.device_dump,
'2': self.accounts,
'3': self.wifi_passwords,
'4': self.call_logs,
'5': self.sms_messages,
'6': self.contacts,
'7': self.browser_history,
'8': self.saved_credentials,
'9': self.export_report,
's': self._select_device,
}
if choice == '0':
break
action = actions.get(choice)
if action:
action()
else:
print(" Invalid choice.")
def run():
m = AndroidRecon()
m.run_interactive()

Some files were not shown because too many files have changed in this diff Show More