Skip to content

Commit 75392c1

Browse files
authored
Merge pull request #24 from chkp-eyalit/code-cleanup
Major refactor - v2.0.0
2 parents bb9b50b + aacd444 commit 75392c1

File tree

93 files changed

+3331
-2735
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

93 files changed

+3331
-2735
lines changed

.gitignore

Lines changed: 33 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,48 @@
11
# Compiled scout
2-
scout/*.o
3-
scout/*.S
4-
scout/*.bin
5-
scout/*.elf
6-
scout/arc/*.o
7-
scout/arc/*.S
8-
scout/loaders/*.o
9-
scout/loaders/*.S
10-
scout/pic/*.o
11-
scout/pic/*.S
2+
src/scout/*.o
3+
src/scout/*.S
4+
src/scout/*.bin
5+
src/scout/*.elf
6+
src/scout/arc/*.o
7+
src/scout/arc/*.S
8+
src/scout/loaders/*.o
9+
src/scout/loaders/*.S
10+
src/scout/pic/*.o
11+
src/scout/pic/*.S
12+
src/scout/Scout.vpj
13+
src/scout/Scout.vpw
14+
src/scout/Scout.vpwhist
15+
src/scout/Scout.vtg
1216

1317
# Compiled embedded scout
14-
embedded_scout/*.o
15-
embedded_scout/*.S
16-
embedded_scout/*.bin
17-
embedded_scout/*.elf
18+
examples/embedded_scout/*.o
19+
examples/embedded_scout/*.S
20+
examples/embedded_scout/*.bin
21+
examples/embedded_scout/*.elf
1822

19-
# Compiled kernel scoutkernel_scout/driver/*.order
20-
kernel_scout/driver/*.symvers
21-
kernel_scout/driver/*.o
22-
kernel_scout/driver/*.ko
23-
kernel_scout/user_mode/*.o
24-
kernel_scout/user_mode/*.S
25-
kernel_scout/user_mode/*.bin
26-
kernel_scout/user_mode/*.elf
23+
# Compiled kernel scoutexamples/kernel_scout/driver/*.order
24+
examples/kernel_scout/driver/*.symvers
25+
examples/kernel_scout/driver/*.o
26+
examples/kernel_scout/driver/*.ko
27+
examples/kernel_scout/user_mode/*.o
28+
examples/kernel_scout/user_mode/*.S
29+
examples/kernel_scout/user_mode/*.bin
30+
examples/kernel_scout/user_mode/*.elf
2731

2832
# Compiled tests
2933
tests/exploit_me_32
3034
tests/exploit_me_64
3135

3236
# Compiled python modules
33-
utils/*.pyc
34-
manager/*.pyc
37+
src/utils/*.pyc
3538

3639
# Generated docs
3740
docs/_build/*
3841
docs/_build/*/*
3942
docs/_build/*/*/*
40-
docs/_build/*/*/*/*
43+
docs/_build/*/*/*/*
44+
45+
# Python package
46+
build/
47+
dist/
48+
scout_debugger.*

CONTRIBUTING.md

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
How to contribute
2+
=================
3+
First of all, thank you for choosing to contribute to our project. This short guide will describe the required coding conventions, as well as the built-in tests that we use in our project. Following these guidelines will help us merge your pull request into our code base in a fast as smooth manner.
4+
5+
Submitting changes
6+
------------------
7+
Please send us a GitHub Pull Request with a clear list of what you've done. Make sure to include a clear log message for your commits, describing the modifications / additions to the code base, and their implications.
8+
9+
Reporting a bug
10+
---------------
11+
In order to help us close the bug as quickly as possible, please follow these steps:
12+
1. Make sure there isn't an open issue that already addresses this bug
13+
2. If there isn't, open a new issue and attach as many informative details as you can:
14+
* Architecture & compilation flags in which the bug occurs
15+
* Trace + logs, describing the bug / exception
16+
* As many details as you can in order to help us reproduce and fix this issue
17+
3. If you already have a fix, please submit it as a pull request, and include the bug details in it's description
18+
19+
Coding Conventions
20+
------------------
21+
Start reading our code and we believe you'll get the hang of it.
22+
The important notes are:
23+
* Every function should be documented in a manner that is consistent with the current documentation standard
24+
* Each indentation level should be 4 spaces in width (spaces, not tabs)
25+
* We believe that comments improve the readability, make sure that your code is documented enough to be understood by other developers
26+
27+
Testing
28+
-------
29+
**Scout** uses the following tools to enforce coding conventions and to help eliminate common python bugs:
30+
* [pydocstyle](http://www.pydocstyle.org/en/2.1.1/usage.html)
31+
* [flake8](https://pypi.org/project/flake8/)
32+
33+
Testing can be done from the project's home directory:
34+
1. Testing for **pydocstyle**:
35+
```Scout> python tests.py```
36+
2. Testing for **flake8**:
37+
```Scout> flake8 src```
38+
39+
One last note
40+
-------------
41+
We believe that the only way that Open Source tools will help the infosec community in the long term, is to maintain these tools and to make sure they are developed according to the community standards. Each contribution brings as one step further to this goal.
42+
43+
Thanks :)

README.md

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -51,13 +51,18 @@ https://scout-debugger.readthedocs.io/
5151
* Any Posix-like operating system (Embedded Mode)
5252

5353
## Folder Structure
54-
* **docs:** Useful tutorials regarding each unique module of the debugger, including documentation of the API used for custom extensions
55-
* **embedded_scout:** Example project for an embedded debugger scenario, i.e. a debugger that is injected into the address space of a debuggee firmware
56-
* **kernel_scout:** Linux kernel driver-based debugger, including a proxy user mode process used for transparent network access
57-
* **manager:** Python layer for communicating with the debuggee (usually over a TCP connection)
58-
* **scout:** C code of the basic scout debugger
59-
* **tests:** A testing utility for PIC based debuggers
60-
* **utils:** Useful python compilation scripts
54+
* **docs:** Documentation files that generated the read-the-docs that was linked above
55+
* **examples:**
56+
* **embedded_scout** - Use case example for an "Embedded Mode" compilation
57+
* **kernel_scout** - Use case example for a Linux "Kernel Mode" compilation
58+
* **src**
59+
* **scout** - Source code for the debugger (core of the server side)
60+
* **utils** - Python compilation scripts and network API for the client/server
61+
* **tests:** A simple exploit_me.c for checking PIC compiled binaries
62+
63+
## Installation
64+
* Installing the python package: ```python3 setup.py install```
65+
* Dedicated compilers: A list of compilers per-architecture is found on ```compilers.txt```
6166

6267
## Credits
6368
This projects combines together design and compilation tricks that I learned from many fellow researchers during the years.
@@ -73,4 +78,4 @@ Scout was developed and used in our following research projects:
7378
## Contact
7479
Eyal Itkin (eyalit at checkpoint dot com)
7580

76-
[@EyalItkin](https://twitter.com/EyalItkin)
81+
[@EyalItkin](https://twitter.com/EyalItkin)

compilers.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Used compilers:
2+
===============
3+
1. GCC compilation to 32 bits on 64 bits linux machines ==> sudo apt-get install gcc-multilib libc6-dev-i386
4+
2. ARM cross compiler toolchain for Linux ==> sudo apt-get install gcc-arm-none-eabi
5+
3. MIPS cross compiler toolchain for Linux ==> sudo apt-get install gcc-mips-linux-gnu

dependencies.txt

Lines changed: 0 additions & 5 deletions
This file was deleted.

docs/Adding Custom Instructions.md

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@ Being an instruction-based debugger, Scout supports project extensions.
44

55
Registration - C Code
66
---------------------
7-
* Each of the instructions that are added by the project, should be registerred by calling ```register_instruction()```.
8-
* The registration should take place inside the function ```register_specific_instructions()```.
9-
* This design makes sure that when invoking ```register_all_instructions()```, all of the default instructions, and extension instruction, will be registerred correctly.
7+
* Each of the instructions that are added by the project, should be registerred by calling ``register_instruction()``.
8+
* The registration should take place inside the function ``register_specific_instructions()``.
9+
* This design makes sure that when invoking ``register_all_instructions()``, all of the default instructions, and extension instruction, will be registerred correctly.
1010

1111
Implementation - C Code
1212
-----------------------
@@ -15,15 +15,15 @@ In order to implement a new instruction, one should define each of the required
1515
* Instruction ID - must be unique, but not necessarily consecutive
1616
* Minimal Length - minimal amount of bytes needed for a valid instruction (robustness checks)
1717
* Maximal Length - maximal amount of bytes needed for a valid instruction (robustness checks)
18-
* Instruction handler - a handler function with a fixed signature of: ```int32_t (*instrHandler)(void * ctx, uint8_t * instruction, uint32_t length)```
18+
* Instruction handler - a handler function with a fixed signature of: ``int32_t (*instrHandler)(void * ctx, uint8_t * instruction, uint32_t length)``
1919

20-
**Note:** The instructions are stored in a global array with a **fixed** capacity. When adding new instructions, one should make sure to adjust this capacity accordingly.
21-
The capacity is defined in ```scout_api.h``` and is set by default to ```#define SCOUT_MAX_INSTRS (10)```.
20+
**Note:** The instructions are stored in a global array with a **fixed** capacity. When adding new instructions, one should make sure to adjust this capacity accordingly (both in the C and .py files).
21+
The capacity is defined in ``scout_api.h`` and is set by default to ``#define SCOUT_MAX_INSTRS (10)``.
2222

2323
Examples - C Code
2424
-----------------
25-
* Embedded mode (```embedded_scout```) - files ```project_instructions``` (*.c and *.h)
26-
* Linux Kernel mode (```kernel_scout```) - files ```driver\scout_kernel_instructions``` (*.c and *.h)
25+
* Embedded mode (``embedded_scout``) - files ``project_instructions`` (*.c and *.h)
26+
* Linux Kernel mode (``kernel_scout``) - files ``driver\scout_kernel_instructions`` (*.c and *.h)
2727

2828
Client Side - Python Code
2929
-------------------------
@@ -34,4 +34,5 @@ In the client side, adding a new instructions is even easier, and requires only
3434

3535
Examples - Python Code
3636
----------------------
37-
* Linux Kernel example (```manager```) - file ```kernel_scout_api.py```
37+
* Embedded example (``manager``) - file ``embedded_scout_api.py``
38+
* Linux Kernel example (``manager``) - file ``kernel_scout_api.py``

docs/Compilation Modes.md

Lines changed: 31 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,19 @@
11
Compilation Modes
22
=================
3-
Scout is a configurable debugger, that could bedeployed in several different environments:
3+
Scout is a configurable debugger, that could be deployed in several different environments:
44

55
* Linux User-Mode Process - "User Mode"
66
* Linux Kernel Driver - "Kernel Mode"
77
* Linux In-Process Debugging - "User Mode" + "PIC Mode"
8-
* Embedded "In-Process" Debugging - "PIC Mode" + "Embedded Mode"
8+
* Embedded "In-Process" Debugging (low privileges) - "PIC Mode" + "User Mode"
9+
* Embedded "In-Process" Debugging (high privileges) - "PIC Mode" + "Kernel Mode"
910

1011
To decide what will be the suitable compilation mode / architecture flags, one should check the following parameters.
1112
Each of the defined parameters is a C MACRO (define) that controls the behavior (and compilation) of the resulting binary.
1213

14+
**Important Note:**
15+
When using ``scoutCompiler``, it will automatically generate most of the needed flags by deducing the right values based on the architecture and configuration flags that are supplied to it. Please see the ``embedded_scout`` example for more info.
16+
1317
Target Endianness
1418
-----------------
1519
* SCOUT_BIG_ENDIAN - Scout is executed on a Big Endian architecture
@@ -36,48 +40,51 @@ Only one of above flags can be defined.
3640
If none are defined the base library will define "SCOUT_ARCH_INTEL" on it's own.
3741

3842
**Additional Flags:**
39-
* SCOUT_ARM_THUMB - Scout will be executed on an ARM cpu in Thumb mode. Can only be used together with the "SCOUT_ARCH_ARM" flag.
43+
SCOUT_ARM_THUMB - Scout will be executed on an ARM cpu in Thumb mode. Can only be used together with the "SCOUT_ARCH_ARM" flag.
4044

41-
The flags is needed only in PIC mode, in which we use inline assembly.
45+
The flags are needed only in PIC mode, in which we use inline assembly.
4246

4347
Target Permission Level
4448
-----------------------
45-
* SCOUT_MODE_USER - Scout is executed in User-Mode
46-
* SCOUT_MODE_KERNEL - Scout is executed in Kernel-Mode
49+
* SCOUT_MODE_USER - Scout is executed in User-Mode (& low CPU privileges)
50+
* SCOUT_MODE_KERNEL - Scout is executed in Kernel-Mode (& high CPU privileges)
4751

4852
Only one of above flags can be defined.
4953
If none are defined the base library will define "SCOUT_MODE_USER" on it's own.
5054

51-
**Note:** These flags are used only in a Linux PC Environment, and are not used in an Embedded Environment.
52-
53-
Target Loading Environment
54-
--------------------------
55-
* SCOUT_PC_ENV - Scout is executed as a standard process (user) or driver (kernel) on a Linux machine
56-
* SCOUT_EMBEDDED_ENV - Scout is injected to the address space of a given executable
57-
58-
Only one of above flags can be defined.
59-
If none are defined the base library will define "SCOUT_PC_ENV" on it's own.
60-
61-
**Note:** SCOUT_EMBEDDED_ENV has many use cases, including:
62-
1. Injecting a debugger into a debuggee Linux process
63-
2. Injecting a debugger into a debuggee firmware (if the executable's API matches the basic POSIX based API of Scout)
55+
"SCOUT_MODE_KERNEL" will also be the right choice for an RTOS (Real-time OS) in which every task / our task has high privileges. The flag will lead to the definition of "SCOUT_HIGH_PRIVILEGES" by the compilation environment.
6456

65-
**Note:** At the current moment, "SCOUT_EMBEDDED_ENV" must be used with "SCOUT_PIC_CODE", although in the future a linker script could help an embedded scout access external functions without the PIC context.
57+
**Important Note:** As flushing the CPU cache usually requires high privileges, the per-architecture implementation will only be available if compiling using the "SCOUT_MODE_KERNEL" flag.
6658

6759
Position Independent Mode - SCOUT_PIC_CODE
6860
------------------------------------------
6961
Scout will be compiled for full Position Independent Code (PIC) mode. Any access to an external function / global variable will pass through a unique "Context" object. Read the section about "PIC Compilation" for more information.
70-
**Note:** Can only be used with "SCOUT_EMBEDDED_ENV".
62+
63+
"SCOUT_PIC_CODE" will lead to the definition of "SCOUT_ISOLATED_ENV" by the compilation environment, because a PIC blob will always be isolated from the environment, and won't have the luxory of a proper executable loader such as "ld.so".
64+
65+
Host LibC Implementation
66+
------------------------
67+
When injecting our (PIC) code into a host binary, we should make sure to use the proper constants for the matching standard library implementation that is used by the respective binary:
68+
* SCOUT_HOST_GLIBC - The used library is Glibc
69+
* SCOUT_HOST_UCLIBC - The used library is uClibc (or uClibc-NG)
70+
71+
If none are defined the base library will define "SCOUT_HOST_GLIBC" on it's own.
7172

7273
Loader Flags
7374
------------
7475
* SCOUT_LOADER - We are now compiling a loader (that might be using it's own pic plt / globals).
7576
* SCOUT_LOADING_THUMB_CODE - The loader will load a Scout that was compiled to be executed on an ARM cpu in Thumb mode.
76-
* SCOUT_RESTORE_FLOW - The default loaders (```tcp_client_server.c```, ```tcp_loader_server.c```) will clean-up after themselves if the loaded scout will finish his endless loop.
77+
* SCOUT_RESTORE_FLOW - The default loaders (``tcp_client_server.c``, ``tcp_loader_server.c``) will clean-up after themselves if the loaded scout will finish the endless loop.
78+
79+
If the loader will be compiled to be Position Independent (PIC), which is probably the most common use case, it will also define a new flag of "SCOUT_SLIM_SIZE", to help shrink the size of the binary (to serve as an effective shellcode).
80+
Under this definition the TCP server would expect the following flags (if needed):
81+
* SCOUT_TCP_CLIENT - There is a need to include the feature of a TCP client
82+
* SCOUT_TCP_SERVER - There is a need to include the feature of a TCP server
83+
* SCOUT_TCP_SEND - There is a need to include the ability to reliably send TCP messages
7784

7885
Additional Flags:
7986
-----------------
8087
* SCOUT_INSTRUCTIONS - Scout is going to use the instructions api (using the TCP server for instance)
81-
* SCOUT_DYNAMIC_BUFFERS - Scout will dynamically malloc() buffers to be used by the tcp server. Otherwise static buffers will be used.
88+
* SCOUT_DYNAMIC_BUFFERS - Scout will dynamically ``malloc()`` buffers to be used by the tcp server. Otherwise static buffers will be used.
8289
* SCOUT_PROXY - Scout is going to act as a proxy (user scout passing instructions to a kernel driver for instance)
83-
* SCOUT_MMAP - Should scout's loaders use mmap() and mprotect() when loading (if defined) or should they simply use malloc (if undefined)
90+
* SCOUT_MMAP - Should scout's loaders use ``mmap()`` and ``mprotect()`` when loading (if defined) or should they simply use ``malloc()`` (if undefined)

docs/Default Instructions.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,20 @@ Scout is an instruction-based debugger, that commonly uses a TCP network session
44

55
Default Instructions
66
--------------------
7-
* **NOP** - Used as a Pong (or Keep-Alive) instruction to make sure the debugger is active and responds to commands
7+
* **NOP** - Used as a Ping (or Keep-Alive) instruction to make sure the debugger is active and responds to commands
88
* **Memory Read** - Reads (virtual) memory from the given address, and sends it back
99
* **Memory Write** - Writes a given binary content to a (virtual) memory in the debuggee's address space
1010

11-
Each supported instruction must be pre-registered by the debugger before it enters his server loop, usually by calling ```register_all_instructions()```.
11+
Each supported instruction must be pre-registered by the debugger before it enters his server loop, usually by calling ``register_all_instructions()``.
1212

1313
Network API
1414
-----------
1515
Each instruction is sent together with a network header that includes the following:
16+
1617
* Instruction ID - 2 Bytes
1718
* Length field - 4 Bytes
1819

1920
The length field specifies the length, in bytes, of the serialized instruction.
2021

2122
**Note:** All instructions should be serialized to NETWORK order.
22-
See ```manager\scout_api.py``` for a python sample that prepares the instructions for network transmission.
23+
See ``manager\scout_api.py`` for a python sample that prepares the instructions for network transmission.

docs/Default Loaders.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ To overcome these limitations, the scout debugger comes with a list of supported
88

99
The defualt loaders are:
1010

11-
1. ```tcp_client_loader.c``` - Connects to a predefined TCP server
12-
2. ```tcp_server_loader.c``` - Waits for an incoming TCP client
11+
1. ``tcp_client_loader.c`` - Connects to a predefined TCP server
12+
2. ``tcp_server_loader.c`` - Waits for an incoming TCP client
1313

1414
Both of the loaders use the same network protocol:
1515

@@ -18,13 +18,13 @@ Both of the loaders use the same network protocol:
1818

1919
After a TCP connection was established, the loader will follow these steps:
2020

21-
1. The loader will receive the header and malloc() a memory buffer of appropriate size.
21+
1. The loader will receive the header and ``malloc()``/``mmap()`` a memory buffer of appropriate size.
2222
2. The data will be received and stored in this memory buffer.
23-
3. The loader will flush the D-cache and I-cache of the buffer (only in architectures were this is needed)
24-
4. The loader will mprotect() the memory to use the correct permissions (only in architectures were this is needed)
23+
3. The loader will flush the D-cache and I-cache of the buffer (only in architectures were this is needed, and only if we have high enough CPU privileges for it)
24+
4. The loader will ``mprotect()`` the memory to use the correct permissions (only in architectures were this is needed)
2525
5. The loader will jump into the buffer's start (offset 0, as mentioned in the "PIC Compilation" section)
26-
6. In the flow restore case, once the loaded executable finishes the loader will free the memory and close the used sockets.
26+
6. In the flow restore case, once the loaded executable finishes, the loader will free the memory and close the used sockets.
2727

28-
The functions ```remoteLoadServer()``` and ```remoteLoadClient()``` in ```scout_network.py```, implement the required protocol for communicating with the loader, and loading up the full Scout.
28+
The functions ``remoteLoadServer()`` and ``remoteLoadClient()`` in ``scout_network.py``, implement the required protocol for communicating with the loader, and loading up the full Scout. A working example is shown under the ``manager.py`` of the ``embedded_scout`` example.
2929

3030
**Note:** In case there are any W^X style limitations in your environment, it is recommended to make sure that the allocated memory for the full debugger will have both Write and eXcutable permissions (should probably use the SCOUT_MMAP flag in this case).

0 commit comments

Comments
 (0)