Skip to content

Commit c346877

Browse files
Update Linux mode (#246)
- Fix issue #244 - Modified gdb scripts to use a python venv - Included qol updates so you aren't prompted multiple times on long `setup.sh` builds - upgraded to gcc-11 / clang 20 - formatted sh scripts - Made sure Linux mode works on Ubuntu 24.04 out of the box, and added instructions to make it work for Ubuntu 22.04 --------- Co-authored-by: 0vercl0k <1476421+0vercl0k@users.noreply.github.com>
1 parent d2cad9d commit c346877

File tree

8 files changed

+196
-116
lines changed

8 files changed

+196
-116
lines changed

.github/workflows/wtf.yml

Lines changed: 68 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -8,93 +8,93 @@ jobs:
88
strategy:
99
fail-fast: false
1010
matrix:
11-
generator: ['ninja', 'msvc']
11+
generator: ["ninja", "msvc"]
1212

1313
name: Windows latest / ${{ matrix.generator }}
1414
steps:
15-
- name: Checkout
16-
uses: actions/checkout@v4
15+
- name: Checkout
16+
uses: actions/checkout@v4
1717

18-
- name: Add msbuild to PATH
19-
uses: microsoft/setup-msbuild@v2
18+
- name: Add msbuild to PATH
19+
uses: microsoft/setup-msbuild@v2
2020

21-
- name: Setup vs prompt
22-
uses: ilammy/msvc-dev-cmd@v1
21+
- name: Setup vs prompt
22+
uses: ilammy/msvc-dev-cmd@v1
2323

24-
- name: Build with Ninja/cl
25-
if: matrix.generator == 'ninja'
26-
run: |
27-
cd src\build
28-
.\build-release.bat
24+
- name: Build with Ninja/cl
25+
if: matrix.generator == 'ninja'
26+
run: |
27+
cd src\build
28+
.\build-release.bat
2929
30-
- name: Build with msvc
31-
if: matrix.generator == 'msvc'
32-
run: |
33-
cd src\build
34-
.\build-release-msvc.bat
30+
- name: Build with msvc
31+
if: matrix.generator == 'msvc'
32+
run: |
33+
cd src\build
34+
.\build-release-msvc.bat
3535
36-
- name: Copy dbghelp/symsrv
37-
if: matrix.generator == 'ninja'
38-
run: |
39-
copy "c:\program Files (x86)\windows kits\10\debuggers\x64\dbghelp.dll" src/build
40-
copy "c:\program Files (x86)\windows kits\10\debuggers\x64\dbgeng.dll" src/build
41-
copy "c:\program Files (x86)\windows kits\10\debuggers\x64\dbgcore.dll" src/build
42-
copy "c:\program Files (x86)\windows kits\10\debuggers\x64\symsrv.dll" src/build
36+
- name: Copy dbghelp/symsrv
37+
if: matrix.generator == 'ninja'
38+
run: |
39+
copy "c:\program Files (x86)\windows kits\10\debuggers\x64\dbghelp.dll" src/build
40+
copy "c:\program Files (x86)\windows kits\10\debuggers\x64\dbgeng.dll" src/build
41+
copy "c:\program Files (x86)\windows kits\10\debuggers\x64\dbgcore.dll" src/build
42+
copy "c:\program Files (x86)\windows kits\10\debuggers\x64\symsrv.dll" src/build
4343
44-
- name: Upload artifacts
45-
if: matrix.generator == 'ninja'
46-
uses: actions/upload-artifact@v4
47-
with:
48-
name: bin-win64.RelWithDebInfo
49-
path: |
50-
src/build/wtf.exe
51-
src/build/wtf.pdb
52-
src/build/dbghelp.dll
53-
src/build/dbgeng.dll
54-
src/build/dbgcore.dll
55-
src/build/symsrv.dll
44+
- name: Upload artifacts
45+
if: matrix.generator == 'ninja'
46+
uses: actions/upload-artifact@v4
47+
with:
48+
name: bin-win64.RelWithDebInfo
49+
path: |
50+
src/build/wtf.exe
51+
src/build/wtf.pdb
52+
src/build/dbghelp.dll
53+
src/build/dbgeng.dll
54+
src/build/dbgcore.dll
55+
src/build/symsrv.dll
5656
5757
Linux:
5858
runs-on: ubuntu-latest
5959
strategy:
6060
fail-fast: false
6161
matrix:
62-
compiler: ['clang', 'gcc']
62+
compiler: ["clang", "gcc"]
6363

6464
name: Ubuntu latest / ${{ matrix.compiler }}
6565
steps:
66-
- name: Checkout
67-
uses: actions/checkout@v4
66+
- name: Checkout
67+
uses: actions/checkout@v4
6868

69-
- name: Installing dependencies
70-
run: |
71-
sudo apt-get -y update
72-
sudo apt install -y g++-10 ninja-build
73-
sudo bash -c "$(wget -O - https://apt.llvm.org/llvm.sh)"
69+
- name: Installing dependencies
70+
run: |
71+
sudo apt-get -y update
72+
sudo apt install -y g++-10 ninja-build
73+
sudo bash -c "$(wget -O - https://apt.llvm.org/llvm.sh)"
7474
75-
- name: Build with gcc
76-
if: matrix.compiler == 'gcc'
77-
env:
78-
CC: gcc-10
79-
CXX: g++-10
80-
run: |
81-
cd src/build
82-
chmod u+x ./build-release.sh
83-
./build-release.sh
75+
- name: Build with gcc
76+
if: matrix.compiler == 'gcc'
77+
env:
78+
CC: gcc-10
79+
CXX: g++-10
80+
run: |
81+
cd src/build
82+
chmod u+x ./build-release.sh
83+
./build-release.sh
8484
85-
- name: Build with clang
86-
if: matrix.compiler == 'clang'
87-
env:
88-
CC: clang-20
89-
CXX: clang++-20
90-
run: |
91-
cd src/build
92-
chmod u+x ./build-release.sh
93-
./build-release.sh
85+
- name: Build with clang
86+
if: matrix.compiler == 'clang'
87+
env:
88+
CC: clang-20
89+
CXX: clang++-20
90+
run: |
91+
cd src/build
92+
chmod u+x ./build-release.sh
93+
./build-release.sh
9494
95-
- name: Upload artifacts
96-
uses: actions/upload-artifact@v4
97-
with:
98-
name: bin-lin64-${{ matrix.compiler }}.Release
99-
path: |
100-
src/build/wtf
95+
- name: Upload artifacts
96+
uses: actions/upload-artifact@v4
97+
with:
98+
name: bin-lin64-${{ matrix.compiler }}.Release
99+
path: |
100+
src/build/wtf

linux_mode/README.md

Lines changed: 52 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,61 @@
1313

1414
## Overview
1515

16-
This provides experimental Linux ELF userland snapshotting support based on previous work by [Kasimir](https://github.com/0vercl0k/wtf/pull/102) and scripts from [Snapchange](https://github.com/awslabs/snapchange/tree/main/qemu_snapshot).
16+
This provides experimental Linux ELF userland snapshotting support based on previous work by [Kasimir](https://github.com/0vercl0k/wtf/pull/102) and scripts from [Snapchange](https://github.com/awslabs/snapchange/tree/main/qemu_snapshot). It has been tested and should work out of the box against [Ubuntu 'Noble Numbat' 24.04](https://ubuntu.com/download/desktop?version=24.04&architecture=amd64&lts=true).
1717

1818
<p align='center'>
1919
<img src='../pics/wtf-linux-snapshot.webp'>
2020
</p>
2121

22+
It also has been tested against [Ubuntu 'Jammy Jellyfish' 22.04](https://releases.ubuntu.com/jammy/) but requires you to rebuild [`libbochscpu_ffi.a`](../src/libs/bochscpu-bins/lib/libbochscpu_ffi.a) in order to build `wtf`. Otherwise, you will encounter these linker errors:
23+
24+
```console
25+
user@pc:~/wtf/src/build$ CXX=clang++-20 CC=clang-20 ./build-release.sh
26+
...
27+
[36/36] Linking CXX executable wtf
28+
FAILED: wtf
29+
...
30+
/usr/bin/ld: ../libs/bochscpu-bins/lib/libbochscpu_ffi.a(85d2494f718bd438-paramtree.o): in function `bx_param_num_c::parse_param(char const*)':
31+
paramtree.cc:(.text._ZN14bx_param_num_c11parse_paramEPKc+0x5b): undefined reference to `__isoc23_strtoull'
32+
/usr/bin/ld: paramtree.cc:(.text._ZN14bx_param_num_c11parse_paramEPKc+0xa9): undefined reference to `__isoc23_strtoull'
33+
/usr/bin/ld: paramtree.cc:(.text._ZN14bx_param_num_c11parse_paramEPKc+0xd5): undefined reference to `__isoc23_strtoull'
34+
/usr/bin/ld: paramtree.cc:(.text._ZN14bx_param_num_c11parse_paramEPKc+0x111): undefined reference to `__isoc23_strtoull'
35+
/usr/bin/ld: ../libs/bochscpu-bins/lib/libbochscpu_ffi.a(85d2494f718bd438-paramtree.o): in function `bx_param_bytestring_c::parse_param(char const*)':
36+
paramtree.cc:(.text._ZN21bx_param_bytestring_c11parse_paramEPKc+0x97): undefined reference to `__isoc23_sscanf'
37+
/usr/bin/ld: ../libs/bochscpu-bins/lib/libbochscpu_ffi.a(msr.o): in function `BX_CPU_C::load_MSRs(char const*)':
38+
/mnt/c/work/codes/wtf/src/libs/bochscpu-bins/bxbuild-lin/bochscpu-build/Bochs/bochs/cpu/msr.cc:1557: undefined reference to `__isoc23_sscanf'
39+
clang++-20: error: linker command failed with exit code 1 (use -v to see invocation)
40+
ninja: build stopped: subcommand failed.
41+
```
42+
43+
Rebuild `libbochscpu_ffi` by running the [build-bochscpu.sh](../src/libs/bochscpu-bins/build-bochscpu.sh) script like so to build the `libbochscpu_ffi.a` library (a Rust toolchain is needed; you can install it with `curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh`)..:
44+
45+
```console
46+
user@pc:~/wtf/src/libs/bochscpu-bins$ bash build-bochscpu.sh
47+
...
48+
Finished `release` profile [optimized] target(s) in 11.81s
49+
~/wtf/src/libs/bochscpu-bins
50+
user@pc:~/wtf/src/libs/bochscpu-bins$ ls bxbuild-lin/bochscpu-ffi/target/x86_64-unknown-linux-gnu/release/*.a
51+
bxbuild-lin/bochscpu-ffi/target/x86_64-unknown-linux-gnu/release/libbochscpu_ffi.a
52+
```
53+
54+
..this should have generated a `libbochscpu_ffi.a` file. Move into `src/libs/bochscpu-bins/lib`:
55+
56+
```console
57+
user@pc:~/wtf/src/libs/bochscpu-bins$ mv bxbuild-lin/bochscpu-ffi/target/x86_64-unknown-linux-gnu/release/libbochscpu_ffi.a lib
58+
user@pc:~/wtf/src/libs/bochscpu-bins$ git status
59+
...
60+
modified: lib/libbochscpu_ffi.a
61+
```
62+
63+
Linking `wtf` should now be working successfully:
64+
65+
```console
66+
user@pc:~/wtf/src/build$ CXX=clang++-20 CC=clang-20 ./build-release.sh
67+
...
68+
[1/1] Linking CXX executable wtf
69+
```
70+
2271
## Setting up the environment
2372

2473
Move into the `linux_mode/qemu_snapshot` directory and run `setup.sh`:
@@ -63,6 +112,8 @@ Start the virtual machine in one tab while in the snapshot subdirectory by runni
63112
user@pc:/wtf/linux_mode/crash_test$ ../qemu_snapshot/gdb_server.sh
64113
```
65114

115+
(If you are running into `Could not access KVM kernel module: Permission denied` or KVM related errors, close an re-open your shell. `setup.sh` added the current user to the `kvm` group and it seems to require to close / re-open the shell).
116+
66117
In a separate tab, scp the target file to the target VM. With `crash_test` this can be done by first compiling the target file:
67118

68119
```console
@@ -161,7 +212,6 @@ Breakpoint 1, 0x00005555555551e9 in do_crash_test ()
161212
```
162213

163214
## Harnessing and Fuzzing
164-
165215
Writing harnesses is the same process as writing harnesses for Windows executables. Example harnesses for crash_test and page_fault_test are present in [src/wtf/fuzzer_linux_crash_test.cc](../src/wtf/fuzzer_linux_crash_test.cc) and [src/wtf/fuzzer_linux_page_fault_test.cc](../src/wtf/fuzzer_linux_page_fault_test.cc).
166216

167217
Now that we have everything set up we can start our server and fuzzer:

linux_mode/qemu_snapshot/gdb_client.sh

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
#!/bin/bash
22

3+
34
# get our environmental variables
45
export LINUX_MODE_BASE=../
56
export WTF=${LINUX_MODE_BASE}../
7+
PYTHON_SITE_PACKAGES=$(echo ../qemu_snapshot/target_vm/venv/lib/python3.*/site-packages/)
8+
export PYTHONPATH=${PYTHONPATH}:${PYTHON_SITE_PACKAGES}
69
export PYTHONPATH=${PYTHONPATH}:${LINUX_MODE_BASE}/qemu_snapshot
710
export KERNEL=${LINUX_MODE_BASE}qemu_snapshot/target_vm/linux/vmlinux
811
export LINUX_GDB=${LINUX_MODE_BASE}qemu_snapshot/target_vm/linux/scripts/gdb/vmlinux-gdb.py
@@ -15,5 +18,7 @@ gdb \
1518
-iex "add-auto-load-safe-path ${LINUX_GDB}" \
1619
-ex "set confirm off" \
1720
-ex "target remote localhost:1234" \
21+
-ex "python import sys; sys.path.insert(0, '${LINUX_MODE_BASE}qemu_snapshot/target_vm/linux/scripts/gdb')" \
22+
-ex "source ${LINUX_GDB}" \
1823
-x ./bkpt.py \
1924
-ex continue

linux_mode/qemu_snapshot/gdb_fuzzbkpt.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,11 @@
1212
import subprocess
1313
import pathlib
1414
import lief
15+
import glob
1516

17+
venv_site_packages = glob.glob("../qemu_snapshot/target_vm/venv/lib/python3.*/site-packages")
18+
if venv_site_packages:
19+
sys.path.insert(0, venv_site_packages[0])
1620
currentdir = pathlib.Path(inspect.getfile(inspect.currentframe()))
1721
currentdir = currentdir.absolute().parent
1822
sys.path.insert(0, str(currentdir.parent / "qemu_snapshot"))

linux_mode/qemu_snapshot/target_vm/image/create-image.sh

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,12 @@ echo "root soft memlock unlimited" | sudo tee -a $DIR/etc/securit
168168
# Example for setting afl-system-config.sh to run automatically on reboot
169169
#sudo cp ./afl-system-config.sh $DIR/root
170170
#sudo chroot $DIR /bin/bash -c "(crontab -l 2>/dev/null; echo \"@reboot /root/afl-system-config.sh\") | crontab -"
171-
ssh-keygen -f $RELEASE.id_rsa -t rsa -N ''
171+
172+
# Don't regenerate key if it already exists
173+
if [ ! -f "$RELEASE.id_rsa" ]; then
174+
ssh-keygen -f $RELEASE.id_rsa -t rsa -N ''
175+
fi
176+
172177
sudo mkdir -p $DIR/root/.ssh/
173178
cat $RELEASE.id_rsa.pub | sudo tee $DIR/root/.ssh/authorized_keys
174179

0 commit comments

Comments
 (0)