Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: greatscottgadgets/facedancer
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 3.0.2
Choose a base ref
...
head repository: greatscottgadgets/facedancer
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: main
Choose a head ref

Commits on Jul 20, 2024

  1. Add Hydradancer backend

    kauwua committed Jul 20, 2024
    Copy the full SHA
    5567751 View commit details
  2. Copy the full SHA
    371b2b2 View commit details
  3. Simplify data ep handling

    kauwua committed Jul 20, 2024
    Copy the full SHA
    2aae14e View commit details
  4. Handle new status structure

    kauwua committed Jul 20, 2024
    Copy the full SHA
    06fbb53 View commit details
  5. Copy the full SHA
    b6b6b55 View commit details
  6. Handle bus reset

    kauwua committed Jul 20, 2024
    Copy the full SHA
    0431942 View commit details
  7. Copy the full SHA
    df2aefc View commit details
  8. Copy the full SHA
    2a1326e View commit details
  9. Copy the full SHA
    03d38a0 View commit details
  10. Copy the full SHA
    09fe3eb View commit details
  11. Copy the full SHA
    9492a9e View commit details
  12. Copy the full SHA
    d21ebae View commit details
  13. Copy the full SHA
    415c439 View commit details
  14. Copy the full SHA
    7dd172f View commit details
  15. Copy the full SHA
    22d625a View commit details
  16. Fix function description

    kauwua committed Jul 20, 2024
    Copy the full SHA
    84d1496 View commit details
  17. Change speed handling

    kauwua committed Jul 20, 2024
    Copy the full SHA
    d6f9e44 View commit details
  18. Change event system, use NAKs + buffer state to sync, remove unnecess…

    …ary bus reset cleanup
    kauwua committed Jul 20, 2024
    Copy the full SHA
    56996ac View commit details
  19. Improve NAK handling

    kauwua committed Jul 20, 2024
    Copy the full SHA
    d33d057 View commit details
  20. Copy the full SHA
    9080438 View commit details
  21. Copy the full SHA
    a5b8021 View commit details
  22. Copy the full SHA
    b53d24e View commit details
  23. pylint pass

    kauwua committed Jul 20, 2024
    Copy the full SHA
    2d5c9a2 View commit details
  24. Match backend template

    kauwua committed Jul 20, 2024
    Copy the full SHA
    fc3b38d View commit details
  25. Add more type annotations

    kauwua committed Jul 20, 2024
    Copy the full SHA
    0613c80 View commit details
  26. Copy the full SHA
    bd50623 View commit details
  27. cleanup

    kauwua committed Jul 20, 2024
    Copy the full SHA
    255b2af View commit details
  28. Copy the full SHA
    88c5f9e View commit details
  29. Copy the full SHA
    76ffce4 View commit details
  30. Copy the full SHA
    eec104a View commit details
  31. Update README.md

    Fix Typo and add note about the fact FaceDancer does not works on Windows but only GNU/Linux
    bvernoux authored and kauwua committed Jul 20, 2024
    Copy the full SHA
    8fef024 View commit details
  32. Copy the full SHA
    c281d00 View commit details
  33. Copy the full SHA
    7753b71 View commit details

Commits on Aug 22, 2024

  1. Copy the full SHA
    7058217 View commit details

Commits on Aug 25, 2024

  1. Copy the full SHA
    6d1b1d1 View commit details
  2. Allow supported_languages = None

    This replies to LANGID (string descriptor zero) requests with a stall
    which is appropriate for devices that do not implement string
    descriptors.
    
    The spec specifically says "USB devices that omit all string descriptors
    must not return an array of LANGID codes." Whether that is a stall or an
    empty LANGID array appears to be open to interpretation. With this
    change we can either stall (with None) or return an empty array (with an
    empty tuple).
    mossmann committed Aug 25, 2024
    Copy the full SHA
    f4be389 View commit details

