Inital (stash) commit
This commit is contained in:
commit
f86ed5fda6
20
LICENSE
Normal file
20
LICENSE
Normal file
@ -0,0 +1,20 @@
|
||||
Copyright (c) 2023 Sivert V. Sæther
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included
|
||||
in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
17
asm/Makefile
Normal file
17
asm/Makefile
Normal file
@ -0,0 +1,17 @@
|
||||
|
||||
.PHONY: clean
|
||||
|
||||
SOOPTS := -shared -nostdlib
|
||||
OUT := out
|
||||
|
||||
test: $(OUT)
|
||||
$(CC) $(SOOPTS) pt.s -o $(OUT)/pt.so
|
||||
|
||||
build: $(OUT)
|
||||
$(CC) $(SOOPTS) loud.s -o $(OUT)/libloud.so
|
||||
|
||||
$(OUT):
|
||||
mkdir $(OUT)
|
||||
|
||||
clean:
|
||||
$(RM) -r $(OUT)
|
182
asm/fork.s
Normal file
182
asm/fork.s
Normal file
@ -0,0 +1,182 @@
|
||||
.intel_syntax noprefix
|
||||
.file "fork.s"
|
||||
.text
|
||||
|
||||
.data
|
||||
.section .rodata
|
||||
child_msg:
|
||||
.string "Made a child!\n"
|
||||
child_wait:
|
||||
.string "Child attach!\n"
|
||||
fuck:
|
||||
.string "Fuck you!\n"
|
||||
.text
|
||||
.globl main
|
||||
.type main, @function
|
||||
main:
|
||||
# fork
|
||||
mov rax, 57
|
||||
syscall
|
||||
cmp rax, 0
|
||||
jl no_fork
|
||||
jg ctrl
|
||||
|
||||
child:
|
||||
# trace me
|
||||
mov rax, 101
|
||||
mov rdi, 0
|
||||
xor rsi, rsi
|
||||
xor rdx, rdx
|
||||
xor r10, r10
|
||||
syscall
|
||||
# print
|
||||
mov rax, 1
|
||||
mov rdi, 1
|
||||
lea rsi, [rip + child_wait]
|
||||
mov rdx, 14
|
||||
syscall
|
||||
# wait!
|
||||
mov rax, 110
|
||||
syscall
|
||||
mov rdi, rax
|
||||
mov rax, 61
|
||||
xor rsi, rsi
|
||||
xor rdx, rdx
|
||||
xor r10, r10
|
||||
syscall
|
||||
cmp rax, 0
|
||||
jge print
|
||||
.rept 42069
|
||||
nop
|
||||
.endr
|
||||
print:
|
||||
mov rax, 1
|
||||
mov rdi, 1
|
||||
lea rsi, [rip + child_msg]
|
||||
mov rdx, 14
|
||||
syscall
|
||||
ret
|
||||
|
||||
.data
|
||||
pid:
|
||||
.quad 0
|
||||
regsptr:
|
||||
.quad 0
|
||||
.section .rodata
|
||||
ctrl_msg:
|
||||
.string "Parent is watching!\n"
|
||||
.text
|
||||
ctrl:
|
||||
# store ptrs
|
||||
mov [rip + pid], rax
|
||||
mov rdi, 216
|
||||
call malloc
|
||||
mov [rip + regsptr], rax
|
||||
# wait and set ptrace option
|
||||
call wait
|
||||
mov rax, 101
|
||||
mov rdi, 0x4200
|
||||
mov rsi, [rip + pid]
|
||||
xor rdx, rdx
|
||||
mov r10, 0x100000
|
||||
syscall
|
||||
mov rax, 1
|
||||
mov rdi, 2
|
||||
lea rsi, [rip + ctrl_msg]
|
||||
mov rdx, 20
|
||||
syscall
|
||||
loop:
|
||||
# ptrace enter syscall
|
||||
mov rax, 101
|
||||
mov rdi, 24
|
||||
mov rsi, [rip + pid]
|
||||
xor rdx, rdx
|
||||
xor r10, r10
|
||||
syscall
|
||||
cmp rax, 0
|
||||
jl ctrl_err
|
||||
call wait
|
||||
cmp rax, 0
|
||||
jl ctrl_err
|
||||
# fetch child regs
|
||||
mov rax, 101
|
||||
mov rdi, 12
|
||||
mov rsi, [rip + pid]
|
||||
xor rdx, rdx
|
||||
lea r10, [rip + regsptr]
|
||||
syscall
|
||||
cmp rax, 0
|
||||
jl ctrl_err
|
||||
# skip non write syscalls
|
||||
cmp rax, 1
|
||||
jne skip
|
||||
cmp rdi, 2
|
||||
jg skip
|
||||
|
||||
mov rax, 1
|
||||
mov rdi, 2
|
||||
lea rsi, [rip + ctrl_err_msg]
|
||||
mov rdx, 9
|
||||
syscall
|
||||
|
||||
skip:
|
||||
mov rax, 101
|
||||
mov rdi, 24
|
||||
mov rsi, [rip + pid]
|
||||
xor rdx, rdx
|
||||
xor r10, r10
|
||||
syscall
|
||||
cmp rax, 0
|
||||
jl ctrl_err
|
||||
jmp loop
|
||||
|
||||
.data
|
||||
.section .rodata
|
||||
parent_wait:
|
||||
.string "Parent waiting!\n"
|
||||
.text
|
||||
wait:
|
||||
mov rax, 1
|
||||
mov rdi, 2
|
||||
mov rsi, [rip + parent_wait]
|
||||
mov rdx, 16
|
||||
syscall
|
||||
mov rax, 61
|
||||
mov rdi, [rip + pid]
|
||||
xor rsi, rsi
|
||||
xor rdx, rdx
|
||||
xor r10, r10
|
||||
syscall
|
||||
cmp rax, 0
|
||||
jl ctrl_err
|
||||
ret
|
||||
|
||||
.data
|
||||
.section .rodata
|
||||
ctrl_err_msg:
|
||||
.string "Fuck you!\n"
|
||||
.text
|
||||
ctrl_err:
|
||||
mov rax, 1
|
||||
mov rdi, 2
|
||||
mov rsi, [rip + ctrl_err_msg]
|
||||
mov rdx, 10
|
||||
syscall
|
||||
mov rax, 60
|
||||
mov rdi, 69
|
||||
syscall
|
||||
|
||||
.data
|
||||
.section .rodata
|
||||
no_fork_msg:
|
||||
.string "Unable to fork!\n"
|
||||
.text
|
||||
no_fork:
|
||||
mov rax, 1
|
||||
mov rdi, 2
|
||||
mov rsi, [rip + no_fork_msg]
|
||||
mov rdx, 15
|
||||
syscall
|
||||
mov rax, 60
|
||||
mov rdi, 420
|
||||
syscall
|
19
asm/loud.s
Normal file
19
asm/loud.s
Normal file
@ -0,0 +1,19 @@
|
||||
.intel_syntax noprefix
|
||||
.file "lOuD.S"
|
||||
.text
|
||||
|
||||
.section .init_array
|
||||
.quad pre
|
||||
|
||||
.text
|
||||
.globl pre
|
||||
.type pre, @function
|
||||
pre:
|
||||
# .init_array shit to prevent segv
|
||||
pushq rbp
|
||||
movq rbp, rsp
|
||||
subq rsp, 16
|
||||
# do fun stuff
|
||||
|
||||
leave
|
||||
ret
|
170
asm/pt.s
Normal file
170
asm/pt.s
Normal file
@ -0,0 +1,170 @@
|
||||
.intel_syntax noprefix
|
||||
.file "pt.s"
|
||||
.text
|
||||
|
||||
# pointers in the .init_array section of shared object files are called by the dynamic linker at load
|
||||
# before main and even _start of the actual excecutable
|
||||
.section .init_array
|
||||
.quad pre
|
||||
|
||||
# everything before the next comment is needed for correct linking
|
||||
# and to run some arbitrary code before an excecutable
|
||||
.text
|
||||
.globl pre
|
||||
.type pre, @function
|
||||
pre:
|
||||
pushq rbp
|
||||
movq rbp, rsp
|
||||
subq rsp, 16
|
||||
# fork and setup ptrace
|
||||
mov rax, 57
|
||||
syscall
|
||||
cmp rax, 0 # zero means we're a child
|
||||
jl err_nofork # negative means we were unable to fork
|
||||
je leave # leave to the actual executable we're fucking with
|
||||
jg ctrl # positive indicates we're the parent-/inital-process
|
||||
# and just in case (this should never run, unless jumed to by address)
|
||||
jmp err_nofork
|
||||
|
||||
# run some actual program this shared object unfortunately got dynamically loaded into
|
||||
leave:
|
||||
# ptrace me first
|
||||
mov rax, 101
|
||||
xor rdi, rdi
|
||||
xor rsi, rsi
|
||||
xor rdx, rdx
|
||||
xor r10, r10
|
||||
syscall
|
||||
# then leave
|
||||
leave
|
||||
ret
|
||||
|
||||
# hijack and fuck with all write syscalls
|
||||
ctrl:
|
||||
# store child pid
|
||||
mov [rip + pid], rax
|
||||
# malloc some mem to store captured register values from child
|
||||
mov rdi, 216 # size of user_regs_struct on x86_64 machines running Linux
|
||||
call malloc
|
||||
mov [rip + regsptr], rax
|
||||
call wait
|
||||
# ptrace set option exit kill
|
||||
mov rax, 101
|
||||
mov rdi, 0x4200
|
||||
mov rsi, [rip + pid]
|
||||
mov rdx, 0
|
||||
mov r10, 0x100000
|
||||
syscall
|
||||
ctrl_loop:
|
||||
# ptrace enter syscall
|
||||
mov rax, 101
|
||||
mov rdi, 24
|
||||
mov rsi, [rip + pid]
|
||||
mov rdx, 0
|
||||
mov r10, 0
|
||||
syscall
|
||||
cmp rax, -1
|
||||
jne err_ctrl
|
||||
call wait
|
||||
cmp rax, -1
|
||||
jne err_ctrl
|
||||
# fetch register values from child about to perform a syscall
|
||||
mov rax, 101
|
||||
mov rdi, 12
|
||||
mov rsi, [rip + pid]
|
||||
mov rdx, 0
|
||||
lea r10, [rip + regsptr]
|
||||
syscall
|
||||
|
||||
# don't fuck with non write syscalls
|
||||
cmp rax, 1
|
||||
jne skip
|
||||
# also skip if write destination ain't std-out/-err
|
||||
cmp rdi, 2
|
||||
jg skip
|
||||
# the syscall is a write to std-out/-err
|
||||
|
||||
mov rax, 1
|
||||
mov rdi, 2
|
||||
lea rsi, [rip + msg]
|
||||
mov rdx, 10
|
||||
syscall
|
||||
skip:
|
||||
# let the child complete the syscall we captured
|
||||
mov rax, 101
|
||||
mov rdi, 24
|
||||
mov rsi, [rip + pid]
|
||||
mov rdx, 0
|
||||
mov r10, 0
|
||||
syscall
|
||||
cmp rax, -1
|
||||
jne err_ctrl
|
||||
jmp ctrl_loop
|
||||
|
||||
# waitid syscall for parent to sync with / wait for child
|
||||
wait:
|
||||
mov rax, 247
|
||||
mov rdi, [rip + pid]
|
||||
mov rsi, 0
|
||||
mov rdx, 0
|
||||
syscall
|
||||
ret
|
||||
|
||||
# ptrace syscall with common args for parent-/ctrl-process
|
||||
ptrace:
|
||||
mov rax, 101
|
||||
mov rsi, [rip + pid]
|
||||
syscall
|
||||
ret
|
||||
|
||||
# exit syscall
|
||||
exit:
|
||||
mov rax, 60
|
||||
syscall
|
||||
|
||||
err_ctrl:
|
||||
mov rax, 1
|
||||
mov rdi, 2
|
||||
lea rsi, [rip + msg]
|
||||
mov rdx, 10
|
||||
syscall
|
||||
mov rax, 60
|
||||
mov rdi, 42069
|
||||
syscall
|
||||
|
||||
# write no_fork to stderr and return
|
||||
# hopefully to the start of some executable
|
||||
err_nofork:
|
||||
mov rax, 1
|
||||
mov rdi, 2
|
||||
lea rsi, [rip + no_fork]
|
||||
mov rdx, 15
|
||||
syscall
|
||||
leave
|
||||
ret
|
||||
|
||||
.section .data
|
||||
regsptr:
|
||||
.quad 0
|
||||
pid: # store child process pid here
|
||||
.quad 0
|
||||
# user_regs_struct with labels to the parts we care about
|
||||
#regs:
|
||||
# .fill 27 8 0
|
||||
# .fill 10 8
|
||||
#_rax:
|
||||
# .fill 1 8
|
||||
# .fill 1 8
|
||||
#_rdx:
|
||||
# .fill 1 8
|
||||
#_rsi:
|
||||
# .fill 1 8
|
||||
#_rdi:
|
||||
# .fill 1 8
|
||||
# .fill 12 8
|
||||
|
||||
.section rodata
|
||||
no_fork:
|
||||
.string "Unable to fork!\n"
|
||||
msg:
|
||||
.string "Fuck you!\n"
|
1
hs/.gitignore
vendored
Normal file
1
hs/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
dist-newstlye
|
19
hs/csrc/pre.c
Normal file
19
hs/csrc/pre.c
Normal file
@ -0,0 +1,19 @@
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
|
||||
extern void hs_init(int*, char***);
|
||||
extern void hs_exit();
|
||||
extern void setup();
|
||||
|
||||
int argc = 0;
|
||||
char* argv[] = { NULL };
|
||||
char** pargv = argv;
|
||||
|
||||
void __attribute__((constructor)) pre() {
|
||||
hs_init(&argc, &pargv);
|
||||
setup();
|
||||
}
|
||||
|
||||
void __attribute__((destructor)) post() {
|
||||
hs_exit();
|
||||
}
|
52
hs/loud.cabal
Normal file
52
hs/loud.cabal
Normal file
@ -0,0 +1,52 @@
|
||||
cabal-version: 3.4
|
||||
name: loud
|
||||
version: 0.1.0
|
||||
-- synopsis:
|
||||
-- description:
|
||||
license: MIT
|
||||
license-file: LICENSE
|
||||
author: Sivert V. Sæther
|
||||
maintainer: gmail@sivert.pw
|
||||
category: Prank
|
||||
build-type: Simple
|
||||
extra-source-files: cbits
|
||||
|
||||
common warnings
|
||||
ghc-options: -Wall
|
||||
|
||||
foreign-library loud
|
||||
type: native-shared
|
||||
other-extensions: CApiFFI
|
||||
other-modules: Loud
|
||||
build-depends:
|
||||
bytestring ^>= 0.11.4.0,
|
||||
vector ^>= 0.13.0.0,
|
||||
base ^>= 4.18.0.0
|
||||
hs-source-dirs: src
|
||||
-- asm-sources: pre.s
|
||||
c-sources: csrc/pre.c
|
||||
default-language: GHC2021
|
||||
|
||||
library
|
||||
import: warnings
|
||||
exposed-modules: Loud
|
||||
other-extensions: CApiFFI
|
||||
build-depends:
|
||||
bytestring ^>= 0.11.4.0,
|
||||
vector ^>= 0.13.0.0,
|
||||
base ^>= 4.18.0.0,
|
||||
mmap ^>= 0.5.9
|
||||
hs-source-dirs: src
|
||||
asm-sources: pre.s
|
||||
-- c-sources: csrc/pre.c
|
||||
default-language: GHC2021
|
||||
|
||||
test-suite loud-test
|
||||
import: warnings
|
||||
default-language: GHC2021
|
||||
type: exitcode-stdio-1.0
|
||||
hs-source-dirs: test
|
||||
main-is: Main.hs
|
||||
build-depends:
|
||||
base ^>=4.18.0.0,
|
||||
loud
|
23
hs/pre.s
Normal file
23
hs/pre.s
Normal file
@ -0,0 +1,23 @@
|
||||
.intel_syntax noprefix
|
||||
.file "pre.s"
|
||||
.text
|
||||
|
||||
.extern hs_init
|
||||
.extern setup
|
||||
|
||||
.section .init_array, "aw"
|
||||
.quad pre
|
||||
|
||||
.text
|
||||
.global pre
|
||||
.type pre, @function
|
||||
pre:
|
||||
pushq rbp
|
||||
movq rbp, rsp
|
||||
subq rsp, 16
|
||||
|
||||
call hs_init
|
||||
call setup
|
||||
|
||||
leave
|
||||
ret
|
22
hs/src/Loud.hs
Normal file
22
hs/src/Loud.hs
Normal file
@ -0,0 +1,22 @@
|
||||
module Loud ( write ) where
|
||||
|
||||
import Data.String ( fromString )
|
||||
import Data.ByteString
|
||||
import Foreign.Ptr
|
||||
import Foreign.C
|
||||
|
||||
setup :: IO ()
|
||||
setup = putStrLn "Fuck you!"
|
||||
|
||||
write :: IO Int
|
||||
write = do
|
||||
let msg = "Hello, Haskell!\n"
|
||||
useAsCStringLen (fromString msg :: ByteString) sus_write
|
||||
|
||||
sus_write :: CStringLen -> IO Int
|
||||
sus_write (cstr, len) = _syscall 1 1 (minusPtr cstr nullPtr) len 0 0
|
||||
|
||||
foreign import ccall "syscall"
|
||||
_syscall :: Int -> Int -> Int -> Int -> Int -> Int -> IO Int
|
||||
|
||||
foreign export ccall setup :: IO ()
|
6
hs/test/Main.hs
Normal file
6
hs/test/Main.hs
Normal file
@ -0,0 +1,6 @@
|
||||
module Main (main) where
|
||||
|
||||
import Loud ( write )
|
||||
|
||||
main :: IO Int
|
||||
main = write
|
2
rs/.gitignore
vendored
Normal file
2
rs/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
/target
|
||||
/Cargo.lock
|
11
rs/Cargo.toml
Normal file
11
rs/Cargo.toml
Normal file
@ -0,0 +1,11 @@
|
||||
[package]
|
||||
name = "loud"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[lib]
|
||||
crate-type = ["cdylib"]
|
||||
|
||||
[dependencies]
|
||||
libc = "0.2.144"
|
||||
ctor = "0.2.0"
|
14
rs/src/lib.rs
Normal file
14
rs/src/lib.rs
Normal file
@ -0,0 +1,14 @@
|
||||
|
||||
#[ctor::ctor]
|
||||
fn pre() {
|
||||
println!("Fuck you");
|
||||
}
|
||||
/*
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn write(fd: libc::c_int, buf: *const libc::c_void, len: libc::size_t) -> libc::ssize_t {
|
||||
println!("hook'd!");
|
||||
libc::write(fd, buf, len)
|
||||
}
|
||||
*/
|
||||
#[cfg(test)]
|
||||
mod test;
|
Loading…
x
Reference in New Issue
Block a user