Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature: Adding powerful, granular, and fully customizable logging capabilities to PoCs. #25

Merged
merged 8 commits into from
Nov 16, 2023

Conversation

infosec-us-team
Copy link
Contributor

@infosec-us-team infosec-us-team commented Nov 15, 2023

Vulnerability Type

This template is for adding powerful, granular, and fully customizable logging capabilities to your PoCs.

The template provides a foundry/hardhat-like console logging interface with manual control over what types of messages can be logged to avoid mass commenting/uncommenting code and a simple switch to turn all logging from this template on or off.

For even further control over the logging behavior all functions can be overridden, allowing hunters to locally implement any custom feature they need in the blink of an eye.

Usage

Log messages in a foundry/hardhat-style, but instead of calling a library (console.log(...)), all functions are internal (_log(...)):

// Log a string
_log("Funds deposited");

// Log a string with a uint256 variable "_deposited"
_log("Funds deposited: %s", _deposited);

// Log an int256 variable "_negativeValue"
_logInt(_negativeValue);

Turn off logging:

// Disable logging
_setLogType(LogType.NONE);

Log everything:

// Enable logging and log all messages from all phases of the attack vector
_setLogType(LogType.ALL);

Log messages from a specific phase of the attack vector:

// Only log messages from the Complete Attack phase
_setLogType(LogType.COMPLETE_ATTACK);

A LogType for every main phase of an attack vector is supported. Additionally, up to 10 steps can be defined to group and control logs related to every step of an attack vector:

Phase Code
INITIALIZE_ATTACK _setLogType(LogType.INITIALIZE_ATTACK);
EXECUTE_ATTACK _setLogType(LogType.EXECUTE_ATTACK);
COMPLETE_ATTACK _setLogType(LogType.COMPLETE_ATTACK);
STEP_1 _setLogType(LogType.STEP_1);
STEP_2 _setLogType(LogType.STEP_2);
STEP_3 _setLogType(LogType.STEP_3);
STEP_4 _setLogType(LogType.STEP_4);
STEP_5 _setLogType(LogType.STEP_5);
STEP_6 _setLogType(LogType.STEP_6);
STEP_7 _setLogType(LogType.STEP_7);
STEP_8 _setLogType(LogType.STEP_8);
STEP_9 _setLogType(LogType.STEP_9);
STEP_10 _setLogType(LogType.STEP_10);

Automatically control the lifecicle of a phase by adding a modifier to any function:

/**
  * @dev Adding the modifier `step_1` to the "depositFunds()" function
  * defines the start and end of the STEP_1 Phase and allows turning
  * on and off all logging within this phase.
  */
function depositFunds() public step_1 {

    // Approve Market to spend DSU tokens
    DSU.approve(address(market), UINT256_MAX);

    // Log the balance before depositing
    uint256 balanceBefore = DSU.balanceOf(address(this));
    _log("Balance before deposit: %s", balanceBefore);

    // Deposit in market DSU balance
    market.update(
        address(this), // account
        0, // newMaker
        0, // newLong
        0, // newShort
        int256(1000000 * 1e6), // collateral
        false); // protect

    // Log balance after deposit
    uint256 balanceAfter = DSU.balanceOf(address(this));
    _log("Balance before deposit: %s", balanceAfter);
}

Manually control the lifecicle of a phase:

// Manually start STEP_1 phase
_setPhase(LogPhase.STEP_1);

// Manually start STEP_2 phase
_setPhase(LogPhase.STEP_2);

// Manually end all phases (set the default phase)
_setPhase(LogPhase.DEFAULT);

A LogPhase for every main phase of an attack vector is supported. Additionally, up to 10 steps can be defined to group and control logs related to every step of an attack vector:

Phase Code
INITIALIZE_ATTACK _setPhase(LogPhase.INITIALIZE_ATTACK);
EXECUTE_ATTACK _setPhase(LogPhase.EXECUTE_ATTACK);
COMPLETE_ATTACK _setPhase(LogPhase.COMPLETE_ATTACK);
STEP_1 _setPhase(LogPhase.STEP_1);
STEP_2 _setPhase(LogPhase.STEP_2);
STEP_3 _setPhase(LogPhase.STEP_3);
STEP_4 _setPhase(LogPhase.STEP_4);
STEP_5 _setPhase(LogPhase.STEP_5);
STEP_6 _setPhase(LogPhase.STEP_6);
STEP_7 _setPhase(LogPhase.STEP_7);
STEP_8 _setPhase(LogPhase.STEP_8);
STEP_9 _setPhase(LogPhase.STEP_9);
STEP_10 _setPhase(LogPhase.STEP_10);

PR Checklist

  • Attack Template
  • Attack Example
  • Test
  • Readme Updated

infosec-us-team and others added 6 commits November 14, 2023 12:48
…e logging capabilities to your PoCs.

The template provides a foundry/hardhat-like console logging interface with manual control over what types of messages can be logged to avoid mass commenting/uncommenting code and a simple switch to turn all logging from this template on or off.

For even further control over the logging behavior all functions can be overridden.

Log messages in a foundry/hardhat-style, but instead of calling a library (`console.log(...)`), all functions are internal (`_log(...)`):

```solidity
// Log a string
_log("Funds deposited");

// Log a string with a uint256 variable "_deposited"
_log("Funds deposited: %s", _deposited);

// Log an int256 variable "_negativeValue"
_logInt(_negativeValue);
```