Commits on Aug 26, 2024

  1. Merge pull request #109 from mossmann/fix-device-descriptor

    Correct byte order of bcdUSB and bcdDevice
    antoinevg authored Aug 26, 2024
    Copy the full SHA
    9052b04 View commit details
  2. Merge pull request #112 from mossmann/string-by-index

    Support specification of string descriptor index
    antoinevg authored Aug 26, 2024
    Copy the full SHA
    f83bf3f View commit details
  3. Merge pull request #93 from HydraDancer/hydradancer

    New Hydradancer backend for Facedancer
    antoinevg authored Aug 26, 2024
    Copy the full SHA
    fc4f06c View commit details
  4. Copy the full SHA
    e0e491a View commit details
  5. Copy the full SHA
    47912e6 View commit details

Commits on Aug 28, 2024

  1. backend: add a new base method for facedancer backends 'send_on_contr…

    …ol_endpoint'
    
    If it is not implemented on a backend it will simply fall back to 'send_on_endpoint'.
    antoinevg committed Aug 28, 2024
    Copy the full SHA
    165f227 View commit details
  2. Copy the full SHA
    75fe0c3 View commit details
  3. Copy the full SHA
    50cdd94 View commit details

Commits on Aug 29, 2024

  1. Copy the full SHA
    b0f4855 View commit details

Commits on Sep 6, 2024

  1. Copy the full SHA
    820f9da View commit details

Commits on Sep 16, 2024

  1. Merge pull request #116 from HydraDancer/fix/switch_to_log

    Fix log function in handle_set_interface_request
    antoinevg authored Sep 16, 2024
    Copy the full SHA
    57d76f2 View commit details
  2. Merge pull request #106 from antoinevg/antoinevg/better-usbproxy

    Improve USBProxy reliability
    antoinevg authored Sep 16, 2024
    Copy the full SHA
    7314d29 View commit details
  3. Merge pull request #115 from antoinevg/antoinevg/fix-facedancer-zlp-bug

    Fix ZLP bug on CONTROL IN transfers
    antoinevg authored Sep 16, 2024
    Copy the full SHA
    b4defce View commit details

Commits on Sep 19, 2024

  1. Copy the full SHA
    cfb3d58 View commit details
68 changes: 67 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -9,6 +9,67 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
-->

