diff --git a/.gitignore b/.gitignore
index dfe16e4..468018e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,8 +1,11 @@
-*.order
-*.symvers
-Revird
-*.ko
-TaxiDriver.mod.c
-imgui.ini
*.o
*.cmd
+*.symvers
+*.ko
+*.mod*
+*.order
+km/build/*
+um/main
+um/test/test_app
+um/test/libmath_module.so
+imgui.ini
\ No newline at end of file
diff --git a/.gitmodules b/.gitmodules
deleted file mode 100644
index 830ab12..0000000
--- a/.gitmodules
+++ /dev/null
@@ -1,6 +0,0 @@
-[submodule "imgui"]
- path = imgui
- url = https://github.com/ocornut/imgui/
-[submodule "src/client/imgui"]
- path = src/client/imgui
- url = https://github.com/ocornut/imgui/
diff --git a/Makefile b/Makefile
deleted file mode 100644
index 0dde011..0000000
--- a/Makefile
+++ /dev/null
@@ -1,36 +0,0 @@
-# Makefile for Linux Kernel Driver
-CONFIG_MODULE_SIG=n
-
-# Source files and object files
-SRC_DIR := src
-SOURCE_FILES := $(wildcard $(SRC_DIR)/*.c)
-OBJ_FILES := src/TaxiDriver.o
-obj-m := $(OBJ_FILES)
-# KERNELDIR ?= /home/maxime/Downloads/linux-6.5.7-arch1/
-KERNELDIR ?= /lib/modules/6.5.8-arch1-1/build/
-# Kernel module name
-MODULE_NAME := TaxiDriver
-
-all: default
-
-default:
- $(MAKE) -C $(KERNELDIR) M=$(PWD) modules
- mv src/$(MODULE_NAME).ko .
- $(MAKE) clean
- cd src/client && $(MAKE)
-
-clean:
- find src/ -maxdepth 1 -type f ! -name "*.h" ! -name "*.c" -exec rm {} \;
-
-fclean: clean
- find . -maxdepth 1 -type f ! -name "Makefile" -exec rm {} \;
-
-load:
- sudo insmod $(MODULE_NAME).ko
- sudo mknod /dev/$(MODULE_NAME) c 511 0
-
-unload:
- sudo rmmod $(MODULE_NAME)
- sudo rm /dev/$(MODULE_NAME)
-
-.PHONY: all clean fclean load unload
diff --git a/README.md b/README.md
index daa2ab5..b76d566 100644
--- a/README.md
+++ b/README.md
@@ -1,53 +1,78 @@
# TaxiDriver
-W/RPM Driver and usermode for Linux.
-Some things in the client are still not finished :
-* X11 overlay
+Linux Kernel Module for RPM/WPM and usermode driver with examples.
-# Features
+## Features
* Get the base address of any process/loaded .so file
* RPM
* WPM
-# Compiling
-To compile the driver you'll need to be at least on kernel version v6.5.8 (i used the [arch kernel](https://github.com/archlinux/linux/releases/tag/v6.5.8-arch1)).
-
-## Prerequises :
-You'll need git, linux-headers, SDL3 and OpenGL :
+## Compiling
+### Prerequises :
```
-sudo pacman -S git linux-headers OpenGL
+sudo pacman -S git linux-headers OpenGL cmake
yay -S sdl3-git
```
+### Upstream Linux Kernel
+To compile the driver you'll need to be at least on kernel version v6.5 (i used the [arch kernel](https://github.com/archlinux/linux/releases/tag/v6.5.8-arch1)).
+### legacy Linux Kernel
+To build for an older Linux Kernel ex. 5.15 change KERNEL_UPSTREAM preprocessor definition
+in TaxiDriver.h:
+`#define KERNEL_UPSTREAM 0`
+or if you use cmake only change required in CmakeLists.txt:
+`add_compile_definitions(TaxiDriver PRIVATE KERNEL_UPSTREAM=0)`
-## Compiling and running :
-Clone the repo, prepare imgui (still in active dev) :
+### Compiling and running :
```
-git clone https://github.com/ALittlePatate/TaxiDriver --recursive
-chmod +x prepare_imgui.sh
-./prepare_imgui.sh
+git clone --recursive https://github.com/ALittlePatate/TaxiDriver
```
-Compile :
+#### Kernel Module
+choose and write a MAJOR number ex. 506 in install.sh and validate for uniqueness `grep "506" /proc/devices`
```
-make
+# sudo mknod /dev/TaxiDriver c 0
+# cmake is still incomplete
+cd km && ./install.sh
```
-Run the driver :
+system might still choose to set a different one, so read the number that is in use, after TaxiDriver is loaded,
+with `grep "TaxiDriver" /proc/devices` and adjust in mknod and reload TaxiDriver.
+After loading the Driver, you should find a line saying that TaxiDriver was loaded with X major code.
```
-sudo make load
sudo dmesg | grep TaxiDriver
```
-You should find a line saying that TaxiDriver was loaded with X major code.
-```
-sudo mknod /dev/TaxiDriver c X 0
-```
-replace X with your major code.
-Run the client :
-```
-sudo ./Revird
-```
Unload the driver :
```
-sudo make unload
+# sudo make unload
+sudo rmmod TaxiDriver
+sudo rm /dev/TaxiDriver
```
-# Contact
+#### Usermode Target/Test Application
+```
+cd um/test && make
+./test_app
+```
+
+#### Usermode Driver Application
+```
+cd um && make
+./main
+```
+
+
+### Known Issues
+- Fails to open device:
+MAJOR number has to match in mknod to open device! Check with `grep "TaxiDriver" /proc/devices`
+
+If you find anything not listed above. Please open up Issues on the Repo
+and provide the build log showing the issue with `LANG=C make` with all of your steps and envoirment info to reproduce.
+
+### Missing Features in development
+- ImGui Overlay
+- expand km mem functions
+- expand um driver example and test_app
+ - Findpattern
+ - write/inject shellcode with asm mid function hook
+- X11 Input Event Handling
+
+## Contact
If you have a problem regarding the code, open an issue or make a pull request, i'll be happy to add your contribution !
-If you need to contact me for any other reasons, message me at @_.patate on discord.
+If you need to contact me for any other reasons, message me at `_.patate` on discord.
diff --git a/km/CMakeLists.txt b/km/CMakeLists.txt
new file mode 100644
index 0000000..a3d1631
--- /dev/null
+++ b/km/CMakeLists.txt
@@ -0,0 +1,30 @@
+cmake_minimum_required(VERSION 3.12)
+project(TaxiDriverModule)
+
+# Set the source files for your module
+set(SRC ${CMAKE_SOURCE_DIR}/TaxiDriver.c)
+
+# Locate the kernel build directory
+execute_process(
+ COMMAND uname -r
+ OUTPUT_VARIABLE KERNEL_RELEASE
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+)
+set(KERNEL_BUILD_DIR /lib/modules/${KERNEL_RELEASE}/build)
+
+# Define the target
+add_custom_target(TaxiDriverModule ALL
+ COMMAND ${CMAKE_MAKE_PROGRAM} -C ${KERNEL_BUILD_DIR} M=${CMAKE_BINARY_DIR} modules
+ WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
+ COMMENT "Building TaxiDriver module"
+)
+
+# Define the clean target
+add_custom_target(clean_TaxiDriverModule
+ COMMAND ${CMAKE_MAKE_PROGRAM} -C ${KERNEL_BUILD_DIR} M=${CMAKE_BINARY_DIR} clean
+ WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
+ COMMENT "Cleaning TaxiDriver module"
+)
+
+# Specify the files to be cleaned
+set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES "${CMAKE_BINARY_DIR}/*.ko")
diff --git a/km/Makefile b/km/Makefile
new file mode 100644
index 0000000..1863457
--- /dev/null
+++ b/km/Makefile
@@ -0,0 +1,7 @@
+obj-m += TaxiDriver.o
+
+all:
+ make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
+
+clean:
+ make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
\ No newline at end of file
diff --git a/km/TaxiDriver.c b/km/TaxiDriver.c
new file mode 100644
index 0000000..d927f32
--- /dev/null
+++ b/km/TaxiDriver.c
@@ -0,0 +1,394 @@
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include // Add this header for basename function
+
+#define KERNEL_UPSTREAM 0
+#define TESTING 0
+#define DEBUG 0
+
+#if KERNEL_UPSTREAM==1
+#include
+#else
+#include
+#include
+#endif
+
+#define DRIVER_NAME "TaxiDriver"
+#define DRIVER
+#include "../um/communication_struct.h"
+
+static int major_number;
+static struct task_struct *task;
+
+static int device_open(struct inode *inode, struct file *file)
+{
+ return 0;
+}
+
+static int device_release(struct inode *inode, struct file *file)
+{
+ return 0;
+}
+
+#if TESTING == 1
+static unsigned long translate_physical_to_virtual(unsigned long paddr) {
+ unsigned long vaddr = 0xffff888000000000 | (paddr & (PAGE_SIZE - 1));
+ return vaddr;
+}
+#endif
+
+#if TESTING == 1
+static unsigned long translate_virtual_to_physical(struct mm_struct *mm, unsigned long vaddr) {
+ pgd_t *pgd;
+ p4d_t *p4d;
+ pud_t *pud;
+ pmd_t *pmd;
+ pte_t *pte;
+ unsigned long pfn;
+ unsigned long paddr = 0;
+
+ if (!mm)
+ return 0; // Handle invalid mm_struct
+
+ pgd = pgd_offset(mm, vaddr);
+ if (!pgd_present(*pgd))
+ return 0; // Handle invalid pgd
+
+ p4d = p4d_offset(pgd, vaddr);
+ if (!p4d_present(*p4d))
+ return 0; // Handle invalid p4d
+
+ pud = pud_offset(p4d, vaddr);
+ if (!pud_present(*pud))
+ return 0; // Handle invalid pud
+
+ pmd = pmd_offset(pud, vaddr);
+ if (!pmd_present(*pmd))
+ return 0; // Handle invalid pmd
+
+ pte = pte_offset_map(pmd, vaddr);
+ if (!pte_present(*pte))
+ return 0; // Handle invalid pte
+
+ pfn = page_to_pfn(pte_page(*pte));
+ paddr = (pfn << PAGE_SHIFT) | (vaddr & ~PAGE_MASK);
+ pte_unmap(pte);
+
+ return paddr;
+}
+#endif
+
+int RPM(t_RPM args) {
+ struct mm_struct *mm;
+ unsigned long value = 0;
+
+ printk(KERN_INFO "TaxiDriver: RPM --> addr : 0x%lx, size : %ld\n", args.addr, args.size);
+ if (!args.addr)
+ {
+ return -1;
+ }
+ if (!task) {
+ return -EINVAL; // Invalid argument
+ }
+ mm = get_task_mm(task);
+ if (mm) {
+ if (access_process_vm(task, args.addr, &value, args.size, 0) == args.size) {
+ printk(KERN_INFO "TaxiDriver: Value at 0x%lx: %lu\n", args.addr, value);
+ mmput(mm);
+ } else {
+ printk(KERN_ALERT "TaxiDriver: Failed to read value at 0x%lx\n", args.addr);
+ return -1;
+ }
+ }
+ return (int)value;
+}
+
+int WPM(t_WPM args) {
+ struct mm_struct *mm;
+ int ret = 0;
+
+ printk(KERN_INFO "TaxiDriver: WPM --> addr : 0x%lx, size : %ld, value : %ld\n",
+ args.addr, args.size, args.value);
+ if (!args.addr)
+ return -1;
+ if (!task) {
+ return -EINVAL; // Invalid argument
+ }
+ mm = get_task_mm(task);
+ if (mm) {
+ if (access_process_vm(task, args.addr, &args.value, args.size, 1) == args.size) {
+ printk(KERN_INFO "TaxiDriver: Successfully wrote value %lu to 0x%lx\n", args.value, args.addr);
+ mmput(mm);
+ } else {
+ printk(KERN_ALERT "TaxiDriver: Failed to write value at 0x%lx\n", args.addr);
+ ret = -1;
+ }
+ } else {
+ ret = -EINVAL;
+ }
+ return ret;
+}
+
+static uintptr_t list_process_modules(const char *mod) {
+ struct vm_area_struct *vma;
+#if KERNEL_UPSTREAM == 1
+ struct mm_struct *mm = task->mm;
+ VMA_ITERATOR(vmi, mm, 0);
+
+ for_each_vma(vmi, vma) {
+ if (vma->vm_file) {
+ struct file *file = vma->vm_file;
+ printk(KERN_INFO "TaxiDriver: Shared Library: %s start: 0x%lx end: 0x%lx\n",
+ file->f_path.dentry->d_name.name, vma->vm_start, vma->vm_end);
+ if (strcmp(file->f_path.dentry->d_name.name, mod) == 0)
+ return (uintptr_t)vma->vm_start;
+ }
+ }
+#else
+ struct task_struct *task;
+ struct mm_struct *mm;
+
+ for_each_process(task) {
+ mm = get_task_mm(task);
+
+ if (mm) {
+ printk(KERN_INFO "\nTaxiDriver: PARENT PID: %d PROCESS: %s", task->pid, task->comm);
+ down_read(&mm->mmap_lock);
+ for (vma = mm->mmap; vma; vma = vma->vm_next) {
+ printk(KERN_INFO "TaxiDriver: Address Range: 0x%lx - 0x%lx", vma->vm_start, vma->vm_end);
+
+ if (vma->vm_file) {
+ char buf[256];
+ char *file_name = d_path(&vma->vm_file->f_path, buf, sizeof(buf));
+ //const char *base_name = kbasename(file_name); // Extract the base name
+ printk(KERN_INFO "TaxiDriver: Mapped File: %s", file_name);
+ //printk(KERN_INFO "TaxiDriver: Mapped File: %s", base_name);
+ if (strcmp(file_name, mod) == 0)
+ //if (strcmp(base_name, mod) == 0) // Compare with the base name
+ //printk(KERN_INFO "TaxiDriver: Mapped File %s found at 0x%lx - 0x%lx", base_name, vma->vm_start, vma->vm_end);
+ return (uintptr_t)vma->vm_start;
+ }
+ }
+
+ up_read(&mm->mmap_lock);
+ mmput(mm);
+ }
+ }
+#endif
+ return 0;
+}
+
+//only checked for KERNEL_UPSTREAM == 0
+#if KERNEL_UPSTREAM == 0
+static unsigned long long list_pid_mod(t_PM args) {
+ printk(KERN_INFO "\nTaxiDriver list_pid_mod:%s", args.mod);
+ struct task_struct *task;
+ struct mm_struct *mm;
+ struct vm_area_struct *vma;
+
+ for_each_process(task) {
+ mm = get_task_mm(task);
+
+ if (mm) {
+ if(task->pid == args.pid)
+ {
+ printk(KERN_INFO "\nTaxiDriver: PARENT PID: %d PROCESS: %s", task->pid, task->comm);
+ }
+ down_read(&mm->mmap_lock);
+ for (vma = mm->mmap; vma; vma = vma->vm_next) {
+ //printk(KERN_INFO "TaxiDriver: Address Range: 0x%lx - 0x%lx", vma->vm_start, vma->vm_end);
+ if (vma->vm_file) {
+ char buf[256];
+ char *file_name = d_path(&vma->vm_file->f_path, buf, sizeof(buf));
+ const char *base_name = kbasename(file_name);
+ if (strcmp(base_name, args.mod) == 0)
+ {
+ unsigned long long vmstartaddr = (unsigned long long)vma->vm_start;
+ if(vmstartaddr>0)
+ {
+ printk(KERN_INFO "TaxiDriver: Mapped File %s found at 0x%lx - 0x%lx", base_name, vma->vm_start, vma->vm_end);
+ return vmstartaddr;
+ }
+ }
+ }
+ }
+ up_read(&mm->mmap_lock);
+ mmput(mm);
+ }
+ }
+ return 0;
+}
+#endif
+
+static int init_process_by_pid(int target_pid) {
+ printk(KERN_INFO "TaxiDriver: Accessing process with PID: %d\n", target_pid);
+
+ struct pid *pid_struct;
+ pid_struct = find_get_pid(target_pid);
+ if (pid_struct) {
+ task = get_pid_task(pid_struct, PIDTYPE_PID);
+ if (task) {
+ const char *process_name = task->comm;
+ printk(KERN_INFO "TaxiDriver: Process with PID %d has name: %s\n", target_pid, process_name);
+ put_task_struct(task);
+ } else {
+ printk(KERN_INFO "TaxiDriver: Process with PID %d not found\n", target_pid);
+ return -1;
+ }
+ put_pid(pid_struct);
+ } else {
+ printk(KERN_INFO "TaxiDriver: Process with PID %d not found\n", target_pid);
+ return -1;
+ }
+
+ return 1; // A successful module initialization
+}
+
+static long device_ioctl(struct file *file, unsigned int ioctl_num, unsigned long arg)
+{
+ struct s_WPM wpm_args;
+ struct s_RPM rpm_args;
+#if KERNEL_UPSTREAM == 0
+ struct s_PM pm_args;
+#endif
+ const char *mod = kmalloc(sizeof(char) * 256, GFP_KERNEL);
+ if (!mod)
+ {
+ return -ENOMEM;
+ }
+
+ static uintptr_t addr = 0;
+ int pid;
+ long return_value = 0;
+
+ switch (ioctl_num) {
+ case IOCTL_GETMODULE:
+ if (copy_from_user((void *)mod, (int *)arg, sizeof(char *)))
+ return -EFAULT;
+ return_value = list_process_modules(mod);
+ addr = return_value;
+ kfree(mod);
+ break;
+#if KERNEL_UPSTREAM == 0
+ case IOCTL_GETPIDMODULE:
+ if (copy_from_user(&pm_args, (int *)arg, sizeof(t_PM)))
+ return -EFAULT;
+
+ if (copy_from_user(mod, pm_args.mod, 256)) // ptr/data Userspace to Kernel else perms/page fault
+ {
+ return -EFAULT;
+ }
+ pm_args.mod = mod;
+
+ return_value = list_pid_mod(pm_args);
+ addr = return_value;
+ kfree(mod);
+ break;
+#endif
+ case IOCTL_OPENPROC:
+ if (copy_from_user(&pid, (int *)arg, sizeof(int)))
+ return -EFAULT;
+ return_value = init_process_by_pid(pid);
+ break;
+
+ case IOCTL_RPM:
+ if (copy_from_user(&rpm_args, (int *)arg, sizeof(t_RPM)))
+ return -EFAULT;
+ if (rpm_args.addr == 0x69420) {
+ put_user(addr, rpm_args.out_addr);
+ break;
+ }
+ return_value = RPM(rpm_args);
+ put_user(return_value, rpm_args.out_addr);
+ break;
+
+ case IOCTL_WPM:
+ if (copy_from_user(&wpm_args, (int *)arg, sizeof(t_WPM)))
+ return -EFAULT;
+ return_value = WPM(wpm_args);
+ break;
+#if KERNEL_UPSTREAM == 0 && TESTING==1
+ case IOCTL_VIRT_TO_PHYS:
+ {
+ struct mm_struct *mm = current->mm; // Get the current process's mm_struct
+ unsigned long vaddr;
+ unsigned long paddr;
+
+ if (copy_from_user(&vaddr, (unsigned long *)arg, sizeof(unsigned long))) {
+ return -EFAULT;
+ }
+
+ paddr = translate_virtual_to_physical(mm, vaddr);
+ return_value = paddr;
+ if (copy_to_user((unsigned long *)arg, &return_value, sizeof(unsigned long))) {
+ return -EFAULT;
+ }
+ }
+ break;
+#endif
+
+#if KERNEL_UPSTREAM == 0 && TESTING==1
+ case IOCTL_PHYS_TO_VIRT:
+ {
+ unsigned long paddr;
+ unsigned long vaddr;
+
+ if (copy_from_user(&paddr, (unsigned long *)arg, sizeof(unsigned long))) {
+ return -EFAULT;
+ }
+
+ vaddr = translate_physical_to_virtual(paddr);
+ if (copy_to_user((unsigned long *)arg, &vaddr, sizeof(unsigned long))) {
+ return -EFAULT;
+ }
+ }
+ break;
+#endif
+
+ default:
+ return -ENOTTY;
+ }
+#if KERNEL_UPSTREAM == 0 && TESTING==1
+ printk(KERN_INFO "return_value=0x%llx\n", (unsigned long long)return_value);
+#endif
+ return return_value;
+}
+
+static struct file_operations fops = {
+ .unlocked_ioctl = device_ioctl,
+ .open = device_open,
+ .release = device_release,
+};
+
+static int __init driver_init(void)
+{
+ printk(KERN_INFO "TaxiDriver: Loaded\n");
+
+ // Dynamically allocate the major number
+ major_number = register_chrdev(0, DRIVER_NAME, &fops);
+
+ if (major_number < 0) {
+ printk(KERN_ALERT "TaxiDriver: Failed to register the driver.\n");
+ return major_number;
+ }
+
+ printk(KERN_INFO "TaxiDriver: Registered %s with major number %d\n", DRIVER_NAME, major_number);
+
+ return 0;
+}
+
+static void __exit driver_exit(void)
+{
+ unregister_chrdev(major_number, DRIVER_NAME);
+ printk(KERN_INFO "TaxiDriver: Unloaded\n");
+}
+
+module_init(driver_init);
+module_exit(driver_exit);
+MODULE_LICENSE("GPL");
diff --git a/km/install.sh b/km/install.sh
new file mode 100755
index 0000000..1b8b2ff
--- /dev/null
+++ b/km/install.sh
@@ -0,0 +1,12 @@
+#!/bin/bash
+make clean
+make
+sudo rmmod TaxiDriver
+sudo rm /dev/TaxiDriver
+# choose a unique MAJOR number; read out the used number and adjust in mknod for next use.
+# MAJOR number has to match mknod to open device!
+# 511, 250, 505
+sudo mknod /dev/TaxiDriver c 506 0
+sudo chmod 666 /dev/TaxiDriver
+sudo insmod TaxiDriver.ko
+cat /proc/devices | grep -i "TaxiDriver"
diff --git a/prepare_imgui.sh b/prepare_imgui.sh
deleted file mode 100755
index dc0f191..0000000
--- a/prepare_imgui.sh
+++ /dev/null
@@ -1,5 +0,0 @@
-#!/bin/bash
-
-cd src/client/imgui/backends
-mv imgui_impl_opengl3* ..
-mv imgui_impl_sdl3* ..
diff --git a/src/TaxiDriver.c b/src/TaxiDriver.c
deleted file mode 100644
index 1cf48cf..0000000
--- a/src/TaxiDriver.c
+++ /dev/null
@@ -1,199 +0,0 @@
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#define DRIVER_NAME "TaxiDriver"
-#define DRIVER
-#include "client/communication_struct.h"
-
-static int major_number;
-static struct task_struct *task;
-
-static int device_open(struct inode *inode, struct file *file)
-{
- return 0;
-}
-
-static int device_release(struct inode *inode, struct file *file)
-{
- return 0;
-}
-
-int RPM(t_RPM args) {
- struct mm_struct *mm;
- unsigned long value = 0;
-
- printk(KERN_INFO "TaxiDriver: RPM --> addr : 0x%lx, size : %ld\n", args.addr, args.size);
- if (args.addr == 0)
- return -1;
- if (task == NULL) {
- return -EINVAL; // Invalid argument
- }
- mm = get_task_mm(task);
- if (mm != NULL) {
- if (access_process_vm(task, args.addr, &value, args.size, 0) == args.size) {
- printk(KERN_INFO "TaxiDriver: Value at 0x%lx: %lu\n", args.addr, value);
- mmput(mm);
- } else {
- printk(KERN_ALERT "TaxiDriver: Failed to read value at 0x%lx\n", args.addr);
- return -1;
- }
- }
- return (int)value;
-}
-
-int WPM(t_WPM args) {
- struct mm_struct *mm;
- int ret = 0;
-
- printk(KERN_INFO "TaxiDriver: WPM --> addr : 0x%lx, size : %ld, value : %ld\n",
- args.addr, args.size, args.value);
- if (args.addr == 0)
- return -1;
- if (task == NULL) {
- return -EINVAL; // Invalid argument
- }
- mm = get_task_mm(task);
- if (mm != NULL) {
- if (access_process_vm(task, args.addr, &args.value, args.size, 1) == args.size) {
- printk(KERN_INFO "TaxiDriver: Successfully wrote value %lu to 0x%lx\n", args.value, args.addr);
- mmput(mm);
- } else {
- printk(KERN_ALERT "TaxiDriver: Failed to write value at 0x%lx\n", args.addr);
- ret = -1;
- }
- } else {
- ret = -EINVAL;
- }
- return ret;
-}
-
-static uintptr_t list_process_modules(const char *mod) {
- struct mm_struct *mm = task->mm;
- struct vm_area_struct *vma;
- VMA_ITERATOR(vmi, mm, 0);
-
- for_each_vma(vmi, vma) {
- if (vma->vm_file) {
- struct file *file = vma->vm_file;
- printk(KERN_INFO "TaxiDriver: Shared Library: %s start: 0x%lx end: 0x%lx\n",
- file->f_path.dentry->d_name.name, vma->vm_start, vma->vm_end);
- if (strcmp(file->f_path.dentry->d_name.name, mod) == 0)
- return (uintptr_t)vma->vm_start;
- }
- }
- return 0;
-}
-
-static int init_process_by_pid(int target_pid) {
- printk(KERN_INFO "TaxiDriver: Accessing process with PID: %d\n", target_pid);
-
- struct pid *pid_struct;
- pid_struct = find_get_pid(target_pid);
- if (pid_struct != NULL) {
- task = get_pid_task(pid_struct, PIDTYPE_PID);
- if (task != NULL) {
- const char *process_name = task->comm;
- printk(KERN_INFO "TaxiDriver: Process with PID %d has name: %s\n", target_pid, process_name);
- put_task_struct(task);
- } else {
- printk(KERN_INFO "TaxiDriver: Process with PID %d not found\n", target_pid);
- return -1;
- }
- put_pid(pid_struct);
- } else {
- printk(KERN_INFO "TaxiDriver: Process with PID %d not found\n", target_pid);
- return -1;
- }
-
- return 1; // A successful module initialization
-}
-
-static long device_ioctl(struct file *file, unsigned int ioctl_num, unsigned long arg)
-{
- struct s_WPM wpm_args;
- struct s_RPM rpm_args;
- const char *mod = kmalloc(sizeof(char) * 256, GFP_KERNEL);
- if (!mod)
- return -ENOMEM;
- static uintptr_t addr = 0;
- int pid;
- long return_value = 0;
-
- switch (ioctl_num) {
- case IOCTL_GETMODULE:
- if (copy_from_user((void *)mod, (int *)arg, sizeof(char *)))
- return -EFAULT;
- return_value = list_process_modules(mod);
- addr = return_value;
- kfree(mod);
- break;
-
- case IOCTL_OPENPROC:
- if (copy_from_user(&pid, (int *)arg, sizeof(int)))
- return -EFAULT;
- return_value = init_process_by_pid(pid);
- break;
-
- case IOCTL_RPM:
- if (copy_from_user(&rpm_args, (int *)arg, sizeof(t_RPM)))
- return -EFAULT;
- if (rpm_args.addr == 0x69420) {
- put_user(addr, rpm_args.out_addr);
- break;
- }
- return_value = RPM(rpm_args);
- put_user(return_value, rpm_args.out_addr);
- break;
-
- case IOCTL_WPM:
- if (copy_from_user(&wpm_args, (int *)arg, sizeof(t_WPM)))
- return -EFAULT;
- return_value = WPM(wpm_args);
- break;
-
- default:
- return -ENOTTY;
- }
-
- return return_value;
-}
-
-static struct file_operations fops = {
- .unlocked_ioctl = device_ioctl,
- .open = device_open,
- .release = device_release,
-};
-
-static int __init driver_init(void)
-{
- printk(KERN_INFO "TaxiDriver: Loaded\n");
-
- // Dynamically allocate the major number
- major_number = register_chrdev(0, DRIVER_NAME, &fops);
-
- if (major_number < 0) {
- printk(KERN_ALERT "TaxiDriver: Failed to register the driver.\n");
- return major_number;
- }
-
- printk(KERN_INFO "TaxiDriver: Registered %s with major number %d\n", DRIVER_NAME, major_number);
-
- return 0;
-}
-
-static void __exit driver_exit(void)
-{
- unregister_chrdev(major_number, DRIVER_NAME);
- printk(KERN_INFO "TaxiDriver: Unloaded\n");
-}
-
-module_init(driver_init);
-module_exit(driver_exit);
-MODULE_LICENSE("GPL");
diff --git a/src/client/Makefile b/src/client/Makefile
deleted file mode 100644
index 71b748f..0000000
--- a/src/client/Makefile
+++ /dev/null
@@ -1,24 +0,0 @@
-SRC = main.cpp \
- memory.cpp \
- overlay.cpp \
- imgui/*.cpp
-OBJ = $(SRC:.cpp=.o)
-NAME = Revird
-INC = -Iimgui/
-CFLAGS = -Wall -Wextra -Wpedantic -lSDL3 -lOpenGL
-
-all: $(NAME)
-
-$(NAME): $(OBJ)
- g++ $(SRC) $(CFLAGS) $(INC) -o $(NAME)
- mv $(NAME) ../../.
-
-clean:
- rm -f $(OBJ)
-
-fclean: clean
- rm -f $(NAME)
-
-re: fclean all
-
-.PHONY : all $(NAME) clean fclean re
diff --git a/src/client/communication_struct.h b/src/client/communication_struct.h
deleted file mode 100644
index b9c9dde..0000000
--- a/src/client/communication_struct.h
+++ /dev/null
@@ -1,26 +0,0 @@
-#pragma once
-
-#ifndef DRIVER
-#include
-#include
-#endif
-
-#define IOCTL_OPENPROC _IOW('k', 1, int)
-#define IOCTL_GETMODULE _IOW('k', 2, const char*)
-#define IOCTL_RPM _IOW('k', 3, t_RPM)
-#define IOCTL_WPM _IOW('k', 4, t_WPM)
-
-typedef struct s_RPM
-{
- uintptr_t addr;
- ssize_t size;
- uintptr_t out;
- uintptr_t *out_addr;
-} t_RPM;
-
-typedef struct s_WPM
-{
- uintptr_t addr;
- ssize_t size;
- uintptr_t value;
-} t_WPM;
diff --git a/src/client/imgui b/src/client/imgui
deleted file mode 160000
index 313676d..0000000
--- a/src/client/imgui
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit 313676d200f093e2694b5cfca574f72a2b116c85
diff --git a/src/client/main.cpp b/src/client/main.cpp
deleted file mode 100644
index 597b78d..0000000
--- a/src/client/main.cpp
+++ /dev/null
@@ -1,23 +0,0 @@
-#include "memory.hpp"
-#include "overlay.hpp"
-#include
-
-int main() {
- //run_overlay();
- if (!open_device())
- return -1;
-
- int pid = get_pid("nsnake");
- if (!open_process(pid))
- return -1;
-
- uintptr_t addr = get_module("nsnake");
- printf("module : 0x%lx\n", addr);
- WPM(addr + 0x1d71510, 1337);
-
- int out = RPM(addr + 0x1d71510);
- printf("Value from RPM: %d\n", out);
-
- close_device();
- return 0;
-}
diff --git a/src/client/overlay.cpp b/src/client/overlay.cpp
deleted file mode 100644
index eaeb382..0000000
--- a/src/client/overlay.cpp
+++ /dev/null
@@ -1,99 +0,0 @@
-#include "overlay.hpp"
-#include
-#include "imgui/imgui.h"
-#include "imgui/imgui_impl_sdl3.h"
-#include "imgui/imgui_impl_opengl3.h"
-#include
-#include
-
-int run_overlay(void)
-{
- // Setup SDL
- if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_GAMEPAD) != 0)
- {
- printf("Error: SDL_Init(): %s\n", SDL_GetError());
- return -1;
- }
-
- const char* glsl_version = "#version 130";
- SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, 0);
- SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
- SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
- SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
-
- // Enable native IME.
- SDL_SetHint(SDL_HINT_IME_SHOW_UI, "1");
-
- // Create window with graphics context
- SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
- SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
- SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
- SDL_WindowFlags window_flags = (SDL_WindowFlags)(SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_HIDDEN | SDL_WINDOW_ALWAYS_ON_TOP | SDL_WINDOW_UTILITY);
- SDL_Window* window = SDL_CreateWindow("Dear ImGui SDL3+OpenGL3 example", 1280, 720, window_flags);
- if (window == nullptr)
- {
- printf("Error: SDL_CreateWindow(): %s\n", SDL_GetError());
- return -1;
- }
- SDL_SetWindowPosition(window, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);
- SDL_GLContext gl_context = SDL_GL_CreateContext(window);
- SDL_GL_MakeCurrent(window, gl_context);
- SDL_GL_SetSwapInterval(1); // Enable vsync
- SDL_ShowWindow(window);
-
- // Setup Dear ImGui context
- IMGUI_CHECKVERSION();
- ImGui::CreateContext();
- ImGuiIO& io = ImGui::GetIO(); (void)io;
- io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
- io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
-
- // Setup Dear ImGui style
- ImGui::StyleColorsDark();
-
- // Setup Platform/Renderer backends
- ImGui_ImplSDL3_InitForOpenGL(window, gl_context);
- ImGui_ImplOpenGL3_Init(glsl_version);
-
- // Main loop
- bool done = false;
- ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
- while (!done)
- {
- SDL_Event event;
- while (SDL_PollEvent(&event))
- {
- ImGui_ImplSDL3_ProcessEvent(&event);
- if (event.type == SDL_EVENT_QUIT)
- done = true;
- if (event.type == SDL_EVENT_WINDOW_CLOSE_REQUESTED && event.window.windowID == SDL_GetWindowID(window))
- done = true;
- }
-
- // Start the Dear ImGui frame
- ImGui_ImplOpenGL3_NewFrame();
- ImGui_ImplSDL3_NewFrame();
- ImGui::NewFrame();
-
- ImGui::ShowDemoWindow();
-
- // Rendering
- ImGui::Render();
- glViewport(0, 0, (int)io.DisplaySize.x, (int)io.DisplaySize.y);
- glClearColor(clear_color.x * clear_color.w, clear_color.y * clear_color.w, clear_color.z * clear_color.w, clear_color.w);
- glClear(GL_COLOR_BUFFER_BIT);
- ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
- SDL_GL_SwapWindow(window);
- }
-
- // Cleanup
- ImGui_ImplOpenGL3_Shutdown();
- ImGui_ImplSDL3_Shutdown();
- ImGui::DestroyContext();
-
- SDL_GL_DeleteContext(gl_context);
- SDL_DestroyWindow(window);
- SDL_Quit();
-
- return 1;
-}
diff --git a/src/client/overlay.hpp b/src/client/overlay.hpp
deleted file mode 100644
index cc8f84c..0000000
--- a/src/client/overlay.hpp
+++ /dev/null
@@ -1,3 +0,0 @@
-#pragma once
-
-int run_overlay(void);
diff --git a/um/Makefile b/um/Makefile
new file mode 100644
index 0000000..d3efaa6
--- /dev/null
+++ b/um/Makefile
@@ -0,0 +1,19 @@
+APP_NAME = main
+APP_SRCS = main.cpp memory.cpp
+APP_OBJS = $(APP_SRCS:.cpp=.o)
+
+CXX = g++
+CXXFLAGS = -Wall -Werror
+
+all: $(APP_NAME)
+
+$(APP_NAME): $(APP_OBJS)
+ $(CXX) $(CXXFLAGS) -o $@ $(APP_OBJS)
+
+clean:
+ rm -f $(APP_NAME) $(APP_OBJS)
+
+$(APP_OBJS): %.o: %.cpp
+ $(CXX) $(CXXFLAGS) -c $< -o $@
+
+.PHONY: all
\ No newline at end of file
diff --git a/um/communication_struct.h b/um/communication_struct.h
new file mode 100644
index 0000000..a7ec42a
--- /dev/null
+++ b/um/communication_struct.h
@@ -0,0 +1,41 @@
+#pragma once
+
+#ifndef DRIVER
+#include
+#include
+#endif
+
+#define IOCTL_OPENPROC _IOW('k', 1, int)
+#define IOCTL_GETMODULE _IOW('k', 2, const char*)
+#define IOCTL_RPM _IOW('k', 3, t_RPM)
+#define IOCTL_WPM _IOW('k', 4, t_WPM)
+
+#if KERNEL_UPSTREAM == 0
+#define IOCTL_GETPIDMODULE _IOWR('k', 5, t_PM)
+#if TESTING == 1
+#define IOCTL_VIRT_TO_PHYS _IOWR('k', 6, unsigned long)
+#define IOCTL_PHYS_TO_VIRT _IOWR('k', 7, unsigned long)
+#endif
+#endif
+
+typedef struct s_RPM
+{
+ uintptr_t addr;
+ ssize_t size;
+ uintptr_t out;
+ uintptr_t *out_addr;
+} t_RPM;
+
+typedef struct s_WPM
+{
+ uintptr_t addr;
+ ssize_t size;
+ uintptr_t value;
+} t_WPM;
+
+#if KERNEL_UPSTREAM == 0
+typedef struct s_PM {
+ int pid;
+ const char *mod;
+} t_PM;
+#endif
diff --git a/um/main.cpp b/um/main.cpp
new file mode 100644
index 0000000..329d75b
--- /dev/null
+++ b/um/main.cpp
@@ -0,0 +1,67 @@
+#include "memory.hpp"
+
+std::string target_proc_name{"test_app"};
+std::string target_mod_name{"libmath_module.so"};
+
+int main() {
+ //run_overlay();
+ if (!open_device())
+ return -1;
+ std::cout << "[Main]device opened" << std::endl;
+
+ int pid = get_pid(target_proc_name.c_str());
+ std::cout << "pid of " << target_proc_name << "=" << std::dec << pid << std::endl;
+ if (!open_process(pid))
+ return -1;
+
+ uint64_t addr;
+ std::ifstream inFile("test/addr.txt");
+ if (!inFile.is_open()) {
+ std::cerr << "Error: Could not open the file for reading." << std::endl;
+ return 1;
+ }
+ inFile >> std::hex;
+ if (inFile >> addr) {
+ std::cout << "Read from file var_virtaddr=" << std::hex << addr << std::endl;
+ } else {
+ std::cerr << "Error: Failed to read value from file." << std::endl;
+ return 1;
+ }
+ inFile.close();
+
+#if KERNEL_UPSTREAM==1
+ uint64_t mod_primary_addr = get_module(target_proc_name.c_str());
+#else
+ uint64_t mod_primary_addr = get_pid_module(pid, target_proc_name.c_str());
+#endif
+ std::cout << "module of " << target_proc_name << "=" << std::hex << mod_primary_addr << std::endl;
+
+#if KERNEL_UPSTREAM==1
+ uint64_t modaddr_libmath_addr = get_module(target_mod_name.c_str());
+#else
+ uint64_t modaddr_libmath_addr = get_pid_module(pid, target_mod_name.c_str());
+#endif
+ std::cout << "module of " << target_mod_name << "=" << std::hex << modaddr_libmath_addr << std::endl;
+
+ //mod_primary_addr = 0; // primary_module not required
+ int value_read = RPM(0 + addr);
+ std::cout << "Value before write=" << std::dec << value_read << std::endl;
+
+ WPM(0 + addr, 1337);
+ value_read = RPM(0 + addr);
+ std::cout << "Value after write=" << std::dec << value_read << std::endl;
+
+#if KERNEL_UPSTREAM==0 && TESTING==1
+ uint64_t physaddr = VIRT_TO_PHYS(0x7fff2a2cb7a4);
+ std::cout << "phys addr=" << std::hex << physaddr << std::endl;
+ uint64_t phys2virtaddr = PHYS_TO_VIRT(0x7fff2a2cb7a4);
+ std::cout << "phys2virtaddr=" << std::hex << phys2virtaddr << std::endl;
+
+ //attempt to read relative to proc primary module
+ int value_read_primarymod = RPM(mod_primary_addr + 0x2A917D6757A4);
+ std::cout << "value_read_primarymod=" << std::dec << value_read_primarymod << std::endl;
+#endif
+ close_device();
+ return 0;
+}
+//pmap -x $(pidof test_app)
diff --git a/src/client/memory.cpp b/um/memory.cpp
similarity index 54%
rename from src/client/memory.cpp
rename to um/memory.cpp
index 8ca181b..50987bb 100644
--- a/src/client/memory.cpp
+++ b/um/memory.cpp
@@ -1,12 +1,4 @@
#include "memory.hpp"
-#include "communication_struct.h"
-#include
-#include
-#include
-#include
-#include
-
-#define DEVICE_FILE "/dev/TaxiDriver"
int file_desc = 0;
int open_device(void)
@@ -35,7 +27,7 @@ int get_pid(const char *program_name) {
// Open a pipe to execute the command and read the output
fp = popen(command, "r");
- if (fp == NULL) {
+ if (!fp) {
perror("popen");
return -1;
}
@@ -58,9 +50,7 @@ int get_pid(const char *program_name) {
int open_process(int pid)
{
- int ret;
-
- ret = ioctl(file_desc, IOCTL_OPENPROC, &pid);
+ uint64_t ret = ioctl(file_desc, IOCTL_OPENPROC, &pid);
if (ret < 0) {
perror("Revird: openprocess failed.");
close(file_desc);
@@ -71,7 +61,7 @@ int open_process(int pid)
uintptr_t get_module(const char *mod)
{
- int ret = ioctl(file_desc, IOCTL_GETMODULE, mod);
+ uint64_t ret = ioctl(file_desc, IOCTL_GETMODULE, mod);
if (ret < 0) {
perror("Revird: getmodule failed.");
close(file_desc);
@@ -81,3 +71,46 @@ uintptr_t get_module(const char *mod)
uintptr_t addr = RPM(0x69420);
return addr;
}
+
+#if KERNEL_UPSTREAM == 0
+uintptr_t get_pid_module(int pid, const char *mod) {
+ struct s_PM pma;
+ pma.pid = pid;
+ pma.mod = mod;
+
+ uint64_t ret = ioctl(file_desc, IOCTL_GETPIDMODULE, &pma);
+ if (ret < 0) {
+ perror("Revird: get_pid_module failed.");
+ close(file_desc);
+ return -1;
+ }
+
+ uintptr_t addr = RPM(0x69420);
+ return addr;
+}
+#endif
+
+#if KERNEL_UPSTREAM == 0 && TESTING==1
+uintptr_t VIRT_TO_PHYS(uintptr_t vaddr) {
+ uint64_t ret = ioctl(file_desc, IOCTL_VIRT_TO_PHYS, vaddr);
+ if (ret < 0) {
+ perror("VIRT_TO_PHYS failed.");
+ return 0;
+ }
+ // At this point, 'vaddr' contains the physical address.
+ return vaddr;
+}
+#endif
+
+#if KERNEL_UPSTREAM == 0 && TESTING==1
+uintptr_t PHYS_TO_VIRT(uintptr_t paddr) {
+ uint64_t ret = ioctl(file_desc, IOCTL_PHYS_TO_VIRT, &paddr);
+ if (ret < 0) {
+ perror("PHYS_TO_VIRT failed.");
+ return 0;
+ }
+
+ // At this point, 'paddr' contains the virtual address.
+ return paddr;
+}
+#endif
diff --git a/src/client/memory.hpp b/um/memory.hpp
similarity index 70%
rename from src/client/memory.hpp
rename to um/memory.hpp
index c623d66..427831f 100644
--- a/src/client/memory.hpp
+++ b/um/memory.hpp
@@ -4,7 +4,12 @@
#include
#include
#include
+//#include "overlay.hpp"
+#include
+#include
+#include
#include "communication_struct.h"
+#define DEVICE_FILE "/dev/TaxiDriver"
extern int file_desc;
int open_device(void);
@@ -20,7 +25,7 @@ T RPM(uintptr_t address)
args.out = 0;
args.out_addr = &args.out;
- int ret = ioctl(file_desc, IOCTL_RPM, &args);
+ uint64_t ret = ioctl(file_desc, IOCTL_RPM, &args);
if (ret < 0) {
perror("Revird: RPM failed.");
close(file_desc);
@@ -36,9 +41,7 @@ void WPM(uintptr_t address, T value)
args_wpm.addr = address;
args_wpm.size = sizeof(T);
args_wpm.value = value;
- int ret;
-
- ret = ioctl(file_desc, IOCTL_WPM, &args_wpm);
+ uint64_t ret = ioctl(file_desc, IOCTL_WPM, &args_wpm);
if (ret < 0) {
perror("Revird: WPM failed.");
close(file_desc);
@@ -50,3 +53,10 @@ void WPM(uintptr_t address, T value)
void WPM(uintptr_t addr, uintptr_t value, ssize_t size);
int open_process(int pid);
uintptr_t get_module(const char *mod);
+#if KERNEL_UPSTREAM == 0
+uintptr_t get_pid_module(int pid, const char *mod);
+#if TESTING==1
+uintptr_t VIRT_TO_PHYS(uintptr_t vaddr);
+uintptr_t PHYS_TO_VIRT(uintptr_t paddr);
+#endif
+#endif
\ No newline at end of file
diff --git a/um/test/Makefile b/um/test/Makefile
new file mode 100644
index 0000000..bb8e572
--- /dev/null
+++ b/um/test/Makefile
@@ -0,0 +1,35 @@
+# Define the name of your application
+APP_NAME = test_app
+
+# Source files for your application
+APP_SRCS = main.cpp
+APP_OBJS = $(APP_SRCS:.cpp=.o)
+
+# Compiler and compiler flags
+CXX = g++
+CXXFLAGS = -Wall -Werror -fexceptions
+
+# Library name and source files
+LIB_NAME = libmath_module.so
+LIB_SRCS = math_module.cpp
+LIB_OBJS = $(LIB_SRCS:.cpp=.o)
+
+# Additional flags for creating PIC code
+PICFLAGS = -fPIC
+
+# The default target is 'all', which builds your application
+all: $(APP_NAME) $(LIB_NAME)
+
+$(APP_NAME): $(APP_OBJS) $(LIB_NAME)
+ $(CXX) $(CXXFLAGS) -o $@ $(APP_OBJS) -L. -lmath_module -Wl,-rpath,'$$ORIGIN'
+
+$(LIB_NAME): $(LIB_OBJS)
+ $(CXX) -shared -o $@ $(LIB_OBJS) $(CXXFLAGS)
+
+# Compile source files to object files
+%.o: %.cpp
+ $(CXX) $(CXXFLAGS) $(PICFLAGS) -c $< -o $@
+
+# Clean rule to remove the executable, object files, and library
+clean:
+ rm -f $(APP_NAME) $(APP_OBJS) $(LIB_NAME) $(LIB_OBJS)
diff --git a/um/test/addr.txt b/um/test/addr.txt
new file mode 100644
index 0000000..2f0abf8
--- /dev/null
+++ b/um/test/addr.txt
@@ -0,0 +1 @@
+0x7fff7203ed94
\ No newline at end of file
diff --git a/um/test/main.cpp b/um/test/main.cpp
new file mode 100644
index 0000000..396ceb5
--- /dev/null
+++ b/um/test/main.cpp
@@ -0,0 +1,44 @@
+#include
+#include
+#include
+#include
+
+#include "math_module.h"
+
+int main() {
+ MathModule math;
+
+ int result = math.add(10, 5);
+ std::cout << "10 + 5 = " << result << std::endl;
+
+ result = math.subtract(10, 5);
+ std::cout << "10 - 5 = " << result << std::endl;
+
+ result = math.multiply(10, 5);
+ std::cout << "10 * 5 = " << result << std::endl;
+
+ double divisionResult = math.divide(10.0, 5.0);
+ std::cout << "10 / 5 = " << divisionResult << std::endl;
+
+
+ int var = 0;
+ uint64_t* var_virtaddr = reinterpret_cast(&var);
+ std::ofstream outFile("addr.txt");
+ if (!outFile.is_open()) {
+ std::cerr << "Error: Could not open the file for writing." << std::endl;
+ return 1;
+ }
+ outFile << var_virtaddr;
+ outFile.close();
+
+ while (true) {
+ int random_increment = std::rand() % 100; // Generate a random number between 0 and 99
+ std::cout << "before inc value=" << std::dec << var << "@" << std::hex << var_virtaddr << std::endl;
+ var += random_increment;
+ std::cout << "after inc value=" << std::dec << var << "@" << std::hex << var_virtaddr << std::endl;
+ std::cin.get(); // Wait for Enter key press
+ }
+
+ return 0;
+}
+//export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:.
diff --git a/um/test/math_module.cpp b/um/test/math_module.cpp
new file mode 100644
index 0000000..7e42771
--- /dev/null
+++ b/um/test/math_module.cpp
@@ -0,0 +1,24 @@
+#include "math_module.h"
+
+MathModule::MathModule() {
+ // Constructor, if any initialization is needed
+}
+
+int MathModule::add(int a, int b) {
+ return a + b;
+}
+
+int MathModule::subtract(int a, int b) {
+ return a - b;
+}
+
+int MathModule::multiply(int a, int b) {
+ return a * b;
+}
+
+double MathModule::divide(double a, double b) {
+ if (b == 0) {
+ throw "Division by zero is not allowed.";
+ }
+ return a / b;
+}
diff --git a/um/test/math_module.h b/um/test/math_module.h
new file mode 100644
index 0000000..4911b48
--- /dev/null
+++ b/um/test/math_module.h
@@ -0,0 +1,14 @@
+#ifndef MATH_MODULE_H
+#define MATH_MODULE_H
+
+class MathModule {
+public:
+ MathModule(); // Constructor
+
+ int add(int a, int b);
+ int subtract(int a, int b);
+ int multiply(int a, int b);
+ double divide(double a, double b);
+};
+
+#endif