{"id":13611760,"url":"https://github.com/vxcall/toy-arms","last_synced_at":"2025-04-13T05:33:35.841Z","repository":{"id":39654582,"uuid":"409585158","full_name":"vxcall/toy-arms","owner":"vxcall","description":":nut_and_bolt: tiny crate that empowers your game hack/mod experience!","archived":false,"fork":false,"pushed_at":"2025-03-12T04:00:55.000Z","size":286,"stargazers_count":187,"open_issues_count":2,"forks_count":11,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-04-06T02:45:24.321Z","etag":null,"topics":["cheat","cheating","csgo","dll-injection","game-hacking","hack"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/vxcall.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"ko_fi":"pseuxide"}},"created_at":"2021-09-23T12:35:40.000Z","updated_at":"2025-04-06T00:01:27.000Z","dependencies_parsed_at":"2024-01-14T06:50:57.220Z","dependency_job_id":"83e4104b-5d86-4786-bad2-9464e9837f28","html_url":"https://github.com/vxcall/toy-arms","commit_stats":null,"previous_names":["s3pt3mb3r/toy-arms","vxcall/toy-arms"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vxcall%2Ftoy-arms","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vxcall%2Ftoy-arms/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vxcall%2Ftoy-arms/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vxcall%2Ftoy-arms/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/vxcall","download_url":"https://codeload.github.com/vxcall/toy-arms/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248670513,"owners_count":21142896,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cheat","cheating","csgo","dll-injection","game-hacking","hack"],"created_at":"2024-08-01T19:02:05.189Z","updated_at":"2025-10-14T12:03:42.768Z","avatar_url":"https://github.com/vxcall.png","language":"Rust","funding_links":["https://ko-fi.com/pseuxide"],"categories":["Rust"],"sub_categories":[],"readme":"[![Crates.io](https://img.shields.io/crates/v/toy-arms?style=for-the-badge)](https://crates.io/crates/toy-arms)\n[![Docs.rs](https://img.shields.io/badge/docs.rs-66c2a5?style=for-the-badge\u0026labelColor=555555\u0026logoColor=white\u0026logo=data:image/svg+xml;base64,PHN2ZyByb2xlPSJpbWciIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDUxMiA1MTIiPjxwYXRoIGZpbGw9IiNmNWY1ZjUiIGQ9Ik00ODguNiAyNTAuMkwzOTIgMjE0VjEwNS41YzAtMTUtOS4zLTI4LjQtMjMuNC0zMy43bC0xMDAtMzcuNWMtOC4xLTMuMS0xNy4xLTMuMS0yNS4zIDBsLTEwMCAzNy41Yy0xNC4xIDUuMy0yMy40IDE4LjctMjMuNCAzMy43VjIxNGwtOTYuNiAzNi4yQzkuMyAyNTUuNSAwIDI2OC45IDAgMjgzLjlWMzk0YzAgMTMuNiA3LjcgMjYuMSAxOS45IDMyLjJsMTAwIDUwYzEwLjEgNS4xIDIyLjEgNS4xIDMyLjIgMGwxMDMuOS01MiAxMDMuOSA1MmMxMC4xIDUuMSAyMi4xIDUuMSAzMi4yIDBsMTAwLTUwYzEyLjItNi4xIDE5LjktMTguNiAxOS45LTMyLjJWMjgzLjljMC0xNS05LjMtMjguNC0yMy40LTMzLjd6TTM1OCAyMTQuOGwtODUgMzEuOXYtNjguMmw4NS0zN3Y3My4zek0xNTQgMTA0LjFsMTAyLTM4LjIgMTAyIDM4LjJ2LjZsLTEwMiA0MS40LTEwMi00MS40di0uNnptODQgMjkxLjFsLTg1IDQyLjV2LTc5LjFsODUtMzguOHY3NS40em0wLTExMmwtMTAyIDQxLjQtMTAyLTQxLjR2LS42bDEwMi0zOC4yIDEwMiAzOC4ydi42em0yNDAgMTEybC04NSA0Mi41di03OS4xbDg1LTM4Ljh2NzUuNHptMC0xMTJsLTEwMiA0MS40LTEwMi00MS40di0uNmwxMDItMzguMiAxMDIgMzguMnYuNnoiPjwvcGF0aD48L3N2Zz4K)](https://docs.rs/toy-arms)\n\n\u003cdiv align=\"center\"\u003e\n\n# :crossed_swords: toy-arms\n\u003cimg src=\"https://user-images.githubusercontent.com/33578715/155048461-cb5cdd3f-6d59-4558-b3be-ce8b78144953.png\" /\u003e\n\nHuge thanks to my pal for this header [@suzuharuR](https://twitter.com/suzuharuR)\n\n[Usage](#Usage) | [Examples](#fire-minimal-examples) | [Document](https://docs.rs/toy-arms)\n\n\u003c/div\u003e\n\n# What's toy-arms?\nThis library is meant to be created to test rust's capability for game hacking. u know it's kinda far from normal programming, right? However, cuz I was too lazy and beginner this library is relatively high level, meaning it doesnt use either Nt or Zw API, and it's only capable of things that a user-mode application does. Dont get it something fancy, rather consider this as my training of rust, can't guarantee the quality of the code. Oh, and never ever mention about the bizzar project structure, even if it looks bloody cringy. My bad.\n\n# :pushpin: Table of contents\n\n- [:two_hearts: support me](#two_hearts-support-me)\n- [:fire: Get started](#fire-get-started)\n  - [step1](#step1)\n  - [step2](#step2)\n- [:scroll: Practical Examples](#scroll-practical-examples)\n  - [internal](#internal)\n    - [simplest dll](#simplest-dll-internal)\n    - [auto shoot](#auto-shoot-internal)\n    - [get localplayer health](#get-localplayer-health-internal)\n    - [pattern scang](#pattern-scan-internal)\n  - [external](#external)\n    - [auto shoot](#auto-shoot-external)\n    - [get localpalyer health](#get-localplayer-health-external)\n    - [pattern scan](#pattern-scan-external)\n- [:card_file_box: Other examples?](#card_file_box-other-examples)\n- [:herb: API info](#herb-api-info)\n\n# :fire: Get started\n\nBut before actually test the example, I'll show you some preparation steps you're supposed to know.\n\n## step1\nFirstly, include `toy-arms` in your dependencies' table in `Cargo.toml`.\n\nAs of now toy-arms has 2 features which are `internal` and `external`.\n`internal` feature flag is on by default so you have to specify `external` when you wanna use it.\n\n**for internal use:**\n```toml\n[dependencies]\ntoy-arms = {git = \"version = \"https://github.com/vxcall/toy-arms\"}\n\n# This annotation below is to tell the compiler to compile this into dll. MUST.\n[lib]\ncrate-type = [\"cdylib\"]\n```\n\n**for external use:**\n```toml\n[dependencies]\ntoy-arms = {git = \"https://github.com/vxcall/toy-arms\", features = [\"external\"]}\n```\n\n## step2\n\nSecondly, sicne most of those tests are targeting the game \"csgo.exe(x86)\", you may have to build the code in x86 architecture depending on the example.\nYou can either specify in `.cargo/config.toml` as following:\n```toml\n[build]\ntarget = \"i686-pc-windows-msvc\"\n```\n\nOr put `--target i686-pc-windows-msvc` flag everytime when you build the code.\n\nIf you don't have toolchain for 32bit msvc, do following\n```shell\n rustup target add i686-pc-windows-msvc \n```\n\n# :scroll: Practical Examples\n\nIn this section I'll showcase you various examples for different situations with internal and external features. Find one fits your purpose.\n\nBe informed that all these examples are happened to target **CSGO:counter strike global offencive**\n, so be sure to get it and test with it.\n\n\n## internal\n\nWelcome to the examples of internal hack. \nA dll file will be generated by build these examples, inject it with whatever dll injector you possess.\n\n### simplest dll (internal)\n\nWith this crate, making the injectable dll which is the smallest possible is simple as this:\n\n`cargo b --example in_simplest_dll --target i686-pc-windows-msvc`\n\n```rust\n/*\nThis is the demonstration of how to make the simplest hack with toy-arms.\n*/\n// A neat macro which defines entry point instead of you.\n// Also, you dont have to alloc/free console by yourself, console will show up when u compile into debug build.\n\ninternal::create_entrypoint!(hack_main_thread);\n\n// Main thread\nfn hack_main_thread() {\n    // YOUR STUNNING CODE'S SUPPOSED TO BE HERE;\n    for i in 0..30000 {\n        println!(\"using toy-arms {}\", i);\n    }\n}\n```\n\n### auto shoot (internal)\n\nThis is the code that overwrites the value at `DW_FORCE_ATTACK` to 0x5 every loop in csgo.exe.\nNote that you have to check if the address of `DW_FORCE_ATTACK` is up-to-date.\n\n`cargo b --example in_auto_shoot --target i686-pc-windows-msvc`\n\n```rust\n/*\nThis is the demonstration of how to use internal analysis feature in toy-arms.\nThis code gets module handle and function address of the func called MessageBoxA as an example.\nThen read the value called dwForceAttack and overwrite it to make player shoot.\nThe offset DW_FORCE_ATTACK works as of the day i wrote this but it might not be up to date in your case.\n*/\n\nuse toy_arms::internal::cast;\nuse toy_arms::utils::detect_keydown;\nuse toy_arms::utils::keyboard::{detect_keypress, VirtualKeyCode};\nuse internal::common::get_module_handle;\nuse winapi::shared::minwindef::HMODULE;\n\ninternal::create_entrypoint!(hack_main_thread);\n\n// This offset has to be up to date.\nconst DW_FORCE_ATTACK: usize = 0x320BDE8;\n\nfn hack_main_thread() {\n    let mut once = false;\n\n    // Gets module handle\n    let module_handle: HMODULE = get_module_handle(\"client.dll\").unwrap();\n    println!(\"module handle = {:?}\", module_handle as usize);\n\n    let shoot_flag = cast!(mut module_handle as usize + DW_FORCE_ATTACK, u8);\n\n    loop {\n        if !once {\n            println!(\"Press INSERT to exit...\");\n            once = !once;\n        }\n\n        unsafe {\n            // Auto shoot\n            *shoot_flag = 5u8;\n        }\n\n        // To exit this hack loop when you input INSEERT KEY\n        if detect_keypress(VirtualKeyCode::VK_INSERT) {\n            break;\n        }\n\n        // just flexing this neat function xd.\n        if detect_keydown!(VirtualKeyCode::VK_HOME) {\n            println!(\"HOME is both pressed\");\n        }\n    }\n}\n```\n\n### get localplayer health (internal)\n\nWhile this code below will retrieve health value of LocalPlayer object in csgo.exe.\nNote that you have to update the offset of `DW_LOCAL_PLAYER`.\n\n`cargo b --example in_get_localplayer_health --target i686-pc-windows-msvc`\n\n```rust\n/*\nThis example is the demonstration of getting player health with toy-arms internal memory analysis feature.\nMake sure that you inject this image to csgo.exe.\nalso, the offset of DW_LOCAL_PLAYER works as of the day i wrote this but it might not be up to date in your case.\n*/\nuse internal::cast;\nuse internal::module::Module;\nuse internal::GameObject;\nuse toy_arms::derive::GameObject;\nuse utils::keyboard::VirtualKeyCode;\n\ninternal::create_entrypoint!(hack_main_thread);\n\n// This macro provides from_raw() func that ensures the base address is not null.\n#[derive(GameObject)]\nstruct LocalPlayer {\n    pointer: *const usize, // Denote the base address of LocalPlayer to use it later in get_health() function.\n}\n\nimpl LocalPlayer {\n    unsafe fn get_health(\u0026self) -\u003e u16 {\n        *cast!(self.pointer as usize + 0x100, u16)\n    }\n}\n\n// This offset has to be up to date.\nconst DW_LOCAL_PLAYER: u32 = 0xDBF4BC;\n\nfn hack_main_thread() {\n    let module = Module::from_name(\"client.dll\").unwrap();\n    unsafe {\n        //let dw_local_player = memory.read_mut::\u003cLocalPlayer\u003e(0xDA244C);\n        loop {\n            if let Some(i) = LocalPlayer::from_raw(module.read(DW_LOCAL_PLAYER as usize)) {\n                println!(\"health = {:?}\", (*i).get_health());\n            };\n            if toy_arms::utils::keyboard::detect_keypress(VirtualKeyCode::VK_INSERT) {\n                break;\n            }\n        }\n    }\n}\n```\n\n### pattern scan (internal)\n\nThis is the pattern scanning example where the pattern is for dwForceAttack in csgo.\n\n`cargo b --example in_pattern_scan --target i686-pc-windows-msvc`\n\n```rust\n/*\nThis is an example to demonstrate how to use powerful pattern scan feature in toy-arms.\nMake sure you inject this image to csgo.exe.\nThe model pattern is for dwForceAttack.\n*/\n\nuse internal::module::Module;\nuse toy_arms::utils::keyboard::{detect_keypress, VirtualKeyCode};\ninternal::create_entrypoint!(hack_main_thread);\n\nconst DW_FORCE_ATTACK_PATTERN: \u0026str = \"89 0D ? ? ? ? 8B 0D ? ? ? ? 8B F2 8B C1 83 CE 04\";\n\nfn hack_main_thread() {\n    let mut once = false;\n\n    let mut client = Module::from_name(\"client.dll\").unwrap();\n\n    match client.find_pattern(DW_FORCE_ATTACK_PATTERN) {\n        Some(i) =\u003e println!(\"[+] *dwForceAttack address: 0x{:x}\", i),\n        None =\u003e println!(\"[-] Pattern not found\"),\n    }\n\n    match client.pattern_scan(DW_FORCE_ATTACK_PATTERN, 2, 0) {\n        Some(i) =\u003e println!(\"[+] dwForceAttack address: 0x{:x}\", i),\n        None =\u003e println!(\"[-] Offset not found\"),\n    }\n\n    loop {\n        if !once {\n            println!(\"[+] Press INSERT to exit...\");\n            once = !once;\n        }\n        // To exit this hack loop when you input INSEERT KEY\n        if detect_keypress(VirtualKeyCode::VK_INSERT) {\n            break;\n        }\n    }\n}\n```\n\n## external\n\nOn the other hand, following code is how tamper with memory externally is like.\n\n### auto shoot (external)\n\nThis is the code that overwrites the value at `DW_FORCE_ATTACK` to 0x5 every loop in csgo.exe.\nNote that you have to check if the address of `DW_FORCE_ATTACK` is up-to-date.\n\n`cargo r --example ex_auto_shoot --features external --no-default-features`\n\n```rust\n/*\nThis is the demonstration of how to use external feature of toy-arms.\nFollowing code is trying to get process id and process handle first, then getting a value called dwClientState_state.\nThen showing the way to overwrite value at dwForceAttack to make player shoot.\nThe offset DW_CLIENT_STATE, DW_CLIENT_STATE_STATE and DW_FORCE_ATTACK work as of the day i wrote this but it might not be up to date in your case.\n*/\n\nuse toy_arms::external::process::Process;\nuse toy_arms::external::{read, write};\nuse toy_arms::utils::keyboard::VirtualKeyCode;\n\nfn main() {\n    // This const has to be up to date.\n    const DW_FORCE_ATTACK: u32 = 0x320BDE8;\n    // Getting process information\n    let process = Process::from_process_name(\"csgo.exe\").unwrap();\n    println!(\n        \"[+] process id: {}, \\n[+] process handle: {:?}\",\n        process.id, process.handle\n    );\n\n    // You can get module information by using get_module_info\n    let module_info = process.get_module_info(\"client.dll\").unwrap();\n    println!(\"[+] module name: {}\", module_info.name);\n\n    loop {\n        // write helps you tamper with the value.\n        write::\u003cu32\u003e(\n            \u0026process.handle,\n            process.get_module_base(\"client.dll\").unwrap() + DW_FORCE_ATTACK as usize,\n            \u0026mut 0x5,\n        )\n        .unwrap();\n\n        // Exit this loop by pressing INSERT\n        if toy_arms::utils::keyboard::detect_keypress(VirtualKeyCode::VK_INSERT) {\n            break;\n        }\n    }\n}\n```\n\n### get localplayer health (external)\n\nRetrieving local player health demo is present as below.\nQuick tip: You don't wanna use usize as the pointer type cuz external program itself is going to be 64bit, \ntherefore the buffer size will be 8bytes whereas the actual pointer is 4bytes. Use u32 or DWORD instead.\n\n`cargo r --example ex_get_localplayer_health --features external --no-default-features`\n\n```rust\nuse external::error::{ReadWriteMemoryFailedDetail, TAExternalError};\nuse std::mem::size_of;\nuse toy_arms::external::error::TAExternalError::ReadMemoryFailed;\nuse toy_arms::external::module::Module;\nuse toy_arms::external::process::Process;\nuse toy_arms::external::read;\n\nconst DW_LOCAL_PLAYER: u32 = 0xDBF4BC;\n\nfn main() {\n    let csgo: Process;\n    match Process::from_process_name(\"csgo.exe\") {\n        Ok(p) =\u003e csgo = p,\n        Err(e) =\u003e {\n            println!(\"{}\", e);\n            return;\n        }\n    }\n    let client: Module;\n    match csgo.get_module_info(\"client.dll\") {\n        Ok(m) =\u003e client = m,\n        Err(e) =\u003e {\n            println!(\"{}\", e);\n            return;\n        }\n    }\n\n    println!(\"[+] module_base: {:x}\", client.base_address);\n    println!(\n        \"[+] localplayer pointer pointer: 0x{:x}\",\n        client.base_address + DW_LOCAL_PLAYER as usize\n    );\n\n    let mut localplayer: u32 = 0;\n    let ok = read::\u003cu32\u003e(\n        \u0026csgo.handle,\n        client.base_address + DW_LOCAL_PLAYER as usize,\n        size_of::\u003cu32\u003e(),\n        \u0026mut localplayer as *mut u32,\n    );\n\n    match ok {\n        Ok(_ok) =\u003e {\n            println!(\"[+] localplayer pointer: 0x{:x}\", localplayer);\n            let mut health: u16 = 0;\n            // 0x100 is the offset of the health in player entity class.\n            let ok2 = read::\u003cu16\u003e(\n                \u0026csgo.handle,\n                localplayer as usize + 0x100,\n                size_of::\u003cu16\u003e(),\n                \u0026mut health as *mut u16,\n            );\n            match ok2 {\n                // This is what we wanted.\n                Ok(h) =\u003e println!(\"[+] localplayer's health: {}\", health),\n                Err(ReadMemoryFailed(e)) =\u003e println!(\"{}\", e),\n                Err(_) =\u003e println!(\"[-] some error\"),\n            }\n        }\n        Err(e) =\u003e match e {\n            TAExternalError::ReadMemoryFailed(ReadWriteMemoryFailedDetail::ErrorPartialCopy) =\u003e {\n                println!(\"Partial Copy. Probably the address is protected\")\n            }\n            TAExternalError::ReadMemoryFailed(ReadWriteMemoryFailedDetail::ErrorInvalidAddress) =\u003e {\n                println!(\"Invalid Address\")\n            }\n            TAExternalError::ReadMemoryFailed(ReadWriteMemoryFailedDetail::ErrorInvalidHandle) =\u003e {\n                println!(\"Invalid Handle\")\n            }\n            TAExternalError::ReadMemoryFailed(ReadWriteMemoryFailedDetail::UnknownError {\n                error_code,\n            }) =\u003e println!(\"Unknown Error: {}\", error_code),\n            _ =\u003e println!(\n                \"[-] error: {}\\n[-] Maybe non-updated offset are the reason. update it yourself.\",\n                e\n            ),\n        },\n    }\n}\n```\n\n### pattern scan (external)\n\nThis is the pattern scanning example where the pattern is for dwForceAttack in csgo.\n\n`cargo r --example ex_pattern_scan --features external --no-default-features`\n\n```rust\nuse toy_arms::external::process::Process;\nuse toy_arms::utils::keyboard::VirtualKeyCode;\n\nconst DW_FORCE_ATTACK_PATTERN: \u0026str = \"89 0D ? ? ? ? 8B 0D ? ? ? ? 8B F2 8B C1 83 CE 04\";\n\nfn main() {\n    let mut once = false;\n\n    // Getting process information\n    let process = Process::from_process_name(\"csgo.exe\").unwrap();\n\n    // You can get module information by using get_client\n    let mut client = process.get_module_info(\"client.dll\").unwrap();\n\n    let address = client.find_pattern(DW_FORCE_ATTACK_PATTERN);\n    match address {\n        Some(i) =\u003e println!(\"[+] found *dwForceAttack pattern at 0x{:x}\", i),\n        None =\u003e println!(\"[-] NOTHING FOUND\"),\n    }\n\n    let offset = client.pattern_scan::\u003cu32\u003e(DW_FORCE_ATTACK_PATTERN, 2, 0);\n    match offset {\n        Some(i) =\u003e println!(\"[+] found dwForceAttack offset at 0x{:x}\", i),\n        None =\u003e println!(\"NOTHING FOUND\"),\n    }\n\n    loop {\n        if !once {\n            println!(\"[+] Press INSERT to exit...\");\n            once = !once;\n        }\n        // Exit this loop by pressing INSERT\n        if toy_arms::utils::detect_keydown!(VirtualKeyCode::VK_INSERT) {\n            break;\n        }\n    }\n}\n```\n\n# :card_file_box: Other examples?\nYes you have! Take a look at [examples directory](https://github.com/s3pt3mb3r/toy-arms/tree/master/examples), you'll see more examples!\n\nHowever, you may need to update offsets which some examples contain with your own hands.\n\nRefer to [hazedumper](https://github.com/frk1/hazedumper/blob/master/csgo.hpp) as always for latest offsets of CSGO.\n\nTo build examples in x86 arch:\n```shell\ncargo build --example EXAMPLE_NAME --target i686-pc-windows-msvc\n```\n\n# :herb: API info\n\n### external `read()` func\n\n```rs\nfn read\u003cT\u003e(\n    process_handle: \u0026HANDLE,\n    base_address: usize,\n    size: usize,\n    buffer: *mut T,\n)\n```\n\nmake sure to pass buffer like following:\n\n```rs\nlet mut buffer: u32 = 0; // Declare with mut keyword\nread::\u003cu32\u003e(\n    \u0026handle,\n    base_address,\n    size_of::\u003cu32\u003e(),\n    \u0026mut buffer as *mut u32, // Must be the form of \u0026mut buffer as *mut T\n    // These are equivalent to \u0026buffer in C++.\n);\n```\n\n### internal `read()` func and `cast!()` macro\n\nin the example, both of them are used conditionally. They are present for different use.\n\n`cast!()` is the basic dereference and u can always use this of course.\n\n`read()` is the member method of Module struct. It allows u to just pass the offset of what u want from module base, and it adds them for you. `cast!()` is used under the hood.\n\n# Acknowledge\n[hazedumper-rs](https://github.com/frk1/hazedumper-rs) - referenced as role model of pattern scan\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvxcall%2Ftoy-arms","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fvxcall%2Ftoy-arms","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvxcall%2Ftoy-arms/lists"}