## [3.1.0] - 2025-01-08
> This is a breaking release which may require updates to your usage of Facedancer API's.
### Changed
* Dropped support for Python 3.8 and 3.9. The minimum supported Python version is now Python 3.10.
* The descriptor API has been changed and expanded to handle more complex device definitions:
- New USBDescriptor property: `include_in_config`, which specifies whether the descriptor should be included in a GET_CONFIGURATION response.
- Descriptors attached to endpoints are now instantiated (replaces #139)
- The `instantiate_subordinates` function is redesigned to avoid silent dropping of subordinates with duplicate identifiers.
- Orderings of declaration/insertion of subordinates are preserved, allowing control of ordering in binary configurations.
- Fixes to convert some fields to the right types in `from_binary_descriptor` methods.
- A dictionary of known strings and their indexes may be passed to `from_binary_descriptor` methods.
- The `number` field of `USBDescriptor` is made optional, as it is not required for descriptors attached in a configuration.
- The `type_number` field will now be inferred from the `raw` bytes if not otherwise specified.
- Add `@include_in_config` and `@requestable(number=N)` decorators for use on declared descriptor classes.
- Add docstrings for all `USBDescriptor` fields.
- More information: #126 #141

### Fixed
* USBProxy errors after changes for alternate interface settings.

### Added
* Round-trip support for creating Facedancer devices, configurations, interfaces, endpoints and descriptors from binary data to objects, to code, to objects and back to binary data.
* New backend method: `validate_configuration` for rejecting USB device configurations that are not supported by a given backend.



## [3.0.6] - 2024-11-27
### Fixed
* Updated Keyboard device / rubber-ducky to work with new descriptor handling features.

## [3.0.5] - 2024-11-25
### Added
* Support switching between alternate interface settings.
* Improved Facedancer descriptor functionality.
* Log a warning when Moondancer needs system permissions for the interface.
* Group Facedancer request handler suggestions by their recipients.
* Implement the `raw` field in `HIDReportDescriptor`. (tx @jalmeroth!)
### Fixed
* Moondancer: Only prime control endpoints on receipt of a setup packet.
* Moondancer: Use `ep_out_interface_enable` instead of `ep_out_prime_endpoint` where appropriate.

## [3.0.4] - 2024-10-10
### Added
* Example: `examples/coroutine.py` demonstrates how to create a custom main function and the use of coroutines.
* Keyboard shortcut: `Ctrl-C` will now gracefully exit a Facedancer emulation.

## [3.0.3] - 2024-09-19
### Added
* Support for specifying string descriptor indices.
* Allow `supported_languages = None` for device definitions.
* Provide an error message when device claim/release fails.
* New backend method: `clear_halt()`
* New backend method: `send_on_control_endpoint()`
* [HydraDancer](https://github.com/HydraDancer) backend. (tx @kauwua!)
### Fixed
* Correct byteorder for bcdUSB and bcdDevice.
* Older facedancer backends were not derived from `FacedancerBackend`.
* Log message in `handle_set_interface_request` was using the incorrect logging method. (tx @kawua!)


## [3.0.2] - 2024-08-20
### Changed
* Added support for Cynthion on Windows.
@@ -57,7 +118,12 @@ Any future bug-fixes or backports to Facedancer `2.9.x` should use the [`v2.9.x
- The current Facedancer core will be supersed by the implementation in `future/` with the `v3.0` release.


[Unreleased]: https://github.com/greatscottgadgets/facedancer/compare/3.0.2...HEAD
[Unreleased]: https://github.com/greatscottgadgets/facedancer/compare/3.1.0...HEAD
[3.1.0]: https://github.com/greatscottgadgets/facedancer/compare/3.0.6...3.1.0
[3.0.6]: https://github.com/greatscottgadgets/facedancer/compare/3.0.5...3.0.6
[3.0.5]: https://github.com/greatscottgadgets/facedancer/compare/3.0.4...3.0.5
[3.0.4]: https://github.com/greatscottgadgets/facedancer/compare/3.0.3...3.0.4
[3.0.3]: https://github.com/greatscottgadgets/facedancer/compare/3.0.2...3.0.3
[3.0.2]: https://github.com/greatscottgadgets/facedancer/compare/3.0.1...3.0.2
[3.0.1]: https://github.com/greatscottgadgets/facedancer/compare/3.0.0...3.0.1
[3.0.0]: https://github.com/greatscottgadgets/facedancer/compare/2.9.0...3.0.0
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -99,15 +99,19 @@ export BACKEND=greatfet
* The CCCamp 2015 rad1o badge with GreatFET l0adable (```BACKEND=greatfet```)
* All GoodFET-based Facedancers, including the common Facedancer21 (```BACKEND=goodfet```)
* RPi + Max3241 Raspdancer boards (```BACKEND=raspdancer```)
* HydraDancer and HydraUSB3 boards (```BACKEND=hydradancer```)

Note that hardware restrictions prevent the MAX3420/MAX3421 boards from emulating
more complex devices -- there's limitation on the number/type of endpoints that can be
set up. The LPC4330 boards -- such as the GreatFET -- have fewer limitations.

For a similar reason, the MAX3420/MAX3421 boards (`BACKEND=goodfet` or `BACKEND=raspdancer`)
currently cannot be used as USBProxy-nv MITM devices. All modern boards (`BACKEND=greatfet`)
currently cannot be used as USBProxy-nv MITM devices. All modern boards (`BACKEND=greatfet`, `BACKEND=hydradancer`)
should be fully functional.

Note that the HydraDancer and HydraUSB3 boards (`BACKEND=hydradancer`) do not currently support host-mode.
Note actual FaceDancer 3.0 does not work on Windows(some issues in pyusb...) and only GNU/Linux

## What boards could be supported soon?

* Any Linux computer with gadgetfs support (e.g. the Pi Zero or Beaglebone Black)
2 changes: 1 addition & 1 deletion docs/requirements.txt
Original file line number Diff line number Diff line change
@@ -3,7 +3,7 @@ sphinx==7.2.6
sphinx_rtd_theme==2.0.0
sphinxcontrib-apidoc
readthedocs-sphinx-search==0.3.2
jinja2==3.1.4
jinja2==3.1.5

# needed to build api docs
facedancer @ git+https://github.com/greatscottgadgets/facedancer
66 changes: 66 additions & 0 deletions examples/coroutine.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
#!/usr/bin/env python3
# pylint: disable=unused-wildcard-import, wildcard-import
#
# This file is part of Facedancer.
#

import asyncio
import sys

from facedancer import *
from facedancer.errors import EndEmulation
from facedancer.logging import configure_default_logging, log

from minimal import MyDevice


async def my_exit_handler(bindkey: bytes):
"""A custom exit handler that will gracefully shut down the
emulation when the user presses the given key combination.
"""
import platform
if platform.system() == "Windows":
import msvcrt
def get_key():
key = msvcrt.getch()
# check for, and propagate Control-C
if key == b'\x03':
raise KeyboardInterrupt
return key
else:
import termios, tty
def get_key():
fd = sys.stdin.fileno()
restore = termios.tcgetattr(fd)
try:
tty.setcbreak(fd)
key = sys.stdin.read(1)
finally:
termios.tcsetattr(fd, termios.TCSADRAIN, restore)
return str.encode(key)

while True:
key = get_key()
if key == bindkey:
raise EndEmulation("User quit the emulation.")
await asyncio.sleep(0)


def my_main_function(device, *coroutines):
"""
A custom main function for emulating a Facedancer device.
"""

# Set up our logging output.
configure_default_logging(level=20)

# Add a custom exit handler to our coroutines.
coroutines = (*coroutines, my_exit_handler(b'\x05'))

# Run the relevant code, along with any added coroutines.
log.info("Starting emulation, press 'Control-E' to disconnect and exit.")
device.emulate(*coroutines)


if __name__ == "__main__":
my_main_function(MyDevice())
3 changes: 2 additions & 1 deletion examples/minimal.py
Original file line number Diff line number Diff line change
@@ -51,4 +51,5 @@ def my_out_vendor_request_handler(self: USBDevice, request: USBControlRequest):
request.ack()


main(MyDevice)
if __name__ == "__main__":
main(MyDevice)
8 changes: 4 additions & 4 deletions examples/template.py
Original file line number Diff line number Diff line change
@@ -56,12 +56,12 @@ class TemplateDevice(USBDevice):
supported_languages : tuple = (LanguageIDs.ENGLISH_US,)

# The revision of the device hardware. This doesn't matter to the USB specification,
# but it's sometimes read by drivers.
device_revision : int = 0
# but it's sometimes read by drivers. 0x0001 represents "0.1" in BCD.
device_revision : int = 0x0001

# The revision of the USB specification that this device adheres to.
# Typically, you'll leave this at '2'.
usb_spec_version : int = 0x0002
# Typically, you'll leave this at 0x0200 which represents "2.0" in BCD.
usb_spec_version : int = 0x0200


#
7 changes: 4 additions & 3 deletions facedancer/__init__.py
Original file line number Diff line number Diff line change
@@ -3,7 +3,7 @@
from .configuration import USBConfiguration
from .interface import USBInterface
from .endpoint import USBEndpoint
from .descriptor import USBDescriptor, USBClassDescriptor, USBDescriptorTypeNumber
from .descriptor import USBDescriptor, USBClassDescriptor, USBDescriptorTypeNumber, StringRef

# Control request handlers.
from .request import standard_request_handler, class_request_handler, vendor_request_handler
@@ -17,7 +17,8 @@
from .types import DeviceSpeed

# Decorators.
from .magic import use_automatically, use_inner_classes_automatically
from .magic import use_automatically, use_inner_classes_automatically
from .descriptor import include_in_config, requestable

# Alias objects to make them easier to import.
from .backends import *
@@ -33,5 +34,5 @@
'USBDirection', 'USBTransferType', 'USBUsageType', 'USBSynchronizationType',
'USBRequestType', 'USBRequestRecipient', 'USBStandardRequests', 'LanguageIDs',
'DeviceSpeed', 'use_automatically', 'use_inner_classes_automatically',
'USBControlRequest',
'USBControlRequest', 'include_in_config', 'requestable', 'StringRef',
]
7 changes: 5 additions & 2 deletions facedancer/backends/MAXUSBApp.py
Original file line number Diff line number Diff line change
@@ -6,7 +6,10 @@

from ..core import FacedancerApp

class MAXUSBApp(FacedancerApp):
from .base import FacedancerBackend


class MAXUSBApp(FacedancerApp, FacedancerBackend):
app_name = "MAXUSB"

reg_ep0_fifo = 0x00
@@ -229,8 +232,8 @@ def configured(self, configuration):
Args:
configuration : The configuration applied by the SET_CONFIG request.
"""
self.validate_configuration(configuration)

# For the MAXUSB case, we don't need to do anything, though it might
# be nice to print a message or store the active configuration for
# use by the USBDevice, etc. etc.
pass
1 change: 1 addition & 0 deletions facedancer/backends/__init__.py
Original file line number Diff line number Diff line change
@@ -6,4 +6,5 @@
"greathost",
"libusbhost",
"moondancer",
"hydradancer"
]
55 changes: 55 additions & 0 deletions facedancer/backends/base.py
Original file line number Diff line number Diff line change
@@ -93,6 +93,21 @@ def read_from_endpoint(self, endpoint_number: int) -> bytes:
raise NotImplementedError


def send_on_control_endpoint(self, endpoint_number: int, in_request: USBControlRequest, data: bytes, blocking: bool=True):
"""
Sends a collection of USB data in response to a IN control request by the host.
Args:
endpoint_number : The number of the IN endpoint on which data should be sent.
in_request : The control request being responded to.
data : The data to be sent.
blocking : If true, this function should wait for the transfer to complete.
"""
# Truncate data to requested length and forward to `send_on_endpoint()` for backends
# that do not need to support this method.
return self.send_on_endpoint(endpoint_number, data[:in_request.length], blocking)


def send_on_endpoint(self, endpoint_number: int, data: bytes, blocking: bool=True):
"""
Sends a collection of USB data on a given endpoint.
@@ -130,9 +145,49 @@ def stall_endpoint(self, endpoint_number:int, direction: USBDirection=USBDirecti
raise NotImplementedError


def clear_halt(self, endpoint_number:int, direction: USBDirection):
""" Clears a halt condition on the provided non-control endpoint.
Args:
endpoint_number : The endpoint number
direction : The endpoint direction; or OUT if not provided.
"""
# FIXME do nothing as only the moondancer backend supports this for now
# raise NotImplementedError
pass


def service_irqs(self):
"""
Core routine of the Facedancer execution/event loop. Continuously monitors the
Facedancer's execution status, and reacts as events occur.
"""
raise NotImplementedError


def validate_configuration(self, configuration: USBConfiguration):
"""
Check if this backend is able to support this configuration.
Raises an exception if it is not.
Args:
configuration : The configuration to validate.
"""
if configuration is None:
return

# Currently, endpoints are only set up in the configured() method, and
# cannot be changed on the fly by SET_INTERFACE requests.
#
# Therefore, no backends are able to support configurations which
# re-use endpoint addresses between alternate interface settings.
used_addresses = set()
for interface in configuration.get_interfaces():
for endpoint in interface.get_endpoints():
address = endpoint.get_identifier()
if address in used_addresses:
raise Exception(
f"This configuration cannot currently be supported, "
f"because it re-uses endpoint address 0x{address:02X} "
f"between multiple interface definitions.")
used_addresses.add(address)
5 changes: 4 additions & 1 deletion facedancer/backends/greatdancer.py
Original file line number Diff line number Diff line change
@@ -10,8 +10,10 @@

from ..logging import log

from .base import FacedancerBackend

class GreatDancerApp(FacedancerApp):

class GreatDancerApp(FacedancerApp, FacedancerBackend):
"""
Backend for using GreatFET devices as Facedancers.
"""
@@ -761,6 +763,7 @@ def configured(self, configuration):
Args:
configuration: The configuration applied by the SET_CONFIG request.
"""
self.validate_configuration(configuration)
self._configure_endpoints(configuration)
self.configuration = configuration

Loading