-
Notifications
You must be signed in to change notification settings - Fork 11
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
8 changed files
with
433 additions
and
312 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,6 @@ | ||
[package] | ||
name = "Autorun" | ||
version = "0.1.1" | ||
version = "0.2.0" | ||
authors = ["Vurv78 <[email protected]>"] | ||
edition = "2018" | ||
|
||
|
@@ -10,16 +10,17 @@ edition = "2018" | |
crate-type = ["dylib"] | ||
|
||
[dependencies] | ||
# detour-rs static detours needs nightly, which sucks since nightly breaks rls, I don't wanna bother trying to search up how to fix that. | ||
detour = { version = "0.7.1", default-features = false } | ||
|
||
libc = "0.2.85" # FFI Types | ||
winapi = {version = "0.3.9", features = ["consoleapi"]} | ||
# lua_shared bindings | ||
rglua = { git = "https://github.com/Vurv78/rglua", branch = "main" } | ||
|
||
# DLL Loading | ||
dlopen = "0.1.8" | ||
dlopen_derive = "0.1.4" | ||
# Detour lua_loadbufferx and other functions | ||
detour = { version = "0.8.0", default-features = false } | ||
|
||
dirs = "3.0.1" # To get your home directory. | ||
# Global Mutable Variables | ||
once_cell = "1.7.2" | ||
atomic = "0.5.0" | ||
|
||
lazy_static = "1.4.0" | ||
# Misc | ||
winapi = {version = "0.3.9", features = ["consoleapi"]} | ||
dirs = "3.0.1" # To get your home directory. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,29 +1,40 @@ | ||
## Autorun-rs [![Release Shield](https://img.shields.io/github/v/release/Vurv78/Autorun-rs)](https://github.com/Vurv78/Autorun-rs/releases/latest) [![License](https://img.shields.io/github/license/Vurv78/Autorun-rs?color=red)](https://opensource.org/licenses/Apache-2.0) ![CI](https://github.com/Vurv78/Autorun-rs/workflows/Build/badge.svg) [![github/Vurv78](https://discordapp.com/api/guilds/824727565948157963/widget.png)](https://discord.gg/epJFC6cNsw) | ||
# Autorun-rs | ||
[![Release Shield](https://img.shields.io/github/v/release/Vurv78/Autorun-rs)](https://github.com/Vurv78/Autorun-rs/releases/latest) | ||
[![License](https://img.shields.io/github/license/Vurv78/Autorun-rs?color=red)](https://opensource.org/licenses/Apache-2.0) | ||
![CI](https://github.com/Vurv78/Autorun-rs/workflows/Build/badge.svg) [![github/Vurv78](https://img.shields.io/discord/824727565948157963?color=7289DA&label=chat&logo=discord)](https://discord.gg/epJFC6cNsw) | ||
|
||
Garrysmod Lua Dumper / Runner, written in Rust. | ||
|
||
Like my other repo, https://github.com/Vurv78/Autorun, but written in Rust. | ||
Also, this has more features and is safer. | ||
|
||
The file structure starts at C:\Users\User\sautorun-rs\. | ||
The file structure starts at ``C:\Users\<User>\sautorun-rs\`` | ||
|
||
### Features | ||
* Lua dumping through hooked loadbufferx at C:\Users\User\sautorun-rs\lua_dumps\ServerIP\... (Use init_file_steal) | ||
* Lua loading through lua_run and lua_openscript | ||
* Could load lua scripts before autorun. | ||
* Not supported out of the box, could add it yourself relatively easily | ||
* Separate AllocConsole that allows for running commands (See the help command) | ||
* Works for both x64 and x86 windows. (Tested on Chromium / x86-64 branch) | ||
* Dumping all lua scripts to ``C:\Users\<User>\sautorun-rs\lua_dumps\<ServerIP>\..`` | ||
* Runtime lua loading through lua_run and lua_openscript in an external console | ||
* Supports x86 and x64 bit | ||
* Scripthook, stop & run scripts before anything runs on you, gives information & functions to assist in a safe separate lua fenv | ||
|
||
### Usage | ||
Get an injector (Make sure it's compatible to inject 32/64 bit code depending on your use). | ||
Use one of the build_win batchfiles to build the output dll, then inject that into garrysmod at the main menu. | ||
See the Notes for more info. | ||
|
||
### TODOs | ||
* Automating JoinServer hook | ||
* Making a lua script in sautorun run before autorun out of the box. | ||
|
||
### Notes | ||
This is Windows ONLY. Autorun might've had a chance at being multi-platform but this is absolutely not going to work with OSX/Linux. | ||
You need to call init_file_steal in your garrysmod main menu in the Autorun terminal, so that files will be dumped. | ||
* For now this is only supporting Windows. | ||
In the future this may be able to run on Linux/OSX but if that does happen I won't be able to actively support it. | ||
|
||
### Examples | ||
|
||
sautorun-rs/hook.lua | ||
```lua | ||
local script = sautorun.CODE | ||
if script:find("while true do end") then | ||
sautorun.log("Found a naughty script!") | ||
return true -- Exit from here & don't run the script | ||
end | ||
``` | ||
|
||
sautorun-rs/autorun.lua | ||
```lua | ||
sautorun.log( "Connected to server " .. sautorun.IP ) | ||
``` | ||
|
||
### TODOs | ||
* Actual GUI |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
use std::{ | ||
io::prelude::*, | ||
sync::atomic::Ordering, | ||
ffi::CStr, | ||
fs | ||
}; | ||
|
||
use crate::sys::{ | ||
funcs::getAutorunHandle, | ||
statics::*, | ||
runlua::runLuaEnv | ||
}; | ||
|
||
use rglua::{ | ||
lua_shared::*, | ||
types::* | ||
}; | ||
|
||
#[macro_export] | ||
macro_rules! get_cstring { | ||
($cstring:expr) => { | ||
{ | ||
#[allow(unused_unsafe)] | ||
let cstr = unsafe{ CStr::from_ptr($cstring) }; | ||
cstr.to_owned() | ||
} | ||
} | ||
} | ||
|
||
pub extern fn loadbufferx(state: LuaState, code: CharBuf, size: SizeT, identifier: CharBuf, mode: CharBuf) -> CInt { | ||
if state != std::ptr::null_mut() { | ||
CURRENT_LUA_STATE.store(state, Ordering::Relaxed); | ||
} | ||
|
||
// If JoinServer hasn't been hooked, hook it. | ||
let _ = JOIN_SERVER.get_or_try_init(|| { | ||
lua_getglobal!( state, cstring!("JoinServer") ); | ||
let hook = match unsafe { detour::GenericDetour::new( lua_tocfunction(state, -1), crate::hooks::joinserver ) } { | ||
Ok(hook) => { | ||
unsafe { | ||
hook.enable().expect("Couldn't enable JoinServer hook"); | ||
} | ||
|
||
Ok(hook) | ||
} | ||
Err(why) => { | ||
eprintln!("Couldn't hook JoinServer. {}", why); | ||
return Err(()); | ||
} | ||
}; | ||
lua_pop!(state, 1); | ||
hook | ||
}); | ||
|
||
// Todo: Check if you're in menu state (Not by checking MENU_DLL because that can be modified by lua) and if so, don't dump files. | ||
// Dump the file to sautorun-rs/lua_dumps/IP/... | ||
let raw_path = &rstring!(identifier)[1 ..]; // Remove the @ from the beginning of the path. | ||
let server_ip = CURRENT_SERVER_IP.load( Ordering::Relaxed ); | ||
|
||
let loadbuffer_h = &*LUAL_LOADBUFFERX; | ||
|
||
let mut autoran = false; | ||
let mut do_run = true; | ||
if raw_path == "lua/includes/init.lua" { | ||
if let Ok(_) = HAS_AUTORAN.compare_exchange(false, true, Ordering::Relaxed, Ordering::Relaxed) { | ||
// This will only run once when HAS_AUTORAN is false, setting it to true. | ||
// Will be reset by JoinServer. | ||
if let Ok(script) = fs::read_to_string(&*AUTORUN_SCRIPT_PATH) { | ||
// Try to run here | ||
runLuaEnv(&script, identifier, code, server_ip, true); | ||
autoran = true; | ||
} else { | ||
eprintln!( "Couldn't read your autorun script file at {}/{}", SAUTORUN_DIR.display(), AUTORUN_SCRIPT_PATH.display() ); | ||
} | ||
} | ||
} | ||
|
||
if !autoran { | ||
if let Ok(script) = fs::read_to_string(&*HOOK_SCRIPT_PATH) { | ||
if runLuaEnv(&script, identifier, code, server_ip, false) { | ||
// If you return ``true`` in your sautorun/hook.lua file, then don't run the sautorun.CODE that is about to run. | ||
if lua_type(state, 1) == rglua::globals::Lua::Type::Bool as i32 { | ||
do_run = lua_toboolean(state, 1) == 0; | ||
lua_pop!(state, 1); | ||
} | ||
} | ||
} | ||
|
||
} | ||
|
||
if let Some(mut file) = getAutorunHandle(raw_path, server_ip) { | ||
if let Err(why) = file.write_all( get_cstring!(code).as_bytes() ) { | ||
eprintln!("Couldn't write to file made from lua path [{}]. {}", raw_path, why); | ||
} | ||
} | ||
|
||
if do_run { | ||
return loadbuffer_h.call( state, code, size, identifier, mode ); // Call the original function and return the value. | ||
} | ||
0 | ||
} | ||
|
||
// Since the first lua state will always be the menu state, just keep a variable for whether joinserver has been hooked or not, | ||
// If not, then hook it. | ||
pub extern fn joinserver(state: LuaState) -> CInt { | ||
let ip = rstring!( lua_tolstring(state, 1, 0) ); | ||
println!("Joining Server with IP {}!", ip); | ||
|
||
CURRENT_SERVER_IP.store(ip, Ordering::Relaxed); // Set the IP so we know where to write files in loadbufferx. | ||
HAS_AUTORAN.store(false, Ordering::Relaxed); | ||
if let Some(hook) = JOIN_SERVER.get() { | ||
// We could retrieve the hook from our global variables | ||
hook.call(state); | ||
} else { | ||
eprintln!("Failed to get JOIN_SERVER hook from global state"); | ||
} | ||
0 | ||
} |
Oops, something went wrong.