├── page ├── .prettierrc ├── .prettierignore ├── public │ └── pinata.png ├── src │ ├── vite-env.d.ts │ ├── lib │ │ └── utils.ts │ ├── fb │ │ ├── events.ts │ │ ├── debugger │ │ │ ├── state.ts │ │ │ ├── pause-request.ts │ │ │ └── get-state-request.ts │ │ └── debugger.ts │ ├── components │ │ ├── ui │ │ │ ├── skeleton.tsx │ │ │ ├── label.tsx │ │ │ ├── separator.tsx │ │ │ ├── input.tsx │ │ │ ├── checkbox.tsx │ │ │ ├── radio-group.tsx │ │ │ ├── popover.tsx │ │ │ ├── badge.tsx │ │ │ ├── scroll-area.tsx │ │ │ ├── tooltip.tsx │ │ │ ├── tabs.tsx │ │ │ ├── resizable.tsx │ │ │ ├── button.tsx │ │ │ └── card.tsx │ │ ├── text-tooltip.tsx │ │ ├── youtube-video.tsx │ │ ├── app-sidebar.tsx │ │ ├── theme-provider.tsx │ │ ├── status-indicator.tsx │ │ └── item-list.tsx │ ├── hooks │ │ └── use-mobile.ts │ ├── main.tsx │ ├── animation.css │ ├── zip-file.ts │ ├── Loader.ts │ ├── Header.tsx │ ├── App.tsx │ └── download.ts ├── tsconfig.json ├── .gitignore ├── components.json ├── tsconfig.node.json ├── eslint.config.js ├── tsconfig.app.json ├── vite.config.ts ├── index.html └── package.json ├── src ├── emulator │ ├── empty.cpp │ ├── CMakeLists.txt │ ├── memory_region.hpp │ ├── emulator.hpp │ ├── cpu_interface.hpp │ ├── address_utils.hpp │ ├── serialization_helper.hpp │ ├── scoped_hook.hpp │ ├── memory_permission.hpp │ └── arch_emulator.hpp ├── windows-gdb-stub │ ├── empty.cpp │ └── CMakeLists.txt ├── tools │ ├── .gitignore │ ├── CMakeLists.txt │ ├── dump-apiset │ │ └── CMakeLists.txt │ └── grab-registry.bat ├── backends │ ├── icicle-emulator │ │ ├── icicle-bridge │ │ │ ├── .gitignore │ │ │ ├── data │ │ │ │ └── Ghidra │ │ │ │ │ └── Processors │ │ │ │ │ └── x86 │ │ │ │ │ └── data │ │ │ │ │ └── languages │ │ │ │ │ ├── x86-16.gdis │ │ │ │ │ ├── macros.sinc │ │ │ │ │ ├── x86-64.slaspec │ │ │ │ │ ├── x86-32-golang.register.info │ │ │ │ │ ├── old │ │ │ │ │ ├── x86RealV1.trans │ │ │ │ │ ├── x86smmV1.trans │ │ │ │ │ ├── x86V1.trans │ │ │ │ │ └── x86_64bit_v1.trans │ │ │ │ │ ├── x86.slaspec │ │ │ │ │ ├── clwb.sinc │ │ │ │ │ ├── x86-64-golang.register.info │ │ │ │ │ ├── lzcnt.sinc │ │ │ │ │ ├── x86-16-real.pspec │ │ │ │ │ ├── x86-16.pspec │ │ │ │ │ ├── adx.sinc │ │ │ │ │ ├── rdrand.sinc │ │ │ │ │ ├── x86.dwarf │ │ │ │ │ ├── smx.sinc │ │ │ │ │ ├── x86-64.dwarf │ │ │ │ │ └── sha.sinc │ │ │ └── Cargo.toml │ │ ├── icicle_x86_64_emulator.hpp │ │ └── CMakeLists.txt │ ├── CMakeLists.txt │ └── unicorn-emulator │ │ ├── unicorn_x86_64_emulator.hpp │ │ ├── CMakeLists.txt │ │ ├── unicorn.hpp │ │ ├── function_wrapper.hpp │ │ ├── unicorn_memory_regions.hpp │ │ └── unicorn_hook.hpp ├── fuzzer │ ├── resources │ │ └── icon.ico │ ├── CMakeLists.txt │ └── std_include.hpp ├── analyzer │ ├── resources │ │ └── icon.ico │ ├── snapshot.hpp │ ├── test.py │ ├── std_include.hpp │ ├── CMakeLists.txt │ ├── analysis.hpp │ └── tenet_tracer.hpp ├── windows-emulator │ ├── ports │ │ ├── api_port.hpp │ │ ├── dns_resolver.hpp │ │ └── api_port.cpp │ ├── devices │ │ ├── mount_point_manager.hpp │ │ ├── security_support_provider.hpp │ │ ├── afd_endpoint.hpp │ │ └── named_pipe.hpp │ ├── network │ │ ├── static_socket_factory.hpp │ │ ├── socket_factory.hpp │ │ ├── i_socket.hpp │ │ ├── socket_wrapper.hpp │ │ └── socket_factory.cpp │ ├── cpu_context.hpp │ ├── minidump_loader.hpp │ ├── CMakeLists.txt │ ├── module │ │ ├── module_mapping.hpp │ │ └── mapped_module.hpp │ ├── generic_logger.hpp │ ├── std_include.hpp │ ├── wow64_heaven_gate.hpp │ ├── apiset │ │ └── apiset.hpp │ ├── logger.hpp │ ├── exception_dispatch.hpp │ ├── syscall_dispatcher.hpp │ ├── kusd_mmio.hpp │ └── syscalls │ │ └── exception.cpp ├── samples │ ├── test-sample │ │ ├── resources │ │ │ └── icon.ico │ │ └── CMakeLists.txt │ ├── bad-sample │ │ ├── CMakeLists.txt │ │ └── bad.cpp │ └── CMakeLists.txt ├── backend-selection │ ├── backend_selection.hpp │ ├── CMakeLists.txt │ └── backend_selection.cpp ├── common │ ├── platform │ │ ├── network.hpp │ │ ├── synchronisation.hpp │ │ ├── traits.hpp │ │ ├── platform.hpp │ │ ├── compiler.hpp │ │ ├── primitives.hpp │ │ └── port.hpp │ ├── utils │ │ ├── compression.hpp │ │ ├── win.hpp │ │ ├── interupt_handler.hpp │ │ ├── object.hpp │ │ ├── timer.hpp │ │ ├── io.hpp │ │ ├── moved_marker.hpp │ │ ├── string.cpp │ │ ├── function.hpp │ │ ├── finally.hpp │ │ ├── lazy_object.hpp │ │ ├── concurrency.hpp │ │ ├── path_key.hpp │ │ ├── nt_handle.hpp │ │ └── interupt_handler.cpp │ ├── CMakeLists.txt │ └── network │ │ ├── tcp_server_socket.hpp │ │ ├── udp_socket.hpp │ │ ├── tcp_server_socket.cpp │ │ ├── tcp_client_socket.hpp │ │ ├── udp_socket.cpp │ │ └── socket.hpp ├── debugger │ ├── message_transmitter.hpp │ ├── event_handler.hpp │ ├── CMakeLists.txt │ ├── events.fbs │ └── message_transmitter.cpp ├── gdb-stub │ ├── CMakeLists.txt │ ├── checksum.hpp │ ├── stream_processor.hpp │ ├── async_handler.hpp │ ├── connection_handler.hpp │ ├── async_handler.cpp │ └── gdb_stub.hpp ├── fuzzing-engine │ ├── CMakeLists.txt │ ├── fuzzer.hpp │ ├── random_generator.cpp │ ├── input_generator.hpp │ └── random_generator.hpp ├── windows-emulator-test │ ├── file_system_test.cpp │ ├── CMakeLists.txt │ ├── emulation_test.cpp │ └── time_test.cpp └── CMakeLists.txt ├── .clang-format-ignore ├── docs └── images │ ├── yt.jpg │ ├── cover.png │ └── preview.jpg ├── cmake ├── misc │ └── node-pre-script.js └── toolchain │ ├── ios.cmake │ ├── android-ndk.cmake │ ├── emscripten.cmake │ └── mingw-w64.cmake ├── deps ├── googletest.cmake ├── zlib.cmake └── CMakeLists.txt ├── .github └── dependabot.yml ├── .clang-format ├── .gitmodules └── CMakePresets.json /page/.prettierrc: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /src/emulator/empty.cpp: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/windows-gdb-stub/empty.cpp: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.clang-format-ignore: -------------------------------------------------------------------------------- 1 | **/*.hxx 2 | deps/**/* 3 | -------------------------------------------------------------------------------- /src/tools/.gitignore: -------------------------------------------------------------------------------- 1 | root 2 | root*/ 3 | registry -------------------------------------------------------------------------------- /src/tools/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory(dump-apiset) 2 | -------------------------------------------------------------------------------- /page/.prettierignore: -------------------------------------------------------------------------------- 1 | # Ignore artifacts: 2 | dist 3 | src/fb/ -------------------------------------------------------------------------------- /src/backends/icicle-emulator/icicle-bridge/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | /Ghidra 3 | -------------------------------------------------------------------------------- /docs/images/yt.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/momo5502/sogen/HEAD/docs/images/yt.jpg -------------------------------------------------------------------------------- /cmake/misc/node-pre-script.js: -------------------------------------------------------------------------------- 1 | Module["preRun"] = () => { 2 | ENV = process.env; 3 | }; 4 | -------------------------------------------------------------------------------- /docs/images/cover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/momo5502/sogen/HEAD/docs/images/cover.png -------------------------------------------------------------------------------- /docs/images/preview.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/momo5502/sogen/HEAD/docs/images/preview.jpg -------------------------------------------------------------------------------- /page/public/pinata.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/momo5502/sogen/HEAD/page/public/pinata.png -------------------------------------------------------------------------------- /src/fuzzer/resources/icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/momo5502/sogen/HEAD/src/fuzzer/resources/icon.ico -------------------------------------------------------------------------------- /src/analyzer/resources/icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/momo5502/sogen/HEAD/src/analyzer/resources/icon.ico -------------------------------------------------------------------------------- /deps/googletest.cmake: -------------------------------------------------------------------------------- 1 | option(BUILD_GMOCK OFF) 2 | option(INSTALL_GTEST OFF) 3 | 4 | add_subdirectory(googletest) 5 | -------------------------------------------------------------------------------- /page/src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | -------------------------------------------------------------------------------- /src/windows-emulator/ports/api_port.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "../port.hpp" 3 | 4 | std::unique_ptr create_api_port(); 5 | -------------------------------------------------------------------------------- /cmake/toolchain/ios.cmake: -------------------------------------------------------------------------------- 1 | set(CMAKE_SYSTEM_NAME "iOS") 2 | set(CMAKE_OSX_ARCHITECTURES "arm64") 3 | set(CMAKE_OSX_DEPLOYMENT_TARGET 14.0) -------------------------------------------------------------------------------- /src/samples/test-sample/resources/icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/momo5502/sogen/HEAD/src/samples/test-sample/resources/icon.ico -------------------------------------------------------------------------------- /src/windows-emulator/ports/dns_resolver.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "../port.hpp" 3 | 4 | std::unique_ptr create_dns_resolver(); 5 | -------------------------------------------------------------------------------- /src/backends/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory(unicorn-emulator) 2 | 3 | if (MOMO_ENABLE_RUST) 4 | add_subdirectory(icicle-emulator) 5 | endif() 6 | -------------------------------------------------------------------------------- /src/backends/icicle-emulator/icicle-bridge/data/Ghidra/Processors/x86/data/languages/x86-16.gdis: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/windows-emulator/devices/mount_point_manager.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "../io_device.hpp" 3 | 4 | std::unique_ptr create_mount_point_manager(); 5 | -------------------------------------------------------------------------------- /src/windows-emulator/devices/security_support_provider.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "../io_device.hpp" 3 | 4 | std::unique_ptr create_security_support_provider(); 5 | -------------------------------------------------------------------------------- /src/backend-selection/backend_selection.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | std::unique_ptr create_x86_64_emulator(); 7 | -------------------------------------------------------------------------------- /src/common/platform/network.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | template 4 | struct EMU_WSABUF 5 | { 6 | ULONG len; 7 | EMULATOR_CAST(typename Traits::PVOID, CHAR*) buf; 8 | }; 9 | -------------------------------------------------------------------------------- /page/src/lib/utils.ts: -------------------------------------------------------------------------------- 1 | import { clsx, type ClassValue } from "clsx"; 2 | import { twMerge } from "tailwind-merge"; 3 | 4 | export function cn(...inputs: ClassValue[]) { 5 | return twMerge(clsx(inputs)); 6 | } 7 | -------------------------------------------------------------------------------- /src/windows-emulator/devices/afd_endpoint.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "../io_device.hpp" 3 | 4 | std::unique_ptr create_afd_endpoint(); 5 | std::unique_ptr create_afd_async_connect_hlp(); 6 | -------------------------------------------------------------------------------- /src/windows-emulator/network/static_socket_factory.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "socket_factory.hpp" 4 | 5 | namespace network 6 | { 7 | std::unique_ptr create_static_socket_factory(); 8 | } 9 | -------------------------------------------------------------------------------- /src/backends/icicle-emulator/icicle-bridge/data/Ghidra/Processors/x86/data/languages/macros.sinc: -------------------------------------------------------------------------------- 1 | macro conditionalAssign(dest, cond, trueVal, falseVal) { 2 | dest = zext(cond) * trueVal | zext(!cond) * falseVal; 3 | } 4 | -------------------------------------------------------------------------------- /src/backends/icicle-emulator/icicle-bridge/data/Ghidra/Processors/x86/data/languages/x86-64.slaspec: -------------------------------------------------------------------------------- 1 | @define IA64 "IA64" 2 | @include "x86.slaspec" 3 | with : lockprefx=0 { 4 | @include "sgx.sinc" 5 | @include "fma.sinc" 6 | } 7 | -------------------------------------------------------------------------------- /cmake/toolchain/android-ndk.cmake: -------------------------------------------------------------------------------- 1 | set(CMAKE_SYSTEM_NAME "Android") 2 | set(CMAKE_ANDROID_NDK "$ENV{ANDROID_NDK_ROOT}") 3 | 4 | set(ANDROID_ABI "$ENV{ANDROID_ABI}") 5 | set(CMAKE_ANDROID_ARCH_ABI "${ANDROID_ABI}") 6 | set(CMAKE_ANDROID_API "24") -------------------------------------------------------------------------------- /src/windows-emulator/cpu_context.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "arch_emulator.hpp" 3 | 4 | namespace cpu_context 5 | { 6 | void save(x86_64_emulator& emu, CONTEXT64& context); 7 | void restore(x86_64_emulator& emu, const CONTEXT64& context); 8 | } 9 | -------------------------------------------------------------------------------- /src/windows-emulator/minidump_loader.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | class windows_emulator; 5 | 6 | namespace minidump_loader 7 | { 8 | void load_minidump_into_emulator(windows_emulator& win_emu, const std::filesystem::path& minidump_path); 9 | } 10 | -------------------------------------------------------------------------------- /page/src/fb/events.ts: -------------------------------------------------------------------------------- 1 | // automatically generated by the FlatBuffers compiler, do not modify 2 | 3 | /* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */ 4 | 5 | export * as Debugger from './debugger.js'; 6 | -------------------------------------------------------------------------------- /src/samples/bad-sample/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | file(GLOB_RECURSE SRC_FILES CONFIGURE_DEPENDS 2 | *.cpp 3 | *.hpp 4 | *.rc 5 | ) 6 | 7 | list(SORT SRC_FILES) 8 | 9 | add_executable(bad-sample ${SRC_FILES}) 10 | target_link_libraries(bad-sample PRIVATE emulator-common) 11 | 12 | momo_assign_source_group(${SRC_FILES}) 13 | -------------------------------------------------------------------------------- /src/emulator/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | file(GLOB_RECURSE SRC_FILES CONFIGURE_DEPENDS 2 | *.cpp 3 | *.hpp 4 | *.rc 5 | ) 6 | 7 | list(SORT SRC_FILES) 8 | 9 | add_library(emulator ${SRC_FILES}) 10 | 11 | target_link_libraries(emulator PUBLIC emulator-common) 12 | target_include_directories(emulator INTERFACE "${CMAKE_CURRENT_LIST_DIR}") 13 | -------------------------------------------------------------------------------- /page/src/fb/debugger/state.ts: -------------------------------------------------------------------------------- 1 | // automatically generated by the FlatBuffers compiler, do not modify 2 | 3 | /* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */ 4 | 5 | export enum State { 6 | None = 0, 7 | Running = 1, 8 | Paused = 2 9 | } 10 | -------------------------------------------------------------------------------- /src/debugger/message_transmitter.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace debugger 7 | { 8 | void suspend_execution(std::chrono::milliseconds ms = std::chrono::milliseconds(0)); 9 | void send_message(const std::string& message); 10 | std::string receive_message(); 11 | } 12 | -------------------------------------------------------------------------------- /src/samples/test-sample/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | file(GLOB_RECURSE SRC_FILES CONFIGURE_DEPENDS 2 | *.cpp 3 | *.hpp 4 | *.rc 5 | ) 6 | 7 | list(SORT SRC_FILES) 8 | 9 | add_executable(test-sample ${SRC_FILES}) 10 | 11 | if(WIN) 12 | target_link_libraries(test-sample PRIVATE ws2_32) 13 | endif() 14 | 15 | momo_assign_source_group(${SRC_FILES}) 16 | -------------------------------------------------------------------------------- /page/src/components/ui/skeleton.tsx: -------------------------------------------------------------------------------- 1 | import { cn } from "@/lib/utils"; 2 | 3 | function Skeleton({ className, ...props }: React.ComponentProps<"div">) { 4 | return ( 5 |
10 | ); 11 | } 12 | 13 | export { Skeleton }; 14 | -------------------------------------------------------------------------------- /page/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "files": [], 3 | "references": [ 4 | { 5 | "path": "./tsconfig.app.json" 6 | }, 7 | { 8 | "path": "./tsconfig.node.json" 9 | } 10 | ], 11 | "compilerOptions": { 12 | "baseUrl": ".", 13 | "paths": { 14 | "@/*": ["./src/*"] 15 | }, 16 | "types": ["vite-plugin-pwa/client"] 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /page/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /src/backends/icicle-emulator/icicle-bridge/data/Ghidra/Processors/x86/data/languages/x86-32-golang.register.info: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /src/tools/dump-apiset/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | file(GLOB_RECURSE SRC_FILES CONFIGURE_DEPENDS 2 | *.cpp 3 | *.hpp 4 | *.rc 5 | ) 6 | 7 | list(SORT SRC_FILES) 8 | 9 | add_executable(dump-apiset ${SRC_FILES}) 10 | 11 | momo_assign_source_group(${SRC_FILES}) 12 | 13 | target_link_libraries(dump-apiset PRIVATE 14 | emulator-common 15 | ) 16 | 17 | momo_strip_target(dump-apiset) 18 | -------------------------------------------------------------------------------- /src/backends/icicle-emulator/icicle-bridge/data/Ghidra/Processors/x86/data/languages/old/x86RealV1.trans: -------------------------------------------------------------------------------- 1 | 2 | 3 | x86:LE:16:Real Mode 4 | x86:LE:16:Real Mode 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/backends/icicle-emulator/icicle-bridge/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "icicle" 3 | version = "0.1.0" 4 | edition = "2024" 5 | 6 | [lib] 7 | crate-type = ["staticlib"] 8 | 9 | [dependencies] 10 | icicle-vm = { git = "https://github.com/icicle-emu/icicle-emu" } 11 | icicle-cpu = { git = "https://github.com/icicle-emu/icicle-emu" } 12 | pcode = { git = "https://github.com/icicle-emu/icicle-emu" } 13 | -------------------------------------------------------------------------------- /src/common/utils/compression.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace utils::compression 7 | { 8 | namespace zlib 9 | { 10 | constexpr unsigned int ZCHUNK_SIZE = 16384u; 11 | std::vector compress(std::span data); 12 | std::vector decompress(std::span data); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/backends/icicle-emulator/icicle-bridge/data/Ghidra/Processors/x86/data/languages/old/x86smmV1.trans: -------------------------------------------------------------------------------- 1 | 2 | 3 | x86:LE:32:System Management Mode 4 | x86:LE:32:System Management Mode 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/emulator/memory_region.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "memory_permission.hpp" 3 | #include 4 | 5 | template 6 | struct basic_memory_region 7 | { 8 | uint64_t start{}; 9 | size_t length{}; // uint64_t? 10 | PermissionType permissions{}; 11 | }; 12 | 13 | struct memory_region : basic_memory_region<> 14 | { 15 | bool committed{}; 16 | }; 17 | -------------------------------------------------------------------------------- /src/common/platform/synchronisation.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // NOLINTBEGIN(modernize-use-using) 4 | 5 | typedef enum _EVENT_TYPE 6 | { 7 | NotificationEvent, 8 | SynchronizationEvent 9 | } EVENT_TYPE; 10 | 11 | typedef enum _WAIT_TYPE 12 | { 13 | WaitAll, 14 | WaitAny, 15 | WaitNotification, 16 | WaitDequeue, 17 | WaitDpc, 18 | } WAIT_TYPE; 19 | 20 | // NOLINTEND(modernize-use-using) 21 | -------------------------------------------------------------------------------- /src/backends/icicle-emulator/icicle-bridge/data/Ghidra/Processors/x86/data/languages/old/x86V1.trans: -------------------------------------------------------------------------------- 1 | 2 | 3 | x86:LE:32:default 4 | x86:LE:32:default 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/backends/icicle-emulator/icicle-bridge/data/Ghidra/Processors/x86/data/languages/old/x86_64bit_v1.trans: -------------------------------------------------------------------------------- 1 | 2 | 3 | x64:LE:64:default 4 | x86:LE:64:default 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/gdb-stub/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | file(GLOB_RECURSE SRC_FILES CONFIGURE_DEPENDS 2 | *.cpp 3 | *.hpp 4 | *.rc 5 | ) 6 | 7 | list(SORT SRC_FILES) 8 | 9 | add_library(gdb-stub ${SRC_FILES}) 10 | 11 | momo_assign_source_group(${SRC_FILES}) 12 | 13 | target_link_libraries(gdb-stub PUBLIC 14 | emulator-common 15 | ) 16 | 17 | target_include_directories(gdb-stub INTERFACE "${CMAKE_CURRENT_LIST_DIR}") 18 | 19 | momo_strip_target(gdb-stub) 20 | -------------------------------------------------------------------------------- /src/gdb-stub/checksum.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace gdb_stub 6 | { 7 | constexpr size_t CHECKSUM_SIZE = 2; 8 | 9 | inline uint8_t compute_checksum(const std::string_view data) 10 | { 11 | uint8_t checksum = 0; 12 | for (const auto c : data) 13 | { 14 | checksum += static_cast(c); 15 | } 16 | 17 | return checksum; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/samples/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | momo_get_all_targets(EXISTING_TARGETS) 2 | 3 | ########################################## 4 | 5 | add_subdirectory(bad-sample) 6 | add_subdirectory(test-sample) 7 | 8 | ########################################## 9 | 10 | momo_get_all_targets(ALL_TARGETS) 11 | momo_list_difference("${ALL_TARGETS}" "${EXISTING_TARGETS}" SAMPLE_TARGETS) 12 | momo_targets_remove_compile_options("${SAMPLE_TARGETS}" /arch:AVX2 -mavx2) -------------------------------------------------------------------------------- /src/fuzzing-engine/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | file(GLOB_RECURSE SRC_FILES CONFIGURE_DEPENDS 2 | *.cpp 3 | *.hpp 4 | *.rc 5 | ) 6 | 7 | list(SORT SRC_FILES) 8 | 9 | add_library(fuzzing-engine ${SRC_FILES}) 10 | 11 | momo_assign_source_group(${SRC_FILES}) 12 | 13 | target_link_libraries(fuzzing-engine PRIVATE 14 | emulator-common 15 | ) 16 | 17 | target_include_directories(fuzzing-engine INTERFACE "${CMAKE_CURRENT_LIST_DIR}") 18 | 19 | momo_strip_target(fuzzing-engine) 20 | -------------------------------------------------------------------------------- /src/windows-gdb-stub/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | file(GLOB_RECURSE SRC_FILES CONFIGURE_DEPENDS 2 | *.cpp 3 | *.hpp 4 | *.rc 5 | ) 6 | 7 | list(SORT SRC_FILES) 8 | 9 | add_library(windows-gdb-stub ${SRC_FILES}) 10 | 11 | momo_assign_source_group(${SRC_FILES}) 12 | 13 | target_link_libraries(windows-gdb-stub PUBLIC 14 | gdb-stub 15 | windows-emulator 16 | ) 17 | 18 | target_include_directories(windows-gdb-stub INTERFACE "${CMAKE_CURRENT_LIST_DIR}") 19 | 20 | momo_strip_target(windows-gdb-stub) 21 | -------------------------------------------------------------------------------- /src/backends/icicle-emulator/icicle_x86_64_emulator.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include "platform/platform.hpp" 6 | 7 | #ifdef ICICLE_EMULATOR_IMPL 8 | #define ICICLE_EMULATOR_DLL_STORAGE EXPORT_SYMBOL 9 | #else 10 | #define ICICLE_EMULATOR_DLL_STORAGE IMPORT_SYMBOL 11 | #endif 12 | 13 | namespace icicle 14 | { 15 | #if !SOGEN_BUILD_STATIC 16 | ICICLE_EMULATOR_DLL_STORAGE 17 | #endif 18 | std::unique_ptr create_x86_64_emulator(); 19 | } 20 | -------------------------------------------------------------------------------- /src/backends/unicorn-emulator/unicorn_x86_64_emulator.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include "platform/platform.hpp" 6 | 7 | #ifdef UNICORN_EMULATOR_IMPL 8 | #define UNICORN_EMULATOR_DLL_STORAGE EXPORT_SYMBOL 9 | #else 10 | #define UNICORN_EMULATOR_DLL_STORAGE IMPORT_SYMBOL 11 | #endif 12 | 13 | namespace unicorn 14 | { 15 | #if !SOGEN_BUILD_STATIC 16 | UNICORN_EMULATOR_DLL_STORAGE 17 | #endif 18 | std::unique_ptr create_x86_64_emulator(); 19 | } 20 | -------------------------------------------------------------------------------- /src/analyzer/snapshot.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace snapshot 6 | { 7 | std::vector create_emulator_snapshot(const windows_emulator& win_emu); 8 | std::filesystem::path write_emulator_snapshot(const windows_emulator& win_emu, bool log = true); 9 | 10 | void load_emulator_snapshot(windows_emulator& win_emu, std::span snapshot); 11 | void load_emulator_snapshot(windows_emulator& win_emu, const std::filesystem::path& snapshot_file); 12 | } 13 | -------------------------------------------------------------------------------- /page/components.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://ui.shadcn.com/schema.json", 3 | "style": "new-york", 4 | "rsc": false, 5 | "tsx": true, 6 | "tailwind": { 7 | "config": "", 8 | "css": "src/index.css", 9 | "baseColor": "neutral", 10 | "cssVariables": true, 11 | "prefix": "" 12 | }, 13 | "aliases": { 14 | "components": "@/components", 15 | "utils": "@/lib/utils", 16 | "ui": "@/components/ui", 17 | "lib": "@/lib", 18 | "hooks": "@/hooks" 19 | }, 20 | "iconLibrary": "lucide" 21 | } 22 | -------------------------------------------------------------------------------- /src/common/utils/win.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifdef _WIN32 4 | 5 | #ifndef _CRT_SECURE_NO_WARNINGS 6 | #define _CRT_SECURE_NO_WARNINGS 7 | #endif 8 | 9 | #ifndef _CRT_NO_POSIX_ERROR_CODES 10 | #define _CRT_NO_POSIX_ERROR_CODES 11 | #endif 12 | 13 | #ifndef NOMINMAX 14 | #define NOMINMAX 15 | #endif 16 | 17 | #ifndef WIN32_LEAN_AND_MEAN 18 | #define WIN32_LEAN_AND_MEAN 19 | #endif 20 | 21 | #ifdef __MINGW64__ 22 | #include 23 | #else 24 | #include 25 | #endif 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /src/tools/grab-registry.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | NET SESSIONS > NUL 2>&1 4 | IF %ERRORLEVEL% NEQ 0 ( 5 | ECHO Error: This script requires administrative privileges. 6 | EXIT /B 1 7 | ) 8 | 9 | SET REGDIR="registry" 10 | MKDIR %REGDIR% 11 | 12 | REG SAVE HKLM\SYSTEM %REGDIR%\SYSTEM /Y 13 | REG SAVE HKLM\SECURITY %REGDIR%\SECURITY /Y 14 | REG SAVE HKLM\SOFTWARE %REGDIR%\SOFTWARE /Y 15 | REG SAVE HKLM\HARDWARE %REGDIR%\HARDWARE /Y 16 | REG SAVE HKLM\SAM %REGDIR%\SAM /Y 17 | COPY /B /Y C:\Users\Default\NTUSER.DAT "%REGDIR%\NTUSER.DAT" 18 | -------------------------------------------------------------------------------- /src/gdb-stub/stream_processor.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | namespace gdb_stub 6 | { 7 | class stream_processor 8 | { 9 | public: 10 | bool has_packet() const; 11 | std::string get_next_packet(); 12 | void push_stream_data(const std::string& data); 13 | 14 | private: 15 | std::string stream_{}; 16 | std::queue packets_{}; 17 | 18 | void process_data_stream(); 19 | void enqueue_packet(std::string packet); 20 | }; 21 | } 22 | -------------------------------------------------------------------------------- /src/common/utils/interupt_handler.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | namespace utils 5 | { 6 | struct interupt_handler 7 | { 8 | interupt_handler(std::function callback); 9 | ~interupt_handler(); 10 | 11 | interupt_handler(interupt_handler&&) = delete; 12 | interupt_handler(const interupt_handler&) = delete; 13 | 14 | interupt_handler& operator=(interupt_handler&&) = delete; 15 | interupt_handler& operator=(const interupt_handler&) = delete; 16 | }; 17 | } 18 | -------------------------------------------------------------------------------- /src/backend-selection/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | file(GLOB_RECURSE SRC_FILES CONFIGURE_DEPENDS 2 | *.cpp 3 | *.hpp 4 | *.rc 5 | ) 6 | 7 | list(SORT SRC_FILES) 8 | 9 | add_library(backend-selection ${SRC_FILES}) 10 | 11 | momo_assign_source_group(${SRC_FILES}) 12 | 13 | target_include_directories(backend-selection INTERFACE "${CMAKE_CURRENT_LIST_DIR}") 14 | 15 | target_link_libraries(backend-selection PRIVATE 16 | unicorn-emulator 17 | ) 18 | 19 | if (MOMO_ENABLE_RUST) 20 | target_link_libraries(backend-selection PRIVATE 21 | icicle-emulator 22 | ) 23 | endif() -------------------------------------------------------------------------------- /src/backends/icicle-emulator/icicle-bridge/data/Ghidra/Processors/x86/data/languages/x86.slaspec: -------------------------------------------------------------------------------- 1 | @include "ia.sinc" 2 | @include "lockable.sinc" 3 | with : lockprefx=0 { 4 | @include "avx.sinc" 5 | @include "avx_manual.sinc" 6 | @include "avx2.sinc" 7 | @include "avx2_manual.sinc" 8 | @include "adx.sinc" 9 | @include "clwb.sinc" 10 | @include "pclmulqdq.sinc" 11 | @include "mpx.sinc" 12 | @include "lzcnt.sinc" 13 | @include "bmi1.sinc" 14 | @include "bmi2.sinc" 15 | @include "sha.sinc" 16 | @include "smx.sinc" 17 | @include "cet.sinc" 18 | @include "rdrand.sinc" 19 | } 20 | -------------------------------------------------------------------------------- /deps/zlib.cmake: -------------------------------------------------------------------------------- 1 | set(ZLIB_BUILD_TESTING OFF CACHE BOOL "" FORCE) 2 | set(ZLIB_BUILD_SHARED OFF CACHE BOOL "" FORCE) 3 | set(ZLIB_BUILD_MINIZIP OFF CACHE BOOL "" FORCE) 4 | set(ZLIB_INSTALL OFF CACHE BOOL "" FORCE) 5 | 6 | add_subdirectory(zlib) 7 | target_compile_definitions(zlibstatic PUBLIC ZLIB_CONST=1) 8 | #target_include_directories(zlibstatic PUBLIC ${zlib_SOURCE_DIR} ${zlib_BINARY_DIR}) 9 | 10 | if (TARGET zlib) 11 | set_target_properties(zlib PROPERTIES EXCLUDE_FROM_ALL TRUE) 12 | set_target_properties(zlib PROPERTIES EXCLUDE_FROM_DEFAULT_BUILD TRUE) 13 | endif() 14 | -------------------------------------------------------------------------------- /src/windows-emulator/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | file(GLOB_RECURSE SRC_FILES CONFIGURE_DEPENDS 2 | *.cpp 3 | *.hpp 4 | *.rc 5 | ) 6 | 7 | list(SORT SRC_FILES) 8 | 9 | add_library(windows-emulator ${SRC_FILES}) 10 | 11 | momo_assign_source_group(${SRC_FILES}) 12 | 13 | if(NOT MOMO_ENABLE_CLANG_TIDY) 14 | target_precompile_headers(windows-emulator PRIVATE std_include.hpp) 15 | endif() 16 | 17 | target_link_libraries(windows-emulator PUBLIC emulator minidump) 18 | 19 | target_include_directories(windows-emulator INTERFACE "${CMAKE_CURRENT_LIST_DIR}") 20 | 21 | momo_strip_target(windows-emulator) 22 | -------------------------------------------------------------------------------- /src/backends/icicle-emulator/icicle-bridge/data/Ghidra/Processors/x86/data/languages/clwb.sinc: -------------------------------------------------------------------------------- 1 | define pcodeop clwb; 2 | :CLWB m8 is vexMode=0 & $(PRE_66) & byte=0x0F; byte=0xAE; m8 & reg_opcode=6 ... { 3 | clwb(m8); 4 | } 5 | 6 | @ifdef IA64 7 | define pcodeop clflushopt; 8 | :CLFLUSHOPT m8 is $(LONGMODE_ON) & vexMode=0 & $(PRE_66) & byte=0x0F; byte=0xAE; m8 & reg_opcode=7 ... { 9 | clflushopt(m8); 10 | } 11 | @endif 12 | 13 | # Note: PCOMMIT was deprecated prior to it ever being implemented in production processors. 14 | # I never found the encoding for it. Therefore, no constructor. 15 | -------------------------------------------------------------------------------- /page/src/components/text-tooltip.tsx: -------------------------------------------------------------------------------- 1 | import { 2 | Tooltip, 3 | TooltipContent, 4 | TooltipTrigger, 5 | } from "@/components/ui/tooltip"; 6 | 7 | export interface TextTooltipProps { 8 | children?: React.ReactNode; 9 | tooltip: React.ReactNode; 10 | } 11 | 12 | export function TextTooltip(props: TextTooltipProps) { 13 | return ( 14 | 15 | 16 | {props.children} 17 | 18 | {props.tooltip} 19 | 20 | ); 21 | } 22 | -------------------------------------------------------------------------------- /src/backends/icicle-emulator/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory(icicle-bridge) 2 | 3 | file(GLOB_RECURSE SRC_FILES CONFIGURE_DEPENDS 4 | *.cpp 5 | *.hpp 6 | *.rc 7 | ) 8 | 9 | list(SORT SRC_FILES) 10 | 11 | if(SOGEN_BUILD_STATIC) 12 | add_library(icicle-emulator STATIC ${SRC_FILES}) 13 | else() 14 | add_library(icicle-emulator SHARED ${SRC_FILES}) 15 | endif() 16 | 17 | target_include_directories(icicle-emulator INTERFACE "${CMAKE_CURRENT_LIST_DIR}") 18 | 19 | target_link_libraries(icicle-emulator PUBLIC emulator) 20 | target_link_libraries(icicle-emulator PRIVATE emulator-common icicle-bridge) 21 | -------------------------------------------------------------------------------- /src/windows-emulator/network/socket_factory.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "i_socket.hpp" 4 | 5 | #include 6 | 7 | namespace network 8 | { 9 | struct poll_entry 10 | { 11 | i_socket* s{}; 12 | int16_t events{}; 13 | int16_t revents{}; 14 | }; 15 | 16 | struct socket_factory 17 | { 18 | socket_factory(); 19 | virtual ~socket_factory() = default; 20 | 21 | virtual std::unique_ptr create_socket(int af, int type, int protocol); 22 | virtual int poll_sockets(std::span entries); 23 | }; 24 | } 25 | -------------------------------------------------------------------------------- /src/backends/unicorn-emulator/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | file(GLOB_RECURSE SRC_FILES CONFIGURE_DEPENDS 2 | *.cpp 3 | *.hpp 4 | *.rc 5 | ) 6 | 7 | list(SORT SRC_FILES) 8 | 9 | if(SOGEN_BUILD_STATIC) 10 | add_library(unicorn-emulator STATIC ${SRC_FILES}) 11 | else() 12 | add_library(unicorn-emulator SHARED ${SRC_FILES}) 13 | endif() 14 | 15 | target_include_directories(unicorn-emulator INTERFACE "${CMAKE_CURRENT_LIST_DIR}") 16 | 17 | target_link_libraries(unicorn-emulator PUBLIC emulator) 18 | target_link_libraries(unicorn-emulator PRIVATE unicorn emulator-common) 19 | 20 | momo_strip_target(unicorn-emulator) 21 | -------------------------------------------------------------------------------- /src/common/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | file(GLOB_RECURSE SRC_FILES CONFIGURE_DEPENDS 2 | *.cpp 3 | *.hpp 4 | ) 5 | 6 | add_library(emulator-common ${SRC_FILES}) 7 | 8 | momo_assign_source_group(${SRC_FILES}) 9 | 10 | target_include_directories(emulator-common INTERFACE "${CMAKE_CURRENT_LIST_DIR}") 11 | 12 | set(THREADS_PREFER_PTHREAD_FLAG ON) 13 | find_package(Threads REQUIRED) 14 | 15 | target_link_libraries(emulator-common PUBLIC 16 | Threads::Threads 17 | zlibstatic 18 | minidump::minidump 19 | ) 20 | 21 | if(WIN) 22 | target_link_libraries(emulator-common PUBLIC 23 | ws2_32 24 | ) 25 | endif() 26 | -------------------------------------------------------------------------------- /src/fuzzer/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | file(GLOB_RECURSE SRC_FILES CONFIGURE_DEPENDS 2 | *.cpp 3 | *.hpp 4 | *.rc 5 | ) 6 | 7 | list(SORT SRC_FILES) 8 | 9 | add_executable(fuzzer ${SRC_FILES}) 10 | 11 | momo_assign_source_group(${SRC_FILES}) 12 | 13 | if(NOT MOMO_ENABLE_CLANG_TIDY) 14 | target_precompile_headers(fuzzer PRIVATE std_include.hpp) 15 | endif() 16 | 17 | target_link_libraries(fuzzer PRIVATE 18 | fuzzing-engine 19 | windows-emulator 20 | ) 21 | 22 | if (MOMO_ENABLE_RUST) 23 | target_link_libraries(fuzzer PRIVATE 24 | icicle-emulator 25 | ) 26 | endif() 27 | 28 | momo_strip_target(fuzzer) 29 | -------------------------------------------------------------------------------- /src/common/utils/object.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace utils 4 | { 5 | struct object 6 | { 7 | object() = default; 8 | virtual ~object() = default; 9 | 10 | object(object&&) = default; 11 | object(const object&) = default; 12 | object& operator=(object&&) = default; 13 | object& operator=(const object&) = default; 14 | }; 15 | 16 | template 17 | void reset_object_with_delayed_destruction(T& obj) 18 | { 19 | T new_obj{}; 20 | const auto old = std::move(obj); 21 | obj = std::move(new_obj); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/windows-emulator/module/module_mapping.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "mapped_module.hpp" 4 | #include "../memory_manager.hpp" 5 | 6 | mapped_module map_module_from_data(memory_manager& memory, std::span data, std::filesystem::path file); 7 | template 8 | mapped_module map_module_from_file(memory_manager& memory, std::filesystem::path file); 9 | template 10 | mapped_module map_module_from_memory(memory_manager& memory, uint64_t base_address, uint64_t image_size, const std::string& module_name); 11 | 12 | bool unmap_module(memory_manager& memory, const mapped_module& mod); 13 | -------------------------------------------------------------------------------- /src/debugger/event_handler.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace debugger 6 | { 7 | enum class emulation_state 8 | { 9 | none, 10 | running, 11 | paused, 12 | }; 13 | 14 | struct event_context 15 | { 16 | windows_emulator& win_emu; 17 | emulation_state state{emulation_state::none}; 18 | }; 19 | 20 | void handle_events(event_context& c); 21 | void handle_exit(const windows_emulator& win_emu, std::optional exit_status); 22 | void update_emulation_status(const windows_emulator& win_emu); 23 | } 24 | -------------------------------------------------------------------------------- /src/analyzer/test.py: -------------------------------------------------------------------------------- 1 | import os 2 | import subprocess 3 | 4 | emulator_root = os.getenv('EMULATOR_ROOT') 5 | analysis_sample = os.getenv('ANALYSIS_SAMPLE') 6 | virtual_sample = 'C:/analysis-sample.exe' 7 | 8 | application = 'analyzer' 9 | 10 | def make_app(app): 11 | if os.name == 'nt': 12 | return app + ".exe" 13 | 14 | return app 15 | 16 | command = [ 17 | os.path.join(os.getcwd(), make_app(application)), 18 | '-c', 19 | '-e', emulator_root, 20 | '-p', virtual_sample, analysis_sample, 21 | virtual_sample 22 | ] 23 | 24 | result = subprocess.run(command, cwd=os.getcwd()) 25 | 26 | exit(result.returncode) 27 | -------------------------------------------------------------------------------- /src/backends/icicle-emulator/icicle-bridge/data/Ghidra/Processors/x86/data/languages/x86-64-golang.register.info: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/windows-emulator-test/file_system_test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | namespace test 6 | { 7 | TEST(FileSystemTest, PathTraversalIsNotPossible) 8 | { 9 | const auto current_dir = std::filesystem::current_path(); 10 | 11 | const file_system fs{current_dir}; 12 | 13 | EXPECT_EQ(current_dir / "a", fs.translate(windows_path('a', {u"..", u"..", u"..", u"..", u"a.txt"}))); 14 | EXPECT_EQ(current_dir / "a", fs.translate(windows_path('a', {u"b", u"..", u"..", u"b", u"..", u"a.txt"}))); 15 | EXPECT_EQ(current_dir / "a", fs.translate(windows_path('a', {u"..", u"b"}))); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: gitsubmodule 4 | directory: "/" 5 | schedule: 6 | interval: monthly 7 | open-pull-requests-limit: 100 8 | 9 | - package-ecosystem: "github-actions" 10 | directory: "/" 11 | schedule: 12 | interval: monthly 13 | open-pull-requests-limit: 100 14 | 15 | - package-ecosystem: "npm" 16 | directory: "/page" 17 | schedule: 18 | interval: monthly 19 | open-pull-requests-limit: 100 20 | 21 | - package-ecosystem: "cargo" 22 | directory: "/src/backends/icicle-emulator/icicle-bridge/" 23 | schedule: 24 | interval: monthly 25 | open-pull-requests-limit: 100 26 | -------------------------------------------------------------------------------- /page/src/hooks/use-mobile.ts: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | 3 | const MOBILE_BREAKPOINT = 768; 4 | 5 | export function useIsMobile() { 6 | const [isMobile, setIsMobile] = React.useState( 7 | undefined, 8 | ); 9 | 10 | React.useEffect(() => { 11 | const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`); 12 | const onChange = () => { 13 | setIsMobile(window.innerWidth < MOBILE_BREAKPOINT); 14 | }; 15 | mql.addEventListener("change", onChange); 16 | setIsMobile(window.innerWidth < MOBILE_BREAKPOINT); 17 | return () => mql.removeEventListener("change", onChange); 18 | }, []); 19 | 20 | return !!isMobile; 21 | } 22 | -------------------------------------------------------------------------------- /src/common/network/tcp_server_socket.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "socket.hpp" 4 | #include "tcp_client_socket.hpp" 5 | 6 | namespace network 7 | { 8 | class tcp_server_socket : public socket 9 | { 10 | public: 11 | tcp_server_socket(int af); 12 | 13 | tcp_server_socket() = default; 14 | ~tcp_server_socket() override = default; 15 | 16 | tcp_server_socket(tcp_server_socket&& obj) noexcept = default; 17 | tcp_server_socket& operator=(tcp_server_socket&& obj) noexcept = default; 18 | 19 | tcp_client_socket accept(); 20 | 21 | void listen(); 22 | 23 | private: 24 | bool listening_{false}; 25 | }; 26 | } 27 | -------------------------------------------------------------------------------- /page/tsconfig.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", 4 | "target": "ES2022", 5 | "lib": ["ES2023"], 6 | "module": "ESNext", 7 | "skipLibCheck": true, 8 | 9 | /* Bundler mode */ 10 | "moduleResolution": "bundler", 11 | "allowImportingTsExtensions": true, 12 | "isolatedModules": true, 13 | "moduleDetection": "force", 14 | "noEmit": true, 15 | 16 | /* Linting */ 17 | "strict": true, 18 | "noUnusedLocals": true, 19 | "noUnusedParameters": true, 20 | "noFallthroughCasesInSwitch": true, 21 | "noUncheckedSideEffectImports": true 22 | }, 23 | "include": ["vite.config.ts"] 24 | } 25 | -------------------------------------------------------------------------------- /page/src/components/ui/label.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import * as LabelPrimitive from "@radix-ui/react-label"; 3 | 4 | import { cn } from "@/lib/utils"; 5 | 6 | function Label({ 7 | className, 8 | ...props 9 | }: React.ComponentProps) { 10 | return ( 11 | 19 | ); 20 | } 21 | 22 | export { Label }; 23 | -------------------------------------------------------------------------------- /src/common/network/udp_socket.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "socket.hpp" 4 | 5 | #include 6 | 7 | namespace network 8 | { 9 | struct udp_socket : socket 10 | { 11 | udp_socket(int af); 12 | udp_socket() = default; 13 | ~udp_socket() override = default; 14 | 15 | udp_socket(udp_socket&& obj) noexcept = default; 16 | udp_socket& operator=(udp_socket&& obj) noexcept = default; 17 | 18 | [[maybe_unused]] bool send(const address& target, const void* data, size_t size) const; 19 | [[maybe_unused]] bool send(const address& target, std::string_view data) const; 20 | std::optional> receive() const; 21 | }; 22 | } 23 | -------------------------------------------------------------------------------- /src/fuzzer/std_include.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | #include 27 | 28 | #include 29 | 30 | // NOLINTNEXTLINE(google-global-names-in-headers) 31 | using namespace std::literals; 32 | -------------------------------------------------------------------------------- /page/src/main.tsx: -------------------------------------------------------------------------------- 1 | import { StrictMode } from "react"; 2 | import { createRoot } from "react-dom/client"; 3 | import "./index.css"; 4 | import App from "./App.tsx"; 5 | import { registerSW } from "virtual:pwa-register"; 6 | import Loader from "./Loader"; 7 | 8 | registerSW({ 9 | onNeedRefresh() { 10 | Loader.setLoading(false); 11 | window.location.reload(); 12 | }, 13 | onOfflineReady() { 14 | Loader.setLoading(false); 15 | }, 16 | onRegisteredSW(_, registration) { 17 | registration?.addEventListener("updatefound", () => { 18 | Loader.setLoading(true); 19 | }); 20 | }, 21 | }); 22 | 23 | createRoot(document.getElementById("root")!).render( 24 | 25 | 26 | , 27 | ); 28 | -------------------------------------------------------------------------------- /src/windows-emulator/generic_logger.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | #if (defined(__clang__) || defined(__GNUC__)) && !defined(__MINGW64__) 5 | #define FORMAT_ATTRIBUTE(fmt_pos, var_pos) __attribute__((format(printf, fmt_pos, var_pos))) 6 | #else 7 | #define FORMAT_ATTRIBUTE(fmt_pos, var_pos) 8 | #endif 9 | 10 | enum class color 11 | { 12 | black, 13 | red, 14 | green, 15 | yellow, 16 | blue, 17 | cyan, 18 | pink, 19 | white, 20 | gray, 21 | dark_gray, 22 | }; 23 | 24 | struct generic_logger : utils::object 25 | { 26 | virtual void print(color c, std::string_view message) = 0; 27 | virtual void print(color c, const char* message, ...) FORMAT_ATTRIBUTE(3, 4) = 0; 28 | }; 29 | -------------------------------------------------------------------------------- /src/common/utils/timer.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace utils 6 | { 7 | template 8 | class timer 9 | { 10 | public: 11 | void update() 12 | { 13 | this->point_ = Clock::now(); 14 | } 15 | 16 | bool has_elapsed(typename Clock::duration duration) const 17 | { 18 | return this->elapsed() > duration; 19 | } 20 | 21 | typename Clock::duration elapsed() const 22 | { 23 | const auto now = Clock::now(); 24 | return now - this->point_; 25 | } 26 | 27 | private: 28 | typename Clock::time_point point_{Clock::now()}; 29 | }; 30 | } 31 | -------------------------------------------------------------------------------- /src/analyzer/std_include.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | #include 28 | #include 29 | 30 | #include 31 | 32 | // NOLINTNEXTLINE(google-global-names-in-headers) 33 | using namespace std::literals; 34 | -------------------------------------------------------------------------------- /page/src/animation.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --gradient-loader-1: rgba(38, 38, 38, 0); 3 | --gradient-loader-2: rgb(255, 255, 255); 4 | } 5 | 6 | .animated-gradient { 7 | background: repeating-linear-gradient( 8 | to right, 9 | var(--gradient-loader-1) 0%, 10 | var(--gradient-loader-1) 35%, 11 | var(--gradient-loader-2) 50%, 12 | var(--gradient-loader-1) 53%, 13 | var(--gradient-loader-1) 100% 14 | ); 15 | width: 100%; 16 | background-size: 200% auto; 17 | background-position: 0 100%; 18 | animation: gradient 2s infinite; 19 | animation-fill-mode: forwards; 20 | animation-timing-function: linear; 21 | } 22 | 23 | @keyframes gradient { 24 | 0% { 25 | background-position: 0 0; 26 | } 27 | 100% { 28 | background-position: -200% 0; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/common/platform/traits.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | // used to retain original type "x" 6 | #define EMULATOR_CAST(T, x) T 7 | 8 | struct Emu32 9 | { 10 | }; 11 | 12 | struct Emu64 13 | { 14 | }; 15 | 16 | template 17 | struct EmulatorTraits; 18 | 19 | template <> 20 | struct EmulatorTraits 21 | { 22 | using PVOID = std::uint32_t; 23 | using ULONG_PTR = std::uint32_t; 24 | using SIZE_T = std::uint32_t; 25 | using UNICODE = char16_t; 26 | using HANDLE = std::uint32_t; 27 | }; 28 | 29 | template <> 30 | struct EmulatorTraits 31 | { 32 | using PVOID = std::uint64_t; 33 | using ULONG_PTR = std::uint64_t; 34 | using SIZE_T = std::uint64_t; 35 | using UNICODE = char16_t; 36 | using HANDLE = std::uint64_t; 37 | }; 38 | -------------------------------------------------------------------------------- /.clang-format: -------------------------------------------------------------------------------- 1 | # Format Style Options - Created with Clang Power Tools 2 | --- 3 | BasedOnStyle: Microsoft 4 | AlwaysBreakTemplateDeclarations: Yes 5 | BreakConstructorInitializers: BeforeColon 6 | DerivePointerAlignment: false 7 | FixNamespaceComments: false 8 | KeepEmptyLinesAtTheStartOfBlocks: false 9 | Language: Cpp 10 | MaxEmptyLinesToKeep: 1 11 | NamespaceIndentation: All 12 | PointerAlignment: Left 13 | SortIncludes: false 14 | AlignEscapedNewlines: Left 15 | PackConstructorInitializers: Never 16 | IndentPPDirectives: None 17 | InsertNewlineAtEOF: true 18 | ColumnLimit: 140 19 | AlignConsecutiveMacros: 20 | Enabled: true 21 | AcrossEmptyLines: true 22 | AcrossComments: true 23 | AlignCompound: true 24 | PadOperators: true 25 | BraceWrapping: 26 | AfterStruct: true 27 | AfterUnion: true 28 | ... 29 | -------------------------------------------------------------------------------- /src/debugger/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | file(GLOB_RECURSE SRC_FILES CONFIGURE_DEPENDS 2 | *.cpp 3 | *.hpp 4 | *.rc 5 | ) 6 | 7 | list(SORT SRC_FILES) 8 | 9 | add_library(debugger ${SRC_FILES}) 10 | 11 | momo_assign_source_group(${SRC_FILES}) 12 | 13 | target_link_libraries(debugger PRIVATE 14 | windows-emulator 15 | flatbuffers 16 | base64 17 | ) 18 | 19 | target_include_directories(debugger INTERFACE "${CMAKE_CURRENT_LIST_DIR}") 20 | 21 | add_custom_target(generate-flatbuffer 22 | DEPENDS flatc 23 | COMMAND "$" --gen-mutable --gen-object-api --filename-ext hxx --cpp -o "${CMAKE_CURRENT_LIST_DIR}" "${CMAKE_CURRENT_LIST_DIR}/events.fbs" 24 | COMMAND "$" --gen-mutable --gen-object-api --ts -o "${PROJECT_SOURCE_DIR}/page/src/fb" "${CMAKE_CURRENT_LIST_DIR}/events.fbs" 25 | ) 26 | -------------------------------------------------------------------------------- /src/emulator/emulator.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "cpu_interface.hpp" 4 | #include "hook_interface.hpp" 5 | #include "memory_interface.hpp" 6 | 7 | #include "serialization.hpp" 8 | 9 | class emulator : public cpu_interface, public memory_interface, public hook_interface 10 | { 11 | public: 12 | emulator() = default; 13 | ~emulator() override = default; 14 | 15 | emulator(const emulator&) = delete; 16 | emulator& operator=(const emulator&) = delete; 17 | 18 | emulator(emulator&&) = delete; 19 | emulator& operator=(emulator&&) = delete; 20 | 21 | virtual std::string get_name() const = 0; 22 | 23 | virtual void serialize_state(utils::buffer_serializer& buffer, bool is_snapshot) const = 0; 24 | virtual void deserialize_state(utils::buffer_deserializer& buffer, bool is_snapshot) = 0; 25 | }; 26 | -------------------------------------------------------------------------------- /src/windows-emulator/std_include.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #include 29 | #include 30 | #include 31 | 32 | #include "platform/platform.hpp" 33 | 34 | // NOLINTNEXTLINE(google-global-names-in-headers) 35 | using namespace std::literals; 36 | -------------------------------------------------------------------------------- /page/src/components/ui/separator.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import * as React from "react"; 4 | import * as SeparatorPrimitive from "@radix-ui/react-separator"; 5 | 6 | import { cn } from "@/lib/utils"; 7 | 8 | function Separator({ 9 | className, 10 | orientation = "horizontal", 11 | decorative = true, 12 | ...props 13 | }: React.ComponentProps) { 14 | return ( 15 | 25 | ); 26 | } 27 | 28 | export { Separator }; 29 | -------------------------------------------------------------------------------- /src/common/network/tcp_server_socket.cpp: -------------------------------------------------------------------------------- 1 | #include "tcp_server_socket.hpp" 2 | 3 | namespace network 4 | { 5 | tcp_server_socket::tcp_server_socket(const int af) 6 | : socket(af, SOCK_STREAM, IPPROTO_TCP) 7 | { 8 | } 9 | 10 | tcp_client_socket tcp_server_socket::accept() 11 | { 12 | this->listen(); 13 | 14 | address a{}; 15 | auto len = a.get_max_size(); 16 | const auto s = ::accept(this->get_socket(), &a.get_addr(), &len); 17 | if (s == INVALID_SOCKET) 18 | { 19 | return {}; 20 | } 21 | 22 | return {s, a}; 23 | } 24 | 25 | void tcp_server_socket::listen() 26 | { 27 | if (this->listening_) 28 | { 29 | return; 30 | } 31 | 32 | this->listening_ = ::listen(this->get_socket(), 32) == 0; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /page/eslint.config.js: -------------------------------------------------------------------------------- 1 | import js from "@eslint/js"; 2 | import globals from "globals"; 3 | import reactHooks from "eslint-plugin-react-hooks"; 4 | import reactRefresh from "eslint-plugin-react-refresh"; 5 | import tseslint from "typescript-eslint"; 6 | 7 | export default tseslint.config( 8 | { ignores: ["dist"] }, 9 | { 10 | extends: [js.configs.recommended, ...tseslint.configs.recommended], 11 | files: ["**/*.{ts,tsx}"], 12 | languageOptions: { 13 | ecmaVersion: 2020, 14 | globals: globals.browser, 15 | }, 16 | plugins: { 17 | "react-hooks": reactHooks, 18 | "react-refresh": reactRefresh, 19 | }, 20 | rules: { 21 | ...reactHooks.configs.recommended.rules, 22 | "react-refresh/only-export-components": [ 23 | "warn", 24 | { allowConstantExport: true }, 25 | ], 26 | }, 27 | }, 28 | ); 29 | -------------------------------------------------------------------------------- /src/windows-emulator/wow64_heaven_gate.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | namespace wow64::heaven_gate 8 | { 9 | inline constexpr uint64_t kCodeBase = 0xFF300000ULL; 10 | inline constexpr std::size_t kCodeSize = 0x1000ULL; 11 | 12 | inline constexpr uint64_t kStackBase = 0xFF400000ULL; 13 | inline constexpr std::size_t kStackSize = 0x10000ULL; 14 | inline constexpr uint64_t kStackTop = kStackBase + kStackSize; 15 | 16 | inline constexpr uint16_t kUserCodeSelector = 0x33; 17 | inline constexpr uint16_t kUserStackSelector = 0x2B; 18 | 19 | inline constexpr std::array kTrampolineBytes{0x6A, 0x33, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x83, 0x04, 0x24, 20 | 0x05, 0xCB, 0x52, 0x53, 0x9C, 0x51, 0x50, 0x48, 0xCF}; 21 | } 22 | -------------------------------------------------------------------------------- /page/tsconfig.app.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", 4 | "target": "ES2020", 5 | "useDefineForClassFields": true, 6 | "lib": ["ES2020", "DOM", "DOM.Iterable"], 7 | "module": "ESNext", 8 | "skipLibCheck": true, 9 | 10 | /* Bundler mode */ 11 | "moduleResolution": "bundler", 12 | "allowImportingTsExtensions": true, 13 | "isolatedModules": true, 14 | "moduleDetection": "force", 15 | "noEmit": true, 16 | "jsx": "react-jsx", 17 | 18 | /* Linting */ 19 | "strict": true, 20 | "noUnusedLocals": false, 21 | "noUnusedParameters": false, 22 | "noFallthroughCasesInSwitch": true, 23 | "noUncheckedSideEffectImports": true, 24 | "baseUrl": ".", 25 | "paths": { 26 | "@/*": ["./src/*"] 27 | } 28 | }, 29 | "include": ["src"] 30 | } 31 | -------------------------------------------------------------------------------- /src/backend-selection/backend_selection.cpp: -------------------------------------------------------------------------------- 1 | #include "backend_selection.hpp" 2 | 3 | #include 4 | #include 5 | 6 | #if MOMO_ENABLE_RUST_CODE 7 | #include 8 | #endif 9 | 10 | using namespace std::literals; 11 | 12 | std::unique_ptr create_x86_64_emulator() 13 | { 14 | #if MOMO_ENABLE_RUST_CODE 15 | const auto* env = getenv("EMULATOR_ICICLE"); 16 | if (env && (env == "1"sv || env == "true"sv)) 17 | { 18 | // TODO: Add proper handling for WOW64 case (x64 -> x86 emulation is not supported yet). 19 | // icicle does not support automatic cross-architecture conversion from x64 to x86. 20 | // therefore WOW64 programs are naturally not supported to run. 21 | return icicle::create_x86_64_emulator(); 22 | } 23 | #endif 24 | 25 | return unicorn::create_x86_64_emulator(); 26 | } 27 | -------------------------------------------------------------------------------- /src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory(common) 2 | add_subdirectory(emulator) 3 | add_subdirectory(gdb-stub) 4 | add_subdirectory(windows-emulator) 5 | add_subdirectory(windows-gdb-stub) 6 | add_subdirectory(backend-selection) 7 | 8 | momo_add_subdirectory_and_get_targets("backends" BACKEND_TARGETS) 9 | momo_targets_set_folder("backends" ${BACKEND_TARGETS}) 10 | 11 | if (NOT SOGEN_BUILD_STATIC) 12 | add_subdirectory(analyzer) 13 | add_subdirectory(debugger) 14 | add_subdirectory(fuzzing-engine) 15 | add_subdirectory(fuzzer) 16 | add_subdirectory(windows-emulator-test) 17 | if(WIN32 AND CMAKE_SIZEOF_VOID_P EQUAL 8) 18 | momo_add_subdirectory_and_get_targets("tools" TOOL_TARGETS) 19 | momo_targets_set_folder("tools" ${TOOL_TARGETS}) 20 | 21 | momo_add_subdirectory_and_get_targets("samples" SAMPLE_TARGETS) 22 | momo_targets_set_folder("samples" ${SAMPLE_TARGETS}) 23 | endif() 24 | endif() 25 | -------------------------------------------------------------------------------- /src/backends/icicle-emulator/icicle-bridge/data/Ghidra/Processors/x86/data/languages/lzcnt.sinc: -------------------------------------------------------------------------------- 1 | macro lzcntflags(input, output) { 2 | ZF = (output == 0); 3 | CF = (input == 0); 4 | # OF, SF, PF, AF are undefined 5 | } 6 | 7 | #### 8 | #### LZCNT instructions 9 | #### 10 | 11 | 12 | :LZCNT Reg16, rm16 is vexMode=0 & opsize=0 & $(PRE_66) & $(PRE_F3) & byte=0x0F; byte=0xBD; Reg16 ... & rm16 { 13 | 14 | Reg16 = lzcount(rm16); 15 | lzcntflags(rm16, Reg16); 16 | } 17 | 18 | :LZCNT Reg32, rm32 is vexMode=0 & opsize=1 & $(PRE_F3) & byte=0x0F; byte=0xBD; Reg32 ... & check_Reg32_dest ... & rm32 { 19 | 20 | Reg32 = lzcount(rm32); 21 | lzcntflags(rm32, Reg32); 22 | build check_Reg32_dest; 23 | } 24 | 25 | @ifdef IA64 26 | :LZCNT Reg64, rm64 is $(LONGMODE_ON) & vexMode=0 & opsize=2 & $(PRE_F3) & $(REX_W) & byte=0x0F; byte=0xBD; Reg64 ... & rm64 { 27 | 28 | Reg64 = lzcount(rm64); 29 | lzcntflags(rm64, Reg64); 30 | } 31 | @endif 32 | 33 | -------------------------------------------------------------------------------- /src/windows-emulator-test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | file(GLOB_RECURSE SRC_FILES CONFIGURE_DEPENDS 2 | *.cpp 3 | *.hpp 4 | *.rc 5 | ) 6 | 7 | list(SORT SRC_FILES) 8 | 9 | add_executable(windows-emulator-test ${SRC_FILES}) 10 | 11 | momo_assign_source_group(${SRC_FILES}) 12 | 13 | target_link_libraries(windows-emulator-test PRIVATE 14 | gtest 15 | gtest_main 16 | windows-emulator 17 | backend-selection 18 | ) 19 | 20 | if(WIN32 AND CMAKE_SIZEOF_VOID_P EQUAL 8) 21 | add_dependencies(windows-emulator-test test-sample) 22 | endif() 23 | 24 | add_test(NAME windows-emulator-test 25 | COMMAND ${CMAKE_COMMAND} -E env "LD_LIBRARY_PATH=." -- "${PYTHON3_EXE}" "${PROJECT_SOURCE_DIR}/deps/gtest-parallel/gtest_parallel.py" ./windows-emulator-test 26 | WORKING_DIRECTORY "$") 27 | 28 | momo_targets_set_folder("tests" windows-emulator-test) 29 | 30 | momo_strip_target(windows-emulator-test) 31 | -------------------------------------------------------------------------------- /src/analyzer/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | file(GLOB_RECURSE SRC_FILES CONFIGURE_DEPENDS 2 | *.cpp 3 | *.hpp 4 | *.rc 5 | ) 6 | 7 | list(SORT SRC_FILES) 8 | 9 | add_executable(analyzer ${SRC_FILES}) 10 | 11 | momo_assign_source_group(${SRC_FILES}) 12 | 13 | if(NOT MOMO_ENABLE_CLANG_TIDY) 14 | target_precompile_headers(analyzer PRIVATE std_include.hpp) 15 | endif() 16 | 17 | target_link_libraries(analyzer PRIVATE 18 | reflect 19 | debugger 20 | capstone 21 | windows-emulator 22 | windows-gdb-stub 23 | backend-selection 24 | ) 25 | 26 | set_property(GLOBAL PROPERTY VS_STARTUP_PROJECT analyzer) 27 | 28 | momo_strip_target(analyzer) 29 | 30 | set(ENV_PREFIX "$") 31 | set(ENV_SUFFIX "") 32 | 33 | if(WIN) 34 | set(ENV_PREFIX "%") 35 | set(ENV_SUFFIX "%") 36 | endif() 37 | 38 | add_test(NAME analyzer-test 39 | COMMAND "${PYTHON3_EXE}" "${CMAKE_CURRENT_LIST_DIR}/test.py" 40 | WORKING_DIRECTORY "$") 41 | -------------------------------------------------------------------------------- /src/emulator/cpu_interface.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | struct cpu_interface 9 | { 10 | virtual ~cpu_interface() = default; 11 | 12 | struct descriptor_table_register 13 | { 14 | uint64_t base{}; 15 | uint32_t limit{}; 16 | }; 17 | 18 | virtual bool read_descriptor_table(int reg, descriptor_table_register& table) = 0; 19 | 20 | virtual void start(size_t count = 0) = 0; 21 | virtual void stop() = 0; 22 | 23 | virtual size_t read_raw_register(int reg, void* value, size_t size) = 0; 24 | virtual size_t write_raw_register(int reg, const void* value, size_t size) = 0; 25 | 26 | virtual std::vector save_registers() const = 0; 27 | virtual void restore_registers(const std::vector& register_data) = 0; 28 | 29 | // TODO: Remove this 30 | virtual bool has_violation() const = 0; 31 | }; 32 | -------------------------------------------------------------------------------- /src/fuzzing-engine/fuzzer.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | namespace fuzzer 9 | { 10 | using coverage_functor = void(uint64_t address); 11 | 12 | enum class execution_result 13 | { 14 | success, 15 | error, 16 | }; 17 | 18 | struct executer 19 | { 20 | virtual ~executer() = default; 21 | 22 | virtual execution_result execute(std::span data, const std::function& coverage_handler) = 0; 23 | }; 24 | 25 | struct fuzzing_handler 26 | { 27 | virtual ~fuzzing_handler() = default; 28 | 29 | virtual std::unique_ptr make_executer() = 0; 30 | 31 | virtual bool stop() 32 | { 33 | return false; 34 | } 35 | }; 36 | 37 | void run(fuzzing_handler& handler, size_t concurrency = std::thread::hardware_concurrency()); 38 | } 39 | -------------------------------------------------------------------------------- /src/windows-emulator/devices/named_pipe.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "../io_device.hpp" 3 | 4 | class named_pipe : public io_device_container 5 | { 6 | public: 7 | std::u16string name; 8 | std::deque write_queue; 9 | ACCESS_MASK access = 0; 10 | ULONG pipe_type; 11 | ULONG read_mode; 12 | ULONG completion_mode; 13 | ULONG max_instances; 14 | ULONG inbound_quota; 15 | ULONG outbound_quota; 16 | LARGE_INTEGER default_timeout; 17 | 18 | void create(windows_emulator&, const io_device_creation_data&) override 19 | { 20 | } 21 | void work(windows_emulator&) override 22 | { 23 | } 24 | NTSTATUS io_control(windows_emulator&, const io_device_context&) override 25 | { 26 | return STATUS_NOT_SUPPORTED; 27 | } 28 | 29 | void serialize_object(utils::buffer_serializer&) const override 30 | { 31 | } 32 | void deserialize_object(utils::buffer_deserializer&) override 33 | { 34 | } 35 | }; 36 | -------------------------------------------------------------------------------- /src/fuzzing-engine/random_generator.cpp: -------------------------------------------------------------------------------- 1 | #include "random_generator.hpp" 2 | #include 3 | 4 | namespace fuzzer 5 | { 6 | random_generator::random_generator() 7 | : rng_(std::random_device()()) 8 | { 9 | } 10 | 11 | std::mt19937::result_type random_generator::generate_number() 12 | { 13 | return this->distribution_(this->rng_); 14 | } 15 | 16 | void random_generator::fill(void* data, const size_t size) 17 | { 18 | this->fill(std::span(static_cast(data), size)); 19 | } 20 | 21 | void random_generator::fill(std::span data) 22 | { 23 | size_t i = 0; 24 | while (i < data.size()) 25 | { 26 | const auto number = this->generate_number(); 27 | 28 | const auto remaining_data = data.size() - i; 29 | const auto data_to_fill = std::min(remaining_data, sizeof(number)); 30 | 31 | memcpy(data.data() + i, &number, data_to_fill); 32 | i += data_to_fill; 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/common/platform/platform.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #if defined(_WIN32) && !defined(__MINGW64__) 4 | #pragma warning(push) 5 | #pragma warning(disable : 4201) // nameless struct/union 6 | #pragma warning(disable : 4702) // unreachable code 7 | #endif 8 | 9 | #if defined(__GNUC__) || defined(__clang__) 10 | #pragma GCC diagnostic push 11 | #pragma GCC diagnostic ignored "-Wpedantic" 12 | #endif 13 | 14 | #include "compiler.hpp" 15 | #include "primitives.hpp" 16 | #include "traits.hpp" 17 | #include "unicode.hpp" 18 | #include "status.hpp" 19 | #include "process.hpp" 20 | #include "kernel_mapped.hpp" 21 | #include "memory.hpp" 22 | #include "file_management.hpp" 23 | #include "win_pefile.hpp" 24 | #include "synchronisation.hpp" 25 | #include "registry.hpp" 26 | #include "network.hpp" 27 | #include "threading.hpp" 28 | #include "window.hpp" 29 | #include "port.hpp" 30 | 31 | #if defined(__GNUC__) || defined(__clang__) 32 | #pragma GCC diagnostic pop 33 | #endif 34 | 35 | #if defined(_WIN32) && !defined(__MINGW64__) 36 | #pragma warning(pop) 37 | #endif 38 | -------------------------------------------------------------------------------- /page/src/zip-file.ts: -------------------------------------------------------------------------------- 1 | import JSZip from "jszip"; 2 | 3 | export type ProgressHandler = ( 4 | processed: number, 5 | total: number, 6 | filename: string, 7 | ) => void; 8 | 9 | export interface FileEntry { 10 | name: string; 11 | data: ArrayBuffer; 12 | } 13 | 14 | export async function parseZipFile( 15 | arrayBuffer: ArrayBuffer, 16 | progressHandler?: ProgressHandler, 17 | ) { 18 | const zip = await JSZip.loadAsync(arrayBuffer); 19 | 20 | const files: Promise[] = []; 21 | const progress = { 22 | files: 0, 23 | processed: 0, 24 | }; 25 | 26 | zip.forEach(function (relativePath, zipEntry) { 27 | progress.files += 1; 28 | files.push( 29 | zipEntry.async("arraybuffer").then((data) => { 30 | progress.processed += 1; 31 | 32 | if (progressHandler) { 33 | progressHandler(progress.processed, progress.files, relativePath); 34 | } 35 | 36 | return { name: relativePath, data }; 37 | }), 38 | ); 39 | }); 40 | 41 | return await Promise.all(files); 42 | } 43 | -------------------------------------------------------------------------------- /src/common/network/tcp_client_socket.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "socket.hpp" 4 | 5 | #include 6 | 7 | namespace network 8 | { 9 | class tcp_server_socket; 10 | 11 | class tcp_client_socket : public socket 12 | { 13 | public: 14 | tcp_client_socket(int af); 15 | 16 | tcp_client_socket() = default; 17 | ~tcp_client_socket() override; 18 | 19 | tcp_client_socket(tcp_client_socket&& obj) noexcept = default; 20 | tcp_client_socket& operator=(tcp_client_socket&& obj) noexcept = default; 21 | 22 | [[maybe_unused]] bool send(const void* data, size_t size) const; 23 | [[maybe_unused]] bool send(std::string_view data) const; 24 | std::optional receive(std::optional max_size = std::nullopt); 25 | 26 | std::optional
get_target() const; 27 | 28 | bool connect(const address& target); 29 | 30 | private: 31 | friend tcp_server_socket; 32 | tcp_client_socket(SOCKET s, const address& target); 33 | }; 34 | } 35 | -------------------------------------------------------------------------------- /page/src/components/ui/input.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | 3 | import { cn } from "@/lib/utils"; 4 | 5 | function Input({ className, type, ...props }: React.ComponentProps<"input">) { 6 | return ( 7 | 18 | ); 19 | } 20 | 21 | export { Input }; 22 | -------------------------------------------------------------------------------- /src/gdb-stub/async_handler.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | namespace gdb_stub 8 | { 9 | class async_handler 10 | { 11 | public: 12 | using handler = void(std::atomic_bool& should_run); 13 | using handler_function = std::function; 14 | 15 | async_handler(handler_function handler); 16 | ~async_handler(); 17 | 18 | async_handler(async_handler&&) = delete; 19 | async_handler(const async_handler&) = delete; 20 | 21 | async_handler& operator=(async_handler&&) = delete; 22 | async_handler& operator=(const async_handler&) = delete; 23 | 24 | void run(); 25 | void pause(); 26 | bool is_running() const; 27 | 28 | private: 29 | std::atomic_bool run_{false}; 30 | std::atomic_bool stop_{false}; 31 | std::atomic_bool is_running_{false}; 32 | 33 | handler_function handler_{}; 34 | std::thread runner_{}; 35 | 36 | void work(); 37 | }; 38 | } 39 | -------------------------------------------------------------------------------- /src/windows-emulator/ports/api_port.cpp: -------------------------------------------------------------------------------- 1 | #include "../std_include.hpp" 2 | #include "api_port.hpp" 3 | 4 | #include "../windows_emulator.hpp" 5 | 6 | namespace 7 | { 8 | struct api_port : port 9 | { 10 | NTSTATUS handle_request(windows_emulator& win_emu, const lpc_request_context& c) override 11 | { 12 | // TODO: Fix this. This is broken and wrong. 13 | 14 | try 15 | { 16 | const emulator_object>> data{win_emu.emu(), c.recv_buffer + 0x20}; 17 | const auto dest = data.read(); 18 | const auto base = dest.Base; 19 | 20 | const auto value = base + 0x10; 21 | win_emu.emu().write_memory(base + 8, &value, sizeof(value)); 22 | } 23 | catch (...) 24 | { 25 | return STATUS_NOT_SUPPORTED; 26 | } 27 | 28 | return STATUS_SUCCESS; 29 | } 30 | }; 31 | } 32 | 33 | std::unique_ptr create_api_port() 34 | { 35 | return std::make_unique(); 36 | } 37 | -------------------------------------------------------------------------------- /src/windows-emulator/apiset/apiset.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "../emulator_utils.hpp" 8 | 9 | namespace apiset 10 | { 11 | enum class location : uint8_t 12 | { 13 | host, 14 | file, 15 | default_windows_10, 16 | default_windows_11 17 | }; 18 | 19 | struct container 20 | { 21 | std::vector data{}; 22 | 23 | const API_SET_NAMESPACE& get() const 24 | { 25 | return *reinterpret_cast(data.data()); 26 | } 27 | }; 28 | 29 | container obtain(location location, const std::filesystem::path& root); 30 | container obtain(const std::filesystem::path& root); 31 | 32 | emulator_object clone(x86_64_emulator& emu, emulator_allocator& allocator, 33 | const API_SET_NAMESPACE& orig_api_set_map); 34 | 35 | emulator_object clone(x86_64_emulator& emu, emulator_allocator& allocator, const container& container); 36 | } 37 | -------------------------------------------------------------------------------- /src/windows-emulator/network/i_socket.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace network 7 | { 8 | struct i_socket 9 | { 10 | virtual ~i_socket() = default; 11 | 12 | virtual void set_blocking(bool blocking) = 0; 13 | 14 | virtual int get_last_error() = 0; 15 | 16 | virtual bool is_ready(bool in_poll) = 0; 17 | virtual bool is_listening() = 0; 18 | 19 | virtual std::optional
get_local_address() = 0; 20 | 21 | virtual bool bind(const address& addr) = 0; 22 | virtual bool connect(const address& addr) = 0; 23 | virtual bool listen(int backlog) = 0; 24 | virtual std::unique_ptr accept(address& address) = 0; 25 | 26 | virtual sent_size send(std::span data) = 0; 27 | virtual sent_size sendto(const address& destination, std::span data) = 0; 28 | 29 | virtual sent_size recv(std::span data) = 0; 30 | virtual sent_size recvfrom(address& source, std::span data) = 0; 31 | }; 32 | } 33 | -------------------------------------------------------------------------------- /src/windows-emulator/logger.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "generic_logger.hpp" 3 | 4 | class logger : public generic_logger 5 | { 6 | public: 7 | void print(color c, std::string_view message) override; 8 | void print(color c, const char* message, ...) override FORMAT_ATTRIBUTE(3, 4); 9 | void force_print(color c, const char* message, ...) FORMAT_ATTRIBUTE(3, 4); 10 | void info(const char* message, ...) const FORMAT_ATTRIBUTE(2, 3); 11 | void warn(const char* message, ...) const FORMAT_ATTRIBUTE(2, 3); 12 | void error(const char* message, ...) const FORMAT_ATTRIBUTE(2, 3); 13 | void success(const char* message, ...) const FORMAT_ATTRIBUTE(2, 3); 14 | void log(const char* message, ...) const FORMAT_ATTRIBUTE(2, 3); 15 | 16 | void disable_output(const bool value) 17 | { 18 | this->disable_output_ = value; 19 | } 20 | 21 | bool is_output_disabled() const 22 | { 23 | return this->disable_output_; 24 | } 25 | 26 | private: 27 | bool disable_output_{false}; 28 | void print_message(color c, std::string_view message, bool force = false) const; 29 | }; 30 | -------------------------------------------------------------------------------- /src/common/utils/io.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | namespace utils::io 8 | { 9 | bool remove_file(const std::filesystem::path& file); 10 | bool move_file(const std::filesystem::path& src, const std::filesystem::path& target); 11 | bool file_exists(const std::filesystem::path& file); 12 | bool write_file(const std::filesystem::path& file, std::span data, bool append = false); 13 | bool read_file(const std::filesystem::path& file, std::vector* data); 14 | std::vector read_file(const std::filesystem::path& file); 15 | size_t file_size(const std::filesystem::path& file); 16 | bool create_directory(const std::filesystem::path& directory); 17 | bool directory_exists(const std::filesystem::path& directory); 18 | bool directory_is_empty(const std::filesystem::path& directory); 19 | void copy_folder(const std::filesystem::path& src, const std::filesystem::path& target); 20 | 21 | std::vector list_files(const std::filesystem::path& directory, bool recursive = false); 22 | } 23 | -------------------------------------------------------------------------------- /src/fuzzing-engine/input_generator.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "random_generator.hpp" 8 | 9 | namespace fuzzer 10 | { 11 | using input_score = uint64_t; 12 | using input_handler = input_score(std::span); 13 | 14 | struct input_entry 15 | { 16 | std::vector data{}; 17 | input_score score{}; 18 | }; 19 | 20 | class input_generator 21 | { 22 | public: 23 | input_generator(); 24 | 25 | void access_input(const std::function& handler); 26 | 27 | input_entry get_highest_scorer(); 28 | double get_average_score(); 29 | 30 | private: 31 | std::mutex mutex_{}; 32 | random_generator rng{}; 33 | 34 | std::vector top_scorer_{}; 35 | input_score lowest_score{0}; 36 | size_t lowest_scorer{0}; 37 | 38 | input_entry highest_scorer_{}; 39 | 40 | std::vector generate_next_input(); 41 | 42 | void store_input_entry(input_entry entry); 43 | }; 44 | } 45 | -------------------------------------------------------------------------------- /src/windows-emulator/exception_dispatch.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | class windows_emulator; 9 | 10 | void dispatch_exception(windows_emulator& win_emu, DWORD status, const std::vector::ULONG_PTR>& parameters); 11 | template 12 | requires(std::is_integral_v && !std::is_same_v) 13 | void dispatch_exception(windows_emulator& win_emu, const T status, const std::vector::ULONG_PTR>& parameters) 14 | { 15 | dispatch_exception(win_emu, static_cast(status), parameters); 16 | } 17 | 18 | void dispatch_access_violation(windows_emulator& win_emu, uint64_t address, memory_operation operation); 19 | void dispatch_guard_page_violation(windows_emulator& win_emu, uint64_t address, memory_operation operation); 20 | void dispatch_illegal_instruction_violation(windows_emulator& win_emu); 21 | void dispatch_integer_division_by_zero(windows_emulator& win_emu); 22 | void dispatch_single_step(windows_emulator& win_emu); 23 | void dispatch_breakpoint(windows_emulator& win_emu); 24 | -------------------------------------------------------------------------------- /src/common/utils/moved_marker.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | namespace utils 5 | { 6 | class moved_marker 7 | { 8 | public: 9 | moved_marker() = default; 10 | 11 | moved_marker(const moved_marker& copy) = default; 12 | moved_marker& operator=(const moved_marker&) = default; 13 | 14 | moved_marker(moved_marker&& obj) noexcept 15 | : moved_marker() 16 | { 17 | this->operator=(std::move(obj)); 18 | } 19 | 20 | moved_marker& operator=(moved_marker&& obj) noexcept 21 | { 22 | if (this != &obj) 23 | { 24 | this->was_moved_ = obj.was_moved_; 25 | obj.was_moved_ = true; 26 | } 27 | 28 | return *this; 29 | } 30 | 31 | ~moved_marker() = default; 32 | 33 | bool was_moved() const 34 | { 35 | return this->was_moved_; 36 | } 37 | 38 | void mark_as_moved() 39 | { 40 | this->was_moved_ = true; 41 | } 42 | 43 | private: 44 | bool was_moved_{false}; 45 | }; 46 | } 47 | -------------------------------------------------------------------------------- /src/backends/icicle-emulator/icicle-bridge/data/Ghidra/Processors/x86/data/languages/x86-16-real.pspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /src/samples/bad-sample/bad.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #define THE_SIZE 30 7 | 8 | extern "C" NO_INLINE EXPORT_SYMBOL void vulnerable(const uint8_t* data, const size_t size) 9 | { 10 | if (size < 10) 11 | { 12 | return; 13 | } 14 | 15 | if (data[9] != 'A') 16 | { 17 | return; 18 | } 19 | 20 | if (data[8] != 'B') 21 | { 22 | return; 23 | } 24 | 25 | if (data[7] != 'C') 26 | { 27 | return; 28 | } 29 | 30 | if (data[2] != 'V') 31 | { 32 | return; 33 | } 34 | 35 | if (data[4] != 'H') 36 | { 37 | return; 38 | } 39 | 40 | if (size < 100) 41 | { 42 | return; 43 | } 44 | 45 | *(int*)1 = 1; 46 | } 47 | 48 | uint8_t buffer[THE_SIZE] = {}; 49 | 50 | int main(int argc, const char* argv[]) 51 | { 52 | const void* input = buffer; 53 | auto size = sizeof(buffer); 54 | 55 | if (argc > 1) 56 | { 57 | input = argv[1]; 58 | size = strlen(argv[1]); 59 | } 60 | 61 | vulnerable((uint8_t*)input, size); 62 | return 0; 63 | } 64 | -------------------------------------------------------------------------------- /src/backends/icicle-emulator/icicle-bridge/data/Ghidra/Processors/x86/data/languages/x86-16.pspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /src/backends/unicorn-emulator/unicorn.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifdef _MSC_VER 4 | #pragma warning(push) 5 | #pragma warning(disable : 4505) 6 | #endif 7 | 8 | #ifdef __clang__ 9 | #pragma GCC diagnostic push 10 | #pragma GCC diagnostic ignored "-Wunused-function" 11 | #endif 12 | 13 | #ifndef NOMINMAX 14 | #define NOMINMAX 15 | #endif 16 | #include 17 | 18 | #ifdef __clang__ 19 | #pragma GCC diagnostic pop 20 | #endif 21 | 22 | #ifdef _MSC_VER 23 | #pragma warning(pop) 24 | #endif 25 | 26 | #include 27 | 28 | namespace unicorn 29 | { 30 | struct unicorn_error : std::runtime_error 31 | { 32 | unicorn_error(const uc_err error_code) 33 | : std::runtime_error(uc_strerror(error_code)), 34 | code(error_code) 35 | { 36 | } 37 | 38 | uc_err code{}; 39 | }; 40 | 41 | inline void throw_if_unicorn_error(const uc_err error_code) 42 | { 43 | if (error_code != UC_ERR_OK) 44 | { 45 | throw unicorn_error(error_code); 46 | } 47 | } 48 | 49 | inline void uce(const uc_err error_code) 50 | { 51 | throw_if_unicorn_error(error_code); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /page/src/Loader.ts: -------------------------------------------------------------------------------- 1 | import { useEffect, useState } from "react"; 2 | 3 | type Callback = (loading: boolean) => void; 4 | 5 | class Loader { 6 | private callbacks: Set = new Set(); 7 | private loading: boolean = false; 8 | 9 | public isLoading(): boolean { 10 | return this.loading; 11 | } 12 | 13 | public setLoading(value: boolean) { 14 | if (this.loading == value) { 15 | return; 16 | } 17 | 18 | this.loading = value; 19 | this.callbacks.forEach((callback) => callback(this.loading)); 20 | } 21 | 22 | public register(callback: Callback): void { 23 | this.callbacks.add(callback); 24 | } 25 | 26 | public unregister(callback: Callback): void { 27 | this.callbacks.delete(callback); 28 | } 29 | 30 | public useLoader() { 31 | const [isLoading, setIsLoading] = useState(this.isLoading()); 32 | 33 | useEffect(() => { 34 | function callback(loading: boolean) { 35 | setIsLoading(loading); 36 | } 37 | 38 | this.register(callback); 39 | 40 | return () => { 41 | this.unregister(callback); 42 | }; 43 | }); 44 | 45 | return isLoading; 46 | } 47 | } 48 | 49 | export default new Loader(); 50 | -------------------------------------------------------------------------------- /deps/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(UNICORN_ARCH "x86" CACHE STRING "") 2 | add_subdirectory(unicorn) 3 | 4 | ########################################## 5 | 6 | option(BASE64_ENABLE_TESTING "" OFF) 7 | add_subdirectory(base64) 8 | 9 | ########################################## 10 | 11 | option(FLATBUFFERS_BUILD_TESTS "" OFF) 12 | option(FLATBUFFERS_INSTALL "" OFF) 13 | add_subdirectory(flatbuffers) 14 | 15 | if(MSVC) 16 | target_compile_options(flatc PRIVATE /MD$<$:d>) 17 | endif() 18 | 19 | ########################################## 20 | 21 | add_library(reflect INTERFACE) 22 | target_include_directories(reflect INTERFACE 23 | "${CMAKE_CURRENT_LIST_DIR}/reflect" 24 | ) 25 | 26 | ########################################## 27 | 28 | add_subdirectory(minidump_cpp) 29 | 30 | ########################################## 31 | 32 | 33 | option(CAPSTONE_BUILD_MACOS_THIN "" ON) 34 | option(CAPSTONE_X86_SUPPORT "" ON) 35 | option(CAPSTONE_X86_ATT_DISABLE "" ON) 36 | option(CAPSTONE_ARCHITECTURE_DEFAULT "" OFF) 37 | option(CAPSTONE_BUILD_STATIC_MSVC_RUNTIME "" OFF) 38 | add_subdirectory(capstone) 39 | 40 | ########################################## 41 | 42 | include(googletest.cmake) 43 | include(zlib.cmake) 44 | -------------------------------------------------------------------------------- /src/backends/unicorn-emulator/function_wrapper.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | 8 | template 9 | class function_wrapper : public utils::object 10 | { 11 | public: 12 | using user_data_pointer = void*; 13 | using c_function_type = ReturnType(Args..., user_data_pointer); 14 | using functor_type = std::function; 15 | 16 | function_wrapper() = default; 17 | 18 | function_wrapper(functor_type functor) 19 | : functor_(std::make_unique(std::move(functor))) 20 | { 21 | } 22 | 23 | c_function_type* get_c_function() const 24 | { 25 | return +[](Args... args, user_data_pointer user_data) -> ReturnType { 26 | return (*static_cast(user_data))(std::forward(args)...); 27 | }; 28 | } 29 | 30 | void* get_function() const 31 | { 32 | return reinterpret_cast(this->get_c_function()); 33 | } 34 | 35 | user_data_pointer get_user_data() const 36 | { 37 | return this->functor_.get(); 38 | } 39 | 40 | private: 41 | std::unique_ptr functor_{}; 42 | }; 43 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "deps/unicorn"] 2 | path = deps/unicorn 3 | url = https://github.com/momo5502/unicorn.git 4 | shallow = true 5 | branch = dev 6 | [submodule "deps/reflect"] 7 | path = deps/reflect 8 | url = https://github.com/qlibs/reflect.git 9 | shallow = true 10 | [submodule "deps/googletest"] 11 | path = deps/googletest 12 | url = https://github.com/google/googletest.git 13 | shallow = true 14 | [submodule "deps/zlib"] 15 | path = deps/zlib 16 | url = https://github.com/madler/zlib.git 17 | branch = develop 18 | ignore = dirty 19 | shallow = true 20 | [submodule "deps/gtest-parallel"] 21 | path = deps/gtest-parallel 22 | url = https://github.com/google/gtest-parallel.git 23 | shallow = true 24 | [submodule "deps/flatbuffers"] 25 | path = deps/flatbuffers 26 | url = https://github.com/google/flatbuffers.git 27 | shallow = true 28 | [submodule "deps/base64"] 29 | path = deps/base64 30 | url = https://github.com/tobiaslocker/base64.git 31 | shallow = true 32 | [submodule "deps/minidump_cpp"] 33 | path = deps/minidump_cpp 34 | url = https://github.com/redthing1/minidump_cpp 35 | shallow = true 36 | [submodule "deps/capstone"] 37 | path = deps/capstone 38 | url = https://github.com/capstone-engine/capstone.git 39 | shallow = true -------------------------------------------------------------------------------- /src/backends/icicle-emulator/icicle-bridge/data/Ghidra/Processors/x86/data/languages/adx.sinc: -------------------------------------------------------------------------------- 1 | :ADCX Reg32, rm32 is vexMode=0 & $(PRE_66) & byte=0x0F; byte=0x38; byte=0xF6; rm32 & Reg32 ... & check_Reg32_dest ... { 2 | tmp:5 = zext(Reg32) + zext(rm32) + zext(CF); 3 | tmpCF:1 = tmp(4); # just the carry byte 4 | CF = tmpCF != 0; 5 | Reg32 = tmp:4; 6 | build check_Reg32_dest; 7 | } 8 | 9 | @ifdef IA64 10 | :ADCX Reg64, rm64 is $(LONGMODE_ON) & vexMode=0 & opsize=2 & $(PRE_66) & byte=0x0F; byte=0x38; byte=0xF6; Reg64 ... & rm64 { 11 | tmp:9 = zext(Reg64) + zext(rm64) + zext(CF); 12 | tmpCF:1 = tmp(8); # just the carry byte 13 | CF = tmpCF != 0; 14 | Reg64 = tmp:8; 15 | } 16 | @endif 17 | 18 | :ADOX Reg32, rm32 is vexMode=0 & $(PRE_F3) & byte=0x0F; byte=0x38; byte=0xF6; rm32 & Reg32 ... & check_Reg32_dest ... { 19 | tmp:5 = zext(Reg32) + zext(rm32) + zext(OF); 20 | tmpOF:1 = tmp(4); # just the carry byte 21 | OF = tmpOF != 0; 22 | Reg32 = tmp:4; 23 | build check_Reg32_dest; 24 | } 25 | 26 | @ifdef IA64 27 | :ADOX Reg64, rm64 is $(LONGMODE_ON) & vexMode=0 & opsize=2 & $(PRE_F3) & byte=0x0F; byte=0x38; byte=0xF6; Reg64 ... & rm64 { 28 | tmp:9 = zext(Reg64) + zext(rm64) + zext(OF); 29 | tmpOF:1 = tmp(8); # just the carry byte 30 | OF = tmpOF != 0; 31 | Reg64 = tmp:8; 32 | } 33 | @endif 34 | -------------------------------------------------------------------------------- /page/src/components/ui/checkbox.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import * as CheckboxPrimitive from "@radix-ui/react-checkbox"; 3 | import { CheckIcon } from "lucide-react"; 4 | 5 | import { cn } from "@/lib/utils"; 6 | 7 | function Checkbox({ 8 | className, 9 | ...props 10 | }: React.ComponentProps) { 11 | return ( 12 | 20 | 24 | 25 | 26 | 27 | ); 28 | } 29 | 30 | export { Checkbox }; 31 | -------------------------------------------------------------------------------- /src/common/platform/compiler.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #if defined(_WIN32) || defined(_WIN64) 4 | #define OS_WINDOWS 5 | 6 | #if defined(_WIN64) 7 | #define OS_WINDOWS_64 8 | #else 9 | #define OS_WINDOWS_32 10 | #endif 11 | 12 | #elif defined(__APPLE__) || defined(__MACH__) 13 | #define OS_MAC 14 | #elif defined(__linux__) 15 | #define OS_LINUX 16 | #elif defined(__EMSCRIPTEN__) 17 | #define OS_EMSCRIPTEN 18 | #else 19 | #error "Unsupported platform" 20 | #endif 21 | 22 | #ifdef OS_WINDOWS 23 | #define EXPORT_SYMBOL __declspec(dllexport) 24 | #define IMPORT_SYMBOL __declspec(dllimport) 25 | #define NO_INLINE __declspec(noinline) 26 | 27 | #ifndef DECLSPEC_ALIGN 28 | #define DECLSPEC_ALIGN(n) __declspec(align(n)) 29 | #endif 30 | 31 | #define RESTRICTED_POINTER 32 | 33 | #else 34 | #include 35 | 36 | #define EXPORT_SYMBOL __attribute__((visibility("default"))) 37 | #define IMPORT_SYMBOL 38 | #define NO_INLINE __attribute__((noinline)) 39 | 40 | #define DECLSPEC_ALIGN(n) alignas(n) 41 | #define fopen_s fopen 42 | #define sscanf_s sscanf 43 | 44 | #define RESTRICTED_POINTER __restrict 45 | 46 | #ifdef OS_MAC 47 | #define _fseeki64 fseeko 48 | #define _ftelli64 ftello 49 | #define _stat64 stat 50 | #else 51 | #define _fseeki64 fseeko64 52 | #define _ftelli64 ftello64 53 | #define _stat64 stat64 54 | #endif 55 | 56 | #endif 57 | -------------------------------------------------------------------------------- /src/windows-emulator/network/socket_wrapper.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "i_socket.hpp" 4 | 5 | namespace network 6 | { 7 | class socket_wrapper : public i_socket 8 | { 9 | public: 10 | socket_wrapper(SOCKET s); 11 | socket_wrapper(int af, int type, int protocol); 12 | ~socket_wrapper() override = default; 13 | 14 | void set_blocking(bool blocking) override; 15 | 16 | int get_last_error() override; 17 | 18 | bool is_ready(bool in_poll) override; 19 | bool is_listening() override; 20 | 21 | std::optional
get_local_address() override; 22 | 23 | bool bind(const address& addr) override; 24 | bool connect(const address& addr) override; 25 | bool listen(int backlog) override; 26 | std::unique_ptr accept(address& address) override; 27 | 28 | sent_size send(std::span data) override; 29 | sent_size sendto(const address& destination, std::span data) override; 30 | 31 | sent_size recv(std::span data) override; 32 | sent_size recvfrom(address& source, std::span data) override; 33 | 34 | const socket& get() const 35 | { 36 | return this->socket_; 37 | } 38 | 39 | private: 40 | socket socket_{}; 41 | }; 42 | } 43 | -------------------------------------------------------------------------------- /src/windows-emulator/syscall_dispatcher.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "process_context.hpp" 4 | 5 | struct syscall_context; 6 | using syscall_handler = void (*)(const syscall_context& c); 7 | 8 | struct syscall_handler_entry 9 | { 10 | syscall_handler handler{}; 11 | std::string name{}; 12 | }; 13 | 14 | class windows_emulator; 15 | 16 | class syscall_dispatcher 17 | { 18 | public: 19 | syscall_dispatcher() = default; 20 | syscall_dispatcher(const exported_symbols& ntdll_exports, std::span ntdll_data, const exported_symbols& win32u_exports, 21 | std::span win32u_data); 22 | 23 | void dispatch(windows_emulator& win_emu); 24 | 25 | void serialize(utils::buffer_serializer& buffer) const; 26 | void deserialize(utils::buffer_deserializer& buffer); 27 | 28 | void setup(const exported_symbols& ntdll_exports, std::span ntdll_data, const exported_symbols& win32u_exports, 29 | std::span win32u_data); 30 | 31 | std::string get_syscall_name(const uint64_t id) 32 | { 33 | return this->handlers_.at(id).name; 34 | } 35 | 36 | private: 37 | std::map handlers_{}; 38 | 39 | static void add_handlers(std::map& handler_mapping); 40 | void add_handlers(); 41 | }; 42 | -------------------------------------------------------------------------------- /src/windows-emulator/kusd_mmio.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "std_include.hpp" 4 | #include 5 | 6 | #include "arch_emulator.hpp" 7 | 8 | #include 9 | 10 | struct process_context; 11 | class windows_emulator; 12 | 13 | class kusd_mmio 14 | { 15 | public: 16 | kusd_mmio(memory_manager& memory, utils::clock& clock); 17 | ~kusd_mmio(); 18 | 19 | kusd_mmio(utils::buffer_deserializer& buffer); 20 | 21 | kusd_mmio(kusd_mmio&&) = delete; 22 | kusd_mmio(const kusd_mmio&) = delete; 23 | kusd_mmio& operator=(kusd_mmio&& obj) = delete; 24 | kusd_mmio& operator=(const kusd_mmio&) = delete; 25 | 26 | void serialize(utils::buffer_serializer& buffer) const; 27 | void deserialize(utils::buffer_deserializer& buffer); 28 | 29 | KUSER_SHARED_DATA64& get() 30 | { 31 | return this->kusd_; 32 | } 33 | 34 | const KUSER_SHARED_DATA64& get() const 35 | { 36 | return this->kusd_; 37 | } 38 | 39 | static uint64_t address(); 40 | 41 | void setup(); 42 | 43 | private: 44 | memory_manager* memory_{}; 45 | utils::clock* clock_{}; 46 | 47 | bool registered_{}; 48 | 49 | KUSER_SHARED_DATA64 kusd_{}; 50 | 51 | void read(uint64_t addr, void* data, size_t size); 52 | 53 | void update(); 54 | 55 | void register_mmio(); 56 | void deregister_mmio(); 57 | }; 58 | -------------------------------------------------------------------------------- /page/src/Header.tsx: -------------------------------------------------------------------------------- 1 | import { Helmet } from "react-helmet"; 2 | 3 | export interface HeaderProps { 4 | title: string; 5 | description: string; 6 | preload?: string[]; 7 | } 8 | 9 | const image = "https://momo5502.com/emulator/preview.png"; 10 | 11 | export function Header(props: HeaderProps) { 12 | return ( 13 | 14 | {props.title} 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | {props.preload?.map((l) => ( 28 | 35 | ))} 36 | 37 | ); 38 | } 39 | -------------------------------------------------------------------------------- /page/src/components/youtube-video.tsx: -------------------------------------------------------------------------------- 1 | export interface FolderProps { 2 | id: string; 3 | } 4 | 5 | export function YoutubeVideo(props: FolderProps) { 6 | const style = ` 7 | * { 8 | padding: 0; 9 | margin: 0; 10 | overflow: hidden; 11 | } 12 | 13 | html, 14 | body { 15 | height: 100%; 16 | } 17 | 18 | img, 19 | div { 20 | position: absolute; 21 | width: 100%; 22 | top: 0; 23 | bottom: 0; 24 | margin: auto; 25 | } 26 | 27 | div { 28 | height: 1.5em; 29 | text-align: center; 30 | font: 30px/1.5 sans-serif; 31 | color: white; 32 | overflow: visible; 33 | } 34 | 35 | span { 36 | background: red; 37 | padding: 10px 20px; 38 | border-radius: 15px; 39 | box-shadow: 3px 5px 10px #0000007a; 40 | } 41 | `; 42 | 43 | return ( 44 | 60 | ); 61 | } 62 | -------------------------------------------------------------------------------- /src/common/utils/string.cpp: -------------------------------------------------------------------------------- 1 | #include "string.hpp" 2 | 3 | #include 4 | #include 5 | 6 | namespace utils::string 7 | { 8 | // NOLINTNEXTLINE(cert-dcl50-cpp) 9 | const char* va(const char* format, ...) 10 | { 11 | constexpr auto buffer_count = 4; 12 | thread_local std::array, buffer_count> buffers{}; 13 | thread_local size_t current_index{0}; 14 | 15 | const auto index = current_index++; 16 | current_index %= buffers.size(); 17 | 18 | auto& buffer = buffers.at(index); 19 | 20 | if (buffer.size() < 10) 21 | { 22 | buffer.resize(10); 23 | } 24 | 25 | while (true) 26 | { 27 | va_list ap{}; 28 | va_start(ap, format); 29 | 30 | #ifdef _WIN32 31 | const int res = vsnprintf_s(buffer.data(), buffer.size(), _TRUNCATE, format, ap); 32 | #else 33 | const int res = vsnprintf(buffer.data(), buffer.size(), format, ap); 34 | #endif 35 | 36 | va_end(ap); 37 | 38 | if (res > 0 && static_cast(res) < buffer.size()) 39 | { 40 | break; 41 | } 42 | if (res == 0) 43 | { 44 | return nullptr; 45 | } 46 | 47 | buffer.resize(std::max(buffer.size() * 2, static_cast(1))); 48 | } 49 | 50 | return buffer.data(); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/windows-emulator-test/emulation_test.cpp: -------------------------------------------------------------------------------- 1 | #include "emulation_test_utils.hpp" 2 | 3 | namespace test 4 | { 5 | TEST(EmulationTest, BasicEmulationWorks) 6 | { 7 | auto emu = create_sample_emulator(); 8 | emu.start(); 9 | 10 | ASSERT_TERMINATED_SUCCESSFULLY(emu); 11 | } 12 | 13 | TEST(EmulationTest, CountedEmulationWorks) 14 | { 15 | constexpr auto count = 200000; 16 | 17 | auto emu = create_sample_emulator(); 18 | emu.start(count); 19 | 20 | ASSERT_EQ(emu.get_executed_instructions(), count); 21 | } 22 | 23 | TEST(EmulationTest, CountedEmulationIsAccurate) 24 | { 25 | auto emu = create_sample_emulator(); 26 | emu.start(); 27 | 28 | ASSERT_TERMINATED_SUCCESSFULLY(emu); 29 | 30 | const auto executedInstructions = emu.get_executed_instructions(); 31 | 32 | auto new_emu = create_sample_emulator(); 33 | 34 | constexpr auto offset = 1; 35 | const auto instructionsToExecute = executedInstructions - offset; 36 | 37 | new_emu.start(static_cast(instructionsToExecute)); 38 | 39 | ASSERT_EQ(new_emu.get_executed_instructions(), instructionsToExecute); 40 | ASSERT_NOT_TERMINATED(new_emu); 41 | 42 | new_emu.start(offset); 43 | 44 | ASSERT_TERMINATED_SUCCESSFULLY(new_emu); 45 | ASSERT_EQ(new_emu.get_executed_instructions(), executedInstructions); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/common/utils/function.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace utils 6 | { 7 | template 8 | class optional_function; 9 | 10 | template 11 | class optional_function 12 | { 13 | std::function func; 14 | 15 | public: 16 | optional_function() = default; 17 | 18 | optional_function(std::function f) 19 | : func(std::move(f)) 20 | { 21 | } 22 | 23 | template 24 | requires(std::is_invocable_r_v) 25 | optional_function(F&& f) 26 | : func(std::forward(f)) 27 | { 28 | } 29 | 30 | template 31 | requires(std::is_invocable_r_v) 32 | optional_function& operator=(F&& f) 33 | { 34 | func = std::forward(f); 35 | return *this; 36 | } 37 | 38 | Ret operator()(Args... args) const 39 | { 40 | if (func) 41 | { 42 | return func(std::forward(args)...); 43 | } 44 | 45 | if constexpr (!std::is_void_v) 46 | { 47 | return Ret(); 48 | } 49 | } 50 | 51 | explicit operator bool() const noexcept 52 | { 53 | return static_cast(func); 54 | } 55 | }; 56 | } 57 | -------------------------------------------------------------------------------- /src/backends/icicle-emulator/icicle-bridge/data/Ghidra/Processors/x86/data/languages/rdrand.sinc: -------------------------------------------------------------------------------- 1 | define pcodeop rdrand; 2 | define pcodeop rdrandIsValid; 3 | 4 | macro rdflags(){ 5 | OF = 0; SF = 0; ZF = 0; AF = 0; PF = 0; 6 | } 7 | 8 | :RDRAND Rmr16 is vexMode=0 & opsize=0 & byte=0x0f; byte=0xC7; mod=3 & Rmr16 & reg_opcode=6 9 | { 10 | Rmr16 = rdrand(); 11 | CF=rdrandIsValid(); 12 | rdflags(); 13 | 14 | } 15 | :RDRAND Rmr32 is vexMode=0 & opsize=1 & byte=0x0f; byte=0xC7; mod=3 & Rmr32 & reg_opcode=6 16 | { 17 | Rmr32 = rdrand(); 18 | CF=rdrandIsValid(); 19 | rdflags(); 20 | } 21 | @ifdef IA64 22 | :RDRAND Rmr64 is $(LONGMODE_ON) & vexMode=0 & opsize=2 & $(REX_W) & byte=0x0f; byte=0xC7; mod=3 & Rmr64 & reg_opcode=6 23 | { 24 | Rmr64 = rdrand(); 25 | CF=rdrandIsValid(); 26 | rdflags(); 27 | } 28 | @endif 29 | 30 | define pcodeop rdseed; 31 | define pcodeop rdseedIsValid; 32 | :RDSEED Rmr16 is vexMode=0 & opsize=0 & byte=0x0f; byte=0xC7; mod=3 & Rmr16 & reg_opcode=7 33 | { 34 | Rmr16 = rdseed(); 35 | CF=rdseedIsValid(); 36 | rdflags(); 37 | } 38 | :RDSEED Rmr32 is vexMode=0 & opsize=1 & byte=0x0f; byte=0xC7; mod=3 & Rmr32 & reg_opcode=7 39 | { 40 | Rmr32 = rdseed(); 41 | CF=rdseedIsValid(); 42 | rdflags(); 43 | } 44 | @ifdef IA64 45 | :RDSEED Rmr64 is $(LONGMODE_ON) & vexMode=0 & opsize=2 & $(REX_W) & byte=0x0f; byte=0xC7; mod=3 & Rmr64 & reg_opcode=7 46 | { 47 | Rmr64 = rdseed(); 48 | CF=rdseedIsValid(); 49 | rdflags(); 50 | } 51 | @endif 52 | -------------------------------------------------------------------------------- /src/windows-emulator-test/time_test.cpp: -------------------------------------------------------------------------------- 1 | #include "emulation_test_utils.hpp" 2 | 3 | namespace test 4 | { 5 | TEST(TimeTest, SystemTimeIsAccurate) 6 | { 7 | std::string output_buffer{}; 8 | 9 | emulator_callbacks callbacks{}; 10 | callbacks.on_stdout = [&output_buffer](const std::string_view data) { 11 | output_buffer.append(data); // 12 | }; 13 | 14 | const emulator_settings settings{ 15 | .use_relative_time = false, 16 | }; 17 | 18 | auto emu = create_sample_emulator(settings, {.print_time = true}, std::move(callbacks)); 19 | emu.start(); 20 | 21 | constexpr auto prefix = "Time: "sv; 22 | 23 | ASSERT_TERMINATED_SUCCESSFULLY(emu); 24 | ASSERT_TRUE(output_buffer.starts_with(prefix)); 25 | 26 | output_buffer = output_buffer.substr(prefix.size()); 27 | while (!output_buffer.empty() && (output_buffer.back() == '\n' || output_buffer.back() == '\r')) 28 | { 29 | output_buffer.pop_back(); 30 | } 31 | 32 | const auto time = strtoll(output_buffer.c_str(), nullptr, 10); 33 | 34 | using time_point = std::chrono::system_clock::time_point; 35 | 36 | const time_point::duration time_duration(time); 37 | const time_point tp(time_duration); 38 | 39 | const auto now = std::chrono::system_clock::now(); 40 | const auto diff = now - tp; 41 | 42 | ASSERT_LE(diff, std::chrono::hours(1)); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /cmake/toolchain/emscripten.cmake: -------------------------------------------------------------------------------- 1 | set(CMAKE_SYSTEM_NAME Emscripten) 2 | set(CMAKE_SYSTEM_VERSION 1) 3 | 4 | # Specify the cross-compilers 5 | set(CMAKE_C_COMPILER emcc) 6 | set(CMAKE_CXX_COMPILER em++) 7 | 8 | # Set the Emscripten root directory 9 | set(EMSCRIPTEN_ROOT_PATH $ENV{EMSDK}/upstream/emscripten) 10 | 11 | # Set the Emscripten toolchain file 12 | set(CMAKE_SYSROOT ${EMSCRIPTEN_ROOT_PATH}/system) 13 | 14 | # Set the Emscripten include directories 15 | set(CMAKE_FIND_ROOT_PATH ${EMSCRIPTEN_ROOT_PATH}/system/include) 16 | 17 | # Set the Emscripten library directories 18 | set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) 19 | set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) 20 | 21 | # Set the Emscripten linker 22 | set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -s USE_SDL=2 -s USE_SDL_MIXER=2") 23 | 24 | # Set the Emscripten runtime 25 | set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --shell-file shell_minimal.html") 26 | 27 | # Set the Emscripten optimization flags 28 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3") 29 | 30 | # Set the Emscripten debug flags 31 | set(CMAKE_BUILD_TYPE Release) 32 | 33 | # Set the Emscripten output format 34 | set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -o .html") 35 | 36 | # Set the Emscripten file extensions 37 | set(CMAKE_EXECUTABLE_SUFFIX ".js") 38 | 39 | # Set the Emscripten runtime options 40 | set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -s EXPORTED_FUNCTIONS='[_main]' -s EXPORTED_RUNTIME_METHODS='[\"cwrap\"]'") -------------------------------------------------------------------------------- /page/src/components/app-sidebar.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | 3 | import { 4 | Sidebar, 5 | SidebarContent, 6 | SidebarGroup, 7 | SidebarGroupLabel, 8 | SidebarHeader, 9 | /*SidebarMenu, 10 | SidebarGroupContent, 11 | SidebarMenuButton, 12 | SidebarMenuItem,*/ 13 | SidebarRail, 14 | } from "@/components/ui/sidebar"; 15 | 16 | // This is sample data. 17 | const data = { 18 | navMain: [ 19 | { 20 | title: "TODO", 21 | }, 22 | ], 23 | }; 24 | 25 | export function AppSidebar({ ...props }: React.ComponentProps) { 26 | return ( 27 | 28 | Filesystem 29 | 30 | {/* We create a SidebarGroup for each parent. */} 31 | {data.navMain.map((item) => ( 32 | 33 | {item.title} 34 | {/* 35 | 36 | {item.items.map((item) => ( 37 | 38 | 39 | {item.title} 40 | 41 | 42 | ))} 43 | 44 | */} 45 | 46 | ))} 47 | 48 | 49 | 50 | ); 51 | } 52 | -------------------------------------------------------------------------------- /src/common/platform/primitives.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | // NOLINTBEGIN(modernize-use-using) 6 | 7 | #ifdef OS_WINDOWS 8 | 9 | #include "../utils/win.hpp" 10 | #include "winnt.h" 11 | 12 | #else 13 | 14 | #define _Field_size_(...) 15 | #define _Struct_size_bytes_(...) 16 | 17 | #define ANYSIZE_ARRAY 1 18 | 19 | #define DWORD std::uint32_t 20 | using LONG = std::int32_t; 21 | using ULONG = DWORD; 22 | using DWORD64 = std::uint64_t; 23 | using ULONG64 = std::uint64_t; 24 | using ULONGLONG = DWORD64; 25 | using LONGLONG = std::int64_t; 26 | using UINT = std::uint32_t; 27 | using BOOL = std::int32_t; 28 | 29 | typedef union _ULARGE_INTEGER 30 | { 31 | struct 32 | { 33 | DWORD LowPart; 34 | DWORD HighPart; 35 | }; 36 | 37 | ULONGLONG QuadPart; 38 | } ULARGE_INTEGER; 39 | 40 | typedef union _LARGE_INTEGER 41 | { 42 | struct 43 | { 44 | DWORD LowPart; 45 | LONG HighPart; 46 | }; 47 | 48 | LONGLONG QuadPart; 49 | } LARGE_INTEGER; 50 | 51 | using BYTE = std::uint8_t; 52 | #define CHAR BYTE 53 | #endif 54 | 55 | using WORD = std::uint16_t; 56 | #define WCHAR WORD 57 | 58 | #define UCHAR uint8_t 59 | #define BOOLEAN UCHAR 60 | 61 | using CSHORT = int16_t; 62 | using USHORT = WORD; 63 | 64 | #define DUMMYSTRUCTNAME 65 | 66 | #ifndef TRUE 67 | #define TRUE 1 68 | #define FALSE 0 69 | #endif 70 | 71 | static_assert(sizeof(DWORD) == 4); 72 | static_assert(sizeof(ULONG) == 4); 73 | static_assert(sizeof(int) == 4); 74 | static_assert(sizeof(BOOLEAN) == 1); 75 | 76 | // NOLINTEND(modernize-use-using) 77 | -------------------------------------------------------------------------------- /src/analyzer/analysis.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include "disassembler.hpp" 6 | 7 | struct mapped_module; 8 | class module_manager; 9 | class windows_emulator; 10 | 11 | using string_set = std::set>; 12 | 13 | struct analysis_settings 14 | { 15 | bool concise_logging{false}; 16 | bool verbose_logging{false}; 17 | bool silent{false}; 18 | bool buffer_stdout{false}; 19 | bool instruction_summary{false}; 20 | 21 | string_set modules{}; 22 | string_set ignored_functions{}; 23 | }; 24 | 25 | struct accessed_import 26 | { 27 | uint64_t address{}; 28 | uint32_t thread_id{}; 29 | uint64_t access_rip{}; 30 | uint64_t access_inst_count{}; 31 | std::string accessor_module{}; 32 | std::string import_name{}; 33 | std::string import_module{}; 34 | }; 35 | 36 | struct analysis_context 37 | { 38 | const analysis_settings* settings{}; 39 | windows_emulator* win_emu{}; 40 | 41 | std::string output{}; 42 | bool has_reached_main{false}; 43 | 44 | disassembler d{}; 45 | std::unordered_map instructions{}; 46 | std::vector accessed_imports{}; 47 | std::set rdtsc_cache{}; 48 | std::set rdtscp_cache{}; 49 | std::set> cpuid_cache{}; 50 | }; 51 | 52 | void register_analysis_callbacks(analysis_context& c); 53 | std::optional get_module_if_interesting(module_manager& manager, const string_set& modules, uint64_t address); 54 | -------------------------------------------------------------------------------- /src/gdb-stub/connection_handler.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "stream_processor.hpp" 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | namespace gdb_stub 12 | { 13 | class connection_handler 14 | { 15 | public: 16 | connection_handler(network::tcp_client_socket& client, utils::optional_function should_stop = {}); 17 | ~connection_handler(); 18 | 19 | connection_handler(connection_handler&&) = delete; 20 | connection_handler(const connection_handler&) = delete; 21 | 22 | connection_handler& operator=(connection_handler&&) = delete; 23 | connection_handler& operator=(const connection_handler&) = delete; 24 | 25 | std::optional get_packet(); 26 | 27 | void send_reply(std::string_view data); 28 | void send_raw_data(std::string_view data); 29 | 30 | void close() const; 31 | 32 | bool should_stop() const; 33 | 34 | private: 35 | utils::optional_function should_stop_{}; 36 | network::tcp_client_socket& client_; 37 | stream_processor processor_{}; 38 | 39 | std::mutex mutex_{}; 40 | std::atomic_bool stop_{}; 41 | std::string output_stream_{}; 42 | std::thread output_thread_{}; 43 | std::condition_variable condition_variable_{}; 44 | 45 | void transmission_loop(); 46 | void await_transmission(const std::function& handler); 47 | std::string get_next_data_to_transmit(); 48 | }; 49 | } 50 | -------------------------------------------------------------------------------- /src/common/network/udp_socket.cpp: -------------------------------------------------------------------------------- 1 | #include "udp_socket.hpp" 2 | #include 3 | 4 | namespace network 5 | { 6 | udp_socket::udp_socket(const int af) 7 | : socket(af, SOCK_DGRAM, IPPROTO_UDP) 8 | { 9 | } 10 | 11 | bool udp_socket::send(const address& target, const void* data, const size_t size) const 12 | { 13 | return this->send(target, std::string_view(static_cast(data), size)); 14 | } 15 | 16 | bool udp_socket::send(const address& target, const std::string_view data) const 17 | { 18 | while (true) 19 | { 20 | const auto res = 21 | sendto(this->get_socket(), data.data(), static_cast(data.size()), 0, &target.get_addr(), target.get_size()); 22 | 23 | if (res < 0 && GET_SOCKET_ERROR() == SERR(EWOULDBLOCK)) 24 | { 25 | this->sleep(std::chrono::milliseconds(10), true); 26 | continue; 27 | } 28 | 29 | return static_cast(res) == data.size(); 30 | } 31 | } 32 | 33 | std::optional> udp_socket::receive() const 34 | { 35 | std::array buffer{}; 36 | address source{}; 37 | auto len = source.get_max_size(); 38 | 39 | const auto result = recvfrom(this->get_socket(), buffer.data(), static_cast(buffer.size()), 0, &source.get_addr(), &len); 40 | if (result == SOCKET_ERROR) 41 | { 42 | return std::nullopt; 43 | } 44 | 45 | return {{source, std::string(buffer.data(), static_cast(result))}}; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /page/src/components/ui/radio-group.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import * as RadioGroupPrimitive from "@radix-ui/react-radio-group"; 3 | import { CircleIcon } from "lucide-react"; 4 | 5 | import { cn } from "@/lib/utils"; 6 | 7 | function RadioGroup({ 8 | className, 9 | ...props 10 | }: React.ComponentProps) { 11 | return ( 12 | 17 | ); 18 | } 19 | 20 | function RadioGroupItem({ 21 | className, 22 | ...props 23 | }: React.ComponentProps) { 24 | return ( 25 | 33 | 37 | 38 | 39 | 40 | ); 41 | } 42 | 43 | export { RadioGroup, RadioGroupItem }; 44 | -------------------------------------------------------------------------------- /src/backends/icicle-emulator/icicle-bridge/data/Ghidra/Processors/x86/data/languages/x86.dwarf: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /cmake/toolchain/mingw-w64.cmake: -------------------------------------------------------------------------------- 1 | # cross compile 2 | set(CMAKE_SYSTEM_NAME Windows) 3 | 4 | set(MINGW_C_COMPILER_NAME "x86_64-w64-mingw32-gcc") 5 | set(MINGW_CXX_COMPILER_NAME "x86_64-w64-mingw32-g++") 6 | set(MINGW_WINDRES_COMPILER_NAME "x86_64-w64-mingw32-windres") 7 | 8 | find_file(MINGW_C_COMPILER ${MINGW_C_COMPILER_NAME}) 9 | find_file(MINGW_CXX_COMPILER ${MINGW_CXX_COMPILER_NAME}) 10 | find_file(MINGW_WINDRES_COMPILER ${MINGW_WINDRES_COMPILER_NAME}) 11 | 12 | if (${MINGW_C_COMPILER} STREQUAL "MINGW_C_COMPILER-NOTFOUND") 13 | message(FATAL_ERROR "mingw-w64 compiler not found: ${MINGW_C_COMPILER_NAME}") 14 | endif() 15 | if (${MINGW_CXX_COMPILER} STREQUAL "MINGW_CXX_COMPILER-NOTFOUND") 16 | message(FATAL_ERROR "mingw-w64 compiler not found: ${MINGW_CXX_COMPILER_NAME}") 17 | endif() 18 | if (${MINGW_WINDRES_COMPILER} STREQUAL "MINGW_WINDRES_COMPILER-NOTFOUND") 19 | message(FATAL_ERROR "mingw-w64 compiler not found: ${MINGW_WINDRES_COMPILER_NAME}") 20 | endif() 21 | 22 | # this macro is needed when compile `libwindows-emulator.a` 23 | add_compile_definitions(NTDDI_VERSION=NTDDI_WIN10_MN) 24 | 25 | # set the compiler 26 | set(CMAKE_C_COMPILER ${MINGW_C_COMPILER}) 27 | set(CMAKE_CXX_COMPILER ${MINGW_CXX_COMPILER}) 28 | set(CMAKE_RC_COMPILER ${MINGW_WINDRES_COMPILER}) 29 | 30 | # set the compiler search path 31 | set(CMAKE_FIND_ROOT_PATH /usr/x86_64-w64-mingw32) 32 | 33 | # adjust the default behaviour of the FIND_XXX() commands: 34 | # search headers and libraries in the target environment, search 35 | # programs in the host environment 36 | set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) 37 | set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) 38 | set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) 39 | -------------------------------------------------------------------------------- /src/common/utils/finally.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | namespace utils 6 | { 7 | /* 8 | * Copied from here: 9 | * https://github.com/microsoft/GSL/blob/e0880931ae5885eb988d1a8a57acf8bc2b8dacda/include/gsl/util#L57 10 | */ 11 | 12 | template 13 | class final_action 14 | { 15 | public: 16 | static_assert(!std::is_reference_v && !std::is_const_v && !std::is_volatile_v, 17 | "Final_action should store its callable by value"); 18 | 19 | explicit final_action(F f) noexcept 20 | : f_(std::move(f)) 21 | { 22 | } 23 | 24 | final_action(final_action&& other) noexcept 25 | : f_(std::move(other.f_)), 26 | invoke_(std::exchange(other.invoke_, false)) 27 | { 28 | } 29 | 30 | final_action(const final_action&) = delete; 31 | final_action& operator=(const final_action&) = delete; 32 | final_action& operator=(final_action&&) = delete; 33 | 34 | ~final_action() noexcept 35 | { 36 | if (this->invoke_) 37 | { 38 | this->f_(); 39 | } 40 | } 41 | 42 | // Added by momo5502 43 | void cancel() 44 | { 45 | this->invoke_ = false; 46 | } 47 | 48 | private: 49 | F f_; 50 | bool invoke_{true}; 51 | }; 52 | 53 | template 54 | final_action>> finally(F&& f) noexcept 55 | { 56 | return final_action>>(std::forward(f)); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/windows-emulator/syscalls/exception.cpp: -------------------------------------------------------------------------------- 1 | #include "../std_include.hpp" 2 | #include "../emulator_utils.hpp" 3 | #include "../syscall_utils.hpp" 4 | 5 | namespace syscalls 6 | { 7 | NTSTATUS handle_NtRaiseHardError(const syscall_context& c, const NTSTATUS error_status, const ULONG /*number_of_parameters*/, 8 | const emulator_object>> 9 | /*unicode_string_parameter_mask*/, 10 | const emulator_object /*parameters*/, const HARDERROR_RESPONSE_OPTION /*valid_response_option*/, 11 | const emulator_object response) 12 | { 13 | if (response) 14 | { 15 | response.write(ResponseAbort); 16 | } 17 | 18 | c.proc.exit_status = error_status; 19 | c.win_emu.callbacks.on_exception(); 20 | c.emu.stop(); 21 | 22 | return STATUS_SUCCESS; 23 | } 24 | 25 | NTSTATUS handle_NtRaiseException(const syscall_context& c, 26 | const emulator_object>> /*exception_record*/, 27 | const emulator_object /*thread_context*/, const BOOLEAN handle_exception) 28 | { 29 | if (handle_exception) 30 | { 31 | c.win_emu.log.error("Unhandled exceptions not supported yet!\n"); 32 | c.emu.stop(); 33 | return STATUS_NOT_SUPPORTED; 34 | } 35 | 36 | c.win_emu.callbacks.on_exception(); 37 | c.emu.stop(); 38 | 39 | return STATUS_SUCCESS; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /page/src/App.tsx: -------------------------------------------------------------------------------- 1 | import { ThemeProvider } from "@/components/theme-provider"; 2 | import { TooltipProvider } from "@/components/ui/tooltip"; 3 | import { HashRouter, Route, Routes, Navigate } from "react-router-dom"; 4 | import { Playground, storeEmulateData } from "./playground"; 5 | import { LandingPage } from "./landing-page"; 6 | import { useParams } from "react-router-dom"; 7 | import Loader from "./Loader"; 8 | 9 | import "@fontsource/inter/latin.css"; 10 | 11 | import "./App.css"; 12 | import "./animation.css"; 13 | 14 | function EmulateFile() { 15 | const { encodedData } = useParams(); 16 | storeEmulateData(encodedData); 17 | return ; 18 | } 19 | 20 | function Spinner() { 21 | const loading = Loader.useLoader(); 22 | 23 | return ( 24 |
30 | ); 31 | } 32 | 33 | function App() { 34 | return ( 35 | 36 | 37 | 38 | 39 | } /> 40 | } /> 41 | } /> 42 | } /> 43 | 44 | 45 | 46 | 47 | 48 | ); 49 | } 50 | 51 | export default App; 52 | -------------------------------------------------------------------------------- /page/src/fb/debugger.ts: -------------------------------------------------------------------------------- 1 | // automatically generated by the FlatBuffers compiler, do not modify 2 | 3 | /* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */ 4 | 5 | export { ApplicationExit, ApplicationExitT } from './debugger/application-exit.js'; 6 | export { DebugEvent, DebugEventT } from './debugger/debug-event.js'; 7 | export { EmulationStatus, EmulationStatusT } from './debugger/emulation-status.js'; 8 | export { Event } from './debugger/event.js'; 9 | export { GetStateRequest, GetStateRequestT } from './debugger/get-state-request.js'; 10 | export { GetStateResponse, GetStateResponseT } from './debugger/get-state-response.js'; 11 | export { PauseRequest, PauseRequestT } from './debugger/pause-request.js'; 12 | export { ReadMemoryRequest, ReadMemoryRequestT } from './debugger/read-memory-request.js'; 13 | export { ReadMemoryResponse, ReadMemoryResponseT } from './debugger/read-memory-response.js'; 14 | export { ReadRegisterRequest, ReadRegisterRequestT } from './debugger/read-register-request.js'; 15 | export { ReadRegisterResponse, ReadRegisterResponseT } from './debugger/read-register-response.js'; 16 | export { RunRequest, RunRequestT } from './debugger/run-request.js'; 17 | export { State } from './debugger/state.js'; 18 | export { WriteMemoryRequest, WriteMemoryRequestT } from './debugger/write-memory-request.js'; 19 | export { WriteMemoryResponse, WriteMemoryResponseT } from './debugger/write-memory-response.js'; 20 | export { WriteRegisterRequest, WriteRegisterRequestT } from './debugger/write-register-request.js'; 21 | export { WriteRegisterResponse, WriteRegisterResponseT } from './debugger/write-register-response.js'; 22 | -------------------------------------------------------------------------------- /src/common/utils/lazy_object.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace utils 7 | { 8 | template 9 | concept CallableWithReturn = requires(const F f) { 10 | { f() } -> std::same_as; 11 | }; 12 | 13 | template 14 | requires(CallableWithReturn) 15 | class lazy_object 16 | { 17 | public: 18 | lazy_object(F accessor) 19 | : accessor_(std::move(accessor)) 20 | { 21 | } 22 | 23 | operator const T&() const 24 | { 25 | return this->get(); 26 | } 27 | 28 | operator T&() 29 | { 30 | return this->get(); 31 | } 32 | 33 | T& operator->() 34 | requires std::is_pointer_v 35 | { 36 | return this->get(); 37 | } 38 | 39 | const T& operator->() const 40 | requires std::is_pointer_v 41 | { 42 | return this->get(); 43 | } 44 | 45 | private: 46 | F accessor_{}; 47 | mutable std::optional object_{}; 48 | 49 | T& get() const 50 | { 51 | this->ensure_construction(); 52 | return *this->object_; 53 | } 54 | 55 | void ensure_construction() const 56 | { 57 | if (!this->object_.has_value()) 58 | { 59 | this->object_.emplace(this->accessor_()); 60 | } 61 | } 62 | }; 63 | 64 | template 65 | auto make_lazy(F accessor) 66 | { 67 | return lazy_object, F>(std::move(accessor)); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/windows-emulator/network/socket_factory.cpp: -------------------------------------------------------------------------------- 1 | #include "socket_factory.hpp" 2 | #include "socket_wrapper.hpp" 3 | 4 | namespace network 5 | { 6 | socket_factory::socket_factory() 7 | { 8 | initialize_wsa(); 9 | } 10 | 11 | std::unique_ptr socket_factory::create_socket(int af, int type, int protocol) 12 | { 13 | return std::make_unique(af, type, protocol); 14 | } 15 | 16 | int socket_factory::poll_sockets(const std::span entries) 17 | { 18 | std::vector poll_data{}; 19 | poll_data.reserve(entries.size()); 20 | 21 | for (const auto& entry : entries) 22 | { 23 | if (!entry.s) 24 | { 25 | throw std::runtime_error("Bad socket given!"); 26 | } 27 | 28 | const auto* wrapper = dynamic_cast(entry.s); 29 | if (!wrapper) 30 | { 31 | throw std::runtime_error("Socket was not created using the given factory"); 32 | } 33 | 34 | pollfd fd{}; 35 | fd.fd = wrapper->get().get_socket(); 36 | fd.events = entry.events; 37 | fd.revents = entry.revents; 38 | 39 | poll_data.push_back(fd); 40 | } 41 | 42 | const auto res = poll(poll_data.data(), static_cast(poll_data.size()), 0); 43 | 44 | for (size_t i = 0; i < poll_data.size() && i < entries.size(); ++i) 45 | { 46 | auto& entry = entries[i]; 47 | const auto& fd = poll_data[i]; 48 | 49 | entry.events = fd.events; 50 | entry.revents = fd.revents; 51 | } 52 | 53 | return res; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/fuzzing-engine/random_generator.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | namespace fuzzer 8 | { 9 | class random_generator 10 | { 11 | public: 12 | random_generator(); 13 | 14 | void fill(std::span data); 15 | void fill(void* data, size_t size); 16 | 17 | template 18 | requires(std::is_trivially_copyable_v) 19 | T get() 20 | { 21 | T value{}; 22 | this->fill(&value, sizeof(value)); 23 | return value; 24 | } 25 | 26 | template 27 | T get(const T& max) 28 | { 29 | return this->get() % max; 30 | } 31 | 32 | template 33 | T get(T min, T max) 34 | { 35 | if (max < min) 36 | { 37 | std::swap(max, min); 38 | } 39 | 40 | const auto diff = max - min; 41 | 42 | return (this->get() % diff) + min; 43 | } 44 | 45 | template 46 | T get_geometric() 47 | { 48 | T value{0}; 49 | 50 | while (this->get()) 51 | { 52 | ++value; 53 | } 54 | 55 | return value; 56 | } 57 | 58 | private: 59 | std::mt19937 rng_; 60 | std::uniform_int_distribution distribution_{}; 61 | 62 | std::mt19937::result_type generate_number(); 63 | }; 64 | 65 | template <> 66 | inline bool random_generator::get() 67 | { 68 | return (this->generate_number() & 1) != 0; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/backends/icicle-emulator/icicle-bridge/data/Ghidra/Processors/x86/data/languages/smx.sinc: -------------------------------------------------------------------------------- 1 | define pcodeop getsec_capabilities; 2 | define pcodeop getsec_enteraccs; 3 | define pcodeop getsec_exitac; 4 | define pcodeop getsec_senter; 5 | define pcodeop getsec_sexit; 6 | define pcodeop getsec_parameters_EAX; 7 | define pcodeop getsec_parameters_EBX; 8 | define pcodeop getsec_parameters_ECX; 9 | define pcodeop getsec_smctrl; 10 | define pcodeop getsec_wakeup; 11 | define pcodeop getsec_unknown; 12 | 13 | 14 | :GETSEC is vexMode=0 & byte=0x0f; byte=0x37 { 15 | 16 | if ( EAX != 0x0 ) goto ; 17 | EAX = 0; 18 | if ( EBX != 0x0 ) goto ; 19 | EAX = getsec_capabilities( EBX ); 20 | goto ; 21 | 22 | 23 | if ( EAX != 0x2 ) goto ; 24 | getsec_enteraccs( EBX, ECX ); 25 | goto ; 26 | 27 | 28 | if ( EAX != 0x3 ) goto ; 29 | @ifdef IA64 30 | getsec_exitac( RBX, EDX ); 31 | @else 32 | getsec_exitac( EBX, EDX ); 33 | @endif 34 | goto ; 35 | 36 | 37 | if ( EAX != 0x4 ) goto ; 38 | getsec_senter( EBX, ECX, EDX); 39 | goto ; 40 | 41 | 42 | if ( EAX != 0x5 ) goto ; 43 | getsec_sexit(); 44 | goto ; 45 | 46 | 47 | if ( EAX != 0x6 ) goto ; 48 | EAX = getsec_parameters_EAX( EBX ); 49 | ECX = getsec_parameters_ECX( EBX ); 50 | EBX = getsec_parameters_EBX( EBX ); 51 | goto ; 52 | 53 | 54 | if ( EAX != 0x7 ) goto ; 55 | getsec_smctrl(EBX); 56 | goto ; 57 | 58 | 59 | if ( EAX != 0x8 ) goto ; 60 | getsec_wakeup(); 61 | goto ; 62 | 63 | 64 | getsec_unknown(); 65 | 66 | 67 | } 68 | -------------------------------------------------------------------------------- /src/common/utils/concurrency.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace utils::concurrency 6 | { 7 | template 8 | class container 9 | { 10 | public: 11 | template 12 | R access(F&& accessor) const 13 | { 14 | std::lock_guard _{mutex_}; 15 | return accessor(object_); 16 | } 17 | 18 | template 19 | R access(F&& accessor) 20 | { 21 | std::lock_guard _{mutex_}; 22 | return accessor(object_); 23 | } 24 | 25 | template 26 | R access_with_lock(F&& accessor) const 27 | { 28 | std::unique_lock lock{mutex_}; 29 | return accessor(object_, lock); 30 | } 31 | 32 | template 33 | R access_with_lock(F&& accessor) 34 | { 35 | std::unique_lock lock{mutex_}; 36 | return accessor(object_, lock); 37 | } 38 | 39 | T& get_raw() 40 | { 41 | return object_; 42 | } 43 | const T& get_raw() const 44 | { 45 | return object_; 46 | } 47 | 48 | T copy() const 49 | { 50 | std::unique_lock lock{mutex_}; 51 | return object_; 52 | } 53 | 54 | std::unique_lock acquire_lock() 55 | { 56 | return std::unique_lock{mutex_}; 57 | } 58 | 59 | private: 60 | mutable MutexType mutex_{}; 61 | T object_{}; 62 | }; 63 | } 64 | -------------------------------------------------------------------------------- /src/backends/unicorn-emulator/unicorn_memory_regions.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "unicorn.hpp" 6 | 7 | namespace unicorn 8 | { 9 | class unicorn_memory_regions 10 | { 11 | public: 12 | unicorn_memory_regions(uc_engine* uc) 13 | { 14 | uce(uc_mem_regions(uc, &this->regions_, &this->count_)); 15 | } 16 | 17 | ~unicorn_memory_regions() 18 | { 19 | this->release(); 20 | } 21 | 22 | unicorn_memory_regions(const unicorn_memory_regions&) = delete; 23 | unicorn_memory_regions& operator=(const unicorn_memory_regions&) = delete; 24 | 25 | unicorn_memory_regions(unicorn_memory_regions&& obj) noexcept 26 | { 27 | this->operator=(std::move(obj)); 28 | } 29 | 30 | unicorn_memory_regions& operator=(unicorn_memory_regions&& obj) noexcept 31 | { 32 | if (this != &obj) 33 | { 34 | this->release(); 35 | 36 | this->count_ = obj.count_; 37 | this->regions_ = obj.regions_; 38 | 39 | obj.count_ = {}; 40 | obj.regions_ = nullptr; 41 | } 42 | 43 | return *this; 44 | } 45 | 46 | std::span get_span() const 47 | { 48 | return {this->regions_, this->count_}; 49 | } 50 | 51 | private: 52 | uint32_t count_{}; 53 | uc_mem_region* regions_{}; 54 | 55 | void release() 56 | { 57 | if (this->regions_) 58 | { 59 | uc_free(regions_); 60 | } 61 | 62 | this->count_ = {}; 63 | this->regions_ = nullptr; 64 | } 65 | }; 66 | } 67 | -------------------------------------------------------------------------------- /src/common/utils/path_key.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "string.hpp" 4 | #include 5 | 6 | namespace utils 7 | { 8 | class path_key 9 | { 10 | public: 11 | path_key() = default; 12 | path_key(const std::filesystem::path& p) 13 | : path_(canonicalize_path(p)) 14 | { 15 | } 16 | 17 | path_key(const path_key&) = default; 18 | path_key(path_key&&) noexcept = default; 19 | 20 | path_key& operator=(const path_key&) = default; 21 | path_key& operator=(path_key&&) noexcept = default; 22 | 23 | ~path_key() = default; 24 | 25 | const std::filesystem::path& get() const 26 | { 27 | return this->path_; 28 | } 29 | 30 | bool operator==(const path_key& other) const 31 | { 32 | return this->get() == other.get(); 33 | } 34 | 35 | bool operator!=(const path_key& other) const 36 | { 37 | return !this->operator==(other); 38 | } 39 | 40 | static std::filesystem::path canonicalize_path(const std::filesystem::path& key) 41 | { 42 | auto key_string = key.u16string(); 43 | std::ranges::replace(key_string, u'\\', '/'); 44 | 45 | auto path = std::filesystem::path(key_string).lexically_normal().wstring(); 46 | return utils::string::to_lower_consume(path); 47 | } 48 | 49 | private: 50 | std::filesystem::path path_{}; 51 | }; 52 | } 53 | 54 | namespace std 55 | { 56 | template <> 57 | struct hash 58 | { 59 | size_t operator()(const utils::path_key& p) const noexcept 60 | { 61 | return hash()(p.get().native()); 62 | } 63 | }; 64 | } 65 | -------------------------------------------------------------------------------- /page/src/components/ui/popover.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import * as PopoverPrimitive from "@radix-ui/react-popover"; 3 | 4 | import { cn } from "@/lib/utils"; 5 | 6 | function Popover({ 7 | ...props 8 | }: React.ComponentProps) { 9 | return ; 10 | } 11 | 12 | function PopoverTrigger({ 13 | ...props 14 | }: React.ComponentProps) { 15 | return ; 16 | } 17 | 18 | function PopoverContent({ 19 | className, 20 | align = "center", 21 | sideOffset = 4, 22 | ...props 23 | }: React.ComponentProps) { 24 | return ( 25 | 26 | 36 | 37 | ); 38 | } 39 | 40 | function PopoverAnchor({ 41 | ...props 42 | }: React.ComponentProps) { 43 | return ; 44 | } 45 | 46 | export { Popover, PopoverTrigger, PopoverContent, PopoverAnchor }; 47 | -------------------------------------------------------------------------------- /page/src/components/ui/badge.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import { Slot } from "@radix-ui/react-slot"; 3 | import { cva, type VariantProps } from "class-variance-authority"; 4 | 5 | import { cn } from "@/lib/utils"; 6 | 7 | const badgeVariants = cva( 8 | "inline-flex items-center justify-center rounded-md border px-2 py-0.5 text-xs font-medium w-fit whitespace-nowrap shrink-0 [&>svg]:size-3 gap-1 [&>svg]:pointer-events-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive transition-[color,box-shadow] overflow-hidden", 9 | { 10 | variants: { 11 | variant: { 12 | default: 13 | "border-transparent bg-primary text-primary-foreground [a&]:hover:bg-primary/90", 14 | secondary: 15 | "border-transparent bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90", 16 | destructive: 17 | "border-transparent bg-destructive text-white [a&]:hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60", 18 | outline: 19 | "text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground", 20 | }, 21 | }, 22 | defaultVariants: { 23 | variant: "default", 24 | }, 25 | }, 26 | ); 27 | 28 | function Badge({ 29 | className, 30 | variant, 31 | asChild = false, 32 | ...props 33 | }: React.ComponentProps<"span"> & 34 | VariantProps & { asChild?: boolean }) { 35 | const Comp = asChild ? Slot : "span"; 36 | 37 | return ( 38 | 43 | ); 44 | } 45 | 46 | export { Badge, badgeVariants }; 47 | -------------------------------------------------------------------------------- /src/emulator/address_utils.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | template 5 | T* offset_pointer(void* data, const size_t offset) 6 | { 7 | return reinterpret_cast(static_cast(data) + offset); 8 | } 9 | 10 | template 11 | const T* offset_pointer(const void* data, const size_t offset) 12 | { 13 | return reinterpret_cast(static_cast(data) + offset); 14 | } 15 | 16 | constexpr bool is_within_start_and_end(const uint64_t value, const uint64_t start, const uint64_t end) 17 | { 18 | return value >= start && value < end; 19 | } 20 | 21 | constexpr bool is_within_start_and_length(const uint64_t value, const uint64_t start, const uint64_t length) 22 | { 23 | return is_within_start_and_end(value, start, start + length); 24 | } 25 | 26 | constexpr bool regions_intersect(const uint64_t start1, const uint64_t end1, const uint64_t start2, const uint64_t end2) 27 | { 28 | return start1 < end2 && start2 < end1; 29 | } 30 | 31 | constexpr bool regions_with_length_intersect(const uint64_t start1, const uint64_t length1, const uint64_t start2, const uint64_t length2) 32 | { 33 | return regions_intersect(start1, start1 + length1, start2, start2 + length2); 34 | } 35 | 36 | constexpr uint64_t align_down(const uint64_t value, const uint64_t alignment) 37 | { 38 | return value & ~(alignment - 1); 39 | } 40 | 41 | constexpr uint64_t align_up(const uint64_t value, const uint64_t alignment) 42 | { 43 | return align_down(value + (alignment - 1), alignment); 44 | } 45 | 46 | constexpr uint64_t page_align_down(const uint64_t value, const uint64_t page_size = 0x1000) 47 | { 48 | return align_down(value, page_size); 49 | } 50 | 51 | constexpr uint64_t page_align_up(const uint64_t value, const uint64_t page_size = 0x1000) 52 | { 53 | return align_up(value, page_size); 54 | } 55 | -------------------------------------------------------------------------------- /page/src/components/ui/scroll-area.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import * as ScrollAreaPrimitive from "@radix-ui/react-scroll-area"; 3 | 4 | import { cn } from "@/lib/utils"; 5 | 6 | function ScrollArea({ 7 | className, 8 | children, 9 | ...props 10 | }: React.ComponentProps) { 11 | return ( 12 | 17 | 21 | {children} 22 | 23 | 24 | 25 | 26 | ); 27 | } 28 | 29 | function ScrollBar({ 30 | className, 31 | orientation = "vertical", 32 | ...props 33 | }: React.ComponentProps) { 34 | return ( 35 | 48 | 52 | 53 | ); 54 | } 55 | 56 | export { ScrollArea, ScrollBar }; 57 | -------------------------------------------------------------------------------- /src/backends/unicorn-emulator/unicorn_hook.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "unicorn.hpp" 4 | 5 | namespace unicorn 6 | { 7 | class unicorn_hook 8 | { 9 | public: 10 | unicorn_hook() = default; 11 | 12 | unicorn_hook(uc_engine* uc) 13 | : unicorn_hook(uc, {}) 14 | { 15 | } 16 | 17 | unicorn_hook(uc_engine* uc, const uc_hook hook) 18 | : uc_(uc), 19 | hook_(hook) 20 | { 21 | } 22 | 23 | ~unicorn_hook() 24 | { 25 | release(); 26 | } 27 | 28 | unicorn_hook(const unicorn_hook&) = delete; 29 | unicorn_hook& operator=(const unicorn_hook&) = delete; 30 | 31 | unicorn_hook(unicorn_hook&& obj) noexcept 32 | { 33 | this->operator=(std::move(obj)); 34 | } 35 | 36 | uc_hook* make_reference() 37 | { 38 | if (!this->uc_) 39 | { 40 | throw std::runtime_error("Cannot make reference on default constructed hook"); 41 | } 42 | 43 | this->release(); 44 | return &this->hook_; 45 | } 46 | 47 | unicorn_hook& operator=(unicorn_hook&& obj) noexcept 48 | { 49 | if (this != &obj) 50 | { 51 | this->release(); 52 | 53 | this->uc_ = obj.uc_; 54 | this->hook_ = obj.hook_; 55 | 56 | obj.hook_ = {}; 57 | obj.uc_ = {}; 58 | } 59 | 60 | return *this; 61 | } 62 | 63 | void release() 64 | { 65 | if (this->hook_ && this->uc_) 66 | { 67 | uc_hook_del(this->uc_, this->hook_); 68 | this->hook_ = {}; 69 | } 70 | } 71 | 72 | private: 73 | uc_engine* uc_{}; 74 | uc_hook hook_{}; 75 | }; 76 | } 77 | -------------------------------------------------------------------------------- /page/vite.config.ts: -------------------------------------------------------------------------------- 1 | import path from "path"; 2 | import tailwindcss from "@tailwindcss/vite"; 3 | import { defineConfig } from "vite"; 4 | import { VitePWA } from "vite-plugin-pwa"; 5 | import react from "@vitejs/plugin-react"; 6 | import { RuntimeCaching } from "workbox-build"; 7 | 8 | const mb = 1024 ** 2; 9 | 10 | function generateExternalCache( 11 | pattern: string | RegExp, 12 | name: string, 13 | ): RuntimeCaching { 14 | return { 15 | urlPattern: pattern, 16 | handler: "CacheFirst", 17 | options: { 18 | cacheName: name, 19 | expiration: { 20 | maxEntries: 10, 21 | maxAgeSeconds: 60 * 60 * 24 * 365, // <== 365 days 22 | }, 23 | cacheableResponse: { 24 | statuses: [0, 200], 25 | }, 26 | }, 27 | }; 28 | } 29 | 30 | // https://vite.dev/config/ 31 | export default defineConfig({ 32 | plugins: [ 33 | react(), 34 | tailwindcss(), 35 | VitePWA({ 36 | registerType: "autoUpdate", 37 | manifest: { 38 | theme_color: "#0279E8", 39 | background_color: "#141416", 40 | }, 41 | workbox: { 42 | maximumFileSizeToCacheInBytes: 100 * mb, 43 | cleanupOutdatedCaches: true, 44 | globPatterns: ["**/*.{js,css,html,woff,woff2,wasm}"], 45 | globIgnores: ["root.zip"], 46 | navigateFallbackDenylist: [/^\/root\.zip$/], 47 | runtimeCaching: [ 48 | generateExternalCache( 49 | /^https:\/\/momo5502\.com\/.*/i, 50 | "momo5502-cache", 51 | ), 52 | generateExternalCache( 53 | /^https:\/\/img\.youtube\.com\/.*/i, 54 | "youtube-img-cache", 55 | ), 56 | ], 57 | }, 58 | }), 59 | ], 60 | resolve: { 61 | alias: { 62 | "@": path.resolve(__dirname, "./src"), 63 | }, 64 | }, 65 | define: { 66 | "import.meta.env.VITE_BUILD_TIME": JSON.stringify(Date.now()), 67 | }, 68 | }); 69 | -------------------------------------------------------------------------------- /page/src/components/theme-provider.tsx: -------------------------------------------------------------------------------- 1 | import { createContext, useContext, useEffect, useState } from "react"; 2 | 3 | type Theme = "dark" | "light" | "system"; 4 | 5 | type ThemeProviderProps = { 6 | children: React.ReactNode; 7 | defaultTheme?: Theme; 8 | storageKey?: string; 9 | }; 10 | 11 | type ThemeProviderState = { 12 | theme: Theme; 13 | setTheme: (theme: Theme) => void; 14 | }; 15 | 16 | const initialState: ThemeProviderState = { 17 | theme: "system", 18 | setTheme: () => null, 19 | }; 20 | 21 | const ThemeProviderContext = createContext(initialState); 22 | 23 | export function ThemeProvider({ 24 | children, 25 | defaultTheme = "system", 26 | storageKey = "vite-ui-theme", 27 | ...props 28 | }: ThemeProviderProps) { 29 | const [theme, setTheme] = useState( 30 | () => (localStorage.getItem(storageKey) as Theme) || defaultTheme, 31 | ); 32 | 33 | useEffect(() => { 34 | const root = window.document.documentElement; 35 | 36 | root.classList.remove("light", "dark"); 37 | 38 | if (theme === "system") { 39 | const systemTheme = window.matchMedia("(prefers-color-scheme: dark)") 40 | .matches 41 | ? "dark" 42 | : "light"; 43 | 44 | root.classList.add(systemTheme); 45 | return; 46 | } 47 | 48 | root.classList.add(theme); 49 | }, [theme]); 50 | 51 | const value = { 52 | theme, 53 | setTheme: (theme: Theme) => { 54 | localStorage.setItem(storageKey, theme); 55 | setTheme(theme); 56 | }, 57 | }; 58 | 59 | return ( 60 | 61 | {children} 62 | 63 | ); 64 | } 65 | 66 | export const useTheme = () => { 67 | const context = useContext(ThemeProviderContext); 68 | 69 | if (context === undefined) 70 | throw new Error("useTheme must be used within a ThemeProvider"); 71 | 72 | return context; 73 | }; 74 | -------------------------------------------------------------------------------- /src/debugger/events.fbs: -------------------------------------------------------------------------------- 1 | namespace Debugger; 2 | 3 | table GetStateRequest {} 4 | 5 | enum State : uint32 { 6 | None = 0, 7 | Running, 8 | Paused, 9 | } 10 | 11 | table GetStateResponse { 12 | state: State; 13 | } 14 | 15 | table PauseRequest {} 16 | 17 | table RunRequest { 18 | single_step: bool; 19 | } 20 | 21 | table WriteMemoryRequest { 22 | address: uint64; 23 | data: [ubyte]; 24 | } 25 | 26 | table WriteMemoryResponse { 27 | address: uint64; 28 | size: uint32; 29 | success: bool; 30 | } 31 | 32 | table ReadMemoryRequest { 33 | address: uint64; 34 | size: uint32; 35 | } 36 | 37 | table ReadMemoryResponse { 38 | address: uint64; 39 | data: [ubyte]; 40 | } 41 | 42 | table WriteRegisterRequest { 43 | register: uint32; 44 | data: [ubyte]; 45 | } 46 | 47 | table WriteRegisterResponse { 48 | register: uint32; 49 | size: uint32; 50 | success: bool; 51 | } 52 | 53 | table ReadRegisterRequest { 54 | register: uint32; 55 | } 56 | 57 | table ReadRegisterResponse { 58 | register: uint32; 59 | data: [ubyte]; 60 | } 61 | 62 | table ApplicationExit { 63 | exit_status: uint32 = null; 64 | } 65 | 66 | table EmulationStatus { 67 | active_threads: uint32; 68 | reserved_memory: uint64; 69 | committed_memory: uint64; 70 | executed_instructions: uint64; 71 | } 72 | 73 | union Event { 74 | PauseRequest, 75 | RunRequest, 76 | GetStateRequest, 77 | GetStateResponse, 78 | WriteMemoryRequest, 79 | WriteMemoryResponse, 80 | ReadMemoryRequest, 81 | ReadMemoryResponse, 82 | WriteRegisterRequest, 83 | WriteRegisterResponse, 84 | ReadRegisterRequest, 85 | ReadRegisterResponse, 86 | ApplicationExit, 87 | EmulationStatus, 88 | } 89 | 90 | table DebugEvent { 91 | event: Event; 92 | } 93 | 94 | root_type DebugEvent; 95 | -------------------------------------------------------------------------------- /page/src/fb/debugger/pause-request.ts: -------------------------------------------------------------------------------- 1 | // automatically generated by the FlatBuffers compiler, do not modify 2 | 3 | /* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */ 4 | 5 | import * as flatbuffers from 'flatbuffers'; 6 | 7 | 8 | 9 | export class PauseRequest implements flatbuffers.IUnpackableObject { 10 | bb: flatbuffers.ByteBuffer|null = null; 11 | bb_pos = 0; 12 | __init(i:number, bb:flatbuffers.ByteBuffer):PauseRequest { 13 | this.bb_pos = i; 14 | this.bb = bb; 15 | return this; 16 | } 17 | 18 | static getRootAsPauseRequest(bb:flatbuffers.ByteBuffer, obj?:PauseRequest):PauseRequest { 19 | return (obj || new PauseRequest()).__init(bb.readInt32(bb.position()) + bb.position(), bb); 20 | } 21 | 22 | static getSizePrefixedRootAsPauseRequest(bb:flatbuffers.ByteBuffer, obj?:PauseRequest):PauseRequest { 23 | bb.setPosition(bb.position() + flatbuffers.SIZE_PREFIX_LENGTH); 24 | return (obj || new PauseRequest()).__init(bb.readInt32(bb.position()) + bb.position(), bb); 25 | } 26 | 27 | static startPauseRequest(builder:flatbuffers.Builder) { 28 | builder.startObject(0); 29 | } 30 | 31 | static endPauseRequest(builder:flatbuffers.Builder):flatbuffers.Offset { 32 | const offset = builder.endObject(); 33 | return offset; 34 | } 35 | 36 | static createPauseRequest(builder:flatbuffers.Builder):flatbuffers.Offset { 37 | PauseRequest.startPauseRequest(builder); 38 | return PauseRequest.endPauseRequest(builder); 39 | } 40 | 41 | unpack(): PauseRequestT { 42 | return new PauseRequestT(); 43 | } 44 | 45 | 46 | unpackTo(_o: PauseRequestT): void {} 47 | } 48 | 49 | export class PauseRequestT implements flatbuffers.IGeneratedObject { 50 | constructor(){} 51 | 52 | 53 | pack(builder:flatbuffers.Builder): flatbuffers.Offset { 54 | return PauseRequest.createPauseRequest(builder); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/emulator/serialization_helper.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "serialization.hpp" 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | namespace utils 10 | { 11 | inline void serialize(buffer_serializer& buffer, const std::chrono::steady_clock::time_point& tp) 12 | { 13 | buffer.write(tp.time_since_epoch().count()); 14 | } 15 | 16 | inline void deserialize(buffer_deserializer& buffer, std::chrono::steady_clock::time_point& tp) 17 | { 18 | using time_point = std::chrono::steady_clock::time_point; 19 | using duration = time_point::duration; 20 | 21 | const auto count = buffer.read(); 22 | tp = time_point{duration{count}}; 23 | } 24 | 25 | inline void serialize(buffer_serializer& buffer, const std::chrono::system_clock::time_point& tp) 26 | { 27 | buffer.write(tp.time_since_epoch().count()); 28 | } 29 | 30 | inline void deserialize(buffer_deserializer& buffer, std::chrono::system_clock::time_point& tp) 31 | { 32 | using time_point = std::chrono::system_clock::time_point; 33 | using duration = time_point::duration; 34 | 35 | const auto count = buffer.read(); 36 | tp = time_point{duration{count}}; 37 | } 38 | 39 | inline void serialize(buffer_serializer& buffer, const std::filesystem::path& path) 40 | { 41 | buffer.write_string(path.u16string()); 42 | } 43 | 44 | inline void deserialize(buffer_deserializer& buffer, std::filesystem::path& path) 45 | { 46 | path = buffer.read_string(); 47 | } 48 | 49 | inline void serialize(buffer_serializer& buffer, const path_key& path) 50 | { 51 | buffer.write(path.get()); 52 | } 53 | 54 | inline void deserialize(buffer_deserializer& buffer, path_key& path) 55 | { 56 | path = buffer.read(); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/debugger/message_transmitter.cpp: -------------------------------------------------------------------------------- 1 | #include "message_transmitter.hpp" 2 | #include 3 | 4 | #include 5 | 6 | #include 7 | #ifdef OS_EMSCRIPTEN 8 | #include 9 | #endif 10 | 11 | using namespace std::literals; 12 | 13 | namespace debugger 14 | { 15 | void send_message(const std::string& message) 16 | { 17 | #ifdef OS_EMSCRIPTEN 18 | // clang-format off 19 | EM_ASM_({ 20 | handleMessage(UTF8ToString($0)); 21 | }, message.c_str()); 22 | // clang-format on 23 | #else 24 | (void)message; 25 | #endif 26 | } 27 | 28 | std::string receive_message() 29 | { 30 | #ifdef OS_EMSCRIPTEN 31 | // clang-format off 32 | auto* ptr = EM_ASM_PTR({ 33 | var message = getMessageFromQueue(); 34 | if (!message || message.length == 0) 35 | { 36 | return 0; 37 | } 38 | 39 | const length = lengthBytesUTF8(message) + 1; 40 | const buffer = _malloc(length); 41 | stringToUTF8(message, buffer, length); 42 | return buffer; 43 | }); 44 | // clang-format on 45 | 46 | if (!ptr) 47 | { 48 | return {}; 49 | } 50 | 51 | const auto _ = utils::finally([&] { 52 | free(ptr); // 53 | }); 54 | 55 | return {reinterpret_cast(ptr)}; 56 | #else 57 | return {}; 58 | #endif 59 | } 60 | 61 | void suspend_execution(const std::chrono::milliseconds ms) 62 | { 63 | #ifdef OS_EMSCRIPTEN 64 | emscripten_sleep(static_cast(ms.count())); 65 | #else 66 | if (ms > 0ms) 67 | { 68 | std::this_thread::sleep_for(ms); 69 | } 70 | else 71 | { 72 | std::this_thread::yield(); 73 | } 74 | #endif 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/gdb-stub/async_handler.cpp: -------------------------------------------------------------------------------- 1 | #include "async_handler.hpp" 2 | #include 3 | #include 4 | 5 | using namespace std::chrono_literals; 6 | 7 | namespace gdb_stub 8 | { 9 | async_handler::async_handler(handler_function h) 10 | : handler_(std::move(h)) 11 | { 12 | this->stop_ = false; 13 | this->runner_ = std::thread([this] { 14 | this->work(); // 15 | }); 16 | } 17 | 18 | async_handler::~async_handler() 19 | { 20 | this->stop_ = true; 21 | this->run_ = false; 22 | 23 | if (this->runner_.joinable()) 24 | { 25 | this->runner_.join(); 26 | } 27 | } 28 | 29 | void async_handler::pause() 30 | { 31 | this->run_ = false; 32 | 33 | while (this->is_running_ && !this->stop_) 34 | { 35 | std::this_thread::sleep_for(1ms); 36 | } 37 | } 38 | 39 | void async_handler::run() 40 | { 41 | if (this->stop_) 42 | { 43 | return; 44 | } 45 | 46 | this->run_ = true; 47 | 48 | while (!this->is_running_ && !this->stop_) 49 | { 50 | std::this_thread::sleep_for(1ms); 51 | } 52 | } 53 | 54 | bool async_handler::is_running() const 55 | { 56 | return this->is_running_; 57 | } 58 | 59 | void async_handler::work() 60 | { 61 | while (true) 62 | { 63 | while (!this->run_ && !this->stop_) 64 | { 65 | this->is_running_ = false; 66 | std::this_thread::sleep_for(10ms); 67 | } 68 | 69 | if (this->stop_) 70 | { 71 | break; 72 | } 73 | 74 | const auto _ = utils::finally([this] { 75 | this->is_running_ = false; // 76 | }); 77 | 78 | this->is_running_ = true; 79 | this->handler_(this->run_); 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/gdb-stub/gdb_stub.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | namespace gdb_stub 6 | { 7 | enum class action : uint8_t 8 | { 9 | none, 10 | resume, 11 | shutdown, 12 | }; 13 | 14 | enum class breakpoint_type : uint8_t 15 | { 16 | software = 0, 17 | hardware_exec = 1, 18 | hardware_write = 2, 19 | hardware_read = 3, 20 | hardware_read_write = 4, 21 | END, 22 | }; 23 | 24 | struct debugging_handler 25 | { 26 | virtual ~debugging_handler() = default; 27 | 28 | virtual action run() = 0; 29 | virtual action singlestep() = 0; 30 | 31 | virtual size_t get_register_count() = 0; 32 | virtual size_t get_max_register_size() = 0; 33 | 34 | virtual size_t read_register(size_t reg, void* data, size_t max_length) = 0; 35 | virtual size_t write_register(size_t reg, const void* data, size_t size) = 0; 36 | 37 | virtual bool read_memory(uint64_t address, void* data, size_t length) = 0; 38 | virtual bool write_memory(uint64_t address, const void* data, size_t length) = 0; 39 | 40 | virtual bool set_breakpoint(breakpoint_type type, uint64_t address, size_t size) = 0; 41 | virtual bool delete_breakpoint(breakpoint_type type, uint64_t address, size_t size) = 0; 42 | 43 | virtual void on_interrupt() = 0; 44 | 45 | virtual std::string get_target_description(std::string_view file) = 0; 46 | 47 | virtual bool switch_to_thread(uint32_t thread_id) = 0; 48 | 49 | virtual uint32_t get_current_thread_id() = 0; 50 | virtual std::vector get_thread_ids() = 0; 51 | 52 | virtual std::optional get_exit_code() = 0; 53 | 54 | virtual bool should_stop() 55 | { 56 | return false; 57 | } 58 | }; 59 | 60 | bool run_gdb_stub(const network::address& bind_address, debugging_handler& handler); 61 | } 62 | -------------------------------------------------------------------------------- /src/backends/icicle-emulator/icicle-bridge/data/Ghidra/Processors/x86/data/languages/x86-64.dwarf: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /page/src/fb/debugger/get-state-request.ts: -------------------------------------------------------------------------------- 1 | // automatically generated by the FlatBuffers compiler, do not modify 2 | 3 | /* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */ 4 | 5 | import * as flatbuffers from 'flatbuffers'; 6 | 7 | 8 | 9 | export class GetStateRequest implements flatbuffers.IUnpackableObject { 10 | bb: flatbuffers.ByteBuffer|null = null; 11 | bb_pos = 0; 12 | __init(i:number, bb:flatbuffers.ByteBuffer):GetStateRequest { 13 | this.bb_pos = i; 14 | this.bb = bb; 15 | return this; 16 | } 17 | 18 | static getRootAsGetStateRequest(bb:flatbuffers.ByteBuffer, obj?:GetStateRequest):GetStateRequest { 19 | return (obj || new GetStateRequest()).__init(bb.readInt32(bb.position()) + bb.position(), bb); 20 | } 21 | 22 | static getSizePrefixedRootAsGetStateRequest(bb:flatbuffers.ByteBuffer, obj?:GetStateRequest):GetStateRequest { 23 | bb.setPosition(bb.position() + flatbuffers.SIZE_PREFIX_LENGTH); 24 | return (obj || new GetStateRequest()).__init(bb.readInt32(bb.position()) + bb.position(), bb); 25 | } 26 | 27 | static startGetStateRequest(builder:flatbuffers.Builder) { 28 | builder.startObject(0); 29 | } 30 | 31 | static endGetStateRequest(builder:flatbuffers.Builder):flatbuffers.Offset { 32 | const offset = builder.endObject(); 33 | return offset; 34 | } 35 | 36 | static createGetStateRequest(builder:flatbuffers.Builder):flatbuffers.Offset { 37 | GetStateRequest.startGetStateRequest(builder); 38 | return GetStateRequest.endGetStateRequest(builder); 39 | } 40 | 41 | unpack(): GetStateRequestT { 42 | return new GetStateRequestT(); 43 | } 44 | 45 | 46 | unpackTo(_o: GetStateRequestT): void {} 47 | } 48 | 49 | export class GetStateRequestT implements flatbuffers.IGeneratedObject { 50 | constructor(){} 51 | 52 | 53 | pack(builder:flatbuffers.Builder): flatbuffers.Offset { 54 | return GetStateRequest.createGetStateRequest(builder); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/analyzer/tenet_tracer.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | constexpr std::array, 16> GPRs_TO_TRACE = { 8 | { 9 | {x86_register::rax, "rax"}, 10 | {x86_register::rbx, "rbx"}, 11 | {x86_register::rcx, "rcx"}, 12 | {x86_register::rdx, "rdx"}, 13 | {x86_register::rsi, "rsi"}, 14 | {x86_register::rdi, "rdi"}, 15 | {x86_register::rbp, "rbp"}, 16 | {x86_register::rsp, "rsp"}, 17 | {x86_register::r8, "r8"}, 18 | {x86_register::r9, "r9"}, 19 | {x86_register::r10, "r10"}, 20 | {x86_register::r11, "r11"}, 21 | {x86_register::r12, "r12"}, 22 | {x86_register::r13, "r13"}, 23 | {x86_register::r14, "r14"}, 24 | {x86_register::r15, "r15"}, 25 | }, 26 | }; 27 | 28 | class tenet_tracer 29 | { 30 | public: 31 | tenet_tracer(windows_emulator& win_emu, const std::filesystem::path& log_filename); 32 | ~tenet_tracer(); 33 | 34 | tenet_tracer(tenet_tracer&) = delete; 35 | tenet_tracer(const tenet_tracer&) = delete; 36 | tenet_tracer& operator=(tenet_tracer&) = delete; 37 | tenet_tracer& operator=(const tenet_tracer&) = delete; 38 | 39 | private: 40 | void filter_and_write_buffer(); 41 | void log_memory_read(uint64_t address, const void* data, size_t size); 42 | void log_memory_write(uint64_t address, const void* data, size_t size); 43 | void process_instruction(uint64_t address); 44 | 45 | windows_emulator& win_emu_; 46 | std::ofstream log_file_; 47 | 48 | std::vector raw_log_buffer_; 49 | std::array previous_registers_{}; 50 | bool is_first_instruction_ = true; 51 | 52 | std::stringstream mem_read_log_; 53 | std::stringstream mem_write_log_; 54 | 55 | scoped_hook read_hook_; 56 | scoped_hook write_hook_; 57 | scoped_hook execute_hook_; 58 | }; 59 | -------------------------------------------------------------------------------- /page/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 13 | 14 | Sogen - Windows User Space Emulator 15 | 16 | 17 | 18 | 23 | 24 | 25 | 30 | 31 | 32 | 37 | 42 | 43 | 48 | 53 | 54 | 55 |
56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /src/common/utils/nt_handle.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifdef WIN32 4 | 5 | #include "win.hpp" 6 | 7 | #include 8 | 9 | namespace utils::nt 10 | { 11 | using HandleFunction = HANDLE(); 12 | 13 | inline HANDLE null_handle() 14 | { 15 | return nullptr; 16 | } 17 | 18 | inline HANDLE invalid_handle() 19 | { 20 | return INVALID_HANDLE_VALUE; 21 | } 22 | 23 | template 24 | class handle 25 | { 26 | public: 27 | handle() = default; 28 | 29 | handle(const HANDLE h) 30 | : handle_(h) 31 | { 32 | } 33 | 34 | ~handle() 35 | { 36 | if (*this) 37 | { 38 | CloseHandle(this->handle_); 39 | this->handle_ = InvalidHandleFunction(); 40 | } 41 | } 42 | 43 | handle(const handle&) = delete; 44 | handle& operator=(const handle&) = delete; 45 | 46 | handle(handle&& obj) noexcept 47 | : handle() 48 | { 49 | this->operator=(std::move(obj)); 50 | } 51 | 52 | handle& operator=(handle&& obj) noexcept 53 | { 54 | if (this != &obj) 55 | { 56 | this->~handle(); 57 | this->handle_ = obj.handle_; 58 | obj.handle_ = InvalidHandleFunction(); 59 | } 60 | 61 | return *this; 62 | } 63 | 64 | handle& operator=(HANDLE h) noexcept 65 | { 66 | this->~handle(); 67 | this->handle_ = h; 68 | 69 | return *this; 70 | } 71 | 72 | [[nodiscard]] operator bool() const 73 | { 74 | return this->handle_ != InvalidHandleFunction(); 75 | } 76 | 77 | [[nodiscard]] operator HANDLE() const 78 | { 79 | return this->handle_; 80 | } 81 | 82 | private: 83 | HANDLE handle_{InvalidHandleFunction()}; 84 | }; 85 | } 86 | 87 | #endif 88 | -------------------------------------------------------------------------------- /src/emulator/scoped_hook.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "emulator.hpp" 3 | 4 | class scoped_hook 5 | { 6 | public: 7 | scoped_hook() = default; 8 | 9 | scoped_hook(emulator& emu) 10 | : emu_(&emu) 11 | { 12 | } 13 | 14 | scoped_hook(emulator& emu, emulator_hook* hook) 15 | : scoped_hook(emu, std::vector{hook}) 16 | { 17 | } 18 | 19 | scoped_hook(emulator& emu, std::vector hooks) 20 | : emu_(&emu), 21 | hooks_(std::move(hooks)) 22 | { 23 | } 24 | 25 | ~scoped_hook() 26 | { 27 | this->remove(); 28 | } 29 | 30 | scoped_hook(const scoped_hook&) = delete; 31 | scoped_hook& operator=(const scoped_hook&) = delete; 32 | 33 | scoped_hook(scoped_hook&& obj) noexcept 34 | { 35 | this->operator=(std::move(obj)); 36 | } 37 | 38 | scoped_hook& operator=(scoped_hook&& obj) noexcept 39 | { 40 | if (this != &obj) 41 | { 42 | this->remove(); 43 | this->emu_ = obj.emu_; 44 | this->hooks_ = std::move(obj.hooks_); 45 | 46 | obj.hooks_ = {}; 47 | } 48 | 49 | return *this; 50 | } 51 | 52 | scoped_hook& operator=(emulator_hook* hook) 53 | { 54 | this->replace({hook}); 55 | return *this; 56 | } 57 | 58 | void replace(std::vector hooks) 59 | { 60 | if (!this->emu_) 61 | { 62 | throw std::runtime_error("Invalid scoped hook"); 63 | } 64 | 65 | this->remove(); 66 | this->hooks_ = std::move(hooks); 67 | } 68 | 69 | void remove() 70 | { 71 | auto hooks = std::move(this->hooks_); 72 | this->hooks_ = {}; 73 | 74 | for (auto* hook : hooks) 75 | { 76 | try 77 | { 78 | this->emu_->delete_hook(hook); 79 | } 80 | catch (...) 81 | { 82 | } 83 | } 84 | } 85 | 86 | private: 87 | emulator* emu_{}; 88 | std::vector hooks_{}; 89 | }; 90 | -------------------------------------------------------------------------------- /src/common/platform/port.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // NOLINTBEGIN(modernize-use-using,cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) 4 | 5 | #define LPC_REQUEST 1 6 | #define LPC_REPLY 2 7 | #define LPC_DATAGRAM 3 8 | #define LPC_LOST_REPLY 4 9 | #define LPC_PORT_CLOSED 5 10 | #define LPC_CLIENT_DIED 6 11 | #define LPC_EXCEPTION 7 12 | #define LPC_DEBUG_EVENT 8 13 | #define LPC_ERROR_EVENT 9 14 | #define LPC_CONNECTION_REQUEST 10 15 | #define LPC_NO_IMPERSONATE 0x4000 16 | #define LPC_KERNELMODE_MESSAGE 0x8000 17 | 18 | #define LpcpGetMessageType(x) ((x)->u2.s2.Type & ~LPC_KERNELMODE_MESSAGE) 19 | 20 | struct PORT_MESSAGE64 21 | { 22 | union 23 | { 24 | struct 25 | { 26 | CSHORT DataLength; 27 | CSHORT TotalLength; 28 | } s1; 29 | 30 | ULONG Length; 31 | } u1; 32 | 33 | union 34 | { 35 | struct 36 | { 37 | CSHORT Type; 38 | CSHORT DataInfoOffset; 39 | } s2; 40 | 41 | ULONG ZeroInit; 42 | } u2; 43 | 44 | union 45 | { 46 | CLIENT_ID64 ClientId; 47 | double DoNotUseThisField; 48 | }; 49 | 50 | ULONG MessageId; 51 | 52 | union 53 | { 54 | EmulatorTraits::SIZE_T ClientViewSize; // only valid for LPC_CONNECTION_REQUEST messages 55 | ULONG CallbackId; // only valid for LPC_REQUEST messages 56 | }; 57 | }; 58 | 59 | struct ALPC_MESSAGE_ATTRIBUTES 60 | { 61 | ULONG AllocatedAttributes; 62 | ULONG ValidAttributes; 63 | }; 64 | 65 | template 66 | struct PORT_DATA_ENTRY 67 | { 68 | typename Traits::PVOID Base; 69 | ULONG Size; 70 | }; 71 | 72 | template 73 | struct ALPC_SECURITY_ATTR 74 | { 75 | ULONG Flags; 76 | typename Traits::PVOID SecurityQos; 77 | typename Traits::HANDLE ContextHandle; 78 | }; 79 | 80 | // NOLINTEND(modernize-use-using,cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) 81 | -------------------------------------------------------------------------------- /page/src/components/ui/tooltip.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import * as TooltipPrimitive from "@radix-ui/react-tooltip"; 3 | 4 | import { cn } from "@/lib/utils"; 5 | 6 | function TooltipProvider({ 7 | delayDuration = 0, 8 | ...props 9 | }: React.ComponentProps) { 10 | return ( 11 | 16 | ); 17 | } 18 | 19 | function Tooltip({ 20 | ...props 21 | }: React.ComponentProps) { 22 | return ( 23 | 24 | 25 | 26 | ); 27 | } 28 | 29 | function TooltipTrigger({ 30 | ...props 31 | }: React.ComponentProps) { 32 | return ; 33 | } 34 | 35 | function TooltipContent({ 36 | className, 37 | sideOffset = 0, 38 | children, 39 | ...props 40 | }: React.ComponentProps) { 41 | return ( 42 | 43 | 52 | {children} 53 | 54 | 55 | 56 | ); 57 | } 58 | 59 | export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider }; 60 | -------------------------------------------------------------------------------- /CMakePresets.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 6, 3 | "cmakeMinimumRequired": { 4 | "major": 3, 5 | "minor": 26, 6 | "patch": 4 7 | }, 8 | "configurePresets": [ 9 | { 10 | "name": "build", 11 | "hidden": true, 12 | "binaryDir": "${sourceDir}/build/${presetName}" 13 | }, 14 | { 15 | "name": "ninja", 16 | "hidden": true, 17 | "generator": "Ninja" 18 | }, 19 | { 20 | "name": "release", 21 | "inherits": [ 22 | "ninja", 23 | "build" 24 | ], 25 | "cacheVariables": { 26 | "CMAKE_BUILD_TYPE": "RelWithDebInfo" 27 | } 28 | }, 29 | { 30 | "name": "debug", 31 | "inherits": [ 32 | "ninja", 33 | "build" 34 | ], 35 | "cacheVariables": { 36 | "CMAKE_BUILD_TYPE": "Debug" 37 | } 38 | }, 39 | { 40 | "name": "vs2022", 41 | "generator": "Visual Studio 17 2022", 42 | "inherits": "build" 43 | } 44 | ], 45 | "buildPresets": [ 46 | { 47 | "name": "release", 48 | "configurePreset": "release" 49 | }, 50 | { 51 | "name": "debug", 52 | "configurePreset": "debug" 53 | } 54 | ], 55 | "workflowPresets": [ 56 | { 57 | "name": "release", 58 | "steps": [ 59 | { 60 | "type": "configure", 61 | "name": "release" 62 | }, 63 | { 64 | "type": "build", 65 | "name": "release" 66 | } 67 | ] 68 | }, 69 | { 70 | "name": "debug", 71 | "steps": [ 72 | { 73 | "type": "configure", 74 | "name": "debug" 75 | }, 76 | { 77 | "type": "build", 78 | "name": "debug" 79 | } 80 | ] 81 | } 82 | ] 83 | } -------------------------------------------------------------------------------- /src/common/utils/interupt_handler.cpp: -------------------------------------------------------------------------------- 1 | #include "interupt_handler.hpp" 2 | #include 3 | #include 4 | #include 5 | 6 | #include "win.hpp" 7 | 8 | #ifndef _WIN32 9 | #include 10 | #endif 11 | 12 | namespace utils 13 | { 14 | namespace 15 | { 16 | struct signal_data 17 | { 18 | std::atomic_bool installed{false}; 19 | std::function handler{}; 20 | }; 21 | 22 | signal_data& get_signal_data() 23 | { 24 | static signal_data data{}; 25 | return data; 26 | } 27 | 28 | #ifdef _WIN32 29 | BOOL WINAPI handler(const DWORD signal) 30 | { 31 | const auto& data = get_signal_data(); 32 | 33 | if (signal == CTRL_C_EVENT && data.handler) 34 | { 35 | data.handler(); 36 | } 37 | 38 | return TRUE; 39 | } 40 | 41 | #else 42 | void handler(int signal) 43 | { 44 | const auto& data = get_signal_data(); 45 | 46 | if (signal == SIGINT && data.handler) 47 | { 48 | data.handler(); 49 | } 50 | } 51 | #endif 52 | } 53 | 54 | interupt_handler::interupt_handler(std::function callback) 55 | { 56 | auto& data = get_signal_data(); 57 | 58 | bool value{false}; 59 | if (!data.installed.compare_exchange_strong(value, true)) 60 | { 61 | throw std::runtime_error("Global signal handler already installed"); 62 | } 63 | 64 | data.handler = std::move(callback); 65 | 66 | #ifdef _WIN32 67 | SetConsoleCtrlHandler(handler, TRUE); 68 | #else 69 | signal(SIGINT, handler); 70 | #endif 71 | } 72 | 73 | interupt_handler::~interupt_handler() 74 | { 75 | #ifdef _WIN32 76 | SetConsoleCtrlHandler(handler, FALSE); 77 | #else 78 | signal(SIGINT, SIG_DFL); 79 | #endif 80 | 81 | std::this_thread::yield(); 82 | 83 | auto& data = get_signal_data(); 84 | 85 | data.handler = {}; 86 | data.installed = false; 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /page/src/components/ui/tabs.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import * as TabsPrimitive from "@radix-ui/react-tabs"; 3 | 4 | import { cn } from "@/lib/utils"; 5 | 6 | function Tabs({ 7 | className, 8 | ...props 9 | }: React.ComponentProps) { 10 | return ( 11 | 16 | ); 17 | } 18 | 19 | function TabsList({ 20 | className, 21 | ...props 22 | }: React.ComponentProps) { 23 | return ( 24 | 32 | ); 33 | } 34 | 35 | function TabsTrigger({ 36 | className, 37 | ...props 38 | }: React.ComponentProps) { 39 | return ( 40 | 48 | ); 49 | } 50 | 51 | function TabsContent({ 52 | className, 53 | ...props 54 | }: React.ComponentProps) { 55 | return ( 56 | 61 | ); 62 | } 63 | 64 | export { Tabs, TabsList, TabsTrigger, TabsContent }; 65 | -------------------------------------------------------------------------------- /page/src/components/ui/resizable.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import { GripVerticalIcon } from "lucide-react"; 3 | import * as ResizablePrimitive from "react-resizable-panels"; 4 | 5 | import { cn } from "@/lib/utils"; 6 | 7 | function ResizablePanelGroup({ 8 | className, 9 | ...props 10 | }: React.ComponentProps) { 11 | return ( 12 | 20 | ); 21 | } 22 | 23 | function ResizablePanel({ 24 | ...props 25 | }: React.ComponentProps) { 26 | return ; 27 | } 28 | 29 | function ResizableHandle({ 30 | withHandle, 31 | className, 32 | ...props 33 | }: React.ComponentProps & { 34 | withHandle?: boolean; 35 | }) { 36 | return ( 37 | div]:rotate-90", 41 | className, 42 | )} 43 | {...props} 44 | > 45 | {withHandle && ( 46 |
47 | 48 |
49 | )} 50 |
51 | ); 52 | } 53 | 54 | export { ResizablePanelGroup, ResizablePanel, ResizableHandle }; 55 | -------------------------------------------------------------------------------- /src/backends/icicle-emulator/icicle-bridge/data/Ghidra/Processors/x86/data/languages/sha.sinc: -------------------------------------------------------------------------------- 1 | # INFO This file automatically generated by andre on Fri Mar 16 15:13:25 2018 2 | # INFO Direct edits to this file may be lost in future updates 3 | # INFO Command line arguments: ['--sinc', '--cpuid-match', 'SHA'] 4 | 5 | # SHA1RNDS4 4-602 PAGE 1722 LINE 89511 6 | define pcodeop sha1rnds4_sha ; 7 | :SHA1RNDS4 XmmReg1, XmmReg2_m128, imm8 is vexMode=0 & byte=0x0F; byte=0x3A; byte=0xCC; (XmmReg1 & YmmReg1) ... & XmmReg2_m128; imm8 8 | { 9 | XmmReg1 = sha1rnds4_sha( XmmReg1, XmmReg2_m128, imm8:1 ); 10 | } 11 | 12 | # SHA1NEXTE 4-604 PAGE 1724 LINE 89602 13 | define pcodeop sha1nexte_sha ; 14 | :SHA1NEXTE XmmReg1, XmmReg2_m128 is vexMode=0 & byte=0x0F; byte=0x38; byte=0xC8; (XmmReg1 & YmmReg1) ... & XmmReg2_m128 15 | { 16 | XmmReg1 = sha1nexte_sha( XmmReg1, XmmReg2_m128 ); 17 | } 18 | 19 | # SHA1MSG1 4-605 PAGE 1725 LINE 89654 20 | define pcodeop sha1msg1_sha ; 21 | :SHA1MSG1 XmmReg1, XmmReg2_m128 is vexMode=0 & byte=0x0F; byte=0x38; byte=0xC9; (XmmReg1 & YmmReg1) ... & XmmReg2_m128 22 | { 23 | XmmReg1 = sha1msg1_sha( XmmReg1, XmmReg2_m128 ); 24 | } 25 | 26 | # SHA1MSG2 4-606 PAGE 1726 LINE 89708 27 | define pcodeop sha1msg2_sha ; 28 | :SHA1MSG2 XmmReg1, XmmReg2_m128 is vexMode=0 & byte=0x0F; byte=0x38; byte=0xCA; (XmmReg1 & YmmReg1) ... & XmmReg2_m128 29 | { 30 | XmmReg1 = sha1msg2_sha( XmmReg1, XmmReg2_m128 ); 31 | } 32 | 33 | # SHA256RNDS2 4-607 PAGE 1727 LINE 89765 34 | define pcodeop sha256rnds2_sha ; 35 | :SHA256RNDS2 XmmReg1, XmmReg2_m128, XMM0 is vexMode=0 & byte=0x0F; byte=0x38; byte=0xCB; (XmmReg1 & YmmReg1) ... & XmmReg2_m128 & XMM0 36 | { 37 | XmmReg1 = sha256rnds2_sha( XmmReg1, XmmReg2_m128, XMM0 ); 38 | } 39 | 40 | # SHA256MSG1 4-609 PAGE 1729 LINE 89847 41 | define pcodeop sha256msg1_sha ; 42 | :SHA256MSG1 XmmReg1, XmmReg2_m128 is vexMode=0 & byte=0x0F; byte=0x38; byte=0xCC; (XmmReg1 & YmmReg1) ... & XmmReg2_m128 43 | { 44 | XmmReg1 = sha256msg1_sha( XmmReg1, XmmReg2_m128 ); 45 | } 46 | 47 | # SHA256MSG2 4-610 PAGE 1730 LINE 89900 48 | define pcodeop sha256msg2_sha ; 49 | :SHA256MSG2 XmmReg1, XmmReg2_m128 is vexMode=0 & byte=0x0F; byte=0x38; byte=0xCD; (XmmReg1 & YmmReg1) ... & XmmReg2_m128 50 | { 51 | XmmReg1 = sha256msg2_sha( XmmReg1, XmmReg2_m128 ); 52 | } 53 | 54 | -------------------------------------------------------------------------------- /src/windows-emulator/module/mapped_module.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | struct exported_symbol 5 | { 6 | std::string name{}; 7 | uint64_t ordinal{}; 8 | uint64_t rva{}; 9 | uint64_t address{}; 10 | }; 11 | 12 | struct imported_symbol 13 | { 14 | std::string name{}; 15 | size_t module_index{}; 16 | }; 17 | 18 | using exported_symbols = std::vector; 19 | using imported_symbols = std::unordered_map; 20 | using imported_module_list = std::vector; 21 | using address_name_mapping = std::map; 22 | 23 | struct mapped_section 24 | { 25 | std::string name{}; 26 | basic_memory_region<> region{}; 27 | }; 28 | 29 | struct mapped_module 30 | { 31 | std::string name{}; 32 | std::filesystem::path path{}; 33 | 34 | uint64_t image_base{}; 35 | uint64_t image_base_file{}; 36 | uint64_t size_of_image{}; 37 | uint64_t entry_point{}; 38 | 39 | // PE header fields 40 | uint16_t machine{}; // Machine type from file header 41 | uint64_t size_of_stack_reserve{}; // Stack reserve size from optional header 42 | uint64_t size_of_stack_commit{}; // Stack commit size from optional header 43 | uint64_t size_of_heap_reserve{}; // Heap reserve size from optional header 44 | uint64_t size_of_heap_commit{}; // Heap commit size from optional header 45 | 46 | exported_symbols exports{}; 47 | imported_symbols imports{}; 48 | imported_module_list imported_modules{}; 49 | address_name_mapping address_names{}; 50 | 51 | std::vector sections{}; 52 | 53 | bool is_static{false}; 54 | 55 | bool contains(const uint64_t address) const 56 | { 57 | return (address - this->image_base) < this->size_of_image; 58 | } 59 | 60 | uint64_t find_export(const std::string_view export_name) const 61 | { 62 | for (const auto& symbol : this->exports) 63 | { 64 | if (symbol.name == export_name) 65 | { 66 | return symbol.address; 67 | } 68 | } 69 | 70 | return 0; 71 | } 72 | 73 | uint64_t get_image_base_file() const 74 | { 75 | return this->image_base_file; 76 | } 77 | }; 78 | -------------------------------------------------------------------------------- /page/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sogen", 3 | "private": true, 4 | "version": "1.0.0", 5 | "type": "module", 6 | "scripts": { 7 | "dev": "vite", 8 | "build": "tsc -b && vite build", 9 | "lint": "eslint .", 10 | "preview": "vite preview" 11 | }, 12 | "dependencies": { 13 | "@fontsource/inter": "^5.2.8", 14 | "@irori/idbfs": "^0.5.1", 15 | "@radix-ui/react-checkbox": "^1.3.3", 16 | "@radix-ui/react-context-menu": "^2.2.16", 17 | "@radix-ui/react-dialog": "^1.1.15", 18 | "@radix-ui/react-dropdown-menu": "^2.1.16", 19 | "@radix-ui/react-label": "^2.1.8", 20 | "@radix-ui/react-popover": "^1.1.15", 21 | "@radix-ui/react-radio-group": "^1.3.8", 22 | "@radix-ui/react-scroll-area": "^1.2.10", 23 | "@radix-ui/react-separator": "^1.1.8", 24 | "@radix-ui/react-slot": "^1.2.4", 25 | "@radix-ui/react-tabs": "^1.1.13", 26 | "@radix-ui/react-tooltip": "^1.2.8", 27 | "@tailwindcss/vite": "^4.1.17", 28 | "class-variance-authority": "^0.7.1", 29 | "clsx": "^2.1.1", 30 | "flatbuffers": "^25.9.23", 31 | "jszip": "^3.10.1", 32 | "lucide-react": "^0.555.0", 33 | "pe-library": "^2.0.1", 34 | "react": "^19.2.0", 35 | "react-bootstrap-icons": "^1.11.6", 36 | "react-dom": "^19.2.0", 37 | "react-dropzone": "^14.3.8", 38 | "react-helmet": "^6.1.0", 39 | "react-resizable-panels": "^3.0.6", 40 | "react-router-dom": "^7.10.0", 41 | "react-window": "^2.2.3", 42 | "shell-quote": "^1.8.3", 43 | "tailwind-merge": "^3.4.0", 44 | "tailwindcss": "^4.1.16", 45 | "tw-animate-css": "^1.4.0", 46 | "vaul": "^1.1.2", 47 | "wasm-feature-detect": "^1.8.0" 48 | }, 49 | "devDependencies": { 50 | "@eslint/js": "^9.39.1", 51 | "@types/node": "^24.10.1", 52 | "@types/react": "^19.2.7", 53 | "@types/react-dom": "^19.2.3", 54 | "@types/react-helmet": "^6.1.11", 55 | "@types/shell-quote": "^1.7.5", 56 | "@vitejs/plugin-react": "^5.1.1", 57 | "eslint": "^9.39.1", 58 | "eslint-plugin-react-hooks": "^7.0.1", 59 | "eslint-plugin-react-refresh": "^0.4.24", 60 | "globals": "^16.5.0", 61 | "prettier": "3.7.3", 62 | "typescript": "~5.9.3", 63 | "typescript-eslint": "^8.48.1", 64 | "vite": "^7.2.6", 65 | "vite-plugin-pwa": "^1.2.0" 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /page/src/components/status-indicator.tsx: -------------------------------------------------------------------------------- 1 | import { Badge } from "@/components/ui/badge"; 2 | import { CircleFill } from "react-bootstrap-icons"; 3 | import { EmulationStatus, EmulationState as State } from "@/emulator"; 4 | 5 | function getStateName(state: State) { 6 | switch (state) { 7 | case State.Stopped: 8 | return "Stopped"; 9 | case State.Paused: 10 | return "Paused"; 11 | case State.Running: 12 | return "Running"; 13 | case State.Failed: 14 | return "Failed"; 15 | case State.Success: 16 | return "Success"; 17 | default: 18 | return ""; 19 | } 20 | } 21 | 22 | function getStateColor(state: State) { 23 | switch (state) { 24 | case State.Failed: 25 | return "bg-orange-600"; 26 | case State.Paused: 27 | return "bg-amber-500"; 28 | case State.Success: 29 | return "bg-lime-600"; 30 | case State.Stopped: 31 | return "bg-yellow-800"; 32 | case State.Running: 33 | return "bg-sky-500"; 34 | default: 35 | return ""; 36 | } 37 | } 38 | 39 | function getStateEmoji(state: State) { 40 | switch (state) { 41 | case State.Stopped: 42 | return "🟤"; 43 | case State.Paused: 44 | return "🟡"; 45 | case State.Running: 46 | return "🔵"; 47 | case State.Failed: 48 | return "🔴"; 49 | case State.Success: 50 | return "🟢"; 51 | default: 52 | return ""; 53 | } 54 | } 55 | 56 | function getFilename(path: string) { 57 | const lastSlash = path.lastIndexOf("/"); 58 | if (lastSlash == -1) { 59 | return path; 60 | } 61 | 62 | return path.substring(lastSlash + 1); 63 | } 64 | 65 | export interface StatusIndicatorProps { 66 | state: State; 67 | application: string | undefined; 68 | } 69 | 70 | export function StatusIndicator(props: StatusIndicatorProps) { 71 | if (props.application && props.application.length > 0) { 72 | document.title = `${getStateEmoji(props.state)} ${getFilename(props.application)} | Sogen`; 73 | } 74 | 75 | return ( 76 | 77 | 84 | {getStateName(props.state)} 85 | 86 | ); 87 | } 88 | -------------------------------------------------------------------------------- /src/emulator/memory_permission.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | enum class memory_permission : uint8_t 5 | { 6 | none = 0, 7 | read = 1 << 0, 8 | write = 1 << 1, 9 | exec = 1 << 2, 10 | read_write = read | write, 11 | all = read | write | exec 12 | }; 13 | 14 | /***************************************************************************** 15 | * 16 | ****************************************************************************/ 17 | 18 | constexpr memory_permission operator&(const memory_permission x, const memory_permission y) 19 | { 20 | return static_cast(static_cast(x) & static_cast(y)); 21 | } 22 | 23 | constexpr memory_permission operator|(const memory_permission x, const memory_permission y) 24 | { 25 | return static_cast(static_cast(x) | static_cast(y)); 26 | } 27 | 28 | constexpr memory_permission operator^(const memory_permission x, const memory_permission y) 29 | { 30 | return static_cast(static_cast(x) ^ static_cast(y)); 31 | } 32 | 33 | constexpr memory_permission operator~(memory_permission x) 34 | { 35 | return static_cast(~static_cast(x)); 36 | } 37 | 38 | inline memory_permission& operator&=(memory_permission& x, const memory_permission y) 39 | { 40 | x = x & y; 41 | return x; 42 | } 43 | 44 | inline memory_permission& operator|=(memory_permission& x, const memory_permission y) 45 | { 46 | x = x | y; 47 | return x; 48 | } 49 | 50 | inline memory_permission& operator^=(memory_permission& x, const memory_permission y) 51 | { 52 | x = x ^ y; 53 | return x; 54 | } 55 | 56 | /***************************************************************************** 57 | * 58 | ****************************************************************************/ 59 | 60 | inline bool is_executable(const memory_permission permission) 61 | { 62 | return (permission & memory_permission::exec) != memory_permission::none; 63 | } 64 | 65 | inline bool is_readable(const memory_permission permission) 66 | { 67 | return (permission & memory_permission::read) != memory_permission::none; 68 | } 69 | 70 | inline bool is_writable(const memory_permission permission) 71 | { 72 | return (permission & memory_permission::write) != memory_permission::none; 73 | } 74 | -------------------------------------------------------------------------------- /page/src/components/ui/button.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import { Slot } from "@radix-ui/react-slot"; 3 | import { cva, type VariantProps } from "class-variance-authority"; 4 | 5 | import { cn } from "@/lib/utils"; 6 | 7 | const buttonVariants = cva( 8 | "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive", 9 | { 10 | variants: { 11 | variant: { 12 | default: 13 | "bg-primary text-primary-foreground shadow-xs hover:bg-primary/90", 14 | destructive: 15 | "bg-destructive text-white shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60", 16 | outline: 17 | "border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50", 18 | secondary: 19 | "bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80", 20 | ghost: 21 | "hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50", 22 | link: "text-primary underline-offset-4 hover:underline", 23 | }, 24 | size: { 25 | default: "h-9 px-4 py-2 has-[>svg]:px-3", 26 | sm: "h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5", 27 | lg: "h-10 rounded-md px-6 has-[>svg]:px-4", 28 | icon: "size-9", 29 | }, 30 | }, 31 | defaultVariants: { 32 | variant: "default", 33 | size: "default", 34 | }, 35 | }, 36 | ); 37 | 38 | function Button({ 39 | className, 40 | variant, 41 | size, 42 | asChild = false, 43 | ...props 44 | }: React.ComponentProps<"button"> & 45 | VariantProps & { 46 | asChild?: boolean; 47 | }) { 48 | const Comp = asChild ? Slot : "button"; 49 | 50 | return ( 51 | 56 | ); 57 | } 58 | 59 | export { Button, buttonVariants }; 60 | -------------------------------------------------------------------------------- /src/common/network/socket.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "address.hpp" 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | #ifdef _WIN32 10 | using send_size = int; 11 | using sent_size = int; 12 | #define GET_SOCKET_ERROR() (WSAGetLastError()) 13 | #define poll WSAPoll 14 | #define SERR(x) (WSA##x) 15 | #define SHUT_RDWR SD_BOTH 16 | #else 17 | using SOCKET = int; 18 | using send_size = size_t; 19 | using sent_size = ssize_t; 20 | #define INVALID_SOCKET (SOCKET)(~0) 21 | #define SOCKET_ERROR (-1) 22 | #define GET_SOCKET_ERROR() (errno) 23 | #define closesocket close 24 | #define SERR(x) (x) 25 | #endif 26 | 27 | namespace network 28 | { 29 | class socket 30 | { 31 | public: 32 | socket() = default; 33 | 34 | socket(SOCKET s); 35 | 36 | socket(int af, int type, int protocol); 37 | virtual ~socket(); 38 | 39 | socket(const socket& obj) = delete; 40 | socket& operator=(const socket& obj) = delete; 41 | 42 | socket(socket&& obj) noexcept; 43 | socket& operator=(socket&& obj) noexcept; 44 | 45 | operator bool() const; 46 | 47 | bool is_valid() const; 48 | 49 | bool bind(const address& target); 50 | 51 | bool set_blocking(bool blocking); 52 | static bool set_blocking(SOCKET s, bool blocking); 53 | 54 | static constexpr bool socket_is_ready = true; 55 | bool sleep(std::chrono::milliseconds timeout, bool in_poll = true) const; 56 | bool sleep_until(std::chrono::high_resolution_clock::time_point time_point, bool in_poll = true) const; 57 | 58 | SOCKET get_socket() const; 59 | uint16_t get_port() const; 60 | std::optional
get_name() const; 61 | 62 | int get_address_family() const; 63 | 64 | bool is_ready(bool in_poll) const; 65 | 66 | static bool sleep_sockets(const std::span& sockets, std::chrono::milliseconds timeout, bool in_poll); 67 | static bool sleep_sockets_until(const std::span& sockets, std::chrono::high_resolution_clock::time_point time_point, 68 | bool in_poll); 69 | 70 | static bool is_socket_ready(SOCKET s, bool in_poll); 71 | 72 | void close(); 73 | 74 | private: 75 | SOCKET socket_ = INVALID_SOCKET; 76 | }; 77 | } 78 | -------------------------------------------------------------------------------- /page/src/components/ui/card.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | 3 | import { cn } from "@/lib/utils"; 4 | 5 | function Card({ className, ...props }: React.ComponentProps<"div">) { 6 | return ( 7 |
15 | ); 16 | } 17 | 18 | function CardHeader({ className, ...props }: React.ComponentProps<"div">) { 19 | return ( 20 |
28 | ); 29 | } 30 | 31 | function CardTitle({ className, ...props }: React.ComponentProps<"div">) { 32 | return ( 33 |
38 | ); 39 | } 40 | 41 | function CardDescription({ className, ...props }: React.ComponentProps<"div">) { 42 | return ( 43 |
48 | ); 49 | } 50 | 51 | function CardAction({ className, ...props }: React.ComponentProps<"div">) { 52 | return ( 53 |
61 | ); 62 | } 63 | 64 | function CardContent({ className, ...props }: React.ComponentProps<"div">) { 65 | return ( 66 |
71 | ); 72 | } 73 | 74 | function CardFooter({ className, ...props }: React.ComponentProps<"div">) { 75 | return ( 76 |
81 | ); 82 | } 83 | 84 | export { 85 | Card, 86 | CardHeader, 87 | CardFooter, 88 | CardTitle, 89 | CardAction, 90 | CardDescription, 91 | CardContent, 92 | }; 93 | -------------------------------------------------------------------------------- /src/emulator/arch_emulator.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Design notes: 3 | 4 | 1. emulator: the root interface (provides CPU, memory, and hook interfaces). 5 | 2. typed_emulator: a template that adapts to architecture/bitness via the Traits struct. 6 | 3. arch_emulator: a thin layer for architecture-specific logic, things that are shared by all x86 (32/64), or 7 | all ARM (32/64), etc. 8 | X. x86_emulator: x86_emulator are specialisations for 9 | x86 and ARM, parameterised by their respective traits (e.g., x86_64_traits) and stuff :) 10 | 11 | 1. emulator (cpu_interface, memory_interface, hook_interface) 12 | 2. └── typed_emulator 13 | 3. └── arch_emulator 14 | ├── x86_emulator 15 | ├── x86_emulator 16 | ├── arm_emulator 17 | └── arm_emulator 18 | */ 19 | 20 | #pragma once 21 | #include "typed_emulator.hpp" 22 | #include "x86_register.hpp" 23 | 24 | // --[Core]-------------------------------------------------------------------------- 25 | 26 | template 27 | struct arch_emulator : typed_emulator 28 | { 29 | }; 30 | 31 | template 32 | struct x86_emulator : arch_emulator 33 | { 34 | using register_type = typename Traits::register_type; 35 | using pointer_type = typename Traits::pointer_type; 36 | 37 | virtual void set_segment_base(register_type base, pointer_type value) = 0; 38 | virtual void load_gdt(pointer_type address, uint32_t limit) = 0; 39 | }; 40 | 41 | template 42 | struct arm_emulator : arch_emulator 43 | { 44 | }; 45 | 46 | enum class x86_hookable_instructions 47 | { 48 | invalid, // TODO: Get rid of that 49 | syscall, 50 | cpuid, 51 | rdtsc, 52 | rdtscp, 53 | }; 54 | 55 | // --[x86_64]------------------------------------------------------------------------- 56 | 57 | struct x86_64_traits 58 | { 59 | using pointer_type = uint64_t; 60 | using register_type = x86_register; 61 | static constexpr register_type instruction_pointer = x86_register::rip; 62 | static constexpr register_type stack_pointer = x86_register::rsp; 63 | using hookable_instructions = x86_hookable_instructions; 64 | }; 65 | 66 | using x86_64_emulator = x86_emulator; 67 | -------------------------------------------------------------------------------- /page/src/download.ts: -------------------------------------------------------------------------------- 1 | export type DownloadProgressHandler = ( 2 | receivedBytes: number, 3 | totalBytes: number, 4 | ) => void; 5 | 6 | export type DownloadPercentHandler = (percent: number) => void; 7 | 8 | export function makePercentHandler( 9 | handler: DownloadPercentHandler, 10 | ): DownloadProgressHandler { 11 | const progress = { 12 | tracked: 0, 13 | }; 14 | 15 | return (current, total) => { 16 | if (total == 0) { 17 | return; 18 | } 19 | 20 | const percent = Math.floor((current * 100) / total); 21 | const sanePercent = Math.max(Math.min(percent, 100), 0); 22 | 23 | if (sanePercent + 1 > progress.tracked) { 24 | progress.tracked = sanePercent + 1; 25 | handler(sanePercent); 26 | } 27 | }; 28 | } 29 | 30 | export function downloadBinaryFile( 31 | file: string, 32 | progressCallback: DownloadProgressHandler, 33 | ) { 34 | return fetch(file, { 35 | method: "GET", 36 | headers: { 37 | "Content-Type": "application/octet-stream", 38 | }, 39 | }).then((response) => { 40 | const maybeReader = response.body?.getReader(); 41 | if (!maybeReader) { 42 | throw new Error("Bad reader"); 43 | } 44 | 45 | const reader = maybeReader; 46 | 47 | const contentLength = parseInt( 48 | response.headers?.get("Content-Length") || "0", 49 | ); 50 | 51 | let receivedLength = 0; 52 | let chunks: Uint8Array[] = []; 53 | 54 | function processData( 55 | res: ReadableStreamReadResult>, 56 | ): Promise { 57 | if (res.value) { 58 | chunks.push(res.value); 59 | receivedLength += res.value.length; 60 | } 61 | 62 | progressCallback(receivedLength, contentLength); 63 | 64 | if (!res.done) { 65 | return reader.read().then(processData); 66 | } 67 | const chunksAll = new Uint8Array(receivedLength); 68 | let position = 0; 69 | for (const chunk of chunks) { 70 | chunksAll.set(new Uint8Array(chunk), position); 71 | position += chunk.length; 72 | } 73 | 74 | return Promise.resolve(chunksAll.buffer); 75 | } 76 | 77 | return reader.read().then(processData); 78 | }); 79 | } 80 | 81 | export function downloadBinaryFilePercent( 82 | file: string, 83 | progressCallback: DownloadPercentHandler, 84 | ) { 85 | return downloadBinaryFile(file, makePercentHandler(progressCallback)); 86 | } 87 | -------------------------------------------------------------------------------- /page/src/components/item-list.tsx: -------------------------------------------------------------------------------- 1 | import { Input } from "./ui/input"; 2 | import { Button } from "./ui/button"; 3 | import { Plus, Trash } from "react-bootstrap-icons"; 4 | import { Label } from "./ui/label"; 5 | 6 | interface ItemListProps { 7 | title: string; 8 | items: string[]; 9 | onChange: (items: string[]) => void; 10 | } 11 | 12 | export function ItemList(props: ItemListProps) { 13 | const removeItem = (index: number) => { 14 | const newItems = [...props.items]; 15 | newItems.splice(index, 1); 16 | props.onChange(newItems); 17 | }; 18 | 19 | const addItem = (item: string) => { 20 | if (item.length == 0) { 21 | return; 22 | } 23 | 24 | const newItems = props.items.concat(item); 25 | props.onChange(newItems); 26 | }; 27 | 28 | return ( 29 |
30 |
31 |

{props.title}

32 | {/*

33 | Set the settings for the emulation. 34 |

*/} 35 |
36 | 37 |
38 | {props.items.map((item, index) => { 39 | return ( 40 |
44 | 47 | 55 |
56 | ); 57 | })} 58 |
59 | 60 |
{ 62 | const nameInput = (e.target as any).elements.name; 63 | const newItem = nameInput.value; 64 | nameInput.value = ""; 65 | 66 | addItem(newItem); 67 | e.preventDefault(); 68 | }} 69 | > 70 |
71 | 72 | 79 |
80 |
81 |
82 | ); 83 | } 84 | --------------------------------------------------------------------------------