diff --git a/.github/workflows/_github_api_helper.py b/.github/workflows/_github_api_helper.py new file mode 100644 index 0000000..b7f3d3d --- /dev/null +++ b/.github/workflows/_github_api_helper.py @@ -0,0 +1,28 @@ +import requests +import os +import time + +def github_api_get(url): + for i in range(3): + changes = None + hdrs = {} + if 'GITHUB_TOKEN' in os.environ: # Github will sometimes rate limit if we don't pass token + print("Using GITHUB_TOKEN!") + hdrs = { + "Authorization": os.environ['GITHUB_TOKEN'] + } + rjson = None + try: + r = requests.get(url, headers=hdrs) + rjson = r.json() + if r.status_code != 200: + raise Exception() + except: + print("Error occurred in GitHub API, Retrying. Server return: %s" % rjson) + time.sleep(2.0) + if i == 2: + raise + else: + return rjson + + # should never get here \ No newline at end of file diff --git a/.github/workflows/auto-update.yml b/.github/workflows/auto-update.yml new file mode 100644 index 0000000..ed78d42 --- /dev/null +++ b/.github/workflows/auto-update.yml @@ -0,0 +1,235 @@ +name: Github CI + +on: + push: + workflow_dispatch: + inputs: + debug_enabled: + description: 'Run the build with tmate debugging enabled (https://github.com/marketplace/actions/debugging-with-tmate)' + required: false + default: false + repository_dispatch: + schedule: + - cron: "0 * */7 * *" # https://crontab.guru/ + +defaults: + run: + shell: bash -x -e -c ". $0" "{0}" + working-directory: Fermion + +jobs: + update: + runs-on: ubuntu-latest + outputs: + FRIDA_VER: ${{ steps.check.outputs.FRIDA_VER }} + FRIDA_GUM_VER: ${{ steps.check.outputs.FRIDA_GUM_VER }} + FRIDA_ELECTRON: ${{ steps.check.outputs.FRIDA_ELECTRON }} + FERMION_TAG: ${{ steps.check.outputs.FERMION_TAG }} + NO_BUILD: ${{ steps.checkTag.outputs.exists }} + + steps: + - name: Checkout + uses: actions/checkout@v3 + with: + fetch-depth: 2 + submodules: recursive + + - uses: gautamkrishnar/keepalive-workflow@master + + # Enable tmate debugging of manually-triggered workflows if the input option was provided + - name: Setup tmate session + uses: mxschmitt/action-tmate@v3 + if: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.debug_enabled }} + env: + SECRETS_CONTEXT: ${{ toJson(secrets) }} + + - name: Populate Fermion Variables + id: check + run: python3 ../.github/workflows/populate_variables.py + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + # Check if we are building a new Fermion tag + - uses: mukunku/tag-exists-action@v1.1.0 + id: checkTag + with: + tag: v${{ steps.check.outputs.FERMION_TAG }} + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + build: + needs: + - update + if: ${{ needs.update.outputs.NO_BUILD == 'false' }} + + # Build Matrix + strategy: + matrix: + os: [macos-latest, ubuntu-latest, windows-latest] + + # Create tasks across our build matrix + runs-on: ${{ matrix.os }} + steps: + - name: Checkout + uses: actions/checkout@v3 + with: + fetch-depth: 2 + submodules: recursive + + - uses: actions/setup-node@v3 + with: + node-version: '16' + + # Update dependency versions in the package manifest & install + - name: Update Frida package + id: npmi + run: | + export npm_config_runtime=electron + export npm_config_target=${{needs.update.outputs.FRIDA_ELECTRON}} + npm install + npm i @types/frida-gum@${{needs.update.outputs.FRIDA_GUM_VER}} + npm i frida@${{needs.update.outputs.FRIDA_VER}} + echo "ELECTRON_VER=${{needs.update.outputs.FRIDA_ELECTRON}}" >> $GITHUB_OUTPUT + + - name: Prepare building.. + run: | + OUT='${{ github.workspace }}/build' + echo "OUT=$OUT" >> $GITHUB_ENV + rm -rf "$OUT" + mkdir "$OUT" + + # Package Fermion across our build matrix + - name: Build Windows + if: runner.os == 'Windows' + run: | + npx electron-packager . --icon ./src/images/fermion-ico.ico --out "$OUT" + - name: Build Linux + if: runner.os == 'Linux' + run: | + npx electron-packager . --icon ./src/images/fermion-ico.png --out "$OUT" + - name: Build macOS + if: runner.os == 'macOS' + run: | + npx electron-packager . --icon ./src/images/fermion-ico.icns --out "$OUT" + + # Archive fermion + - name: Package build asset + run: | + cd "$OUT" + find . -type d -name node_modules -prune -exec ls -ald "{}" \; + ZIPNAME="fermion-${{ matrix.os }}-v${{ needs.update.outputs.FERMION_TAG }}" + if command -v zip > /dev/null; then + (cd *; zip -qr "../$ZIPNAME.zip" .) + else + (cd *; python3 -c "import shutil; shutil.make_archive('../$ZIPNAME', 'zip', '.')") + fi + ls -al + + # Upload action artifact as-is + - name: Upload to GitHub Actions artifact + uses: NyaMisty/upload-artifact-as-is@master + with: + path: ${{ env.OUT }}/fermion-*.zip + + release: + runs-on: ubuntu-latest + needs: + - update + - build + name: "release" + + steps: + - name: "Create artifact directory" + run: | + mkdir -p build_output + working-directory: ${{ runner.temp }} + + - name: "Download all artifacts" + uses: actions/download-artifact@v2 + with: + path: ${{ runner.temp }}/build_output + + - name: "Rearrange artifacts" + run: | + find build_output + mkdir -p build_release + mv build_output/*/* build_release + ls build_release + if [ "$(ls -A build_release)" ]; then exit 0; else exit 1; fi + working-directory: ${{ runner.temp }} + + - name: Checkout + uses: actions/checkout@v3 + with: + fetch-depth: 2 + submodules: recursive + + - name: Update package index + run: | + export npm_config_runtime=electron + export npm_config_target=${{needs.update.outputs.FRIDA_ELECTRON}} + npm install + npm i @types/frida-gum@${{needs.update.outputs.FRIDA_GUM_VER}} + npm i frida@${{needs.update.outputs.FRIDA_VER}} + + - name: Update badgen & compile instructions + run: | + # Set new frida version for badgen + perl -i -pe 's|badgen.net/badge/Frida-Node/v[\d.]+?/grey|badgen.net/badge/Frida-Node/v${{ needs.update.outputs.FRIDA_VER }}/grey|' ../README.md + + # Set new gum version for badgen + perl -i -pe 's|badgen.net/badge/Frida-Gum/v[\d.]+?/grey|badgen.net/badge/Frida-Gum/v${{ needs.update.outputs.FRIDA_GUM_VER }}/grey|' ../README.md + + # Set new electron version for README + perl -i -pe 's|npm_config_target=[\d.]+|npm_config_target=${{ needs.update.outputs.FRIDA_ELECTRON }}|' ../README.md + + # This is still a todo + - name: Update Frida assets + run: | + /bin/bash .github/workflows/update_fermion_asset.sh + working-directory: ${{ github.workspace }} + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + # Commit + - name: Update Versions to Git + id: bumpver + run: | + if ! [ -z "$(git status --untracked-files=no --porcelain)" ]; then + AUTOUPDATE_PATTERN="^\[AutoUpdate\]" + preserve_branch=0 + if ! [[ "$(git log -1 --pretty=%B)" =~ $AUTOUPDATE_PATTERN ]]; then + preserve_branch=1 + git branch -f before_auto_update + fi + + git config --local user.email "41898282+github-actions[bot]@users.noreply.github.com" + git config --local user.name "github-actions[bot]" + git commit -a -m "[AutoUpdate] v${{ needs.update.outputs.FERMION_TAG }}" + + git push origin master + + if [[ "$preserve_branch" == "1" ]]; then + git push -f origin before_auto_update + fi + fi + echo "CURRENT_SHA=$(git rev-parse HEAD)" >> $GITHUB_OUTPUT + + # Release + - name: Create New Release and Upload + if: ${{ !startsWith(github.ref, 'refs/tags/') }} + uses: ncipollo/release-action@v1 + with: + artifacts: "${{ runner.temp }}/build_release/*" + name: "${{ format('Fermion v{0}', needs.update.outputs.FERMION_TAG, needs.update.outputs.FRIDA_VER, needs.update.outputs.FRIDA_GUM_VER) }}" + body: "${{ format('Electron: {0}\nFrida: {1}\nGumJS: {2}\nBuild: Windows, Linux, Mac\n', needs.update.outputs.FRIDA_ELECTRON, needs.update.outputs.FRIDA_VER, needs.update.outputs.FRIDA_GUM_VER) }}" + tag: v${{ needs.update.outputs.FERMION_TAG }} + commit: ${{ steps.bumpver.outputs.CURRENT_SHA }} + prerelease: false + allowUpdates: true + + # NOTE: edit this to false & true if you want to preserve original artifact + removeArtifacts: true + replacesArtifacts: false + artifactErrorsFailBuild: true + token: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file diff --git a/.github/workflows/populate_variables.py b/.github/workflows/populate_variables.py new file mode 100644 index 0000000..b1bdb7c --- /dev/null +++ b/.github/workflows/populate_variables.py @@ -0,0 +1,38 @@ +import requests +import re +import json +import os + +from _github_api_helper import github_api_get + +# Get latests Frida version +fridaLatestRelease = github_api_get('https://api.github.com/repos/frida/frida/releases/latest') +fridaVer = fridaLatestRelease['tag_name'] + +# Get latests Frida Gum version +fridaGumVer = requests.get('https://registry.npmjs.org/@types/frida-gum').json()['dist-tags']['latest'] + +# Get Electron ver from package index +with open(os.path.dirname(os.path.abspath(__file__)) + "/../../" + "Fermion/package.json", 'r') as f: + fridaElectronVer = json.load(f)['dependencies']['electron'] + +# Get package ver from package index +with open(os.path.dirname(os.path.abspath(__file__)) + "/../../" + "Fermion/package.json", 'r') as f: + fermionVer = json.load(f)['version'] +fermionVer = fermionVer.split("-")[0] +fermionTag = "%s" % (fermionVer) + +import os, json +if 'GITHUB_OUTPUT' in os.environ: + f = open(os.environ['GITHUB_OUTPUT'], "a") + output = lambda x: f.write(x) +else: + output = print + +print("[?] Build on Electron: ", fridaElectronVer) +print("[?] Latest Frida version: ", fridaVer) + +output("FRIDA_VER=%s\n" % fridaVer) +output("FRIDA_GUM_VER=%s\n" % fridaGumVer) +output("FRIDA_ELECTRON=%s\n" % fridaElectronVer) +output("FERMION_TAG=%s\n" % fermionTag) diff --git a/.github/workflows/update_fermion_asset.sh b/.github/workflows/update_fermion_asset.sh new file mode 100644 index 0000000..9316619 --- /dev/null +++ b/.github/workflows/update_fermion_asset.sh @@ -0,0 +1,21 @@ +#!/bin/bash + +####### +## This needs more work +####### + +## +# Auto-update JS docs in about.html +# |_ It may be best to integrate a markdown reader into about this way docs can +# be ingested from https://github.com/frida/frida-website/blob/master/_i18n/en/_docs/javascript-api.md +## + +# Get updated js docs +#docOutput=$(curl -s "https://frida.re/docs/javascript-api/"); +#copyStart=$(echo "$docOutput"| grep -n "Table of contents" |awk -F: '{print $1}'); +#copyEnd=$(echo "$docOutput"| grep -n "section-nav" |awk -F: '{print $1}'); +#newDoc=$(echo "$docOutput" | sed -n "$copyStart,$((copyEnd - 1))p"); + +## +# Auto-generate version image for about.html +## \ No newline at end of file diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 7483a52..a9ca54f 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -114,4 +114,22 @@ -= Fermion v1.8.1 =- -* Minor release to bugfix #15 \ No newline at end of file +* Minor release to bugfix #15 + +-= Fermion v1.9 =- + +* Upgrade Electron v13.3.0 -> v21.0.0 +* Upgrade Frida v15.1.3 -> v16.0.5 +* Some fixes added for changes in Electron v14+ +* Change Frida TypeScript language bindings to use the Frida Gum node package instead or a local resource +* Allow Fermion to dynamically display the current Frida version on load +* Allow Fermion to dynamically display it's own version on load +* Fix for incorrectly parsing application arguments in some cases +* Implemented GitHub CI for Fermion +* MacOS release packages reintroduced with CI +* A number of documentation, process, HTML changes +* Added scrollbar to "Process List" +* Make User, PID, PPID and Process columns sortable +* Closed most of the items related to #14 +* Update inline documentation +* NOTE: A big thanks to @MiscMisty for the great PR \ No newline at end of file diff --git a/Fermion/core.js b/Fermion/core.js index dd2cc84..3cd551f 100644 --- a/Fermion/core.js +++ b/Fermion/core.js @@ -26,6 +26,10 @@ function createWindow() { webviewTag: true } }); + + // needed after electron v14.0.1 + // https://stackoverflow.com/questions/69059668/enableremotemodule-is-missing-from-electron-v14-typescript-type-definitions/69059669#69059669 + require('@electron/remote/main').enable(bWin.webContents); // and load the index.html of the app. bWin.loadFile(path.join(__dirname, '/pages/index.html')); diff --git a/Fermion/package.json b/Fermion/package.json index 72cd772..bdfd49c 100644 --- a/Fermion/package.json +++ b/Fermion/package.json @@ -1,6 +1,6 @@ { "name": "fermion", - "version": "1.8.1", + "version": "1.9.0", "description": "Fermion is a stand-alone Frida electron tool.", "main": "core.js", "scripts": { @@ -11,8 +11,9 @@ "license": "BSD-3-Clause", "dependencies": { "@electron/remote": "^2.0.0", - "electron": "13.3.0", - "frida": "15.1.3", + "@types/frida-gum": "^18.3.0", + "electron": "21.0.0", + "frida": "^16.0.7", "jquery": "3.6.0", "monaco-editor": "0.30.0", "mutex-promise": "0.1.0", diff --git a/Fermion/pages/device.html b/Fermion/pages/device.html index 5664299..0a5de23 100644 --- a/Fermion/pages/device.html +++ b/Fermion/pages/device.html @@ -3,6 +3,7 @@ @@ -73,62 +74,63 @@