├── .gitattributes ├── .gitignore ├── README.md ├── apex_dma ├── Game.cpp ├── Game.h ├── Makefile ├── Math.cpp ├── Math.h ├── apex_dma.cpp ├── build.sh ├── memflow_lib │ ├── .cargo │ │ └── config │ ├── .github │ │ └── workflows │ │ │ └── build.yml │ ├── .gitignore │ ├── CHANGES.md │ ├── CONTRIBUTE.md │ ├── Cargo.toml │ ├── LICENSE │ ├── README.md │ ├── RELEASE.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 │ │ │ ├── util.rs │ │ │ ├── vat.rs │ │ │ └── virt.rs │ │ └── vagrant │ │ │ └── Vagrantfile │ ├── memflow-derive │ │ ├── Cargo.toml │ │ ├── README.md │ │ └── src │ │ │ └── lib.rs │ ├── memflow-ffi │ │ ├── .gitignore │ │ ├── Cargo.toml │ │ ├── README.md │ │ ├── binddestr.h │ │ ├── bindgen.sh │ │ ├── cbindgen.toml │ │ ├── cglue.toml │ │ ├── examples │ │ │ ├── c │ │ │ │ ├── .clang-format │ │ │ │ ├── Makefile │ │ │ │ ├── find_process.c │ │ │ │ ├── module_dump.c │ │ │ │ ├── module_list.c │ │ │ │ ├── phys_mem.c │ │ │ │ └── process_list.c │ │ │ └── cpp │ │ │ │ ├── Makefile │ │ │ │ └── plist.cpp │ │ ├── memflow.h │ │ ├── memflow.hpp │ │ ├── memflow_go.yml │ │ ├── src │ │ │ ├── architecture │ │ │ │ ├── mod.rs │ │ │ │ └── x86.rs │ │ │ ├── lib.rs │ │ │ ├── log.rs │ │ │ ├── mem │ │ │ │ └── mod.rs │ │ │ ├── os │ │ │ │ └── mod.rs │ │ │ ├── plugins │ │ │ │ └── mod.rs │ │ │ ├── types │ │ │ │ └── mod.rs │ │ │ └── util.rs │ │ └── verify_headers.sh │ ├── memflow-win32 │ │ ├── .github │ │ │ └── workflows │ │ │ │ ├── binary-build.yml │ │ │ │ └── build.yml │ │ ├── .gitignore │ │ ├── Cargo.toml │ │ ├── LICENSE │ │ ├── README.md │ │ ├── install.sh │ │ ├── memflow-win32-defs │ │ │ ├── Cargo.toml │ │ │ ├── examples │ │ │ │ └── generate_offsets.rs │ │ │ └── src │ │ │ │ ├── kernel.rs │ │ │ │ ├── lib.rs │ │ │ │ └── offsets │ │ │ │ ├── builder.rs │ │ │ │ ├── mod.rs │ │ │ │ ├── offset_table.rs │ │ │ │ ├── pdb.rs │ │ │ │ ├── pdb │ │ │ │ └── data.rs │ │ │ │ └── symstore.rs │ │ └── memflow-win32 │ │ │ ├── Cargo.toml │ │ │ ├── build.rs │ │ │ ├── examples │ │ │ ├── dump_offsets.rs │ │ │ ├── open_process.rs │ │ │ └── process_list.rs │ │ │ ├── offsets │ │ │ ├── 10_0_18362_X64_0AFB69F5FD264D54673570E37B38A3181.toml │ │ │ ├── 10_0_19041_X64_1C9875F76C8F0FBF3EB9A9D7C1C274061.toml │ │ │ ├── 10_0_19041_X64_9C00B19DBDE003DBFE4AB4216993C8431.toml │ │ │ ├── 10_0_19041_X64_BBED7C2955FBE4522AAA23F4B8677AD91.toml │ │ │ ├── 10_0_19041_X86_1B1D6AA205E1C87DC63A314ACAA50B491.toml │ │ │ ├── 10_0_19045_X64_5F0CF5D532F385333A9B4ABA25CA65961.toml │ │ │ ├── 10_0_22000_X86_55678BC384F099B6ED05E9E39046924A1.toml │ │ │ ├── 3_10_511_X86.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 │ │ │ ├── kernel │ │ │ ├── mod.rs │ │ │ ├── ntos.rs │ │ │ ├── ntos │ │ │ │ ├── pehelper.rs │ │ │ │ ├── x64.rs │ │ │ │ └── x86.rs │ │ │ ├── start_block.rs │ │ │ ├── start_block │ │ │ │ ├── aarch64.rs │ │ │ │ ├── x64.rs │ │ │ │ ├── x86.rs │ │ │ │ └── x86pae.rs │ │ │ └── sysproc.rs │ │ │ ├── lib.rs │ │ │ ├── offsets │ │ │ └── mod.rs │ │ │ ├── plugins.rs │ │ │ ├── win32.rs │ │ │ └── win32 │ │ │ ├── kernel.rs │ │ │ ├── kernel │ │ │ └── mem_map.rs │ │ │ ├── kernel_builder.rs │ │ │ ├── kernel_info.rs │ │ │ ├── keyboard.rs │ │ │ ├── module.rs │ │ │ ├── process.rs │ │ │ ├── unicode_string.rs │ │ │ └── vat.rs │ ├── memflow │ │ ├── Cargo.toml │ │ ├── examples │ │ │ ├── cached_view.rs │ │ │ ├── integration.rs │ │ │ ├── kernel_exports.rs │ │ │ ├── kernel_maps.rs │ │ │ ├── kernel_modules.rs │ │ │ ├── keyboard.rs │ │ │ ├── mem_maps.rs │ │ │ ├── module_info.rs │ │ │ ├── module_list.rs │ │ │ ├── multithreading.rs │ │ │ ├── open_process.rs │ │ │ ├── process_list.rs │ │ │ ├── read_bench.rs │ │ │ └── target_list.rs │ │ └── src │ │ │ ├── architecture │ │ │ ├── arm │ │ │ │ ├── aarch64.rs │ │ │ │ └── mod.rs │ │ │ ├── mod.rs │ │ │ └── x86 │ │ │ │ ├── mod.rs │ │ │ │ ├── x32.rs │ │ │ │ ├── x32_pae.rs │ │ │ │ └── x64.rs │ │ │ ├── connector │ │ │ ├── cpu_state.rs │ │ │ ├── fileio.rs │ │ │ ├── filemap.rs │ │ │ ├── mmap.rs │ │ │ └── mod.rs │ │ │ ├── dummy │ │ │ ├── mem.rs │ │ │ ├── mod.rs │ │ │ ├── offset_pt.rs │ │ │ ├── os.rs │ │ │ └── process.rs │ │ │ ├── error.rs │ │ │ ├── iter │ │ │ ├── double_buffered_iterator.rs │ │ │ ├── doublepeek.rs │ │ │ ├── mod.rs │ │ │ └── page_chunks.rs │ │ │ ├── lib.rs │ │ │ ├── mem │ │ │ ├── mem_data.rs │ │ │ ├── mem_map.rs │ │ │ ├── memory_view │ │ │ │ ├── arch_overlay.rs │ │ │ │ ├── batcher.rs │ │ │ │ ├── cached_view.rs │ │ │ │ ├── cursor.rs │ │ │ │ ├── mod.rs │ │ │ │ └── remap_view.rs │ │ │ ├── mod.rs │ │ │ ├── phys_mem │ │ │ │ ├── middleware │ │ │ │ │ ├── cache │ │ │ │ │ │ ├── mod.rs │ │ │ │ │ │ └── page_cache.rs │ │ │ │ │ ├── delay.rs │ │ │ │ │ ├── metrics.rs │ │ │ │ │ └── mod.rs │ │ │ │ └── mod.rs │ │ │ ├── virt_mem │ │ │ │ ├── mod.rs │ │ │ │ └── virtual_dma.rs │ │ │ └── virt_translate │ │ │ │ ├── cache │ │ │ │ ├── mod.rs │ │ │ │ └── tlb_cache.rs │ │ │ │ ├── direct_translate.rs │ │ │ │ ├── mmu │ │ │ │ ├── def.rs │ │ │ │ ├── mod.rs │ │ │ │ ├── spec.rs │ │ │ │ └── translate_data.rs │ │ │ │ ├── mod.rs │ │ │ │ └── tests.rs │ │ │ ├── os │ │ │ ├── keyboard.rs │ │ │ ├── mod.rs │ │ │ ├── module.rs │ │ │ ├── process.rs │ │ │ ├── root.rs │ │ │ └── util.rs │ │ │ ├── plugins │ │ │ ├── args.rs │ │ │ ├── connector.rs │ │ │ ├── logger.rs │ │ │ ├── mod.rs │ │ │ ├── os.rs │ │ │ └── util.rs │ │ │ └── types │ │ │ ├── address.rs │ │ │ ├── byte_swap.rs │ │ │ ├── cache │ │ │ ├── count_validator.rs │ │ │ ├── mod.rs │ │ │ └── timed_validator.rs │ │ │ ├── gap_remover.rs │ │ │ ├── mem.rs │ │ │ ├── mem_units.rs │ │ │ ├── mod.rs │ │ │ ├── page.rs │ │ │ ├── physical_address.rs │ │ │ └── pointer.rs │ ├── nostd-test │ │ ├── .cargo │ │ │ └── config │ │ ├── .gitignore │ │ ├── Cargo.toml │ │ ├── rust-toolchain │ │ └── src │ │ │ └── main.rs │ └── runner.sh ├── memory.cpp ├── memory.h ├── offsets.h ├── prediction.h └── vector.h └── apex_guest ├── Client ├── Client.sln └── Client │ ├── Client.rc │ ├── Client.vcxproj │ ├── Client.vcxproj.filters │ ├── Client.vcxproj.user │ ├── 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 │ ├── main.cpp │ ├── main.h │ ├── overlay.cpp │ ├── overlay.h │ └── resource.h ├── Overlay ├── Overlay.sln └── Overlay │ ├── Overlay.vcxproj │ ├── Overlay.vcxproj.filters │ ├── Overlay.vcxproj.user │ └── main.cpp └── apex_guest.sln /.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/ -------------------------------------------------------------------------------- /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 & Origin): v3.0.40.25 9 | -------------------------------------------------------------------------------- /apex_dma/Game.h: -------------------------------------------------------------------------------- 1 | #include "Math.h" 2 | #include "offsets.h" 3 | #include "memory.h" 4 | 5 | #define NUM_ENT_ENTRIES (1 << 12) 6 | #define ENT_ENTRY_MASK (NUM_ENT_ENTRIES - 1) 7 | 8 | typedef struct Bone 9 | { 10 | uint8_t pad1[0xCC]; 11 | float x; 12 | uint8_t pad2[0xC]; 13 | float y; 14 | uint8_t pad3[0xC]; 15 | float z; 16 | }Bone; 17 | 18 | class Entity 19 | { 20 | public: 21 | uint64_t ptr; 22 | uint8_t buffer[0x3FF0]; 23 | Vector getPosition(); 24 | bool isDummy(); 25 | bool isPlayer(); 26 | bool isKnocked(); 27 | bool isAlive(); 28 | float lastVisTime(); 29 | int getTeamId(); 30 | int getHealth(); 31 | int getShield(); 32 | bool isGlowing(); 33 | bool isZooming(); 34 | Vector getAbsVelocity(); 35 | QAngle GetSwayAngles(); 36 | QAngle GetViewAngles(); 37 | Vector GetCamPos(); 38 | QAngle GetRecoil(); 39 | Vector GetViewAnglesV(); 40 | float GetYaw(); 41 | 42 | void enableGlow(); 43 | void disableGlow(); 44 | void SetViewAngles(SVector angles); 45 | void SetViewAngles(QAngle& angles); 46 | Vector getBonePosition(int id); 47 | Vector getBonePositionByHitbox(int id); 48 | bool Observing(uint64_t local); 49 | void get_name(uint64_t g_Base, uint64_t index, char* name); 50 | }; 51 | 52 | class Item 53 | { 54 | public: 55 | uint64_t ptr; 56 | uint8_t buffer[0x3FF0]; 57 | Vector getPosition(); 58 | bool isItem(); 59 | bool isGlowing(); 60 | 61 | void enableGlow(); 62 | void disableGlow(); 63 | }; 64 | 65 | class WeaponXEntity 66 | { 67 | public: 68 | void update(uint64_t LocalPlayer); 69 | float get_projectile_speed(); 70 | float get_projectile_gravity(); 71 | float get_zoom_fov(); 72 | int get_ammo(); 73 | 74 | private: 75 | float projectile_scale; 76 | float projectile_speed; 77 | float zoom_fov; 78 | int ammo; 79 | }; 80 | 81 | struct ClientClass { 82 | uint64_t pCreateFn; 83 | uint64_t pCreateEventFn; 84 | uint64_t pNetworkName; 85 | uint64_t pRecvTable; 86 | uint64_t pNext; 87 | uint32_t ClassID; 88 | uint32_t ClassSize; 89 | }; 90 | 91 | Entity getEntity(uintptr_t ptr); 92 | Item getItem(uintptr_t ptr); 93 | bool WorldToScreen(Vector from, float* m_vMatrix, int targetWidth, int targetHeight, Vector& to); 94 | float CalculateFov(Entity& from, Entity& target); 95 | QAngle CalculateBestBoneAim(Entity& from, uintptr_t target, float max_fov); 96 | void get_class_name(uint64_t entity_ptr, char* out_str); 97 | void charge_rifle_hack(uint64_t entity_ptr); -------------------------------------------------------------------------------- /apex_dma/Makefile: -------------------------------------------------------------------------------- 1 | CXX=g++ 2 | CXXFLAGS=-I./memflow_lib/memflow-ffi/ -L./memflow_lib/target/release -Wno-multichar 3 | LIBS=-lm -ldl -lpthread -l:libmemflow_ffi.a 4 | 5 | OUTDIR=./build 6 | OBJDIR=$(OUTDIR)/obj 7 | 8 | $(shell mkdir -p $(OBJDIR)) 9 | 10 | %.o: %.cpp 11 | $(CXX) -c -o $(OBJDIR)/$@ $< $(CXXFLAGS) 12 | 13 | apex_dma: apex_dma.o Game.o Math.o memory.o 14 | $(CXX) -o $(OUTDIR)/$@ $(OBJDIR)/apex_dma.o $(OBJDIR)/Game.o $(OBJDIR)/Math.o $(OBJDIR)/memory.o $(CXXFLAGS) $(LIBS) 15 | 16 | .PHONY: all 17 | all: apex_dma 18 | 19 | .DEFAULT_GOAL := all 20 | 21 | clean: 22 | rm -rf $(OUTDIR) 23 | -------------------------------------------------------------------------------- /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/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cd memflow_lib/memflow-ffi/ 4 | if cargo build --release ; then 5 | cd ../../ 6 | make 7 | else 8 | echo "Error while building memflow-ffi" 9 | fi 10 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/.cargo/config: -------------------------------------------------------------------------------- 1 | [target.'cfg(unix)'] 2 | runner = "./runner.sh" -------------------------------------------------------------------------------- /apex_dma/memflow_lib/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | **/*.rs.bk 3 | *.swp 4 | *.so 5 | *.dll 6 | *.dylib 7 | .vscode 8 | nostd-test/target 9 | nostd-test/Cargo.lock 10 | *.so 11 | .vagrant 12 | TODO.md 13 | TODO.txt 14 | -------------------------------------------------------------------------------- /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 --all` 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 | [profile.bench] 2 | debug = true 3 | 4 | [workspace] 5 | members = [ 6 | "memflow", 7 | "memflow-ffi", 8 | "memflow-bench", 9 | ] 10 | default-members = [ 11 | "memflow", 12 | "memflow-ffi", 13 | "memflow-bench", 14 | ] 15 | 16 | exclude = [ 17 | "nostd-test" 18 | ] 19 | 20 | [patch.crates-io] 21 | goblin = { git = "https://github.com/h33p/goblin", branch = "lossy-macho" } 22 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020-2022 ko1N 4 | Copyright (c) 2020-2022 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/RELEASE.md: -------------------------------------------------------------------------------- 1 | # Checklist: 2 | - memflow 3 | - memflow-ffi 4 | 5 | # Plugins: 6 | - memflow-win32 7 | - memflow-pcileech 8 | - memflow-reclass-plugin 9 | - memflow-native 10 | - memflow-qemu 11 | - memflow-kcore 12 | - memflow-cmake-example 13 | - memflow-kvm 14 | - memflow-coredump 15 | - memflow-linux 16 | - memflow-microvmi 17 | 18 | # Tools: 19 | - cloudflow 20 | - scanflow 21 | - reflow 22 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/docs/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MisterY52/apex_dma_kvm_pub/92c155d477f5487982e16ea71b6ad07527698951/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.2.0" 4 | authors = ["Aurimas Blažulionis <0x60@pm.me>", "ko1N "] 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 = "MIT" 11 | keywords = [ "memflow", "introspection", "memory", "dma" ] 12 | categories = [ "memory-management", "os" ] 13 | publish = false 14 | 15 | [dependencies] 16 | memflow = { version = "0.2", path = "../memflow", features = ["dummy_mem"] } 17 | log = "^0.4.14" 18 | rand = "^0.8.4" 19 | rand_xorshift = "^0.3" 20 | 21 | # This branch provides throughput plots 22 | criterion = { git = "https://github.com/h33p/criterion.rs.git", branch = "tput2" } 23 | 24 | [dev-dependencies] 25 | memflow = { version = "0.2", path = "../memflow", features = ["dummy_mem", "plugins"] } 26 | simplelog = "^0.12.0" 27 | 28 | [features] 29 | default = [] 30 | 31 | [[bench]] 32 | name = "read_dummy" 33 | harness = false 34 | 35 | [[bench]] 36 | name = "read_win32" 37 | harness = false 38 | 39 | [[bench]] 40 | name = "batcher" 41 | harness = false 42 | -------------------------------------------------------------------------------- /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::dummy::DummyMemory as Memory; 7 | use memflow::prelude::v1::*; 8 | 9 | fn initialize_virt_ctx(cache_size: usize, use_tlb: bool) -> Result> { 10 | util::build_os("", cache_size, "dummy", use_tlb) 11 | } 12 | 13 | fn dummy_read_group(c: &mut Criterion) { 14 | virt::seq_read(c, "dummy", &initialize_virt_ctx, false); 15 | virt::chunk_read(c, "dummy", &initialize_virt_ctx, false); 16 | phys::seq_read(c, "dummy", &|| Ok(Memory::new(size::mb(64)))); 17 | phys::chunk_read(c, "dummy", &|| Ok(Memory::new(size::mb(64)))); 18 | vat::chunk_vat(c, "dummy", &initialize_virt_ctx, false); 19 | } 20 | 21 | criterion_group! { 22 | name = dummy_read; 23 | config = Criterion::default() 24 | .warm_up_time(std::time::Duration::from_millis(1000)) 25 | .measurement_time(std::time::Duration::from_millis(10000)); 26 | targets = dummy_read_group 27 | } 28 | 29 | criterion_main!(dummy_read); 30 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-bench/benches/read_win32.rs: -------------------------------------------------------------------------------- 1 | extern crate memflow_bench; 2 | use memflow_bench::{phys, util, vat, virt}; 3 | 4 | use criterion::*; 5 | 6 | use memflow::prelude::v1::*; 7 | 8 | fn create_connector(args: Option<&ConnectorArgs>) -> Result { 9 | // this workaround is to prevent loaded libraries 10 | // from spitting out to much log information and skewing benchmarks 11 | let filter = log::max_level(); 12 | log::set_max_level(log::Level::Error.to_level_filter()); 13 | 14 | let result = Inventory::scan().create_connector("qemu", None, args)?; 15 | 16 | log::set_max_level(filter); 17 | Ok(result) 18 | } 19 | 20 | fn initialize_virt_ctx(cache_size: usize, use_tlb: bool) -> Result> { 21 | util::build_os("qemu", cache_size, "win32", use_tlb) 22 | } 23 | 24 | fn win32_read_group(c: &mut Criterion) { 25 | virt::seq_read(c, "win32", &initialize_virt_ctx, true); 26 | virt::chunk_read(c, "win32", &initialize_virt_ctx, true); 27 | phys::seq_read(c, "win32", &|| create_connector(None)); 28 | phys::chunk_read(c, "win32", &|| create_connector(None)); 29 | vat::chunk_vat(c, "win32", &initialize_virt_ctx, true); 30 | } 31 | 32 | criterion_group! { 33 | name = win32_read; 34 | config = Criterion::default() 35 | .warm_up_time(std::time::Duration::from_millis(1000)) 36 | .measurement_time(std::time::Duration::from_millis(10000)); 37 | targets = win32_read_group 38 | } 39 | 40 | criterion_main!(win32_read); 41 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-bench/src/lib.rs: -------------------------------------------------------------------------------- 1 | pub mod phys; 2 | pub mod util; 3 | pub mod vat; 4 | pub mod virt; 5 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-bench/src/util.rs: -------------------------------------------------------------------------------- 1 | use memflow::prelude::v1::*; 2 | 3 | pub fn build_os( 4 | conn_name: &str, 5 | cache_size: usize, 6 | os_name: &str, 7 | use_tlb: bool, 8 | ) -> Result> { 9 | // this workaround is to prevent loaded libraries 10 | // from spitting out to much log information and skewing benchmarks 11 | let filter = log::max_level(); 12 | log::set_max_level(log::Level::Debug.to_level_filter()); 13 | 14 | let inventory = Inventory::scan(); 15 | 16 | log::set_max_level(log::Level::Error.to_level_filter()); 17 | 18 | let mut args = Args::new(); 19 | 20 | if !use_tlb { 21 | args = args.insert("vatcache", "none"); 22 | } 23 | 24 | let page_cache_params = if cache_size > 0 { 25 | Some(ConnectorMiddlewareArgs::new().cache_size(cache_size)) 26 | } else { 27 | None 28 | }; 29 | 30 | let conn_args = ConnectorArgs::new(None, Default::default(), page_cache_params); 31 | let args = OsArgs::new(None, args); 32 | 33 | let ret = if conn_name.is_empty() { 34 | inventory.builder().os(os_name).args(args).build() 35 | } else { 36 | inventory 37 | .builder() 38 | .connector(conn_name) 39 | .args(conn_args) 40 | .os(os_name) 41 | .args(args) 42 | .build() 43 | }?; 44 | 45 | log::set_max_level(filter); 46 | 47 | Ok(ret) 48 | } 49 | 50 | pub fn find_proc(os: &mut T) -> Result<(::ProcessType<'_>, ModuleInfo)> { 51 | let infos = os.process_info_list()?; 52 | 53 | let mut data = None; 54 | 55 | for info in infos { 56 | if let Ok(mut proc) = os.process_by_info(info.clone()) { 57 | let mut module = None; 58 | 59 | proc.module_list_callback( 60 | None, 61 | (&mut |info: ModuleInfo| { 62 | if info.size > 0x1000 { 63 | module = Some(info); 64 | } 65 | module.is_none() 66 | }) 67 | .into(), 68 | )?; 69 | 70 | if let Some(module) = module { 71 | data = Some((info, module)); 72 | break; 73 | } 74 | } 75 | } 76 | 77 | data.and_then(move |(info, module)| Some((os.process_by_info(info).ok()?, module))) 78 | .ok_or_else(|| ErrorKind::NotFound.into()) 79 | } 80 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-bench/src/vat.rs: -------------------------------------------------------------------------------- 1 | use criterion::*; 2 | 3 | use memflow::cglue::as_mut; 4 | use memflow::mem::virt_translate::*; 5 | use memflow::prelude::v1::*; 6 | 7 | use rand::prelude::*; 8 | use rand::{Rng, SeedableRng}; 9 | use rand_xorshift::XorShiftRng as CurRng; 10 | 11 | use std::convert::TryInto; 12 | 13 | fn vat_test_with_mem( 14 | bench: &mut Bencher, 15 | vat: &mut impl VirtualTranslate, 16 | chunk_count: usize, 17 | translations: usize, 18 | module: ModuleInfo, 19 | ) { 20 | let mut rng = CurRng::from_rng(thread_rng()).unwrap(); 21 | 22 | let mut bufs = vec![CTup2(Address::null(), 1); translations]; 23 | 24 | let base_addr = rng.gen_range(module.base.to_umem()..(module.base.to_umem() + module.size)); 25 | 26 | for CTup2(address, _) in bufs.iter_mut() { 27 | *address = (base_addr + rng.gen_range(0..0x2000)).into(); 28 | } 29 | 30 | let mut out = vec![]; 31 | 32 | bench.iter(|| { 33 | for chunk in bufs.chunks_mut(chunk_count) { 34 | out.clear(); 35 | vat.virt_to_phys_list(chunk, (&mut out).into(), (&mut |_| true).into()); 36 | black_box(&out); 37 | } 38 | }); 39 | } 40 | 41 | fn vat_test_with_os( 42 | bench: &mut Bencher, 43 | chunks: usize, 44 | translations: usize, 45 | os: &mut OsInstanceArcBox<'static>, 46 | ) { 47 | let (mut process, module) = crate::util::find_proc(os).unwrap(); 48 | 49 | vat_test_with_mem( 50 | bench, 51 | as_mut!(process impl VirtualTranslate).unwrap(), 52 | chunks, 53 | translations, 54 | module, 55 | ); 56 | } 57 | 58 | fn chunk_vat_params( 59 | group: &mut BenchmarkGroup<'_, measurement::WallTime>, 60 | func_name: String, 61 | cache_size: usize, 62 | use_tlb: bool, 63 | initialize_ctx: &dyn Fn(usize, bool) -> Result>, 64 | ) { 65 | let size = 0x10; 66 | 67 | let mut os = initialize_ctx(cache_size, use_tlb).unwrap(); 68 | 69 | for &chunk_size in [1, 4, 16, 64].iter() { 70 | group.throughput(Throughput::Elements(chunk_size * size)); 71 | group.bench_with_input( 72 | BenchmarkId::new(func_name.clone(), chunk_size), 73 | &size, 74 | |b, &size| { 75 | vat_test_with_os( 76 | b, 77 | black_box(chunk_size.try_into().unwrap()), 78 | black_box((size * chunk_size).try_into().unwrap()), 79 | &mut os, 80 | ) 81 | }, 82 | ); 83 | } 84 | } 85 | 86 | pub fn chunk_vat( 87 | c: &mut Criterion, 88 | backend_name: &str, 89 | initialize_ctx: &dyn Fn(usize, bool) -> Result>, 90 | use_caches: bool, 91 | ) { 92 | let plot_config = PlotConfiguration::default().summary_scale(AxisScale::Logarithmic); 93 | 94 | let group_name = format!("{backend_name}_chunk_vat"); 95 | 96 | let mut group = c.benchmark_group(group_name.clone()); 97 | group.plot_config(plot_config); 98 | 99 | chunk_vat_params( 100 | &mut group, 101 | format!("{group_name}_nocache"), 102 | 0, 103 | false, 104 | initialize_ctx, 105 | ); 106 | if use_caches { 107 | chunk_vat_params( 108 | &mut group, 109 | format!("{group_name}_tlb_nocache"), 110 | 0, 111 | true, 112 | initialize_ctx, 113 | ); 114 | chunk_vat_params( 115 | &mut group, 116 | format!("{group_name}_cache"), 117 | 2, 118 | false, 119 | initialize_ctx, 120 | ); 121 | chunk_vat_params( 122 | &mut group, 123 | format!("{group_name}_tlb_cache"), 124 | 2, 125 | true, 126 | initialize_ctx, 127 | ); 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-bench/vagrant/Vagrantfile: -------------------------------------------------------------------------------- 1 | # -*- mode: ruby -*- 2 | # vi: set ft=ruby : 3 | 4 | Vagrant.configure("2") do |config| 5 | config.vm.provider :virtualbox do |v| 6 | v.memory = 2048 7 | v.cpus = 4 8 | config.vm.synced_folder "../..", "/memflow", create: true, disabled: false 9 | end 10 | config.vm.provider :libvirt do |v| 11 | v.memory = 2048 12 | v.cpus = 4 13 | v.qemu_use_session = false 14 | config.vm.synced_folder "../..", "/memflow", type: 'nfs', nfs_udp: false, create: true, disabled: false 15 | end 16 | 17 | config.vm.box = "generic/ubuntu2004" 18 | config.vm.provision :shell, privileged: true, inline: $install_updates 19 | config.vm.provision :shell, privileged: false, inline: $install_memflow 20 | end 21 | 22 | $install_updates = <<-SCRIPT 23 | echo "installing updates" 24 | export DEBIAN_FRONTEND=noninteractive 25 | apt-get -qq update 26 | apt-get -qq install git build-essential 27 | SCRIPT 28 | 29 | $install_memflow = <<-SCRIPT 30 | echo "installing rust" 31 | curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y 32 | source $HOME/.cargo/env 33 | 34 | echo "building memflow" 35 | cd /memflow 36 | cargo build --release --workspace --all-features 37 | 38 | # TODO: install memflow-win32, memflow-coredump, etc 39 | SCRIPT 40 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-derive/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "memflow-derive" 3 | version = "0.2.0" 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 = "MIT" 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 = "^2.0" 24 | quote = "^1.0" 25 | darling = "^0.20" 26 | proc-macro-crate = "^2.0" 27 | 28 | -------------------------------------------------------------------------------- /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-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.2.0" 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 = "MIT" 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.2", path = "../memflow" } 25 | log = "^0.4.14" 26 | simplelog = "^0.12.0" 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. 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 | #!/usr/bin/env bash 2 | 3 | run_twice() { 4 | echo $@ 5 | 6 | v=$(exec $@) 7 | 8 | if [ $? -ne 0 ]; then 9 | echo "Error occured! Maybe a fluke. Retrying..." 10 | v=$(exec $@) 11 | fi 12 | } 13 | 14 | # remove any RUSTC_WRAPPER like sccache which might cause issues with cglue-bindgen 15 | export RUSTC_WRAPPER="" 16 | 17 | # update cglue-bindgen 18 | cargo +nightly install cbindgen 19 | cargo +nightly install cglue-bindgen 20 | 21 | # generate c and cpp bindings 22 | run_twice rustup run nightly cglue-bindgen +nightly -c cglue.toml -- --config cbindgen.toml --crate memflow-ffi --output memflow.h -l C 23 | run_twice rustup run nightly cglue-bindgen +nightly -c cglue.toml -- --config cbindgen.toml --crate memflow-ffi --output memflow.hpp -l C++ 24 | -------------------------------------------------------------------------------- /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 | after_includes = "typedef void *Library;" 11 | 12 | [parse] 13 | parse_deps = true 14 | include = ["memflow"] 15 | 16 | [parse.expand] 17 | crates = ["cglue", "memflow", "memflow-ffi", "log"] 18 | 19 | [macro_expansion] 20 | bitflags = true 21 | 22 | [fn] 23 | sort_by = "None" 24 | 25 | [export] 26 | include = ["OsInstanceArcBox", "ProcessInstanceArcBox", "IntoProcessInstanceArcBox", "MemoryViewArcBox"] 27 | 28 | [export.rename] 29 | "OptionMut_c_void" = "pvoid" 30 | 31 | [enum] 32 | prefix_with_name = true 33 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-ffi/cglue.toml: -------------------------------------------------------------------------------- 1 | default_container = "Box" 2 | default_context = "Arc" 3 | function_prefix = "mf" 4 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-ffi/examples/c/.clang-format: -------------------------------------------------------------------------------- 1 | --- 2 | BasedOnStyle: LLVM -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-ffi/examples/c/Makefile: -------------------------------------------------------------------------------- 1 | CC = clang 2 | CFLAGS = -g -O0 -I../../../memflow-ffi/ -L../../../target/release 3 | LIBS=-lm -ldl -lpthread -l:libmemflow_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 | process_list.out: process_list.o 14 | $(CC) -o $@ $^ $(CFLAGS) $(LIBS) 15 | 16 | module_list.out: module_list.o 17 | $(CC) -o $@ $^ $(CFLAGS) $(LIBS) 18 | 19 | module_dump.out: module_dump.o 20 | $(CC) -o $@ $^ $(CFLAGS) $(LIBS) 21 | 22 | find_process.out: find_process.o 23 | $(CC) -o $@ $^ $(CFLAGS) $(LIBS) 24 | 25 | .PHONY: all 26 | all: phys_mem.out process_list.out module_list.out module_dump.out find_process.out 27 | 28 | .DEFAULT_GOAL := all 29 | 30 | clean: 31 | rm -f $(ODIR)/*.o 32 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-ffi/examples/c/module_list.c: -------------------------------------------------------------------------------- 1 | #include "memflow.h" 2 | 3 | #include 4 | #include 5 | 6 | int main(int argc, char *argv[]) { 7 | 8 | int ret = 0; 9 | 10 | // enable info level logging 11 | log_init(3); 12 | 13 | // load all available plugins 14 | Inventory *inventory = inventory_scan(); 15 | printf("inventory initialized: %p\n", inventory); 16 | 17 | const char *conn_name = argc > 1 ? argv[1] : "kvm"; 18 | const char *conn_arg = argc > 2 ? argv[2] : ""; 19 | const char *os_name = argc > 3 ? argv[3]: "win32"; 20 | const char *os_arg = argc > 4? argv[4]: ""; 21 | const char *target_proc = argc > 5? argv[5]: "notepad.exe"; 22 | 23 | ConnectorInstance connector, *conn = conn_name[0] ? &connector : NULL; 24 | 25 | // initialize the connector plugin 26 | if (conn) { 27 | if (inventory_create_connector(inventory, conn_name, conn_arg, conn)) { 28 | log_error("unable to initialize connector"); 29 | inventory_free(inventory); 30 | return 1; 31 | } 32 | 33 | printf("connector initialized: %p\n", connector.container.instance.instance); 34 | } 35 | 36 | // initialize the OS plugin 37 | OsInstance os; 38 | if (inventory_create_os(inventory, os_name, os_arg, conn, &os)) { 39 | log_error("unable to initialize os plugin"); 40 | inventory_free(inventory); 41 | return 1; 42 | } 43 | 44 | printf("os plugin initialized: %p\n", os.container.instance.instance); 45 | 46 | // find a specific process based on its name via process_by_name 47 | ProcessInstance target_process; 48 | if (!(ret = mf_osinstance_process_by_name(&os, STR(target_proc), &target_process))) { 49 | const struct ProcessInfo *info = mf_processinstance_info(&target_process); 50 | 51 | printf("%s process found: 0x%lx] %d %s %s\n", target_proc, info->address, 52 | info->pid, info->name, info->path); 53 | 54 | // iterate over all module info structs and collect them in a buffer 55 | COLLECT_CB(ModuleInfo, module_info); 56 | mf_processinstance_module_list_callback(&target_process, NULL, module_info); 57 | for (size_t i = 0; i < module_info_base.size; i++) { 58 | ModuleInfo *module_info = &((ModuleInfo *)module_info_base.buf)[i]; 59 | printf("%s module found: 0x%lx] 0x%lx %s %s\n", target_proc, module_info->address, 60 | module_info->base, module_info->name, module_info->path); 61 | } 62 | free(module_info_base.buf); 63 | 64 | // cleanup the processinstance 65 | mf_processinstance_drop(target_process); 66 | } else { 67 | printf("Unable to find %s\n", target_proc); 68 | log_debug_errorcode(ret); 69 | } 70 | 71 | // This will also free the connector here 72 | // as it was _moved_ into the os by `inventory_create_os` 73 | mf_osinstance_drop(os); 74 | log_info("os plugin/connector freed"); 75 | 76 | inventory_free(inventory); 77 | log_info("inventory freed"); 78 | 79 | return 0; 80 | } 81 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-ffi/examples/c/phys_mem.c: -------------------------------------------------------------------------------- 1 | #include "memflow.h" 2 | 3 | #include 4 | 5 | int main(int argc, char *argv[]) { 6 | // enable debug level logging 7 | log_init(3); 8 | 9 | Inventory *inv = inventory_scan(); 10 | printf("inv: %p\n", inv); 11 | 12 | const char *conn_name = argc > 1 ? argv[1] : "kvm"; 13 | const char *conn_arg = argc > 2 ? argv[2] : ""; 14 | 15 | ConnectorInstance conn; 16 | if (!inventory_create_connector(inv, conn_name, conn_arg, &conn)) { 17 | for (int i = 0; i < 1000 * 1000; i++) { 18 | uint8_t buffer[0x1000]; 19 | 20 | ConnectorInstance cloned = mf_connectorinstance_clone(&conn); 21 | 22 | mf_connectorinstance_drop(cloned); 23 | 24 | MemoryView phys_view = mf_connectorinstance_phys_view(&conn); 25 | 26 | // regular read_into 27 | mf_read_raw_into(&phys_view, 0x1000 + i, MUT_SLICE(u8, buffer, sizeof(buffer))); 28 | 29 | // read multiple 30 | ReadData read_data = {0x1000 + i, {buffer, sizeof(buffer)}}; 31 | mf_read_raw_list(&phys_view, MUT_SLICE(ReadData, &read_data, 1)); 32 | 33 | printf("Read: %lx\n", *(uint64_t *)buffer); 34 | 35 | mf_memoryview_drop(phys_view); 36 | } 37 | 38 | mf_connectorinstance_drop(conn); 39 | printf("conn dropped!\n"); 40 | } 41 | 42 | inventory_free(inv); 43 | printf("inv freed!\n"); 44 | 45 | return 0; 46 | } 47 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-ffi/examples/cpp/Makefile: -------------------------------------------------------------------------------- 1 | CC = g++ 2 | CFLAGS = -g -O0 -pedantic -std=c++14 -I../../../memflow-ffi/ -L../../../target/release 3 | LIBS=-lm -ldl -lpthread -l:libmemflow_ffi.a 4 | 5 | ODIR=./ 6 | 7 | %.o: %.cpp $(DEPS) 8 | $(CC) -c -o $@ $< $(CFLAGS) 9 | 10 | plist.out: plist.o 11 | $(CC) -o $@ $^ $(CFLAGS) $(LIBS) 12 | 13 | .PHONY: all 14 | all: plist.out 15 | 16 | .DEFAULT_GOAL := all 17 | 18 | clean: 19 | rm -f $(ODIR)/*.o 20 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-ffi/examples/cpp/plist.cpp: -------------------------------------------------------------------------------- 1 | #include "memflow.hpp" 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | void fmt_arch(char *arch, int n, ArchitectureIdent ident); 8 | 9 | int main(int argc, char *argv[], const int t[]) 10 | { 11 | log_init(LevelFilter::LevelFilter_Info); 12 | int arr[] = {1, 2, 3, 4, 5}; 13 | int b=3; 14 | //CSliceMut((char*)arr); 15 | CSliceRef((char*)t, sizeof(int)); 16 | 17 | /*Inventory *inventory = inventory_scan(); 18 | 19 | if (!inventory) 20 | { 21 | log_error("unable to create inventory"); 22 | return 1; 23 | } 24 | 25 | printf("inventory initialized: %p\n", inventory); 26 | 27 | const char *conn_name = argc > 1 ? argv[1] : "kvm"; 28 | const char *conn_arg = argc > 2 ? argv[2] : ""; 29 | const char *os_name = argc > 3 ? argv[3] : "win32"; 30 | const char *os_arg = argc > 4 ? argv[4] : ""; 31 | 32 | // ConnectorInstance<> connector, *conn = conn_name[0] ? &connector : nullptr; 33 | 34 | std::unique_ptr> connector = nullptr; 35 | 36 | if (!connector) 37 | { 38 | connector = std::make_unique>(); 39 | if (inventory_create_connector(inventory, conn_name, conn_arg, connector.get())) 40 | { 41 | printf("unable to initialize connector\n"); 42 | inventory_free(inventory); 43 | return 1; 44 | } 45 | 46 | printf("connector initialized: %p\n", connector->container.instance.instance); 47 | } 48 | 49 | OsInstance<> os; 50 | 51 | if (inventory_create_os(inventory, os_name, os_arg, connector.get(), &os)) 52 | { 53 | printf("unable to initialize OS\n"); 54 | inventory_free(inventory); 55 | return 1; 56 | } 57 | 58 | inventory_free(inventory); 59 | 60 | printf("os initialized: %p\n", os.container.instance.instance); 61 | 62 | auto info = os.info(); 63 | char arch[11]; 64 | fmt_arch(arch, sizeof(arch), info->arch); 65 | 66 | printf("Kernel base: %llx\nKernel size: %llx\nArchitecture: %s\n", info->base, info->size, arch); 67 | 68 | printf("Process List:\n"); 69 | 70 | printf("%-4s | %-8s | %-10s | %-10s | %s\n", "Seq", "Pid", "Sys Arch", "Proc Arch", "Name"); 71 | 72 | int i = 0; 73 | 74 | os.process_info_list_callback([&i](ProcessInfo info) 75 | { 76 | char sys_arch[11]; 77 | char proc_arch[11]; 78 | 79 | fmt_arch(sys_arch, sizeof(sys_arch), info.sys_arch); 80 | fmt_arch(proc_arch, sizeof(proc_arch), info.proc_arch); 81 | 82 | printf("%-4d | %-8d | %-10s | %-10s | %s\n", i++, info.pid, sys_arch, proc_arch, info.name); 83 | 84 | return true; }); 85 | 86 | */ 87 | 88 | return 0; 89 | } 90 | 91 | void fmt_arch(char *arch, int n, ArchitectureIdent ident) 92 | { 93 | switch (ident.tag) 94 | { 95 | case ArchitectureIdent::Tag::ArchitectureIdent_X86: 96 | snprintf(arch, n, "X86_%d", ident.x86._0); 97 | break; 98 | case ArchitectureIdent::Tag::ArchitectureIdent_AArch64: 99 | snprintf(arch, n, "AArch64"); 100 | break; 101 | default: 102 | snprintf(arch, n, "Unknown"); 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-ffi/memflow_go.yml: -------------------------------------------------------------------------------- 1 | --- 2 | GENERATOR: 3 | PackageName: memflow_go 4 | PackageDescription: "core components of the memflow physical memory introspection framework" 5 | PackageLicense: "MIT" 6 | Includes: ["memflow.h"] 7 | FlagGroups: 8 | - { name: "CFLAGS", traits: ["linux"], flags: [ -I../../memflow-ffi/ ] } 9 | - { name: "LDFLAGS", traits: ["linux"], flags: [ -L../../target/release -lm -ldl -lpthread -l:libmemflow_ffi.a ] } 10 | 11 | PARSER: 12 | IncludePaths: ["./"] 13 | SourcesPaths: ["memflow.h"] 14 | 15 | TRANSLATOR: 16 | ConstRules: 17 | defines: expand 18 | Rules: 19 | global: 20 | - { transform: lower } 21 | - { action: accept, from: "^log_" } 22 | - { action: accept, from: "^inventory_" } 23 | - { action: accept, from: "^connector_" } 24 | - { action: accept, from: "^phys_" } 25 | - { action: accept, from: "^virt_" } 26 | - { action: replace, from: "_", to: _ } 27 | - { transform: export } 28 | const: 29 | - { action: replace, from: "_", to: _ } 30 | type: 31 | - { action: accept, from: "^MU" } 32 | - { action: accept, from: "Inventory" } 33 | - { action: accept, from: "^Connector" } 34 | - { action: accept, from: "^Physical" } 35 | - { action: accept, from: "^Virtual" } 36 | - { action: accept, from: "^Translation" } 37 | - { action: accept, from: "^Page" } 38 | - { action: replace, from: "_t$" } 39 | private: 40 | - { transform: unexport } 41 | post-global: 42 | - { action: replace, from: _$ } 43 | - { load: snakecase } -------------------------------------------------------------------------------- /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 plugins; 6 | 7 | pub mod mem; 8 | 9 | pub mod os; 10 | 11 | pub mod architecture; 12 | 13 | pub mod util; 14 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-ffi/src/log.rs: -------------------------------------------------------------------------------- 1 | use log::{Level, LevelFilter}; 2 | use memflow::cglue::IntError; 3 | use memflow::error::Error; 4 | use memflow::plugins::Inventory; 5 | use std::num::NonZeroI32; 6 | 7 | use std::ffi::CStr; 8 | use std::os::raw::c_char; 9 | 10 | /// Initialize logging with selected logging level. 11 | #[no_mangle] 12 | pub extern "C" fn log_init(level_filter: LevelFilter) { 13 | simplelog::TermLogger::init( 14 | level_filter, 15 | simplelog::Config::default(), 16 | simplelog::TerminalMode::Stdout, 17 | simplelog::ColorChoice::Auto, 18 | ) 19 | .unwrap(); 20 | } 21 | 22 | // TODO: add variadic functions when this is being stabilized, see https://github.com/rust-lang/rust/issues/44930 23 | 24 | /// Logs a error message via log::error! 25 | /// 26 | /// # Safety 27 | /// 28 | /// The provided string must be a valid null-terminated char array. 29 | #[no_mangle] 30 | pub unsafe extern "C" fn log_error(s: *const c_char) { 31 | if !s.is_null() { 32 | let c_str = CStr::from_ptr(s); 33 | if let Ok(r_str) = c_str.to_str() { 34 | log::error!("{}", r_str); 35 | } 36 | } 37 | } 38 | 39 | /// Logs a warning message via log::warn! 40 | /// 41 | /// # Safety 42 | /// 43 | /// The provided string must be a valid null-terminated char array. 44 | #[no_mangle] 45 | pub unsafe extern "C" fn log_warn(s: *const c_char) { 46 | if !s.is_null() { 47 | let c_str = CStr::from_ptr(s); 48 | if let Ok(r_str) = c_str.to_str() { 49 | log::warn!("{}", r_str); 50 | } 51 | } 52 | } 53 | 54 | /// Logs a info message via log::info! 55 | /// 56 | /// # Safety 57 | /// 58 | /// The provided string must be a valid null-terminated char array. 59 | #[no_mangle] 60 | pub unsafe extern "C" fn log_info(s: *const c_char) { 61 | if !s.is_null() { 62 | let c_str = CStr::from_ptr(s); 63 | if let Ok(r_str) = c_str.to_str() { 64 | log::info!("{}", r_str); 65 | } 66 | } 67 | } 68 | 69 | /// Logs a debug message via log::debug! 70 | /// 71 | /// # Safety 72 | /// 73 | /// The provided string must be a valid null-terminated char array. 74 | #[no_mangle] 75 | pub unsafe extern "C" fn log_debug(s: *const c_char) { 76 | if !s.is_null() { 77 | let c_str = CStr::from_ptr(s); 78 | if let Ok(r_str) = c_str.to_str() { 79 | log::debug!("{}", r_str); 80 | } 81 | } 82 | } 83 | 84 | /// Logs a trace message via log::trace! 85 | /// 86 | /// # Safety 87 | /// 88 | /// The provided string must be a valid null-terminated char array. 89 | #[no_mangle] 90 | pub unsafe extern "C" fn log_trace(s: *const c_char) { 91 | if !s.is_null() { 92 | let c_str = CStr::from_ptr(s); 93 | if let Ok(r_str) = c_str.to_str() { 94 | log::trace!("{}", r_str); 95 | } 96 | } 97 | } 98 | 99 | /// Logs an error code with custom log level. 100 | #[no_mangle] 101 | pub extern "C" fn log_errorcode(level: Level, error: i32) { 102 | if let Some(error) = NonZeroI32::new(error) { 103 | log::log!(level, "{}", ::from_int_err(error)); 104 | } 105 | } 106 | 107 | /// Logs an error with debug log level. 108 | #[no_mangle] 109 | pub extern "C" fn log_debug_errorcode(error: i32) { 110 | log_errorcode(Level::Debug, error) 111 | } 112 | 113 | /// Sets new maximum log level. 114 | /// 115 | /// If `inventory` is supplied, the log level is also updated within all plugin instances. However, 116 | /// if it is not supplied, plugins will not have their log levels updated, potentially leading to 117 | /// lower performance, or less logging than expected. 118 | #[no_mangle] 119 | pub extern "C" fn log_set_max_level(level_filter: LevelFilter, inventory: Option<&Inventory>) { 120 | if let Some(inventory) = inventory { 121 | inventory.set_max_log_level(level_filter); 122 | } else { 123 | log::set_max_level(level_filter); 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-ffi/src/mem/mod.rs: -------------------------------------------------------------------------------- 1 | #[allow(unused)] 2 | pub use memflow::mem::phys_mem::*; 3 | #[allow(unused)] 4 | pub use memflow::mem::virt_mem::*; 5 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-ffi/src/os/mod.rs: -------------------------------------------------------------------------------- 1 | #[allow(unused)] 2 | pub use memflow::os::*; 3 | #[allow(unused)] 4 | pub use memflow::plugins::*; 5 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-ffi/verify_headers.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # update cglue-bindgen 4 | cargo +nightly install cbindgen 5 | cargo +nightly install cglue-bindgen 6 | 7 | DIFFC=$(diff memflow.h <(rustup run nightly cglue-bindgen +nightly -c cglue.toml -- --config cbindgen.toml --crate memflow-ffi -l C)) 8 | DIFFCPP=$(diff memflow.hpp <(rustup run nightly cglue-bindgen +nightly -c cglue.toml -- --config cbindgen.toml --crate memflow-ffi -l C++)) 9 | if [ "$DIFFC" != "" ] || [ "$DIFFCPP" != "" ] 10 | then 11 | exit 1 12 | fi 13 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-win32/.github/workflows/binary-build.yml: -------------------------------------------------------------------------------- 1 | name: Binary build 2 | 3 | on: 4 | push: 5 | branch: 6 | - 'main' 7 | - 'stable' 8 | 9 | env: 10 | CARGO_TERM_COLOR: always 11 | 12 | jobs: 13 | 14 | cross-build: 15 | name: Publish binary builds 16 | runs-on: ubuntu-latest 17 | strategy: 18 | matrix: 19 | target: ["x86_64-unknown-linux-gnu", "i686-unknown-linux-gnu", "aarch64-unknown-linux-gnu", "armv7-unknown-linux-gnueabihf", "x86_64-pc-windows-gnu"] 20 | steps: 21 | - uses: actions/checkout@v2 22 | - name: Install rust 1.70.0 23 | uses: actions-rs/toolchain@v1 24 | with: 25 | toolchain: 1.70.0 26 | override: true 27 | - name: Download renamer 28 | run: curl -sSf https://raw.githubusercontent.com/memflow/memflowup/master/target_rename.sh > target_rename.sh 29 | - name: Build artifacts 30 | uses: actions-rs/cargo@v1 31 | with: 32 | use-cross: true 33 | command: build 34 | args: --release --all-features --workspace --verbose --target ${{ matrix.target }} 35 | - name: Rename and collect artifacts 36 | id: artifacts 37 | run: echo "::set-output name=artifact::$(sh ./target_rename.sh "${{ matrix.target }}" | head -n 1)" 38 | - name: Upload build artifacts 39 | uses: softprops/action-gh-release@v1 40 | with: 41 | tag_name: bin-${{ github.ref_name }} 42 | files: | 43 | ${{ steps.artifacts.outputs.artifact }} 44 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-win32/.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Build and test 2 | 3 | on: [push, pull_request] 4 | 5 | env: 6 | CARGO_TERM_COLOR: always 7 | 8 | jobs: 9 | 10 | build: 11 | runs-on: ${{ matrix.os }} 12 | strategy: 13 | matrix: 14 | os: [macos-latest, ubuntu-latest, windows-latest] 15 | flags: [--all-features, --no-default-features] 16 | steps: 17 | - uses: actions/checkout@v2 18 | - name: Install rust 1.70.0 19 | uses: actions-rs/toolchain@v1 20 | with: 21 | toolchain: 1.70.0 22 | override: true 23 | 24 | - name: Build 25 | run: cargo build --workspace ${{ matrix.flags }} --verbose 26 | 27 | - name: Build examples 28 | run: cargo build --workspace ${{ matrix.flags }} --examples --verbose 29 | 30 | build-cross-targets: 31 | runs-on: ubuntu-latest 32 | strategy: 33 | fail-fast: false 34 | matrix: 35 | target: [aarch64-unknown-linux-gnu, armv7-unknown-linux-gnueabihf, i686-unknown-linux-gnu] 36 | steps: 37 | - uses: actions/checkout@v2 38 | - uses: actions-rs/toolchain@v1 39 | with: 40 | toolchain: 1.70.0 41 | target: ${{ matrix.target }} 42 | override: true 43 | - uses: actions-rs/cargo@v1 44 | with: 45 | use-cross: true 46 | command: build 47 | args: --target ${{ matrix.target }} --workspace --all-features --verbose 48 | 49 | test: 50 | runs-on: ${{ matrix.os }} 51 | strategy: 52 | matrix: 53 | os: [macos-latest, ubuntu-latest, windows-latest] 54 | steps: 55 | - uses: actions/checkout@v2 56 | - name: Install rust 1.70.0 57 | uses: actions-rs/toolchain@v1 58 | with: 59 | toolchain: 1.70.0 60 | override: true 61 | 62 | - name: Pre-build binaries (for inventory integration tests) 63 | run: cargo build --workspace --all-features --verbose 64 | 65 | - name: Run all tests 66 | run: cargo test --workspace --all-features --verbose 67 | if: runner.os == 'Linux' 68 | 69 | - name: Run all tests 70 | run: cargo test --workspace --exclude memflow-derive --all-features --verbose 71 | if: runner.os != 'Linux' 72 | 73 | test-cross: 74 | runs-on: ubuntu-latest 75 | strategy: 76 | fail-fast: false 77 | matrix: 78 | target: [aarch64-unknown-linux-gnu, i686-unknown-linux-gnu] 79 | steps: 80 | - uses: actions/checkout@v2 81 | - uses: actions-rs/toolchain@v1 82 | with: 83 | toolchain: nightly # currently required due to -Zdoctest-xcompile 84 | target: ${{ matrix.target }} 85 | override: true 86 | - name: Pre-build binaries (for inventory integration tests) 87 | uses: actions-rs/cargo@v1 88 | with: 89 | use-cross: true 90 | command: build 91 | args: --target ${{ matrix.target }} --workspace --all-features --verbose --release 92 | - name: Run all tests 93 | uses: actions-rs/cargo@v1 94 | with: 95 | use-cross: true 96 | command: test 97 | args: -Zdoctest-xcompile --target ${{ matrix.target }} --workspace --all-features --verbose --release 98 | 99 | lint: 100 | runs-on: ubuntu-latest 101 | steps: 102 | - uses: actions/checkout@v2 103 | - uses: actions-rs/toolchain@v1 104 | with: 105 | toolchain: 1.70.0 106 | override: true 107 | components: rustfmt, clippy 108 | - run: rustup component add clippy 109 | - name: Check formatting 110 | run: cargo fmt -- --check 111 | - uses: actions-rs/clippy-check@v1 112 | with: 113 | token: ${{ secrets.GITHUB_TOKEN }} 114 | args: --all-targets --all-features --workspace -- -D clippy::all 115 | 116 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-win32/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | **/*.rs.bk 3 | *.swp 4 | *.so 5 | *.dll 6 | *.dylib 7 | .vscode 8 | *.so 9 | .vagrant 10 | TODO.md 11 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-win32/Cargo.toml: -------------------------------------------------------------------------------- 1 | [profile.bench] 2 | debug = true 3 | 4 | [workspace] 5 | resolver = "1" 6 | 7 | members = [ 8 | "memflow-win32", 9 | "memflow-win32-defs", 10 | ] 11 | 12 | default-members = [ 13 | "memflow-win32", 14 | "memflow-win32-defs", 15 | ] 16 | 17 | # [patch.crates-io] 18 | # memflow = { path = "../memflow/memflow" } 19 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-win32/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020-2022 ko1N 4 | Copyright (c) 2020-2022 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/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 | Examples can be found in the `memflow-win32/examples` subdirectory. 11 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-win32/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/local/lib/memflow" 8 | if [[ ! -d /usr/local/lib/memflow ]]; then 9 | sudo mkdir /usr/local/lib/memflow 10 | fi 11 | sudo cp target/release/libmemflow_win32.so /usr/local/lib/memflow/libmemflow_win32.7.so 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_win32.so ~/.local/lib/memflow/libmemflow_win32.7.so 20 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-win32/memflow-win32-defs/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "memflow-win32-defs" 3 | version = "0.2.0" 4 | authors = ["ko1N ", "Aurimas Blažulionis <0x60@pm.me>"] 5 | edition = "2018" 6 | description = "static offset templates for " 7 | documentation = "https://docs.rs/memflow-win32-defs" 8 | readme = "../README.md" 9 | homepage = "https://memflow.io" 10 | repository = "https://github.com/memflow/memflow-win32" 11 | license = "MIT" 12 | keywords = [ "memflow", "introspection", "memory", "dma" ] 13 | categories = [ "api-bindings", "memory-management", "os" ] 14 | 15 | [dependencies] 16 | memflow = { version = "0.2", default-features = false } 17 | log = { version = "^0.4.14", default-features = false } 18 | no-std-compat = { version = "^0.4.1", features = ["alloc"] } 19 | serde = { version = "^1.0.133", default-features = false, optional = true, features = ["derive"] } 20 | 21 | # symbolstore 22 | dirs = { version = "^5.0.0", optional = true } 23 | ureq = { version = "^2.4.0", optional = true } 24 | pdb = { version = "^0.8.0", optional = true } 25 | indicatif = { version = "^0.17.2", optional = true } 26 | progress-streams = { version = "^1.1.0", optional = true } 27 | 28 | [dev_dependencies] 29 | simplelog = "^0.12.0" 30 | clap = { version = "^4.0.26", features = ["cargo"] } 31 | toml = "^0.8.8" 32 | 33 | [features] 34 | default = ["symstore", "download_progress"] 35 | std = ["no-std-compat/std"] 36 | symstore = ["dirs", "ureq", "pdb", "std"] 37 | download_progress = ["indicatif", "progress-streams"] 38 | 39 | [[example]] 40 | name = "generate_offsets" 41 | path = "examples/generate_offsets.rs" 42 | required-features = ["symstore", "serde"] 43 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-win32/memflow-win32-defs/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![cfg_attr(not(feature = "std"), no_std)] 2 | extern crate no_std_compat as std; 3 | 4 | pub mod kernel; 5 | pub mod offsets; 6 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-win32/memflow-win32/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "memflow-win32" 3 | version = "0.2.0" 4 | authors = ["ko1N ", "Aurimas Blažulionis <0x60@pm.me>"] 5 | edition = "2021" 6 | rust-version = "1.65" 7 | description = "win32 integration of the memflow physical memory introspection framework" 8 | documentation = "https://docs.rs/memflow-win32" 9 | readme = "../README.md" 10 | homepage = "https://memflow.io" 11 | repository = "https://github.com/memflow/memflow-win32" 12 | license = "MIT" 13 | keywords = [ "memflow", "introspection", "memory", "dma" ] 14 | categories = [ "api-bindings", "memory-management", "os" ] 15 | 16 | [badges] 17 | maintenance = { status = "actively-developed" } 18 | codecov = { repository = "github", branch = "master", service = "github" } 19 | 20 | [lib] 21 | crate-type = ["lib", "cdylib"] 22 | 23 | [dependencies] 24 | memflow = { version = "0.2", default-features = false } 25 | log = { version = "^0.4.14", default-features = false } 26 | pelite = { version = "^0.10.0", default-features = false } 27 | widestring = { version = "^1.0.2", default-features = false, features = ["alloc"] } 28 | no-std-compat = { version = "^0.4.1", features = ["alloc"] } 29 | serde = { version = "^1.0.133", default-features = false, optional = true, features = ["derive"] } 30 | memflow-win32-defs = { version = "0.2", path = "../memflow-win32-defs", default-features = false } 31 | 32 | # will be replaced by our own signature scanner 33 | regex = { version = "^1.5.0", optional = true } 34 | 35 | [dev_dependencies] 36 | simplelog = "^0.12.0" 37 | rand = "^0.8.4" 38 | rand_xorshift = "^0.3.0" 39 | clap = { version = "^4.0.26", features = ["cargo"] } 40 | toml = "^0.7.3" 41 | 42 | [build_dependencies] 43 | toml = "^0.7.3" 44 | serde = { version = "^1.0.133", default-features = false, features = ["derive", "alloc"] } 45 | memflow = { version = "0.2", default-features = false } 46 | memflow-win32-defs = { version = "0.2", path = "../memflow-win32-defs", features = ["symstore"] } 47 | 48 | [features] 49 | default = ["std", "serde_derive", "embed_offsets", "symstore", "download_progress", "regex", "memflow/default"] 50 | std = ["no-std-compat/std", "memflow/std", "pelite/std"] 51 | plugins = ["memflow/plugins"] 52 | embed_offsets = ["serde", "memflow/serde_derive", "memflow-win32-defs/serde"] 53 | serde_derive = ["serde", "memflow/serde_derive", "pelite/std", "pelite/serde", "memflow-win32-defs/serde"] 54 | symstore = ["memflow-win32-defs/symstore"] 55 | download_progress = ["memflow-win32-defs/download_progress"] 56 | 57 | [[example]] 58 | name = "dump_offsets" 59 | path = "examples/dump_offsets.rs" 60 | required-features = ["memflow/serde_derive"] 61 | 62 | [[example]] 63 | name = "open_process" 64 | path = "examples/open_process.rs" 65 | required-features = ["memflow/plugins"] 66 | 67 | [[example]] 68 | name = "process_list" 69 | path = "examples/process_list.rs" 70 | required-features = ["memflow/plugins"] 71 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-win32/memflow-win32/examples/open_process.rs: -------------------------------------------------------------------------------- 1 | /*! 2 | This example shows how to use a dynamically loaded connector in conjunction 3 | with memflow-win32. This example uses the `Inventory` feature of memflow 4 | but hard-wires the connector instance into the memflow-win32 OS layer. 5 | 6 | The example showcases how to retrieve extended process info data, 7 | opening the process and getting a list of all modules. 8 | 9 | # Usage: 10 | ```bash 11 | cargo run --release --example open_process -- -vv -c kvm -p "explorer.exe" 12 | ``` 13 | */ 14 | use clap::*; 15 | use log::{info, Level}; 16 | 17 | use memflow::prelude::v1::*; 18 | use memflow_win32::prelude::v1::*; 19 | 20 | pub fn main() -> Result<()> { 21 | let matches = parse_args(); 22 | let (chain, process_name) = extract_args(&matches)?; 23 | let process_name = process_name.unwrap_or("explorer.exe"); 24 | 25 | // create inventory + connector 26 | let inventory = Inventory::scan(); 27 | let connector = inventory.builder().connector_chain(chain).build()?; 28 | 29 | let mut os = Win32Kernel::builder(connector) 30 | .build_default_caches() 31 | .build() 32 | .expect("unable to initialize memflow-win32"); 33 | 34 | // display the extended process info for the process 35 | let process_info = os.process_info_by_name(process_name)?; 36 | let process_info_ext = os.process_info_from_base_info(process_info.clone())?; 37 | info!("{:?}", process_info_ext); 38 | 39 | // create a new process instance 40 | let mut process = os 41 | .into_process_by_info(process_info) 42 | .expect("unable to open process"); 43 | 44 | // retrieve all modules 45 | let module_list = process.module_list().expect("unable to read module list"); 46 | 47 | info!("{:>5} {:>10} {:^32} {:<}", "ADDR", "BASE", "NAME", "PATH"); 48 | 49 | for m in module_list { 50 | info!("{:>5} {:^16} {:^32} {}", m.address, m.base, m.name, m.path); 51 | } 52 | 53 | Ok(()) 54 | } 55 | 56 | fn parse_args() -> ArgMatches { 57 | Command::new("dump_offsets example") 58 | .version(crate_version!()) 59 | .author(crate_authors!()) 60 | .arg(Arg::new("verbose").short('v').action(ArgAction::Count)) 61 | .arg( 62 | Arg::new("connector") 63 | .short('c') 64 | .action(ArgAction::Append) 65 | .required(true), 66 | ) 67 | .arg(Arg::new("os").short('o').action(ArgAction::Append)) 68 | .arg(Arg::new("process").short('p').action(ArgAction::Set)) 69 | .get_matches() 70 | } 71 | 72 | fn extract_args(matches: &ArgMatches) -> Result<(ConnectorChain<'_>, Option<&str>)> { 73 | let log_level = match matches.get_count("verbose") { 74 | 0 => Level::Error, 75 | 1 => Level::Warn, 76 | 2 => Level::Info, 77 | 3 => Level::Debug, 78 | 4 => Level::Trace, 79 | _ => Level::Trace, 80 | }; 81 | simplelog::TermLogger::init( 82 | log_level.to_level_filter(), 83 | simplelog::Config::default(), 84 | simplelog::TerminalMode::Stdout, 85 | simplelog::ColorChoice::Auto, 86 | ) 87 | .unwrap(); 88 | 89 | let conn_iter = matches 90 | .indices_of("connector") 91 | .zip(matches.get_many::("connector")) 92 | .map(|(a, b)| a.zip(b.map(String::as_str))) 93 | .into_iter() 94 | .flatten(); 95 | 96 | let os_iter = matches 97 | .indices_of("os") 98 | .zip(matches.get_many::("os")) 99 | .map(|(a, b)| a.zip(b.map(String::as_str))) 100 | .into_iter() 101 | .flatten(); 102 | 103 | Ok(( 104 | ConnectorChain::new(conn_iter, os_iter)?, 105 | matches.get_one::("process").map(String::as_str), 106 | )) 107 | } 108 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-win32/memflow-win32/examples/process_list.rs: -------------------------------------------------------------------------------- 1 | /*! 2 | This example shows how to use a dynamically loaded connector in conjunction 3 | with memflow-win32. This example uses the `Inventory` feature of memflow 4 | but hard-wires the connector instance into the memflow-win32 OS layer. 5 | 6 | The example is an adaption of the memflow core process list example: 7 | https://github.com/memflow/memflow/blob/next/memflow/examples/process_list.rs 8 | 9 | # Usage: 10 | ```bash 11 | cargo run --release --example process_list -- -vv -c kvm 12 | ``` 13 | */ 14 | use clap::*; 15 | use log::{info, Level}; 16 | 17 | use memflow::prelude::v1::*; 18 | use memflow_win32::prelude::v1::*; 19 | 20 | pub fn main() -> Result<()> { 21 | let matches = parse_args(); 22 | let chain = extract_args(&matches)?; 23 | 24 | // create inventory + connector 25 | let inventory = Inventory::scan(); 26 | let connector = inventory.builder().connector_chain(chain).build()?; 27 | 28 | let mut os = Win32Kernel::builder(connector) 29 | .build_default_caches() 30 | .build() 31 | .unwrap(); 32 | 33 | let process_list = os.process_info_list().expect("unable to read process list"); 34 | 35 | info!( 36 | "{:>5} {:>10} {:>10} {:<}", 37 | "PID", "SYS ARCH", "PROC ARCH", "NAME" 38 | ); 39 | 40 | for p in process_list { 41 | info!( 42 | "{:>5} {:^10} {:^10} {}", 43 | p.pid, p.sys_arch, p.proc_arch, p.name 44 | ); 45 | } 46 | 47 | Ok(()) 48 | } 49 | 50 | fn parse_args() -> ArgMatches { 51 | Command::new("process_list example") 52 | .version(crate_version!()) 53 | .author(crate_authors!()) 54 | .arg(Arg::new("verbose").short('v').action(ArgAction::Count)) 55 | .arg( 56 | Arg::new("connector") 57 | .short('c') 58 | .action(ArgAction::Append) 59 | .required(true), 60 | ) 61 | .arg(Arg::new("os").short('o').action(ArgAction::Append)) 62 | .get_matches() 63 | } 64 | 65 | fn extract_args(matches: &ArgMatches) -> Result> { 66 | let log_level = match matches.get_count("verbose") { 67 | 0 => Level::Error, 68 | 1 => Level::Warn, 69 | 2 => Level::Info, 70 | 3 => Level::Debug, 71 | 4 => Level::Trace, 72 | _ => Level::Trace, 73 | }; 74 | simplelog::TermLogger::init( 75 | log_level.to_level_filter(), 76 | simplelog::Config::default(), 77 | simplelog::TerminalMode::Stdout, 78 | simplelog::ColorChoice::Auto, 79 | ) 80 | .unwrap(); 81 | 82 | let conn_iter = matches 83 | .indices_of("connector") 84 | .zip(matches.get_many::("connector")) 85 | .map(|(a, b)| a.zip(b.map(String::as_str))) 86 | .into_iter() 87 | .flatten(); 88 | 89 | let os_iter = matches 90 | .indices_of("os") 91 | .zip(matches.get_many::("os")) 92 | .map(|(a, b)| a.zip(b.map(String::as_str))) 93 | .into_iter() 94 | .flatten(); 95 | 96 | ConnectorChain::new(conn_iter, os_iter) 97 | } 98 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-win32/memflow-win32/offsets/10_0_18362_X64_0AFB69F5FD264D54673570E37B38A3181.toml: -------------------------------------------------------------------------------- 1 | [header] 2 | pdb_file_name = "ntkrnlmp.pdb" 3 | pdb_guid = "0AFB69F5FD264D54673570E37B38A3181" 4 | nt_major_version = 10 5 | nt_minor_version = 0 6 | nt_build_number = 18362 7 | arch = "X64" 8 | 9 | [offsets] 10 | list_blink = 8 11 | eproc_link = 752 12 | phys_mem_block = 5719112 13 | kproc_dtb = 40 14 | eproc_pid = 744 15 | eproc_name = 1104 16 | eproc_peb = 1016 17 | eproc_section_base = 968 18 | eproc_exit_status = 1620 19 | eproc_thread_list = 1160 20 | eproc_wow64 = 1064 21 | eproc_vad_root = 1624 22 | kthread_teb = 240 23 | ethread_list_entry = 1720 24 | teb_peb = 96 25 | teb_peb_x86 = 48 26 | 27 | [offsets.mmvad] 28 | vad_node = 0 29 | starting_vpn = 24 30 | ending_vpn = 28 31 | starting_vpn_high = 32 32 | ending_vpn_high = 33 33 | u = 48 34 | protection_bit = 7 35 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-win32/memflow-win32/offsets/10_0_19041_X64_1C9875F76C8F0FBF3EB9A9D7C1C274061.toml: -------------------------------------------------------------------------------- 1 | [header] 2 | pdb_file_name = "ntkrnlmp.pdb" 3 | pdb_guid = "1C9875F76C8F0FBF3EB9A9D7C1C274061" 4 | nt_major_version = 10 5 | nt_minor_version = 0 6 | nt_build_number = 19041 7 | arch = "X64" 8 | 9 | [offsets] 10 | list_blink = 8 11 | eproc_link = 1096 12 | phys_mem_block = 13612224 13 | kproc_dtb = 40 14 | eproc_pid = 1088 15 | eproc_name = 1448 16 | eproc_peb = 1360 17 | eproc_section_base = 1312 18 | eproc_exit_status = 2004 19 | eproc_thread_list = 1504 20 | eproc_wow64 = 1408 21 | eproc_vad_root = 2008 22 | kthread_teb = 240 23 | ethread_list_entry = 1256 24 | teb_peb = 96 25 | teb_peb_x86 = 48 26 | 27 | [offsets.mmvad] 28 | vad_node = 0 29 | starting_vpn = 24 30 | ending_vpn = 28 31 | starting_vpn_high = 32 32 | ending_vpn_high = 33 33 | u = 48 34 | protection_bit = 7 35 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-win32/memflow-win32/offsets/10_0_19041_X64_9C00B19DBDE003DBFE4AB4216993C8431.toml: -------------------------------------------------------------------------------- 1 | [header] 2 | pdb_file_name = "ntkrnlmp.pdb" 3 | pdb_guid = "9C00B19DBDE003DBFE4AB4216993C8431" 4 | nt_major_version = 10 5 | nt_minor_version = 0 6 | nt_build_number = 19041 7 | arch = "X64" 8 | 9 | [offsets] 10 | list_blink = 8 11 | eproc_link = 1096 12 | phys_mem_block = 13616296 13 | kproc_dtb = 40 14 | eproc_pid = 1088 15 | eproc_name = 1448 16 | eproc_peb = 1360 17 | eproc_section_base = 1312 18 | eproc_exit_status = 2004 19 | eproc_thread_list = 1504 20 | eproc_wow64 = 1408 21 | eproc_vad_root = 2008 22 | kthread_teb = 240 23 | ethread_list_entry = 1256 24 | teb_peb = 96 25 | teb_peb_x86 = 48 26 | 27 | [offsets.mmvad] 28 | vad_node = 0 29 | starting_vpn = 24 30 | ending_vpn = 28 31 | starting_vpn_high = 32 32 | ending_vpn_high = 33 33 | u = 48 34 | protection_bit = 7 35 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-win32/memflow-win32/offsets/10_0_19041_X64_BBED7C2955FBE4522AAA23F4B8677AD91.toml: -------------------------------------------------------------------------------- 1 | [header] 2 | pdb_file_name = "ntkrnlmp.pdb" 3 | pdb_guid = "BBED7C2955FBE4522AAA23F4B8677AD91" 4 | nt_major_version = 10 5 | nt_minor_version = 0 6 | nt_build_number = 19041 7 | arch = "X64" 8 | 9 | [offsets] 10 | list_blink = 8 11 | eproc_link = 1096 12 | phys_mem_block = 13612224 13 | kproc_dtb = 40 14 | eproc_pid = 1088 15 | eproc_name = 1448 16 | eproc_peb = 1360 17 | eproc_section_base = 1312 18 | eproc_exit_status = 2004 19 | eproc_thread_list = 1504 20 | eproc_wow64 = 1408 21 | eproc_vad_root = 2008 22 | kthread_teb = 240 23 | ethread_list_entry = 1256 24 | teb_peb = 96 25 | teb_peb_x86 = 48 26 | 27 | [offsets.mmvad] 28 | vad_node = 0 29 | starting_vpn = 24 30 | ending_vpn = 28 31 | starting_vpn_high = 32 32 | ending_vpn_high = 33 33 | u = 48 34 | protection_bit = 7 35 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-win32/memflow-win32/offsets/10_0_19041_X86_1B1D6AA205E1C87DC63A314ACAA50B491.toml: -------------------------------------------------------------------------------- 1 | [header] 2 | pdb_file_name = "ntkrpamp.pdb" 3 | pdb_guid = "1B1D6AA205E1C87DC63A314ACAA50B491" 4 | nt_major_version = 10 5 | nt_minor_version = 0 6 | nt_build_number = 19041 7 | arch = "X86" 8 | 9 | [offsets] 10 | list_blink = 4 11 | eproc_link = 232 12 | phys_mem_block = 3225556 13 | kproc_dtb = 24 14 | eproc_pid = 228 15 | eproc_name = 428 16 | eproc_peb = 380 17 | eproc_section_base = 352 18 | eproc_exit_status = 844 19 | eproc_thread_list = 464 20 | eproc_wow64 = 0 21 | eproc_vad_root = 848 22 | kthread_teb = 168 23 | ethread_list_entry = 740 24 | teb_peb = 48 25 | teb_peb_x86 = 48 26 | 27 | [offsets.mmvad] 28 | vad_node = 0 29 | starting_vpn = 12 30 | ending_vpn = 16 31 | starting_vpn_high = 0 32 | ending_vpn_high = 0 33 | u = 28 34 | protection_bit = 7 35 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-win32/memflow-win32/offsets/10_0_19045_X64_5F0CF5D532F385333A9B4ABA25CA65961.toml: -------------------------------------------------------------------------------- 1 | [header] 2 | pdb_file_name = 'ntkrnlmp.pdb' 3 | pdb_guid = '5F0CF5D532F385333A9B4ABA25CA65961' 4 | nt_major_version = 10 5 | nt_minor_version = 0 6 | nt_build_number = 19045 7 | arch = 'X64' 8 | 9 | [offsets] 10 | list_blink = 8 11 | eproc_link = 1096 12 | phys_mem_block = 13612216 13 | kproc_dtb = 40 14 | eproc_pid = 1088 15 | eproc_name = 1448 16 | eproc_peb = 1360 17 | eproc_section_base = 1312 18 | eproc_exit_status = 2004 19 | eproc_thread_list = 1504 20 | eproc_wow64 = 1408 21 | eproc_vad_root = 2008 22 | kthread_teb = 240 23 | ethread_list_entry = 1256 24 | teb_peb = 96 25 | teb_peb_x86 = 48 26 | 27 | [offsets.mmvad] 28 | vad_node = 0 29 | starting_vpn = 24 30 | ending_vpn = 28 31 | starting_vpn_high = 32 32 | ending_vpn_high = 33 33 | u = 48 34 | protection_bit = 7 35 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-win32/memflow-win32/offsets/10_0_22000_X86_55678BC384F099B6ED05E9E39046924A1.toml: -------------------------------------------------------------------------------- 1 | [header] 2 | pdb_file_name = "ntkrnlmp.pdb" 3 | pdb_guid = "55678BC384F099B6ED05E9E39046924A1" 4 | nt_major_version = 10 5 | nt_minor_version = 0 6 | nt_build_number = 22000 7 | arch = "X86" 8 | 9 | [offsets] 10 | list_blink = 8 11 | eproc_link = 1096 12 | phys_mem_block = 13658416 13 | kproc_dtb = 40 14 | eproc_pid = 1088 15 | eproc_name = 1448 16 | eproc_peb = 1360 17 | eproc_section_base = 1312 18 | eproc_exit_status = 2004 19 | eproc_thread_list = 1504 20 | eproc_wow64 = 1408 21 | eproc_vad_root = 2008 22 | kthread_teb = 240 23 | ethread_list_entry = 1336 24 | teb_peb = 96 25 | teb_peb_x86 = 48 26 | 27 | [offsets.mmvad] 28 | vad_node = 0 29 | starting_vpn = 24 30 | ending_vpn = 28 31 | starting_vpn_high = 32 32 | ending_vpn_high = 33 33 | u = 48 34 | protection_bit = 7 35 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-win32/memflow-win32/offsets/3_10_511_X86.toml: -------------------------------------------------------------------------------- 1 | [header] 2 | nt_major_version = 3 3 | nt_minor_version = 10 4 | nt_build_number = 511 5 | arch = 'X86' 6 | 7 | [offsets] 8 | phys_mem_block = 0 9 | 10 | list_blink = 4 11 | eproc_link = 0xb4 12 | 13 | kproc_dtb = 0x38 14 | eproc_pid = 0xb0 15 | eproc_name = 0x228 16 | eproc_peb = 0x1c0 17 | eproc_section_base = 0x1c4 18 | eproc_exit_status = 0 #5.1+ 19 | eproc_thread_list = 0 #5.1+ 20 | eproc_wow64 = 0 #5.0+ 21 | eproc_vad_root = 0x01a4 #3.10+ 22 | 23 | kthread_teb = 0 #6.2+ 24 | ethread_list_entry = 0x0 #5.0+ 25 | teb_peb = 0 #? 26 | teb_peb_x86 = 0 #? 27 | 28 | [offsets.mmvad] 29 | vad_node = 12 30 | starting_vpn = 0 31 | ending_vpn = 4 32 | starting_vpn_high = 0 33 | ending_vpn_high = 0 34 | u = 20 35 | protection_bit = 0 36 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-win32/memflow-win32/offsets/4_0_1381_X86.toml: -------------------------------------------------------------------------------- 1 | [header] 2 | nt_major_version = 4 3 | nt_minor_version = 0 4 | nt_build_number = 1381 5 | arch = 'X86' 6 | 7 | [offsets] 8 | phys_mem_block = 0 9 | 10 | list_blink = 4 11 | eproc_link = 0x98 12 | 13 | kproc_dtb = 0x18 14 | eproc_pid = 0x94 15 | eproc_name = 0x1dc 16 | eproc_peb = 0x18c 17 | eproc_section_base = 0x190 18 | eproc_exit_status = 0 #5.1+ 19 | eproc_thread_list = 0 #5.1+ 20 | eproc_wow64 = 0 #5.0+ 21 | eproc_vad_root = 0x0170 #3.10+ 22 | 23 | kthread_teb = 0 #6.2+ 24 | ethread_list_entry = 0x0 #5.0+ 25 | teb_peb = 0 #? 26 | teb_peb_x86 = 0 #? 27 | 28 | [offsets.mmvad] 29 | vad_node = 12 30 | starting_vpn = 0 31 | ending_vpn = 4 32 | starting_vpn_high = 0 33 | ending_vpn_high = 0 34 | u = 20 35 | protection_bit = 0 36 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-win32/memflow-win32/offsets/5_2_3790_X64_82DCF67A38274C9CA99B60B421D2786D2.toml: -------------------------------------------------------------------------------- 1 | [header] 2 | pdb_file_name = "ntkrnlmp.pdb" 3 | pdb_guid = "82DCF67A38274C9CA99B60B421D2786D2" 4 | nt_major_version = 5 5 | nt_minor_version = 2 6 | nt_build_number = 3790 7 | arch = "X64" 8 | 9 | [offsets] 10 | list_blink = 8 11 | eproc_link = 224 12 | phys_mem_block = 1921104 13 | kproc_dtb = 40 14 | eproc_pid = 216 15 | eproc_name = 616 16 | eproc_peb = 704 17 | eproc_section_base = 504 18 | eproc_exit_status = 908 19 | eproc_thread_list = 656 20 | eproc_wow64 = 680 21 | eproc_vad_root = 920 22 | kthread_teb = 176 23 | ethread_list_entry = 976 24 | teb_peb = 96 25 | teb_peb_x86 = 48 26 | 27 | [offsets.mmvad] 28 | vad_node = 8 29 | starting_vpn = 24 30 | ending_vpn = 32 31 | starting_vpn_high = 0 32 | ending_vpn_high = 0 33 | u = 40 34 | protection_bit = 56 35 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-win32/memflow-win32/offsets/6_1_7601_X64_ECE191A20CFF4465AE46DF96C22638451.toml: -------------------------------------------------------------------------------- 1 | [header] 2 | pdb_file_name = "ntkrnlmp.pdb" 3 | pdb_guid = "ECE191A20CFF4465AE46DF96C22638451" 4 | nt_major_version = 6 5 | nt_minor_version = 1 6 | nt_build_number = 7601 7 | arch = "X64" 8 | 9 | [offsets] 10 | list_blink = 8 11 | eproc_link = 392 12 | phys_mem_block = 2740280 13 | kproc_dtb = 40 14 | eproc_pid = 384 15 | eproc_name = 736 16 | eproc_peb = 824 17 | eproc_section_base = 624 18 | eproc_exit_status = 1092 19 | eproc_thread_list = 776 20 | eproc_wow64 = 800 21 | eproc_vad_root = 1096 22 | kthread_teb = 184 23 | ethread_list_entry = 1064 24 | teb_peb = 96 25 | teb_peb_x86 = 48 26 | 27 | [offsets.mmvad] 28 | vad_node = 8 29 | starting_vpn = 24 30 | ending_vpn = 32 31 | starting_vpn_high = 0 32 | ending_vpn_high = 0 33 | u = 40 34 | protection_bit = 56 35 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-win32/memflow-win32/offsets/6_1_7601_X86_684DA42A30CC450F81C535B4D18944B12.toml: -------------------------------------------------------------------------------- 1 | [header] 2 | pdb_file_name = "ntkrpamp.pdb" 3 | pdb_guid = "684DA42A30CC450F81C535B4D18944B12" 4 | nt_major_version = 6 5 | nt_minor_version = 1 6 | nt_build_number = 7601 7 | arch = "X86" 8 | 9 | [offsets] 10 | list_blink = 4 11 | eproc_link = 184 12 | phys_mem_block = 1484392 13 | kproc_dtb = 24 14 | eproc_pid = 180 15 | eproc_name = 364 16 | eproc_peb = 424 17 | eproc_section_base = 300 18 | eproc_exit_status = 628 19 | eproc_thread_list = 392 20 | eproc_wow64 = 0 21 | eproc_vad_root = 632 22 | kthread_teb = 136 23 | ethread_list_entry = 616 24 | teb_peb = 48 25 | teb_peb_x86 = 48 26 | 27 | [offsets.mmvad] 28 | vad_node = 4 29 | starting_vpn = 12 30 | ending_vpn = 16 31 | starting_vpn_high = 0 32 | ending_vpn_high = 0 33 | u = 20 34 | protection_bit = 24 35 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-win32/memflow-win32/src/kernel/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod ntos; 2 | pub mod start_block; 3 | pub mod sysproc; 4 | 5 | pub use memflow_win32_defs::kernel::*; 6 | pub use start_block::StartBlock; 7 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-win32/memflow-win32/src/kernel/ntos/pehelper.rs: -------------------------------------------------------------------------------- 1 | use std::convert::TryInto; 2 | use std::prelude::v1::*; 3 | 4 | use log::debug; 5 | 6 | use memflow::error::{Error, ErrorKind, ErrorOrigin, PartialResultExt, Result}; 7 | use memflow::mem::MemoryView; 8 | use memflow::types::{size, umem, Address}; 9 | 10 | use pelite::{self, PeView}; 11 | 12 | pub fn try_get_pe_size(mem: &mut T, probe_addr: Address) -> Result { 13 | let mut probe_buf = vec![0; size::kb(4)]; 14 | mem.read_raw_into(probe_addr, &mut probe_buf)?; 15 | 16 | let pe_probe = PeView::from_bytes(&probe_buf) 17 | .map_err(|err| Error(ErrorOrigin::OsLayer, ErrorKind::InvalidExeFile).log_trace(err))?; 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 umem) 30 | } else { 31 | Err(Error(ErrorOrigin::OsLayer, ErrorKind::InvalidExeFile) 32 | .log_trace("pe size_of_image is zero")) 33 | } 34 | } 35 | 36 | pub fn try_get_pe_image(mem: &mut T, probe_addr: Address) -> Result> { 37 | let size_of_image = try_get_pe_size(mem, probe_addr)?; 38 | mem.read_raw(probe_addr, size_of_image.try_into().unwrap()) 39 | .data_part() 40 | } 41 | 42 | pub fn try_get_pe_name(mem: &mut T, probe_addr: Address) -> Result { 43 | let image = try_get_pe_image(mem, probe_addr)?; 44 | let pe = PeView::from_bytes(&image) 45 | .map_err(|err| Error(ErrorOrigin::OsLayer, ErrorKind::InvalidExeFile).log_trace(err))?; 46 | let name = pe 47 | .exports() 48 | .map_err(|_| { 49 | Error(ErrorOrigin::OsLayer, ErrorKind::InvalidExeFile) 50 | .log_trace("unable to get exports") 51 | })? 52 | .dll_name() 53 | .map_err(|_| { 54 | Error(ErrorOrigin::OsLayer, ErrorKind::InvalidExeFile) 55 | .log_trace("unable to get dll name") 56 | })? 57 | .to_str() 58 | .map_err(|_| { 59 | Error(ErrorOrigin::OsLayer, ErrorKind::Encoding) 60 | .log_trace("unable to convert dll name string") 61 | })?; 62 | debug!("try_get_pe_name: found pe header for {}", name); 63 | Ok(name.to_string()) 64 | } 65 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-win32/memflow-win32/src/kernel/ntos/x86.rs: -------------------------------------------------------------------------------- 1 | use std::prelude::v1::*; 2 | 3 | use super::pehelper; 4 | use crate::kernel::StartBlock; 5 | 6 | use memflow::dataview::PodMethods; 7 | use memflow::error::{Error, ErrorKind, ErrorOrigin, PartialResultExt, Result}; 8 | use memflow::mem::MemoryView; 9 | use memflow::types::{size, umem, Address}; 10 | 11 | use log::{debug, info}; 12 | 13 | use pelite::image::IMAGE_DOS_HEADER; 14 | 15 | const SIZE_256MB: usize = size::mb(256); 16 | const SIZE_8MB: usize = size::mb(8); 17 | const SIZE_4KB: usize = size::kb(4); 18 | 19 | // https://github.com/ufrisk/MemProcFS/blob/f2d15cf4fe4f19cfeea3dad52971fae2e491064b/vmm/vmmwininit.c#L410 20 | pub fn find(virt_mem: &mut T, _start_block: &StartBlock) -> Result<(Address, umem)> { 21 | debug!("x86::find: trying to find ntoskrnl.exe"); 22 | 23 | for base_addr in (0..SIZE_256MB).step_by(SIZE_8MB) { 24 | let base_addr = size::gb(2) + base_addr; 25 | // search in each page in the first 8mb chunks in the first 64mb of virtual memory 26 | let mut buf = vec![0; SIZE_8MB]; 27 | virt_mem 28 | .read_raw_into(base_addr.into(), &mut buf) 29 | .data_part()?; 30 | 31 | for addr in (0..SIZE_8MB).step_by(SIZE_4KB) { 32 | // TODO: potential endian mismatch in pod 33 | let view = PodMethods::as_data_view(&buf[addr..]); 34 | 35 | // check for dos header signature (MZ) // TODO: create global 36 | if view.read::(0).e_magic != 0x5a4d { 37 | continue; 38 | } 39 | 40 | if view.read::(0).e_lfanew > 0x800 { 41 | continue; 42 | } 43 | 44 | let image_base = Address::from(base_addr + addr); 45 | if let Ok(name) = pehelper::try_get_pe_name(virt_mem, image_base) { 46 | if name == "ntoskrnl.exe" { 47 | info!("ntoskrnl found"); 48 | // TODO: unify pe name + size 49 | if let Ok(size_of_image) = pehelper::try_get_pe_size(virt_mem, image_base) { 50 | return Ok((image_base, size_of_image)); 51 | } 52 | } 53 | } 54 | } 55 | } 56 | 57 | Err(Error(ErrorOrigin::OsLayer, ErrorKind::ProcessNotFound) 58 | .log_trace("find_x86(): unable to locate ntoskrnl.exe in high mem")) 59 | } 60 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-win32/memflow-win32/src/kernel/start_block.rs: -------------------------------------------------------------------------------- 1 | mod aarch64; 2 | mod x64; 3 | mod x86; 4 | mod x86pae; 5 | 6 | use std::prelude::v1::*; 7 | 8 | use log::warn; 9 | 10 | use memflow::architecture::ArchitectureIdent; 11 | use memflow::error::{Error, ErrorKind, ErrorOrigin, Result}; 12 | use memflow::mem::PhysicalMemory; 13 | use memflow::types::{size, Address, PhysicalAddress}; 14 | 15 | // PROCESSOR_START_BLOCK 16 | #[derive(Debug, Copy, Clone)] 17 | #[cfg_attr(feature = "serde", derive(::serde::Serialize))] 18 | pub struct StartBlock { 19 | pub arch: ArchitectureIdent, 20 | pub kernel_hint: Address, 21 | pub dtb: Address, 22 | } 23 | 24 | pub fn find_fallback( 25 | mem: &mut T, 26 | arch: ArchitectureIdent, 27 | ) -> Result { 28 | match arch { 29 | ArchitectureIdent::X86(64, _) => { 30 | // read low 16mb stub 31 | let mut low16m = vec![0; size::mb(16)]; 32 | mem.phys_read_into(PhysicalAddress::NULL, low16m.as_mut_slice())?; 33 | 34 | x64::find(&low16m) 35 | } 36 | ArchitectureIdent::AArch64(_) => { 37 | // read low 16mb stub 38 | let mut low16m = vec![0; size::mb(16)]; 39 | 40 | //TODO: configure this, but so far arm null starts at this address 41 | mem.phys_read_into(aarch64::PHYS_BASE.into(), low16m.as_mut_slice())?; 42 | 43 | aarch64::find(&low16m) 44 | } 45 | _ => Err(Error(ErrorOrigin::OsLayer, ErrorKind::NotImplemented) 46 | .log_error("start_block: fallback not implemented for given arch")), 47 | } 48 | } 49 | 50 | // bcdedit /set firstmegabytepolicyuseall 51 | pub fn find(mem: &mut T, arch: Option) -> Result { 52 | if let Some(arch) = arch { 53 | match arch { 54 | ArchitectureIdent::X86(64, _) => { 55 | // read low 1mb stub 56 | let mut low1m = vec![0; size::mb(1)]; 57 | mem.phys_read_into(PhysicalAddress::NULL, low1m.as_mut_slice())?; 58 | 59 | // find x64 dtb in low stub < 1M 60 | match x64::find_lowstub(&low1m) { 61 | Ok(d) => { 62 | if d.dtb.to_umem() != 0 { 63 | return Ok(d); 64 | } 65 | } 66 | Err(e) => warn!("x64::find_lowstub() error: {}", e), 67 | } 68 | 69 | find_fallback(mem, arch) 70 | } 71 | ArchitectureIdent::X86(32, true) => { 72 | let mut low16m = vec![0; size::mb(16)]; 73 | mem.phys_read_into(PhysicalAddress::NULL, low16m.as_mut_slice())?; 74 | x86pae::find(&low16m) 75 | } 76 | ArchitectureIdent::X86(32, false) => { 77 | let mut low16m = vec![0; size::mb(16)]; 78 | mem.phys_read_into(PhysicalAddress::NULL, low16m.as_mut_slice())?; 79 | x86::find(&low16m) 80 | } 81 | ArchitectureIdent::AArch64(_) => find_fallback(mem, arch), 82 | _ => Err(Error(ErrorOrigin::OsLayer, ErrorKind::NotSupported) 83 | .log_error("Unsupported architecture")), 84 | } 85 | } else { 86 | find(mem, Some(ArchitectureIdent::X86(64, false))) 87 | .or_else(|_| find(mem, Some(ArchitectureIdent::X86(32, true)))) 88 | .or_else(|_| find(mem, Some(ArchitectureIdent::X86(32, false)))) 89 | .or_else(|_| find(mem, Some(ArchitectureIdent::AArch64(size::kb(4))))) 90 | .map_err(|_| { 91 | Error(ErrorOrigin::OsLayer, ErrorKind::NotFound).log_error("unable to find dtb") 92 | }) 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-win32/memflow-win32/src/kernel/start_block/aarch64.rs: -------------------------------------------------------------------------------- 1 | use crate::kernel::StartBlock; 2 | 3 | use std::convert::TryInto; 4 | 5 | use memflow::architecture::arm::aarch64; 6 | use memflow::error::{Error, ErrorKind, ErrorOrigin, Result}; 7 | use memflow::types::{mem, umem, Address}; 8 | 9 | #[allow(clippy::unnecessary_cast)] 10 | pub const PHYS_BASE: u64 = mem::gb(1) as u64; 11 | 12 | // mem here has to be a single page (4kb sized) 13 | fn find_pt(addr: Address, mem: &[u8]) -> Option
{ 14 | // TODO: global define / config setting 15 | #[allow(clippy::unnecessary_cast)] 16 | let max_mem = mem::gb(512) as u64; 17 | 18 | let pte = u64::from_le_bytes(mem[0..8].try_into().unwrap()); 19 | 20 | if (pte & 0x0000_0000_0000_0fff) != 0xf03 || (pte & 0x0000_ffff_ffff_f000) > max_mem { 21 | return None; 22 | } 23 | 24 | // Second half must have a self ref entry 25 | // This is usually enough to filter wrong data out 26 | #[allow(clippy::unnecessary_cast)] 27 | mem[0x800..] 28 | .chunks(8) 29 | .map(|c| u64::from_le_bytes(c.try_into().unwrap())) 30 | .find(|a| (a ^ 0xf03) & (!0u64 >> 12) == addr.to_umem() as u64)?; 31 | 32 | // A page table does need to have some entries, right? Particularly, kernel-side page table 33 | // entries must exist 34 | mem[0x800..] 35 | .chunks(8) 36 | .map(|c| u64::from_le_bytes(c.try_into().unwrap())) 37 | .filter(|a| (a & 0xfff) == 0x703) 38 | .nth(5)?; 39 | 40 | Some(addr) 41 | } 42 | 43 | pub fn find(mem: &[u8]) -> Result { 44 | mem.chunks_exact(aarch64::ARCH.page_size()) 45 | .enumerate() 46 | .filter_map(|(i, c)| { 47 | find_pt( 48 | Address::from(PHYS_BASE) + (i as umem * aarch64::ARCH.page_size() as umem), 49 | c, 50 | ) 51 | }) 52 | .map(|addr| StartBlock { 53 | arch: aarch64::ARCH.ident(), 54 | kernel_hint: Address::NULL, 55 | dtb: addr, 56 | }) 57 | .next() 58 | .ok_or_else(|| { 59 | Error(ErrorOrigin::OsLayer, ErrorKind::NotFound) 60 | .log_warn("unable to find aarch64 dtb in lowstub < 16M") 61 | }) 62 | } 63 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-win32/memflow-win32/src/kernel/start_block/x64.rs: -------------------------------------------------------------------------------- 1 | use crate::kernel::StartBlock; 2 | 3 | use std::convert::TryInto; 4 | 5 | use memflow::architecture::x86::x64; 6 | use memflow::error::{Error, ErrorKind, ErrorOrigin, Result}; 7 | use memflow::types::{mem, umem, Address}; 8 | 9 | // https://github.com/ufrisk/MemProcFS/blob/f2d15cf4fe4f19cfeea3dad52971fae2e491064b/vmm/vmmwininit.c#L560 10 | pub fn find_lowstub(stub: &[u8]) -> Result { 11 | stub.chunks_exact(x64::ARCH.page_size()) 12 | .skip(1) 13 | .filter(|c| { 14 | (0xffff_ffff_ffff_00ff & u64::from_le_bytes(c[0..8].try_into().unwrap())) 15 | == 0x0000_0001_0006_00E9 16 | }) // start bytes 17 | .filter(|c| { 18 | (0xffff_f800_0000_0003 & u64::from_le_bytes(c[0x70..0x70 + 8].try_into().unwrap())) 19 | == 0xffff_f800_0000_0000 20 | }) // kernel entry 21 | .find(|c| { 22 | (0xffff_ff00_0000_0fff & u64::from_le_bytes(c[0xa0..0xa0 + 8].try_into().unwrap())) == 0 23 | }) // pml4 24 | .map(|c| StartBlock { 25 | arch: x64::ARCH.ident(), 26 | kernel_hint: u64::from_le_bytes(c[0x70..0x70 + 8].try_into().unwrap()).into(), 27 | dtb: u64::from_le_bytes(c[0xa0..0xa0 + 8].try_into().unwrap()).into(), 28 | }) 29 | .ok_or_else(|| { 30 | Error(ErrorOrigin::OsLayer, ErrorKind::NotFound) 31 | .log_warn("unable to find x64 dtb in lowstub < 1M") 32 | }) 33 | } 34 | 35 | fn find_pt(addr: Address, mem: &[u8]) -> Option
{ 36 | // TODO: global define / config setting 37 | #[allow(clippy::unnecessary_cast)] 38 | let max_mem = mem::gb(512) as u64; 39 | 40 | let pte = u64::from_le_bytes(mem[0..8].try_into().unwrap()); 41 | 42 | if (pte & 0x0000_0000_0000_0087) != 0x7 || (pte & 0x0000_ffff_ffff_f000) > max_mem { 43 | return None; 44 | } 45 | 46 | // Second half must have a self ref entry 47 | // This is usually enough to filter wrong data out 48 | #[allow(clippy::unnecessary_cast)] 49 | mem[0x800..] 50 | .chunks(8) 51 | .map(|c| u64::from_le_bytes(c.try_into().unwrap())) 52 | .find(|a| (a ^ 0x0000_0000_0000_0063) & !(1u64 << 63) == addr.to_umem() as u64)?; 53 | 54 | // A page table does need to have some entries, right? Particularly, kernel-side page table 55 | // entries must be marked as such 56 | mem[0x800..] 57 | .chunks(8) 58 | .map(|c| u64::from_le_bytes(c.try_into().unwrap())) 59 | .filter(|a| (a & 0xff) == 0x63) 60 | .nth(5)?; 61 | 62 | Some(addr) 63 | } 64 | 65 | pub fn find(mem: &[u8]) -> Result { 66 | mem.chunks_exact(x64::ARCH.page_size()) 67 | .enumerate() 68 | .filter_map(|(i, c)| find_pt((i as umem * x64::ARCH.page_size() as umem).into(), c)) 69 | .map(|addr| StartBlock { 70 | arch: x64::ARCH.ident(), 71 | kernel_hint: Address::NULL, 72 | dtb: addr, 73 | }) 74 | .next() 75 | .ok_or_else(|| { 76 | Error(ErrorOrigin::OsLayer, ErrorKind::NotFound) 77 | .log_warn("unable to find x64 dtb in lowstub < 16M") 78 | }) 79 | } 80 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-win32/memflow-win32/src/kernel/start_block/x86.rs: -------------------------------------------------------------------------------- 1 | use crate::kernel::StartBlock; 2 | 3 | use std::convert::TryInto; 4 | 5 | use memflow::architecture::x86::x32; 6 | use memflow::error::{Error, ErrorKind, ErrorOrigin, Result}; 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) != TryInto::::try_into(base.to_umem() + 0x3).unwrap() { 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::NULL, x32::ARCH.page_size()) 30 | .find(|(a, c)| check_page(*a, c)) 31 | .map(|(a, _)| StartBlock { 32 | arch: x32::ARCH.ident(), 33 | kernel_hint: Address::NULL, 34 | dtb: a, 35 | }) 36 | .ok_or_else(|| { 37 | Error(ErrorOrigin::OsLayer, ErrorKind::NotFound) 38 | .log_warn("unable to find x86 dtb in lowstub < 16M") 39 | }) 40 | } 41 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-win32/memflow-win32/src/kernel/start_block/x86pae.rs: -------------------------------------------------------------------------------- 1 | use crate::kernel::StartBlock; 2 | 3 | use std::convert::TryInto; 4 | 5 | use memflow::architecture::x86::x32_pae; 6 | use memflow::error::{Error, ErrorKind, ErrorOrigin, Result}; 7 | use memflow::iter::PageChunks; 8 | use memflow::types::Address; 9 | 10 | #[allow(clippy::unnecessary_cast)] 11 | fn check_page(addr: Address, mem: &[u8]) -> bool { 12 | for (i, chunk) in mem.to_vec().chunks_exact(8).enumerate() { 13 | let qword = u64::from_le_bytes(chunk[0..8].try_into().unwrap()); 14 | if (i < 4 && qword != addr.to_umem() as u64 + ((i as u64 * 8) << 9) + 0x1001) 15 | || (i >= 4 && qword != 0) 16 | { 17 | return false; 18 | } 19 | } 20 | true 21 | } 22 | 23 | pub fn find(mem: &[u8]) -> Result { 24 | mem.page_chunks(Address::NULL, x32_pae::ARCH.page_size()) 25 | .find(|(a, c)| check_page(*a, c)) 26 | .map(|(a, _)| StartBlock { 27 | arch: x32_pae::ARCH.ident(), 28 | kernel_hint: Address::NULL, 29 | dtb: a, 30 | }) 31 | .ok_or_else(|| { 32 | Error(ErrorOrigin::OsLayer, ErrorKind::NotFound) 33 | .log_warn("unable to find x86_pae dtb in lowstub < 16M") 34 | }) 35 | } 36 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-win32/memflow-win32/src/kernel/sysproc.rs: -------------------------------------------------------------------------------- 1 | use std::prelude::v1::*; 2 | 3 | use super::ntos::pehelper; 4 | use super::StartBlock; 5 | 6 | use std::convert::TryInto; 7 | 8 | use log::{debug, info, warn}; 9 | 10 | use memflow::architecture::ArchitectureObj; 11 | use memflow::error::{Error, ErrorKind, ErrorOrigin, Result}; 12 | use memflow::mem::MemoryView; 13 | use memflow::types::{size, umem, Address}; 14 | 15 | use pelite::{self, pe64::exports::Export, PeView}; 16 | 17 | pub fn find( 18 | virt_mem: &mut T, 19 | start_block: &StartBlock, 20 | ntos: Address, 21 | ) -> Result
{ 22 | debug!("trying to find system eprocess"); 23 | 24 | match find_exported(virt_mem, start_block, ntos) { 25 | Ok(e) => return Ok(e), 26 | Err(e) => warn!("{}", e), 27 | } 28 | 29 | match find_in_section(virt_mem, start_block, ntos) { 30 | Ok(e) => return Ok(e), 31 | Err(e) => warn!("{}", e), 32 | } 33 | 34 | Err(Error(ErrorOrigin::OsLayer, ErrorKind::NotFound).log_info("unable to find system eprocess")) 35 | } 36 | 37 | // find from exported symbol 38 | pub fn find_exported( 39 | virt_mem: &mut T, 40 | start_block: &StartBlock, 41 | kernel_base: Address, 42 | ) -> Result
{ 43 | // PsInitialSystemProcess -> PsActiveProcessHead 44 | let image = pehelper::try_get_pe_image(virt_mem, kernel_base)?; 45 | let pe = PeView::from_bytes(&image) 46 | .map_err(|err| Error(ErrorOrigin::OsLayer, ErrorKind::InvalidExeFile).log_info(err))?; 47 | 48 | let sys_proc = match pe 49 | .get_export_by_name("PsInitialSystemProcess") 50 | .map_err(|err| Error(ErrorOrigin::OsLayer, ErrorKind::ExportNotFound).log_info(err))? 51 | { 52 | Export::Symbol(s) => kernel_base + *s as umem, 53 | Export::Forward(_) => { 54 | return Err(Error(ErrorOrigin::OsLayer, ErrorKind::ExportNotFound) 55 | .log_info("PsInitialSystemProcess found but it was a forwarded export")) 56 | } 57 | }; 58 | info!("PsInitialSystemProcess found at 0x{:x}", sys_proc); 59 | 60 | let arch_obj: ArchitectureObj = start_block.arch.into(); 61 | 62 | // read containing value 63 | let mut buf = vec![0u8; arch_obj.size_addr()]; 64 | let sys_proc_addr: Address = match arch_obj.bits() { 65 | 64 => { 66 | virt_mem.read_raw_into(sys_proc, &mut buf)?; 67 | u64::from_le_bytes(buf[0..8].try_into().unwrap()).into() 68 | } 69 | 32 => { 70 | virt_mem.read_raw_into(sys_proc, &mut buf)?; 71 | u32::from_le_bytes(buf[0..4].try_into().unwrap()).into() 72 | } 73 | _ => return Err(Error(ErrorOrigin::OsLayer, ErrorKind::InvalidArchitecture)), 74 | }; 75 | Ok(sys_proc_addr) 76 | } 77 | 78 | // TODO: scan in pdb 79 | 80 | // scan in section 81 | pub fn find_in_section( 82 | virt_mem: &mut T, 83 | _start_block: &StartBlock, 84 | ntos: Address, 85 | ) -> Result
{ 86 | // find section ALMOSTRO 87 | // scan for va of system process (dtb.va) 88 | // ... check if its 32 or 64bit 89 | 90 | let mut header_buf = vec![0; size::mb(32)]; 91 | virt_mem.read_raw_into(ntos, &mut header_buf)?; 92 | 93 | /* 94 | let mut pe_opts = ParseOptions::default(); 95 | pe_opts.resolve_rva = false; 96 | 97 | let header = PE::parse_with_opts(&header_buf, &pe_opts).unwrap(); // TODO: error 98 | let _sect = header 99 | .sections 100 | .iter() 101 | .filter(|s| String::from_utf8(s.name.to_vec()).unwrap_or_default() == "ALMOSTRO") 102 | .nth(0) 103 | .ok_or_else(|| Error::new("unable to find section ALMOSTRO"))?; 104 | */ 105 | 106 | Err(Error(ErrorOrigin::OsLayer, ErrorKind::NotImplemented) 107 | .log_info("sysproc::find_in_section(): not implemented yet")) 108 | } 109 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-win32/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 kernel; 10 | 11 | pub mod offsets; 12 | 13 | pub mod win32; 14 | 15 | pub mod prelude { 16 | pub mod v1 { 17 | pub use crate::kernel::*; 18 | pub use crate::offsets::*; 19 | pub use crate::win32::*; 20 | } 21 | pub use v1::*; 22 | } 23 | 24 | #[cfg(feature = "plugins")] 25 | pub mod plugins; 26 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-win32/memflow-win32/src/offsets/mod.rs: -------------------------------------------------------------------------------- 1 | pub use memflow_win32_defs::offsets::*; 2 | 3 | use crate::prelude::v1::*; 4 | 5 | #[repr(align(16))] 6 | struct Align16(pub T); 7 | 8 | #[cfg(feature = "embed_offsets")] 9 | const WIN32_OFFSETS: Align16< 10 | [u8; include_bytes!(concat!(env!("OUT_DIR"), "/win32_offsets.bin")).len()], 11 | > = Align16(*include_bytes!(concat!( 12 | env!("OUT_DIR"), 13 | "/win32_offsets.bin" 14 | ))); 15 | 16 | pub fn offset_builder<'a>() -> Win32OffsetBuilder<'a> { 17 | let builder = Win32Offsets::builder(); 18 | 19 | #[cfg(feature = "embed_offsets")] 20 | { 21 | // # Safety 22 | // Struct padding and alignment is compile-time guaranteed by the struct (see mod offset_table). 23 | let offsets = unsafe { 24 | core::slice::from_raw_parts( 25 | WIN32_OFFSETS.0.as_ptr() as *const Win32OffsetFile, 26 | WIN32_OFFSETS.0.len() / std::mem::size_of::(), 27 | ) 28 | }; 29 | builder.offset_list(offsets) 30 | } 31 | #[cfg(not(feature = "embed_offsets"))] 32 | builder 33 | } 34 | 35 | pub fn offset_builder_with_kernel_info<'a>( 36 | kernel_info: &Win32KernelInfo, 37 | ) -> Win32OffsetBuilder<'a> { 38 | let builder = offset_builder(); 39 | kernel_info.into_offset_builder(builder) 40 | } 41 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-win32/memflow-win32/src/win32.rs: -------------------------------------------------------------------------------- 1 | pub mod kernel; 2 | pub mod kernel_builder; 3 | pub mod kernel_info; 4 | 5 | pub use kernel::Win32Kernel; 6 | pub use kernel_builder::Win32KernelBuilder; 7 | pub use kernel_info::Win32KernelInfo; 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/memflow-win32/src/win32/kernel/mem_map.rs: -------------------------------------------------------------------------------- 1 | use std::prelude::v1::*; 2 | 3 | use log::{info, trace}; 4 | use std::fmt; 5 | 6 | use memflow::mem::{MemoryMap, MemoryView}; 7 | use memflow::types::{mem, umem, Address}; 8 | 9 | use memflow::dataview::Pod; 10 | 11 | #[allow(clippy::unnecessary_cast)] 12 | const SIZE_4KB: u64 = mem::kb(4) as u64; 13 | 14 | /// The number of PhysicalMemoryRuns contained in the Header 15 | pub const PHYSICAL_MEMORY_MAX_RUNS: usize = 32; 16 | 17 | #[repr(C)] 18 | #[derive(Copy, Clone, Debug)] 19 | pub struct PhysicalMemoryRun { 20 | pub base_page: T, 21 | pub page_count: T, 22 | } 23 | unsafe impl Pod for PhysicalMemoryRun {} 24 | 25 | #[repr(C)] 26 | #[derive(Copy, Clone, Debug)] 27 | pub struct PhysicalMemoryDescriptor { 28 | pub number_of_runs: T, 29 | pub number_of_pages: T, 30 | pub runs: [PhysicalMemoryRun; PHYSICAL_MEMORY_MAX_RUNS], 31 | } 32 | unsafe impl Pod for PhysicalMemoryDescriptor {} 33 | const _: [(); std::mem::size_of::>()] = [(); 0x108]; 34 | const _: [(); std::mem::size_of::>()] = [(); 0x210]; 35 | 36 | pub fn parse>( 37 | virt_mem: &mut T, 38 | descriptor_ptr_ptr: Address, 39 | ) -> Option> { 40 | let descriptor_ptr = virt_mem.read_addr64(descriptor_ptr_ptr).ok()?; 41 | 42 | trace!("found phys_mem_block pointer at: {}", descriptor_ptr); 43 | let descriptor: PhysicalMemoryDescriptor = virt_mem.read(descriptor_ptr).ok()?; 44 | 45 | trace!("found phys_mem_block: {:?}", descriptor); 46 | if descriptor.number_of_runs.into() <= PHYSICAL_MEMORY_MAX_RUNS as u64 { 47 | let mut mem_map = MemoryMap::new(); 48 | 49 | for i in 0..descriptor.number_of_runs.into() { 50 | let base = descriptor.runs[i as usize].base_page.into() * SIZE_4KB; 51 | let size = descriptor.runs[i as usize].page_count.into() * SIZE_4KB; 52 | 53 | trace!("adding memory mapping: base={:x} size={:x}", base, size); 54 | mem_map.push_remap(base.into(), size as umem, Address::from(base)); 55 | } 56 | 57 | Some(mem_map) 58 | } else { 59 | info!( 60 | "too many memory segments in phys_mem_block: {} found, {} expected", 61 | descriptor.number_of_runs.into(), 62 | PHYSICAL_MEMORY_MAX_RUNS 63 | ); 64 | None 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-win32/memflow-win32/src/win32/unicode_string.rs: -------------------------------------------------------------------------------- 1 | use std::prelude::v1::*; 2 | 3 | use std::convert::TryInto; 4 | 5 | use memflow::architecture::{ArchitectureObj, Endianess}; 6 | use memflow::error::{Error, ErrorKind, ErrorOrigin, Result}; 7 | use memflow::mem::MemoryView; 8 | use memflow::types::Address; 9 | 10 | use widestring::U16CString; 11 | 12 | pub trait VirtualReadUnicodeString { 13 | fn read_unicode_string(&mut self, proc_arch: ArchitectureObj, addr: Address) -> Result; 14 | } 15 | 16 | // TODO: split up cpu and proc arch in read_helper.rs 17 | impl VirtualReadUnicodeString for T { 18 | fn read_unicode_string(&mut self, proc_arch: ArchitectureObj, addr: Address) -> Result { 19 | /* 20 | typedef struct _windows_unicode_string32 { 21 | uint16_t length; 22 | uint16_t maximum_length; 23 | uint32_t pBuffer; // pointer to string contents 24 | } __attribute__((packed)) win32_unicode_string_t; 25 | 26 | typedef struct _windows_unicode_string64 { 27 | uint16_t length; 28 | uint16_t maximum_length; 29 | uint32_t padding; // align pBuffer 30 | uint64_t pBuffer; // pointer to string contents 31 | } __attribute__((packed)) win64_unicode_string_t; 32 | */ 33 | 34 | // length is always the first entry 35 | let mut length = 0u16; 36 | self.read_into(addr, &mut length)?; 37 | if length == 0 { 38 | return Err(Error(ErrorOrigin::OsLayer, ErrorKind::Encoding) 39 | .log_debug("unable to read unicode string length (length is zero)")); 40 | } 41 | 42 | // TODO: chek if length exceeds limit 43 | // buffer is either aligned at 4 or 8 44 | let buffer = match proc_arch.bits() { 45 | 64 => self.read_addr64(addr + 8)?, 46 | 32 => self.read_addr32(addr + 4)?, 47 | _ => { 48 | return Err(Error(ErrorOrigin::OsLayer, ErrorKind::InvalidArchitecture)); 49 | } 50 | }; 51 | if buffer.is_null() { 52 | return Err(Error(ErrorOrigin::OsLayer, ErrorKind::Encoding) 53 | .log_debug("unable to read unicode string buffer")); 54 | } 55 | 56 | // check if buffer length is mod 2 (utf-16) 57 | if length % 2 != 0 { 58 | return Err(Error(ErrorOrigin::OsLayer, ErrorKind::Encoding) 59 | .log_debug("unicode string length is not a multiple of two")); 60 | } 61 | 62 | // read buffer 63 | let mut content = vec![0; length as usize + 2]; 64 | self.read_raw_into(buffer, &mut content)?; 65 | content[length as usize] = 0; 66 | content[length as usize + 1] = 0; 67 | 68 | let content16 = content 69 | .chunks_exact(2) 70 | .map(|b| { 71 | b[0..2] 72 | .try_into() 73 | .map_err(|_| Error(ErrorOrigin::OsLayer, ErrorKind::Encoding)) 74 | }) 75 | .filter_map(Result::ok) 76 | .map(|b| match proc_arch.endianess() { 77 | Endianess::LittleEndian => u16::from_le_bytes(b), 78 | Endianess::BigEndian => u16::from_be_bytes(b), 79 | }) 80 | .collect::>(); 81 | Ok(U16CString::from_vec_truncate(content16).to_string_lossy()) 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow-win32/memflow-win32/src/win32/vat.rs: -------------------------------------------------------------------------------- 1 | use memflow::{ 2 | architecture::{arm, x86, ArchitectureIdent, ArchitectureObj}, 3 | cglue::tuple::*, 4 | iter::SplitAtIndex, 5 | mem::{ 6 | MemoryView, PhysicalMemory, VirtualDma, VirtualTranslate2, VirtualTranslate3, 7 | VtopFailureCallback, VtopOutputCallback, 8 | }, 9 | types::{umem, Address}, 10 | }; 11 | 12 | #[derive(Debug, Clone, Copy)] 13 | pub struct Win32VirtualTranslate { 14 | pub sys_arch: ArchitectureObj, 15 | pub dtb: Address, 16 | } 17 | 18 | impl Win32VirtualTranslate { 19 | pub fn new(arch: ArchitectureIdent, dtb: Address) -> Self { 20 | Self { 21 | sys_arch: arch.into(), 22 | dtb, 23 | } 24 | } 25 | 26 | pub fn virt_mem( 27 | self, 28 | mem: T, 29 | vat: V, 30 | proc_arch: ArchitectureObj, 31 | ) -> impl MemoryView { 32 | VirtualDma::with_vat(mem, proc_arch, self, vat) 33 | } 34 | } 35 | 36 | impl VirtualTranslate3 for Win32VirtualTranslate { 37 | fn virt_to_phys_iter< 38 | T: PhysicalMemory + ?Sized, 39 | B: SplitAtIndex, 40 | VI: Iterator>, 41 | >( 42 | &self, 43 | mem: &mut T, 44 | addrs: VI, 45 | out: &mut VtopOutputCallback, 46 | out_fail: &mut VtopFailureCallback, 47 | tmp_buf: &mut [std::mem::MaybeUninit], 48 | ) { 49 | if let Ok(translator) = x86::new_translator(self.dtb, self.sys_arch) { 50 | translator.virt_to_phys_iter(mem, addrs, out, out_fail, tmp_buf) 51 | } else if let Ok(translator) = arm::new_translator_nonsplit(self.dtb, self.sys_arch) { 52 | translator.virt_to_phys_iter(mem, addrs, out, out_fail, tmp_buf) 53 | } else { 54 | panic!("Invalid architecture"); 55 | } 56 | } 57 | 58 | fn translation_table_id(&self, _address: Address) -> umem { 59 | self.dtb.to_umem().overflowing_shr(12).0 60 | } 61 | 62 | fn arch(&self) -> ArchitectureObj { 63 | self.sys_arch 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow/examples/kernel_exports.rs: -------------------------------------------------------------------------------- 1 | /// A simple kernel module list example using memflow 2 | use clap::*; 3 | use log::Level; 4 | use memflow::prelude::v1::*; 5 | 6 | fn main() -> Result<()> { 7 | let matches = parse_args(); 8 | let chain = extract_args(&matches)?; 9 | 10 | // create inventory + os 11 | let inventory = Inventory::scan(); 12 | let mut os = inventory.builder().os_chain(chain).build()?; 13 | 14 | let ntoskrnl = os.primary_module()?; 15 | let exports = os.module_export_list(&ntoskrnl)?; 16 | 17 | // Print export list, formatted 18 | println!("{:>8} {:>32}", "OFFS", "NAME"); 19 | 20 | for e in exports { 21 | println!("{:>8x} {:<32}", e.offset, e.name); 22 | } 23 | 24 | Ok(()) 25 | } 26 | 27 | fn parse_args() -> ArgMatches { 28 | Command::new("kernel_exports example") 29 | .version(crate_version!()) 30 | .author(crate_authors!()) 31 | .arg(Arg::new("verbose").short('v').action(ArgAction::Count)) 32 | .arg( 33 | Arg::new("connector") 34 | .long("connector") 35 | .short('c') 36 | .action(ArgAction::Append) 37 | .required(false), 38 | ) 39 | .arg( 40 | Arg::new("os") 41 | .long("os") 42 | .short('o') 43 | .action(ArgAction::Append) 44 | .required(true), 45 | ) 46 | .get_matches() 47 | } 48 | 49 | fn extract_args(matches: &ArgMatches) -> Result> { 50 | let log_level = match matches.get_count("verbose") { 51 | 0 => Level::Error, 52 | 1 => Level::Warn, 53 | 2 => Level::Info, 54 | 3 => Level::Debug, 55 | 4 => Level::Trace, 56 | _ => Level::Trace, 57 | }; 58 | simplelog::TermLogger::init( 59 | log_level.to_level_filter(), 60 | simplelog::Config::default(), 61 | simplelog::TerminalMode::Stdout, 62 | simplelog::ColorChoice::Auto, 63 | ) 64 | .unwrap(); 65 | 66 | let conn_iter = matches 67 | .indices_of("connector") 68 | .zip(matches.get_many::("connector")) 69 | .map(|(a, b)| a.zip(b.map(String::as_str))) 70 | .into_iter() 71 | .flatten(); 72 | 73 | let os_iter = matches 74 | .indices_of("os") 75 | .zip(matches.get_many::("os")) 76 | .map(|(a, b)| a.zip(b.map(String::as_str))) 77 | .into_iter() 78 | .flatten(); 79 | 80 | OsChain::new(conn_iter, os_iter) 81 | } 82 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow/examples/kernel_maps.rs: -------------------------------------------------------------------------------- 1 | /// A simple kernel module list example using memflow 2 | use clap::*; 3 | use log::Level; 4 | 5 | use memflow::prelude::v1::*; 6 | 7 | fn main() -> Result<()> { 8 | let matches = parse_args(); 9 | let chain = extract_args(&matches)?; 10 | 11 | // create inventory + os 12 | let inventory = Inventory::scan(); 13 | let mut os = inventory.builder().os_chain(chain).build()?; 14 | 15 | let vt = os 16 | .as_mut_impl_virtualtranslate() 17 | .expect("VirtualTranslate is not implemented for this OS plugin"); 18 | 19 | // Print map list, formatted 20 | println!("{:>16} {:>12} {:<}", "ADDR", "SIZE", "TYPE"); 21 | 22 | let callback = &mut |CTup3(addr, size, pagety)| { 23 | println!("{addr:>16x} {size:>12x} {pagety: ArgMatches { 32 | Command::new("kernel_maps example") 33 | .version(crate_version!()) 34 | .author(crate_authors!()) 35 | .arg(Arg::new("verbose").short('v').action(ArgAction::Count)) 36 | .arg( 37 | Arg::new("connector") 38 | .long("connector") 39 | .short('c') 40 | .action(ArgAction::Append) 41 | .required(false), 42 | ) 43 | .arg( 44 | Arg::new("os") 45 | .long("os") 46 | .short('o') 47 | .action(ArgAction::Append) 48 | .required(true), 49 | ) 50 | .get_matches() 51 | } 52 | 53 | fn extract_args(matches: &ArgMatches) -> Result> { 54 | let log_level = match matches.get_count("verbose") { 55 | 0 => Level::Error, 56 | 1 => Level::Warn, 57 | 2 => Level::Info, 58 | 3 => Level::Debug, 59 | 4 => Level::Trace, 60 | _ => Level::Trace, 61 | }; 62 | simplelog::TermLogger::init( 63 | log_level.to_level_filter(), 64 | simplelog::Config::default(), 65 | simplelog::TerminalMode::Stdout, 66 | simplelog::ColorChoice::Auto, 67 | ) 68 | .unwrap(); 69 | 70 | let conn_iter = matches 71 | .indices_of("connector") 72 | .zip(matches.get_many::("connector")) 73 | .map(|(a, b)| a.zip(b.map(String::as_str))) 74 | .into_iter() 75 | .flatten(); 76 | 77 | let os_iter = matches 78 | .indices_of("os") 79 | .zip(matches.get_many::("os")) 80 | .map(|(a, b)| a.zip(b.map(String::as_str))) 81 | .into_iter() 82 | .flatten(); 83 | 84 | OsChain::new(conn_iter, os_iter) 85 | } 86 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow/examples/kernel_modules.rs: -------------------------------------------------------------------------------- 1 | /// A simple kernel module list example using memflow 2 | use clap::*; 3 | use log::Level; 4 | 5 | use memflow::prelude::v1::*; 6 | 7 | fn main() -> Result<()> { 8 | let matches = parse_args(); 9 | let chain = extract_args(&matches)?; 10 | 11 | // create inventory + os 12 | let inventory = Inventory::scan(); 13 | let mut os = inventory.builder().os_chain(chain).build()?; 14 | 15 | let module_list = os.module_list()?; 16 | 17 | // Print module list, formatted 18 | println!( 19 | "{:>16} {:>16} {:>8} {:>24} {:<}", 20 | "INTERNAL ADDR", "BASE", "SIZE", "NAME", "PATH" 21 | ); 22 | 23 | for m in module_list { 24 | println!( 25 | "{:>16x} {:>16x} {:>8x} {:>24} {}", 26 | m.address, m.base, m.size, m.name, m.path 27 | ); 28 | } 29 | 30 | Ok(()) 31 | } 32 | 33 | fn parse_args() -> ArgMatches { 34 | Command::new("kernel_modules example") 35 | .version(crate_version!()) 36 | .author(crate_authors!()) 37 | .arg(Arg::new("verbose").short('v').action(ArgAction::Count)) 38 | .arg( 39 | Arg::new("connector") 40 | .long("connector") 41 | .short('c') 42 | .action(ArgAction::Append) 43 | .required(false), 44 | ) 45 | .arg( 46 | Arg::new("os") 47 | .long("os") 48 | .short('o') 49 | .action(ArgAction::Append) 50 | .required(true), 51 | ) 52 | .get_matches() 53 | } 54 | 55 | fn extract_args(matches: &ArgMatches) -> Result> { 56 | let log_level = match matches.get_count("verbose") { 57 | 0 => Level::Error, 58 | 1 => Level::Warn, 59 | 2 => Level::Info, 60 | 3 => Level::Debug, 61 | 4 => Level::Trace, 62 | _ => Level::Trace, 63 | }; 64 | simplelog::TermLogger::init( 65 | log_level.to_level_filter(), 66 | simplelog::Config::default(), 67 | simplelog::TerminalMode::Stdout, 68 | simplelog::ColorChoice::Auto, 69 | ) 70 | .unwrap(); 71 | 72 | let conn_iter = matches 73 | .indices_of("connector") 74 | .zip(matches.get_many::("connector")) 75 | .map(|(a, b)| a.zip(b.map(String::as_str))) 76 | .into_iter() 77 | .flatten(); 78 | 79 | let os_iter = matches 80 | .indices_of("os") 81 | .zip(matches.get_many::("os")) 82 | .map(|(a, b)| a.zip(b.map(String::as_str))) 83 | .into_iter() 84 | .flatten(); 85 | 86 | OsChain::new(conn_iter, os_iter) 87 | } 88 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow/examples/keyboard.rs: -------------------------------------------------------------------------------- 1 | /// A simple keyboard example using memflow 2 | use clap::*; 3 | use log::Level; 4 | 5 | use memflow::prelude::v1::*; 6 | 7 | fn main() -> Result<()> { 8 | let matches = parse_args(); 9 | let chain = extract_args(&matches)?; 10 | 11 | // create inventory + os 12 | let inventory = Inventory::scan(); 13 | let os = inventory.builder().os_chain(chain).build()?; 14 | 15 | if !os.check_impl_oskeyboard() { 16 | return Err( 17 | Error(ErrorOrigin::Other, ErrorKind::UnsupportedOptionalFeature) 18 | .log_error("keyboard feature is not implemented for the given os plugin"), 19 | ); 20 | } 21 | 22 | let mut keyboard = into!(os impl OsKeyboard).unwrap().into_keyboard()?; 23 | 24 | loop { 25 | println!("space down: {:?}", keyboard.is_down(0x20)); // VK_SPACE 26 | std::thread::sleep(std::time::Duration::from_millis(1000)); 27 | } 28 | } 29 | 30 | fn parse_args() -> ArgMatches { 31 | Command::new("keyboard example") 32 | .version(crate_version!()) 33 | .author(crate_authors!()) 34 | .arg(Arg::new("verbose").short('v').action(ArgAction::Count)) 35 | .arg( 36 | Arg::new("connector") 37 | .long("connector") 38 | .short('c') 39 | .action(ArgAction::Append) 40 | .required(false), 41 | ) 42 | .arg( 43 | Arg::new("os") 44 | .long("os") 45 | .short('o') 46 | .action(ArgAction::Append) 47 | .required(true), 48 | ) 49 | .get_matches() 50 | } 51 | 52 | fn extract_args(matches: &ArgMatches) -> Result> { 53 | let log_level = match matches.get_count("verbose") { 54 | 0 => Level::Error, 55 | 1 => Level::Warn, 56 | 2 => Level::Info, 57 | 3 => Level::Debug, 58 | 4 => Level::Trace, 59 | _ => Level::Trace, 60 | }; 61 | simplelog::TermLogger::init( 62 | log_level.to_level_filter(), 63 | simplelog::Config::default(), 64 | simplelog::TerminalMode::Stdout, 65 | simplelog::ColorChoice::Auto, 66 | ) 67 | .unwrap(); 68 | 69 | let conn_iter = matches 70 | .indices_of("connector") 71 | .zip(matches.get_many::("connector")) 72 | .map(|(a, b)| a.zip(b.map(String::as_str))) 73 | .into_iter() 74 | .flatten(); 75 | 76 | let os_iter = matches 77 | .indices_of("os") 78 | .zip(matches.get_many::("os")) 79 | .map(|(a, b)| a.zip(b.map(String::as_str))) 80 | .into_iter() 81 | .flatten(); 82 | 83 | OsChain::new(conn_iter, os_iter) 84 | } 85 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow/examples/mem_maps.rs: -------------------------------------------------------------------------------- 1 | /// A simple process list example using memflow 2 | use clap::*; 3 | use log::Level; 4 | 5 | use memflow::prelude::v1::*; 6 | 7 | fn main() -> Result<()> { 8 | let matches = parse_args(); 9 | let (chain, proc_name, gap_size) = extract_args(&matches)?; 10 | 11 | // create inventory + os 12 | let inventory = Inventory::scan(); 13 | let os = inventory.builder().os_chain(chain).build()?; 14 | 15 | let mut process = os 16 | .into_process_by_name(proc_name) 17 | .expect("unable to find process"); 18 | println!("found process: {:?}", process.info()); 19 | 20 | let maps = process.mapped_mem_vec(gap_size); 21 | 22 | // Print module list, formatted 23 | println!("{:>11} {:>11} {:<}", "BASE", "SIZE", "FLAGS"); 24 | 25 | for CTup3(a, s, p) in maps { 26 | println!("0x{a:0>8x} 0x{s:0>8x} {p:?}",); 27 | } 28 | 29 | Ok(()) 30 | } 31 | 32 | fn parse_args() -> ArgMatches { 33 | Command::new("module_list example") 34 | .version(crate_version!()) 35 | .author(crate_authors!()) 36 | .arg(Arg::new("verbose").short('v').action(ArgAction::Count)) 37 | .arg( 38 | Arg::new("connector") 39 | .long("connector") 40 | .short('c') 41 | .action(ArgAction::Append) 42 | .required(false), 43 | ) 44 | .arg( 45 | Arg::new("os") 46 | .long("os") 47 | .short('o') 48 | .action(ArgAction::Append) 49 | .required(true), 50 | ) 51 | .arg( 52 | Arg::new("process") 53 | .long("process") 54 | .short('p') 55 | .action(ArgAction::Set) 56 | .required(true), 57 | ) 58 | .arg( 59 | Arg::new("gap-size") 60 | .long("gap-size") 61 | .short('g') 62 | .action(ArgAction::Set) 63 | .required(false), 64 | ) 65 | .get_matches() 66 | } 67 | 68 | fn extract_args(matches: &ArgMatches) -> Result<(OsChain<'_>, &str, imem)> { 69 | let log_level = match matches.get_count("verbose") { 70 | 0 => Level::Error, 71 | 1 => Level::Warn, 72 | 2 => Level::Info, 73 | 3 => Level::Debug, 74 | 4 => Level::Trace, 75 | _ => Level::Trace, 76 | }; 77 | simplelog::TermLogger::init( 78 | log_level.to_level_filter(), 79 | simplelog::Config::default(), 80 | simplelog::TerminalMode::Stdout, 81 | simplelog::ColorChoice::Auto, 82 | ) 83 | .unwrap(); 84 | 85 | let conn_iter = matches 86 | .indices_of("connector") 87 | .zip(matches.get_many::("connector")) 88 | .map(|(a, b)| a.zip(b.map(String::as_str))) 89 | .into_iter() 90 | .flatten(); 91 | 92 | let os_iter = matches 93 | .indices_of("os") 94 | .zip(matches.get_many::("os")) 95 | .map(|(a, b)| a.zip(b.map(String::as_str))) 96 | .into_iter() 97 | .flatten(); 98 | 99 | Ok(( 100 | OsChain::new(conn_iter, os_iter)?, 101 | matches.get_one::("process").unwrap(), 102 | matches 103 | .get_one::<&str>("gap-size") 104 | .unwrap_or(&"-1") 105 | .parse() 106 | .unwrap(), 107 | )) 108 | } 109 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow/examples/module_info.rs: -------------------------------------------------------------------------------- 1 | /// A simple process list example using memflow 2 | use clap::*; 3 | use log::Level; 4 | 5 | use memflow::prelude::v1::*; 6 | 7 | fn main() -> Result<()> { 8 | let matches = parse_args(); 9 | let (chain, proc_name, module_name) = extract_args(&matches)?; 10 | 11 | // create inventory + os 12 | let inventory = Inventory::scan(); 13 | let os = inventory.builder().os_chain(chain).build()?; 14 | 15 | let mut process = os 16 | .into_process_by_name(proc_name) 17 | .expect("unable to find process"); 18 | println!("found process: {:?}", process.info()); 19 | 20 | let module = process 21 | .module_by_name(module_name) 22 | .expect("unable to retrieve module"); 23 | 24 | println!( 25 | "{}:\nBase - {:x}\nSize - {:x}\nArch - {:?}\nFilename - {}", 26 | module.name, module.base, module.size, module.arch, module.path 27 | ); 28 | 29 | if let Ok(s) = process 30 | .module_section_list(&module) 31 | .map_err(|e| panic!("{}", e)) 32 | { 33 | println!("Sections:"); 34 | 35 | for s in s { 36 | println!("0x{:0>8x} 0x{:0>8x} {}", s.base, s.size, s.name); 37 | } 38 | } 39 | 40 | Ok(()) 41 | } 42 | 43 | fn parse_args() -> ArgMatches { 44 | Command::new("module_list example") 45 | .version(crate_version!()) 46 | .author(crate_authors!()) 47 | .arg(Arg::new("verbose").short('v').action(ArgAction::Count)) 48 | .arg( 49 | Arg::new("connector") 50 | .long("connector") 51 | .short('c') 52 | .action(ArgAction::Append) 53 | .required(false), 54 | ) 55 | .arg( 56 | Arg::new("os") 57 | .long("os") 58 | .short('o') 59 | .action(ArgAction::Append) 60 | .required(true), 61 | ) 62 | .arg( 63 | Arg::new("process") 64 | .long("process") 65 | .short('p') 66 | .action(ArgAction::Set) 67 | .required(true), 68 | ) 69 | .arg( 70 | Arg::new("module") 71 | .long("module") 72 | .short('m') 73 | .action(ArgAction::Set) 74 | .required(true), 75 | ) 76 | .get_matches() 77 | } 78 | 79 | fn extract_args(matches: &ArgMatches) -> Result<(OsChain<'_>, &str, &str)> { 80 | let log_level = match matches.get_count("verbose") { 81 | 0 => Level::Error, 82 | 1 => Level::Warn, 83 | 2 => Level::Info, 84 | 3 => Level::Debug, 85 | 4 => Level::Trace, 86 | _ => Level::Trace, 87 | }; 88 | simplelog::TermLogger::init( 89 | log_level.to_level_filter(), 90 | simplelog::Config::default(), 91 | simplelog::TerminalMode::Stdout, 92 | simplelog::ColorChoice::Auto, 93 | ) 94 | .unwrap(); 95 | 96 | let conn_iter = matches 97 | .indices_of("connector") 98 | .zip(matches.get_many::("connector")) 99 | .map(|(a, b)| a.zip(b.map(String::as_str))) 100 | .into_iter() 101 | .flatten(); 102 | 103 | let os_iter = matches 104 | .indices_of("os") 105 | .zip(matches.get_many::("os")) 106 | .map(|(a, b)| a.zip(b.map(String::as_str))) 107 | .into_iter() 108 | .flatten(); 109 | 110 | Ok(( 111 | OsChain::new(conn_iter, os_iter)?, 112 | matches.get_one::("process").unwrap(), 113 | matches.get_one::("module").unwrap(), 114 | )) 115 | } 116 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow/examples/module_list.rs: -------------------------------------------------------------------------------- 1 | /*! 2 | A simple process list example using memflow 3 | 4 | # Usage: 5 | ```bash 6 | cargo run --release --example module_list -- -vvv -c kvm --os win32 --process explorer.exe 7 | ``` 8 | */ 9 | use clap::*; 10 | use log::Level; 11 | 12 | use memflow::prelude::v1::*; 13 | 14 | fn main() -> Result<()> { 15 | let matches = parse_args(); 16 | let (chain, proc_name) = extract_args(&matches)?; 17 | 18 | // create inventory + os 19 | let inventory = Inventory::scan(); 20 | let os = inventory.builder().os_chain(chain).build()?; 21 | 22 | let mut process = os 23 | .into_process_by_name(proc_name) 24 | .expect("unable to find process"); 25 | println!("found process: {:?}", process.info()); 26 | 27 | let module_list = process 28 | .module_list() 29 | .expect("unable to retrieve module list"); 30 | 31 | // Print module list, formatted 32 | println!( 33 | "{:>11} {:>11} {:>11} {:>11} {:<}", 34 | "BASE", "SIZE", "MOD ARCH", "NAME", "PATH" 35 | ); 36 | 37 | for m in module_list { 38 | println!( 39 | "0x{:0>8x} 0x{:0>8x} {:^10} {} ({})", 40 | m.base, m.size, m.arch, m.name, m.path 41 | ); 42 | } 43 | 44 | Ok(()) 45 | } 46 | 47 | fn parse_args() -> ArgMatches { 48 | Command::new("module_list example") 49 | .version(crate_version!()) 50 | .author(crate_authors!()) 51 | .arg(Arg::new("verbose").short('v').action(ArgAction::Count)) 52 | .arg( 53 | Arg::new("connector") 54 | .long("connector") 55 | .short('c') 56 | .action(ArgAction::Append) 57 | .required(false), 58 | ) 59 | .arg( 60 | Arg::new("os") 61 | .long("os") 62 | .short('o') 63 | .action(ArgAction::Append) 64 | .required(true), 65 | ) 66 | .arg( 67 | Arg::new("process") 68 | .long("process") 69 | .short('p') 70 | .action(ArgAction::Set) 71 | .required(true), 72 | ) 73 | .get_matches() 74 | } 75 | 76 | fn extract_args(matches: &ArgMatches) -> Result<(OsChain<'_>, &str)> { 77 | let log_level = match matches.get_count("verbose") { 78 | 0 => Level::Error, 79 | 1 => Level::Warn, 80 | 2 => Level::Info, 81 | 3 => Level::Debug, 82 | 4 => Level::Trace, 83 | _ => Level::Trace, 84 | }; 85 | simplelog::TermLogger::init( 86 | log_level.to_level_filter(), 87 | simplelog::Config::default(), 88 | simplelog::TerminalMode::Stdout, 89 | simplelog::ColorChoice::Auto, 90 | ) 91 | .unwrap(); 92 | 93 | let conn_iter = matches 94 | .indices_of("connector") 95 | .zip(matches.get_many::("connector")) 96 | .map(|(a, b)| a.zip(b.map(String::as_str))) 97 | .into_iter() 98 | .flatten(); 99 | 100 | let os_iter = matches 101 | .indices_of("os") 102 | .zip(matches.get_many::("os")) 103 | .map(|(a, b)| a.zip(b.map(String::as_str))) 104 | .into_iter() 105 | .flatten(); 106 | 107 | Ok(( 108 | OsChain::new(conn_iter, os_iter)?, 109 | matches.get_one::("process").unwrap(), 110 | )) 111 | } 112 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow/examples/process_list.rs: -------------------------------------------------------------------------------- 1 | /// A simple process list example using memflow 2 | use clap::*; 3 | use log::Level; 4 | 5 | use memflow::prelude::v1::*; 6 | 7 | fn main() -> Result<()> { 8 | let matches = parse_args(); 9 | let chain = extract_args(&matches)?; 10 | 11 | // create inventory + os 12 | let inventory = Inventory::scan(); 13 | let mut os = inventory.builder().os_chain(chain).build()?; 14 | 15 | let process_list = os.process_info_list()?; 16 | 17 | // Print process list, formatted 18 | println!( 19 | "{:>5} {:>10} {:>10} {:<}", 20 | "PID", "SYS ARCH", "PROC ARCH", "NAME" 21 | ); 22 | 23 | for p in process_list { 24 | println!( 25 | "{:>5} {:^10} {:^10} {} ({}) ({:?})", 26 | p.pid, p.sys_arch, p.proc_arch, p.name, p.command_line, p.state 27 | ); 28 | } 29 | 30 | Ok(()) 31 | } 32 | 33 | fn parse_args() -> ArgMatches { 34 | Command::new("mfps example") 35 | .version(crate_version!()) 36 | .author(crate_authors!()) 37 | .arg(Arg::new("verbose").short('v').action(ArgAction::Count)) 38 | .arg( 39 | Arg::new("connector") 40 | .long("connector") 41 | .short('c') 42 | .action(ArgAction::Append) 43 | .required(false), 44 | ) 45 | .arg( 46 | Arg::new("os") 47 | .long("os") 48 | .short('o') 49 | .action(ArgAction::Append) 50 | .required(true), 51 | ) 52 | .get_matches() 53 | } 54 | 55 | fn extract_args(matches: &ArgMatches) -> Result> { 56 | let log_level = match matches.get_count("verbose") { 57 | 0 => Level::Error, 58 | 1 => Level::Warn, 59 | 2 => Level::Info, 60 | 3 => Level::Debug, 61 | 4 => Level::Trace, 62 | _ => Level::Trace, 63 | }; 64 | simplelog::TermLogger::init( 65 | log_level.to_level_filter(), 66 | simplelog::Config::default(), 67 | simplelog::TerminalMode::Stdout, 68 | simplelog::ColorChoice::Auto, 69 | ) 70 | .unwrap(); 71 | 72 | let conn_iter = matches 73 | .indices_of("connector") 74 | .zip(matches.get_many::("connector")) 75 | .map(|(a, b)| a.zip(b.map(String::as_str))) 76 | .into_iter() 77 | .flatten(); 78 | 79 | let os_iter = matches 80 | .indices_of("os") 81 | .zip(matches.get_many::("os")) 82 | .map(|(a, b)| a.zip(b.map(String::as_str))) 83 | .into_iter() 84 | .flatten(); 85 | 86 | OsChain::new(conn_iter, os_iter) 87 | } 88 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow/examples/target_list.rs: -------------------------------------------------------------------------------- 1 | use memflow::plugins::*; 2 | 3 | use clap::*; 4 | use log::Level; 5 | 6 | fn main() { 7 | let connector = parse_args(); 8 | 9 | // create inventory 10 | let inventory = Inventory::scan(); 11 | 12 | // try to get help text 13 | println!( 14 | "Connector help:\n{}", 15 | inventory.connector_help(&connector).unwrap_or_default() 16 | ); 17 | 18 | // try to get target list 19 | let targets = inventory 20 | .connector_target_list(&connector) 21 | .expect("unable to get target list"); 22 | 23 | println!("Targets for connector `{}`:", &connector); 24 | targets.iter().for_each(|t| println!("- {}", t.name)); 25 | } 26 | 27 | fn parse_args() -> String { 28 | let matches = Command::new("multithreading example") 29 | .version(crate_version!()) 30 | .author(crate_authors!()) 31 | .arg(Arg::new("verbose").short('v').action(ArgAction::Count)) 32 | .arg( 33 | Arg::new("connector") 34 | .long("connector") 35 | .short('c') 36 | .action(ArgAction::Set) 37 | .required(true), 38 | ) 39 | .get_matches(); 40 | 41 | // set log level 42 | let log_level = match matches.get_count("verbose") { 43 | 0 => Level::Error, 44 | 1 => Level::Warn, 45 | 2 => Level::Info, 46 | 3 => Level::Debug, 47 | 4 => Level::Trace, 48 | _ => Level::Trace, 49 | }; 50 | simplelog::TermLogger::init( 51 | log_level.to_level_filter(), 52 | simplelog::Config::default(), 53 | simplelog::TerminalMode::Stdout, 54 | simplelog::ColorChoice::Auto, 55 | ) 56 | .unwrap(); 57 | 58 | matches.get_one::("connector").unwrap().into() 59 | } 60 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow/src/architecture/arm/aarch64.rs: -------------------------------------------------------------------------------- 1 | use super::{ 2 | super::{ArchitectureObj, Endianess}, 3 | ArmArchitecture, ArmVirtualTranslate, 4 | }; 5 | 6 | use crate::mem::virt_translate::mmu::ArchMmuDef; 7 | 8 | use crate::types::Address; 9 | 10 | const ARCH_4K_MMU_DEF: ArchMmuDef = ArchMmuDef { 11 | virtual_address_splits: &[9, 9, 9, 9, 12], 12 | valid_final_page_steps: &[2, 3, 4], 13 | address_space_bits: 48, 14 | endianess: Endianess::LittleEndian, 15 | addr_size: 8, 16 | pte_size: 8, 17 | present_bit: |a| a.bit_at(0), 18 | writeable_bit: |a, _| a.bit_at(10), 19 | nx_bit: |a, _| a.bit_at(54), 20 | large_page_bit: |a| !a.bit_at(1), 21 | }; 22 | 23 | pub(super) static ARCH_SPEC: ArmArchitecture = ArmArchitecture { 24 | bits: 64, 25 | mmu: ARCH_4K_MMU_DEF.into_spec(), 26 | }; 27 | 28 | pub static ARCH: ArchitectureObj = &ARCH_SPEC; 29 | 30 | pub fn new_translator(dtb1: Address, dtb2: Address) -> ArmVirtualTranslate { 31 | ArmVirtualTranslate::new(&ARCH_SPEC, dtb1, dtb2) 32 | } 33 | 34 | pub(super) static ARCH_SPEC_16K: ArmArchitecture = ArmArchitecture { 35 | bits: 64, 36 | mmu: ArchMmuDef { 37 | virtual_address_splits: &[1, 11, 11, 11, 14], 38 | valid_final_page_steps: &[3, 4], 39 | ..ARCH_4K_MMU_DEF 40 | } 41 | .into_spec(), 42 | }; 43 | 44 | pub static ARCH_16K: ArchitectureObj = &ARCH_SPEC_16K; 45 | 46 | pub fn new_translator_16k(dtb1: Address, dtb2: Address) -> ArmVirtualTranslate { 47 | ArmVirtualTranslate::new(&ARCH_SPEC_16K, dtb1, dtb2) 48 | } 49 | -------------------------------------------------------------------------------- /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::{Architecture, ArchitectureIdent, ArchitectureObj, Endianess}; 6 | 7 | use crate::mem::virt_translate::{ 8 | mmu::ArchMmuSpec, VirtualTranslate3, VtopFailureCallback, VtopOutputCallback, 9 | }; 10 | 11 | use crate::error::{Error, ErrorKind, ErrorOrigin, Result}; 12 | use crate::iter::SplitAtIndex; 13 | use crate::mem::PhysicalMemory; 14 | use crate::types::{umem, Address}; 15 | use cglue::tuple::*; 16 | 17 | use std::ptr; 18 | 19 | pub struct X86Architecture { 20 | /// Defines how many bits does the native word size have 21 | bits: u8, 22 | /// Defines the underlying MMU used for address translation 23 | mmu: ArchMmuSpec, 24 | } 25 | 26 | impl Architecture for X86Architecture { 27 | fn bits(&self) -> u8 { 28 | self.bits 29 | } 30 | 31 | fn endianess(&self) -> Endianess { 32 | self.mmu.def.endianess 33 | } 34 | 35 | fn page_size(&self) -> usize { 36 | self.mmu.page_size_level(1) as usize 37 | } 38 | 39 | fn size_addr(&self) -> usize { 40 | self.mmu.def.addr_size.into() 41 | } 42 | 43 | fn address_space_bits(&self) -> u8 { 44 | self.mmu.def.address_space_bits 45 | } 46 | 47 | fn ident(&self) -> ArchitectureIdent { 48 | ArchitectureIdent::X86( 49 | self.bits, 50 | ptr::eq(self as *const _, &x32_pae::ARCH_SPEC as *const _), 51 | ) 52 | } 53 | } 54 | 55 | #[derive(Clone, Copy)] 56 | pub struct X86VirtualTranslate { 57 | arch: &'static X86Architecture, 58 | dtb: Address, 59 | } 60 | 61 | impl X86VirtualTranslate { 62 | pub fn new(arch: &'static X86Architecture, dtb: Address) -> Self { 63 | Self { arch, dtb } 64 | } 65 | } 66 | 67 | impl VirtualTranslate3 for X86VirtualTranslate { 68 | fn virt_to_phys_iter< 69 | T: PhysicalMemory + ?Sized, 70 | B: SplitAtIndex, 71 | VI: Iterator>, 72 | >( 73 | &self, 74 | mem: &mut T, 75 | addrs: VI, 76 | out: &mut VtopOutputCallback, 77 | out_fail: &mut VtopFailureCallback, 78 | tmp_buf: &mut [std::mem::MaybeUninit], 79 | ) { 80 | self.arch 81 | .mmu 82 | .virt_to_phys_iter(mem, self.dtb, addrs, out, out_fail, tmp_buf) 83 | } 84 | 85 | fn translation_table_id(&self, _address: Address) -> umem { 86 | self.dtb.to_umem().overflowing_shr(12).0 87 | } 88 | 89 | fn arch(&self) -> ArchitectureObj { 90 | self.arch 91 | } 92 | } 93 | 94 | // This lint doesn't make any sense in our usecase, since we nevel leak ARCH_SPECs, and ARCH is 95 | // a static trait object with a consistent address. 96 | fn underlying_arch(arch: ArchitectureObj) -> Option<&'static X86Architecture> { 97 | if arch == x64::ARCH { 98 | Some(&x64::ARCH_SPEC) 99 | } else if arch == x32::ARCH { 100 | Some(&x32::ARCH_SPEC) 101 | } else if arch == x32_pae::ARCH { 102 | Some(&x32_pae::ARCH_SPEC) 103 | } else { 104 | None 105 | } 106 | } 107 | 108 | pub fn new_translator(dtb: Address, arch: ArchitectureObj) -> Result { 109 | let arch = 110 | underlying_arch(arch).ok_or(Error(ErrorOrigin::Mmu, ErrorKind::InvalidArchitecture))?; 111 | Ok(X86VirtualTranslate::new(arch, dtb)) 112 | } 113 | 114 | pub fn is_x86_arch(arch: ArchitectureObj) -> bool { 115 | underlying_arch(arch).is_some() 116 | } 117 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow/src/architecture/x86/x32.rs: -------------------------------------------------------------------------------- 1 | use super::{ 2 | super::{ArchitectureObj, Endianess}, 3 | X86Architecture, X86VirtualTranslate, 4 | }; 5 | 6 | use crate::mem::virt_translate::mmu::ArchMmuDef; 7 | 8 | use crate::types::Address; 9 | 10 | pub(super) static ARCH_SPEC: X86Architecture = X86Architecture { 11 | bits: 32, 12 | mmu: ArchMmuDef { 13 | virtual_address_splits: &[10, 10, 12], 14 | valid_final_page_steps: &[1, 2], 15 | address_space_bits: 32, 16 | endianess: Endianess::LittleEndian, 17 | addr_size: 4, 18 | pte_size: 4, 19 | present_bit: |a| a.bit_at(0), 20 | writeable_bit: |a, pb| pb || a.bit_at(1), 21 | nx_bit: |_, _| false, 22 | large_page_bit: |a| a.bit_at(7), 23 | } 24 | .into_spec(), 25 | }; 26 | 27 | pub static ARCH: ArchitectureObj = &ARCH_SPEC; 28 | 29 | pub fn new_translator(dtb: Address) -> X86VirtualTranslate { 30 | X86VirtualTranslate::new(&ARCH_SPEC, dtb) 31 | } 32 | 33 | //x64 tests MMU rigorously, here we will only test a few special cases 34 | #[cfg(test)] 35 | mod tests { 36 | use crate::mem::virt_translate::mmu::ArchMmuSpec; 37 | use crate::types::{mem, size, Address}; 38 | 39 | fn get_mmu_spec() -> &'static ArchMmuSpec { 40 | &super::ARCH_SPEC.mmu 41 | } 42 | 43 | #[test] 44 | fn x86_pte_bitmasks() { 45 | let mmu = get_mmu_spec(); 46 | let mask_addr = Address::invalid(); 47 | assert_eq!( 48 | mmu.pte_addr_mask(mask_addr, 0), 49 | Address::bit_mask(12..=31).to_umem() 50 | ); 51 | assert_eq!( 52 | mmu.pte_addr_mask(mask_addr, 1), 53 | Address::bit_mask(12..=31).to_umem() 54 | ); 55 | assert_eq!( 56 | mmu.pte_addr_mask(mask_addr, 2), 57 | Address::bit_mask(12..=31).to_umem() 58 | ); 59 | } 60 | 61 | #[test] 62 | fn x86_pte_leaf_size() { 63 | let mmu = get_mmu_spec(); 64 | assert_eq!(mmu.pt_leaf_size(0), size::kb(4)); 65 | assert_eq!(mmu.pt_leaf_size(1), size::kb(4)); 66 | } 67 | 68 | #[test] 69 | fn x86_page_size_level() { 70 | let mmu = get_mmu_spec(); 71 | assert_eq!(mmu.page_size_level(1), mem::kb(4)); 72 | assert_eq!(mmu.page_size_level(2), mem::mb(4)); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow/src/architecture/x86/x32_pae.rs: -------------------------------------------------------------------------------- 1 | use super::{ 2 | super::{ArchitectureObj, Endianess}, 3 | X86Architecture, X86VirtualTranslate, 4 | }; 5 | 6 | use crate::mem::virt_translate::mmu::ArchMmuDef; 7 | 8 | use crate::types::Address; 9 | 10 | pub(super) static ARCH_SPEC: X86Architecture = X86Architecture { 11 | bits: 32, 12 | mmu: ArchMmuDef { 13 | virtual_address_splits: &[2, 9, 9, 12], 14 | valid_final_page_steps: &[2, 3], 15 | address_space_bits: 36, 16 | endianess: Endianess::LittleEndian, 17 | addr_size: 4, 18 | pte_size: 8, 19 | present_bit: |a| a.bit_at(0), 20 | writeable_bit: |a, pb| pb || a.bit_at(1), 21 | nx_bit: |a, pb| pb || a.bit_at(63), 22 | large_page_bit: |a| a.bit_at(7), 23 | } 24 | .into_spec(), 25 | }; 26 | 27 | pub static ARCH: ArchitectureObj = &ARCH_SPEC; 28 | 29 | pub fn new_translator(dtb: Address) -> X86VirtualTranslate { 30 | X86VirtualTranslate::new(&ARCH_SPEC, dtb) 31 | } 32 | 33 | //x64 tests MMU rigorously, here we will only test a few special cases 34 | #[cfg(test)] 35 | mod tests { 36 | use crate::mem::virt_translate::mmu::ArchMmuSpec; 37 | use crate::types::{mem, size, Address}; 38 | 39 | fn get_mmu_spec() -> &'static ArchMmuSpec { 40 | &super::ARCH_SPEC.mmu 41 | } 42 | 43 | #[test] 44 | fn x86_pae_pte_bitmasks() { 45 | let mmu = get_mmu_spec(); 46 | let mask_addr = Address::invalid(); 47 | assert_eq!( 48 | mmu.pte_addr_mask(mask_addr, 0), 49 | Address::bit_mask(5..=35).to_umem() 50 | ); 51 | assert_eq!( 52 | mmu.pte_addr_mask(mask_addr, 1), 53 | Address::bit_mask(12..=35).to_umem() 54 | ); 55 | assert_eq!( 56 | mmu.pte_addr_mask(mask_addr, 2), 57 | Address::bit_mask(12..=35).to_umem() 58 | ); 59 | } 60 | 61 | #[test] 62 | fn x86_pae_pte_leaf_size() { 63 | let mmu = get_mmu_spec(); 64 | assert_eq!(mmu.pt_leaf_size(0), 32); 65 | assert_eq!(mmu.pt_leaf_size(1), size::kb(4)); 66 | } 67 | 68 | #[test] 69 | fn x86_pae_page_size_level() { 70 | let mmu = get_mmu_spec(); 71 | assert_eq!(mmu.page_size_level(1), mem::kb(4)); 72 | assert_eq!(mmu.page_size_level(2), mem::mb(2)); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow/src/connector/cpu_state.rs: -------------------------------------------------------------------------------- 1 | //! Describes optional cpu state for a connector 2 | 3 | use crate::cglue::*; 4 | use crate::prelude::v1::Result; 5 | 6 | #[cfg_attr(feature = "plugins", cglue_trait)] 7 | #[int_result] 8 | pub trait ConnectorCpuState: Send { 9 | #[wrap_with_obj(crate::connector::cpu_state::CpuState)] 10 | type CpuStateType<'a>: crate::connector::cpu_state::CpuState + 'a 11 | where 12 | Self: 'a; 13 | #[wrap_with_group(crate::connector::cpu_state::IntoCpuState)] 14 | type IntoCpuStateType: crate::connector::cpu_state::CpuState + 'static; 15 | 16 | fn cpu_state(&mut self) -> Result>; 17 | fn into_cpu_state(self) -> Result; 18 | } 19 | 20 | #[cfg(feature = "plugins")] 21 | cglue_trait_group!(IntoCpuState, { CpuState, Clone }, {}); 22 | 23 | #[cfg_attr(feature = "plugins", cglue_trait)] 24 | #[int_result] 25 | #[cglue_forward] 26 | pub trait CpuState { 27 | // TODO: 28 | // max cpu index 29 | // read_register(s) 30 | // write_register(s) 31 | // pause 32 | // resume 33 | // single-step 34 | // breakpoints 35 | 36 | fn pause(&mut self); 37 | fn resume(&mut self); 38 | } 39 | -------------------------------------------------------------------------------- /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 | // TODO: move all of this in a helper module and only keep the connector plugin stuff 13 | #[cfg(feature = "std")] 14 | pub mod fileio; 15 | #[doc(hidden)] 16 | #[cfg(feature = "std")] 17 | pub use fileio::{CloneFile, FileIoMemory}; 18 | 19 | #[cfg(feature = "filemap")] 20 | pub mod filemap; 21 | #[cfg(feature = "filemap")] 22 | pub use filemap::{ 23 | MmapInfo, MmapInfoMut, ReadMappedFilePhysicalMemory, WriteMappedFilePhysicalMemory, 24 | }; 25 | 26 | pub mod mmap; 27 | #[doc(hidden)] 28 | pub use mmap::MappedPhysicalMemory; 29 | 30 | pub mod cpu_state; 31 | #[doc(hidden)] 32 | pub use cpu_state::{ConnectorCpuState, CpuState}; 33 | #[doc(hidden)] 34 | #[cfg(feature = "plugins")] 35 | pub use cpu_state::{CpuStateArcBox, IntoCpuStateArcBox}; 36 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow/src/dummy/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod mem; 2 | pub mod os; 3 | pub mod process; 4 | 5 | pub(crate) mod offset_pt; 6 | pub(crate) use offset_pt::OffsetPageTable; 7 | 8 | pub use mem::DummyMemory; 9 | pub use os::DummyOs; 10 | pub use process::DummyProcessInfo; 11 | -------------------------------------------------------------------------------- /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 | for elem in self.iter.by_ref() { 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/mem/memory_view/arch_overlay.rs: -------------------------------------------------------------------------------- 1 | //! Overlays a custom architecture on the memory view 2 | 3 | use super::*; 4 | use crate::architecture::{ArchitectureObj, Endianess}; 5 | use crate::error::*; 6 | 7 | /// Allows to overwrite the architecture of the memory view. 8 | /// 9 | /// Is useful when a 32 bit process runs in a 64 bit architecture, and a 64-bit Pointer is wanted 10 | /// to be read with `read_ptr`. 11 | #[repr(C)] 12 | #[derive(Clone, Copy, Debug)] 13 | pub struct ArchOverlayView { 14 | mem: T, 15 | arch_bits: u8, 16 | little_endian: bool, 17 | } 18 | 19 | impl ArchOverlayView { 20 | pub fn new_parts(mem: T, arch_bits: u8, little_endian: bool) -> Self { 21 | Self { 22 | mem, 23 | arch_bits, 24 | little_endian, 25 | } 26 | } 27 | 28 | pub fn new(mem: T, arch: ArchitectureObj) -> Self { 29 | Self::new_parts( 30 | mem, 31 | arch.bits(), 32 | arch.endianess() == Endianess::LittleEndian, 33 | ) 34 | } 35 | } 36 | 37 | impl MemoryView for ArchOverlayView { 38 | fn read_raw_iter(&mut self, data: ReadRawMemOps) -> Result<()> { 39 | self.mem.read_raw_iter(data) 40 | } 41 | 42 | fn write_raw_iter(&mut self, data: WriteRawMemOps) -> Result<()> { 43 | self.mem.write_raw_iter(data) 44 | } 45 | 46 | fn metadata(&self) -> MemoryViewMetadata { 47 | MemoryViewMetadata { 48 | little_endian: self.little_endian, 49 | arch_bits: self.arch_bits, 50 | ..self.mem.metadata() 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow/src/mem/memory_view/remap_view.rs: -------------------------------------------------------------------------------- 1 | //! Remapping layer for a memory view. 2 | use super::*; 3 | 4 | /// Remapped memory view. 5 | /// 6 | /// This structure allows to build a new memory view as a subset of an existing view. 7 | /// 8 | /// This is useful for nested VM introspection, or analyzing emulators and custom memory 9 | /// structures. 10 | #[derive(Clone)] 11 | pub struct RemapView { 12 | mem: T, 13 | mem_map: MemoryMap<(Address, umem)>, 14 | } 15 | 16 | impl RemapView { 17 | pub fn new(mem: T, mem_map: MemoryMap<(Address, umem)>) -> Self { 18 | Self { mem, mem_map } 19 | } 20 | } 21 | 22 | impl MemoryView for RemapView { 23 | fn read_raw_iter(&mut self, MemOps { inp, out_fail, out }: ReadRawMemOps) -> Result<()> { 24 | let out_fail = out_fail.map(std::cell::RefCell::new); 25 | 26 | let mut out_fail1 = out_fail 27 | .as_ref() 28 | .map(|of| move |data| of.borrow_mut().call(data)); 29 | let mut out_fail2 = out_fail 30 | .as_ref() 31 | .map(|of| move |data| of.borrow_mut().call(data)); 32 | let mut out_fail2 = out_fail2.as_mut().map(<_>::into); 33 | let out_fail2 = out_fail2.as_mut(); 34 | 35 | let mut out = out.map(|o| move |data| o.call(data)); 36 | let mut out = out.as_mut().map(<_>::into); 37 | let out = out.as_mut(); 38 | 39 | let mem_map = &mut self.mem_map; 40 | let mem = &mut self.mem; 41 | 42 | let iter = mem_map 43 | .map_base_iter(inp, out_fail1.as_mut()) 44 | .map(|CTup3((a, _), m, b)| CTup3(a, m, b)); 45 | 46 | MemOps::with_raw(iter, out, out_fail2, |data| mem.read_raw_iter(data)) 47 | } 48 | 49 | fn write_raw_iter(&mut self, MemOps { inp, out_fail, out }: WriteRawMemOps) -> Result<()> { 50 | let out_fail = out_fail.map(std::cell::RefCell::new); 51 | 52 | let mut out_fail1 = out_fail 53 | .as_ref() 54 | .map(|of| move |data| of.borrow_mut().call(data)); 55 | let mut out_fail2 = out_fail 56 | .as_ref() 57 | .map(|of| move |data| of.borrow_mut().call(data)); 58 | let mut out_fail2 = out_fail2.as_mut().map(<_>::into); 59 | let out_fail2 = out_fail2.as_mut(); 60 | 61 | let mut out = out.map(|o| move |data| o.call(data)); 62 | let mut out = out.as_mut().map(<_>::into); 63 | let out = out.as_mut(); 64 | 65 | let mem_map = &mut self.mem_map; 66 | let mem = &mut self.mem; 67 | 68 | let iter = mem_map 69 | .map_base_iter(inp, out_fail1.as_mut()) 70 | .map(|CTup3((a, _), m, b)| CTup3(a, m, b)); 71 | 72 | MemOps::with_raw(iter, out, out_fail2, |data| mem.write_raw_iter(data)) 73 | } 74 | 75 | fn metadata(&self) -> MemoryViewMetadata { 76 | MemoryViewMetadata { 77 | max_address: self.mem_map.max_address(), 78 | real_size: self.mem_map.real_size(), 79 | ..self.mem.metadata() 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow/src/mem/mod.rs: -------------------------------------------------------------------------------- 1 | //! This module covers all implementations and traits related to 2 | //! reading/writing [physical](phys_mem/index.html) and [virtual](virt_mem/index.html) memory. 3 | //! 4 | //! The [cache](cache/index.html) module contains all caching related 5 | //! implementations. The caches just wrap the physical and virtual accessors 6 | //! and are themselves a memory backend. 7 | //! 8 | //! TODO: more documentation 9 | 10 | pub mod mem_data; 11 | pub mod mem_map; 12 | pub mod memory_view; 13 | pub mod phys_mem; 14 | pub mod virt_mem; 15 | pub mod virt_translate; 16 | 17 | pub use mem_map::{MemoryMap, PhysicalMemoryMapping}; 18 | pub use phys_mem::{CachedPhysicalMemory, PhysicalMemory, PhysicalMemoryMetadata}; 19 | #[cfg(feature = "std")] 20 | pub use phys_mem::{DelayedPhysicalMemory, PhysicalMemoryMetrics}; 21 | pub use virt_mem::VirtualDma; 22 | pub use virt_translate::{ 23 | CachedVirtualTranslate, DirectTranslate, VirtualTranslate, VirtualTranslate2, 24 | VirtualTranslate3, VtopFailureCallback, VtopOutputCallback, 25 | }; 26 | 27 | pub use memory_view::{CachedView, MemoryView, MemoryViewBatcher, MemoryViewMetadata}; 28 | 29 | #[cfg(feature = "std")] 30 | pub use memory_view::MemoryCursor; 31 | 32 | pub use mem_data::*; 33 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow/src/mem/phys_mem/middleware/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod cache; 2 | 3 | #[cfg(feature = "std")] 4 | pub mod delay; 5 | #[cfg(feature = "std")] 6 | pub mod metrics; 7 | 8 | #[doc(hidden)] 9 | pub use cache::*; 10 | 11 | #[cfg(feature = "std")] 12 | #[doc(hidden)] 13 | pub use delay::*; 14 | 15 | #[cfg(feature = "std")] 16 | #[doc(hidden)] 17 | pub use metrics::*; 18 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow/src/mem/virt_mem/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod virtual_dma; 2 | 3 | #[doc(hidden)] 4 | pub use virtual_dma::VirtualDma; 5 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow/src/mem/virt_translate/direct_translate.rs: -------------------------------------------------------------------------------- 1 | use super::{VirtualTranslate2, VirtualTranslate3, VtopFailureCallback, VtopOutputCallback}; 2 | use crate::iter::SplitAtIndex; 3 | use crate::mem::PhysicalMemory; 4 | use crate::types::{size, Address}; 5 | use cglue::tuple::*; 6 | use std::prelude::v1::*; 7 | 8 | /* 9 | The `DirectTranslate` struct provides a default implementation for `VirtualTranslate2` for physical memory. 10 | */ 11 | #[derive(Debug, Default)] 12 | pub struct DirectTranslate { 13 | tmp_buf: Box<[std::mem::MaybeUninit]>, 14 | } 15 | 16 | impl DirectTranslate { 17 | pub fn new() -> Self { 18 | Self::with_capacity(size::mb(64)) 19 | } 20 | 21 | pub fn with_capacity(size: usize) -> Self { 22 | Self { 23 | tmp_buf: vec![std::mem::MaybeUninit::new(0); size].into_boxed_slice(), 24 | } 25 | } 26 | } 27 | 28 | impl Clone for DirectTranslate { 29 | fn clone(&self) -> Self { 30 | Self::with_capacity(self.tmp_buf.len()) 31 | } 32 | } 33 | 34 | impl VirtualTranslate2 for DirectTranslate { 35 | fn virt_to_phys_iter( 36 | &mut self, 37 | phys_mem: &mut T, 38 | translator: &D, 39 | addrs: VI, 40 | out: &mut VtopOutputCallback, 41 | out_fail: &mut VtopFailureCallback, 42 | ) where 43 | T: PhysicalMemory + ?Sized, 44 | B: SplitAtIndex, 45 | D: VirtualTranslate3, 46 | VI: Iterator>, 47 | { 48 | translator.virt_to_phys_iter(phys_mem, addrs, out, out_fail, &mut self.tmp_buf) 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow/src/mem/virt_translate/mmu/mod.rs: -------------------------------------------------------------------------------- 1 | pub(crate) mod def; 2 | pub(crate) mod spec; 3 | pub(crate) mod translate_data; 4 | 5 | use super::VtopFailureCallback; 6 | use crate::iter::SplitAtIndex; 7 | use crate::types::{umem, Address}; 8 | use cglue::tuple::*; 9 | pub(crate) use def::ArchMmuDef; 10 | pub(crate) use fixed_slice_vec::FixedSliceVec as MVec; 11 | pub(crate) use spec::ArchMmuSpec; 12 | pub(crate) use translate_data::FlagsType; 13 | use translate_data::{TranslateDataVec, TranslateVec, TranslationChunk}; 14 | 15 | pub trait MmuTranslationBase: Clone + Copy + core::fmt::Debug { 16 | /// Retrieves page table address by virtual address 17 | fn get_pt_by_virt_addr(&self, address: Address) -> Address; 18 | 19 | /// Retrieves page table address, and its index by index within 20 | /// For instance, on Arm index 257 would return kernel page table 21 | /// address, and index 1. On X86, however, this is a no-op that returns 22 | /// underlying page table Address and `idx`. 23 | fn get_pt_by_index(&self, idx: usize) -> (Address, usize); 24 | 25 | /// Retrieves number of page tables used by translation base. 1 on X86, 26 | /// 1-2 on Arm (Win32 Arm merges both page tables) 27 | fn pt_count(&self) -> usize; 28 | 29 | fn virt_addr_filter( 30 | &self, 31 | spec: &ArchMmuSpec, 32 | addr: CTup3, 33 | work_group: (&mut TranslationChunk, &mut TranslateDataVec), 34 | out_fail: &mut VtopFailureCallback, 35 | ); 36 | 37 | fn fill_init_chunk( 38 | &self, 39 | spec: &ArchMmuSpec, 40 | out_fail: &mut VtopFailureCallback, 41 | addrs: &mut VI, 42 | (next_work_addrs, tmp_addrs): (&mut TranslateDataVec, &mut TranslateDataVec), 43 | work_vecs: &mut (TranslateVec, TranslateDataVec), 44 | wait_vecs: &mut (TranslateVec, TranslateDataVec), 45 | ) where 46 | VI: Iterator>, 47 | B: SplitAtIndex, 48 | { 49 | let mut init_chunk = TranslationChunk::new(*self, FlagsType::NONE); 50 | 51 | let working_addr_count = work_vecs.1.capacity(); 52 | 53 | for (_, data) in (0..working_addr_count).zip(addrs) { 54 | self.virt_addr_filter(spec, data, (&mut init_chunk, next_work_addrs), out_fail); 55 | if init_chunk.next_max_addr_count(spec) >= working_addr_count as umem { 56 | break; 57 | } 58 | } 59 | 60 | if init_chunk.addr_count > 0 { 61 | init_chunk.split_chunk(spec, (next_work_addrs, tmp_addrs), work_vecs, wait_vecs); 62 | } 63 | } 64 | } 65 | 66 | impl MmuTranslationBase for Address { 67 | fn get_pt_by_virt_addr(&self, _: Address) -> Address { 68 | *self 69 | } 70 | 71 | fn get_pt_by_index(&self, idx: usize) -> (Address, usize) { 72 | (*self, idx) 73 | } 74 | 75 | fn pt_count(&self) -> usize { 76 | 1 77 | } 78 | 79 | fn virt_addr_filter( 80 | &self, 81 | spec: &ArchMmuSpec, 82 | addr: CTup3, 83 | work_group: (&mut TranslationChunk, &mut TranslateDataVec), 84 | out_fail: &mut VtopFailureCallback, 85 | ) where 86 | B: SplitAtIndex, 87 | { 88 | spec.virt_addr_filter(addr, work_group, out_fail); 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow/src/os/keyboard.rs: -------------------------------------------------------------------------------- 1 | //! Describes optional keyboard input for a Operating System 2 | 3 | use crate::cglue::*; 4 | use crate::prelude::v1::Result; 5 | 6 | #[cfg_attr(feature = "plugins", cglue_trait)] 7 | #[int_result] 8 | pub trait OsKeyboard: Send { 9 | #[wrap_with_obj(crate::os::keyboard::Keyboard)] 10 | type KeyboardType<'a>: crate::os::keyboard::Keyboard + 'a 11 | where 12 | Self: 'a; 13 | #[wrap_with_group(crate::os::keyboard::IntoKeyboard)] 14 | type IntoKeyboardType: crate::os::keyboard::Keyboard + Clone + 'static; 15 | 16 | fn keyboard(&mut self) -> Result>; 17 | fn into_keyboard(self) -> Result; 18 | } 19 | 20 | #[cfg(feature = "plugins")] 21 | cglue_trait_group!(IntoKeyboard, { Keyboard, Clone }, {}); 22 | 23 | #[cfg_attr(feature = "plugins", cglue_trait)] 24 | #[int_result] 25 | #[cglue_forward] 26 | pub trait Keyboard { 27 | #[wrap_with_obj(crate::os::keyboard::KeyboardState)] 28 | type KeyboardStateType: crate::os::keyboard::KeyboardState; 29 | 30 | fn is_down(&mut self, vk: i32) -> bool; 31 | fn set_down(&mut self, vk: i32, down: bool); 32 | 33 | fn state(&mut self) -> Result; 34 | } 35 | 36 | #[cfg_attr(feature = "plugins", cglue_trait)] 37 | #[int_result] 38 | #[cglue_forward] 39 | pub trait KeyboardState { 40 | fn is_down(&self, vk: i32) -> bool; 41 | } 42 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow/src/os/mod.rs: -------------------------------------------------------------------------------- 1 | //! Describes an operating system in high level. 2 | //! 3 | //! Currently there are 3 key parts describing an OS, each subsetting the previous level: 4 | //! * `OS` 5 | //! * `Process` 6 | //! * `ModuleInfo` 7 | //! 8 | //! `OS` abstracts away the very root of the system. Often times, the underlying object is a OS 9 | //! kernel, but it should not be a concern, because it is designed to also work with various non-OS 10 | //! systems like UEFI firmware, as well as pseudo implementations that use native system calls. 11 | //! 12 | //! `Process` abstracts away a single process. It provides memory access, module lists, and more. 13 | //! 14 | //! `ModuleInfo` currently is just an information block, without any memory access, or special 15 | //! functions. It might be wise to implement helpers for exported functions, memory protection 16 | //! flags, and other things concerned with individual modules. 17 | 18 | pub mod keyboard; 19 | pub mod module; 20 | pub mod process; 21 | pub mod root; 22 | pub mod util; 23 | 24 | pub use keyboard::{Keyboard, KeyboardState, OsKeyboard}; 25 | 26 | pub use module::{ 27 | ExportCallback, ExportInfo, ImportCallback, ImportInfo, ModuleAddressCallback, 28 | ModuleAddressInfo, ModuleInfo, ModuleInfoCallback, SectionCallback, SectionInfo, 29 | }; 30 | 31 | pub use process::{Pid, Process, ProcessInfo, ProcessInfoCallback, ProcessState}; 32 | 33 | pub use root::{Os, OsInfo}; 34 | 35 | use crate::types::Address; 36 | 37 | use crate::cglue::*; 38 | 39 | pub type AddressCallback<'a> = OpaqueCallback<'a, Address>; 40 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow/src/types/cache/count_validator.rs: -------------------------------------------------------------------------------- 1 | //! Validators are used when working with caches and determine for how long 2 | //! a specific cache entry stays valid. 3 | //! 4 | //! This validator limits the cache time based on an actual time instant. 5 | //! Internally it uses the [coarsetime](https://docs.rs/coarsetime/0.1.14/coarsetime/) crate as a less 6 | //! computation intensive alternative for [std::time](https://doc.rust-lang.org/std/time/index.html). 7 | //! Therefor the Duration has to be converted (e.g. via the .into() trait) when constructing this validator. 8 | //! 9 | //! The default implementation will set the cache time to 1 second. 10 | 11 | use std::prelude::v1::*; 12 | 13 | use super::CacheValidator; 14 | 15 | /// Validator for limiting the cache time based on a time `Instant` 16 | /// 17 | /// # Remarks 18 | /// 19 | /// This validator is only available when being compiled with `std`. 20 | /// When using `no_std` you might want to use another validator. 21 | /// TODO: add other validators here 22 | #[derive(Clone)] 23 | pub struct CountCacheValidator { 24 | count: Vec, 25 | valid_count: usize, 26 | last_count: usize, 27 | } 28 | 29 | /// Creates a validator with a cache timeout of 1 second. 30 | impl Default for CountCacheValidator { 31 | fn default() -> Self { 32 | Self::new(10) 33 | } 34 | } 35 | 36 | impl CountCacheValidator { 37 | /// Creates a new CountCacheValidator with a customizable valid count. 38 | /// 39 | /// Valid count is increased on every memory operation by the validator users. 40 | /// 41 | /// # Examples: 42 | /// ``` 43 | /// use memflow::types::cache::{CacheValidator, CountCacheValidator}; 44 | /// 45 | /// let mut validator = CountCacheValidator::new(100); 46 | /// 47 | /// validator.allocate_slots(1); 48 | /// 49 | /// assert!(!validator.is_slot_valid(0)); 50 | /// validator.validate_slot(0); 51 | /// 52 | /// // For a hundred times the slot should stay valid 53 | /// for _ in 0..100 { 54 | /// assert!(validator.is_slot_valid(0)); 55 | /// validator.update_validity(); 56 | /// } 57 | /// 58 | /// // At this point it should become invalid 59 | /// assert!(!validator.is_slot_valid(0)); 60 | /// ``` 61 | pub fn new(valid_count: usize) -> Self { 62 | Self { 63 | count: vec![], 64 | valid_count, 65 | last_count: 0, 66 | } 67 | } 68 | } 69 | 70 | impl CacheValidator for CountCacheValidator { 71 | #[inline] 72 | fn allocate_slots(&mut self, slot_count: usize) { 73 | self.count 74 | .resize(slot_count, self.last_count.wrapping_sub(self.valid_count)); 75 | } 76 | 77 | #[inline] 78 | fn update_validity(&mut self) { 79 | self.last_count = self.last_count.wrapping_add(1); 80 | } 81 | 82 | #[inline] 83 | fn is_slot_valid(&self, slot_id: usize) -> bool { 84 | self.last_count.wrapping_sub(self.count[slot_id]) < self.valid_count 85 | } 86 | 87 | #[inline] 88 | fn validate_slot(&mut self, slot_id: usize) { 89 | self.count[slot_id] = self.last_count; 90 | } 91 | 92 | #[inline] 93 | fn invalidate_slot(&mut self, slot_id: usize) { 94 | self.count[slot_id] = self.last_count - self.valid_count 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow/src/types/cache/mod.rs: -------------------------------------------------------------------------------- 1 | #[cfg(feature = "std")] 2 | pub mod timed_validator; 3 | 4 | pub mod count_validator; 5 | 6 | #[cfg(feature = "std")] 7 | #[doc(hidden)] 8 | pub use timed_validator::*; 9 | 10 | #[doc(hidden)] 11 | pub use count_validator::*; 12 | 13 | #[cfg(feature = "std")] 14 | pub type DefaultCacheValidator = TimedCacheValidator; 15 | #[cfg(not(feature = "std"))] 16 | pub type DefaultCacheValidator = CountCacheValidator; 17 | 18 | /// Validators are used when working with caches and determine for how long 19 | /// a specific cache entry stays valid. 20 | pub trait CacheValidator 21 | where 22 | Self: Send, 23 | { 24 | // TODO: better docs 25 | 26 | /// Allocate the required amount of slots used for validation 27 | fn allocate_slots(&mut self, slot_count: usize); 28 | 29 | /// Invoked once per Read/Write so internal state can be updated if necessary. 30 | /// 31 | /// This is an optimization so things like `std::time::Instant` only need to be computed once. 32 | fn update_validity(&mut self) { 33 | // no-op 34 | } 35 | 36 | /// Checks wether or not the given slot is valid. 37 | fn is_slot_valid(&self, slot_id: usize) -> bool; 38 | 39 | /// Callback from the cache implementation when a page is cached 40 | /// and the slot should become valid. 41 | fn validate_slot(&mut self, slot_id: usize); 42 | 43 | /// Callback from the caching implementation to mark a slot as invalid. 44 | /// 45 | /// This can happen if two different cache entries fall into the same slot id. 46 | fn invalidate_slot(&mut self, slot_id: usize); 47 | } 48 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow/src/types/cache/timed_validator.rs: -------------------------------------------------------------------------------- 1 | //! Validators are used when working with caches and determine for how long 2 | //! a specific cache entry stays valid. 3 | //! 4 | //! This validator limits the cache time based on an actual time instant. 5 | //! Internally it uses the [coarsetime](https://docs.rs/coarsetime/0.1.14/coarsetime/) crate as a less 6 | //! computation intensive alternative for [std::time](https://doc.rust-lang.org/std/time/index.html). 7 | //! Therefor the Duration has to be converted (e.g. via the .into() trait) when constructing this validator. 8 | //! 9 | //! The default implementation will set the cache time to 1 second. 10 | 11 | use std::prelude::v1::*; 12 | 13 | use super::CacheValidator; 14 | use coarsetime::{Duration, Instant}; 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 TimedCacheValidator { 25 | time: Vec, 26 | valid_time: Duration, 27 | last_time: Instant, 28 | } 29 | 30 | /// Creates a validator with a cache timeout of 1 second. 31 | impl Default for TimedCacheValidator { 32 | fn default() -> Self { 33 | Self::new(Duration::from_millis(1000)) 34 | } 35 | } 36 | 37 | impl TimedCacheValidator { 38 | /// Creates a new TimedCacheValidator with a customizable Duration. 39 | /// 40 | /// # Examples: 41 | /// ``` 42 | /// use std::time::Duration; 43 | /// use memflow::types::cache::TimedCacheValidator; 44 | /// 45 | /// let _ = TimedCacheValidator::new(Duration::from_millis(5000).into()); 46 | /// ``` 47 | pub fn new(valid_time: Duration) -> Self { 48 | Self { 49 | time: vec![], 50 | valid_time, 51 | last_time: Instant::now(), 52 | } 53 | } 54 | } 55 | 56 | impl CacheValidator for TimedCacheValidator { 57 | #[inline] 58 | fn allocate_slots(&mut self, slot_count: usize) { 59 | // allocate all slots in an invalid state 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 | // set this slot to invalid 82 | self.time[slot_id] = self.last_time - self.valid_time 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow/src/types/gap_remover.rs: -------------------------------------------------------------------------------- 1 | use crate::mem::mem_data::{MemoryRange, MemoryRangeCallback}; 2 | use crate::types::{imem, umem, Address, PageType}; 3 | use cglue::prelude::v1::*; 4 | use std::prelude::v1::*; 5 | 6 | pub struct GapRemover<'a> { 7 | map: rangemap::RangeMap, 8 | out: Option>, 9 | gap_size: imem, 10 | start: Address, 11 | end: Address, 12 | } 13 | 14 | impl<'a> GapRemover<'a> { 15 | pub fn new(out: MemoryRangeCallback<'a>, gap_size: imem, start: Address, end: Address) -> Self { 16 | Self { 17 | map: Default::default(), 18 | out: Some(out), 19 | gap_size, 20 | start, 21 | end, 22 | } 23 | } 24 | 25 | pub fn push_range(&mut self, CTup3(in_virtual, size, page_type): MemoryRange) { 26 | self.map.insert(in_virtual..(in_virtual + size), page_type); 27 | } 28 | } 29 | 30 | impl<'a> Drop for GapRemover<'a> { 31 | fn drop(&mut self) { 32 | self.map 33 | .gaps(&(self.start..self.end)) 34 | .filter_map(|r| { 35 | assert!(r.end >= r.start); 36 | if self.gap_size >= 0 && (r.end - r.start) as umem <= self.gap_size as umem { 37 | if r.start.to_umem() > 0 { 38 | let next = r.end; 39 | let prev = r.start - 1 as umem; 40 | match (self.map.get(&prev), self.map.get(&next)) { 41 | (Some(p1), Some(p2)) if p1 == p2 => Some((r, *p2)), 42 | _ => None, 43 | } 44 | } else { 45 | None 46 | } 47 | } else { 48 | None 49 | } 50 | }) 51 | .collect::>() 52 | .into_iter() 53 | .for_each(|(r, p)| self.map.insert(r, p)); 54 | 55 | self.map 56 | .iter() 57 | .map(|(r, p)| { 58 | let address = r.start; 59 | assert!(r.end >= address); 60 | let size = r.end - address; 61 | CTup3(address, size as umem, *p) 62 | }) 63 | .feed_into(self.out.take().unwrap()); 64 | } 65 | } 66 | 67 | impl<'a> Extend for GapRemover<'a> { 68 | fn extend(&mut self, iter: T) 69 | where 70 | T: IntoIterator, 71 | { 72 | iter.into_iter().for_each(|r| self.push_range(r)); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow/src/types/mem.rs: -------------------------------------------------------------------------------- 1 | //! Common type aliases for cross-platform introspection 2 | 3 | /// Unsigned memory type. This type is guaranteed to hold a whole address of introspection target. 4 | pub type umem = u64; 5 | 6 | /// Signed memory type. This type is useful for address differences. 7 | pub type imem = i64; 8 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow/src/types/mem_units.rs: -------------------------------------------------------------------------------- 1 | //! This module contains helper functions for creating various byte sizes. 2 | //! All function are const and will be [optimized](https://rust.godbolt.org/z/T6LiwJ) by rustc. 3 | use super::{imem, umem}; 4 | 5 | #[macro_export] 6 | macro_rules! impl_unit_helper { 7 | ($mod_name:ident, $type_name:ident) => { 8 | pub mod $mod_name { 9 | 10 | pub use super::*; 11 | 12 | /// Returns a umem representing the length in bytes from the given number of kilobytes. 13 | pub const fn kb(kb: $type_name) -> $type_name { 14 | kb * 1024 15 | } 16 | 17 | /// Returns a $type_name representing the length in bytes from the given number of kilobits. 18 | pub const fn kib(kib: $type_name) -> $type_name { 19 | kb(kib) / 8 20 | } 21 | 22 | /// Returns a $type_name representing the length in bytes from the given number of megabytes. 23 | pub const fn mb(mb: $type_name) -> $type_name { 24 | kb(mb) * 1024 25 | } 26 | 27 | /// Returns a $type_name representing the length in bytes from the given number of megabits. 28 | pub const fn mib(mib: $type_name) -> $type_name { 29 | mb(mib) / 8 30 | } 31 | 32 | /// Returns a $type_name representing the length in bytes from the given number of gigabytes. 33 | pub const fn gb(gb: $type_name) -> $type_name { 34 | mb(gb) * 1024 35 | } 36 | 37 | /// Returns a $type_name representing the length in bytes from the given number of gigabits. 38 | pub const fn gib(gib: $type_name) -> $type_name { 39 | gb(gib) / 8 40 | } 41 | } 42 | }; 43 | } 44 | 45 | impl_unit_helper!(size, usize); 46 | impl_unit_helper!(mem, umem); 47 | impl_unit_helper!(ssize, isize); 48 | impl_unit_helper!(smem, imem); 49 | 50 | #[cfg(test)] 51 | mod tests { 52 | use super::*; 53 | 54 | #[test] 55 | fn test_from() { 56 | assert_eq!(size::kb(20), 20480); 57 | assert_eq!(size::kib(123), 15744); 58 | assert_eq!(size::mb(20), 20_971_520); 59 | assert_eq!(size::mib(52), 6_815_744); 60 | assert_eq!(size::gb(2), 2_147_483_648); 61 | #[cfg(pointer_width = "64")] 62 | { 63 | assert_eq!(size::gb(20), 21_474_836_480); 64 | assert_eq!(size::gib(52), 6_979_321_856); 65 | } 66 | #[cfg(feature = "64_bit_mem")] 67 | { 68 | assert_eq!(mem::gb(20), 21_474_836_480); 69 | assert_eq!(mem::gib(52), 6_979_321_856); 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /apex_dma/memflow_lib/memflow/src/types/mod.rs: -------------------------------------------------------------------------------- 1 | //! Module with basic types used in memflow. 2 | //! 3 | //! This module contains types for handling virtual and physical addresses. 4 | //! It also contains types for handling pointers, pages and 5 | //! it exposes different size helpers. 6 | 7 | pub mod address; 8 | pub use address::{ 9 | clamp_to_isize, clamp_to_usize, imem, umem, Address, PrimitiveAddress, UMEM_BITS, 10 | }; 11 | 12 | mod mem_units; 13 | pub use mem_units::*; 14 | 15 | pub mod page; 16 | pub use page::{Page, PageType}; 17 | 18 | pub mod physical_address; 19 | pub use physical_address::PhysicalAddress; 20 | 21 | pub mod pointer; 22 | pub use pointer::{Pointer, Pointer32, Pointer64}; 23 | 24 | pub mod byte_swap; 25 | pub use byte_swap::ByteSwap; 26 | 27 | pub mod cache; 28 | pub use cache::{CacheValidator, DefaultCacheValidator}; 29 | 30 | pub mod gap_remover; 31 | -------------------------------------------------------------------------------- /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::{umem, Address}; 6 | 7 | bitflags! { 8 | /// Describes the type of a page using a bitflag. 9 | #[repr(transparent)] 10 | #[cfg_attr(feature = "serde", derive(::serde::Serialize, ::serde::Deserialize))] 11 | #[cfg_attr(feature = "abi_stable", derive(::abi_stable::StableAbi))] 12 | pub struct PageType: u8 { 13 | /// The page explicitly has no flags. 14 | const NONE = 0b0000_0000; 15 | /// The page type is not known. 16 | const UNKNOWN = 0b0000_0001; 17 | /// The page contains page table entries. 18 | const PAGE_TABLE = 0b0000_0010; 19 | /// The page is a writeable page. 20 | const WRITEABLE = 0b0000_0100; 21 | /// The page is read only. 22 | const READ_ONLY = 0b0000_1000; 23 | /// The page is not executable. 24 | const NOEXEC = 0b0001_0000; 25 | } 26 | } 27 | 28 | impl PageType { 29 | pub fn write(mut self, flag: bool) -> Self { 30 | self &= !(PageType::WRITEABLE | PageType::READ_ONLY | PageType::UNKNOWN); 31 | if flag { 32 | self | PageType::WRITEABLE 33 | } else { 34 | self | PageType::READ_ONLY 35 | } 36 | } 37 | 38 | pub fn noexec(mut self, flag: bool) -> Self { 39 | self &= !(PageType::NOEXEC); 40 | if flag { 41 | self | PageType::NOEXEC 42 | } else { 43 | self 44 | } 45 | } 46 | 47 | pub fn page_table(mut self, flag: bool) -> Self { 48 | self &= !(PageType::PAGE_TABLE | PageType::UNKNOWN); 49 | if flag { 50 | self | PageType::PAGE_TABLE 51 | } else { 52 | self 53 | } 54 | } 55 | } 56 | 57 | impl Default for PageType { 58 | fn default() -> Self { 59 | PageType::UNKNOWN 60 | } 61 | } 62 | 63 | /// A `Page` holds information about a memory page. 64 | /// 65 | /// More information about paging can be found [here](https://en.wikipedia.org/wiki/Paging). 66 | #[repr(C)] 67 | #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug)] 68 | #[cfg_attr(feature = "serde", derive(::serde::Serialize, ::serde::Deserialize))] 69 | #[cfg_attr(feature = "abi_stable", derive(::abi_stable::StableAbi))] 70 | pub struct Page { 71 | /// Contains the page type (see above). 72 | pub page_type: PageType, 73 | /// Contains the base address of this page. 74 | pub page_base: Address, 75 | /// Contains the size of this page. 76 | pub page_size: umem, 77 | } 78 | 79 | impl Page { 80 | /// A page object that is invalid. 81 | pub const INVALID: Page = Page { 82 | page_type: PageType::UNKNOWN, 83 | page_base: Address::INVALID, 84 | page_size: 0, 85 | }; 86 | 87 | /// Returns a page that is invalid. 88 | pub const fn invalid() -> Self { 89 | Self::INVALID 90 | } 91 | 92 | /// Checks wether the page is valid or not. 93 | pub fn is_valid(&self) -> bool { 94 | self.page_base.is_valid() && self.page_size != 0 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /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.2.0" 4 | authors = ["Aurimas Blažulionis <0x60@pm.me>", "ko1N "] 5 | edition = "2018" 6 | homepage = "https://memflow.github.io" 7 | repository = "https://github.com/memflow/memflow" 8 | license = "MIT" 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.26.0" 20 | uefi-services = "0.23.0" 21 | log = "^0.4.14" 22 | memflow = { version = "0.2", path = "../memflow", default-features = false } 23 | -------------------------------------------------------------------------------- /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 | #[allow(unused)] 8 | #[macro_use] 9 | extern crate alloc; 10 | 11 | extern crate rlibc; 12 | 13 | use log::*; 14 | 15 | use uefi::{Handle, Status}; 16 | 17 | #[entry] 18 | fn efi_main(_handle: Handle, mut st: SystemTable) -> Status { 19 | uefi_services::init(&mut st).expect_err("Failed to initialize utilities"); 20 | 21 | info!("memflow EFI test"); 22 | 23 | let _bt = st.boot_services(); 24 | 25 | Status::SUCCESS 26 | } 27 | -------------------------------------------------------------------------------- /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.h: -------------------------------------------------------------------------------- 1 | #include "memflow.hpp" 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #define INRANGE(x, a, b) (x >= a && x <= b) 8 | #define getBits(x) (INRANGE(x, '0', '9') ? (x - '0') : ((x & (~0x20)) - 'A' + 0xa)) 9 | #define getByte(x) (getBits(x[0]) << 4 | getBits(x[1])) 10 | 11 | typedef uint8_t *PBYTE; 12 | typedef uint8_t BYTE; 13 | typedef unsigned long DWORD; 14 | typedef unsigned short WORD; 15 | typedef WORD *PWORD; 16 | 17 | static std::unique_ptr> conn = nullptr; 18 | static std::unique_ptr> kernel = nullptr; 19 | 20 | // set MAX_PHYADDR to a reasonable value, larger values will take more time to traverse. 21 | constexpr uint64_t MAX_PHYADDR = 0xFFFFFFFFF; 22 | 23 | inline uint64_t GetFurtherDistance(uint64_t A, uint64_t Min, uint64_t Max) 24 | { 25 | uint64_t distanceToMin = (A > Min) ? (A - Min) : (Min - A); 26 | uint64_t distanceToMax = (A > Max) ? (A - Max) : (Max - A); 27 | 28 | return (distanceToMin > distanceToMax) ? distanceToMin : distanceToMax; 29 | } 30 | 31 | inline bool isMatch(const PBYTE addr, const PBYTE pat, const PBYTE msk) 32 | { 33 | size_t n = 0; 34 | while (addr[n] == pat[n] || msk[n] == (BYTE)'?') 35 | { 36 | if (!msk[++n]) 37 | { 38 | return true; 39 | } 40 | } 41 | return false; 42 | } 43 | 44 | size_t findPattern(const PBYTE rangeStart, size_t len, const char *pattern); 45 | 46 | typedef struct Process 47 | { 48 | IntoProcessInstance<> hProcess; 49 | uint64_t baseaddr = 0; 50 | } Process; 51 | 52 | enum class process_status : BYTE 53 | { 54 | NOT_FOUND, 55 | FOUND_NO_ACCESS, 56 | FOUND_READY 57 | }; 58 | 59 | class Memory 60 | { 61 | private: 62 | Process proc; 63 | process_status status = process_status::NOT_FOUND; 64 | std::mutex m; 65 | uint64_t lastCorrectDtbPhysicalAddress = 0x0; 66 | 67 | public: 68 | ~Memory() = default; 69 | 70 | uint64_t get_proc_baseaddr(); 71 | 72 | process_status get_proc_status(); 73 | 74 | void check_proc(); 75 | 76 | void open_proc(const char *name); 77 | 78 | void close_proc(); 79 | 80 | template 81 | bool Read(uint64_t address, T &out); 82 | 83 | template 84 | bool ReadArray(uint64_t address, T out[], size_t len); 85 | 86 | template 87 | bool Write(uint64_t address, const T &value); 88 | 89 | template 90 | bool WriteArray(uint64_t address, const T value[], size_t len); 91 | 92 | uint64_t ScanPointer(uint64_t ptr_address, const uint32_t offsets[], int level); 93 | 94 | bool bruteforceDtb(uint64_t dtbStartPhysicalAddr, const uint64_t stepPage); 95 | 96 | bool testDtbValue(const uint64_t &dtb_val); 97 | }; 98 | 99 | template 100 | inline bool Memory::Read(uint64_t address, T &out) 101 | { 102 | std::lock_guard l(m); 103 | return proc.baseaddr && proc.hProcess.read_raw_into(address, CSliceMut((char *)&out, sizeof(T))) == 0; 104 | } 105 | 106 | template 107 | inline bool Memory::ReadArray(uint64_t address, T out[], size_t len) 108 | { 109 | std::lock_guard l(m); 110 | return proc.baseaddr && proc.hProcess.read_raw_into(address, CSliceMut((char *)out, sizeof(T) * len)) == 0; 111 | } 112 | 113 | template 114 | inline bool Memory::Write(uint64_t address, const T &value) 115 | { 116 | std::lock_guard l(m); 117 | return proc.baseaddr && proc.hProcess.write_raw(address, CSliceRef((char *)&value, sizeof(T))) == 0; 118 | } 119 | 120 | template 121 | inline bool Memory::WriteArray(uint64_t address, const T value[], size_t len) 122 | { 123 | std::lock_guard l(m); 124 | return proc.baseaddr && proc.hProcess.write_raw(address, CSliceRef((char *)value, sizeof(T) * len)) == 0; 125 | } -------------------------------------------------------------------------------- /apex_dma/offsets.h: -------------------------------------------------------------------------------- 1 | //v3.0.3.26 2 | 3 | #define OFFSET_ENTITYLIST 0x2022bf8 4 | #define OFFSET_LOCAL_ENT 0x24F6288 5 | #define OFFSET_NAME_LIST 0xd506390 6 | #define OFFSET_THIRDPERSON 0x01e3b190 + 0x6c // thirdperson_override + 0x6c 7 | #define OFFSET_TIMESCALE 0x01841ee0 // host_timescale 8 | 9 | #define OFFSET_TEAM 0x0338 // m_iTeamNum 10 | #define OFFSET_HEALTH 0x0328 // m_iHealth 11 | #define OFFSET_SHIELD 0x01a0 // m_shieldHealth 12 | #define OFFSET_NAME 0x0481 // m_iName 13 | #define OFFSET_SIGN_NAME 0x0478 // m_iSignifierName 14 | #define OFFSET_ABS_VELOCITY 0x0170 // m_vecAbsVelocity 15 | #define OFFSET_VISIBLE_TIME 0x1990 // CPlayer!lastVisibleTime 16 | #define OFFSET_ZOOMING 0x1be1 // m_bZooming 17 | #define OFFSET_THIRDPERSON_SV 0x36c8 // m_thirdPersonShoulderView 18 | #define OFFSET_YAW 0x223c - 0x8 // m_currentFramePlayer.m_ammoPoolCount - 0x8 19 | 20 | #define OFFSET_LIFE_STATE 0x0690 // m_lifeState, >0 = dead 21 | #define OFFSET_BLEED_OUT_STATE 0x2760 // m_bleedoutState, >0 = knocked 22 | 23 | #define OFFSET_ORIGIN 0x017c // m_vecAbsOrigin 24 | #define OFFSET_BONES 0x0da8 + 0x48 // m_nForceBone + 0x48 25 | #define OFFSET_STUDIOHDR 0xff0 // CBaseAnimating!m_pStudioHdr 26 | #define OFFSET_AIMPUNCH 0x2438 // m_currentFrameLocalPlayer.m_vecPunchWeapon_Angle 27 | #define OFFSET_CAMERAPOS 0x1ee0 // CPlayer!camera_origin 28 | #define OFFSET_VIEWANGLES 0x2534 - 0x14 // m_ammoPoolCapacity - 0x14 29 | #define OFFSET_BREATH_ANGLES OFFSET_VIEWANGLES - 0x10 30 | #define OFFSET_OBSERVER_MODE 0x34a4 // m_iObserverMode 31 | #define OFFSET_OBSERVING_TARGET 0x34b0 // m_hObserverTarget 32 | #define OFFSET_OBSERVER_LIST 0x02022b50 + 0x20C8 33 | 34 | #define OFFSET_MATRIX 0x11A350 35 | #define OFFSET_RENDER 0x77BD448 36 | 37 | #define OFFSET_WEAPON 0x1934 // m_latestPrimaryWeapons 38 | #define OFFSET_BULLET_SPEED 0x19d8 + 0x04ec // CWeaponX!m_flProjectileSpeed 39 | #define OFFSET_BULLET_SCALE 0x19d8 + 0x04f4 // CWeaponX!m_flProjectileScale 40 | #define OFFSET_ZOOM_FOV 0x15e0 + 0x00b8 // m_playerData + m_curZoomFOV 41 | #define OFFSET_AMMO 0x1590 // m_ammoInClip 42 | 43 | #define OFFSET_ITEM_GLOW 0x02f0 // m_highlightFunctionBits 44 | 45 | #define OFFSET_GLOW_T1 0x292 // 16256 = enabled, 0 = disabled 46 | #define OFFSET_GLOW_T2 0x30c // 1193322764 = enabled, 0 = disabled 47 | #define OFFSET_GLOW_ENABLE 0x28C // 7 = enabled, 2 = disabled 48 | #define OFFSET_GLOW_THROUGH_WALLS 0x26c // 2 = enabled, 5 = disabled 49 | -------------------------------------------------------------------------------- /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/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\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/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/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 | 81 | 82 | 83 | -------------------------------------------------------------------------------- /apex_guest/Client/Client/Client.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /apex_guest/Client/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/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/Client/main.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "math.h" 10 | #include "overlay.h" -------------------------------------------------------------------------------- /apex_guest/Client/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 | #pragma comment(lib, "d3d11.lib") 19 | 20 | #define GREEN ImColor(0, 255, 0) 21 | #define RED ImColor(255, 0, 0) 22 | #define BLUE ImColor(0, 0, 255) 23 | #define ORANGE ImColor(255, 165, 0) 24 | #define WHITE ImColor(255, 255, 255) 25 | 26 | typedef struct visuals 27 | { 28 | bool box = true; 29 | bool line = true; 30 | bool distance = true; 31 | bool healthbar = true; 32 | bool shieldbar = true; 33 | bool name = true; 34 | }visuals; 35 | 36 | class Overlay 37 | { 38 | public: 39 | void Start(); 40 | DWORD CreateOverlay(); 41 | void Clear(); 42 | int getWidth(); 43 | int getHeight(); 44 | void RenderInfo(); 45 | void RenderMenu(); 46 | void RenderEsp(); 47 | void ClickThrough(bool v); 48 | void DrawLine(ImVec2 a, ImVec2 b, ImColor color, float width); 49 | void DrawBox(ImColor color, float x, float y, float w, float h); 50 | void Text(ImVec2 pos, ImColor color, const char* text_begin, const char* text_end, float wrap_width, const ImVec4* cpu_fine_clip_rect); 51 | void RectFilled(float x0, float y0, float x1, float y1, ImColor color, float rounding, int rounding_corners_flags); 52 | void ProgressBar(float x, float y, float w, float h, int value, int v_max); 53 | void String(ImVec2 pos, ImColor color, const char* text); 54 | private: 55 | bool running; 56 | HWND overlayHWND; 57 | }; -------------------------------------------------------------------------------- /apex_guest/Client/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/Overlay/Overlay.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.29519.87 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Overlay", "Overlay\Overlay.vcxproj", "{68C049A1-7EA4-45D2-942C-7710AF16B1FA}" 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 | {68C049A1-7EA4-45D2-942C-7710AF16B1FA}.Debug|x64.ActiveCfg = Debug|x64 15 | {68C049A1-7EA4-45D2-942C-7710AF16B1FA}.Debug|x64.Build.0 = Debug|x64 16 | {68C049A1-7EA4-45D2-942C-7710AF16B1FA}.Release|x64.ActiveCfg = Release|x64 17 | {68C049A1-7EA4-45D2-942C-7710AF16B1FA}.Release|x64.Build.0 = Release|x64 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {CA1CD6B1-E5B8-4031-A3BE-BCFCBAE43EEA} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /apex_guest/Overlay/Overlay/Overlay.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 6 | h;hh;hpp;hxx;hm;inl;inc;ipp;xsd 7 | 8 | 9 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 10 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | -------------------------------------------------------------------------------- /apex_guest/Overlay/Overlay/Overlay.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /apex_guest/Overlay/Overlay/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #pragma comment(lib, "dwmapi.lib") 5 | 6 | const MARGINS margins = { -1 ,-1, -1, -1 }; 7 | const wchar_t g_szClassName[] = L"overlay"; 8 | 9 | int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) 10 | { 11 | WNDCLASSEX wc; 12 | HWND hwnd; 13 | MSG Msg; 14 | 15 | wc.cbSize = sizeof(WNDCLASSEX); 16 | wc.style = CS_HREDRAW | CS_VREDRAW; 17 | wc.lpfnWndProc = DefWindowProc; 18 | wc.cbClsExtra = 0; 19 | wc.cbWndExtra = 0; 20 | wc.hInstance = hInstance; 21 | wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); 22 | wc.hCursor = LoadCursor(NULL, IDC_ARROW); 23 | wc.hbrBackground = (HBRUSH)(RGB(0,0,0)); 24 | wc.lpszMenuName = NULL; 25 | wc.lpszClassName = g_szClassName; 26 | wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION); 27 | 28 | RegisterClassEx(&wc); 29 | 30 | hwnd = CreateWindowEx( 31 | WS_EX_LAYERED | WS_EX_TRANSPARENT, 32 | g_szClassName, 33 | g_szClassName, 34 | WS_POPUP | WS_VISIBLE, 35 | 0, 0, 1920, 1080, 36 | NULL, NULL, hInstance, NULL); 37 | 38 | SetLayeredWindowAttributes(hwnd, RGB(0,0,0), 255, LWA_ALPHA); 39 | DwmExtendFrameIntoClientArea(hwnd, &margins); 40 | 41 | while (GetMessage(&Msg, NULL, 0, 0) > 0) 42 | { 43 | TranslateMessage(&Msg); 44 | DispatchMessage(&Msg); 45 | } 46 | exit(0); 47 | return Msg.wParam; 48 | } -------------------------------------------------------------------------------- /apex_guest/apex_guest.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.29519.87 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Client", "Client\Client\Client.vcxproj", "{9BF6CD05-63DA-49CF-905E-B82F5F24AC6E}" 7 | EndProject 8 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Overlay", "Overlay\Overlay\Overlay.vcxproj", "{68C049A1-7EA4-45D2-942C-7710AF16B1FA}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|x64 = Debug|x64 13 | Release|x64 = Release|x64 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {9BF6CD05-63DA-49CF-905E-B82F5F24AC6E}.Debug|x64.ActiveCfg = Debug|x64 17 | {9BF6CD05-63DA-49CF-905E-B82F5F24AC6E}.Debug|x64.Build.0 = Debug|x64 18 | {9BF6CD05-63DA-49CF-905E-B82F5F24AC6E}.Release|x64.ActiveCfg = Release|x64 19 | {9BF6CD05-63DA-49CF-905E-B82F5F24AC6E}.Release|x64.Build.0 = Release|x64 20 | {68C049A1-7EA4-45D2-942C-7710AF16B1FA}.Debug|x64.ActiveCfg = Debug|x64 21 | {68C049A1-7EA4-45D2-942C-7710AF16B1FA}.Debug|x64.Build.0 = Debug|x64 22 | {68C049A1-7EA4-45D2-942C-7710AF16B1FA}.Release|x64.ActiveCfg = Release|x64 23 | {68C049A1-7EA4-45D2-942C-7710AF16B1FA}.Release|x64.Build.0 = Release|x64 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {CA1CD6B1-E5B8-4031-A3BE-BCFCBAE43EEA} 30 | EndGlobalSection 31 | EndGlobal 32 | --------------------------------------------------------------------------------