├── .gitattributes ├── .gitignore ├── Pictures ├── ItemFilterSettings.jpg ├── MainGameView.jpg ├── MainToggleMenu.jpg ├── RadarSettings.jpg └── WeaponFilterSettings.jpg ├── README.md ├── apex_dma ├── Game.cpp ├── Game.h ├── Makefile ├── Math.cpp ├── Math.h ├── README.md ├── apex_dma.cpp ├── build.sh ├── glowmode.h ├── memflow_lib │ ├── CHANGES.md │ ├── CONTRIBUTE.md │ ├── Cargo.toml │ ├── LICENSE │ ├── README.md │ ├── docs │ │ ├── logo.png │ │ └── windbg_cheat_sheet.txt │ ├── memflow-bench │ │ ├── .gitignore │ │ ├── Cargo.toml │ │ ├── README.md │ │ ├── benches │ │ │ ├── batcher.rs │ │ │ ├── read_dummy.rs │ │ │ └── read_win32.rs │ │ └── src │ │ │ ├── lib.rs │ │ │ ├── phys.rs │ │ │ ├── vat.rs │ │ │ └── virt.rs │ ├── memflow-derive │ │ ├── Cargo.toml │ │ ├── README.md │ │ ├── src │ │ │ └── lib.rs │ │ └── tests │ │ │ └── derive_test.rs │ ├── memflow-ffi │ │ ├── .gitignore │ │ ├── Cargo.toml │ │ ├── README.md │ │ ├── binddestr.h │ │ ├── bindgen.sh │ │ ├── cbindgen.toml │ │ ├── examples │ │ │ ├── Makefile │ │ │ └── phys_mem.c │ │ ├── memflow.h │ │ ├── memflow_cpp.h │ │ └── src │ │ │ ├── architecture │ │ │ ├── mod.rs │ │ │ └── x86.rs │ │ │ ├── connectors │ │ │ └── mod.rs │ │ │ ├── lib.rs │ │ │ ├── log.rs │ │ │ ├── mem │ │ │ ├── mod.rs │ │ │ ├── phys_mem.rs │ │ │ └── virt_mem.rs │ │ │ ├── process.rs │ │ │ ├── types │ │ │ └── mod.rs │ │ │ ├── util.rs │ │ │ └── win32.rs │ ├── memflow-qemu-procfs │ │ ├── .gitignore │ │ ├── Cargo.toml │ │ ├── LICENSE │ │ ├── Makefile │ │ ├── README.md │ │ ├── examples │ │ │ └── read_phys.rs │ │ ├── install.sh │ │ └── src │ │ │ └── lib.rs │ ├── memflow-win32-ffi │ │ ├── .gitignore │ │ ├── Cargo.toml │ │ ├── README.md │ │ ├── bindgen.sh │ │ ├── cbindgen.toml │ │ ├── examples │ │ │ ├── Makefile │ │ │ ├── dump_header.c │ │ │ └── process_list.c │ │ ├── memflow_win32.h │ │ ├── memflow_win32_cpp.h │ │ └── src │ │ │ ├── kernel │ │ │ ├── mod.rs │ │ │ └── start_block.rs │ │ │ ├── lib.rs │ │ │ └── win32 │ │ │ ├── kernel.rs │ │ │ ├── mod.rs │ │ │ ├── module.rs │ │ │ ├── process.rs │ │ │ └── process_info.rs │ ├── memflow-win32 │ │ ├── Cargo.toml │ │ ├── README.md │ │ ├── build.rs │ │ ├── examples │ │ │ ├── dump_offsets.rs │ │ │ ├── generate_offsets.rs │ │ │ ├── integration.rs │ │ │ ├── multithreading.rs │ │ │ ├── read_bench.rs │ │ │ └── read_keys.rs │ │ ├── offsets │ │ │ ├── 10_0_18362_X64_0AFB69F5FD264D54673570E37B38A3181.toml │ │ │ ├── 10_0_19041_X64_1C9875F76C8F0FBF3EB9A9D7C1C274061.toml │ │ │ ├── 10_0_19041_X64_BBED7C2955FBE4522AAA23F4B8677AD91.toml │ │ │ ├── 10_0_19041_X86_1B1D6AA205E1C87DC63A314ACAA50B491.toml │ │ │ ├── 4_0_1381_X86.toml │ │ │ ├── 5_2_3790_X64_82DCF67A38274C9CA99B60B421D2786D2.toml │ │ │ ├── 6_1_7601_X64_ECE191A20CFF4465AE46DF96C22638451.toml │ │ │ └── 6_1_7601_X86_684DA42A30CC450F81C535B4D18944B12.toml │ │ └── src │ │ │ ├── error.rs │ │ │ ├── kernel │ │ │ ├── mod.rs │ │ │ ├── ntos.rs │ │ │ ├── ntos │ │ │ │ ├── pehelper.rs │ │ │ │ ├── x64.rs │ │ │ │ └── x86.rs │ │ │ ├── start_block.rs │ │ │ ├── start_block │ │ │ │ ├── x64.rs │ │ │ │ ├── x86.rs │ │ │ │ └── x86pae.rs │ │ │ └── sysproc.rs │ │ │ ├── lib.rs │ │ │ ├── offsets │ │ │ ├── builder.rs │ │ │ ├── mod.rs │ │ │ ├── offset_table.rs │ │ │ ├── pdb_struct.rs │ │ │ ├── pdb_struct │ │ │ │ └── data.rs │ │ │ └── symstore.rs │ │ │ ├── win32.rs │ │ │ └── win32 │ │ │ ├── kernel.rs │ │ │ ├── kernel_builder.rs │ │ │ ├── kernel_info.rs │ │ │ ├── keyboard.rs │ │ │ ├── module.rs │ │ │ ├── process.rs │ │ │ ├── unicode_string.rs │ │ │ └── vat.rs │ ├── memflow │ │ ├── Cargo.toml │ │ └── src │ │ │ ├── architecture │ │ │ ├── mmu_spec.rs │ │ │ ├── mmu_spec │ │ │ │ └── translate_data.rs │ │ │ ├── mod.rs │ │ │ └── x86 │ │ │ │ ├── mod.rs │ │ │ │ ├── x32.rs │ │ │ │ ├── x32_pae.rs │ │ │ │ └── x64.rs │ │ │ ├── connector │ │ │ ├── args.rs │ │ │ ├── fileio.rs │ │ │ ├── filemap.rs │ │ │ ├── inventory.rs │ │ │ ├── mmap.rs │ │ │ └── mod.rs │ │ │ ├── error.rs │ │ │ ├── iter │ │ │ ├── double_buffered_iterator.rs │ │ │ ├── doublepeek.rs │ │ │ ├── mod.rs │ │ │ ├── page_chunks.rs │ │ │ └── void.rs │ │ │ ├── lib.rs │ │ │ ├── mem │ │ │ ├── cache │ │ │ │ ├── cached_memory_access.rs │ │ │ │ ├── cached_vat.rs │ │ │ │ ├── count_validator.rs │ │ │ │ ├── mod.rs │ │ │ │ ├── page_cache.rs │ │ │ │ ├── timed_validator.rs │ │ │ │ └── tlb_cache.rs │ │ │ ├── dummy.rs │ │ │ ├── mem_map.rs │ │ │ ├── mod.rs │ │ │ ├── phys_mem.rs │ │ │ ├── phys_mem_batcher.rs │ │ │ ├── virt_mem.rs │ │ │ ├── virt_mem │ │ │ │ └── virtual_dma.rs │ │ │ ├── virt_mem_batcher.rs │ │ │ ├── virt_translate.rs │ │ │ └── virt_translate │ │ │ │ ├── direct_translate.rs │ │ │ │ └── tests.rs │ │ │ ├── process │ │ │ └── mod.rs │ │ │ └── types │ │ │ ├── address.rs │ │ │ ├── byte_swap.rs │ │ │ ├── mod.rs │ │ │ ├── page.rs │ │ │ ├── physical_address.rs │ │ │ ├── pointer32.rs │ │ │ ├── pointer64.rs │ │ │ └── size.rs │ ├── nostd-test │ │ ├── .cargo │ │ │ └── config │ │ ├── .gitignore │ │ ├── Cargo.toml │ │ ├── rust-toolchain │ │ └── src │ │ │ └── main.rs │ └── runner.sh ├── memory.cpp ├── memory.h ├── offsets.h ├── performance ├── prediction.h └── vector.h └── apex_guest └── Client ├── .gitattributes ├── .gitignore ├── Client.rc ├── Client.sln ├── Client.vcxproj ├── Client.vcxproj.filters ├── XorString.h ├── imgui ├── imconfig.h ├── imgui.cpp ├── imgui.h ├── imgui_draw.cpp ├── imgui_impl_dx11.cpp ├── imgui_impl_dx11.h ├── imgui_impl_win32.cpp ├── imgui_impl_win32.h ├── imgui_internal.h ├── imgui_tables.cpp ├── imgui_widgets.cpp ├── imstb_rectpack.h ├── imstb_textedit.h └── imstb_truetype.h ├── impl ├── hooking │ └── REMOVED.txt ├── libraries │ ├── ImGui │ │ ├── LICENSE.txt │ │ ├── imconfig.h │ │ ├── imgui.cpp │ │ ├── imgui.h │ │ ├── imgui_draw.cpp │ │ ├── imgui_impl_dx11.cpp │ │ ├── imgui_impl_dx11.h │ │ ├── imgui_internal.h │ │ ├── imgui_xorstr.h │ │ ├── stb_rect_pack.h │ │ ├── stb_textedit.h │ │ └── stb_truetype.h │ ├── lazyimporter │ │ └── lazyimporter.hpp │ ├── shellcode.asm │ └── xor │ │ └── xor.hpp └── render │ ├── font.h │ └── present.h ├── main.cpp ├── main.h ├── overlay.cpp ├── overlay.h ├── playerdef.h ├── resource.h ├── updater.hpp ├── utility.hpp └── vector2.h /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | apex_dma/build 2 | .vs/ 3 | x64/ 4 | *.o 5 | target/ 6 | *.rs.bk 7 | *.swp 8 | *.dll 9 | *.dylib 10 | .vscode 11 | Cargo.lock 12 | *.so 13 | .vscode/ -------------------------------------------------------------------------------- /Pictures/ItemFilterSettings.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KrackerCo/apex_dma_kvm_pub/4e35017c8d6ba5676c4cca85edb2e89e77ff62e8/Pictures/ItemFilterSettings.jpg -------------------------------------------------------------------------------- /Pictures/MainGameView.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KrackerCo/apex_dma_kvm_pub/4e35017c8d6ba5676c4cca85edb2e89e77ff62e8/Pictures/MainGameView.jpg -------------------------------------------------------------------------------- /Pictures/MainToggleMenu.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KrackerCo/apex_dma_kvm_pub/4e35017c8d6ba5676c4cca85edb2e89e77ff62e8/Pictures/MainToggleMenu.jpg -------------------------------------------------------------------------------- /Pictures/RadarSettings.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KrackerCo/apex_dma_kvm_pub/4e35017c8d6ba5676c4cca85edb2e89e77ff62e8/Pictures/RadarSettings.jpg -------------------------------------------------------------------------------- /Pictures/WeaponFilterSettings.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KrackerCo/apex_dma_kvm_pub/4e35017c8d6ba5676c4cca85edb2e89e77ff62e8/Pictures/WeaponFilterSettings.jpg -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # apex_dma_kvm_pub 1.8 2 | Apex Legends QEMU/KVM hack 3 | 4 | UnknownCheats thread: https://www.unknowncheats.me/forum/apex-legends/406426-kvm-vmread-apex-esp-aimbot.html 5 | 6 | Bone IDs reference: https://www.unknowncheats.me/wiki/Apex_Legends_Bones_and_Hitboxes 7 | 8 | Game version (Steam Only right now): v3.0.36.26 9 | 10 | KrackerCo Fork's features. 11 | 12 | ESP Glow color picker for knocked and alive, visable or not visable. 13 | 14 | Item Glow with item filter. 15 | 16 | Weapon Glow with Weapon filter. 17 | 18 | Mini-Map radar*1. 19 | 20 | Full map radar*2. 21 | 22 | Firing Range dummp targeting debug testing. 23 | 24 | TDM Aimbot/Glow so you only target the other team. 25 | 26 | Custom aiming distance. 27 | 28 | Left/Right or both mouse buttons to aim. 29 | 30 | Custom Predition speed and Gravity to use with Headshot Mode*3. 31 | 32 | Save and Load config buttons and at start. 33 | 34 | 35 | NEW: 36 | 37 | Thank you https://github.com/AtomBottle/apex_dma_kvm_pub for some of your lock code. Happy someone had a use for my fork :) 38 | 39 | One V One toggle. Own friends in the firing range*4. 40 | 41 | TODO: 42 | 43 | Triggerbot*5. 44 | 45 | ![Main View](Pictures/MainGameView.jpg) 46 | 47 | ![Main Toggle Menu](Pictures/MainToggleMenu.jpg) 48 | 49 | ![Radar Settings](Pictures/RadarSettings.jpg) 50 | 51 | ![Item Filter Settings](Pictures/ItemFilterSettings.jpg) 52 | 53 | ![Weapon Filter Settings](Pictures/WeaponFilterSettings.jpg) 54 | 55 | 1: needs to be calibrated, info how is in the files. 56 | 57 | 2: needs to be calibrated, info how is in the files. 58 | 59 | 3: Havnt added it back in yet, will do soon. 60 | 61 | 4: Visabilty check is a little buggy. 62 | 63 | 5: Cant get it to work, i got the trigger to work but not the bot part. Don't know how to check if its close and in crosshair. 64 | 65 | DO NOT USE, DETECTED MAYBE -------------------------------------------------------------------------------- /apex_dma/Game.h: -------------------------------------------------------------------------------- 1 | #include "Math.h" 2 | #include "offsets.h" 3 | #include "memory.h" 4 | #include "glowmode.h" 5 | 6 | #define NUM_ENT_ENTRIES (1 << 12) 7 | #define ENT_ENTRY_MASK (NUM_ENT_ENTRIES - 1) 8 | 9 | typedef struct Bone 10 | { 11 | uint8_t pad1[0xCC]; 12 | float x; 13 | uint8_t pad2[0xC]; 14 | float y; 15 | uint8_t pad3[0xC]; 16 | float z; 17 | }Bone; 18 | 19 | struct GColor 20 | { 21 | float r, g, b; 22 | }; 23 | 24 | 25 | 26 | struct Fade 27 | { 28 | int a, b; 29 | float c, d, e, f; 30 | }; 31 | 32 | class Entity 33 | { 34 | public: 35 | uint64_t ptr; 36 | uint8_t buffer[0x3FF0]; 37 | Vector getPosition(); 38 | bool isDummy(); 39 | bool isPlayer(); 40 | bool isKnocked(); 41 | bool isAlive(); 42 | float lastVisTime(); 43 | int getTeamId(); 44 | int getHealth(); 45 | int getShield(); 46 | int getArmortype(); 47 | int getMaxshield(); 48 | bool isGlowing(); 49 | bool isZooming(); 50 | Vector getAbsVelocity(); 51 | QAngle GetSwayAngles(); 52 | QAngle GetViewAngles(); 53 | Vector GetCamPos(); 54 | QAngle GetRecoil(); 55 | Vector GetViewAnglesV(); 56 | float GetYaw(); 57 | void enableGlow(GColor color); 58 | void disableGlow(); 59 | void SetViewAngles(SVector angles); 60 | void SetViewAngles(QAngle& angles); 61 | Vector getBonePosition(int id); 62 | Vector getBonePositionByHitbox(int id); 63 | bool Observing(uint64_t entitylist); 64 | void get_name(uint64_t g_Base, uint64_t index, char* name); 65 | }; 66 | 67 | class Item 68 | { 69 | public: 70 | uint64_t ptr; 71 | uint8_t buffer[0x3FF0]; 72 | Vector getPosition(); 73 | bool isItem(); 74 | bool isBox(); 75 | bool isTrap(); 76 | bool isGlowing(); 77 | void enableGlow(); 78 | void disableGlow(); 79 | void BlueGlow(); 80 | }; 81 | 82 | 83 | 84 | class WeaponXEntity 85 | { 86 | public: 87 | void update(uint64_t LocalPlayer); 88 | float get_projectile_speed(); 89 | float get_projectile_gravity(); 90 | float get_zoom_fov(); 91 | int get_ammo(); 92 | 93 | private: 94 | float projectile_scale; 95 | float projectile_speed; 96 | float zoom_fov; 97 | int ammo; 98 | }; 99 | 100 | struct ClientClass { 101 | uint64_t pCreateFn; 102 | uint64_t pCreateEventFn; 103 | uint64_t pNetworkName; 104 | uint64_t pRecvTable; 105 | uint64_t pNext; 106 | uint32_t ClassID; 107 | uint32_t ClassSize; 108 | }; 109 | 110 | Entity getEntity(uintptr_t ptr); 111 | Item getItem(uintptr_t ptr); 112 | 113 | bool WorldToScreen(Vector from, float* m_vMatrix, int targetWidth, int targetHeight, Vector& to); 114 | float CalculateFov(Entity& from, Entity& target); 115 | QAngle CalculateBestBoneAim(Entity& from, uintptr_t target, float max_fov); 116 | void get_class_name(uint64_t entity_ptr, char* out_str); 117 | void charge_rifle_hack(uint64_t entity_ptr); -------------------------------------------------------------------------------- /apex_dma/Makefile: -------------------------------------------------------------------------------- 1 | CXX=g++ 2 | CXXFLAGS=-I./memflow_lib/memflow-win32-ffi/ -I./memflow_lib/memflow-ffi/ -L./memflow_lib/target/release -Wno-multichar 3 | LIBS=-lm -Wl,--no-as-needed -ldl -lpthread -l:libmemflow_win32_ffi.a 4 | 5 | OUTDIR=./build 6 | OBJDIR=$(OUTDIR)/obj 7 | 8 | $(shell mkdir -p $(OBJDIR)) 9 | $(shell cp memflow_lib/memflow-qemu-procfs/target/release/libmemflow_qemu_procfs.so $(OUTDIR)) 10 | 11 | %.o: %.cpp 12 | $(CXX) -c -o $(OBJDIR)/$@ $< $(CXXFLAGS) 13 | 14 | apex_dma: apex_dma.o Game.o Math.o memory.o 15 | $(CXX) -o $(OUTDIR)/$@ $(OBJDIR)/apex_dma.o $(OBJDIR)/Game.o $(OBJDIR)/Math.o $(OBJDIR)/memory.o $(CXXFLAGS) $(LIBS) 16 | 17 | .PHONY: all 18 | all: apex_dma 19 | 20 | .DEFAULT_GOAL := all 21 | 22 | clean: 23 | rm -rf $(OUTDIR) 24 | -------------------------------------------------------------------------------- /apex_dma/Math.cpp: -------------------------------------------------------------------------------- 1 | #include "Math.h" 2 | 3 | void Math::NormalizeAngles(QAngle& angle) 4 | { 5 | while (angle.x > 89.0f) 6 | angle.x -= 180.f; 7 | 8 | while (angle.x < -89.0f) 9 | angle.x += 180.f; 10 | 11 | while (angle.y > 180.f) 12 | angle.y -= 360.f; 13 | 14 | while (angle.y < -180.f) 15 | angle.y += 360.f; 16 | } 17 | 18 | QAngle Math::CalcAngle(const Vector& src, const Vector& dst) 19 | { 20 | QAngle angle = QAngle(); 21 | SVector delta = SVector((src.x - dst.x), (src.y - dst.y), (src.z - dst.z)); 22 | 23 | double hyp = sqrt(delta.x*delta.x + delta.y * delta.y); 24 | 25 | angle.x = atan(delta.z / hyp) * (180.0f / M_PI); 26 | angle.y = atan(delta.y / delta.x) * (180.0f / M_PI); 27 | angle.z = 0; 28 | if (delta.x >= 0.0) angle.y += 180.0f; 29 | 30 | return angle; 31 | } 32 | 33 | double Math::GetFov(const QAngle& viewAngle, const QAngle& aimAngle) 34 | { 35 | QAngle delta = aimAngle - viewAngle; 36 | NormalizeAngles(delta); 37 | 38 | return sqrt(pow(delta.x, 2.0f) + pow(delta.y, 2.0f)); 39 | } 40 | 41 | double Math::DotProduct(const Vector& v1, const float* v2) 42 | { 43 | return v1.x * v2[0] + v1.y * v2[1] + v1.z * v2[2]; 44 | } -------------------------------------------------------------------------------- /apex_dma/Math.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include "vector.h" 3 | 4 | struct SVector 5 | { 6 | float x; 7 | float y; 8 | float z; 9 | SVector(float x1, float y1, float z1) 10 | { 11 | x = x1; 12 | y = y1; 13 | z = z1; 14 | } 15 | 16 | SVector(QAngle q) 17 | { 18 | x = q.x; 19 | y = q.y; 20 | z = q.z; 21 | } 22 | }; 23 | 24 | namespace Math 25 | { 26 | void NormalizeAngles(QAngle& angle); 27 | double GetFov(const QAngle& viewAngle, const QAngle& aimAngle); 28 | double DotProduct(const Vector& v1, const float* v2); 29 | QAngle CalcAngle(const Vector& src, const Vector& dst); 30 | } -------------------------------------------------------------------------------- /apex_dma/README.md: -------------------------------------------------------------------------------- 1 | # LinuxDMA 2 | -------------------------------------------------------------------------------- /apex_dma/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cd memflow_lib/memflow-win32-ffi/ 4 | if cargo build --release ; then 5 | cd ../memflow-qemu-procfs 6 | 7 | if cargo build --release --all-features ; then 8 | cd ../../ 9 | make 10 | else 11 | echo "Error while building memflow-qemu-procfs" 12 | fi 13 | 14 | else 15 | echo "Error while building memflow-win32-ffi" 16 | fi 17 | -------------------------------------------------------------------------------- /apex_dma/glowmode.h: -------------------------------------------------------------------------------- 1 | struct GlowMode 2 | { 3 | int8_t GeneralGlowMode, BorderGlowMode, BorderSize, TransparentLevel; 4 | }; -------------------------------------------------------------------------------- /apex_dma/memflow_lib/CHANGES.md: -------------------------------------------------------------------------------- 1 | # Release notes 2 | All notable changes to this project will be documented in this file. 3 | This project adheres to [Semantic Versioning](http://semver.org/). 4 | 5 | ## 0.1.5 6 | - Added memflow::prelude::v1 and memflow_win32::prelude::v1 modules 7 | - Added new fields to FFI 8 | - Improved consistency of these function names in C FFI: `phys_read_raw` -> `phys_read_raw_into`, `page_size` -> `arch_page_size`. 9 | - Added C++ bindings for the FFI 10 | - Fixed core errors not displaying the full error message when wrapped in a win32 error 11 | - Changed windows inventory search path from [user]/.local/lib/memflow to [user]/Documents/memflow 12 | - Added {PWD} to inventory search path 13 | 14 | Transitioning from C FFI to C++ FFI: 15 | - `memflow.h`, and `memflow_win32.h` become `memflow_cpp.h`, and `memflow_win32_cpp.h`. 16 | - The headers still depend on `memflow.h`, and `memflow_win32.h`. They are just wrappers for safety, and ergonomics. 17 | - Types transition from `Type *` to `CType`. Every `CType` include automatic object destruction, so there is no need for the `type_free` methods. 18 | - `CType` contains a `Type *` inside. The pointer can still be `null`. Checking whether object is valid is still the same: `if (CType != NULL)` 19 | - Methods are implemented as class members. Most methods loose their prefix. The change looks like this: `process_module_info(Win32Process *process, const char *name)` becomes `CWin32Process::module_info(this, const char *name)`. 20 | - Calling methods changes into calling a function on the object, instead of with the object. Example: `process_module_info(proc, "ntdll.dll")` becomes `proc.module_info("ntdll.dll")`. 21 | - Exception to this are `virt`, and `phys` read/write functions. They do not loose their prefix, because they do have the prefix in the Rust library. So, `virt_read_u64(mem, addr)` becomes `mem.virt_read_u64(addr)`. 22 | - There are extra convenience functions that utilize STL's `string`, and `vector` containers. Getting process/module names, and lists becomes much simpler. 23 | 24 | ## 0.1.4 25 | - Removed namespaces in FFI headers and unused dependencies 26 | - Fixed connector errors not being shown properly 27 | - Added `main_module_info()` helper function which retrieves the main module of a process 28 | - Added the DLL path to the Win32ModuleInfo structure 29 | - Fixed duplicated connectors being added to the inventory multiple times 30 | - Renamed and deprecated the `ConnectorInventory::try_new()` and `ConnectorInventory::with_path()` functions. The new function names are `ConnectorInventory::scan()` and `ConnectorInventory::scan_path()` 31 | - Added a `available_connectors()` function to the ConnectorInventory which returns all connectors that have been found on the system. 32 | - Added a fallback signature for windows 10 for the win32 keyboard implementation in case the PE Header of the win32kbase.sys is paged out 33 | - Added a `MemoryMap::open()` function to load a memory map in TOML format 34 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/CONTRIBUTE.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | There is a feature missing? A bug you have noticed? Some inconsistencies? **Contributions are welcome, and are encouraged!** 4 | 5 | ## Guidelines 6 | 7 | We welcome your contributions, and we love to keep our code standards high. So, there are a few key guidelines that you should follow for smooth sailing: 8 | 9 | - All our code is formatted using rustfmt. Please, run `cargo fmt` before committing your changes. 10 | - Make sure all of the tests pass with `cargo test`, as this would prevent us from merging your changes. 11 | - Make sure that clippy does not complain with `cargo clippy --all-targets --all-features --workspace -- -D warnings -D clippy::all` 12 | 13 | ## Review 14 | 15 | Once you submit a pull request, one of the maintainers will have a look at it, and give you some feedback. If everything looks alright, we will be almost ready to merge it in! If not, the maintainer will point you to the right direction where things may need changing in the code. 16 | 17 | ## Merging 18 | 19 | Once the code is ready, the last step is merging. There are only 2 important things that you need to confirm: 20 | 21 | - That the code is yours 22 | - And that you agree with the project's license terms to be applied to the entire pull request. 23 | 24 | By default, we will go by the assumption that those 2 points are true, but it would still be nice that you confirmed those. And sometimes, we may ask you to do so, just to be sure. 25 | 26 | Ultimately, unless you state otherwise, the merged code will be licensed under the current license of the project. 27 | 28 | Anyways, thanks for giving this a read, and happy hacking! 29 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/Cargo.toml: -------------------------------------------------------------------------------- 1 | 2 | [profile.bench] 3 | debug = true 4 | 5 | [workspace] 6 | members = [ 7 | "memflow", 8 | "memflow-win32", 9 | "memflow-ffi", 10 | "memflow-win32-ffi", 11 | "memflow-bench", 12 | ] 13 | default-members = [ 14 | "memflow", 15 | "memflow-win32", 16 | "memflow-ffi", 17 | "memflow-win32-ffi", 18 | "memflow-bench", 19 | ] 20 | 21 | exclude = [ 22 | "nostd-test", 23 | "memflow-qemu-procfs" 24 | ] 25 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 ko1N 4 | Copyright (c) 2020 Aurimas Blažulionis <0x60@pm.me> 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. -------------------------------------------------------------------------------- /apex_dma/memflow_lib/docs/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KrackerCo/apex_dma_kvm_pub/4e35017c8d6ba5676c4cca85edb2e89e77ff62e8/apex_dma/memflow_lib/docs/logo.png -------------------------------------------------------------------------------- /apex_dma/memflow_lib/docs/windbg_cheat_sheet.txt: -------------------------------------------------------------------------------- 1 | load kernel syms: 2 | .sympath srv*https://msdl.microsoft.com/download/symbols 3 | .reload /f 4 | 5 | get eprocess of a proc: 6 | !process 0 0 7 | or 8 | !process calc.exe 9 | then 10 | dt nt!_EPROCESS
11 | 12 | vtop: 13 | !vtop PFN VirtualAddress 14 | !vtop 0 VirtualAddress 15 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-bench/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-bench/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "memflow-bench" 3 | version = "0.1.5" 4 | authors = ["Aurimas Blažulionis <0x60@pm.me>"] 5 | edition = "2018" 6 | description = "benchmarks for the memflow physical memory introspection framework" 7 | readme = "README.md" 8 | homepage = "https://memflow.github.io" 9 | repository = "https://github.com/memflow/memflow" 10 | license-file = "../LICENSE" 11 | keywords = [ "memflow", "introspection", "memory", "dma" ] 12 | categories = [ "memory-management", "os" ] 13 | publish = false 14 | 15 | [dependencies] 16 | memflow = { path = "../memflow", features = ["dummy_mem"] } 17 | rand = "0.7" 18 | rand_xorshift = "0.2" 19 | 20 | # This branch provides throughput plots 21 | criterion = { git = "https://github.com/h33p/criterion.rs.git", branch = "tput" } 22 | 23 | memflow-win32 = { path = "../memflow-win32" } 24 | 25 | [dev-dependencies] 26 | memflow = { path = "../memflow", features = ["dummy_mem"] } 27 | memflow-win32 = { path = "../memflow-win32" } 28 | 29 | [features] 30 | default = [] 31 | 32 | [[bench]] 33 | name = "read_dummy" 34 | harness = false 35 | 36 | #[[bench]] 37 | #name = "read_win32" 38 | #harness = false 39 | 40 | [[bench]] 41 | name = "batcher" 42 | harness = false 43 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-bench/README.md: -------------------------------------------------------------------------------- 1 | # memflow-bench 2 | [![Crates.io](https://img.shields.io/crates/v/memflow.svg)](https://crates.io/crates/memflow) 3 | ![build and test](https://github.com/memflow/memflow/workflows/Build%20and%20test/badge.svg?branch=dev) 4 | [![codecov](https://codecov.io/gh/memflow/memflow/branch/master/graph/badge.svg?token=XT7R158N6W)](https://codecov.io/gh/memflow/memflow) 5 | [![MIT licensed](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE) 6 | [![Discord](https://img.shields.io/discord/738739624976973835?color=%20%237289da&label=Discord)](https://discord.gg/afsEtMR) 7 | 8 | The bench crate contains benchmarks for the [memflow](https://github.com/memflow/memflow) library by utiziling the [criterion.rs](https://github.com/bheisler/criterion.rs) framework. 9 | 10 | You can run the benchmarks by executing `cargo bench` in the memflow workspace root. 11 | 12 | Current benchmarks contain: 13 | - physical reads 14 | - virtual address translations 15 | - virtual reads 16 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-bench/benches/read_dummy.rs: -------------------------------------------------------------------------------- 1 | extern crate memflow_bench; 2 | use memflow_bench::*; 3 | 4 | use criterion::*; 5 | 6 | use memflow::mem::dummy::{DummyMemory as Memory, DummyModule, DummyProcess}; 7 | use memflow::prelude::v1::*; 8 | 9 | fn initialize_virt_ctx() -> Result<( 10 | Memory, 11 | DirectTranslate, 12 | DummyProcess, 13 | impl ScopedVirtualTranslate, 14 | DummyModule, 15 | )> { 16 | let mut mem = Memory::new(size::mb(64)); 17 | 18 | let vat = DirectTranslate::new(); 19 | 20 | let proc = mem.alloc_process(size::mb(60), &[]); 21 | let module = proc.get_module(size::mb(4)); 22 | let translator = proc.translator(); 23 | Ok((mem, vat, proc, translator, module)) 24 | } 25 | 26 | fn dummy_read_group(c: &mut Criterion) { 27 | virt::seq_read(c, "dummy", &initialize_virt_ctx); 28 | virt::chunk_read(c, "dummy", &initialize_virt_ctx); 29 | phys::seq_read(c, "dummy", &|| Ok(Memory::new(size::mb(64)))); 30 | phys::chunk_read(c, "dummy", &|| Ok(Memory::new(size::mb(64)))); 31 | vat::chunk_vat(c, "dummy", &initialize_virt_ctx); 32 | } 33 | 34 | criterion_group! { 35 | name = dummy_read; 36 | config = Criterion::default() 37 | .warm_up_time(std::time::Duration::from_millis(300)) 38 | .measurement_time(std::time::Duration::from_millis(2700)); 39 | targets = dummy_read_group 40 | } 41 | 42 | criterion_main!(dummy_read); 43 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-bench/benches/read_win32.rs: -------------------------------------------------------------------------------- 1 | extern crate memflow_bench; 2 | use memflow_bench::{phys, vat, virt}; 3 | 4 | use criterion::*; 5 | 6 | use memflow::error::{Error, Result}; 7 | use memflow::prelude::v1::*; 8 | use memflow_win32::prelude::v1::*; 9 | 10 | use rand::prelude::*; 11 | use rand::{Rng, SeedableRng}; 12 | use rand_xorshift::XorShiftRng as CurRng; 13 | 14 | fn create_connector(args: &ConnectorArgs) -> Result { 15 | unsafe { memflow::connector::ConnectorInventory::scan().create_connector("qemu_procfs", args) } 16 | } 17 | 18 | fn initialize_virt_ctx() -> Result<( 19 | impl PhysicalMemory, 20 | DirectTranslate, 21 | Win32ProcessInfo, 22 | impl ScopedVirtualTranslate, 23 | Win32ModuleInfo, 24 | )> { 25 | let mut phys_mem = create_connector(&ConnectorArgs::new())?; 26 | 27 | let kernel_info = KernelInfo::scanner(&mut phys_mem) 28 | .scan() 29 | .map_err(|_| Error::Other("unable to find kernel"))?; 30 | let mut vat = DirectTranslate::new(); 31 | let offsets = Win32Offsets::builder() 32 | .kernel_info(&kernel_info) 33 | .build() 34 | .map_err(|_| Error::Other("unable to initialize win32 offsets with guid"))?; 35 | 36 | let mut kernel = Kernel::new(&mut phys_mem, &mut vat, offsets, kernel_info); 37 | 38 | let mut rng = CurRng::from_rng(thread_rng()).unwrap(); 39 | 40 | let proc_list = kernel 41 | .process_info_list() 42 | .map_err(|_| Error::Other("unable to read process list"))?; 43 | for i in -100..(proc_list.len() as isize) { 44 | let idx = if i >= 0 { 45 | i as usize 46 | } else { 47 | rng.gen_range(0, proc_list.len()) 48 | }; 49 | 50 | let mod_list: Vec = { 51 | let mut prc = Win32Process::with_kernel_ref(&mut kernel, proc_list[idx].clone()); 52 | prc.module_list() 53 | .unwrap_or_default() 54 | .into_iter() 55 | .filter(|module| module.size > 0x1000) 56 | .collect() 57 | }; 58 | 59 | if !mod_list.is_empty() { 60 | let tmod = &mod_list[rng.gen_range(0, mod_list.len())]; 61 | let proc = proc_list[idx].clone(); 62 | let translator = proc.translator(); 63 | return Ok((phys_mem, vat, proc, translator, tmod.clone())); // TODO: remove clone of mem + vat 64 | } 65 | } 66 | 67 | Err("No module found!".into()) 68 | } 69 | 70 | fn win32_read_group(c: &mut Criterion) { 71 | virt::seq_read(c, "win32", &initialize_virt_ctx); 72 | virt::chunk_read(c, "win32", &initialize_virt_ctx); 73 | phys::seq_read(c, "win32", &|| create_connector(&ConnectorArgs::new())); 74 | phys::chunk_read(c, "win32", &|| create_connector(&ConnectorArgs::new())); 75 | vat::chunk_vat(c, "win32", &initialize_virt_ctx); 76 | } 77 | 78 | criterion_group! { 79 | name = win32_read; 80 | config = Criterion::default() 81 | .warm_up_time(std::time::Duration::from_millis(300)) 82 | .measurement_time(std::time::Duration::from_millis(2700)); 83 | targets = win32_read_group 84 | } 85 | 86 | criterion_main!(win32_read); 87 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-bench/src/lib.rs: -------------------------------------------------------------------------------- 1 | pub mod phys; 2 | pub mod vat; 3 | pub mod virt; 4 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-derive/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "memflow-derive" 3 | version = "0.1.5" 4 | authors = ["ko1N ", "Aurimas Blažulionis <0x60@pm.me>"] 5 | edition = "2018" 6 | description = "derive macros for the memflow physical memory introspection framework" 7 | documentation = "https://docs.rs/memflow-derive" 8 | readme = "README.md" 9 | homepage = "https://memflow.github.io" 10 | repository = "https://github.com/memflow/memflow" 11 | license-file = "../LICENSE" 12 | keywords = [ "memflow", "introspection", "memory", "dma" ] 13 | categories = [ "memory-management", "os" ] 14 | 15 | [badges] 16 | maintenance = { status = "actively-developed" } 17 | 18 | [lib] 19 | proc-macro = true 20 | 21 | [dependencies] 22 | proc-macro2 = "1.0" 23 | syn = "1.0" 24 | quote = "1.0" 25 | darling = "0.10" 26 | 27 | [dev-dependencies] 28 | memflow = { version = "0.1", path = "../memflow" } 29 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-derive/README.md: -------------------------------------------------------------------------------- 1 | # memflow-derive 2 | [![Crates.io](https://img.shields.io/crates/v/memflow.svg)](https://crates.io/crates/memflow) 3 | ![build and test](https://github.com/memflow/memflow/workflows/Build%20and%20test/badge.svg?branch=dev) 4 | [![codecov](https://codecov.io/gh/memflow/memflow/branch/master/graph/badge.svg?token=XT7R158N6W)](https://codecov.io/gh/memflow/memflow) 5 | [![MIT licensed](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE) 6 | [![Discord](https://img.shields.io/discord/738739624976973835?color=%20%237289da&label=Discord)](https://discord.gg/afsEtMR) 7 | 8 | The derive crate contains proc macros that can be used with the [memflow](https://github.com/memflow/memflow) library. 9 | 10 | Currently it features the following proc macros: 11 | - A `connector` macro for creating the boilerplate connector plugin code 12 | - A `ByteSwap` derive proc macro 13 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-derive/src/lib.rs: -------------------------------------------------------------------------------- 1 | use darling::FromMeta; 2 | use proc_macro::TokenStream; 3 | use quote::quote; 4 | use syn::{parse_macro_input, AttributeArgs, Data, DeriveInput, Fields, ItemFn}; 5 | 6 | #[derive(Debug, FromMeta)] 7 | struct ConnectorFactoryArgs { 8 | name: String, 9 | #[darling(default)] 10 | version: Option, 11 | } 12 | 13 | // We should add conditional compilation for the crate-type here 14 | // so our rust libraries who use a connector wont export those functions 15 | // again by themselves (e.g. the ffi). 16 | // 17 | // This would also lead to possible duplicated symbols if 18 | // multiple connectors are imported. 19 | // 20 | // See https://github.com/rust-lang/rust/issues/20267 for the tracking issue. 21 | // 22 | // #[cfg(crate_type = "cdylib")] 23 | #[proc_macro_attribute] 24 | pub fn connector(args: TokenStream, input: TokenStream) -> TokenStream { 25 | let attr_args = parse_macro_input!(args as AttributeArgs); 26 | let args = match ConnectorFactoryArgs::from_list(&attr_args) { 27 | Ok(v) => v, 28 | Err(e) => return TokenStream::from(e.write_errors()), 29 | }; 30 | 31 | let connector_name = args.name; 32 | 33 | let func = parse_macro_input!(input as ItemFn); 34 | let func_name = &func.sig.ident; 35 | 36 | let gen = quote! { 37 | #[cfg(feature = "inventory")] 38 | #[doc(hidden)] 39 | pub static CONNECTOR_NAME: &str = #connector_name; 40 | 41 | #[cfg(feature = "inventory")] 42 | #[doc(hidden)] 43 | #[no_mangle] 44 | pub static MEMFLOW_CONNECTOR: ::memflow::connector::ConnectorDescriptor = ::memflow::connector::ConnectorDescriptor { 45 | connector_version: ::memflow::connector::MEMFLOW_CONNECTOR_VERSION, 46 | name: CONNECTOR_NAME, 47 | factory: connector_factory, 48 | }; 49 | 50 | #[cfg(feature = "inventory")] 51 | pub extern "C" fn connector_factory(args: &::memflow::connector::ConnectorArgs) -> ::memflow::error::Result<::memflow::connector::ConnectorType> { 52 | let connector = #func_name(args)?; 53 | Ok(Box::new(connector)) 54 | } 55 | 56 | pub fn static_connector_factory(args: &::memflow::connector::ConnectorArgs) -> ::memflow::error::Result { 57 | #func_name(args) 58 | } 59 | 60 | #func 61 | }; 62 | gen.into() 63 | } 64 | 65 | #[proc_macro_derive(ByteSwap)] 66 | pub fn byteswap_derive(input: TokenStream) -> TokenStream { 67 | let input = parse_macro_input!(input as DeriveInput); 68 | let name = &input.ident; 69 | let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl(); 70 | 71 | let mut gen_inner = quote!(); 72 | match input.data { 73 | Data::Struct(data) => match data.fields { 74 | Fields::Named(named) => { 75 | for field in named.named.iter() { 76 | let name = field.ident.as_ref().unwrap(); 77 | gen_inner.extend(quote!( 78 | self.#name.byte_swap(); 79 | )); 80 | } 81 | } 82 | _ => unimplemented!(), 83 | }, 84 | _ => unimplemented!(), 85 | }; 86 | 87 | let gen = quote!( 88 | impl #impl_generics ::memflow::types::byte_swap::ByteSwap for #name #ty_generics #where_clause { 89 | fn byte_swap(&mut self) { 90 | #gen_inner 91 | } 92 | } 93 | ); 94 | 95 | gen.into() 96 | } 97 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-derive/tests/derive_test.rs: -------------------------------------------------------------------------------- 1 | use memflow::types::byte_swap::ByteSwap; 2 | use memflow_derive::*; 3 | 4 | #[derive(ByteSwap)] 5 | struct ByteSwapDerive { 6 | pub val: u32, 7 | } 8 | 9 | #[derive(ByteSwap)] 10 | struct ByteSwapDeriveGeneric { 11 | pub val: T, 12 | } 13 | 14 | #[derive(ByteSwap)] 15 | struct ByteSwapDeriveWhere 16 | where 17 | T: ByteSwap, 18 | { 19 | pub val: T, 20 | } 21 | 22 | #[derive(ByteSwap)] 23 | struct ByteSwapDeriveSlice { 24 | pub slice: [u8; 32], 25 | } 26 | 27 | #[derive(ByteSwap)] 28 | struct ByteSwapDeriveStructSlice { 29 | pub slice: [ByteSwapDeriveSlice; 128], 30 | } 31 | 32 | #[derive(ByteSwap)] 33 | struct ByteSwapDeriveStructGenericSlice { 34 | pub slice: [ByteSwapDeriveGeneric; 128], 35 | } 36 | 37 | #[test] 38 | pub fn compiles() {} 39 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-ffi/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | **/*.rs.bk 3 | bindings 4 | **/node_modules 5 | **/*.out 6 | **/*.o 7 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-ffi/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "memflow-ffi" 3 | version = "0.1.5" 4 | authors = ["ko1N ", "Aurimas Blažulionis <0x60@pm.me>"] 5 | edition = "2018" 6 | description = "C bindings for the memflow physical memory introspection framework" 7 | documentation = "https://docs.rs/memflow-ffi" 8 | readme = "README.md" 9 | homepage = "https://memflow.github.io" 10 | repository = "https://github.com/memflow/memflow" 11 | license-file = "../LICENSE" 12 | keywords = [ "memflow", "introspection", "memory", "dma" ] 13 | categories = [ "api-bindings", "memory-management", "os" ] 14 | 15 | [badges] 16 | maintenance = { status = "actively-developed" } 17 | codecov = { repository = "github", branch = "master", service = "github" } 18 | 19 | [lib] 20 | name = "memflow_ffi" 21 | crate-type = ["lib", "cdylib", "staticlib"] 22 | 23 | [dependencies] 24 | memflow = { version = "0.1", path = "../memflow" } 25 | log = "0.4" 26 | simple_logger = "1.9" 27 | 28 | [features] 29 | default = [] 30 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-ffi/README.md: -------------------------------------------------------------------------------- 1 | # memflow-ffi 2 | [![Crates.io](https://img.shields.io/crates/v/memflow.svg)](https://crates.io/crates/memflow) 3 | ![build and test](https://github.com/memflow/memflow/workflows/Build%20and%20test/badge.svg?branch=dev) 4 | [![codecov](https://codecov.io/gh/memflow/memflow/branch/master/graph/badge.svg?token=XT7R158N6W)](https://codecov.io/gh/memflow/memflow) 5 | [![MIT licensed](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE) 6 | [![Discord](https://img.shields.io/discord/738739624976973835?color=%20%237289da&label=Discord)](https://discord.gg/afsEtMR) 7 | 8 | The [memflow](https://github.com/memflow/memflow) FFI crate provides an interface to the memflow API for C/C++. Currently a single `memflow.h` file is generated aside from the dynamic library that can be used to interact with memflow. 9 | 10 | A simple example that initializes the library: 11 | ```cpp 12 | #include "memflow.h" 13 | #include 14 | 15 | int main(int argc, char *argv[]) { 16 | log_init(4); 17 | 18 | ConnectorInventory *inv = inventory_try_new(); 19 | printf("inv: %p\n", inv); 20 | 21 | const char *conn_name = argc > 1? argv[1]: "kvm"; 22 | const char *conn_arg = argc > 2? argv[2]: ""; 23 | 24 | CloneablePhysicalMemoryObj *conn = 25 | inventory_create_connector(inv, conn_name, conn_arg); 26 | printf("conn: %p\n", conn); 27 | 28 | if (conn) { 29 | PhysicalMemoryObj *phys_mem = downcast_cloneable(conn); 30 | printf("phys_mem: %p\n", phys_mem); 31 | 32 | uint64_t read = phys_read_u64(phys_mem, addr_to_paddr(0x30000)); 33 | 34 | printf("Read: %lx\n", read); 35 | 36 | phys_free(phys_mem); 37 | 38 | connector_free(conn); 39 | printf("conn freed!\n"); 40 | } 41 | 42 | inventory_free(inv); 43 | printf("inv freed!\n"); 44 | 45 | return 0; 46 | } 47 | ``` 48 | 49 | Additional examples can be found in the `examples` folder as well as in the [memflow-win32-ffi](https://github.com/memflow/memflow/memflow-win32-ffi) crate. 50 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-ffi/binddestr.h: -------------------------------------------------------------------------------- 1 | #ifndef BINDDESTR_H 2 | #define BINDDESTR_H 3 | 4 | #include 5 | 6 | // Binds a particular destructor function to the type, automatically destroying it 7 | template 8 | struct BindDestr 9 | { 10 | T *inner; 11 | 12 | BindDestr(BindDestr &other) = delete; 13 | 14 | BindDestr(BindDestr &&other) { 15 | this->inner = other.inner; 16 | other.inner = NULL; 17 | } 18 | 19 | BindDestr(T *inner2) 20 | : inner(inner2) {} 21 | 22 | ~BindDestr() { 23 | if (this->inner) { 24 | D(this->inner); 25 | } 26 | } 27 | 28 | inline operator const T *() const { 29 | return this->inner; 30 | } 31 | 32 | inline T *invalidate() { 33 | T *ret = this->inner; 34 | this->inner = NULL; 35 | return ret; 36 | } 37 | }; 38 | 39 | // Wrap a C function with a particular class prefix (removes it in the class function) 40 | // and specified return type 41 | #define WRAP_FN_TYPE(TYPE, CLASS, FNAME) \ 42 | template \ 43 | inline TYPE FNAME (Args... args) { \ 44 | return :: CLASS##_##FNAME (this->inner, args...); \ 45 | } 46 | 47 | // Wrap a C function with a particular class prefix (removes it in the class function) 48 | #define WRAP_FN(CLASS, FNAME) WRAP_FN_TYPE(std::function::result_type, CLASS, FNAME) 49 | 50 | // Same, but invalidates the pointer 51 | #define WRAP_FN_TYPE_INVALIDATE(TYPE, CLASS, FNAME) \ 52 | template \ 53 | inline TYPE FNAME (Args... args) { \ 54 | return :: CLASS##_##FNAME (this->invalidate(), args...); \ 55 | } 56 | 57 | #define WRAP_FN_INVALIDATE(CLASS, FNAME) WRAP_FN_TYPE_INVALIDATE(std::function::result_type, CLASS, FNAME) 58 | 59 | // Wrap a C function in a raw way with specified return type 60 | #define WRAP_FN_RAW_TYPE(TYPE, FNAME) \ 61 | template \ 62 | inline TYPE FNAME (Args... args) { \ 63 | return :: FNAME (this->inner, args...); \ 64 | } 65 | 66 | // Wrap a C function in a raw way 67 | #define WRAP_FN_RAW(FNAME) WRAP_FN_RAW_TYPE(std::function::result_type, FNAME) 68 | 69 | #endif 70 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-ffi/bindgen.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | cargo build --release --workspace 3 | cbindgen --config cbindgen.toml --crate memflow-ffi --output memflow.h 4 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-ffi/cbindgen.toml: -------------------------------------------------------------------------------- 1 | language = "C" 2 | 3 | include_guard = "MEMFLOW_H" 4 | tab_width = 4 5 | documentation_style = "doxy" 6 | style = "both" 7 | #no_includes = true 8 | cpp_compat = true 9 | 10 | [parse] 11 | parse_deps = true 12 | 13 | include = ["memflow"] 14 | 15 | [macro_expansion] 16 | bitflags = true 17 | 18 | [fn] 19 | sort_by = "None" 20 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-ffi/examples/Makefile: -------------------------------------------------------------------------------- 1 | CC =g++ 2 | CFLAGS =-I../ -I../../memflow-ffi/ -L../../target/release 3 | LIBS=-lm -Wl,--no-as-needed -ldl -lpthread -l:libmemflow_win32_ffi.a 4 | 5 | ODIR=./ 6 | 7 | %.o: %.c $(DEPS) 8 | $(CC) -c -o $@ $< $(CFLAGS) 9 | 10 | phys_mem.out: phys_mem.o 11 | $(CC) -o $@ $^ $(CFLAGS) $(LIBS) 12 | 13 | .PHONY: all 14 | all: phys_mem.out 15 | 16 | .DEFAULT_GOAL := all 17 | 18 | clean: 19 | rm -f $(ODIR)/*.o 20 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-ffi/examples/phys_mem.c: -------------------------------------------------------------------------------- 1 | #include "memflow.h" 2 | #include 3 | 4 | int main(int argc, char *argv[]) 5 | { 6 | log_init(4); 7 | 8 | ConnectorInventory *inv = inventory_scan(); 9 | printf("inv: %p\n", inv); 10 | 11 | const char *conn_name = argc > 1? argv[1]: "qemu_procfs"; 12 | const char *conn_arg = argc > 2? argv[2]: ""; 13 | 14 | CloneablePhysicalMemoryObj *conn = inventory_create_connector(inv, conn_name, conn_arg); 15 | printf("conn: %p\n", conn); 16 | 17 | if (conn) { 18 | PhysicalMemoryObj *phys_mem = downcast_cloneable(conn); 19 | printf("phys_mem: %p\n", phys_mem); 20 | 21 | uint64_t read = phys_read_u64(phys_mem, addr_to_paddr(0x30000)); 22 | 23 | printf("Read: %lx\n", read); 24 | 25 | phys_free(phys_mem); 26 | 27 | connector_free(conn); 28 | printf("conn freed!\n"); 29 | } 30 | 31 | inventory_free(inv); 32 | printf("inv freed!\n"); 33 | 34 | return 0; 35 | } 36 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-ffi/src/architecture/mod.rs: -------------------------------------------------------------------------------- 1 | use memflow::architecture::{ArchitectureObj, Endianess}; 2 | 3 | pub mod x86; 4 | 5 | #[no_mangle] 6 | pub extern "C" fn arch_bits(arch: &ArchitectureObj) -> u8 { 7 | arch.bits() 8 | } 9 | 10 | #[no_mangle] 11 | pub extern "C" fn arch_endianess(arch: &ArchitectureObj) -> Endianess { 12 | arch.endianess() 13 | } 14 | 15 | #[no_mangle] 16 | pub extern "C" fn arch_page_size(arch: &ArchitectureObj) -> usize { 17 | arch.page_size() 18 | } 19 | 20 | #[no_mangle] 21 | pub extern "C" fn arch_size_addr(arch: &ArchitectureObj) -> usize { 22 | arch.size_addr() 23 | } 24 | 25 | #[no_mangle] 26 | pub extern "C" fn arch_address_space_bits(arch: &ArchitectureObj) -> u8 { 27 | arch.address_space_bits() 28 | } 29 | 30 | /// Free an architecture reference 31 | /// 32 | /// # Safety 33 | /// 34 | /// `arch` must be a valid heap allocated reference created by one of the API's functions. 35 | #[no_mangle] 36 | pub unsafe extern "C" fn arch_free(arch: &'static mut ArchitectureObj) { 37 | let _ = Box::from_raw(arch); 38 | } 39 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-ffi/src/architecture/x86.rs: -------------------------------------------------------------------------------- 1 | use memflow::architecture::{x86, ArchitectureObj}; 2 | 3 | #[no_mangle] 4 | pub static X86_32: &ArchitectureObj = &x86::x32::ARCH; 5 | 6 | #[no_mangle] 7 | pub static X86_32_PAE: &ArchitectureObj = &x86::x32_pae::ARCH; 8 | 9 | #[no_mangle] 10 | pub static X86_64: &ArchitectureObj = &x86::x64::ARCH; 11 | 12 | #[no_mangle] 13 | pub extern "C" fn is_x86_arch(arch: &ArchitectureObj) -> bool { 14 | x86::is_x86_arch(*arch) 15 | } 16 | 17 | // TODO: new_translator, if it is feasible 18 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-ffi/src/lib.rs: -------------------------------------------------------------------------------- 1 | pub mod log; 2 | 3 | pub mod types; 4 | 5 | pub mod connectors; 6 | 7 | pub mod mem; 8 | 9 | pub mod architecture; 10 | 11 | pub mod process; 12 | 13 | pub mod util; 14 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-ffi/src/log.rs: -------------------------------------------------------------------------------- 1 | use log::Level; 2 | 3 | #[no_mangle] 4 | pub extern "C" fn log_init(level_num: i32) { 5 | let level = match level_num { 6 | 0 => Level::Error, 7 | 1 => Level::Warn, 8 | 2 => Level::Info, 9 | 3 => Level::Debug, 10 | 4 => Level::Trace, 11 | _ => Level::Trace, 12 | }; 13 | simple_logger::SimpleLogger::new() 14 | .with_level(level.to_level_filter()) 15 | .init() 16 | .unwrap(); 17 | } 18 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-ffi/src/mem/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod phys_mem; 2 | pub mod virt_mem; 3 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-ffi/src/mem/virt_mem.rs: -------------------------------------------------------------------------------- 1 | use memflow::error::PartialResultExt; 2 | use memflow::mem::virt_mem::*; 3 | use memflow::types::Address; 4 | 5 | use crate::util::*; 6 | 7 | use std::slice::{from_raw_parts, from_raw_parts_mut}; 8 | 9 | pub type VirtualMemoryObj = &'static mut dyn VirtualMemory; 10 | 11 | /// Free a virtual memory object reference 12 | /// 13 | /// This function frees the reference to a virtual memory object. 14 | /// 15 | /// # Safety 16 | /// 17 | /// `mem` must be a valid reference to a virtual memory object. 18 | #[no_mangle] 19 | pub unsafe extern "C" fn virt_free(mem: &'static mut VirtualMemoryObj) { 20 | let _ = Box::from_raw(mem); 21 | } 22 | 23 | /// Read a list of values 24 | /// 25 | /// This will perform `len` virtual memory reads on the provided `data`. Using lists is preferable 26 | /// for performance, because then the underlying connectors can batch those operations, and virtual 27 | /// translation function can cut down on read operations. 28 | /// 29 | /// # Safety 30 | /// 31 | /// `data` must be a valid array of `VirtualReadData` with the length of at least `len` 32 | #[no_mangle] 33 | pub unsafe extern "C" fn virt_read_raw_list( 34 | mem: &mut VirtualMemoryObj, 35 | data: *mut VirtualReadData, 36 | len: usize, 37 | ) -> i32 { 38 | let data = from_raw_parts_mut(data, len); 39 | mem.virt_read_raw_list(data).data_part().int_result() 40 | } 41 | 42 | /// Write a list of values 43 | /// 44 | /// This will perform `len` virtual memory writes on the provided `data`. Using lists is preferable 45 | /// for performance, because then the underlying connectors can batch those operations, and virtual 46 | /// translation function can cut down on read operations. 47 | /// 48 | /// # Safety 49 | /// 50 | /// `data` must be a valid array of `VirtualWriteData` with the length of at least `len` 51 | #[no_mangle] 52 | pub unsafe extern "C" fn virt_write_raw_list( 53 | mem: &mut VirtualMemoryObj, 54 | data: *const VirtualWriteData, 55 | len: usize, 56 | ) -> i32 { 57 | let data = from_raw_parts(data, len); 58 | mem.virt_write_raw_list(data).data_part().int_result() 59 | } 60 | 61 | /// Read a single value into `out` from a provided `Address` 62 | /// 63 | /// # Safety 64 | /// 65 | /// `out` must be a valid pointer to a data buffer of at least `len` size. 66 | #[no_mangle] 67 | pub unsafe extern "C" fn virt_read_raw_into( 68 | mem: &mut VirtualMemoryObj, 69 | addr: Address, 70 | out: *mut u8, 71 | len: usize, 72 | ) -> i32 { 73 | mem.virt_read_raw_into(addr, from_raw_parts_mut(out, len)) 74 | .data_part() 75 | .int_result() 76 | } 77 | 78 | /// Read a single 32-bit value from a provided `Address` 79 | #[no_mangle] 80 | pub extern "C" fn virt_read_u32(mem: &mut VirtualMemoryObj, addr: Address) -> u32 { 81 | mem.virt_read::(addr).unwrap_or_default() 82 | } 83 | 84 | /// Read a single 64-bit value from a provided `Address` 85 | #[no_mangle] 86 | pub extern "C" fn virt_read_u64(mem: &mut VirtualMemoryObj, addr: Address) -> u64 { 87 | mem.virt_read::(addr).unwrap_or_default() 88 | } 89 | 90 | /// Write a single value from `input` into a provided `Address` 91 | /// 92 | /// # Safety 93 | /// 94 | /// `input` must be a valid pointer to a data buffer of at least `len` size. 95 | #[no_mangle] 96 | pub unsafe extern "C" fn virt_write_raw( 97 | mem: &mut VirtualMemoryObj, 98 | addr: Address, 99 | input: *const u8, 100 | len: usize, 101 | ) -> i32 { 102 | mem.virt_write_raw(addr, from_raw_parts(input, len)) 103 | .data_part() 104 | .int_result() 105 | } 106 | 107 | /// Write a single 32-bit value into a provided `Address` 108 | #[no_mangle] 109 | pub extern "C" fn virt_write_u32(mem: &mut VirtualMemoryObj, addr: Address, val: u32) -> i32 { 110 | mem.virt_write(addr, &val).data_part().int_result() 111 | } 112 | 113 | /// Write a single 64-bit value into a provided `Address` 114 | #[no_mangle] 115 | pub extern "C" fn virt_write_u64(mem: &mut VirtualMemoryObj, addr: Address, val: u64) -> i32 { 116 | mem.virt_write(addr, &val).data_part().int_result() 117 | } 118 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-ffi/src/process.rs: -------------------------------------------------------------------------------- 1 | use crate::util::*; 2 | use memflow::process::*; 3 | use std::os::raw::c_char; 4 | use std::slice::from_raw_parts_mut; 5 | 6 | use memflow::architecture::ArchitectureObj; 7 | use memflow::types::Address; 8 | 9 | pub type OsProcessInfoObj = &'static dyn OsProcessInfo; 10 | 11 | #[no_mangle] 12 | pub extern "C" fn os_process_info_address(obj: &OsProcessInfoObj) -> Address { 13 | obj.address() 14 | } 15 | 16 | #[no_mangle] 17 | pub extern "C" fn os_process_info_pid(obj: &OsProcessInfoObj) -> PID { 18 | obj.pid() 19 | } 20 | 21 | /// Retreive name of the process 22 | /// 23 | /// This will copy at most `max_len` characters (including the null terminator) into `out` of the 24 | /// name. 25 | /// 26 | /// # Safety 27 | /// 28 | /// `out` must be a buffer with at least `max_len` size 29 | #[no_mangle] 30 | pub unsafe extern "C" fn os_process_info_name( 31 | obj: &OsProcessInfoObj, 32 | out: *mut c_char, 33 | max_len: usize, 34 | ) -> usize { 35 | let name = obj.name(); 36 | let name_bytes = name.as_bytes(); 37 | let out_bytes = from_raw_parts_mut(out as *mut u8, std::cmp::min(max_len, name.len() + 1)); 38 | let len = out_bytes.len(); 39 | out_bytes[..(len - 1)].copy_from_slice(&name_bytes[..(len - 1)]); 40 | *out_bytes.iter_mut().last().unwrap() = 0; 41 | len 42 | } 43 | 44 | #[no_mangle] 45 | pub extern "C" fn os_process_info_sys_arch(obj: &OsProcessInfoObj) -> &ArchitectureObj { 46 | to_heap(obj.sys_arch()) 47 | } 48 | 49 | #[no_mangle] 50 | pub extern "C" fn os_process_info_proc_arch(obj: &OsProcessInfoObj) -> &ArchitectureObj { 51 | to_heap(obj.proc_arch()) 52 | } 53 | 54 | /// Free a OsProcessInfoObj reference 55 | /// 56 | /// # Safety 57 | /// 58 | /// `obj` must point to a valid `OsProcessInfoObj`, and was created using one of the API's 59 | /// functions. 60 | #[no_mangle] 61 | pub unsafe extern "C" fn os_process_info_free(obj: &'static mut OsProcessInfoObj) { 62 | let _ = Box::from_raw(obj); 63 | } 64 | 65 | pub type OsProcessModuleInfoObj = &'static dyn OsProcessModuleInfo; 66 | 67 | #[no_mangle] 68 | pub extern "C" fn os_process_module_address(obj: &OsProcessModuleInfoObj) -> Address { 69 | obj.address() 70 | } 71 | 72 | #[no_mangle] 73 | pub extern "C" fn os_process_module_parent_process(obj: &OsProcessModuleInfoObj) -> Address { 74 | obj.parent_process() 75 | } 76 | 77 | #[no_mangle] 78 | pub extern "C" fn os_process_module_base(obj: &OsProcessModuleInfoObj) -> Address { 79 | obj.base() 80 | } 81 | 82 | #[no_mangle] 83 | pub extern "C" fn os_process_module_size(obj: &OsProcessModuleInfoObj) -> usize { 84 | obj.size() 85 | } 86 | 87 | /// Retreive name of the module 88 | /// 89 | /// This will copy at most `max_len` characters (including the null terminator) into `out` of the 90 | /// name. 91 | /// 92 | /// # Safety 93 | /// 94 | /// `out` must be a buffer with at least `max_len` size 95 | #[no_mangle] 96 | pub unsafe extern "C" fn os_process_module_name( 97 | obj: &OsProcessModuleInfoObj, 98 | out: *mut c_char, 99 | max_len: usize, 100 | ) -> usize { 101 | let name = obj.name(); 102 | let name_bytes = name.as_bytes(); 103 | let out_bytes = from_raw_parts_mut(out as *mut u8, std::cmp::min(max_len, name.len() + 1)); 104 | let len = out_bytes.len(); 105 | out_bytes[..(len - 1)].copy_from_slice(&name_bytes[..(len - 1)]); 106 | *out_bytes.iter_mut().last().unwrap() = 0; 107 | len 108 | } 109 | 110 | /// Free a OsProcessModuleInfoObj reference 111 | /// 112 | /// # Safety 113 | /// 114 | /// `obj` must point to a valid `OsProcessModuleInfoObj`, and was created using one of the API's 115 | /// functions. 116 | #[no_mangle] 117 | pub unsafe extern "C" fn os_process_module_free(obj: &'static mut OsProcessModuleInfoObj) { 118 | let _ = Box::from_raw(obj); 119 | } 120 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-ffi/src/types/mod.rs: -------------------------------------------------------------------------------- 1 | use memflow::types::{Address, PhysicalAddress}; 2 | 3 | /// Helper to convert `Address` to a `PhysicalAddress` 4 | /// 5 | /// This will create a `PhysicalAddress` with `UNKNOWN` PageType. 6 | #[no_mangle] 7 | pub extern "C" fn addr_to_paddr(address: Address) -> PhysicalAddress { 8 | address.into() 9 | } 10 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-ffi/src/util.rs: -------------------------------------------------------------------------------- 1 | use log::error; 2 | 3 | pub fn inspect_err(e: E) -> E { 4 | error!("{}", e); 5 | e 6 | } 7 | 8 | pub fn to_heap(a: T) -> &'static mut T { 9 | Box::leak(Box::new(a)) 10 | } 11 | 12 | pub trait ToIntResult { 13 | fn int_result(self) -> i32; 14 | 15 | fn int_result_logged(self) -> i32 16 | where 17 | Self: Sized, 18 | { 19 | let res = self.int_result(); 20 | if res != 0 { 21 | error!("err value: {}", res); 22 | } 23 | res 24 | } 25 | } 26 | 27 | impl ToIntResult for Result { 28 | fn int_result(self) -> i32 { 29 | if self.is_ok() { 30 | 0 31 | } else { 32 | -1 33 | } 34 | } 35 | 36 | fn int_result_logged(self) -> i32 { 37 | if let Err(e) = self { 38 | error!("{}", e); 39 | -1 40 | } else { 41 | 0 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-ffi/src/win32.rs: -------------------------------------------------------------------------------- 1 | /* 2 | use std::ffi::c_void; 3 | use std::ptr; 4 | 5 | use memflow_win32::*; 6 | */ 7 | 8 | /* 9 | /// # Safety 10 | /// 11 | /// this function has to be called with an initialized memory backend 12 | /// this function will return a pointer to a win32 object that has to be freed via win32_free() 13 | #[no_mangle] 14 | pub unsafe extern "C" fn win32_init(mem: *mut c_void) -> *mut Win32 { 15 | if !mem.is_null() { 16 | let mut _mem: Box> = std::mem::transmute(mem as *mut _); 17 | 18 | let _os = Win32::try_with(&mut **_mem).unwrap(); 19 | 20 | Box::leak(_mem); 21 | return std::mem::transmute(Box::new(_os)); 22 | } 23 | 24 | ptr::null_mut() 25 | } 26 | 27 | /// # Safety 28 | /// 29 | /// this function has to be called with a pointer that has been initialized from win32_init() 30 | #[no_mangle] 31 | pub unsafe extern "C" fn win32_free(win32: *mut Win32) { 32 | if !win32.is_null() { 33 | let _win32: Box = std::mem::transmute(win32); 34 | // drop _win32 35 | } 36 | } 37 | 38 | /// # Safety 39 | /// 40 | /// this function will return a pointer to a win32_offsets object that has to be freed via win32_offsets_free() 41 | #[no_mangle] 42 | pub unsafe extern "C" fn win32_offsets_init(win32: *mut Win32) -> *mut Win32Offsets { 43 | if !win32.is_null() { 44 | let _win32: Box = std::mem::transmute(win32); 45 | 46 | let _offsets = Win32Offsets::try_with_guid(&_win32.kernel_guid()).unwrap(); 47 | 48 | Box::leak(_win32); 49 | return std::mem::transmute(Box::new(_offsets)); 50 | } 51 | 52 | ptr::null_mut() 53 | } 54 | 55 | /// # Safety 56 | /// 57 | /// this function has to be called with a pointer that has been initialized from win32_offsets_init() 58 | #[no_mangle] 59 | pub unsafe extern "C" fn win32_offsets_free(offsets: *mut Win32Offsets) { 60 | if !offsets.is_null() { 61 | let _offsets: Box = std::mem::transmute(offsets); 62 | // drop _offsets 63 | } 64 | } 65 | */ 66 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-qemu-procfs/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | **/*.rs.bk 3 | *.swp 4 | .vscode 5 | Cargo.lock 6 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-qemu-procfs/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "memflow-qemu-procfs" 3 | version = "0.1.5" 4 | authors = ["ko1N ", "Aurimas Blažulionis <0x60@pm.me>"] 5 | edition = "2018" 6 | description = "qemu procfs connector for the memflow physical memory introspection framework" 7 | documentation = "https://docs.rs/memflow-qemu-procfs" 8 | readme = "README.md" 9 | homepage = "https://memflow.github.io" 10 | repository = "https://github.com/memflow/memflow-qemu-procfs" 11 | license-file = "LICENSE" 12 | keywords = [ "memflow", "introspection", "memory" ] 13 | categories = [ "api-bindings", "memory-management", "os" ] 14 | 15 | [lib] 16 | crate-type = ["lib", "cdylib"] 17 | 18 | [dependencies] 19 | memflow = { version = "0.1", features = ["inventory"] } 20 | log = { version = "0.4", default-features = false } 21 | procfs = "0.7" 22 | libc = "0.2" 23 | 24 | [dev-dependencies] 25 | clap = "2.33" 26 | simple_logger = "1.0" 27 | 28 | [profile.release] 29 | lto = true 30 | 31 | [features] 32 | default = [] 33 | inventory = [] 34 | 35 | [[example]] 36 | name = "read_phys" 37 | path = "examples/read_phys.rs" 38 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-qemu-procfs/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 ko1N 4 | Copyright (c) 2020 Aurimas Blažulionis <0x60@pm.me> 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | 24 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-qemu-procfs/Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: all release debug test install 2 | 3 | all: 4 | make test 5 | make release 6 | 7 | release: 8 | cargo build --release --all-features 9 | 10 | debug: 11 | cargo build --all-features 12 | 13 | clean: 14 | cargo clean 15 | 16 | test: 17 | cargo test --all-features 18 | 19 | install_user: 20 | ./install.sh 21 | 22 | install: 23 | ./install.sh --system 24 | 25 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-qemu-procfs/README.md: -------------------------------------------------------------------------------- 1 | # memflow-qemu-procfs 2 | 3 | This connector implements an interface for Qemu via the Process Filesystem on Linux. 4 | 5 | ## Compilation 6 | 7 | ### Installing the library 8 | 9 | The `./install.sh` script will just compile and install the plugin. 10 | The connector will be installed to `~/.local/lib/memflow` by default. 11 | Additionally the `--system` flag can be specified which will install the connector in `/usr/lib/memflow` as well. 12 | 13 | ### Building the stand-alone connector for dynamic loading 14 | 15 | The stand-alone connector of this library is feature-gated behind the `inventory` feature. 16 | To compile a dynamic library for use with the connector inventory use the following command: 17 | 18 | ``` 19 | cargo build --release --all-features 20 | ``` 21 | 22 | ### Using the crate in a rust project 23 | 24 | To use the connector in a rust project just include it in your Cargo.toml 25 | 26 | ``` 27 | memflow-qemu-procfs = "0.1" 28 | ``` 29 | 30 | Make sure to not enable the `inventory` feature when importing multiple 31 | connectors in a rust project without using the memflow connector inventory. 32 | This might cause duplicated exports being generated in your project. 33 | 34 | ## Arguments 35 | 36 | - `name` - the name of the virtual machine (default argument, optional) 37 | 38 | ## Permissions 39 | 40 | The `qemu_procfs` connector requires access to the qemu process via the linux procfs. This means any process which loads this connector requires to have at least ptrace permissions set. 41 | 42 | To set ptrace permissions on a binary simply use: 43 | ```bash 44 | sudo setcap 'CAP_SYS_PTRACE=ep' [filename] 45 | ``` 46 | 47 | Alternatively you can just run the binary via `sudo`. 48 | 49 | ## License 50 | 51 | Licensed under MIT License, see [LICENSE](LICENSE). 52 | 53 | ### Contribution 54 | 55 | Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, shall be licensed as above, without any additional terms or conditions. 56 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-qemu-procfs/examples/read_phys.rs: -------------------------------------------------------------------------------- 1 | use std::time::Instant; 2 | 3 | use log::{info, Level}; 4 | 5 | use memflow::prelude::v1::*; 6 | 7 | fn main() { 8 | simple_logger::SimpleLogger::new() 9 | .with_level(Level::Debug.to_level_filter()) 10 | .init() 11 | .unwrap(); 12 | 13 | let mut conn = match memflow_qemu_procfs::create_connector(&ConnectorArgs::new()) { 14 | Ok(br) => br, 15 | Err(e) => { 16 | info!("couldn't open memory read context: {:?}", e); 17 | return; 18 | } 19 | }; 20 | 21 | let metadata = conn.metadata(); 22 | info!("Received metadata: {:?}", metadata); 23 | 24 | let mut mem = vec![0; 8]; 25 | conn.phys_read_raw_into(Address::from(0x1000).into(), &mut mem) 26 | .unwrap(); 27 | info!("Received memory: {:?}", mem); 28 | 29 | let start = Instant::now(); 30 | let mut counter = 0; 31 | loop { 32 | let mut buf = vec![0; 0x1000]; 33 | conn.phys_read_raw_into(Address::from(0x1000).into(), &mut buf) 34 | .unwrap(); 35 | 36 | counter += 1; 37 | if (counter % 10000000) == 0 { 38 | let elapsed = start.elapsed().as_millis() as f64; 39 | if elapsed > 0.0 { 40 | info!("{} reads/sec", (f64::from(counter)) / elapsed * 1000.0); 41 | info!("{} ms/read", elapsed / (f64::from(counter))); 42 | } 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-qemu-procfs/install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cargo build --release --all-features 4 | 5 | # install connector to system dir 6 | if [ ! -z "$1" ] && [ $1 = "--system" ]; then 7 | echo "installing connector system-wide in /usr/lib/memflow" 8 | if [[ ! -d /usr/lib/memflow ]]; then 9 | sudo mkdir /usr/lib/memflow 10 | fi 11 | sudo cp target/release/libmemflow_qemu_procfs.so /usr/lib/memflow 12 | fi 13 | 14 | # install connector in user dir 15 | echo "installing connector for user in ~/.local/lib/memflow" 16 | if [[ ! -d ~/.local/lib/memflow ]]; then 17 | mkdir -p ~/.local/lib/memflow 18 | fi 19 | cp target/release/libmemflow_qemu_procfs.so ~/.local/lib/memflow 20 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-win32-ffi/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | **/*.rs.bk 3 | bindings 4 | **/node_modules 5 | **/*.out 6 | **/*.o 7 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-win32-ffi/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "memflow-win32-ffi" 3 | version = "0.1.5" 4 | authors = ["Aurimas Blažulionis <0x60@pm.me>"] 5 | edition = "2018" 6 | description = "C bindings to memflow-win32" 7 | documentation = "https://docs.rs/memflow-win32-ffi" 8 | readme = "README.md" 9 | homepage = "https://memflow.github.io" 10 | repository = "https://github.com/memflow/memflow" 11 | license-file = "../LICENSE" 12 | keywords = [ "memflow", "introspection", "memory", "dma" ] 13 | categories = [ "api-bindings", "memory-management", "os" ] 14 | 15 | [badges] 16 | maintenance = { status = "actively-developed" } 17 | codecov = { repository = "github", branch = "master", service = "github" } 18 | 19 | [lib] 20 | name = "memflow_win32_ffi" 21 | crate-type = ["lib", "cdylib", "staticlib"] 22 | 23 | [dependencies] 24 | memflow-win32 = { version = "0.1", path = "../memflow-win32" } 25 | memflow = { version = "0.1", path = "../memflow" } 26 | memflow-ffi = { version = "0.1", path = "../memflow-ffi" } 27 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-win32-ffi/README.md: -------------------------------------------------------------------------------- 1 | # memflow-win32-ffi 2 | [![Crates.io](https://img.shields.io/crates/v/memflow.svg)](https://crates.io/crates/memflow) 3 | ![build and test](https://github.com/memflow/memflow/workflows/Build%20and%20test/badge.svg?branch=dev) 4 | [![codecov](https://codecov.io/gh/memflow/memflow/branch/master/graph/badge.svg?token=XT7R158N6W)](https://codecov.io/gh/memflow/memflow) 5 | [![MIT licensed](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE) 6 | [![Discord](https://img.shields.io/discord/738739624976973835?color=%20%237289da&label=Discord)](https://discord.gg/afsEtMR) 7 | 8 | The [memflow](https://github.com/memflow/memflow) win32 FFI crate provides an interface to the memflow-win32 API for C/C++. Currently a single `memflow_win32.h` file is generated aside from the dynamic library that can be used to interact with memflow. 9 | 10 | This FFI library is intended to be used in combination with the [memflow-ffi](https://github.com/memflow/memflow/memflow-ffi) library. 11 | 12 | A simple example that initializes the memflow-ffi and memflow-win32-ffi: 13 | ```cpp 14 | #include "memflow_win32.h" 15 | #include 16 | 17 | int main(int argc, char *argv[]) { 18 | log_init(1); 19 | 20 | ConnectorInventory *inv = inventory_try_new(); 21 | printf("inv: %p\n", inv); 22 | 23 | const char *conn_name = argc > 1? argv[1]: "kvm"; 24 | const char *conn_arg = argc > 2? argv[2]: ""; 25 | 26 | CloneablePhysicalMemoryObj *conn = 27 | inventory_create_connector(inv, conn_name, conn_arg); 28 | printf("conn: %p\n", conn); 29 | 30 | if (conn) { 31 | Kernel *kernel = kernel_build(conn); 32 | printf("Kernel: %p\n", kernel); 33 | Win32Version ver = kernel_winver(kernel); 34 | printf("major: %d\n", ver.nt_major_version); 35 | printf("minor: %d\n", ver.nt_minor_version); 36 | printf("build: %d\n", ver.nt_build_number); 37 | 38 | kernel_free(kernel); 39 | } 40 | 41 | inventory_free(inv); 42 | 43 | return 0; 44 | } 45 | ``` 46 | 47 | Additional examples can be found in the `examples` folder as well as in the [memflow-ffi](https://github.com/memflow/memflow/memflow-ffi) crate. 48 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-win32-ffi/bindgen.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | cargo build --release --workspace 3 | cbindgen --config cbindgen.toml --crate memflow-win32-ffi --output memflow_win32.h 4 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-win32-ffi/cbindgen.toml: -------------------------------------------------------------------------------- 1 | language = "C" 2 | 3 | include_guard = "MEMFLOW_WIN32_H" 4 | tab_width = 4 5 | documentation_style = "doxy" 6 | style = "both" 7 | cpp_compat = true 8 | includes = ["memflow.h"] 9 | 10 | [parse] 11 | parse_deps = true 12 | 13 | include = ["memflow-win32", "memflow"] 14 | 15 | [macro_expansion] 16 | bitflags = true 17 | 18 | [fn] 19 | sort_by = "None" 20 | 21 | [export] 22 | exclude = ["PageType", "Address"] 23 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-win32-ffi/examples/Makefile: -------------------------------------------------------------------------------- 1 | CC =gcc 2 | CFLAGS =-I../ -I../../memflow-ffi/ -L../../target/release 3 | LIBS=-lm -ldl -lpthread -l:libmemflow_win32_ffi.a 4 | 5 | ODIR=./ 6 | 7 | %.o: %.c $(DEPS) 8 | $(CC) -c -o $@ $< $(CFLAGS) 9 | 10 | process_list.out: process_list.o 11 | $(CC) -o $@ $^ $(CFLAGS) $(LIBS) 12 | 13 | dump_header.out: dump_header.o 14 | $(CC) -o $@ $^ $(CFLAGS) $(LIBS) 15 | 16 | .PHONY: all 17 | all: process_list.out dump_header.out 18 | 19 | .DEFAULT_GOAL := all 20 | 21 | clean: 22 | rm -f $(ODIR)/*.o 23 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-win32-ffi/examples/dump_header.c: -------------------------------------------------------------------------------- 1 | #include "memflow_win32.h" 2 | #include 3 | 4 | int main(int argc, char *argv[]) { 5 | log_init(1); 6 | 7 | ConnectorInventory *inv = inventory_try_new(); 8 | printf("inv: %p\n", inv); 9 | 10 | const char *conn_name = argc > 1? argv[1]: "kvm"; 11 | const char *conn_arg = argc > 2? argv[2]: ""; 12 | 13 | const char *proc_name = argc > 3? argv[3]: "lsass.exe"; 14 | const char *dll_name = argc > 4? argv[4]: "ntdll.dll"; 15 | 16 | CloneablePhysicalMemoryObj *conn = inventory_create_connector(inv, conn_name, conn_arg); 17 | printf("conn: %p\n", conn); 18 | 19 | if (conn) { 20 | Kernel *kernel = kernel_build(conn); 21 | printf("Kernel: %p\n", kernel); 22 | Win32Version ver = kernel_winver(kernel); 23 | printf("major: %d\n", ver.nt_major_version); 24 | printf("minor: %d\n", ver.nt_minor_version); 25 | printf("build: %d\n", ver.nt_build_number); 26 | 27 | Win32Process *process = kernel_into_process(kernel, proc_name); 28 | 29 | if (process) { 30 | Win32ModuleInfo *module = process_module_info(process, dll_name); 31 | 32 | if (module) { 33 | OsProcessModuleInfoObj *obj = module_info_trait(module); 34 | Address base = os_process_module_base(obj); 35 | os_process_module_free(obj); 36 | VirtualMemoryObj *virt_mem = process_virt_mem(process); 37 | 38 | char header[256]; 39 | if (!virt_read_raw_into(virt_mem, base, header, 256)) { 40 | printf("Read successful!\n"); 41 | for (int o = 0; o < 8; o++) { 42 | for (int i = 0; i < 32; i++) { 43 | printf("%2hhx ", header[o * 32 + i]); 44 | } 45 | printf("\n"); 46 | } 47 | } else { 48 | printf("Failed to read!\n"); 49 | } 50 | 51 | virt_free(virt_mem); 52 | } 53 | 54 | process_free(process); 55 | } 56 | } 57 | 58 | inventory_free(inv); 59 | 60 | return 0; 61 | } 62 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-win32-ffi/examples/process_list.c: -------------------------------------------------------------------------------- 1 | #include "memflow_win32.h" 2 | #include 3 | 4 | int main(int argc, char *argv[]) { 5 | log_init(1); 6 | 7 | ConnectorInventory *inv = inventory_scan(); 8 | printf("inv: %p\n", inv); 9 | 10 | const char *conn_name = argc > 1? argv[1]: "kvm"; 11 | const char *conn_arg = argc > 2? argv[2]: ""; 12 | 13 | CloneablePhysicalMemoryObj *conn = inventory_create_connector(inv, conn_name, conn_arg); 14 | printf("conn: %p\n", conn); 15 | 16 | if (conn) { 17 | Kernel *kernel = kernel_build(conn); 18 | printf("Kernel: %p\n", kernel); 19 | Win32Version ver = kernel_winver(kernel); 20 | printf("major: %d\n", ver.nt_major_version); 21 | printf("minor: %d\n", ver.nt_minor_version); 22 | printf("build: %d\n", ver.nt_build_number); 23 | 24 | Win32ProcessInfo *processes[512]; 25 | size_t process_count = kernel_process_info_list(kernel, processes, 512); 26 | 27 | printf("Process List:\n"); 28 | printf("%-8s | %-16s | %-16s | %-12s | %-5s\n", "PID", "Name", "Base", "DTB", "Wow64"); 29 | 30 | for (size_t i = 0; i < process_count; i++) { 31 | Win32ProcessInfo *process = processes[i]; 32 | OsProcessInfoObj *info = process_info_trait(process); 33 | char name[32]; 34 | os_process_info_name(info, name, 32); 35 | 36 | printf("%-8d | %-16s | %-16lx | %-12lx | %-5s\n", 37 | os_process_info_pid(info), 38 | name, 39 | process_info_section_base(process), 40 | process_info_dtb(process), 41 | process_info_wow64(process)? "Yes" : "No" 42 | ); 43 | 44 | os_process_info_free(info); 45 | process_info_free(process); 46 | } 47 | 48 | kernel_free(kernel); 49 | } 50 | 51 | inventory_free(inv); 52 | 53 | return 0; 54 | } 55 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-win32-ffi/src/kernel/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod start_block; 2 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-win32-ffi/src/kernel/start_block.rs: -------------------------------------------------------------------------------- 1 | use memflow::types::Address; 2 | use memflow_win32::kernel; 3 | 4 | #[repr(C)] 5 | pub struct StartBlock { 6 | pub kernel_hint: Address, 7 | pub dtb: Address, 8 | } 9 | 10 | impl From for StartBlock { 11 | fn from(o: kernel::StartBlock) -> StartBlock { 12 | StartBlock { 13 | kernel_hint: o.kernel_hint, 14 | dtb: o.dtb, 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-win32-ffi/src/lib.rs: -------------------------------------------------------------------------------- 1 | pub mod kernel; 2 | pub mod win32; 3 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-win32-ffi/src/win32/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod kernel; 2 | pub mod module; 3 | pub mod process; 4 | pub mod process_info; 5 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-win32-ffi/src/win32/module.rs: -------------------------------------------------------------------------------- 1 | use memflow_ffi::process::OsProcessModuleInfoObj; 2 | use memflow_ffi::util::to_heap; 3 | use memflow_win32::win32::Win32ModuleInfo; 4 | 5 | #[no_mangle] 6 | pub extern "C" fn module_info_trait( 7 | info: &'static mut Win32ModuleInfo, 8 | ) -> &'static mut OsProcessModuleInfoObj { 9 | to_heap(info) 10 | } 11 | 12 | /// Free a win32 module info instance. 13 | /// 14 | /// Note that it is not the same as `OsProcessModuleInfoObj`, and those references need to be freed 15 | /// manually. 16 | /// 17 | /// # Safety 18 | /// 19 | /// `info` must be a unique heap allocated reference to `Win32ModuleInfo`, and after this call the 20 | /// reference will become invalid. 21 | #[no_mangle] 22 | pub unsafe extern "C" fn module_info_free(info: &'static mut Win32ModuleInfo) { 23 | let _ = Box::from_raw(info); 24 | } 25 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-win32-ffi/src/win32/process_info.rs: -------------------------------------------------------------------------------- 1 | use memflow::types::Address; 2 | use memflow_ffi::process::OsProcessInfoObj; 3 | use memflow_ffi::util::to_heap; 4 | use memflow_win32::win32::{Win32ModuleListInfo, Win32ProcessInfo}; 5 | 6 | #[no_mangle] 7 | pub extern "C" fn process_info_trait( 8 | info: &'static mut Win32ProcessInfo, 9 | ) -> &'static mut OsProcessInfoObj { 10 | to_heap(info) 11 | } 12 | 13 | #[no_mangle] 14 | pub extern "C" fn process_info_dtb(info: &Win32ProcessInfo) -> Address { 15 | info.dtb 16 | } 17 | 18 | #[no_mangle] 19 | pub extern "C" fn process_info_section_base(info: &Win32ProcessInfo) -> Address { 20 | info.section_base 21 | } 22 | 23 | #[no_mangle] 24 | pub extern "C" fn process_info_exit_status(info: &Win32ProcessInfo) -> i32 { 25 | info.exit_status 26 | } 27 | 28 | #[no_mangle] 29 | pub extern "C" fn process_info_ethread(info: &Win32ProcessInfo) -> Address { 30 | info.ethread 31 | } 32 | 33 | #[no_mangle] 34 | pub extern "C" fn process_info_wow64(info: &Win32ProcessInfo) -> Address { 35 | info.wow64() 36 | } 37 | 38 | #[no_mangle] 39 | pub extern "C" fn process_info_peb(info: &Win32ProcessInfo) -> Address { 40 | info.peb() 41 | } 42 | 43 | #[no_mangle] 44 | pub extern "C" fn process_info_peb_native(info: &Win32ProcessInfo) -> Address { 45 | info.peb_native() 46 | } 47 | 48 | #[no_mangle] 49 | pub extern "C" fn process_info_peb_wow64(info: &Win32ProcessInfo) -> Address { 50 | info.peb_wow64().unwrap_or_default() 51 | } 52 | 53 | #[no_mangle] 54 | pub extern "C" fn process_info_teb(info: &Win32ProcessInfo) -> Address { 55 | info.teb.unwrap_or_default() 56 | } 57 | 58 | #[no_mangle] 59 | pub extern "C" fn process_info_teb_wow64(info: &Win32ProcessInfo) -> Address { 60 | info.teb_wow64.unwrap_or_default() 61 | } 62 | 63 | #[no_mangle] 64 | pub extern "C" fn process_info_module_info(info: &Win32ProcessInfo) -> Win32ModuleListInfo { 65 | info.module_info() 66 | } 67 | 68 | #[no_mangle] 69 | pub extern "C" fn process_info_module_info_native(info: &Win32ProcessInfo) -> Win32ModuleListInfo { 70 | info.module_info_native() 71 | } 72 | 73 | /// Free a process information reference 74 | /// 75 | /// # Safety 76 | /// 77 | /// `info` must be a valid heap allocated reference to a Win32ProcessInfo structure 78 | #[no_mangle] 79 | pub unsafe extern "C" fn process_info_free(info: &'static mut Win32ProcessInfo) { 80 | let _ = Box::from_raw(info); 81 | } 82 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-win32/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "memflow-win32" 3 | version = "0.1.5" 4 | authors = ["ko1N ", "Aurimas Blažulionis <0x60@pm.me>"] 5 | edition = "2018" 6 | description = "win32 integration of the memflow physical memory introspection framework" 7 | documentation = "https://docs.rs/memflow-win32" 8 | readme = "README.md" 9 | homepage = "https://memflow.github.io" 10 | repository = "https://github.com/memflow/memflow" 11 | license-file = "../LICENSE" 12 | keywords = [ "memflow", "introspection", "memory", "dma" ] 13 | categories = [ "api-bindings", "memory-management", "os" ] 14 | 15 | [badges] 16 | maintenance = { status = "actively-developed" } 17 | codecov = { repository = "github", branch = "master", service = "github" } 18 | 19 | [dependencies] 20 | memflow = { version = "0.1", path = "../memflow", default-features = false } 21 | log = { version = "0.4", default-features = false } 22 | dataview = "0.1" 23 | pelite = { version = "0.9", default-features = false } 24 | widestring = { version = "0.4", default-features = false, features = ["alloc"] } 25 | no-std-compat = { version = "0.4", features = ["alloc"] } 26 | serde = { version = "1.0", default-features = false, optional = true, features = ["derive"] } 27 | 28 | # will be replaced by our own signature scanner 29 | regex = { version = "1", optional = true } 30 | 31 | # symbolstore 32 | dirs = { version = "2.0", optional = true } 33 | ureq = { version = "1.2", optional = true } 34 | pdb = { version = "0.6", optional = true } 35 | pbr = { version = "1.0", optional = true } 36 | progress-streams = { version = "1.1", optional = true } 37 | 38 | [dev_dependencies] 39 | simple_logger = "1.0" 40 | win_key_codes = "0.1" 41 | rand = "0.7" 42 | rand_xorshift = "0.2" 43 | clap = "2.33" 44 | toml = "0.5" 45 | colored = "2.0" 46 | 47 | [build_dependencies] 48 | toml = "0.5" 49 | dataview = "0.1" 50 | serde = { version = "1.0", default-features = false, features = ["derive", "alloc"] } 51 | 52 | [features] 53 | default = ["std", "serde_derive", "embed_offsets", "symstore", "download_progress", "regex"] 54 | std = ["no-std-compat/std", "memflow/std"] 55 | embed_offsets = ["serde", "memflow/serde_derive"] 56 | collections = [] 57 | alloc = [] 58 | serde_derive = ["serde", "memflow/serde_derive", "pelite/std", "pelite/serde"] 59 | symstore = ["dirs", "ureq", "pdb"] 60 | download_progress = ["pbr", "progress-streams"] 61 | 62 | [[example]] 63 | name = "dump_offsets" 64 | path = "examples/dump_offsets.rs" 65 | 66 | [[example]] 67 | name = "generate_offsets" 68 | path = "examples/generate_offsets.rs" 69 | 70 | [[example]] 71 | name = "read_keys" 72 | path = "examples/read_keys.rs" 73 | 74 | [[example]] 75 | name = "multithreading" 76 | path = "examples/multithreading.rs" 77 | 78 | [[example]] 79 | name = "read_bench" 80 | path = "examples/read_bench.rs" 81 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-win32/README.md: -------------------------------------------------------------------------------- 1 | # memflow-win32 2 | [![Crates.io](https://img.shields.io/crates/v/memflow.svg)](https://crates.io/crates/memflow) 3 | ![build and test](https://github.com/memflow/memflow/workflows/Build%20and%20test/badge.svg?branch=dev) 4 | [![codecov](https://codecov.io/gh/memflow/memflow/branch/master/graph/badge.svg?token=XT7R158N6W)](https://codecov.io/gh/memflow/memflow) 5 | [![MIT licensed](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE) 6 | [![Discord](https://img.shields.io/discord/738739624976973835?color=%20%237289da&label=Discord)](https://discord.gg/afsEtMR) 7 | 8 | This crate provides integration for win32 targets for [memflow](https://github.com/memflow/memflow). This library can be used in addition to the memflow core itself read processes, modules, drivers, etc. 9 | 10 | Example initializing a win32 target: 11 | ```rust 12 | use std::fs::File; 13 | use std::io::Write; 14 | 15 | use log::{error, Level}; 16 | 17 | use memflow::connector::*; 18 | use memflow_win32::win32::{Kernel, Win32OffsetFile}; 19 | 20 | pub fn main() { 21 | let connector_name = std::env::args().nth(1).unwrap(); 22 | let connector_args = std::env::args().nth(2).unwrap_or_default(); 23 | 24 | // create inventory + connector 25 | let inventory = unsafe { ConnectorInventory::try_new() }.unwrap(); 26 | let connector = unsafe { 27 | inventory.create_connector( 28 | &connector_name, 29 | &ConnectorArgs::parse(&connector_args).unwrap(), 30 | ) 31 | } 32 | .unwrap(); 33 | 34 | // initialize kernel 35 | let kernel = Kernel::builder(connector) 36 | .build_default_caches() 37 | .build() 38 | .unwrap(); 39 | 40 | println!("{:?}", kernel); 41 | } 42 | ``` 43 | 44 | Additional examples can be found in the `examples` subdirectory. 45 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-win32/build.rs: -------------------------------------------------------------------------------- 1 | use dataview::Pod; 2 | use std::{ 3 | env, 4 | error::Error, 5 | fs::{self, File}, 6 | io::{Read, Write}, 7 | path::Path, 8 | }; 9 | 10 | #[path = "src/offsets/offset_table.rs"] 11 | #[cfg(feature = "embed_offsets")] 12 | mod offset_table; 13 | 14 | #[cfg(feature = "embed_offsets")] 15 | use offset_table::Win32OffsetFile; 16 | 17 | #[cfg(feature = "embed_offsets")] 18 | fn embed_offsets() -> Result<(), Box> { 19 | let out_dir = env::var("OUT_DIR")?; 20 | let dest_path = Path::new(&out_dir).join("win32_offsets.bin"); 21 | let mut all_the_files = File::create(&dest_path)?; 22 | 23 | // iterate offsets folder 24 | for f in fs::read_dir("./offsets")? { 25 | let f = f?; 26 | 27 | if !f.file_type()?.is_file() { 28 | continue; 29 | } 30 | 31 | let mut file = File::open(f.path())?; 32 | let mut tomlstr = String::new(); 33 | file.read_to_string(&mut tomlstr)?; 34 | 35 | let offsets: Win32OffsetFile = toml::from_str(&tomlstr)?; 36 | all_the_files.write_all(offsets.as_bytes())?; 37 | } 38 | 39 | Ok(()) 40 | } 41 | 42 | #[cfg(not(feature = "embed_offsets"))] 43 | fn embed_offsets() -> Result<(), Box> { 44 | Ok(()) 45 | } 46 | 47 | fn main() -> Result<(), Box> { 48 | embed_offsets()?; 49 | Ok(()) 50 | } 51 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-win32/examples/dump_offsets.rs: -------------------------------------------------------------------------------- 1 | use std::fs::File; 2 | use std::io::Write; 3 | 4 | use clap::*; 5 | use log::{error, Level}; 6 | 7 | use memflow::connector::*; 8 | 9 | use memflow_win32::prelude::{Kernel, Win32OffsetFile}; 10 | 11 | pub fn main() { 12 | let matches = App::new("dump offsets example") 13 | .version(crate_version!()) 14 | .author(crate_authors!()) 15 | .arg(Arg::with_name("verbose").short("v").multiple(true)) 16 | .arg( 17 | Arg::with_name("connector") 18 | .long("connector") 19 | .short("c") 20 | .takes_value(true) 21 | .required(true), 22 | ) 23 | .arg( 24 | Arg::with_name("args") 25 | .long("args") 26 | .short("a") 27 | .takes_value(true) 28 | .default_value(""), 29 | ) 30 | .arg( 31 | Arg::with_name("output") 32 | .long("output") 33 | .short("o") 34 | .takes_value(true), 35 | ) 36 | .get_matches(); 37 | 38 | // set log level 39 | let level = match matches.occurrences_of("verbose") { 40 | 0 => Level::Error, 41 | 1 => Level::Warn, 42 | 2 => Level::Info, 43 | 3 => Level::Debug, 44 | 4 => Level::Trace, 45 | _ => Level::Trace, 46 | }; 47 | simple_logger::SimpleLogger::new() 48 | .with_level(level.to_level_filter()) 49 | .init() 50 | .unwrap(); 51 | 52 | // create inventory + connector 53 | let inventory = unsafe { ConnectorInventory::scan() }; 54 | let connector = unsafe { 55 | inventory.create_connector( 56 | matches.value_of("connector").unwrap(), 57 | &ConnectorArgs::parse(matches.value_of("args").unwrap()).unwrap(), 58 | ) 59 | } 60 | .unwrap(); 61 | 62 | let kernel = Kernel::builder(connector) 63 | .build_default_caches() 64 | .build() 65 | .unwrap(); 66 | 67 | let winver = kernel.kernel_info.kernel_winver; 68 | 69 | if winver != (0, 0).into() { 70 | let offsets = if let Some(guid) = &kernel.kernel_info.kernel_guid { 71 | Win32OffsetFile { 72 | pdb_file_name: guid.file_name.as_str().into(), 73 | pdb_guid: guid.guid.as_str().into(), 74 | 75 | arch: kernel.kernel_info.start_block.arch.into(), 76 | 77 | nt_major_version: winver.major_version(), 78 | nt_minor_version: winver.minor_version(), 79 | nt_build_number: winver.build_number(), 80 | 81 | offsets: kernel.offsets.into(), 82 | } 83 | } else { 84 | Win32OffsetFile { 85 | pdb_file_name: Default::default(), 86 | pdb_guid: Default::default(), 87 | 88 | arch: kernel.kernel_info.start_block.arch.into(), 89 | 90 | nt_major_version: winver.major_version(), 91 | nt_minor_version: winver.minor_version(), 92 | nt_build_number: winver.build_number(), 93 | 94 | offsets: kernel.offsets.into(), 95 | } 96 | }; 97 | 98 | // write offsets to file 99 | let offsetstr = toml::to_string_pretty(&offsets).unwrap(); 100 | match matches.value_of("output") { 101 | Some(output) => { 102 | let mut file = File::create(output).unwrap(); 103 | file.write_all(offsetstr.as_bytes()).unwrap(); 104 | } 105 | None => println!("{}", offsetstr), 106 | } 107 | } else { 108 | error!("kernel version has to be valid in order to generate a offsets file"); 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-win32/examples/generate_offsets.rs: -------------------------------------------------------------------------------- 1 | use clap::*; 2 | use log::{error, Level}; 3 | use std::fs::{create_dir_all, File}; 4 | use std::io::Write; 5 | use std::path::PathBuf; 6 | 7 | use memflow_win32::prelude::{ 8 | SymbolStore, Win32GUID, Win32OffsetFile, Win32Offsets, Win32OffsetsArchitecture, Win32Version, 9 | }; 10 | 11 | pub fn main() { 12 | let matches = App::new("generate offsets example") 13 | .version(crate_version!()) 14 | .author(crate_authors!()) 15 | .arg(Arg::with_name("verbose").short("v").multiple(true)) 16 | .arg( 17 | Arg::with_name("output") 18 | .long("output") 19 | .short("o") 20 | .takes_value(true) 21 | .required(true), 22 | ) 23 | .get_matches(); 24 | 25 | // set log level 26 | let level = match matches.occurrences_of("verbose") { 27 | 0 => Level::Error, 28 | 1 => Level::Warn, 29 | 2 => Level::Info, 30 | 3 => Level::Debug, 31 | 4 => Level::Trace, 32 | _ => Level::Trace, 33 | }; 34 | simple_logger::SimpleLogger::new() 35 | .with_level(level.to_level_filter()) 36 | .init() 37 | .unwrap(); 38 | 39 | let win_ids = vec![ 40 | /* 41 | ( 42 | Win32Version::new(5, 2, 3790), 43 | Win32GUID::new("ntkrnlmp.pdb", "82DCF67A38274C9CA99B60B421D2786D2"), 44 | ), 45 | */ 46 | ( 47 | Win32Version::new(6, 1, 7601), 48 | Win32OffsetsArchitecture::X86, 49 | Win32GUID::new("ntkrpamp.pdb", "684DA42A30CC450F81C535B4D18944B12"), 50 | ), 51 | ( 52 | Win32Version::new(6, 1, 7601), 53 | Win32OffsetsArchitecture::X64, 54 | Win32GUID::new("ntkrnlmp.pdb", "ECE191A20CFF4465AE46DF96C22638451"), 55 | ), 56 | ( 57 | Win32Version::new(10, 0, 18362), 58 | Win32OffsetsArchitecture::X64, 59 | Win32GUID::new("ntkrnlmp.pdb", "0AFB69F5FD264D54673570E37B38A3181"), 60 | ), 61 | ( 62 | Win32Version::new(10, 0, 19041), 63 | Win32OffsetsArchitecture::X64, 64 | Win32GUID::new("ntkrnlmp.pdb", "BBED7C2955FBE4522AAA23F4B8677AD91"), 65 | ), 66 | ( 67 | Win32Version::new(10, 0, 19041), 68 | Win32OffsetsArchitecture::X64, 69 | Win32GUID::new("ntkrnlmp.pdb", "1C9875F76C8F0FBF3EB9A9D7C1C274061"), 70 | ), 71 | ( 72 | Win32Version::new(10, 0, 19041), 73 | Win32OffsetsArchitecture::X86, 74 | Win32GUID::new("ntkrpamp.pdb", "1B1D6AA205E1C87DC63A314ACAA50B491"), 75 | ), 76 | ]; 77 | 78 | let out_dir = matches.value_of("output").unwrap(); 79 | create_dir_all(out_dir).unwrap(); 80 | 81 | for win_id in win_ids.into_iter() { 82 | if let Ok(offsets) = Win32Offsets::builder() 83 | .symbol_store(SymbolStore::new()) 84 | .guid(win_id.2.clone()) 85 | .build() 86 | { 87 | let offset_file = Win32OffsetFile { 88 | pdb_file_name: win_id.2.file_name.as_str().into(), 89 | pdb_guid: win_id.2.guid.as_str().into(), 90 | 91 | nt_major_version: win_id.0.major_version(), 92 | nt_minor_version: win_id.0.minor_version(), 93 | nt_build_number: win_id.0.build_number(), 94 | 95 | arch: win_id.1, 96 | 97 | offsets: offsets.0, 98 | }; 99 | 100 | let offsetstr = toml::to_string_pretty(&offset_file).unwrap(); 101 | 102 | let file_name = format!( 103 | "{}_{}_{}_{}_{}.toml", 104 | win_id.0.major_version(), 105 | win_id.0.minor_version(), 106 | win_id.0.build_number(), 107 | win_id.1.to_string(), 108 | win_id.2.guid, 109 | ); 110 | 111 | let mut file = 112 | File::create([out_dir, &file_name].iter().collect::().as_path()).unwrap(); 113 | file.write_all(offsetstr.as_bytes()).unwrap(); 114 | } else { 115 | error!( 116 | "unable to find offsets for {} {:?} {:?}", 117 | win_id.0, win_id.1, win_id.2 118 | ) 119 | } 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-win32/examples/multithreading.rs: -------------------------------------------------------------------------------- 1 | use std::thread; 2 | 3 | use clap::*; 4 | use log::{info, Level}; 5 | 6 | use memflow::connector::*; 7 | use memflow::mem::*; 8 | 9 | use memflow_win32::win32::Kernel; 10 | 11 | pub fn parallel_init(connector: T) { 12 | (0..8) 13 | .map(|_| connector.clone()) 14 | .into_iter() 15 | .map(|c| { 16 | thread::spawn(move || { 17 | Kernel::builder(c) 18 | .no_symbol_store() 19 | .build_default_caches() 20 | .build() 21 | .unwrap(); 22 | }) 23 | }) 24 | .for_each(|t| t.join().unwrap()); 25 | } 26 | 27 | pub fn parallel_kernels(connector: T) { 28 | let kernel = Kernel::builder(connector).build().unwrap(); 29 | 30 | (0..8) 31 | .map(|_| kernel.clone()) 32 | .into_iter() 33 | .map(|mut k| { 34 | thread::spawn(move || { 35 | let _eprocesses = k.eprocess_list().unwrap(); 36 | }) 37 | }) 38 | .for_each(|t| t.join().unwrap()); 39 | } 40 | 41 | pub fn parallel_kernels_cached(connector: T) { 42 | let kernel = Kernel::builder(connector) 43 | .build_default_caches() 44 | .build() 45 | .unwrap(); 46 | 47 | (0..8) 48 | .map(|_| kernel.clone()) 49 | .into_iter() 50 | .map(|mut k| { 51 | thread::spawn(move || { 52 | let eprocesses = k.eprocess_list().unwrap(); 53 | info!("eprocesses list fetched: {}", eprocesses.len()); 54 | }) 55 | }) 56 | .for_each(|t| t.join().unwrap()); 57 | } 58 | 59 | pub fn parallel_processes(connector: T) { 60 | let kernel = Kernel::builder(connector) 61 | .build_default_caches() 62 | .build() 63 | .unwrap(); 64 | 65 | let process = kernel.into_process("wininit.exe").unwrap(); 66 | 67 | (0..8) 68 | .map(|_| process.clone()) 69 | .into_iter() 70 | .map(|mut p| { 71 | thread::spawn(move || { 72 | let module_list = p.module_list().unwrap(); 73 | info!("wininit.exe module_list: {}", module_list.len()); 74 | }) 75 | }) 76 | .for_each(|t| t.join().unwrap()); 77 | } 78 | 79 | pub fn main() { 80 | let matches = App::new("read_keys example") 81 | .version(crate_version!()) 82 | .author(crate_authors!()) 83 | .arg(Arg::with_name("verbose").short("v").multiple(true)) 84 | .arg( 85 | Arg::with_name("connector") 86 | .long("connector") 87 | .short("c") 88 | .takes_value(true) 89 | .required(true), 90 | ) 91 | .arg( 92 | Arg::with_name("args") 93 | .long("args") 94 | .short("a") 95 | .takes_value(true) 96 | .default_value(""), 97 | ) 98 | .get_matches(); 99 | 100 | // set log level 101 | let level = match matches.occurrences_of("verbose") { 102 | 0 => Level::Error, 103 | 1 => Level::Warn, 104 | 2 => Level::Info, 105 | 3 => Level::Debug, 106 | 4 => Level::Trace, 107 | _ => Level::Trace, 108 | }; 109 | simple_logger::SimpleLogger::new() 110 | .with_level(level.to_level_filter()) 111 | .init() 112 | .unwrap(); 113 | 114 | // create inventory + connector 115 | let inventory = unsafe { ConnectorInventory::scan() }; 116 | let connector = unsafe { 117 | inventory.create_connector( 118 | matches.value_of("connector").unwrap(), 119 | &ConnectorArgs::parse(matches.value_of("args").unwrap()).unwrap(), 120 | ) 121 | } 122 | .unwrap(); 123 | 124 | println!("test"); 125 | 126 | // parallel test functions 127 | // see each function's implementation for further details 128 | 129 | parallel_init(connector.clone()); 130 | 131 | parallel_kernels(connector.clone()); 132 | 133 | parallel_kernels_cached(connector.clone()); 134 | 135 | parallel_processes(connector); 136 | } 137 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-win32/examples/read_keys.rs: -------------------------------------------------------------------------------- 1 | use std::{thread, time}; 2 | 3 | use clap::*; 4 | use log::Level; 5 | 6 | use memflow::connector::*; 7 | 8 | use memflow_win32::win32::{Kernel, Keyboard}; 9 | 10 | pub fn main() { 11 | let matches = App::new("read_keys example") 12 | .version(crate_version!()) 13 | .author(crate_authors!()) 14 | .arg(Arg::with_name("verbose").short("v").multiple(true)) 15 | .arg( 16 | Arg::with_name("connector") 17 | .long("connector") 18 | .short("c") 19 | .takes_value(true) 20 | .required(true), 21 | ) 22 | .arg( 23 | Arg::with_name("args") 24 | .long("args") 25 | .short("a") 26 | .takes_value(true) 27 | .default_value(""), 28 | ) 29 | .get_matches(); 30 | 31 | // set log level 32 | let level = match matches.occurrences_of("verbose") { 33 | 0 => Level::Error, 34 | 1 => Level::Warn, 35 | 2 => Level::Info, 36 | 3 => Level::Debug, 37 | 4 => Level::Trace, 38 | _ => Level::Trace, 39 | }; 40 | simple_logger::SimpleLogger::new() 41 | .with_level(level.to_level_filter()) 42 | .init() 43 | .unwrap(); 44 | 45 | // create inventory + connector 46 | let inventory = unsafe { ConnectorInventory::scan() }; 47 | let connector = unsafe { 48 | inventory.create_connector( 49 | matches.value_of("connector").unwrap(), 50 | &ConnectorArgs::parse(matches.value_of("args").unwrap()).unwrap(), 51 | ) 52 | } 53 | .unwrap(); 54 | 55 | // creating the kernel object 56 | let mut kernel = Kernel::builder(connector) 57 | .build_default_caches() 58 | .build() 59 | .unwrap(); 60 | 61 | // fetch keyboard state 62 | let kbd = Keyboard::try_with(&mut kernel).unwrap(); 63 | 64 | loop { 65 | let kbs = kbd.state_with_kernel(&mut kernel).unwrap(); 66 | println!("space down: {:?}", kbs.is_down(win_key_codes::VK_SPACE)); 67 | thread::sleep(time::Duration::from_millis(1000)); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-win32/offsets/10_0_18362_X64_0AFB69F5FD264D54673570E37B38A3181.toml: -------------------------------------------------------------------------------- 1 | pdb_file_name = 'ntkrnlmp.pdb' 2 | pdb_guid = '0AFB69F5FD264D54673570E37B38A3181' 3 | nt_major_version = 10 4 | nt_minor_version = 0 5 | nt_build_number = 18362 6 | arch = 'X64' 7 | 8 | [offsets] 9 | list_blink = 8 10 | eproc_link = 752 11 | kproc_dtb = 40 12 | eproc_pid = 744 13 | eproc_name = 1104 14 | eproc_peb = 1016 15 | eproc_section_base = 968 16 | eproc_exit_status = 1620 17 | eproc_thread_list = 1160 18 | eproc_wow64 = 1064 19 | kthread_teb = 240 20 | ethread_list_entry = 1720 21 | teb_peb = 96 22 | teb_peb_x86 = 48 23 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-win32/offsets/10_0_19041_X64_1C9875F76C8F0FBF3EB9A9D7C1C274061.toml: -------------------------------------------------------------------------------- 1 | pdb_file_name = 'ntkrnlmp.pdb' 2 | pdb_guid = '1C9875F76C8F0FBF3EB9A9D7C1C274061' 3 | nt_major_version = 10 4 | nt_minor_version = 0 5 | nt_build_number = 19041 6 | arch = 'X64' 7 | 8 | [offsets] 9 | list_blink = 8 10 | eproc_link = 1096 11 | kproc_dtb = 40 12 | eproc_pid = 1088 13 | eproc_name = 1448 14 | eproc_peb = 1360 15 | eproc_section_base = 1312 16 | eproc_exit_status = 2004 17 | eproc_thread_list = 1504 18 | eproc_wow64 = 1408 19 | kthread_teb = 240 20 | ethread_list_entry = 1256 21 | teb_peb = 96 22 | teb_peb_x86 = 48 23 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-win32/offsets/10_0_19041_X64_BBED7C2955FBE4522AAA23F4B8677AD91.toml: -------------------------------------------------------------------------------- 1 | pdb_file_name = 'ntkrnlmp.pdb' 2 | pdb_guid = 'BBED7C2955FBE4522AAA23F4B8677AD91' 3 | nt_major_version = 10 4 | nt_minor_version = 0 5 | nt_build_number = 19041 6 | arch = 'X64' 7 | 8 | [offsets] 9 | list_blink = 8 10 | eproc_link = 1096 11 | kproc_dtb = 40 12 | eproc_pid = 1088 13 | eproc_name = 1448 14 | eproc_peb = 1360 15 | eproc_section_base = 1312 16 | eproc_exit_status = 2004 17 | eproc_thread_list = 1504 18 | eproc_wow64 = 1408 19 | kthread_teb = 240 20 | ethread_list_entry = 1256 21 | teb_peb = 96 22 | teb_peb_x86 = 48 23 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-win32/offsets/10_0_19041_X86_1B1D6AA205E1C87DC63A314ACAA50B491.toml: -------------------------------------------------------------------------------- 1 | pdb_file_name = 'ntkrpamp.pdb' 2 | pdb_guid = '1B1D6AA205E1C87DC63A314ACAA50B491' 3 | nt_major_version = 10 4 | nt_minor_version = 0 5 | nt_build_number = 19041 6 | arch = 'X86' 7 | 8 | [offsets] 9 | list_blink = 4 10 | eproc_link = 232 11 | kproc_dtb = 24 12 | eproc_pid = 228 13 | eproc_name = 428 14 | eproc_peb = 380 15 | eproc_section_base = 352 16 | eproc_exit_status = 844 17 | eproc_thread_list = 464 18 | eproc_wow64 = 0 19 | kthread_teb = 168 20 | ethread_list_entry = 740 21 | teb_peb = 48 22 | teb_peb_x86 = 48 23 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-win32/offsets/4_0_1381_X86.toml: -------------------------------------------------------------------------------- 1 | nt_major_version = 4 2 | nt_minor_version = 0 3 | nt_build_number = 1381 4 | arch = 'X86' 5 | 6 | [offsets] 7 | list_blink = 4 8 | eproc_link = 0x98 9 | 10 | kproc_dtb = 0x18 11 | eproc_pid = 0x94 12 | eproc_name = 0x1dc 13 | eproc_peb = 0x18c 14 | eproc_section_base = 0x190 15 | eproc_exit_status = 0 #5.1+ 16 | eproc_thread_list = 0 #5.1+ 17 | eproc_wow64 = 0 #5.0+ 18 | 19 | kthread_teb = 0 #6.2+ 20 | ethread_list_entry = 0x0 #5.0+ 21 | teb_peb = 0 #? 22 | teb_peb_x86 = 0 #? 23 | 24 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-win32/offsets/5_2_3790_X64_82DCF67A38274C9CA99B60B421D2786D2.toml: -------------------------------------------------------------------------------- 1 | pdb_guid = '82DCF67A38274C9CA99B60B421D2786D2' 2 | nt_major_version = 5 3 | nt_minor_version = 2 4 | nt_build_number = 3790 5 | arch = 'X64' 6 | 7 | [offsets] 8 | list_blink = 8 9 | eproc_link = 224 10 | kproc_dtb = 40 11 | eproc_pid = 216 12 | eproc_name = 616 13 | eproc_peb = 704 14 | eproc_section_base = 0x128 15 | eproc_exit_status = 0x024C 16 | eproc_thread_list = 656 17 | eproc_wow64 = 680 18 | kthread_teb = 176 19 | ethread_list_entry = 976 20 | teb_peb = 96 21 | teb_peb_x86 = 48 22 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-win32/offsets/6_1_7601_X64_ECE191A20CFF4465AE46DF96C22638451.toml: -------------------------------------------------------------------------------- 1 | pdb_file_name = 'ntkrnlmp.pdb' 2 | pdb_guid = 'ECE191A20CFF4465AE46DF96C22638451' 3 | nt_major_version = 6 4 | nt_minor_version = 1 5 | nt_build_number = 7601 6 | arch = 'X64' 7 | 8 | [offsets] 9 | list_blink = 8 10 | eproc_link = 392 11 | kproc_dtb = 40 12 | eproc_pid = 384 13 | eproc_name = 736 14 | eproc_peb = 824 15 | eproc_section_base = 624 16 | eproc_exit_status = 1092 17 | eproc_thread_list = 776 18 | eproc_wow64 = 800 19 | kthread_teb = 184 20 | ethread_list_entry = 1064 21 | teb_peb = 96 22 | teb_peb_x86 = 48 23 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-win32/offsets/6_1_7601_X86_684DA42A30CC450F81C535B4D18944B12.toml: -------------------------------------------------------------------------------- 1 | pdb_file_name = 'ntkrpamp.pdb' 2 | pdb_guid = '684DA42A30CC450F81C535B4D18944B12' 3 | nt_major_version = 6 4 | nt_minor_version = 1 5 | nt_build_number = 7601 6 | arch = 'X86' 7 | 8 | [offsets] 9 | list_blink = 4 10 | eproc_link = 184 11 | kproc_dtb = 24 12 | eproc_pid = 180 13 | eproc_name = 364 14 | eproc_peb = 424 15 | eproc_section_base = 300 16 | eproc_exit_status = 628 17 | eproc_thread_list = 392 18 | eproc_wow64 = 0 19 | kthread_teb = 136 20 | ethread_list_entry = 616 21 | teb_peb = 48 22 | teb_peb_x86 = 48 23 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-win32/src/error.rs: -------------------------------------------------------------------------------- 1 | use std::prelude::v1::*; 2 | 3 | use std::{convert, fmt, result, str}; 4 | 5 | #[cfg(feature = "std")] 6 | use std::error; 7 | 8 | // forward declare partial result extension from core for easier access 9 | pub use memflow::error::PartialResultExt; 10 | 11 | #[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)] 12 | pub enum Error { 13 | /// Generic error type containing a string 14 | Other(&'static str), 15 | /// Out of bounds. 16 | /// 17 | /// Catch-all for bounds check errors. 18 | Bounds, 19 | /// Invalid Architecture error. 20 | /// 21 | /// The architecture provided is not a valid argument for the given function. 22 | InvalidArchitecture, 23 | Initialization(&'static str), 24 | SymbolStore(&'static str), 25 | ProcessInfo, 26 | ModuleInfo, 27 | /// memflow core error. 28 | /// 29 | /// Catch-all for memflow core related errors. 30 | Core(memflow::error::Error), 31 | PDB(&'static str), 32 | /// PE error. 33 | /// 34 | /// Catch-all for pe related errors. 35 | PE(pelite::Error), 36 | /// Encoding error. 37 | /// 38 | /// Catch-all for string related errors such as lacking a nul terminator. 39 | Encoding, 40 | /// Unicode error when reading a string from windows. 41 | /// 42 | /// Encapsulates all unicode related reading errors. 43 | Unicode(&'static str), 44 | } 45 | 46 | /// Convert from &str to error 47 | impl convert::From<&'static str> for Error { 48 | fn from(error: &'static str) -> Self { 49 | Error::Other(error) 50 | } 51 | } 52 | 53 | /// Convert from flow_core::Error 54 | impl From for Error { 55 | fn from(error: memflow::error::Error) -> Error { 56 | Error::Core(error) 57 | } 58 | } 59 | 60 | /// Convert from flow_core::PartialError 61 | impl From> for Error { 62 | fn from(_error: memflow::error::PartialError) -> Error { 63 | Error::Core(memflow::error::Error::Partial) 64 | } 65 | } 66 | 67 | /// Convert from pelite::Error 68 | impl From for Error { 69 | fn from(error: pelite::Error) -> Error { 70 | Error::PE(error) 71 | } 72 | } 73 | 74 | /// Convert from str::Utf8Error 75 | impl From for Error { 76 | fn from(_err: str::Utf8Error) -> Error { 77 | Error::Encoding 78 | } 79 | } 80 | 81 | impl Error { 82 | /// Returns a tuple representing the error description and its string value. 83 | pub fn to_str_pair(self) -> (&'static str, Option<&'static str>) { 84 | match self { 85 | Error::Other(e) => ("other error", Some(e)), 86 | Error::Bounds => ("out of bounds", None), 87 | Error::InvalidArchitecture => ("invalid architecture", None), 88 | Error::Initialization(e) => ("error during initialization", Some(e)), 89 | Error::SymbolStore(e) => ("error in symbol store", Some(e)), 90 | Error::ProcessInfo => ("error retrieving process info", None), 91 | Error::ModuleInfo => ("error retrieving module info", None), 92 | Error::Core(e) => e.to_str_pair(), 93 | Error::PDB(e) => ("error handling pdb", Some(e)), 94 | Error::PE(e) => ("error handling pe", Some(e.to_str())), 95 | Error::Encoding => ("encoding error", None), 96 | Error::Unicode(e) => ("error reading unicode string", Some(e)), 97 | } 98 | } 99 | 100 | /// Returns a simple string representation of the error. 101 | pub fn to_str(self) -> &'static str { 102 | self.to_str_pair().0 103 | } 104 | } 105 | 106 | impl fmt::Display for Error { 107 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 108 | let (desc, value) = self.to_str_pair(); 109 | 110 | if let Some(value) = value { 111 | write!(f, "{}: {}", desc, value) 112 | } else { 113 | f.write_str(desc) 114 | } 115 | } 116 | } 117 | 118 | #[cfg(feature = "std")] 119 | impl error::Error for Error { 120 | fn description(&self) -> &str { 121 | self.to_str() 122 | } 123 | } 124 | 125 | /// Specialized `Result` type for memflow_win32 errors. 126 | pub type Result = result::Result; 127 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-win32/src/kernel/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod ntos; 2 | pub mod start_block; 3 | pub mod sysproc; 4 | 5 | use std::prelude::v1::*; 6 | 7 | pub use start_block::StartBlock; 8 | 9 | use std::cmp::{Ord, Ordering, PartialEq}; 10 | use std::fmt; 11 | 12 | #[derive(Debug, Clone)] 13 | #[cfg_attr(feature = "serde", derive(::serde::Serialize))] 14 | pub struct Win32GUID { 15 | pub file_name: String, 16 | pub guid: String, 17 | } 18 | 19 | impl Win32GUID { 20 | pub fn new(file_name: &str, guid: &str) -> Self { 21 | Self { 22 | file_name: file_name.to_string(), 23 | guid: guid.to_string(), 24 | } 25 | } 26 | } 27 | 28 | #[derive(Debug, Clone, Copy, Default)] 29 | #[cfg_attr(feature = "serde", derive(::serde::Serialize))] 30 | #[repr(C)] 31 | pub struct Win32Version { 32 | nt_major_version: u32, 33 | nt_minor_version: u32, 34 | nt_build_number: u32, 35 | } 36 | 37 | impl Win32Version { 38 | pub fn new(nt_major_version: u32, nt_minor_version: u32, nt_build_number: u32) -> Self { 39 | Self { 40 | nt_major_version, 41 | nt_minor_version, 42 | nt_build_number, 43 | } 44 | } 45 | 46 | pub fn mask_build_number(mut self) -> Self { 47 | self.nt_build_number &= 0xFFFF; 48 | self 49 | } 50 | 51 | pub fn major_version(&self) -> u32 { 52 | self.nt_major_version 53 | } 54 | 55 | pub fn minor_version(&self) -> u32 { 56 | self.nt_minor_version 57 | } 58 | 59 | pub fn build_number(&self) -> u32 { 60 | self.nt_build_number & 0xFFFF 61 | } 62 | 63 | pub fn is_checked_build(&self) -> bool { 64 | (self.nt_build_number & 0xF0000000) == 0xC0000000 65 | } 66 | 67 | pub fn as_tuple(&self) -> (u32, u32, u32) { 68 | ( 69 | self.major_version(), 70 | self.minor_version(), 71 | self.build_number(), 72 | ) 73 | } 74 | } 75 | 76 | impl PartialOrd for Win32Version { 77 | fn partial_cmp(&self, other: &Win32Version) -> Option { 78 | Some(self.cmp(other)) 79 | } 80 | } 81 | 82 | impl Ord for Win32Version { 83 | fn cmp(&self, other: &Win32Version) -> Ordering { 84 | if self.nt_build_number != 0 && other.nt_build_number != 0 { 85 | return self.nt_build_number.cmp(&other.nt_build_number); 86 | } 87 | 88 | if self.nt_major_version != other.nt_major_version { 89 | self.nt_major_version.cmp(&other.nt_major_version) 90 | } else if self.nt_minor_version != other.nt_minor_version { 91 | self.nt_minor_version.cmp(&other.nt_minor_version) 92 | } else { 93 | Ordering::Equal 94 | } 95 | } 96 | } 97 | 98 | impl PartialEq for Win32Version { 99 | fn eq(&self, other: &Win32Version) -> bool { 100 | if self.nt_build_number != 0 && other.nt_build_number != 0 { 101 | self.nt_build_number.eq(&other.nt_build_number) 102 | } else { 103 | self.nt_major_version == other.nt_major_version 104 | && self.nt_minor_version == other.nt_minor_version 105 | } 106 | } 107 | } 108 | 109 | impl Eq for Win32Version {} 110 | 111 | impl From<(u32, u32)> for Win32Version { 112 | fn from((nt_major_version, nt_minor_version): (u32, u32)) -> Win32Version { 113 | Win32Version { 114 | nt_major_version, 115 | nt_minor_version, 116 | nt_build_number: 0, 117 | } 118 | } 119 | } 120 | 121 | impl From<(u32, u32, u32)> for Win32Version { 122 | fn from( 123 | (nt_major_version, nt_minor_version, nt_build_number): (u32, u32, u32), 124 | ) -> Win32Version { 125 | Win32Version { 126 | nt_major_version, 127 | nt_minor_version, 128 | nt_build_number, 129 | } 130 | } 131 | } 132 | 133 | impl fmt::Display for Win32Version { 134 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 135 | if self.nt_major_version != 0 { 136 | write!( 137 | f, 138 | "{}.{}.{}", 139 | self.major_version(), 140 | self.minor_version(), 141 | self.build_number() 142 | ) 143 | } else { 144 | write!(f, "{}", self.build_number()) 145 | } 146 | } 147 | } 148 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-win32/src/kernel/ntos/pehelper.rs: -------------------------------------------------------------------------------- 1 | use std::prelude::v1::*; 2 | 3 | use crate::error::{Error, Result}; 4 | 5 | use log::{debug, info}; 6 | 7 | use memflow::error::PartialResultExt; 8 | use memflow::mem::VirtualMemory; 9 | use memflow::types::{size, Address}; 10 | 11 | use pelite::{self, PeView}; 12 | 13 | pub fn try_get_pe_size(virt_mem: &mut T, probe_addr: Address) -> Result { 14 | let mut probe_buf = vec![0; size::kb(4)]; 15 | virt_mem.virt_read_raw_into(probe_addr, &mut probe_buf)?; 16 | 17 | let pe_probe = PeView::from_bytes(&probe_buf).map_err(Error::PE)?; 18 | 19 | let opt_header = pe_probe.optional_header(); 20 | let size_of_image = match opt_header { 21 | pelite::Wrap::T32(opt32) => opt32.SizeOfImage, 22 | pelite::Wrap::T64(opt64) => opt64.SizeOfImage, 23 | }; 24 | if size_of_image > 0 { 25 | debug!( 26 | "found pe header for image with a size of {} bytes.", 27 | size_of_image 28 | ); 29 | Ok(size_of_image as usize) 30 | } else { 31 | Err(Error::Initialization("pe size_of_image is zero")) 32 | } 33 | } 34 | 35 | pub fn try_get_pe_image( 36 | virt_mem: &mut T, 37 | probe_addr: Address, 38 | ) -> Result> { 39 | let size_of_image = try_get_pe_size(virt_mem, probe_addr)?; 40 | virt_mem 41 | .virt_read_raw(probe_addr, size_of_image) 42 | .data_part() 43 | .map_err(Error::Core) 44 | } 45 | 46 | pub fn try_get_pe_name(virt_mem: &mut T, probe_addr: Address) -> Result { 47 | let image = try_get_pe_image(virt_mem, probe_addr)?; 48 | let pe = PeView::from_bytes(&image).map_err(Error::PE)?; 49 | let name = pe 50 | .exports() 51 | .map_err(|_| Error::Initialization("unable to get exports"))? 52 | .dll_name() 53 | .map_err(|_| Error::Initialization("unable to get dll name"))? 54 | .to_str()?; 55 | info!("try_get_pe_name: found pe header for {}", name); 56 | Ok(name.to_string()) 57 | } 58 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-win32/src/kernel/ntos/x64.rs: -------------------------------------------------------------------------------- 1 | use std::prelude::v1::*; 2 | 3 | use super::pehelper; 4 | use crate::error::{Error, Result}; 5 | use crate::kernel::StartBlock; 6 | 7 | use log::{debug, trace}; 8 | 9 | use memflow::architecture::x86::x64; 10 | use memflow::error::PartialResultExt; 11 | use memflow::iter::PageChunks; 12 | use memflow::mem::VirtualMemory; 13 | use memflow::types::{size, Address}; 14 | 15 | use dataview::Pod; 16 | use pelite::image::IMAGE_DOS_HEADER; 17 | 18 | pub fn find_with_va_hint( 19 | virt_mem: &mut T, 20 | start_block: &StartBlock, 21 | ) -> Result<(Address, usize)> { 22 | debug!( 23 | "x64::find_with_va_hint: trying to find ntoskrnl.exe with va hint at {:x}", 24 | start_block.kernel_hint.as_u64() 25 | ); 26 | 27 | // va was found previously 28 | let mut va_base = start_block.kernel_hint.as_u64() & !0x0001_ffff; 29 | while va_base + size::mb(16) as u64 > start_block.kernel_hint.as_u64() { 30 | trace!("x64::find_with_va_hint: probing at {:x}", va_base); 31 | 32 | match find_with_va(virt_mem, va_base) { 33 | Ok(a) => { 34 | let addr = Address::from(a); 35 | let size_of_image = pehelper::try_get_pe_size(virt_mem, addr)?; 36 | return Ok((addr, size_of_image)); 37 | } 38 | Err(e) => trace!("x64::find_with_va_hint: probe error {:?}", e), 39 | } 40 | 41 | va_base -= size::mb(2) as u64; 42 | } 43 | 44 | Err(Error::Initialization( 45 | "x64::find_with_va_hint: unable to locate ntoskrnl.exe via va hint", 46 | )) 47 | } 48 | 49 | fn find_with_va(virt_mem: &mut T, va_base: u64) -> Result { 50 | let mut buf = vec![0; size::mb(2)]; 51 | virt_mem 52 | .virt_read_raw_into(Address::from(va_base), &mut buf) 53 | .data_part()?; 54 | 55 | buf.chunks_exact(x64::ARCH.page_size()) 56 | .enumerate() 57 | .map(|(i, c)| { 58 | let view = Pod::as_data_view(&c[..]); 59 | (i, c, view.copy::(0)) // TODO: potential endian mismatch 60 | }) 61 | .filter(|(_, _, p)| p.e_magic == 0x5a4d) // MZ 62 | .filter(|(_, _, p)| p.e_lfanew <= 0x800) 63 | .inspect(|(i, _, _)| { 64 | trace!( 65 | "x64::find_with_va: found potential header flags at offset {:x}", 66 | i * x64::ARCH.page_size() 67 | ) 68 | }) 69 | .find(|(i, _, _)| { 70 | let probe_addr = Address::from(va_base + (*i as u64) * x64::ARCH.page_size() as u64); 71 | let name = pehelper::try_get_pe_name(virt_mem, probe_addr).unwrap_or_default(); 72 | name == "ntoskrnl.exe" 73 | }) 74 | .map(|(i, _, _)| va_base + i as u64 * x64::ARCH.page_size() as u64) 75 | .ok_or_else(|| Error::Initialization("unable to locate ntoskrnl.exe")) 76 | } 77 | 78 | pub fn find( 79 | virt_mem: &mut T, 80 | start_block: &StartBlock, 81 | ) -> Result<(Address, usize)> { 82 | debug!("x64::find: trying to find ntoskrnl.exe with page map",); 83 | 84 | let page_map = virt_mem.virt_page_map_range( 85 | size::mb(2), 86 | (!0u64 - (1u64 << (start_block.arch.address_space_bits() - 1))).into(), 87 | (!0u64).into(), 88 | ); 89 | 90 | match page_map 91 | .into_iter() 92 | .flat_map(|(va, size)| size.page_chunks(va, size::mb(2))) 93 | .filter(|&(_, size)| size == size::mb(2)) 94 | .filter_map(|(va, _)| find_with_va(virt_mem, va.as_u64()).ok()) 95 | .next() 96 | { 97 | Some(a) => { 98 | let addr = Address::from(a); 99 | let size_of_image = pehelper::try_get_pe_size(virt_mem, addr)?; 100 | Ok((addr, size_of_image)) 101 | } 102 | None => Err(Error::Initialization( 103 | "x64::find: unable to locate ntoskrnl.exe with a page map", 104 | )), 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-win32/src/kernel/ntos/x86.rs: -------------------------------------------------------------------------------- 1 | use std::prelude::v1::*; 2 | 3 | use super::pehelper; 4 | use crate::error::{Error, Result}; 5 | use crate::kernel::StartBlock; 6 | 7 | use log::{debug, info}; 8 | 9 | use memflow::error::PartialResultExt; 10 | use memflow::mem::VirtualMemory; 11 | use memflow::types::{size, Address}; 12 | 13 | use dataview::Pod; 14 | use pelite::image::IMAGE_DOS_HEADER; 15 | 16 | const SIZE_256MB: usize = size::mb(256); 17 | const SIZE_8MB: usize = size::mb(8); 18 | const SIZE_4KB: usize = size::kb(4); 19 | 20 | // https://github.com/ufrisk/MemProcFS/blob/f2d15cf4fe4f19cfeea3dad52971fae2e491064b/vmm/vmmwininit.c#L410 21 | pub fn find( 22 | virt_mem: &mut T, 23 | _start_block: &StartBlock, 24 | ) -> Result<(Address, usize)> { 25 | debug!("x86::find: trying to find ntoskrnl.exe"); 26 | 27 | for base_addr in (0..SIZE_256MB as u64).step_by(SIZE_8MB) { 28 | let base_addr = size::gb(2) as u64 + base_addr; 29 | // search in each page in the first 8mb chunks in the first 64mb of virtual memory 30 | let mut buf = vec![0; SIZE_8MB]; 31 | virt_mem 32 | .virt_read_raw_into(base_addr.into(), &mut buf) 33 | .data_part()?; 34 | 35 | for addr in (0..SIZE_8MB as u64).step_by(SIZE_4KB) { 36 | // TODO: potential endian mismatch in pod 37 | let view = Pod::as_data_view(&buf[addr as usize..]); 38 | 39 | // check for dos header signature (MZ) // TODO: create global 40 | if view.read::(0).e_magic != 0x5a4d { 41 | continue; 42 | } 43 | 44 | if view.read::(0).e_lfanew > 0x800 { 45 | continue; 46 | } 47 | 48 | let image_base = Address::from(base_addr + addr); 49 | if let Ok(name) = pehelper::try_get_pe_name(virt_mem, image_base) { 50 | if name == "ntoskrnl.exe" { 51 | info!("ntoskrnl found"); 52 | // TODO: unify pe name + size 53 | if let Ok(size_of_image) = pehelper::try_get_pe_size(virt_mem, image_base) { 54 | return Ok((image_base, size_of_image)); 55 | } 56 | } 57 | } 58 | } 59 | } 60 | 61 | Err(Error::Initialization( 62 | "find_x86(): unable to locate ntoskrnl.exe in high mem", 63 | )) 64 | } 65 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-win32/src/kernel/start_block.rs: -------------------------------------------------------------------------------- 1 | mod x64; 2 | mod x86; 3 | mod x86pae; 4 | 5 | use std::prelude::v1::*; 6 | 7 | use crate::error::{Error, Result}; 8 | 9 | use log::warn; 10 | 11 | use memflow::architecture; 12 | use memflow::architecture::ArchitectureObj; 13 | use memflow::mem::PhysicalMemory; 14 | use memflow::types::{size, Address, PhysicalAddress}; 15 | 16 | // PROCESSOR_START_BLOCK 17 | #[derive(Debug, Copy, Clone)] 18 | #[cfg_attr(feature = "serde", derive(::serde::Serialize))] 19 | pub struct StartBlock { 20 | pub arch: ArchitectureObj, 21 | pub kernel_hint: Address, 22 | pub dtb: Address, 23 | } 24 | 25 | pub fn find_fallback(mem: &mut T, arch: ArchitectureObj) -> Result { 26 | if arch == architecture::x86::x64::ARCH { 27 | // read low 16mb stub 28 | let mut low16m = vec![0; size::mb(16)]; 29 | mem.phys_read_raw_into(PhysicalAddress::NULL, &mut low16m)?; 30 | 31 | x64::find(&low16m) 32 | } else { 33 | Err(Error::Initialization( 34 | "start_block: fallback not implemented for given arch", 35 | )) 36 | } 37 | } 38 | 39 | // bcdedit /set firstmegabytepolicyuseall 40 | pub fn find(mem: &mut T, arch: Option) -> Result { 41 | if let Some(arch) = arch { 42 | if arch == architecture::x86::x64::ARCH { 43 | // read low 1mb stub 44 | let mut low1m = vec![0; size::mb(1)]; 45 | mem.phys_read_raw_into(PhysicalAddress::NULL, &mut low1m)?; 46 | 47 | // find x64 dtb in low stub < 1M 48 | match x64::find_lowstub(&low1m) { 49 | Ok(d) => { 50 | if d.dtb.as_u64() != 0 { 51 | return Ok(d); 52 | } 53 | } 54 | Err(e) => warn!("x64::find_lowstub() error: {}", e), 55 | } 56 | 57 | find_fallback(mem, arch) 58 | } else if arch == architecture::x86::x32_pae::ARCH { 59 | let mut low16m = vec![0; size::mb(16)]; 60 | mem.phys_read_raw_into(PhysicalAddress::NULL, &mut low16m)?; 61 | x86pae::find(&low16m) 62 | } else if arch == architecture::x86::x32::ARCH { 63 | let mut low16m = vec![0; size::mb(16)]; 64 | mem.phys_read_raw_into(PhysicalAddress::NULL, &mut low16m)?; 65 | x86::find(&low16m) 66 | } else { 67 | Err(Error::InvalidArchitecture) 68 | } 69 | } else { 70 | find(mem, Some(architecture::x86::x64::ARCH)) 71 | .or_else(|_| find(mem, Some(architecture::x86::x32_pae::ARCH))) 72 | .or_else(|_| find(mem, Some(architecture::x86::x32::ARCH))) 73 | .map_err(|_| Error::Initialization("unable to find dtb")) 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-win32/src/kernel/start_block/x64.rs: -------------------------------------------------------------------------------- 1 | use crate::error::{Error, Result}; 2 | use crate::kernel::StartBlock; 3 | 4 | use std::convert::TryInto; 5 | 6 | use memflow::architecture::x86::x64; 7 | use memflow::types::{size, Address}; 8 | 9 | // https://github.com/ufrisk/MemProcFS/blob/f2d15cf4fe4f19cfeea3dad52971fae2e491064b/vmm/vmmwininit.c#L560 10 | pub fn find_lowstub(stub: &[u8]) -> Result { 11 | Ok(stub 12 | .chunks_exact(x64::ARCH.page_size()) 13 | .skip(1) 14 | .filter(|c| { 15 | (0xffff_ffff_ffff_00ff & u64::from_le_bytes(c[0..8].try_into().unwrap())) 16 | == 0x0000_0001_0006_00E9 17 | }) // start bytes 18 | .filter(|c| { 19 | (0xffff_f800_0000_0003 & u64::from_le_bytes(c[0x70..0x70 + 8].try_into().unwrap())) 20 | == 0xffff_f800_0000_0000 21 | }) // kernel entry 22 | .find(|c| { 23 | (0xffff_ff00_0000_0fff & u64::from_le_bytes(c[0xa0..0xa0 + 8].try_into().unwrap())) == 0 24 | }) // pml4 25 | .map(|c| StartBlock { 26 | arch: x64::ARCH, 27 | kernel_hint: u64::from_le_bytes(c[0x70..0x70 + 8].try_into().unwrap()).into(), 28 | dtb: u64::from_le_bytes(c[0xa0..0xa0 + 8].try_into().unwrap()).into(), 29 | }) 30 | .ok_or_else(|| Error::Initialization("unable to find x64 dtb in lowstub < 1M"))?) 31 | } 32 | 33 | fn find_pt(addr: Address, mem: &[u8]) -> Option
{ 34 | // TODO: global define / config setting 35 | let max_mem = size::gb(512) as u64; 36 | 37 | let pte = u64::from_le_bytes(mem[0..8].try_into().unwrap()); 38 | 39 | if (pte & 0x0000_0000_0000_0087) != 0x7 || (pte & 0x0000_ffff_ffff_f000) > max_mem { 40 | return None; 41 | } 42 | 43 | // Second half must have a self ref entry 44 | // This is usually enough to filter wrong data out 45 | mem[0x800..] 46 | .chunks(8) 47 | .map(|c| u64::from_le_bytes(c.try_into().unwrap())) 48 | .find(|a| (a ^ 0x0000_0000_0000_0063) & !(1u64 << 63) == addr.as_u64())?; 49 | 50 | // A page table does need to have some entries, right? Particularly, kernel-side page table 51 | // entries must be marked as such 52 | mem[0x800..] 53 | .chunks(8) 54 | .map(|c| u64::from_le_bytes(c.try_into().unwrap())) 55 | .filter(|a| (a & 0xff) == 0x63) 56 | .nth(5)?; 57 | 58 | Some(addr) 59 | } 60 | 61 | pub fn find(mem: &[u8]) -> Result { 62 | mem.chunks_exact(x64::ARCH.page_size()) 63 | .enumerate() 64 | .filter_map(|(i, c)| find_pt((i * x64::ARCH.page_size()).into(), c)) 65 | .map(|addr| StartBlock { 66 | arch: x64::ARCH, 67 | kernel_hint: 0.into(), 68 | dtb: addr, 69 | }) 70 | .next() 71 | .ok_or_else(|| Error::Initialization("unable to find x64 dtb in lowstub < 16M")) 72 | } 73 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-win32/src/kernel/start_block/x86.rs: -------------------------------------------------------------------------------- 1 | use crate::error::{Error, Result}; 2 | use crate::kernel::StartBlock; 3 | 4 | use std::convert::TryInto; 5 | 6 | use memflow::architecture::x86::x32; 7 | use memflow::iter::PageChunks; 8 | use memflow::types::Address; 9 | 10 | fn check_page(base: Address, mem: &[u8]) -> bool { 11 | if mem[0] != 0x67 { 12 | return false; 13 | } 14 | 15 | let dword = u32::from_le_bytes(mem[0xc00..0xc00 + 4].try_into().unwrap()); 16 | if (dword & 0xffff_f003) != (base.as_u32() + 0x3) { 17 | return false; 18 | } 19 | 20 | matches!(mem 21 | .iter() 22 | .step_by(4) 23 | .skip(0x200) 24 | .filter(|&&x| x == 0x63 || x == 0xe3) 25 | .count(), x if x > 16) 26 | } 27 | 28 | pub fn find(mem: &[u8]) -> Result { 29 | mem.page_chunks(Address::from(0), x32::ARCH.page_size()) 30 | .find(|(a, c)| check_page(*a, c)) 31 | .map(|(a, _)| StartBlock { 32 | arch: x32::ARCH, 33 | kernel_hint: 0.into(), 34 | dtb: a, 35 | }) 36 | .ok_or_else(|| Error::Initialization("unable to find x86 dtb in lowstub < 16M")) 37 | } 38 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-win32/src/kernel/start_block/x86pae.rs: -------------------------------------------------------------------------------- 1 | use crate::error::{Error, Result}; 2 | use crate::kernel::StartBlock; 3 | 4 | use std::convert::TryInto; 5 | 6 | use memflow::architecture::x86::x32_pae; 7 | use memflow::iter::PageChunks; 8 | use memflow::types::Address; 9 | 10 | fn check_page(addr: Address, mem: &[u8]) -> bool { 11 | for (i, chunk) in mem.to_vec().chunks_exact(8).enumerate() { 12 | let qword = u64::from_le_bytes(chunk[0..8].try_into().unwrap()); 13 | if (i < 4 && qword != addr.as_u64() + ((i as u64 * 8) << 9) + 0x1001) 14 | || (i >= 4 && qword != 0) 15 | { 16 | return false; 17 | } 18 | } 19 | true 20 | } 21 | 22 | pub fn find(mem: &[u8]) -> Result { 23 | mem.page_chunks(Address::from(0), x32_pae::ARCH.page_size()) 24 | .find(|(a, c)| check_page(*a, c)) 25 | .map(|(a, _)| StartBlock { 26 | arch: x32_pae::ARCH, 27 | kernel_hint: 0.into(), 28 | dtb: a, 29 | }) 30 | .ok_or_else(|| Error::Initialization("unable to find x86_pae dtb in lowstub < 16M")) 31 | } 32 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-win32/src/kernel/sysproc.rs: -------------------------------------------------------------------------------- 1 | use std::prelude::v1::*; 2 | 3 | use super::ntos::pehelper; 4 | use super::StartBlock; 5 | use crate::error::{Error, Result}; 6 | 7 | use std::convert::TryInto; 8 | 9 | use log::{debug, info, warn}; 10 | 11 | use memflow::mem::VirtualMemory; 12 | use memflow::types::{size, Address}; 13 | 14 | use pelite::{self, pe64::exports::Export, PeView}; 15 | 16 | pub fn find( 17 | virt_mem: &mut T, 18 | start_block: &StartBlock, 19 | ntos: Address, 20 | ) -> Result
{ 21 | debug!("trying to find system eprocess"); 22 | 23 | match find_exported(virt_mem, start_block, ntos) { 24 | Ok(e) => return Ok(e), 25 | Err(e) => warn!("{}", e), 26 | } 27 | 28 | match find_in_section(virt_mem, start_block, ntos) { 29 | Ok(e) => return Ok(e), 30 | Err(e) => warn!("{}", e), 31 | } 32 | 33 | Err(Error::Initialization("unable to find system eprocess")) 34 | } 35 | 36 | // find from exported symbol 37 | pub fn find_exported( 38 | virt_mem: &mut T, 39 | start_block: &StartBlock, 40 | kernel_base: Address, 41 | ) -> Result
{ 42 | // PsInitialSystemProcess -> PsActiveProcessHead 43 | let image = pehelper::try_get_pe_image(virt_mem, kernel_base)?; 44 | let pe = PeView::from_bytes(&image).map_err(Error::PE)?; 45 | 46 | let sys_proc = match pe 47 | .get_export_by_name("PsInitialSystemProcess") 48 | .map_err(Error::PE)? 49 | { 50 | Export::Symbol(s) => kernel_base + *s as usize, 51 | Export::Forward(_) => { 52 | return Err(Error::Other( 53 | "PsInitialSystemProcess found but it was a forwarded export", 54 | )) 55 | } 56 | }; 57 | info!("PsInitialSystemProcess found at 0x{:x}", sys_proc); 58 | 59 | // read containing value 60 | let mut buf = vec![0u8; start_block.arch.size_addr()]; 61 | let sys_proc_addr: Address = match start_block.arch.bits() { 62 | 64 => { 63 | // TODO: replace by virt_read_into with ByteSwap 64 | virt_mem.virt_read_raw_into(sys_proc, &mut buf)?; 65 | u64::from_le_bytes(buf[0..8].try_into().unwrap()).into() 66 | } 67 | 32 => { 68 | // TODO: replace by virt_read_into with ByteSwap 69 | virt_mem.virt_read_raw_into(sys_proc, &mut buf)?; 70 | u32::from_le_bytes(buf[0..4].try_into().unwrap()).into() 71 | } 72 | _ => return Err(Error::InvalidArchitecture), 73 | }; 74 | Ok(sys_proc_addr) 75 | } 76 | 77 | // scan in pdb 78 | 79 | // scan in section 80 | pub fn find_in_section( 81 | virt_mem: &mut T, 82 | _start_block: &StartBlock, 83 | ntos: Address, 84 | ) -> Result
{ 85 | // find section ALMOSTRO 86 | // scan for va of system process (dtb.va) 87 | // ... check if its 32 or 64bit 88 | 89 | let mut header_buf = vec![0; size::mb(32)]; 90 | virt_mem.virt_read_raw_into(ntos, &mut header_buf)?; 91 | 92 | /* 93 | let mut pe_opts = ParseOptions::default(); 94 | pe_opts.resolve_rva = false; 95 | 96 | let header = PE::parse_with_opts(&header_buf, &pe_opts).unwrap(); // TODO: error 97 | let _sect = header 98 | .sections 99 | .iter() 100 | .filter(|s| String::from_utf8(s.name.to_vec()).unwrap_or_default() == "ALMOSTRO") 101 | .nth(0) 102 | .ok_or_else(|| Error::new("unable to find section ALMOSTRO"))?; 103 | */ 104 | 105 | Err(Error::Other( 106 | "sysproc::find_in_section(): not implemented yet", 107 | )) 108 | } 109 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-win32/src/lib.rs: -------------------------------------------------------------------------------- 1 | /*! 2 | This crate contains memflow's win32 implementation. 3 | It is used to interface with windows targets. 4 | */ 5 | 6 | #![cfg_attr(not(feature = "std"), no_std)] 7 | extern crate no_std_compat as std; 8 | 9 | pub mod error; 10 | 11 | pub mod kernel; 12 | 13 | pub mod offsets; 14 | 15 | pub mod win32; 16 | 17 | pub mod prelude { 18 | pub mod v1 { 19 | pub use crate::error::*; 20 | pub use crate::kernel::*; 21 | pub use crate::offsets::*; 22 | pub use crate::win32::*; 23 | } 24 | pub use v1::*; 25 | } 26 | 27 | #[deprecated] 28 | pub use prelude::v1::*; 29 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-win32/src/win32.rs: -------------------------------------------------------------------------------- 1 | pub mod kernel; 2 | pub mod kernel_builder; 3 | pub mod kernel_info; 4 | 5 | pub use kernel::Kernel; 6 | pub use kernel_builder::KernelBuilder; 7 | pub use kernel_info::KernelInfo; 8 | 9 | pub mod keyboard; 10 | pub mod module; 11 | pub mod process; 12 | pub mod unicode_string; 13 | pub mod vat; 14 | 15 | pub use keyboard::*; 16 | pub use module::*; 17 | pub use process::*; 18 | pub use unicode_string::*; 19 | pub use vat::*; 20 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-win32/src/win32/module.rs: -------------------------------------------------------------------------------- 1 | use std::prelude::v1::*; 2 | 3 | use memflow::process::OsProcessModuleInfo; 4 | use memflow::types::Address; 5 | 6 | #[derive(Debug, Clone)] 7 | pub struct Win32ModuleInfo { 8 | pub peb_entry: Address, 9 | pub parent_eprocess: Address, // parent "reference" 10 | 11 | pub base: Address, // _LDR_DATA_TABLE_ENTRY::DllBase 12 | pub size: usize, // _LDR_DATA_TABLE_ENTRY::SizeOfImage 13 | pub path: String, // _LDR_DATA_TABLE_ENTRY::FullDllName 14 | pub name: String, // _LDR_DATA_TABLE_ENTRY::BaseDllName 15 | } 16 | 17 | impl OsProcessModuleInfo for Win32ModuleInfo { 18 | fn address(&self) -> Address { 19 | self.peb_entry 20 | } 21 | 22 | fn parent_process(&self) -> Address { 23 | self.parent_eprocess 24 | } 25 | 26 | fn base(&self) -> Address { 27 | self.base 28 | } 29 | 30 | fn size(&self) -> usize { 31 | self.size 32 | } 33 | 34 | fn name(&self) -> String { 35 | self.name.clone() 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-win32/src/win32/unicode_string.rs: -------------------------------------------------------------------------------- 1 | use std::prelude::v1::*; 2 | 3 | use crate::error::{Error, Result}; 4 | 5 | use std::convert::TryInto; 6 | 7 | use memflow::architecture::{ArchitectureObj, Endianess}; 8 | use memflow::mem::VirtualMemory; 9 | use memflow::types::Address; 10 | 11 | use widestring::U16CString; 12 | 13 | pub trait VirtualReadUnicodeString { 14 | fn virt_read_unicode_string( 15 | &mut self, 16 | proc_arch: ArchitectureObj, 17 | addr: Address, 18 | ) -> Result; 19 | } 20 | 21 | // TODO: split up cpu and proc arch in read_helper.rs 22 | impl<'a, T: VirtualMemory> VirtualReadUnicodeString for T { 23 | fn virt_read_unicode_string( 24 | &mut self, 25 | proc_arch: ArchitectureObj, 26 | addr: Address, 27 | ) -> Result { 28 | /* 29 | typedef struct _windows_unicode_string32 { 30 | uint16_t length; 31 | uint16_t maximum_length; 32 | uint32_t pBuffer; // pointer to string contents 33 | } __attribute__((packed)) win32_unicode_string_t; 34 | 35 | typedef struct _windows_unicode_string64 { 36 | uint16_t length; 37 | uint16_t maximum_length; 38 | uint32_t padding; // align pBuffer 39 | uint64_t pBuffer; // pointer to string contents 40 | } __attribute__((packed)) win64_unicode_string_t; 41 | */ 42 | 43 | // length is always the first entry 44 | let mut length = 0u16; 45 | self.virt_read_into(addr, &mut length)?; 46 | if length == 0 { 47 | return Err(Error::Unicode("unable to read unicode string length")); 48 | } 49 | 50 | // TODO: chek if length exceeds limit 51 | // buffer is either aligned at 4 or 8 52 | let buffer = match proc_arch.bits() { 53 | 64 => self.virt_read_addr64(addr + 8)?, 54 | 32 => self.virt_read_addr32(addr + 4)?, 55 | _ => { 56 | return Err(Error::InvalidArchitecture); 57 | } 58 | }; 59 | if buffer.is_null() { 60 | return Err(Error::Unicode("unable to read unicode string length")); 61 | } 62 | 63 | // check if buffer length is mod 2 (utf-16) 64 | if length % 2 != 0 { 65 | return Err(Error::Unicode( 66 | "unicode string length is not a multiple of two", 67 | )); 68 | } 69 | 70 | // read buffer 71 | let mut content = vec![0; length as usize + 2]; 72 | self.virt_read_raw_into(buffer, &mut content)?; 73 | content[length as usize] = 0; 74 | content[length as usize + 1] = 0; 75 | 76 | // TODO: check length % 2 == 0 77 | 78 | let content16 = content 79 | .chunks_exact(2) 80 | .map(|b| b[0..2].try_into().map_err(|_| Error::Bounds)) 81 | .filter_map(Result::ok) 82 | .map(|b| match proc_arch.endianess() { 83 | Endianess::LittleEndian => u16::from_le_bytes(b), 84 | Endianess::BigEndian => u16::from_be_bytes(b), 85 | }) 86 | .collect::>(); 87 | Ok(U16CString::from_vec_with_nul(content16) 88 | .map_err(|_| Error::Encoding)? 89 | .to_string_lossy()) 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-win32/src/win32/vat.rs: -------------------------------------------------------------------------------- 1 | use memflow::{ 2 | architecture::{x86, ArchitectureObj, ScopedVirtualTranslate}, 3 | error::Error, 4 | iter::SplitAtIndex, 5 | mem::{PhysicalMemory, VirtualDMA, VirtualMemory, VirtualTranslate}, 6 | types::{Address, PhysicalAddress}, 7 | }; 8 | 9 | #[derive(Debug, Clone, Copy)] 10 | pub struct Win32VirtualTranslate { 11 | pub sys_arch: ArchitectureObj, 12 | pub dtb: Address, 13 | } 14 | 15 | impl Win32VirtualTranslate { 16 | pub fn new(sys_arch: ArchitectureObj, dtb: Address) -> Self { 17 | Self { sys_arch, dtb } 18 | } 19 | 20 | pub fn virt_mem( 21 | self, 22 | mem: T, 23 | vat: V, 24 | proc_arch: ArchitectureObj, 25 | ) -> impl VirtualMemory { 26 | VirtualDMA::with_vat(mem, proc_arch, self, vat) 27 | } 28 | } 29 | 30 | impl ScopedVirtualTranslate for Win32VirtualTranslate { 31 | fn virt_to_phys_iter< 32 | T: PhysicalMemory + ?Sized, 33 | B: SplitAtIndex, 34 | VI: Iterator, 35 | VO: Extend<(PhysicalAddress, B)>, 36 | FO: Extend<(Error, Address, B)>, 37 | >( 38 | &self, 39 | mem: &mut T, 40 | addrs: VI, 41 | out: &mut VO, 42 | out_fail: &mut FO, 43 | arena: &memflow::architecture::Bump, 44 | ) { 45 | let translator = x86::new_translator(self.dtb, self.sys_arch).unwrap(); 46 | translator.virt_to_phys_iter(mem, addrs, out, out_fail, arena) 47 | } 48 | 49 | fn translation_table_id(&self, _address: Address) -> usize { 50 | self.dtb.as_u64().overflowing_shr(12).0 as usize 51 | } 52 | 53 | fn arch(&self) -> ArchitectureObj { 54 | self.sys_arch 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "memflow" 3 | version = "0.1.5" 4 | authors = ["ko1N ", "Aurimas Blažulionis <0x60@pm.me>"] 5 | edition = "2018" 6 | description = "core components of the memflow physical memory introspection framework" 7 | documentation = "https://docs.rs/memflow" 8 | readme = "../README.md" 9 | homepage = "https://memflow.github.io" 10 | repository = "https://github.com/memflow/memflow" 11 | license-file = "../LICENSE" 12 | keywords = [ "memflow", "introspection", "memory", "dma" ] 13 | categories = [ "memory-management", "os" ] 14 | 15 | [badges] 16 | maintenance = { status = "actively-developed" } 17 | codecov = { repository = "github", branch = "master", service = "github" } 18 | 19 | [dependencies] 20 | memflow-derive = { version = "0.1", path = "../memflow-derive" } 21 | dataview = { version = "0.1", features = ["derive_pod"] } 22 | log = "0.4" 23 | bitflags = "1.2" 24 | coarsetime = { version = "0.1", optional = true } 25 | smallvec = { version = "1.4", default-features = false } 26 | x86_64 = { version = "0.12", default-features = false } 27 | rand = { version = "0.7", optional = true } 28 | rand_xorshift = { version = "0.2", optional = true } 29 | bumpalo = { version = "3.4", features = ["collections"] } 30 | no-std-compat = { version = "0.4", features = ["alloc"] } 31 | itertools = { version = "0.9", default-features = false } 32 | vector-trees = { version = "0.1", git = "https://github.com/h33p/vector-trees", features = ["bumpalo"] } 33 | hashbrown = "0.8" 34 | libloading = { version = "0.6", optional = true } 35 | memmap = { version = "0.7", optional = true } 36 | dirs = { version = "3.0", optional = true } 37 | 38 | serde = { version = "1.0", optional = true, default-features = false, features = ["derive", "alloc"] } 39 | toml = { version = "0.5", optional = true } 40 | 41 | [dev-dependencies] 42 | rand = { version = "0.7" } 43 | rand_xorshift = "0.2" 44 | 45 | [features] 46 | default = ["std", "serde_derive", "inventory", "filemap", "memmapfiles"] 47 | trace_mmu = [] # enables debug traces in the mmu (very verbose) 48 | dummy_mem = ["rand", "rand_xorshift"] 49 | std = ["coarsetime", "no-std-compat/std"] 50 | collections = [] 51 | alloc = [] 52 | serde_derive = ["serde"] 53 | memmapfiles = ["toml", "serde_derive"] 54 | inventory = ["libloading", "dirs"] 55 | filemap = ["memmap"] 56 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow/src/architecture/x86/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod x32; 2 | pub mod x32_pae; 3 | pub mod x64; 4 | 5 | use super::{ 6 | mmu_spec::{translate_data::TranslateVec, ArchMMUSpec, MMUTranslationBase}, 7 | Architecture, ArchitectureObj, Endianess, ScopedVirtualTranslate, 8 | }; 9 | 10 | use super::Bump; 11 | use crate::error::{Error, Result}; 12 | use crate::iter::SplitAtIndex; 13 | use crate::mem::PhysicalMemory; 14 | use crate::types::{Address, PhysicalAddress}; 15 | 16 | pub struct X86Architecture { 17 | /// Defines how many bits does the native word size have 18 | bits: u8, 19 | /// Defines the byte order of the architecture 20 | endianess: Endianess, 21 | /// Defines the underlying MMU used for address translation 22 | mmu: ArchMMUSpec, 23 | } 24 | 25 | impl Architecture for X86Architecture { 26 | fn bits(&self) -> u8 { 27 | self.bits 28 | } 29 | 30 | fn endianess(&self) -> Endianess { 31 | self.endianess 32 | } 33 | 34 | fn page_size(&self) -> usize { 35 | self.mmu.page_size_level(1) 36 | } 37 | 38 | fn size_addr(&self) -> usize { 39 | self.mmu.addr_size.into() 40 | } 41 | 42 | fn address_space_bits(&self) -> u8 { 43 | self.mmu.address_space_bits 44 | } 45 | } 46 | 47 | #[derive(Clone, Copy)] 48 | pub struct X86ScopedVirtualTranslate { 49 | arch: &'static X86Architecture, 50 | dtb: X86PageTableBase, 51 | } 52 | 53 | impl X86ScopedVirtualTranslate { 54 | pub fn new(arch: &'static X86Architecture, dtb: Address) -> Self { 55 | Self { 56 | arch, 57 | dtb: X86PageTableBase(dtb), 58 | } 59 | } 60 | } 61 | 62 | impl ScopedVirtualTranslate for X86ScopedVirtualTranslate { 63 | fn virt_to_phys_iter< 64 | T: PhysicalMemory + ?Sized, 65 | B: SplitAtIndex, 66 | VI: Iterator, 67 | VO: Extend<(PhysicalAddress, B)>, 68 | FO: Extend<(Error, Address, B)>, 69 | >( 70 | &self, 71 | mem: &mut T, 72 | addrs: VI, 73 | out: &mut VO, 74 | out_fail: &mut FO, 75 | arena: &Bump, 76 | ) { 77 | self.arch 78 | .mmu 79 | .virt_to_phys_iter(mem, self.dtb, addrs, out, out_fail, arena) 80 | } 81 | 82 | fn translation_table_id(&self, _address: Address) -> usize { 83 | self.dtb.0.as_u64().overflowing_shr(12).0 as usize 84 | } 85 | 86 | fn arch(&self) -> ArchitectureObj { 87 | self.arch 88 | } 89 | } 90 | 91 | #[repr(transparent)] 92 | #[derive(Clone, Copy)] 93 | pub struct X86PageTableBase(Address); 94 | 95 | impl MMUTranslationBase for X86PageTableBase { 96 | fn get_initial_pt(&self, _: Address) -> Address { 97 | self.0 98 | } 99 | 100 | fn get_pt_by_index(&self, _: usize) -> Address { 101 | self.0 102 | } 103 | 104 | fn pt_count(&self) -> usize { 105 | 1 106 | } 107 | 108 | fn virt_addr_filter( 109 | &self, 110 | spec: &ArchMMUSpec, 111 | addr: (Address, B), 112 | data_to_translate: &mut TranslateVec, 113 | out_fail: &mut O, 114 | ) where 115 | B: SplitAtIndex, 116 | O: Extend<(Error, Address, B)>, 117 | { 118 | spec.virt_addr_filter(addr, &mut data_to_translate[0].vec, out_fail); 119 | } 120 | } 121 | 122 | // This lint doesn't make any sense in our usecase, since we nevel leak ARCH_SPECs, and ARCH is 123 | // a static trait object with a consistent address. 124 | fn underlying_arch(arch: ArchitectureObj) -> Option<&'static X86Architecture> { 125 | if arch == x64::ARCH { 126 | Some(&x64::ARCH_SPEC) 127 | } else if arch == x32::ARCH { 128 | Some(&x32::ARCH_SPEC) 129 | } else if arch == x32_pae::ARCH { 130 | Some(&x32_pae::ARCH_SPEC) 131 | } else { 132 | None 133 | } 134 | } 135 | 136 | pub fn new_translator(dtb: Address, arch: ArchitectureObj) -> Result { 137 | let arch = underlying_arch(arch).ok_or(Error::InvalidArchitecture)?; 138 | Ok(X86ScopedVirtualTranslate::new(arch, dtb)) 139 | } 140 | 141 | pub fn is_x86_arch(arch: ArchitectureObj) -> bool { 142 | underlying_arch(arch).is_some() 143 | } 144 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow/src/architecture/x86/x32.rs: -------------------------------------------------------------------------------- 1 | use super::{ 2 | super::{ArchMMUSpec, ArchitectureObj, Endianess, ScopedVirtualTranslate}, 3 | X86Architecture, X86ScopedVirtualTranslate, 4 | }; 5 | 6 | use crate::types::Address; 7 | 8 | pub(super) const ARCH_SPEC: X86Architecture = X86Architecture { 9 | bits: 32, 10 | endianess: Endianess::LittleEndian, 11 | mmu: ArchMMUSpec { 12 | virtual_address_splits: &[10, 10, 12], 13 | valid_final_page_steps: &[1, 2], 14 | address_space_bits: 32, 15 | addr_size: 4, 16 | pte_size: 4, 17 | present_bit: 0, 18 | writeable_bit: 1, 19 | nx_bit: 31, //Actually, NX is unsupported in x86 non-PAE, we have to do something about it 20 | large_page_bit: 7, 21 | }, 22 | }; 23 | 24 | pub static ARCH: ArchitectureObj = &ARCH_SPEC; 25 | 26 | pub fn new_translator(dtb: Address) -> impl ScopedVirtualTranslate { 27 | X86ScopedVirtualTranslate::new(&ARCH_SPEC, dtb) 28 | } 29 | 30 | //x64 tests MMU rigorously, here we will only test a few special cases 31 | #[cfg(test)] 32 | mod tests { 33 | use crate::architecture::mmu_spec::ArchMMUSpec; 34 | use crate::types::{size, Address}; 35 | 36 | fn get_mmu_spec() -> ArchMMUSpec { 37 | super::ARCH_SPEC.mmu 38 | } 39 | 40 | #[test] 41 | fn x86_pte_bitmasks() { 42 | let mmu = get_mmu_spec(); 43 | let mask_addr = Address::invalid(); 44 | assert_eq!( 45 | mmu.pte_addr_mask(mask_addr, 0), 46 | Address::bit_mask(12..31).as_u64() 47 | ); 48 | assert_eq!( 49 | mmu.pte_addr_mask(mask_addr, 1), 50 | Address::bit_mask(12..31).as_u64() 51 | ); 52 | assert_eq!( 53 | mmu.pte_addr_mask(mask_addr, 2), 54 | Address::bit_mask(12..31).as_u64() 55 | ); 56 | } 57 | 58 | #[test] 59 | fn x86_pte_leaf_size() { 60 | let mmu = get_mmu_spec(); 61 | assert_eq!(mmu.pt_leaf_size(0), size::kb(4)); 62 | assert_eq!(mmu.pt_leaf_size(1), size::kb(4)); 63 | } 64 | 65 | #[test] 66 | fn x86_page_size_level() { 67 | let mmu = get_mmu_spec(); 68 | assert_eq!(mmu.page_size_level(1), size::kb(4)); 69 | assert_eq!(mmu.page_size_level(2), size::mb(4)); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow/src/architecture/x86/x32_pae.rs: -------------------------------------------------------------------------------- 1 | use super::{ 2 | super::{ArchMMUSpec, ArchitectureObj, Endianess, ScopedVirtualTranslate}, 3 | X86Architecture, X86ScopedVirtualTranslate, 4 | }; 5 | 6 | use crate::types::Address; 7 | 8 | pub(super) const ARCH_SPEC: X86Architecture = X86Architecture { 9 | bits: 32, 10 | endianess: Endianess::LittleEndian, 11 | mmu: ArchMMUSpec { 12 | virtual_address_splits: &[2, 9, 9, 12], 13 | valid_final_page_steps: &[2, 3], 14 | address_space_bits: 36, 15 | addr_size: 4, 16 | pte_size: 8, 17 | present_bit: 0, 18 | writeable_bit: 1, 19 | nx_bit: 63, 20 | large_page_bit: 7, 21 | }, 22 | }; 23 | 24 | pub static ARCH: ArchitectureObj = &ARCH_SPEC; 25 | 26 | pub fn new_translator(dtb: Address) -> impl ScopedVirtualTranslate { 27 | X86ScopedVirtualTranslate::new(&ARCH_SPEC, dtb) 28 | } 29 | 30 | //x64 tests MMU rigorously, here we will only test a few special cases 31 | #[cfg(test)] 32 | mod tests { 33 | use crate::architecture::mmu_spec::ArchMMUSpec; 34 | use crate::types::{size, Address}; 35 | 36 | fn get_mmu_spec() -> ArchMMUSpec { 37 | super::ARCH_SPEC.mmu 38 | } 39 | 40 | #[test] 41 | fn x86_pae_pte_bitmasks() { 42 | let mmu = get_mmu_spec(); 43 | let mask_addr = Address::invalid(); 44 | assert_eq!( 45 | mmu.pte_addr_mask(mask_addr, 0), 46 | Address::bit_mask(5..35).as_u64() 47 | ); 48 | assert_eq!( 49 | mmu.pte_addr_mask(mask_addr, 1), 50 | Address::bit_mask(12..35).as_u64() 51 | ); 52 | assert_eq!( 53 | mmu.pte_addr_mask(mask_addr, 2), 54 | Address::bit_mask(12..35).as_u64() 55 | ); 56 | } 57 | 58 | #[test] 59 | fn x86_pae_pte_leaf_size() { 60 | let mmu = get_mmu_spec(); 61 | assert_eq!(mmu.pt_leaf_size(0), 32); 62 | assert_eq!(mmu.pt_leaf_size(1), size::kb(4)); 63 | } 64 | 65 | #[test] 66 | fn x86_pae_page_size_level() { 67 | let mmu = get_mmu_spec(); 68 | assert_eq!(mmu.page_size_level(1), size::kb(4)); 69 | assert_eq!(mmu.page_size_level(2), size::mb(2)); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow/src/connector/fileio.rs: -------------------------------------------------------------------------------- 1 | /*! 2 | Basic connector which works on file i/o operations (`Seek`, `Read`, `Write`). 3 | */ 4 | 5 | use crate::error::{Error, Result}; 6 | use crate::iter::FnExtend; 7 | use crate::mem::{ 8 | MemoryMap, PhysicalMemory, PhysicalMemoryMetadata, PhysicalReadData, PhysicalWriteData, 9 | }; 10 | use crate::types::Address; 11 | 12 | use std::io::{Read, Seek, SeekFrom, Write}; 13 | 14 | /// Accesses physical memory via file i/o. 15 | /// 16 | /// This backend helper works in tandem with MappedPhysicalMemory. 17 | /// 18 | /// # Examples 19 | /// ``` 20 | /// use memflow::connector::FileIOMemory; 21 | /// use memflow::mem::MemoryMap; 22 | /// 23 | /// use std::fs::File; 24 | /// 25 | /// fn open(file: &File) { 26 | /// let map = MemoryMap::new(); 27 | /// let connector = FileIOMemory::try_with_reader(file, map); 28 | /// } 29 | /// ``` 30 | #[derive(Clone)] 31 | pub struct FileIOMemory { 32 | reader: T, 33 | mem_map: MemoryMap<(Address, usize)>, 34 | } 35 | 36 | impl FileIOMemory { 37 | pub fn try_with_reader(reader: T, mem_map: MemoryMap<(Address, usize)>) -> Result { 38 | Ok(Self { reader, mem_map }) 39 | } 40 | } 41 | 42 | impl PhysicalMemory for FileIOMemory { 43 | fn phys_read_raw_list(&mut self, data: &mut [PhysicalReadData]) -> Result<()> { 44 | let mut void = FnExtend::void(); 45 | for ((file_off, _), buf) in self.mem_map.map_iter( 46 | data.iter_mut() 47 | .map(|PhysicalReadData(addr, buf)| (*addr, &mut **buf)), 48 | &mut void, 49 | ) { 50 | self.reader 51 | .seek(SeekFrom::Start(file_off.as_u64())) 52 | .map_err(|_| Error::Connector("Seek failed"))?; 53 | self.reader 54 | .read_exact(buf) 55 | .map_err(|_| Error::Connector("Read failed"))?; 56 | } 57 | Ok(()) 58 | } 59 | 60 | fn phys_write_raw_list(&mut self, data: &[PhysicalWriteData]) -> Result<()> { 61 | let mut void = FnExtend::void(); 62 | for ((file_off, _), buf) in self 63 | .mem_map 64 | .map_iter(data.iter().copied().map(<_>::from), &mut void) 65 | { 66 | self.reader 67 | .seek(SeekFrom::Start(file_off.as_u64())) 68 | .map_err(|_| Error::Connector("Seek failed"))?; 69 | self.reader 70 | .write(buf) 71 | .map_err(|_| Error::Connector("Write failed"))?; 72 | } 73 | Ok(()) 74 | } 75 | 76 | fn metadata(&self) -> PhysicalMemoryMetadata { 77 | PhysicalMemoryMetadata { 78 | size: self 79 | .mem_map 80 | .as_ref() 81 | .iter() 82 | .last() 83 | .map(|map| map.base().as_usize() + map.output().1) 84 | .unwrap(), 85 | readonly: false, 86 | } 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow/src/connector/filemap.rs: -------------------------------------------------------------------------------- 1 | use crate::error::{Error, Result}; 2 | use crate::mem::MemoryMap; 3 | use crate::types::Address; 4 | use memmap::{Mmap, MmapMut, MmapOptions}; 5 | 6 | use std::fs::File; 7 | use std::sync::Arc; 8 | 9 | use super::mmap::MappedPhysicalMemory; 10 | 11 | #[derive(Clone)] 12 | pub struct MMAPInfo<'a> { 13 | mem_map: MemoryMap<&'a [u8]>, 14 | _buf: Arc, 15 | } 16 | 17 | impl<'a> AsRef> for MMAPInfo<'a> { 18 | fn as_ref(&self) -> &MemoryMap<&'a [u8]> { 19 | &self.mem_map 20 | } 21 | } 22 | 23 | impl<'a> MMAPInfo<'a> { 24 | pub fn try_with_filemap(file: File, map: MemoryMap<(Address, usize)>) -> Result { 25 | let file_map = unsafe { 26 | MmapOptions::new() 27 | .map(&file) 28 | .map_err(|_| Error::Connector("unable to map file"))? 29 | }; 30 | 31 | Self::try_with_bufmap(file_map, map) 32 | } 33 | 34 | pub fn try_with_bufmap(buf: Mmap, map: MemoryMap<(Address, usize)>) -> Result { 35 | let mut new_map = MemoryMap::new(); 36 | 37 | let buf_len = buf.as_ref().len(); 38 | let buf_ptr = buf.as_ref().as_ptr(); 39 | 40 | for (base, (output_base, size)) in map.into_iter() { 41 | if output_base.as_usize() >= buf_len { 42 | return Err(Error::Connector("Memory map is out of range")); 43 | } 44 | 45 | let output_end = std::cmp::min(output_base.as_usize() + size, buf_len); 46 | 47 | new_map.push(base, unsafe { 48 | std::slice::from_raw_parts( 49 | buf_ptr.add(output_base.as_usize()), 50 | output_end - output_base.as_usize(), 51 | ) 52 | }); 53 | } 54 | 55 | Ok(Self { 56 | mem_map: new_map, 57 | _buf: Arc::new(buf), 58 | }) 59 | } 60 | 61 | pub fn into_connector(self) -> ReadMappedFilePhysicalMemory<'a> { 62 | MappedPhysicalMemory::with_info(self) 63 | } 64 | } 65 | 66 | pub type ReadMappedFilePhysicalMemory<'a> = MappedPhysicalMemory<&'a [u8], MMAPInfo<'a>>; 67 | 68 | pub struct MMAPInfoMut<'a> { 69 | mem_map: MemoryMap<&'a mut [u8]>, 70 | _buf: MmapMut, 71 | } 72 | 73 | impl<'a> AsRef> for MMAPInfoMut<'a> { 74 | fn as_ref(&self) -> &MemoryMap<&'a mut [u8]> { 75 | &self.mem_map 76 | } 77 | } 78 | 79 | impl<'a> MMAPInfoMut<'a> { 80 | pub fn try_with_filemap_mut(file: File, map: MemoryMap<(Address, usize)>) -> Result { 81 | let file_map = unsafe { 82 | MmapOptions::new() 83 | .map_mut(&file) 84 | .map_err(|_| Error::Connector("unable to map file"))? 85 | }; 86 | 87 | Self::try_with_bufmap_mut(file_map, map) 88 | } 89 | 90 | pub fn try_with_bufmap_mut(mut buf: MmapMut, map: MemoryMap<(Address, usize)>) -> Result { 91 | let mut new_map = MemoryMap::new(); 92 | 93 | let buf_len = buf.as_ref().len(); 94 | let buf_ptr = buf.as_mut().as_mut_ptr(); 95 | 96 | for (base, (output_base, size)) in map.into_iter() { 97 | if output_base.as_usize() >= buf_len { 98 | return Err(Error::Connector("Memory map is out of range")); 99 | } 100 | 101 | let output_end = std::cmp::min(output_base.as_usize() + size, buf_len); 102 | 103 | new_map.push(base, unsafe { 104 | std::slice::from_raw_parts_mut( 105 | buf_ptr.add(output_base.as_usize()), 106 | output_end - output_base.as_usize(), 107 | ) 108 | }); 109 | } 110 | 111 | Ok(Self { 112 | mem_map: new_map, 113 | _buf: buf, 114 | }) 115 | } 116 | 117 | pub fn into_connector(self) -> WriteMappedFilePhysicalMemory<'a> { 118 | MappedPhysicalMemory::with_info(self) 119 | } 120 | } 121 | 122 | pub type WriteMappedFilePhysicalMemory<'a> = MappedPhysicalMemory<&'a mut [u8], MMAPInfoMut<'a>>; 123 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow/src/connector/mod.rs: -------------------------------------------------------------------------------- 1 | /*! 2 | Module containing basic connector and inventory related functions. 3 | 4 | This module provides basic building blocks when building connectors. 5 | It contains a file i/o and memory mapped file interface 6 | as well as a interface for interfacing with buffers. 7 | 8 | This module also contains functions to interface with dynamically loaded connectors. 9 | The inventory system is feature gated behind the `inventory` feature. 10 | */ 11 | 12 | pub mod args; 13 | #[doc(hidden)] 14 | pub use args::ConnectorArgs; 15 | 16 | #[cfg(feature = "inventory")] 17 | pub mod inventory; 18 | #[doc(hidden)] 19 | #[cfg(feature = "inventory")] 20 | pub use inventory::{ 21 | Connector, ConnectorDescriptor, ConnectorInstance, ConnectorInventory, ConnectorType, 22 | MEMFLOW_CONNECTOR_VERSION, 23 | }; 24 | 25 | #[cfg(feature = "std")] 26 | pub mod fileio; 27 | #[doc(hidden)] 28 | #[cfg(feature = "std")] 29 | pub use fileio::FileIOMemory; 30 | 31 | #[cfg(feature = "filemap")] 32 | pub mod filemap; 33 | #[cfg(feature = "filemap")] 34 | pub use filemap::{ 35 | MMAPInfo, MMAPInfoMut, ReadMappedFilePhysicalMemory, WriteMappedFilePhysicalMemory, 36 | }; 37 | 38 | pub mod mmap; 39 | #[doc(hidden)] 40 | pub use mmap::MappedPhysicalMemory; 41 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow/src/iter/double_buffered_iterator.rs: -------------------------------------------------------------------------------- 1 | use std::collections::VecDeque; 2 | 3 | pub type VecType = VecDeque; 4 | 5 | pub struct DoubleBufferedMapIterator { 6 | iter: I, 7 | fi: FI, 8 | fo: FO, 9 | buf: VecType, 10 | buf_out: VecType, 11 | } 12 | 13 | impl DoubleBufferedMapIterator { 14 | pub fn new(iter: I, fi: FI, fo: FO) -> Self { 15 | Self { 16 | iter, 17 | fi, 18 | fo, 19 | buf: VecType::new(), 20 | buf_out: VecType::new(), 21 | } 22 | } 23 | } 24 | 25 | impl Iterator for DoubleBufferedMapIterator 26 | where 27 | I: Iterator, 28 | FI: FnMut(A) -> (bool, B), 29 | FO: FnMut(&mut VecType, &mut VecType), 30 | { 31 | type Item = C; 32 | 33 | #[inline] 34 | fn size_hint(&self) -> (usize, Option) { 35 | self.iter.size_hint() 36 | } 37 | 38 | #[inline] 39 | fn next(&mut self) -> Option { 40 | //If empty, buffer up the output deque 41 | if self.buf_out.is_empty() { 42 | while let Some(elem) = self.iter.next() { 43 | match (self.fi)(elem) { 44 | (true, elem) => { 45 | self.buf.push_back(elem); 46 | } 47 | (false, elem) => { 48 | self.buf.push_back(elem); 49 | break; 50 | } 51 | } 52 | } 53 | 54 | (self.fo)(&mut self.buf, &mut self.buf_out); 55 | } 56 | 57 | self.buf_out.pop_front() 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow/src/iter/doublepeek.rs: -------------------------------------------------------------------------------- 1 | pub struct DoublePeekingIterator 2 | where 3 | I: Iterator, 4 | { 5 | iter: I, 6 | next: Option, 7 | next2: Option, 8 | } 9 | 10 | impl DoublePeekingIterator 11 | where 12 | I: Iterator, 13 | { 14 | /// Construct a double peeking iterator 15 | /// 16 | /// It will consume the next 2 elements upon call 17 | pub fn new(mut iter: I) -> Self { 18 | Self { 19 | next: iter.next(), 20 | next2: iter.next(), 21 | iter, 22 | } 23 | } 24 | 25 | /// Peek 2 elements without moving the iterator's head 26 | pub fn double_peek(&self) -> (&Option, &Option) { 27 | (&self.next, &self.next2) 28 | } 29 | 30 | /// Check if there isn't an element after the next one 31 | /// 32 | /// This will check if the second next element is none. 33 | /// It will still return true if next element is None, 34 | /// and it may return false on unfused iterators that happen 35 | /// to have None elements in the middle. 36 | pub fn is_next_last(&self) -> bool { 37 | self.next2.is_none() 38 | } 39 | } 40 | 41 | impl Iterator for DoublePeekingIterator 42 | where 43 | I: Iterator, 44 | { 45 | type Item = I::Item; 46 | 47 | #[inline] 48 | fn size_hint(&self) -> (usize, Option) { 49 | self.iter.size_hint() 50 | } 51 | 52 | #[inline] 53 | fn next(&mut self) -> Option { 54 | std::mem::replace( 55 | &mut self.next, 56 | std::mem::replace(&mut self.next2, self.iter.next()), 57 | ) 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow/src/iter/void.rs: -------------------------------------------------------------------------------- 1 | use std::prelude::v1::*; 2 | 3 | use std::marker::PhantomData; 4 | 5 | pub struct FnExtend { 6 | func: F, 7 | _phantom: PhantomData, 8 | } 9 | 10 | impl FnExtend { 11 | pub fn new(func: F) -> Self { 12 | Self { 13 | func, 14 | _phantom: PhantomData::default(), 15 | } 16 | } 17 | } 18 | 19 | impl FnExtend { 20 | pub fn void() -> Self { 21 | Self { 22 | func: |_| {}, 23 | _phantom: PhantomData::default(), 24 | } 25 | } 26 | } 27 | 28 | impl Extend for FnExtend { 29 | fn extend>(&mut self, iter: I) { 30 | iter.into_iter().for_each(&mut self.func); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow/src/lib.rs: -------------------------------------------------------------------------------- 1 | /*! 2 | memflow is a library that allows live memory introspection of running systems and their snapshots. 3 | Due to its modular approach it trivial to support almost any scenario where Direct Memory Access is available. 4 | 5 | The very core of the library is a [PhysicalMemory](mem/phys_mem/index.html) that provides direct memory access in an abstract environment. 6 | This object that can be defined both statically, and dynamically with the use of the `inventory` feature. 7 | If `inventory` is enabled, it is possible to dynamically load libraries that provide Direct Memory Access. 8 | 9 | Through the use of OS abstraction layers, like [memflow-win32](https://github.com/memflow/memflow/tree/master/memflow-win32), 10 | user can gain access to virtual memory of individual processes, 11 | by creating objects that implement [VirtualMemory](mem/virt_mem/index.html). 12 | 13 | Bridging the two is done by a highly throughput optimized virtual address translation function, 14 | which allows for crazy fast memory transfers at scale. 15 | 16 | The core is architecture independent (as long as addresses fit in 64-bits), and currently both 32, 17 | and 64-bit versions of the x86 family are available to be used. 18 | 19 | For non-rust libraries, it is possible to use the [FFI](https://github.com/memflow/memflow/tree/master/memflow-ffi) 20 | to interface with the library. 21 | 22 | You will almost always import this module when working with memflow. 23 | */ 24 | 25 | #![cfg_attr(not(feature = "std"), no_std)] 26 | extern crate no_std_compat as std; 27 | 28 | #[macro_use] 29 | extern crate bitflags; 30 | 31 | #[macro_use] 32 | extern crate smallvec; 33 | 34 | pub mod error; 35 | 36 | #[macro_use] 37 | pub mod types; 38 | 39 | pub mod architecture; 40 | 41 | pub mod mem; 42 | 43 | pub mod connector; 44 | 45 | pub mod process; 46 | 47 | pub mod iter; 48 | 49 | pub mod derive { 50 | pub use memflow_derive::*; 51 | } 52 | 53 | pub mod prelude { 54 | pub mod v1 { 55 | pub use crate::architecture::*; 56 | pub use crate::connector::*; 57 | pub use crate::derive::*; 58 | pub use crate::error::*; 59 | pub use crate::iter::*; 60 | pub use crate::mem::*; 61 | pub use crate::process::*; 62 | pub use crate::types::*; 63 | } 64 | pub use v1::*; 65 | } 66 | 67 | #[deprecated] 68 | pub use prelude::v1::*; 69 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow/src/mem/cache/count_validator.rs: -------------------------------------------------------------------------------- 1 | /*! 2 | Validators are used when working with caches and determine for how long 3 | a specific cache entry stays valid. 4 | 5 | This validator limits the cache time based on an actual time instant. 6 | Internally it uses the [coarsetime](https://docs.rs/coarsetime/0.1.14/coarsetime/) crate as a less 7 | computation intensive alternative for [std::time](https://doc.rust-lang.org/std/time/index.html). 8 | Therefor the Duration has to be converted (e.g. via the .into() trait) when constructing this validator. 9 | 10 | The default implementation will set the cache time to 1 second. 11 | */ 12 | use std::prelude::v1::*; 13 | 14 | use super::CacheValidator; 15 | 16 | /// Validator for limiting the cache time based on a time `Instant` 17 | /// 18 | /// # Remarks 19 | /// 20 | /// This validator is only available when being compiled with `std`. 21 | /// When using `no_std` you might want to use another validator. 22 | /// TODO: add other validators here 23 | #[derive(Clone)] 24 | pub struct CountCacheValidator { 25 | count: Vec, 26 | valid_count: usize, 27 | last_count: usize, 28 | } 29 | 30 | /// Creates a validator with a cache timeout of 1 second. 31 | impl Default for CountCacheValidator { 32 | fn default() -> Self { 33 | Self::new(10) 34 | } 35 | } 36 | 37 | impl CountCacheValidator { 38 | /// Creates a new CountCacheValidator with a customizable valid count. 39 | /// 40 | /// Valid count is increased on every memory operation by the validator users. 41 | /// 42 | /// # Examples: 43 | /// ``` 44 | /// use memflow::mem::{CacheValidator, CountCacheValidator}; 45 | /// 46 | /// let mut validator = CountCacheValidator::new(100); 47 | /// 48 | /// validator.allocate_slots(1); 49 | /// 50 | /// assert!(!validator.is_slot_valid(0)); 51 | /// validator.validate_slot(0); 52 | /// 53 | /// // For a hundred times the slot should stay valid 54 | /// for _ in 0..100 { 55 | /// assert!(validator.is_slot_valid(0)); 56 | /// validator.update_validity(); 57 | /// } 58 | /// 59 | /// // At this point it should become invalid 60 | /// assert!(!validator.is_slot_valid(0)); 61 | /// ``` 62 | pub fn new(valid_count: usize) -> Self { 63 | Self { 64 | count: vec![], 65 | valid_count, 66 | last_count: 0, 67 | } 68 | } 69 | } 70 | 71 | impl CacheValidator for CountCacheValidator { 72 | #[inline] 73 | fn allocate_slots(&mut self, slot_count: usize) { 74 | self.count 75 | .resize(slot_count, self.last_count.wrapping_sub(self.valid_count)); 76 | } 77 | 78 | #[inline] 79 | fn update_validity(&mut self) { 80 | self.last_count = self.last_count.wrapping_add(1); 81 | } 82 | 83 | #[inline] 84 | fn is_slot_valid(&self, slot_id: usize) -> bool { 85 | self.last_count.wrapping_sub(self.count[slot_id]) < self.valid_count 86 | } 87 | 88 | #[inline] 89 | fn validate_slot(&mut self, slot_id: usize) { 90 | self.count[slot_id] = self.last_count; 91 | } 92 | 93 | #[inline] 94 | fn invalidate_slot(&mut self, slot_id: usize) { 95 | self.count[slot_id] = self.last_count - self.valid_count 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow/src/mem/cache/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod cached_memory_access; 2 | pub mod cached_vat; 3 | 4 | #[cfg(feature = "std")] 5 | pub mod timed_validator; 6 | 7 | pub mod count_validator; 8 | 9 | mod page_cache; 10 | mod tlb_cache; 11 | 12 | #[doc(hidden)] 13 | pub use cached_memory_access::*; 14 | #[doc(hidden)] 15 | pub use cached_vat::*; 16 | 17 | #[cfg(feature = "std")] 18 | #[doc(hidden)] 19 | pub use timed_validator::*; 20 | 21 | #[doc(hidden)] 22 | pub use count_validator::*; 23 | 24 | #[cfg(feature = "std")] 25 | pub type DefaultCacheValidator = TimedCacheValidator; 26 | #[cfg(not(feature = "std"))] 27 | pub type DefaultCacheValidator = CountCacheValidator; 28 | 29 | use crate::types::PageType; 30 | 31 | /// Validators are used when working with caches and determine for how long 32 | /// a specific cache entry stays valid. 33 | pub trait CacheValidator 34 | where 35 | Self: Send, 36 | { 37 | fn allocate_slots(&mut self, slot_count: usize); 38 | fn update_validity(&mut self); 39 | fn is_slot_valid(&self, slot_id: usize) -> bool; 40 | fn validate_slot(&mut self, slot_id: usize); 41 | fn invalidate_slot(&mut self, slot_id: usize); 42 | } 43 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow/src/mem/cache/timed_validator.rs: -------------------------------------------------------------------------------- 1 | /*! 2 | Validators are used when working with caches and determine for how long 3 | a specific cache entry stays valid. 4 | 5 | This validator limits the cache time based on an actual time instant. 6 | Internally it uses the [coarsetime](https://docs.rs/coarsetime/0.1.14/coarsetime/) crate as a less 7 | computation intensive alternative for [std::time](https://doc.rust-lang.org/std/time/index.html). 8 | Therefor the Duration has to be converted (e.g. via the .into() trait) when constructing this validator. 9 | 10 | The default implementation will set the cache time to 1 second. 11 | */ 12 | use std::prelude::v1::*; 13 | 14 | use super::CacheValidator; 15 | use coarsetime::{Duration, Instant}; 16 | 17 | /// Validator for limiting the cache time based on a time `Instant` 18 | /// 19 | /// # Remarks 20 | /// 21 | /// This validator is only available when being compiled with `std`. 22 | /// When using `no_std` you might want to use another validator. 23 | /// TODO: add other validators here 24 | #[derive(Clone)] 25 | pub struct TimedCacheValidator { 26 | time: Vec, 27 | valid_time: Duration, 28 | last_time: Instant, 29 | } 30 | 31 | /// Creates a validator with a cache timeout of 1 second. 32 | impl Default for TimedCacheValidator { 33 | fn default() -> Self { 34 | Self::new(Duration::from_millis(1000)) 35 | } 36 | } 37 | 38 | impl TimedCacheValidator { 39 | /// Creates a new TimedCacheValidator with a customizable Duration. 40 | /// 41 | /// # Examples: 42 | /// ``` 43 | /// use std::time::Duration; 44 | /// use memflow::mem::TimedCacheValidator; 45 | /// 46 | /// let _ = TimedCacheValidator::new(Duration::from_millis(5000).into()); 47 | /// ``` 48 | pub fn new(valid_time: Duration) -> Self { 49 | Self { 50 | time: vec![], 51 | valid_time, 52 | last_time: Instant::now(), 53 | } 54 | } 55 | } 56 | 57 | impl CacheValidator for TimedCacheValidator { 58 | #[inline] 59 | fn allocate_slots(&mut self, slot_count: usize) { 60 | self.time 61 | .resize(slot_count, self.last_time - self.valid_time); 62 | } 63 | 64 | #[inline] 65 | fn update_validity(&mut self) { 66 | self.last_time = Instant::now() 67 | } 68 | 69 | #[inline] 70 | fn is_slot_valid(&self, slot_id: usize) -> bool { 71 | self.last_time.duration_since(self.time[slot_id]) <= self.valid_time 72 | } 73 | 74 | #[inline] 75 | fn validate_slot(&mut self, slot_id: usize) { 76 | self.time[slot_id] = self.last_time; 77 | } 78 | 79 | #[inline] 80 | fn invalidate_slot(&mut self, slot_id: usize) { 81 | self.time[slot_id] = self.last_time - self.valid_time 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow/src/mem/mod.rs: -------------------------------------------------------------------------------- 1 | /*! 2 | This module covers all implementations and traits related to 3 | reading/writing [physical](phys/index.html) and [virtual](virt/index.html) memory. 4 | 5 | The [cache](cache/index.html) module contains all caching related 6 | implementations. The caches just wrap the physical and virtual accessors 7 | and are themselves a memory backend. 8 | 9 | TODO: more documentation 10 | */ 11 | 12 | pub mod cache; 13 | pub mod mem_map; 14 | pub mod phys_mem; 15 | pub mod phys_mem_batcher; 16 | pub mod virt_mem; 17 | pub mod virt_mem_batcher; 18 | pub mod virt_translate; 19 | 20 | #[cfg(any(feature = "dummy_mem", test))] 21 | pub mod dummy; 22 | 23 | #[doc(hidden)] 24 | pub use cache::*; // TODO: specify pub declarations 25 | #[doc(hidden)] 26 | pub use mem_map::MemoryMap; 27 | #[doc(hidden)] 28 | pub use phys_mem::{ 29 | CloneablePhysicalMemory, PhysicalMemory, PhysicalMemoryBox, PhysicalMemoryMetadata, 30 | PhysicalReadData, PhysicalReadIterator, PhysicalWriteData, PhysicalWriteIterator, 31 | }; 32 | #[doc(hidden)] 33 | pub use phys_mem_batcher::PhysicalMemoryBatcher; 34 | #[doc(hidden)] 35 | pub use virt_mem::{VirtualDMA, VirtualMemory, VirtualReadData, VirtualWriteData}; 36 | #[doc(hidden)] 37 | pub use virt_mem_batcher::VirtualMemoryBatcher; 38 | #[doc(hidden)] 39 | pub use virt_translate::{DirectTranslate, VirtualTranslate}; 40 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow/src/mem/phys_mem_batcher.rs: -------------------------------------------------------------------------------- 1 | use std::prelude::v1::*; 2 | 3 | use crate::error::Result; 4 | use crate::mem::phys_mem::{ 5 | PhysicalMemory, PhysicalReadData, PhysicalReadIterator, PhysicalWriteData, 6 | PhysicalWriteIterator, 7 | }; 8 | use crate::types::PhysicalAddress; 9 | 10 | use dataview::Pod; 11 | 12 | pub struct PhysicalMemoryBatcher<'a, T: PhysicalMemory> { 13 | pmem: &'a mut T, 14 | read_list: Vec>, 15 | write_list: Vec>, 16 | } 17 | 18 | impl<'a, T: PhysicalMemory> PhysicalMemoryBatcher<'a, T> { 19 | pub fn new(pmem: &'a mut T) -> Self { 20 | Self { 21 | pmem, 22 | read_list: vec![], 23 | write_list: vec![], 24 | } 25 | } 26 | 27 | pub fn read_prealloc(&mut self, capacity: usize) -> &mut Self { 28 | self.read_list.reserve(capacity); 29 | self 30 | } 31 | 32 | pub fn commit_rw(&mut self) -> Result<()> { 33 | if !self.read_list.is_empty() { 34 | self.pmem.phys_read_raw_list(&mut self.read_list)?; 35 | self.read_list.clear(); 36 | } 37 | 38 | if !self.write_list.is_empty() { 39 | self.pmem.phys_write_raw_list(&self.write_list)?; 40 | self.write_list.clear(); 41 | } 42 | 43 | Ok(()) 44 | } 45 | 46 | #[inline] 47 | pub fn read_raw_iter>(&mut self, iter: VI) -> &mut Self { 48 | self.read_list.extend(iter); 49 | self 50 | } 51 | 52 | #[inline] 53 | pub fn write_raw_iter>(&mut self, iter: VI) -> &mut Self { 54 | self.write_list.extend(iter); 55 | self 56 | } 57 | 58 | // read helpers 59 | #[inline] 60 | pub fn read_raw_into<'b: 'a>(&mut self, addr: PhysicalAddress, out: &'b mut [u8]) -> &mut Self { 61 | self.read_raw_iter(Some(PhysicalReadData(addr, out)).into_iter()) 62 | } 63 | 64 | #[inline] 65 | pub fn read_into<'b: 'a, F: Pod + ?Sized>( 66 | &mut self, 67 | addr: PhysicalAddress, 68 | out: &'b mut F, 69 | ) -> &mut Self { 70 | self.read_raw_into(addr, out.as_bytes_mut()) 71 | } 72 | 73 | // write helpers 74 | #[inline] 75 | pub fn write_raw_into<'b: 'a>(&mut self, addr: PhysicalAddress, out: &'b [u8]) -> &mut Self { 76 | self.write_raw_iter(Some(PhysicalWriteData(addr, out)).into_iter()) 77 | } 78 | 79 | #[inline] 80 | pub fn write_into<'b: 'a, F: Pod + ?Sized>( 81 | &mut self, 82 | addr: PhysicalAddress, 83 | out: &'b F, 84 | ) -> &mut Self { 85 | self.write_raw_into(addr, out.as_bytes()) 86 | } 87 | } 88 | 89 | impl<'a, T: PhysicalMemory> Drop for PhysicalMemoryBatcher<'a, T> { 90 | fn drop(&mut self) { 91 | let _ = self.commit_rw(); 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow/src/mem/virt_mem_batcher.rs: -------------------------------------------------------------------------------- 1 | use std::prelude::v1::*; 2 | 3 | use crate::error::PartialResult; 4 | use crate::mem::virt_mem::{ 5 | VirtualMemory, VirtualReadData, VirtualReadIterator, VirtualWriteData, VirtualWriteIterator, 6 | }; 7 | use crate::types::Address; 8 | 9 | use dataview::Pod; 10 | 11 | pub struct VirtualMemoryBatcher<'a, T: VirtualMemory> { 12 | vmem: &'a mut T, 13 | read_list: Vec>, 14 | write_list: Vec>, 15 | } 16 | 17 | impl<'a, T: VirtualMemory> VirtualMemoryBatcher<'a, T> { 18 | pub fn new(vmem: &'a mut T) -> Self { 19 | Self { 20 | vmem, 21 | read_list: vec![], 22 | write_list: vec![], 23 | } 24 | } 25 | 26 | pub fn commit_rw(&mut self) -> PartialResult<()> { 27 | if !self.read_list.is_empty() { 28 | self.vmem.virt_read_raw_list(&mut self.read_list)?; 29 | self.read_list.clear(); 30 | } 31 | 32 | if !self.write_list.is_empty() { 33 | self.vmem.virt_write_raw_list(&self.write_list)?; 34 | self.write_list.clear(); 35 | } 36 | 37 | Ok(()) 38 | } 39 | 40 | pub fn read_raw_iter>(&mut self, iter: VI) -> &mut Self { 41 | self.read_list.extend(iter); 42 | self 43 | } 44 | 45 | pub fn write_raw_iter>(&mut self, iter: VI) -> &mut Self { 46 | self.write_list.extend(iter); 47 | self 48 | } 49 | 50 | // read helpers 51 | pub fn read_raw_into<'b: 'a>(&mut self, addr: Address, out: &'b mut [u8]) -> &mut Self { 52 | self.read_raw_iter(Some(VirtualReadData(addr, out)).into_iter()) 53 | } 54 | 55 | pub fn read_into<'b: 'a, F: Pod + ?Sized>( 56 | &mut self, 57 | addr: Address, 58 | out: &'b mut F, 59 | ) -> &mut Self { 60 | self.read_raw_into(addr, out.as_bytes_mut()) 61 | } 62 | 63 | // write helpers 64 | pub fn write_raw_into<'b: 'a>(&mut self, addr: Address, out: &'b [u8]) -> &mut Self { 65 | self.write_raw_iter(Some(VirtualWriteData(addr, out)).into_iter()) 66 | } 67 | 68 | pub fn write_into<'b: 'a, F: Pod + ?Sized>(&mut self, addr: Address, out: &'b F) -> &mut Self { 69 | self.write_raw_into(addr, out.as_bytes()) 70 | } 71 | } 72 | 73 | impl<'a, T: VirtualMemory> Drop for VirtualMemoryBatcher<'a, T> { 74 | fn drop(&mut self) { 75 | let _ = self.commit_rw(); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow/src/mem/virt_translate/direct_translate.rs: -------------------------------------------------------------------------------- 1 | use super::VirtualTranslate; 2 | use crate::architecture::ScopedVirtualTranslate; 3 | use crate::error::Error; 4 | use crate::iter::SplitAtIndex; 5 | use crate::mem::PhysicalMemory; 6 | use crate::types::{Address, PhysicalAddress}; 7 | use bumpalo::Bump; 8 | 9 | /* 10 | The `DirectTranslate` struct provides a default implementation for `VirtualTranslate` for physical memory. 11 | */ 12 | #[derive(Debug, Default)] 13 | pub struct DirectTranslate { 14 | arena: Bump, 15 | } 16 | 17 | impl DirectTranslate { 18 | pub fn new() -> Self { 19 | Self { 20 | arena: Bump::with_capacity(0x4000), 21 | } 22 | } 23 | } 24 | 25 | impl Clone for DirectTranslate { 26 | fn clone(&self) -> Self { 27 | Self::new() 28 | } 29 | } 30 | 31 | impl VirtualTranslate for DirectTranslate { 32 | fn virt_to_phys_iter( 33 | &mut self, 34 | phys_mem: &mut T, 35 | translator: &D, 36 | addrs: VI, 37 | out: &mut VO, 38 | out_fail: &mut FO, 39 | ) where 40 | T: PhysicalMemory + ?Sized, 41 | B: SplitAtIndex, 42 | D: ScopedVirtualTranslate, 43 | VI: Iterator, 44 | VO: Extend<(PhysicalAddress, B)>, 45 | FO: Extend<(Error, Address, B)>, 46 | { 47 | self.arena.reset(); 48 | translator.virt_to_phys_iter(phys_mem, addrs, out, out_fail, &self.arena) 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow/src/process/mod.rs: -------------------------------------------------------------------------------- 1 | /*! 2 | Traits for OS independent process abstractions. 3 | */ 4 | 5 | use std::prelude::v1::*; 6 | 7 | use crate::architecture::ArchitectureObj; 8 | use crate::types::Address; 9 | 10 | /// Trait describing a operating system 11 | pub trait OperatingSystem {} 12 | 13 | /// Type alias for a PID. 14 | pub type PID = u32; 15 | 16 | /// Trait describing OS independent process information. 17 | pub trait OsProcessInfo { 18 | /// Returns the base address of this process. 19 | /// 20 | /// # Remarks 21 | /// 22 | /// On Windows this will return the address of the [`_EPROCESS`](https://www.nirsoft.net/kernel_struct/vista/EPROCESS.html) structure. 23 | fn address(&self) -> Address; 24 | 25 | /// Returns the pid of this process. 26 | fn pid(&self) -> PID; 27 | 28 | /// Returns the name of the process. 29 | /// 30 | /// # Remarks 31 | /// 32 | /// On Windows this will be clamped to 16 characters. 33 | fn name(&self) -> String; 34 | 35 | /// Returns the architecture of the target system. 36 | fn sys_arch(&self) -> ArchitectureObj; 37 | 38 | /// Returns the architecture of the process. 39 | /// 40 | /// # Remarks 41 | /// 42 | /// Specifically on 64-bit systems this could be different 43 | /// to the `sys_arch` in case the process is an emulated 32-bit process. 44 | /// 45 | /// On windows this technique is called [`WOW64`](https://docs.microsoft.com/en-us/windows/win32/winprog64/wow64-implementation-details). 46 | fn proc_arch(&self) -> ArchitectureObj; 47 | } 48 | 49 | // TODO: Range impl for base to size? 50 | /// Trait describing OS independent module information. 51 | pub trait OsProcessModuleInfo { 52 | /// Returns the address of the module header. 53 | /// 54 | /// # Remarks 55 | /// 56 | /// On Windows this will return the address where the [`PEB`](https://docs.microsoft.com/en-us/windows/win32/api/winternl/ns-winternl-peb) entry is stored. 57 | fn address(&self) -> Address; 58 | 59 | /// Returns the base address of the parent process. 60 | /// 61 | /// # Remarks 62 | /// 63 | /// This method is analog to the `OsProcessInfo::address` function. 64 | fn parent_process(&self) -> Address; 65 | 66 | /// Returns the actual base address of this module. 67 | /// 68 | /// # Remarks 69 | /// 70 | /// The base address is contained in the virtual address range of the process 71 | /// this module belongs to. 72 | fn base(&self) -> Address; 73 | 74 | /// Returns the size of the module. 75 | fn size(&self) -> usize; 76 | 77 | /// Returns the full name of the module. 78 | fn name(&self) -> String; 79 | } 80 | 81 | // TODO: Exports / Sections / etc 82 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow/src/types/mod.rs: -------------------------------------------------------------------------------- 1 | /*! 2 | Module with basic types used in memflow. 3 | 4 | This module contains types for handling virtual and physical addresses. 5 | It also contains types for handling pointers, pages and 6 | it exposes different size helpers. 7 | */ 8 | 9 | pub mod address; 10 | #[doc(hidden)] 11 | pub use address::Address; 12 | 13 | pub mod size; 14 | 15 | pub mod page; 16 | #[doc(hidden)] 17 | pub use page::{Page, PageType}; 18 | 19 | pub mod physical_address; 20 | #[doc(hidden)] 21 | pub use physical_address::PhysicalAddress; 22 | 23 | pub mod pointer32; 24 | #[doc(hidden)] 25 | pub use pointer32::Pointer32; 26 | 27 | pub mod pointer64; 28 | #[doc(hidden)] 29 | pub use pointer64::Pointer64; 30 | 31 | pub mod byte_swap; 32 | #[doc(hidden)] 33 | pub use byte_swap::ByteSwap; 34 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow/src/types/page.rs: -------------------------------------------------------------------------------- 1 | /*! 2 | This module contains data structures related to information about a page. 3 | */ 4 | 5 | use super::Address; 6 | 7 | bitflags! { 8 | /// Describes the type of a page using a bitflag. 9 | #[cfg_attr(feature = "serde", derive(::serde::Serialize, ::serde::Deserialize))] 10 | #[repr(transparent)] 11 | pub struct PageType: u8 { 12 | /// The page explicitly has no flags. 13 | const NONE = 0b0000_0000; 14 | /// The page type is not known. 15 | const UNKNOWN = 0b0000_0001; 16 | /// The page contains page table entries. 17 | const PAGE_TABLE = 0b0000_0010; 18 | /// The page is a writeable page. 19 | const WRITEABLE = 0b0000_0100; 20 | /// The page is read only. 21 | const READ_ONLY = 0b0000_1000; 22 | /// The page is not executable. 23 | const NOEXEC = 0b0001_0000; 24 | } 25 | } 26 | 27 | impl PageType { 28 | pub fn write(mut self, flag: bool) -> Self { 29 | self &= !(PageType::WRITEABLE | PageType::READ_ONLY | PageType::UNKNOWN); 30 | if flag { 31 | self | PageType::WRITEABLE 32 | } else { 33 | self | PageType::READ_ONLY 34 | } 35 | } 36 | 37 | pub fn noexec(mut self, flag: bool) -> Self { 38 | self &= !(PageType::NOEXEC); 39 | if flag { 40 | self | PageType::NOEXEC 41 | } else { 42 | self 43 | } 44 | } 45 | 46 | pub fn page_table(mut self, flag: bool) -> Self { 47 | self &= !(PageType::PAGE_TABLE | PageType::UNKNOWN); 48 | if flag { 49 | self | PageType::PAGE_TABLE 50 | } else { 51 | self 52 | } 53 | } 54 | } 55 | 56 | impl Default for PageType { 57 | fn default() -> Self { 58 | PageType::UNKNOWN 59 | } 60 | } 61 | 62 | /// A `Page` holds information about a memory page. 63 | /// 64 | /// More information about paging can be found [here](https://en.wikipedia.org/wiki/Paging). 65 | #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug)] 66 | pub struct Page { 67 | /// Contains the page type (see above). 68 | pub page_type: PageType, 69 | /// Contains the base address of this page. 70 | pub page_base: Address, 71 | /// Contains the size of this page. 72 | pub page_size: usize, 73 | } 74 | 75 | impl Page { 76 | /// A page object that is invalid. 77 | pub const INVALID: Page = Page { 78 | page_type: PageType::UNKNOWN, 79 | page_base: Address::INVALID, 80 | page_size: 0, 81 | }; 82 | 83 | /// Returns a page that is invalid. 84 | pub const fn invalid() -> Self { 85 | Self::INVALID 86 | } 87 | 88 | /// Checks wether the page is valid or not. 89 | pub fn is_valid(&self) -> bool { 90 | self.page_base.is_valid() && self.page_size != 0 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow/src/types/size.rs: -------------------------------------------------------------------------------- 1 | /*! 2 | This module contains helper functions for creating various byte sizes. 3 | All function are const and will be [optimized](https://rust.godbolt.org/z/T6LiwJ) by rustc. 4 | */ 5 | 6 | /// Returns a usize representing the length in bytes from the given number of kilobytes. 7 | pub const fn kb(kb: usize) -> usize { 8 | kb * 1024 9 | } 10 | 11 | /// Returns a usize representing the length in bytes from the given number of kilobits. 12 | pub const fn kib(kib: usize) -> usize { 13 | kb(kib) / 8 14 | } 15 | 16 | /// Returns a usize representing the length in bytes from the given number of megabytes. 17 | pub const fn mb(mb: usize) -> usize { 18 | kb(mb) * 1024 19 | } 20 | 21 | /// Returns a usize representing the length in bytes from the given number of megabits. 22 | pub const fn mib(mib: usize) -> usize { 23 | mb(mib) / 8 24 | } 25 | 26 | /// Returns a usize representing the length in bytes from the given number of gigabytes. 27 | pub const fn gb(gb: usize) -> usize { 28 | mb(gb) * 1024 29 | } 30 | 31 | /// Returns a usize representing the length in bytes from the given number of gigabits. 32 | pub const fn gib(gib: usize) -> usize { 33 | gb(gib) / 8 34 | } 35 | 36 | #[cfg(test)] 37 | mod tests { 38 | use super::*; 39 | 40 | #[test] 41 | fn test_from() { 42 | assert_eq!(kb(20), 20480usize); 43 | assert_eq!(kib(123), 15744usize); 44 | assert_eq!(mb(20), 20_971_520_usize); 45 | assert_eq!(mib(52), 6_815_744_usize); 46 | assert_eq!(gb(20), 21_474_836_480_usize); 47 | assert_eq!(gib(52), 6_979_321_856_usize); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/nostd-test/.cargo/config: -------------------------------------------------------------------------------- 1 | 2 | [unstable] 3 | build-std = ["core", "compiler_builtins", "alloc"] 4 | features = ["host_dep"] 5 | 6 | [build] 7 | target = "x86_64-unknown-uefi" 8 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/nostd-test/.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/nostd-test/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "nostd-test" 3 | version = "0.1.5" 4 | authors = ["Aurimas Blažulionis <0x60@pm.me>"] 5 | edition = "2018" 6 | homepage = "https://memflow.github.io" 7 | repository = "https://github.com/memflow/memflow" 8 | license-file = "../LICENSE" 9 | publish = false 10 | 11 | [profile.release] 12 | panic = "abort" 13 | 14 | [profile.dev] 15 | panic = "abort" 16 | 17 | [dependencies] 18 | rlibc = "1.0.0" 19 | uefi = "0.6.0" 20 | uefi-services = "0.3.0" 21 | log = "0.4" 22 | memflow = { path = "../memflow", default-features = false } 23 | memflow-win32 = { path = "../memflow-win32/", default-features = false, features = ["embed_offsets"] } 24 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/nostd-test/rust-toolchain: -------------------------------------------------------------------------------- 1 | nightly 2 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/nostd-test/src/main.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![no_main] 3 | #![feature(abi_efiapi)] 4 | use core::*; 5 | use uefi::prelude::*; 6 | 7 | #[macro_use] 8 | extern crate alloc; 9 | 10 | extern crate rlibc; 11 | 12 | use crate::alloc::vec::Vec; 13 | 14 | use log::*; 15 | 16 | use uefi::{ 17 | data_types::{CStr16, Char16}, 18 | proto::Protocol, 19 | unsafe_guid, Handle, Status, 20 | }; 21 | 22 | #[entry] 23 | fn efi_main(handle: Handle, st: SystemTable) -> Status { 24 | uefi_services::init(&st).expect_success("Failed to initialize utilities"); 25 | 26 | info!("memflow EFI test"); 27 | 28 | let bt = st.boot_services(); 29 | 30 | Status::SUCCESS 31 | } 32 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/runner.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [[ ! -z $RUST_SUDO ]]; then 4 | 5 | exec sudo -E $@ 6 | 7 | else 8 | 9 | if [[ ! -z $RUST_SETPTRACE ]]; then 10 | if [[ -z "$(getcap $1 | grep -i cap_sys_ptrace)" ]]; then 11 | echo "setting CAP_SYS_PTRACE=ep for $1" 12 | sudo setcap 'CAP_SYS_PTRACE=ep' $1 13 | fi 14 | fi 15 | 16 | exec $@ 17 | 18 | fi 19 | -------------------------------------------------------------------------------- /apex_dma/memory.cpp: -------------------------------------------------------------------------------- 1 | #include "memory.h" 2 | 3 | //Credits: learn_more, stevemk14ebr 4 | size_t findPattern(const PBYTE rangeStart, size_t len, const char* pattern) 5 | { 6 | size_t l = strlen(pattern); 7 | PBYTE patt_base = static_cast(malloc(l >> 1)); 8 | PBYTE msk_base = static_cast(malloc(l >> 1)); 9 | PBYTE pat = patt_base; 10 | PBYTE msk = msk_base; 11 | if (pat && msk) 12 | { 13 | l = 0; 14 | while (*pattern) 15 | { 16 | if (*pattern == ' ') 17 | pattern++; 18 | if (!*pattern) 19 | break; 20 | if (*(PBYTE)pattern == (BYTE)'\?') 21 | { 22 | *pat++ = 0; 23 | *msk++ = '?'; 24 | pattern += ((*(PWORD)pattern == (WORD)'\?\?') ? 2 : 1); 25 | } 26 | else 27 | { 28 | *pat++ = getByte(pattern); 29 | *msk++ = 'x'; 30 | pattern += 2; 31 | } 32 | l++; 33 | } 34 | *msk = 0; 35 | pat = patt_base; 36 | msk = msk_base; 37 | for (size_t n = 0; n < (len - l); ++n) 38 | { 39 | if (isMatch(rangeStart + n, patt_base, msk_base)) 40 | { 41 | free(patt_base); 42 | free(msk_base); 43 | return n; 44 | } 45 | } 46 | free(patt_base); 47 | free(msk_base); 48 | } 49 | return -1; 50 | } 51 | 52 | uint64_t Memory::get_proc_baseaddr() 53 | { 54 | return proc.baseaddr; 55 | } 56 | 57 | process_status Memory::get_proc_status() 58 | { 59 | return status; 60 | } 61 | 62 | void Memory::check_proc() 63 | { 64 | if (status == process_status::FOUND_READY) 65 | { 66 | short c; 67 | Read(proc.baseaddr, c); 68 | 69 | if (c != 0x5A4D) 70 | { 71 | status = process_status::FOUND_NO_ACCESS; 72 | close_proc(); 73 | } 74 | } 75 | } 76 | 77 | void Memory::open_proc(const char* name) 78 | { 79 | if(!conn) 80 | { 81 | ConnectorInventory *inv = inventory_scan(); 82 | conn = inventory_create_connector(inv, "qemu_procfs", ""); 83 | inventory_free(inv); 84 | } 85 | 86 | if (conn) 87 | { 88 | if(!kernel) 89 | { 90 | kernel = kernel_build(conn); 91 | } 92 | 93 | if(kernel) 94 | { 95 | Kernel *tmp_ker = kernel_clone(kernel); 96 | proc.hProcess = kernel_into_process(tmp_ker, name); 97 | } 98 | 99 | if (proc.hProcess) 100 | { 101 | Win32ModuleInfo *module = process_module_info(proc.hProcess, name); 102 | 103 | if (module) 104 | { 105 | OsProcessModuleInfoObj *obj = module_info_trait(module); 106 | proc.baseaddr = os_process_module_base(obj); 107 | os_process_module_free(obj); 108 | mem = process_virt_mem(proc.hProcess); 109 | status = process_status::FOUND_READY; 110 | } 111 | else 112 | { 113 | status = process_status::FOUND_NO_ACCESS; 114 | close_proc(); 115 | } 116 | } 117 | else 118 | { 119 | status = process_status::NOT_FOUND; 120 | } 121 | } 122 | else 123 | { 124 | printf("Can't create connector\n"); 125 | exit(0); 126 | } 127 | } 128 | 129 | void Memory::close_proc() 130 | { 131 | if (proc.hProcess) 132 | { 133 | process_free(proc.hProcess); 134 | virt_free(mem); 135 | } 136 | 137 | proc.hProcess = 0; 138 | proc.baseaddr = 0; 139 | mem = 0; 140 | } 141 | 142 | uint64_t Memory::ScanPointer(uint64_t ptr_address, const uint32_t offsets[], int level) 143 | { 144 | if (!ptr_address) 145 | return 0; 146 | 147 | uint64_t lvl = ptr_address; 148 | 149 | for (int i = 0; i < level; i++) 150 | { 151 | if (!Read(lvl, lvl) || !lvl) 152 | return 0; 153 | lvl += offsets[i]; 154 | } 155 | 156 | return lvl; 157 | } -------------------------------------------------------------------------------- /apex_dma/memory.h: -------------------------------------------------------------------------------- 1 | #include "memflow_win32.h" 2 | #include 3 | #include 4 | #include 5 | 6 | #define INRANGE(x,a,b) (x >= a && x <= b) 7 | #define getBits( x ) (INRANGE(x,'0','9') ? (x - '0') : ((x&(~0x20)) - 'A' + 0xa)) 8 | #define getByte( x ) (getBits(x[0]) << 4 | getBits(x[1])) 9 | 10 | typedef uint8_t* PBYTE; 11 | typedef uint8_t BYTE; 12 | typedef unsigned long DWORD; 13 | typedef unsigned short WORD; 14 | typedef WORD *PWORD; 15 | 16 | static CloneablePhysicalMemoryObj *conn = 0; 17 | static Kernel *kernel = 0; 18 | 19 | inline bool isMatch(const PBYTE addr, const PBYTE pat, const PBYTE msk) 20 | { 21 | size_t n = 0; 22 | while (addr[n] == pat[n] || msk[n] == (BYTE)'?') 23 | { 24 | if (!msk[++n]) 25 | { 26 | return true; 27 | } 28 | } 29 | return false; 30 | } 31 | 32 | size_t findPattern(const PBYTE rangeStart, size_t len, const char* pattern); 33 | 34 | typedef struct Process 35 | { 36 | Win32Process* hProcess = 0; 37 | uint64_t baseaddr = 0; 38 | }Process; 39 | 40 | enum class process_status : BYTE 41 | { 42 | NOT_FOUND, 43 | FOUND_NO_ACCESS, 44 | FOUND_READY 45 | }; 46 | 47 | class Memory 48 | { 49 | private: 50 | Process proc; 51 | VirtualMemoryObj* mem; 52 | process_status status = process_status::NOT_FOUND; 53 | std::mutex m; 54 | public: 55 | ~Memory() { if (mem) virt_free(mem); if (proc.hProcess) process_free(proc.hProcess); } 56 | 57 | uint64_t get_proc_baseaddr(); 58 | 59 | process_status get_proc_status(); 60 | 61 | void check_proc(); 62 | 63 | void open_proc(const char* name); 64 | 65 | void close_proc(); 66 | 67 | template 68 | bool Read(uint64_t address, T& out); 69 | 70 | template 71 | bool ReadArray(uint64_t address, T out[], size_t len); 72 | 73 | template 74 | bool Write(uint64_t address, const T& value); 75 | 76 | template 77 | bool WriteArray(uint64_t address, const T value[], size_t len); 78 | 79 | uint64_t ScanPointer(uint64_t ptr_address, const uint32_t offsets[], int level); 80 | }; 81 | 82 | template 83 | inline bool Memory::Read(uint64_t address, T& out) 84 | { 85 | std::lock_guard l(m); 86 | return mem && virt_read_raw_into(mem, address, (uint8_t*)&out, sizeof(T)) == 0; 87 | } 88 | 89 | template 90 | inline bool Memory::ReadArray(uint64_t address, T out[], size_t len) 91 | { 92 | std::lock_guard l(m); 93 | return mem && virt_read_raw_into(mem, address, (uint8_t*)out, sizeof(T) * len) == 0; 94 | } 95 | 96 | template 97 | inline bool Memory::Write(uint64_t address, const T& value) 98 | { 99 | std::lock_guard l(m); 100 | return mem && virt_write_raw(mem, address, (uint8_t*)&value, sizeof(T)) == 0; 101 | } 102 | 103 | template 104 | inline bool Memory::WriteArray(uint64_t address, const T value[], size_t len) 105 | { 106 | std::lock_guard l(m); 107 | return mem && virt_write_raw(mem, address, (uint8_t*)value, sizeof(T) * len) == 0; 108 | } -------------------------------------------------------------------------------- /apex_dma/performance: -------------------------------------------------------------------------------- 1 | performance 2 | -------------------------------------------------------------------------------- /apex_dma/prediction.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include "Game.h" 3 | 4 | struct PredictCtx 5 | { 6 | Vector StartPos; 7 | Vector TargetPos; 8 | Vector TargetVel; 9 | float BulletSpeed; 10 | float BulletGravity; 11 | 12 | Vector2D AimAngles; 13 | }; 14 | 15 | Vector ExtrapolatePos(const PredictCtx& Ctx, float Time) 16 | { 17 | return Ctx.TargetPos + (Ctx.TargetVel * Time); 18 | } 19 | 20 | bool OptimalPitch(const PredictCtx& Ctx, const Vector2D& Dir2D, float* OutPitch) 21 | { 22 | float Vel = Ctx.BulletSpeed, Grav = Ctx.BulletGravity, DirX = Dir2D.x, DirY = Dir2D.y; 23 | float Root = Vel * Vel * Vel * Vel - Grav * (Grav * DirX * DirX + 2.f * DirY * Vel * Vel); 24 | if (Root >= 0.f) { *OutPitch = atanf((Vel * Vel - sqrt(Root)) / (Grav * DirX)); return true; } 25 | return false; 26 | } 27 | 28 | bool SolveTrajectory(PredictCtx& Ctx, const Vector& ExtrPos, float* TravelTime) 29 | { 30 | Vector Dir = ExtrPos - Ctx.StartPos; 31 | Vector2D Dir2D = { sqrtf(Dir.x * Dir.x + Dir.y * Dir.y), Dir.z }; 32 | 33 | float CurPitch; 34 | if (!OptimalPitch(Ctx, Dir2D, &CurPitch)) 35 | { 36 | return false; 37 | } 38 | 39 | *TravelTime = Dir2D.x / (cosf(CurPitch) * Ctx.BulletSpeed); 40 | Ctx.AimAngles.y = atan2f(Dir.y, Dir.x); 41 | Ctx.AimAngles.x = CurPitch; 42 | return true; 43 | } 44 | 45 | bool BulletPredict(PredictCtx& Ctx) 46 | { 47 | float MAX_TIME = 1.f, TIME_STEP = (1.f / 256.f); 48 | for (float CurrentTime = 0.f; CurrentTime <= MAX_TIME; CurrentTime += TIME_STEP) 49 | { 50 | float TravelTime; 51 | Vector ExtrPos = ExtrapolatePos(Ctx, CurrentTime); 52 | if (!SolveTrajectory(Ctx, ExtrPos, &TravelTime)) 53 | { 54 | return false; 55 | } 56 | 57 | if (TravelTime < CurrentTime) 58 | { 59 | Ctx.AimAngles = { -RAD2DEG(Ctx.AimAngles.x), RAD2DEG(Ctx.AimAngles.y) }; 60 | return true; 61 | } 62 | } 63 | return false; 64 | } 65 | -------------------------------------------------------------------------------- /apex_guest/Client/.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /apex_guest/Client/Client.rc: -------------------------------------------------------------------------------- 1 | // Script di risorse generato con Microsoft Visual C++. 2 | // 3 | 4 | #include "resource.h" 5 | 6 | #define APSTUDIO_READONLY_SYMBOLS 7 | ///////////////////////////////////////////////////////////////////////////// 8 | // 9 | // Generato dalla risorsa TEXTINCLUDE 2. 10 | // 11 | #include "winres.h" 12 | 13 | ///////////////////////////////////////////////////////////////////////////// 14 | #undef APSTUDIO_READONLY_SYMBOLS 15 | 16 | ///////////////////////////////////////////////////////////////////////////// 17 | // Risorse di Italiano (Italia) 18 | 19 | #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) 20 | LANGUAGE 16, 1 21 | 22 | #ifdef APSTUDIO_INVOKED 23 | ///////////////////////////////////////////////////////////////////////////// 24 | // 25 | // TEXTINCLUDE 26 | // 27 | 28 | 1 TEXTINCLUDE 29 | BEGIN 30 | "resource.h\0" 31 | END 32 | 33 | 2 TEXTINCLUDE 34 | BEGIN 35 | "#include ""winres.h""\r\n" 36 | "\0" 37 | END 38 | 39 | 3 TEXTINCLUDE 40 | BEGIN 41 | "\r\n" 42 | "\0" 43 | END 44 | 45 | #endif // APSTUDIO_INVOKED 46 | 47 | #endif // Risorse di Italiano (Italia) 48 | ///////////////////////////////////////////////////////////////////////////// 49 | 50 | 51 | 52 | #ifndef APSTUDIO_INVOKED 53 | ///////////////////////////////////////////////////////////////////////////// 54 | // 55 | // Generato dalla risorsa TEXTINCLUDE 3. 56 | // 57 | 58 | 59 | ///////////////////////////////////////////////////////////////////////////// 60 | #endif // non APSTUDIO_INVOKED 61 | -------------------------------------------------------------------------------- /apex_guest/Client/Client.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.29403.142 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Client", "Client.vcxproj", "{9BF6CD05-63DA-49CF-905E-B82F5F24AC6E}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Release|x64 = Release|x64 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {9BF6CD05-63DA-49CF-905E-B82F5F24AC6E}.Debug|x64.ActiveCfg = Debug|x64 15 | {9BF6CD05-63DA-49CF-905E-B82F5F24AC6E}.Debug|x64.Build.0 = Debug|x64 16 | {9BF6CD05-63DA-49CF-905E-B82F5F24AC6E}.Release|x64.ActiveCfg = Release|x64 17 | {9BF6CD05-63DA-49CF-905E-B82F5F24AC6E}.Release|x64.Build.0 = Release|x64 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {D6542325-B9BC-4057-A6CD-43137A5535C1} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /apex_guest/Client/Client.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {09a8a2aa-6277-49bc-bb28-4446ac81fb47} 10 | 11 | 12 | {d82aa3aa-e029-4496-92fc-5a3e4a269824} 13 | 14 | 15 | {2a2873f6-cd40-4bf6-8249-0d7505954a3f} 16 | 17 | 18 | 19 | 20 | Source 21 | 22 | 23 | Source 24 | 25 | 26 | Source\imgui 27 | 28 | 29 | Source\imgui 30 | 31 | 32 | Source\imgui 33 | 34 | 35 | Source\imgui 36 | 37 | 38 | Source\imgui 39 | 40 | 41 | Source\imgui 42 | 43 | 44 | 45 | 46 | Headers 47 | 48 | 49 | Headers 50 | 51 | 52 | 53 | Headers\imgui 54 | 55 | 56 | Headers\imgui 57 | 58 | 59 | Headers\imgui 60 | 61 | 62 | Headers\imgui 63 | 64 | 65 | Headers\imgui 66 | 67 | 68 | Headers\imgui 69 | 70 | 71 | Headers\imgui 72 | 73 | 74 | Headers 75 | 76 | 77 | Headers\imgui 78 | 79 | 80 | Source 81 | 82 | 83 | Headers 84 | 85 | 86 | 87 | 88 | 89 | -------------------------------------------------------------------------------- /apex_guest/Client/imgui/imgui_impl_dx11.h: -------------------------------------------------------------------------------- 1 | // dear imgui: Renderer Backend for DirectX11 2 | // This needs to be used along with a Platform Backend (e.g. Win32) 3 | 4 | // Implemented features: 5 | // [X] Renderer: User texture binding. Use 'ID3D11ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID! 6 | // [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices. 7 | 8 | // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. 9 | // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. 10 | // If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp. 11 | // Read online: https://github.com/ocornut/imgui/tree/master/docs 12 | 13 | #pragma once 14 | #include "imgui.h" // IMGUI_IMPL_API 15 | 16 | struct ID3D11Device; 17 | struct ID3D11DeviceContext; 18 | 19 | IMGUI_IMPL_API bool ImGui_ImplDX11_Init(ID3D11Device* device, ID3D11DeviceContext* device_context); 20 | IMGUI_IMPL_API void ImGui_ImplDX11_Shutdown(); 21 | IMGUI_IMPL_API void ImGui_ImplDX11_NewFrame(); 22 | IMGUI_IMPL_API void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data); 23 | 24 | // Use if you want to reset your rendering device without losing Dear ImGui state. 25 | IMGUI_IMPL_API void ImGui_ImplDX11_InvalidateDeviceObjects(); 26 | IMGUI_IMPL_API bool ImGui_ImplDX11_CreateDeviceObjects(); 27 | -------------------------------------------------------------------------------- /apex_guest/Client/imgui/imgui_impl_win32.h: -------------------------------------------------------------------------------- 1 | // dear imgui: Platform Backend for Windows (standard windows API for 32 and 64 bits applications) 2 | // This needs to be used along with a Renderer (e.g. DirectX11, OpenGL3, Vulkan..) 3 | 4 | // Implemented features: 5 | // [X] Platform: Clipboard support (for Win32 this is actually part of core dear imgui) 6 | // [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'. 7 | // [X] Platform: Keyboard arrays indexed using VK_* Virtual Key Codes, e.g. ImGui::IsKeyPressed(VK_SPACE). 8 | // [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'. 9 | 10 | // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. 11 | // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. 12 | // If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp. 13 | // Read online: https://github.com/ocornut/imgui/tree/master/docs 14 | 15 | #pragma once 16 | #include "imgui.h" // IMGUI_IMPL_API 17 | 18 | IMGUI_IMPL_API bool ImGui_ImplWin32_Init(void* hwnd); 19 | IMGUI_IMPL_API void ImGui_ImplWin32_Shutdown(); 20 | IMGUI_IMPL_API void ImGui_ImplWin32_NewFrame(); 21 | 22 | // Win32 message handler your application need to call. 23 | // - Intentionally commented out in a '#if 0' block to avoid dragging dependencies on from this helper. 24 | // - You should COPY the line below into your .cpp code to forward declare the function and then you can call it. 25 | #if 0 26 | extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); 27 | #endif 28 | 29 | // DPI-related helpers (optional) 30 | // - Use to enable DPI awareness without having to create an application manifest. 31 | // - Your own app may already do this via a manifest or explicit calls. This is mostly useful for our examples/ apps. 32 | // - In theory we could call simple functions from Windows SDK such as SetProcessDPIAware(), SetProcessDpiAwareness(), etc. 33 | // but most of the functions provided by Microsoft require Windows 8.1/10+ SDK at compile time and Windows 8/10+ at runtime, 34 | // neither we want to require the user to have. So we dynamically select and load those functions to avoid dependencies. 35 | IMGUI_IMPL_API void ImGui_ImplWin32_EnableDpiAwareness(); 36 | IMGUI_IMPL_API float ImGui_ImplWin32_GetDpiScaleForHwnd(void* hwnd); // HWND hwnd 37 | IMGUI_IMPL_API float ImGui_ImplWin32_GetDpiScaleForMonitor(void* monitor); // HMONITOR monitor 38 | 39 | // Transparency related helpers (optional) [experimental] 40 | // - Use to enable alpha compositing transparency with the desktop. 41 | // - Use together with e.g. clearing your framebuffer with zero-alpha. 42 | IMGUI_IMPL_API void ImGui_ImplWin32_EnableAlphaCompositing(void* hwnd); // HWND hwnd 43 | -------------------------------------------------------------------------------- /apex_guest/Client/impl/hooking/REMOVED.txt: -------------------------------------------------------------------------------- 1 | Add your own or use minhook -------------------------------------------------------------------------------- /apex_guest/Client/impl/libraries/ImGui/LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014-2019 Omar Cornut 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. -------------------------------------------------------------------------------- /apex_guest/Client/impl/libraries/ImGui/imconfig.h: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // USER IMPLEMENTATION 3 | // This file contains compile-time options for ImGui. 4 | // Other options (memory allocation overrides, callbacks, etc.) can be set at runtime via the ImGuiIO structure - ImGui::GetIO(). 5 | //----------------------------------------------------------------------------- 6 | 7 | #pragma once 8 | 9 | //---- Define assertion handler. Defaults to calling assert(). 10 | //#define IM_ASSERT(_EXPR) MyAssert(_EXPR) 11 | 12 | //---- Define attributes of all API symbols declarations, e.g. for DLL under Windows. 13 | //#define IMGUI_API __declspec( dllexport ) 14 | //#define IMGUI_API __declspec( dllimport ) 15 | 16 | //---- Don't define obsolete functions names. Consider enabling from time to time or when updating to reduce like hood of using already obsolete function/names 17 | //#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS 18 | 19 | //---- Include imgui_user.h at the end of imgui.h 20 | //#define IMGUI_INCLUDE_IMGUI_USER_H 21 | 22 | //---- Don't implement default handlers for Windows (so as not to link with OpenClipboard() and others Win32 functions) 23 | //#define IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS 24 | //#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS 25 | 26 | //---- Don't implement demo windows functionality (ShowDemoWindow()/ShowStyleEditor()/ShowUserGuide() methods will be empty) 27 | //---- It is very strongly recommended to NOT disable the demo windows. Please read the comment at the top of imgui_demo.cpp to learn why. 28 | //#define IMGUI_DISABLE_DEMO_WINDOWS 29 | 30 | //---- Don't implement ImFormatString(), ImFormatStringV() so you can reimplement them yourself. 31 | //#define IMGUI_DISABLE_FORMAT_STRING_FUNCTIONS 32 | 33 | //---- Pack colors to BGRA instead of RGBA (remove need to post process vertex buffer in back ends) 34 | //#define IMGUI_USE_BGRA_PACKED_COLOR 35 | 36 | //---- Implement STB libraries in a namespace to avoid linkage conflicts 37 | //#define IMGUI_STB_NAMESPACE ImGuiStb 38 | 39 | //---- Define constructor and implicit cast operators to convert back<>forth from your math types and ImVec2/ImVec4. 40 | /* 41 | #define IM_VEC2_CLASS_EXTRA \ 42 | ImVec2(const MyVec2& f) { x = f.x; y = f.y; } \ 43 | operator MyVec2() const { return MyVec2(x,y); } 44 | 45 | #define IM_VEC4_CLASS_EXTRA \ 46 | ImVec4(const MyVec4& f) { x = f.x; y = f.y; z = f.z; w = f.w; } \ 47 | operator MyVec4() const { return MyVec4(x,y,z,w); } 48 | */ 49 | 50 | //---- Use 32-bit vertex indices (instead of default: 16-bit) to allow meshes with more than 64K vertices 51 | //#define ImDrawIdx unsigned int 52 | 53 | //---- Tip: You can add extra functions within the ImGui:: namespace, here or in your own headers files. 54 | //---- e.g. create variants of the ImGui::Value() helper for your low-level math types, or your own widgets/helpers. 55 | /* 56 | namespace ImGui 57 | { 58 | void Value(const char* prefix, const MyMatrix44& v, const char* float_format = NULL); 59 | } 60 | */ 61 | 62 | -------------------------------------------------------------------------------- /apex_guest/Client/impl/libraries/ImGui/imgui_impl_dx11.h: -------------------------------------------------------------------------------- 1 | // ImGui Win32 + DirectX11 binding 2 | // In this binding, ImTextureID is used to store a 'ID3D11ShaderResourceView*' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. 3 | 4 | // You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. 5 | // If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown(). 6 | // If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp. 7 | // https://github.com/ocornut/imgui 8 | 9 | #include 10 | 11 | struct ID3D11Device; 12 | struct ID3D11DeviceContext; 13 | 14 | IMGUI_API bool ImGui_ImplDX11_Init(void* hwnd, ID3D11Device* device, ID3D11DeviceContext* device_context); 15 | IMGUI_API void ImGui_ImplDX11_Shutdown(); 16 | IMGUI_API void ImGui_ImplDX11_NewFrame(); 17 | 18 | // Use if you want to reset your rendering device without losing ImGui state. 19 | IMGUI_API void ImGui_ImplDX11_InvalidateDeviceObjects(); 20 | IMGUI_API bool ImGui_ImplDX11_CreateDeviceObjects(); 21 | IMGUI_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); 22 | -------------------------------------------------------------------------------- /apex_guest/Client/impl/libraries/shellcode.asm: -------------------------------------------------------------------------------- 1 | PUBLIC _spoofer_stub 2 | 3 | .code 4 | 5 | _spoofer_stub PROC 6 | pop r11 7 | add rsp, 8 8 | mov rax, [rsp + 24] 9 | 10 | mov r10, [rax] 11 | mov [rsp], r10 12 | 13 | mov r10, [rax + 8] 14 | mov [rax + 8], r11 15 | 16 | mov [rax + 16], rsi 17 | lea rsi, fixup 18 | mov [rax], rsi 19 | mov rsi, rax 20 | 21 | jmp r10 22 | 23 | fixup: 24 | sub rsp, 16 25 | mov rcx, rsi 26 | mov rsi, [rcx + 16] 27 | jmp QWORD PTR [rcx + 8] 28 | _spoofer_stub ENDP 29 | 30 | END -------------------------------------------------------------------------------- /apex_guest/Client/impl/render/font.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KrackerCo/apex_dma_kvm_pub/4e35017c8d6ba5676c4cca85edb2e89e77ff62e8/apex_guest/Client/impl/render/font.h -------------------------------------------------------------------------------- /apex_guest/Client/main.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #pragma warning (disable : 4005) 3 | #pragma warning (disable : 4244) 4 | #pragma warning (disable : 4305) 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | //#include 13 | //#include "D3DX10Math.h" 14 | #include 15 | #include "overlay.h" 16 | #include 17 | #include 18 | #include 19 | //#include 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /apex_guest/Client/overlay.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #pragma comment(lib, "dwmapi.lib") 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include "XorString.h" 14 | #include "imgui/imgui.h" 15 | #include "imgui/imgui_impl_dx11.h" 16 | #include "imgui/imgui_impl_win32.h" 17 | #include 18 | #include 19 | #include "D3DX10Math.h" 20 | #pragma comment(lib, "d3d11.lib") 21 | 22 | #define GREEN ImColor(0, 255, 0) 23 | #define RED ImColor(255, 0, 0) 24 | #define BLUE ImColor(0, 0, 255) 25 | #define ORANGE ImColor(255, 165, 0) 26 | #define WHITE ImColor(255, 255, 255) 27 | #define TEAL ImColor(0, 128, 128) 28 | #define YELLOW ImColor(255, 255, 0) 29 | 30 | typedef struct visuals 31 | { 32 | bool box = false; 33 | bool line = false; 34 | bool distance = true; 35 | bool healthbar = true; 36 | bool shieldbar = true; 37 | bool name = true; 38 | }visuals; 39 | 40 | class Overlay 41 | { 42 | public: 43 | void Start(); 44 | DWORD CreateOverlay(); 45 | void Clear(); 46 | int getWidth(); 47 | int getHeight(); 48 | void RenderInfo(); 49 | void RenderMenu(); 50 | void RenderEsp(); 51 | void ClickThrough(bool v); 52 | void DrawLine(ImVec2 a, ImVec2 b, ImColor color, float width); 53 | void DrawBox(ImColor color, float x, float y, float w, float h); 54 | void Text(ImVec2 pos, ImColor color, const char* text_begin, const char* text_end, float wrap_width, const ImVec4* cpu_fine_clip_rect); 55 | void RectFilled(float x0, float y0, float x1, float y1, ImColor color, float rounding, int rounding_corners_flags); 56 | void ProgressBar(float x, float y, float w, float h, int value, int v_max); 57 | void String(ImVec2 pos, ImColor color, const char* text); 58 | //Seer 59 | void DrawSeerLikeHealth(float x, float y, int shield, int max_shield, int armorType, int health); 60 | private: 61 | bool running; 62 | HWND overlayHWND; 63 | }; 64 | -------------------------------------------------------------------------------- /apex_guest/Client/playerdef.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include "D3DX10Math.h" 3 | #ifndef PLAYERDEF_H 4 | #define PLAYERDEF_H 5 | typedef struct player 6 | { 7 | float dist = 0; 8 | int entity_team = 0; 9 | float boxMiddle = 0; 10 | float h_y = 0; 11 | float width = 0; 12 | float height = 0; 13 | float b_x = 0; 14 | float b_y = 0; 15 | bool knocked = false; 16 | bool visible = false; 17 | int health = 0; 18 | int shield = 0; 19 | //seer 20 | int maxshield = 0; 21 | int armortype = 0; 22 | D3DXVECTOR3 EntityPosition; 23 | D3DXVECTOR3 LocalPlayerPosition; 24 | D3DXVECTOR3 localviewangle; 25 | char name[33] = { 0 }; 26 | }player; 27 | 28 | #endif -------------------------------------------------------------------------------- /apex_guest/Client/resource.h: -------------------------------------------------------------------------------- 1 | //{{NO_DEPENDENCIES}} 2 | // Microsoft Visual C++ generated include file. 3 | // Used by LocalStrunder.rc 4 | 5 | // Valori predefiniti successivi per i nuovi oggetti 6 | // 7 | #ifdef APSTUDIO_INVOKED 8 | #ifndef APSTUDIO_READONLY_SYMBOLS 9 | #define _APS_NEXT_RESOURCE_VALUE 101 10 | #define _APS_NEXT_COMMAND_VALUE 40001 11 | #define _APS_NEXT_CONTROL_VALUE 1001 12 | #define _APS_NEXT_SYMED_VALUE 101 13 | #endif 14 | #endif 15 | -------------------------------------------------------------------------------- /apex_guest/Client/updater.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | 6 | inline uintptr_t BaseAddress = ( uintptr_t ) GetModuleHandle( NULL ); 7 | 8 | #define ENTITY_MAX_COUNT 15000 9 | 10 | enum classes : int32_t 11 | { 12 | pEntityList, 13 | pCInput, 14 | pLocalPlayer, 15 | pNameList, 16 | pViewRender, 17 | pViewMatrix, 18 | pLastVisibleTime, 19 | }; 20 | 21 | class update 22 | { 23 | public: 24 | static auto GetClass( classes offset_name ) 25 | { 26 | uint64_t offset; 27 | 28 | switch ( offset_name ) 29 | { 30 | case pEntityList: 31 | offset = scanner::find( x( "4C 8D 05 ? ? ? ? 4C 8B 25 ? ? ? ?" ) ); 32 | break; 33 | case pViewRender: 34 | offset = scanner::find( x( "48 8B 0D ? ? ? ? 48 8B 01 FF 50 40 48 8B 0D ? ? ? ?" ) ); 35 | break; 36 | case pCInput: 37 | offset = scanner::find( x( "4C 8B 05 ? ? ? ? 48 8D 0D ? ? ? ? 49 8B 80 80 00 00 00" ) ); 38 | break; 39 | case pLocalPlayer: 40 | offset = scanner::find( x( "48 8B 05 ? ? ? ? 48 0F 44 C7" ) ); 41 | break; 42 | case pNameList: 43 | offset = scanner::find( x( "48 8D 05 ? ? ? ? FF CA" ) ); 44 | break; 45 | case pViewMatrix: 46 | offset = scanner::find( x( "48 8D 1D ? ? ? ? 66 0F 1F 84 00 00 00 00 00 48 8B 01 48 0F BE F7 49 3B C6 0F 85" ) ); 47 | break; 48 | case pLastVisibleTime: 49 | offset = scanner::find( x( "C0 03 00 00 00 00 00" ) ); 50 | break; 51 | default: 52 | break; 53 | } 54 | 55 | offset -= ( uint64_t ) GetModuleHandle( NULL ); 56 | 57 | return offset; 58 | } 59 | }; --------------------------------------------------------------------------------