Skip to content

Commit

Permalink
Fixed a bug in pack&parse and updated the docs
Browse files Browse the repository at this point in the history
  • Loading branch information
oryair1 committed Aug 12, 2024
1 parent db79c5c commit da0b3a7
Show file tree
Hide file tree
Showing 5 changed files with 77 additions and 5 deletions.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ This repository includes the tools we developed during our research:
5. [**force_wifi_connection**](./docs/doc_force_wifi_connection.md): Forces a device with Quick Share to connect to a given WiFi network. If performed against a Windows device with the vulnerable Quick Share version, then it also crashes its Quick Share app, creating a Wi-Fi connection to the given Wi-Fi network that lasts forever.
6. [**quick_fuzz**](./docs/doc_quick_fuzz.md): A fuzzer for Quick Share for Windows. Each fuzzing iteration sends a sequence of offline frames, simulating an entire transfer session.

### Supporting Tools
1. [**pack_packet_flows & parse_packet_flows**](./docs/doc_pack_parse_packet_flows.md)

## Building Tools
This repository uses Bazel for building. In order to build the tools you'll need to install Bazel - [Install Bazel on Windows](https://bazel.build/install/windows)

Expand Down
56 changes: 56 additions & 0 deletions docs/doc_pack_parse_packet_flows.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# pack_packet_flows & parse_packet_flows

Tools for packing and parsing our custom binary format for representing sequences of packets (OfflineFrames). The format is simple:

`[DWORD Length][Serialized Offline Frame][DWORD Length][Serialized Offline Frame]...`

* [DWORD Length] - Four bytes that represent the size of a packet in little endian
* [Serialized Offline Frame] - A serialized protobuf packet (OfflineFrame)

Three of the tools that we developed in this repo use these custom format:
* [**quick_fuzz**](/docs/doc_quick_fuzz.md) - Receives files in this format as corpus (fuzzing input files)
* [**send_packets**](/docs/doc_send_packets.md) - Receives files in this format as an input, and sends the contained packets
* [**quick_sniff**](/docs/doc_quick_sniff.md) - Outputs files in this format that hold the sequence of packets that each device that participated a sniffed session sent


## Build
Run:
```cmd
bazel build //tools:pack_packet_flows
bazel build //tools:parse_packet_flows
```
The executables will be created in `./bazel-bin/tools`

## Usage
pack_packet_flows:

```cmd
usage: pack_packet_flows.py [-h] parsed_packet_flow_dir out_packet_flow_file
Packs (serializes) Quick Share's (OfflineFrame) packets' pretty YAML files into their
protobuf serialized byte form
positional arguments:
parsed_packet_flow_dir
A path to a directory containing all packets in YAML (as
parse_packet_flows parses outputs)
out_packet_flow_file A path to the packets file to be create
```

parse_packet_flows:

```cmd
usage: parse_packet_flows.py [-h] packet_flow_file out_dir
Parse Quick Share's (OfflineFrame) packets into textual readable YAML structures
positional arguments:
packet_flow_file A path to a file with containing all packets in
|length|packet|length|packet| format
out_dir A path to a directory where the output file/s will be created
```

### Advanced Parameters
quick_sniff works by hooking the most basic Read & Write functions that are used by Quick Share to send and receive packets using any communication method. They don't have symbols inside the compiled binary, and so we must set their addresses (offsets) statically per the version of the Quick Share app. We set the addresses to the addresses of these functions in the vulnerable version of Quick Share that is present in this repository. If you want to sniff packets on a different version, you'll have to modify the addresses. Quick explanations for how to find these functions in a disassembler are written in comments in `quick_sniff.cc`. The names of these functions in Quick Share's source code are:
* BaseEndpointChannel::Read
* BaseEndpointChannel::Write
13 changes: 13 additions & 0 deletions docs/doc_quick_fuzz.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,19 @@ Once you install one of them, make sure you disable updates.

In addition to these DLLs, you'll need to have WinAFL as the fuzzing framework. We needed to perform a small patch in WinAFL's code in order for it to work with our harness and libprotobuf-mutator. You can either run the [`clone_and_patch_winafl.bat`](/quick_fuzz/winafl_clone_and_patch/clone_and_patch_winafl.bat) script that we created and then follow WinAFL's instructions for compilation yourself. Or you can use the precompiled version of WinAFL that we uploaded to this repo at [precompiled_patched_winafl.zip](/quick_fuzz/precompiled_patched_winafl.zip). Note that you'll have to download DynamoRIO version 10.92.19896, since `afl-fuzz.exe` needs it in order to run. You can download it from [here](https://github.com/DynamoRIO/dynamorio/releases/download/cronbuild-10.92.19896/DynamoRIO-Windows-10.92.19896.zip)

### Corpus (Input Files):
The input files are files in our custom binary format. Each file contains a sequence of packets (OfflineFrames) that should be sent in a fuzzing iteration. The fuzzing harness behaves as if the first packets in the sequence are:
1. Connection Request
2. Connection Response
3. Paired Key Encryption
4. Paired Key Result
5. Introduction
6. Introduction Done

And then sends the rest of the packets (Usually Payload Transfer OfflineFrames with the content of the file to be sent)

Corpus files can be created using the [**quick_sniff**](/docs/doc_quick_sniff.md) fuzzer (Would be best if you make sure that are no redundant packets up to the Introduction packet). To better understand the format of the corpus files, read the docs about [**pack_packet_flows & parse_packet_flows**](/docs/doc_pack_parse_packet_flows.md)

### Usage of afl-fuzz with our harness:
You should refer to WinAFL's documentation in order to fully understand `afl-fuzz.exe`'s parameters

Expand Down
6 changes: 3 additions & 3 deletions tools/pack_packet_flows.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@
import os
import yaml

from python_tool_helpers.offline_frames_utils import offline_frame_dict_to_offline_frame
from tools.python_tool_helpers.offline_frames_utils import offline_frame_dict_to_offline_frame


def parse_args():
parser = argparse.ArgumentParser(description="Packs (serializes) Quick Share's (OfflineFrame) packets' pretty YAML files into their protobuf serialized byte form")

parser.add_argument("packets_dir", help="A path to a directory containing all YAML packets")
parser.add_argument("out_file", help="A path to the packets file to be created")
parser.add_argument("parsed_packet_flow_dir", help="A path to a directory containing all packets in YAML (as parse_packet_flows parses outputs)")
parser.add_argument("out_packet_flow_file", help="A path to the packets file to be created")

return parser.parse_args()

Expand Down
4 changes: 2 additions & 2 deletions tools/parse_packet_flows.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@
import os
import yaml

from python_tool_helpers.offline_frames_utils import decode_offline_frame_protobuf_bytes
from tools.python_tool_helpers.offline_frames_utils import decode_offline_frame_protobuf_bytes


def parse_args():
parser = argparse.ArgumentParser(description="Parse Quick Share's (OfflineFrame) packets into textual readable YAML structures")

parser.add_argument("packets_file", help="A path to a file with containing all packets in |length|packet|length|packet| format")
parser.add_argument("packet_flow_file", help="A path to a file with containing all packets in |length|packet|length|packet| format")
parser.add_argument("out_dir", help="A path to a directory where the output file/s will be created")

return parser.parse_args()
Expand Down

0 comments on commit da0b3a7

Please sign in to comment.