Skip to content

Commit

Permalink
add workflow to publish package
Browse files Browse the repository at this point in the history
  • Loading branch information
shuo-young committed Jan 30, 2024
1 parent 38a987d commit fb9dd35
Show file tree
Hide file tree
Showing 12 changed files with 1,725 additions and 30 deletions.
52 changes: 52 additions & 0 deletions .github/workflows/publish-docker-image.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
name: Create and publish the lydia docker image

# Configures this workflow to run every time a change is pushed to the branch called `release`.
on:
push:
branches:
- "v*"
- "latest"
tags:
- "v*"

# Defines two custom environment variables for the workflow. These are used for the Container registry domain, and a name for the Docker image that this workflow builds.
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}

# There is a single job in this workflow. It's configured to run on the latest available version of Ubuntu.
jobs:
build-and-push-image:
runs-on: ubuntu-latest
# Sets the permissions granted to the `GITHUB_TOKEN` for the actions in this job.
permissions:
contents: read
packages: write
#
steps:
- name: Checkout repository
uses: actions/checkout@v4
# Uses the `docker/login-action` action to log in to the Container registry registry using the account and password that will publish the packages. Once published, the packages are scoped to the account defined here.
- name: Log in to the Container registry
uses: docker/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
# This step uses [docker/metadata-action](https://github.com/docker/metadata-action#about) to extract tags and labels that will be applied to the specified image. The `id` "meta" allows the output of this step to be referenced in a subsequent step. The `images` value provides the base name for the tags and labels.
- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@9ec57ed1fcdbf14dcef7dfbe97b2010124a938b7
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
# This step uses the `docker/build-push-action` action to build the image, based on your repository's `Dockerfile`. If the build succeeds, it pushes the image to GitHub Packages.
# It uses the `context` parameter to define the build's context as the set of files located in the specified path. For more information, see "[Usage](https://github.com/docker/build-push-action#usage)" in the README of the `docker/build-push-action` repository.
# It uses the `tags` and `labels` parameters to tag and label the image with the output from the "meta" step.
- name: Build and push Docker image
id: build-and-push
uses: docker/[email protected]
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
159 changes: 130 additions & 29 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,46 +1,147 @@
# Lydia