Turn off logging:
```solidity
// Disable logging
_setLogType(LogType.NONE);
```

Log everything:
```solidity
// Enable logging and log all messages from all phases of the attack vector
_setLogType(LogType.ALL);
```

Log messages from a specific phase of the attack vector:
```solidity
// Only log messages from the Complete Attack phase
_setLogType(LogType.COMPLETE_ATTACK);
```

The following `LogType`s are supported:
<details>
  <summary>
  </summary>
A `LogType` for every main phase of an attack vector:
| Phase | Code |
| ---------- | ------------------------------------------------------- |
| `INITIALIZE_ATTACK` | `_setLogType(LogType.INITIALIZE_ATTACK);` |
| `EXECUTE_ATTACK` | `_setLogType(LogType.EXECUTE_ATTACK);` |
| `COMPLETE_ATTACK` | `_setLogType(LogType.COMPLETE_ATTACK);` |

Additionally, up to 10 steps can be defined to group and control logs related to every step of an attack vector:
| Phase | Code |
| `STEP_1` | `_setLogType(LogType.STEP_1);` |
| `STEP_2` | `_setLogType(LogType.STEP_2);` |
| `STEP_3` | `_setLogType(LogType.STEP_3);` |
| `STEP_4` | `_setLogType(LogType.STEP_4);` |
| `STEP_5` | `_setLogType(LogType.STEP_5);` |
| `STEP_6` | `_setLogType(LogType.STEP_6);` |
| `STEP_7` | `_setLogType(LogType.STEP_7);` |
| `STEP_8` | `_setLogType(LogType.STEP_8);` |
| `STEP_9` | `_setLogType(LogType.STEP_9);` |
| `STEP_10` | `_setLogType(LogType.STEP_10);` |

</details>

Automatically control the lifecicle of a phases by adding a modifier to any function:
```solidity
/**
  * @dev Adding the modifier `step_1` to the "depositFunds()" function
  * defines the start and end of the STEP_1 Phase and allows turning
  * on and off all logging within this phase.
  */
function depositFunds() public step_1 {

    // Approve Market to spend DSU tokens
    DSU.approve(address(market), UINT256_MAX);

    // Log the balance before depositing
    uint256 balanceBefore = DSU.balanceOf(address(this));
    _log("Balance before deposit: %s", balanceBefore);

    // Deposit in market DSU balance
    market.update(
        address(this), // account
        0, // newMaker
        0, // newLong
        0, // newShort
        int256(1000000 * 1e6), // collateral
        false); // protect

    // Log balance after deposit
    uint256 balanceAfter = DSU.balanceOf(address(this));
    _log("Balance before deposit: %s", balanceAfter);
}
```

Manually control the lifecicle of a phase:
```solidity
// Manually start STEP_1 phase
_setPhase(LogPhase.STEP_1);

// Manually start STEP_2 phase
_setPhase(LogPhase.STEP_2);

// Manually end all phases (set the default phase)
_setPhase(LogPhase.DEFAULT);

```

The following `LogPhase`s are supported:
<details>
  <summary>
  </summary>
A `LogPhase` for every main phase of an attack vector:
| Phase | Code |
| ---------- | ------------------------------------------------------- |
| `INITIALIZE_ATTACK` | `_setPhase(LogPhase.INITIALIZE_ATTACK);` |
| `EXECUTE_ATTACK` | `_setPhase(LogPhase.EXECUTE_ATTACK);` |
| `COMPLETE_ATTACK` | `_setPhase(LogPhase.COMPLETE_ATTACK);` |

Additionally, up to 10 steps can be defined to group and control logs related to every step of an attack vector:
| Phase | Code |
| `STEP_1` | `_setPhase(LogPhase.STEP_1);` |
| `STEP_2` | `_setPhase(LogPhase.STEP_2);` |
| `STEP_3` | `_setPhase(LogPhase.STEP_3);` |
| `STEP_4` | `_setPhase(LogPhase.STEP_4);` |
| `STEP_5` | `_setPhase(LogPhase.STEP_5);` |
| `STEP_6` | `_setPhase(LogPhase.STEP_6);` |
| `STEP_7` | `_setPhase(LogPhase.STEP_7);` |
| `STEP_8` | `_setPhase(LogPhase.STEP_8);` |
| `STEP_9` | `_setPhase(LogPhase.STEP_9);` |
| `STEP_10` | `_setPhase(LogPhase.STEP_10);` |

</details>

- [X] Attack Template
- [X] Attack Example
- [ ] Test
- [X] Readme Updated
Fixes table format
Fixing typo
@janbro
Copy link
Collaborator

janbro commented Nov 16, 2023

Sweet. This is good with me. I don't love duplicating forge functionality but in this case I think the functionality is worth it, especially hiding the console calls from the transaction traces. In the meantime we could look at getting some similar functionality merged to forge-std. Thank you for adding documentation and updating the PoC template 👏

@janbro
Copy link
Collaborator

janbro commented Nov 16, 2023

I'm thinking we can add log levels later as well, and allow for increased/decreased logging depending on the level set, but it would require adding differentiated log calls, something like log_1(...), log_2(...), etc.

@janbro janbro merged commit 3c0e232 into immunefi-team:main Nov 16, 2023
1 of 2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants