| 632 | } |
| 633 | |
| 634 | static int lua_mem_patch(lua_State* L) { |
| 635 | uintptr_t address = (uintptr_t)luaL_checkinteger(L, 1); |
| 636 | size_t patch_len; |
| 637 | const char* patch_bytes = luaL_checklstring(L, 2, &patch_len); |
| 638 | |
| 639 | LOGI("Memory.patch: address=0x%lx, len=%zu", (unsigned long)address, patch_len); |
| 640 | |
| 641 | size_t page_size = sysconf(_SC_PAGESIZE); |
| 642 | uintptr_t page_start = address & ~(page_size - 1); |
| 643 | size_t region_size = ((address + patch_len - page_start) + page_size - 1) & ~(page_size - 1); |
| 644 | |
| 645 | if (mprotect((void*)page_start, region_size, PROT_READ | PROT_WRITE | PROT_EXEC) != 0) { |
| 646 | char err_msg[256]; |
| 647 | snprintf(err_msg, sizeof(err_msg), "ERROR: mprotect failed at 0x%lx", (unsigned long)address); |
| 648 | send_to_cli(err_msg); |
| 649 | lua_pushboolean(L, 0); |
| 650 | lua_pushstring(L, "mprotect failed"); |
| 651 | return 2; |
| 652 | } |
| 653 | |
| 654 | memcpy((void*)address, patch_bytes, patch_len); |
| 655 | |
| 656 | |
| 657 | char success_msg[256]; |
| 658 | snprintf(success_msg, sizeof(success_msg), "✓ Patched %zu bytes at 0x%lx", patch_len, (unsigned long)address); |
| 659 | send_to_cli(success_msg); |
| 660 | |
| 661 | lua_pushboolean(L, 1); |
| 662 | return 1; |
| 663 | } |
| 664 | |
| 665 | /* |
| 666 | * hexdump(target [, length]) |
nothing calls this directly
no test coverage detected