![Static Badge](https://img.shields.io/badge/license-apache-blue)
![Static Badge](https://img.shields.io/badge/language-rust-red)

An Attacker Contract Identification Tool Implemented in Rust based on BlockWatchdog.

## Quick Start

### Rust Environment

Before running Lydia, you need to have the Rust environment set up.
<!-- <h1 align="center">Welcome to NFTDefects 👋</h1> -->
<p>
<img alt="Static Badge" src="https://img.shields.io/badge/rust-1.75.0-blue">
<img alt="Static Badge" src="https://img.shields.io/badge/ubuntu-20.04-yellow">
<img alt="Static Badge" src="https://img.shields.io/badge/docker-v0.1-purple">
<a href="doc url" target="_blank">
<img alt="Documentation" src="https://img.shields.io/badge/documentation-yes-brightgreen.svg" />
</a>
<a href="LICSEN" target="_blank">
<img alt="License: Apache" src="https://img.shields.io/badge/License-Apache-yellow.svg" />
</a>
<img alt="GitHub Actions Workflow Status" src="https://img.shields.io/github/actions/workflow/status/shuo-young/lydia/publish-docker-image.yml">
<!-- <img alt="GitHub forks" src="https://img.shields.io/github/forks/NFTDefects/nftdefects">
<!-- <img alt="GitHub forks" src="https://img.shields.io/github/stars/NFTDefects/nftdefects"> -->

<!-- <a href="https://twitter.com/shall_yangshuo" target="_blank">
<img alt="Twitter: shall\_yangshuo" src="https://img.shields.io/twitter/follow/shall_yangshuo.svg?style=social" />
</a> -->
</p>

<br />
<div align="center">
<a href="https://github.com/shuo-young/lydia">
<img src="logo.png" alt="Logo" width="80" height="80">
</a>

<h3 align="center">Lydia</h3>

<p align="center">
<!-- <a href="https://github.com/shuo-young/BlockWatchdog"><strong>Explore the docs »</strong></a> -->
<!-- <br /> -->
<!-- <br /> -->
<!-- <a href="https://github.com/shuo-young/BlockWatchdog">View Demo</a>
· -->
<a href="https://github.com/shuo-young/lydia/issues">Report Bug</a>
·
<a href="https://github.com/shuo-young/lydia/issues">Request Feature</a>
</p>
</div>

<!-- TABLE OF CONTENTS -->
<details>
<summary>Table of Contents</summary>
<ol>
<li>
<a href="#about-the-project">About The Project</a>
</li>
<li>
<a href="#getting-started">Prerequisites</a>
<ul>
<li><a href="#prerequisites">Prerequisites</a></li>
<li><a href="#install">Install</a></li>
</ul>
</li>
<li>
<a href="#usage">Usage</a>
<ul>
<li><a href="#local">Local</a></li>
<li><a href="#docker">Docker</a></li>
</ul>
</li>
<!-- <li><a href="#code-structure">Code Structure</a></li> -->
<li><a href="#features">Features</a></li>
<!-- <li><a href="#publication">Publication</a></li> -->
<li><a href="#contact">Contact</a></li>
<li><a href="#license">License</a></li>

</ol>
</details>

<!-- ABOUT THE PROJECT -->

## About The Project

An Attacker Contract Identification Tool Implemented in Rust based on [BlockWatchdog](https://github.com/shuo-young/BlockWatchdog).

<!-- [![Product Name Screen Shot][product-screenshot]](https://example.com) -->
<!-- <p align="right">(<a href="#readme-top">back to top</a>)</p> -->

## Prerequisites

- rust toolchain

```bash
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
```

- gigahorse-toolchain

Lydia requires Gigahorse to be set up for analyzing EVM bytecode. To set up Gigahorse, refer to its [repository](https://github.com/nevillegrech/gigahorse-toolchain).

<!-- <img align="left" width="213" src="logo.png"> -->

## Install

1. Rust build locally.

```sh
cargo build --release
```

### Gigahorse Environment
2. Or you can build or pull the docker image.

Lydia requires Gigahorse to be set up for analyzing Ethereum bytecode. To set up Gigahorse, refer to its [repository](https://github.com/nevillegrech/gigahorse-toolchain)
```sh
docker build -t lydia:v0.1 .
docker pull ghcr.io/shuo-young/lydia:latest
```

## Run
## Usage

### Local

To run Lydia locally, use the following command:

```shell
```sh
RUST_LOG=info cargo run -- ETH 0x10C509AA9ab291C76c45414e7CdBd375e1D5AcE8
# or use build bin
./target/release/lydia -- ETH 0x10C509AA9ab291C76c45414e7CdBd375e1D5AcE8
```

Replace the address of the contract you want to analyze. Contracts on other platforms (e.g., BSC) are also supported.

### Docker

To build and run Lydia using Docker, use the following commands:
For the docker image, run with the following command.

```shell
docker build -t lydia:v1.0 .
```sh
docker run ghcr.io/shuo-young/lydia:latest ETH 0x10C509AA9ab291C76c45414e7CdBd375e1D5AcE8
```

Run with the following command:
## Features

```shell
docker run lydia:v1.0 ETH 0x10C509AA9ab291C76c45414e7CdBd375e1D5AcE8
```
> more faster for identifying attackers and contracts with malicious intentions

- Recover all possible call chains in attacker contract (each public function).
- Report critical attack semantic, e.g., call in hook functions, selfdestruct, use randomnumer, creation (sole and multi) etc.
- Locating call sites that could perform reentrancy and possible reentrancy targets.

## Contact

👤 **Shuo Yang**

- Website: [shuo-young.github.io](https://shuo-young.github.io/)
- Twitter: [@shall_yangshuo](https://twitter.com/shall_yangshuo)
- Github: [@shuo-young](https://github.com/shuo-young)

## Publication
## License

Based on _*BlockWatchdog*_, the ICSE'24 paper: Uncover the Premeditated Attacks: Detecting Exploitable Reentrancy Vulnerabilities by Identifying Attacker Contracts.
Copyright © 2024 [Shuo Yang](https://github.com/shuo-young).<br />
This project is [Apache](https://github.com/NFTDefects/nftdefects/blob/master/LICENSE) licensed.
2 changes: 1 addition & 1 deletion gigahorse-toolchain/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ results.json
*_compiled
*_compiled
*.ccerr
*.cpp
# *.cpp

# testing files
.tests/**
Expand Down
74 changes: 74 additions & 0 deletions gigahorse-toolchain/souffle-addon/keccak256.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
#include <boost/multiprecision/cpp_int.hpp>
#include <string.h>

using namespace boost::multiprecision;
using namespace std;

char num_to_hex(char num) {
return num < 10 ? num + '0' : (num - 10) + 'a';
}

char hex_to_num(char hex_char) {
return hex_char <= '9' ? hex_char - '0' : (hex_char - 'a') + 10;
}

extern "C"
{
#include "keccak/KeccakHash.h"
const char* keccak_256(const char* input) {
thread_local static char out_str[67] = {"0x"};
thread_local static char out[32] = {0};

Keccak_HashInstance hi;
Keccak_HashInitialize(&hi, 1088, 512, 256, 0x01);
Keccak_HashUpdate(&hi, (const unsigned char*)input, strlen(input) * 8);
Keccak_HashFinal(&hi, (unsigned char*)out);

for (int i = 0; i < 32; ++i) {
unsigned char c = out[i];
out_str[2 + 2*i] = num_to_hex(c >> 4);
out_str[2 + 2*i + 1] = num_to_hex(c & 0x0f);
}

return out_str;
}

const char* hex_keccak_256(const char* input) {
thread_local static char out_str[67] = {"0x"};
thread_local static char out[32] = {0};

const size_t input_len = strlen(input);
const size_t input_byte_len = input_len/2 - 1;

char* input_bytes = (char*) malloc(sizeof(char) * input_byte_len);

for (size_t i = 0; i < input_byte_len; ++i)
input_bytes[i] = (hex_to_num(input[2 + 2*i]) << 4) + hex_to_num(input[2 + 2*i + 1]);

Keccak_HashInstance hi;
Keccak_HashInitialize(&hi, 1088, 512, 256, 0x01);
Keccak_HashUpdate(&hi, (const unsigned char*)input_bytes, input_byte_len * 8);
Keccak_HashFinal(&hi, (unsigned char*)out);

free(input_bytes);

for (int i = 0; i < 32; ++i) {
unsigned char c = out[i];
out_str[2 + 2*i] = num_to_hex(c >> 4);
out_str[2 + 2*i + 1] = num_to_hex(c & 0x0f);
}

return out_str;
}

const char* hex_to_str(const char* input) {
thread_local static char* out = (char*) malloc(sizeof(char) * (strlen(input)/2));

for (int i = 1; i < strlen(input)/2; i++){
out[i - 1] = hex_to_num(input[2*i])*16 + hex_to_num(input[2*i + 1]);
}
out[strlen(input)/2 - 1] = '\0';

return out;
}
}
60 changes: 60 additions & 0 deletions gigahorse-toolchain/souffle-addon/keccak256_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
#define BOOST_TEST_MODULE Keccak Tests
#include <boost/test/included/unit_test.hpp>

#include "keccak256.cpp"

BOOST_AUTO_TEST_CASE(test_hash_empty) {
BOOST_TEST(
keccak_256("")
==
"0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"
);
}

BOOST_AUTO_TEST_CASE(test_hash_simple) {
BOOST_TEST(
keccak_256("hi")
==
"0x7624778dedc75f8b322b9fa1632a610d40b85e106c7d9bf0e743a9ce291b9c6f"
);
}

BOOST_AUTO_TEST_CASE(test_hash_signature) {
BOOST_TEST(
keccak_256("transfer(address,uint256)")
==
"0xa9059cbb2ab09eb219583f4a59a5d0623ade346d962bcd4e46b11da047c9049b"
);
}

BOOST_AUTO_TEST_CASE(test_hex_to_str) {
BOOST_TEST(
hex_to_str("0x72656365697665417070726f76616c28616464726573732c75696e743235362c616464726573732c627974657329")
==
"receiveApproval(address,uint256,address,bytes)"
);
}

BOOST_AUTO_TEST_CASE(test_hash_hex_to_str) {
BOOST_TEST(
keccak_256(hex_to_str("0x7472616e7366657228616464726573732c75696e7432353629"))
==
"0xa9059cbb2ab09eb219583f4a59a5d0623ade346d962bcd4e46b11da047c9049b"
);
}

BOOST_AUTO_TEST_CASE(test_hash_hex_keccak_256_single_byte) {
BOOST_TEST(
hex_keccak_256("0x61")
==
"0x3ac225168df54212a25c1c01fd35bebfea408fdac2e31ddd6f80a4bbf9a5f1cb"
);
}

BOOST_AUTO_TEST_CASE(test_hash_hex_keccak_256_two_bytes) {
BOOST_TEST(
hex_keccak_256("0x6162")
==
"0x67fad3bfa1e0321bd021ca805ce14876e50acac8ca8532eda8cbf924da565160"
);
}
Loading

0 comments on commit fb9dd35

Please sign in to comment.