├── .gitignore ├── Cargo.toml ├── .gitmodules ├── src ├── tor_sys.rs └── main.rs ├── LICENSE └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | /Cargo.lock 2 | /target 3 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "rtsw-poc" 3 | version = "0.1.0" 4 | authors = ["Chad Retz "] 5 | build = "build.rs" -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "vendor/openssl"] 2 | path = vendor/openssl 3 | url = https://github.com/openssl/openssl.git 4 | [submodule "vendor/libevent"] 5 | path = vendor/libevent 6 | url = https://github.com/libevent/libevent.git 7 | [submodule "vendor/zlib"] 8 | path = vendor/zlib 9 | url = https://github.com/madler/zlib.git 10 | [submodule "vendor/xz"] 11 | path = vendor/xz 12 | url = http://git.tukaani.org/xz.git 13 | [submodule "vendor/tor"] 14 | path = vendor/tor 15 | url = https://github.com/torproject/tor.git 16 | -------------------------------------------------------------------------------- /src/tor_sys.rs: -------------------------------------------------------------------------------- 1 | use std::os::raw::{c_char, c_int}; 2 | 3 | #[repr(C)] 4 | #[derive(Debug,Copy,Clone)] 5 | pub struct tor_main_configuration_t { 6 | _unused: [u8; 0] 7 | } 8 | 9 | extern "C" { 10 | pub fn tor_main_configuration_new() -> *mut tor_main_configuration_t; 11 | 12 | pub fn tor_main_configuration_set_command_line(cfg: *mut tor_main_configuration_t, 13 | argc: c_int, 14 | argv: *mut *mut c_char) -> c_int; 15 | 16 | pub fn tor_main_configuration_free(cfg: *mut tor_main_configuration_t); 17 | 18 | pub fn tor_run_main(arg1: *const tor_main_configuration_t) -> c_int; 19 | 20 | pub fn tor_main(argc: c_int, argv: *mut *mut c_char) -> c_int; 21 | } -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | use std::os::raw::c_char; 2 | use std::ffi::CString; 3 | 4 | pub mod tor_sys; 5 | 6 | fn main() { 7 | unsafe { 8 | // Create the conf 9 | let conf = tor_sys::tor_main_configuration_new(); 10 | // Create a set of args as though we called this from CLI 11 | let mut args: Vec<*mut c_char> = vec![CString::new("tor.exe").unwrap().into_raw(), 12 | CString::new("--version").unwrap().into_raw()]; 13 | let res = tor_sys::tor_main_configuration_set_command_line(conf, 2, args.as_mut_ptr()); 14 | if res != 0 { 15 | panic!("Result from conf set: {}", res); 16 | } 17 | // Run main and clean up args 18 | let res = tor_sys::tor_run_main(conf); 19 | tor_sys::tor_main_configuration_free(conf); 20 | if res != 0 { 21 | panic!("Result from main: {}", res); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Chad Retz 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Rust + Tor (embedded) + Static (compile) + Windows + Proof of Concept 2 | 3 | This project makes a standalone executable built in Rust that statically compiles Tor and all of its dependencies. It 4 | uses the new (as of this writing) 5 | [0.3.3.1-alpha](https://blog.torproject.org/tor-0331-alpha-released-back-unstable-development) version which includes 6 | embedding via a small, supported API. The simple goal of this project is to make the Tor version string appear. I put a 7 | compiled version of `rtsw-poc.exe` in the [releases area](https://github.com/cretz/rtsw-poc/releases). 8 | 9 | The [vendor/](vendor) folder contains all of the dependencies as submodules. So clone this repository with 10 | `--recursive`. The dependencies are: 11 | 12 | * [OpenSSL](https://github.com/openssl/openssl/) - Checked out at tag `OpenSSL_1_0_2n` 13 | * [Libevent](https://github.com/libevent/libevent) - Checked out at tag `release-2.1.8-stable` 14 | * [zlib](https://github.com/madler/zlib) - Checked out at tag `v1.2.11` 15 | * [XZ Utils](https://git.tukaani.org/?p=xz.git) - Checked out at tag `v5.2.3` 16 | * [Tor](https://github.com/torproject/tor) - Checked out at tag `tor-0.3.3.1-alpha` 17 | 18 | Many many bugs and quirks were hit while deriving these steps. Also many other repos, mailing lists, etc were leveraged 19 | to get some of the pieces right. They are not listed here for brevity reasons. 20 | 21 | ### Building 22 | 23 | #### Msys2 and MinGW Setup 24 | 25 | Tor is not really designed to work well with MSVC so we use MinGW instead. Since we are statically compiling, this means 26 | we use the MinGW form of Rust too. In order to compile the dependencies, Msys2 + MinGW should be installed. 27 | 28 | Download and install the latest [MSYS2 64-bit](http://www.msys2.org/) that uses the `MinGW-w64` toolchains. Once 29 | installed, open the "MSYS MinGW 64-bit" shell link that was created. Once in the shell, run: 30 | 31 | pacman -Syuu 32 | 33 | Terminate and restart the shell if asked. Rerun this command as many times as needed until it reports that everything is 34 | up to date. Then in the same mingw-64 shell, run: 35 | 36 | pacman -Sy --needed base-devel mingw-w64-i686-toolchain mingw-w64-x86_64-toolchain \ 37 | git subversion mercurial \ 38 | mingw-w64-i686-cmake mingw-w64-x86_64-cmake 39 | 40 | This will install all the tools needed for building and will take a while. Once complete, we have to downgrade a couple 41 | of packages due to a bug in the current MinGW libraries. In the same shell, run: 42 | 43 | pacman -U /var/cache/pacman/pkg/mingw-w64-x86_64-crt-git-5.0.0.4745.d2384c2-1-any.pkg.tar.xz 44 | pacman -U /var/cache/pacman/pkg/mingw-w64-x86_64-headers-git-5.0.0.4747.0f8f626-1-any.pkg.tar.xz 45 | pacman -U /var/cache/pacman/pkg/mingw-w64-x86_64-winpthreads-git-5.0.0.4741.2c8939a-1-any.pkg.tar.xz \ 46 | /var/cache/pacman/pkg/mingw-w64-x86_64-libwinpthread-git-5.0.0.4741.2c8939a-1-any.pkg.tar.xz 47 | 48 | At least these were the cached package names on my install, they may be different on others. Once complete, MinGW is now 49 | setup to build the dependencies. 50 | 51 | #### Clone Repo 52 | 53 | Inside the mingw-64 shell, clone this repo and submodules: 54 | 55 | git clone --recursive https://github.com/cretz/rtsw-poc.git 56 | 57 | Then you can `cd rtsw-poc`. We will assume throughout this guide that you are starting at the cloned root. 58 | 59 | #### OpenSSL 60 | 61 | Inside the mingw-64 shell, navigate to the OpenSSL folder and build it: 62 | 63 | cd vendor/openssl 64 | ./Configure --prefix=$PWD/dist no-shared no-dso no-zlib mingw64 65 | make depend 66 | make 67 | make install 68 | 69 | This will put OpenSSL libs at `dist/lib`. 70 | 71 | #### Libevent 72 | 73 | Inside the mingw-64 shell, navigate to the Libevent folder and build it: 74 | 75 | cd vendor/libevent 76 | ./autogen.sh 77 | ./configure --prefix=$PWD/dist --disable-shared --enable-static --with-pic 78 | make 79 | make install 80 | 81 | This will put Libevent libs at `dist/lib`. 82 | 83 | #### zlib 84 | 85 | Inside the mingw-64 shell, navigate to the zlib folder and build it: 86 | 87 | cd vendor/zlib 88 | PREFIX=$PWD/dist make -fwin32/Makefile.gcc 89 | PREFIX=$PWD/dist BINARY_PATH=$PWD/dist/bin INCLUDE_PATH=$PWD/dist/include LIBRARY_PATH=$PWD/dist/lib make install -fwin32/Makefile.gcc 90 | 91 | This will put zlib libs at `dist/lib`. 92 | 93 | #### XZ Utils 94 | 95 | Inside the mingw-64 shell, navigate to the XZ Utils folder and build it: 96 | 97 | cd vendor/xz 98 | ./autogen.sh 99 | ./configure --prefix=$PWD/dist \ 100 | --disable-shared \ 101 | --enable-static \ 102 | --disable-doc \ 103 | --disable-scripts \ 104 | --disable-xz \ 105 | --disable-xzdec \ 106 | --disable-lzmadec \ 107 | --disable-lzmainfo \ 108 | --disable-lzma-links 109 | make 110 | make install 111 | 112 | This will put XZ Utils libs at `dist/lib`. 113 | 114 | #### Tor 115 | 116 | Inside the mingw-64 shell, navigate to the tor folder and build it: 117 | 118 | cd vendor/tor 119 | ./autogen.sh 120 | LIBS=-lcrypt32 ./configure --prefix=$PWD/dist \ 121 | --disable-gcc-hardening \ 122 | --enable-static-tor \ 123 | --enable-static-libevent \ 124 | --with-libevent-dir=$PWD/../libevent/dist \ 125 | --enable-static-openssl \ 126 | --with-openssl-dir=$PWD/../openssl/dist \ 127 | --enable-static-zlib \ 128 | --with-zlib-dir=$PWD/../openssl/dist \ 129 | --disable-system-torrc \ 130 | --disable-asciidoc 131 | ln -s $PWD/../zlib/dist/lib/libz.a $PWD/../openssl/dist/lib/libz.a 132 | make 133 | make install 134 | 135 | This will put Tor libs throughout the `src` area. 136 | 137 | #### Rust 138 | 139 | Install Rust in Windows which installs `rustup`. Then, from a `cmd` prompt with administrator privileges, run: 140 | 141 | rustup toolchain install stable-x86_64-pc-windows-gnu 142 | rustup default stable-gnu 143 | 144 | Rust is now set to the MinGW 64 compiler by default. 145 | 146 | #### Proof of Concept Program 147 | 148 | From a `cmd` prompt with administrator privileges, navigate to repo root and run: 149 | 150 | cargo run 151 | 152 | This will output: 153 | 154 | Tor version 0.3.3.1-alpha (git-de8bc9eed6eaadfc). 155 | 156 | To generate a self-contained executable, run: 157 | 158 | cargo build --release 159 | 160 | The executable will be at `target/release/rtsw-poc.exe`. My version is ~21MB. 161 | 162 | This uses the new [tor_api.h](https://github.com/torproject/tor/blob/tor-0.3.3.1-alpha/src/or/tor_api.h) introduced 163 | [here](https://trac.torproject.org/projects/tor/ticket/23684). Ideally we would make `build.rs` work with multiple 164 | targets, automate the building of dependencies, etc but this is just a PoC. --------------------------------------------------------------------------------