From c5aa6ac920f0bfeacb9b3d685ec5d4117e3517f1 Mon Sep 17 00:00:00 2001 From: Dudi Date: Thu, 11 Nov 2021 13:27:23 +0200 Subject: Add MacOS support --- CMakeLists.txt | 2 ++ README.md | 6 ++--- subhook.c | 2 ++ subhook.h | 8 +++--- subhook_macos.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ tests/test.c | 2 +- tests/test.cpp | 2 +- 7 files changed, 88 insertions(+), 9 deletions(-) create mode 100644 subhook_macos.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 84999c4..afc4c11 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -37,6 +37,8 @@ set(SUBHOOK_HEADERS subhook.h) set(SUBHOOK_SOURCES subhook.c subhook_private.h subhook_x86.c) if(WIN32) list(APPEND SUBHOOK_SOURCES subhook_windows.c) +elseif(APPLE) + list(APPEND SUBHOOK_SOURCES subhook_macos.c) elseif(UNIX) list(APPEND SUBHOOK_SOURCES subhook_unix.c) endif() diff --git a/README.md b/README.md index ff51c9c..01c905a 100644 --- a/README.md +++ b/README.md @@ -152,10 +152,8 @@ Known issues memory as executable, which prevents the use of trampolines. For example, on Fedora you can have such problems because of SELinux (though - you can disable it or exclude your files). On macOS Catalina the - `mprotect()` call inside `subhook_new` will fail with "Permission denied" - (see https://github.com/Zeex/subhook/issues/45). - + you can disable it or exclude your files). + License ------- diff --git a/subhook.c b/subhook.c index 8ea7d51..1c96888 100644 --- a/subhook.c +++ b/subhook.c @@ -68,6 +68,8 @@ SUBHOOK_EXPORT void SUBHOOK_API subhook_set_disasm_handler( #include "subhook_windows.c" #elif defined SUBHOOK_UNIX #include "subhook_unix.c" +#elif defined SUBHOOK_APPLE + #include "subhook_macos.c" #endif #if defined SUBHOOK_X86 || defined SUBHOOK_X86_64 diff --git a/subhook.h b/subhook.h index d2f6814..d8216c6 100644 --- a/subhook.h +++ b/subhook.h @@ -41,9 +41,11 @@ #if defined _WIN32 || defined __CYGWIN__ #define SUBHOOK_WINDOWS -#elif defined __linux__ || defined __APPLE__ \ +#elif defined __linux__ \ || defined __FreeBSD__ || defined __OpenBSD__ || defined __NetBSD__ #define SUBHOOK_UNIX + #elif defined __APPLE__ + #define SUBHOOK_APPLE #else #error Unsupported operating system #endif @@ -65,7 +67,7 @@ #if defined SUBHOOK_X86 #if defined SUBHOOK_WINDOWS #define SUBHOOK_API __cdecl - #elif defined SUBHOOK_UNIX + #elif defined SUBHOOK_UNIX || defined SUBHOOK_APPLE #define SUBHOOK_API __attribute__((cdecl)) #endif #else @@ -80,7 +82,7 @@ #else #define SUBHOOK_EXPORT SUBHOOK_EXTERN __declspec(dllimport) #endif - #elif defined SUBHOOK_UNIX + #elif defined SUBHOOK_UNIX || defined SUBHOOK_APPLE #if defined SUBHOOK_IMPLEMENTATION #define SUBHOOK_EXPORT SUBHOOK_EXTERN __attribute__((visibility("default"))) #else diff --git a/subhook_macos.c b/subhook_macos.c new file mode 100644 index 0000000..866edf5 --- /dev/null +++ b/subhook_macos.c @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2012-2018 Zeex + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include + +#define SUBHOOK_CODE_PROTECT_FLAGS (PROT_READ | PROT_WRITE | PROT_EXEC) + +int subhook_unprotect(void *address, size_t size) { + long pagesize; + + pagesize = sysconf(_SC_PAGESIZE); + address = (void *)((long)address & ~(pagesize - 1)); + int error = mprotect(address, size, SUBHOOK_CODE_PROTECT_FLAGS); + + if (-1 == error) + { + // If mprotect fails, try to use VM_PROT_COPY with vm_protect + kern_return_t kret = vm_protect(mach_task_self(), (unsigned long)address, size, 0, SUBHOOK_CODE_PROTECT_FLAGS | VM_PROT_COPY); + if (kret != KERN_SUCCESS) + { + error = -1; + } + error = 0; + } + + return error; +} + +void *subhook_alloc_code(size_t size) { + void *address; + + address = mmap(NULL, + size, + SUBHOOK_CODE_PROTECT_FLAGS, + #if defined MAP_32BIT && !defined __APPLE__ + MAP_32BIT | + #endif + MAP_PRIVATE | MAP_ANONYMOUS, + -1, + 0); + return address == MAP_FAILED ? NULL : address; +} + +int subhook_free_code(void *address, size_t size) { + if (address == NULL) { + return 0; + } + return munmap(address, size); +} diff --git a/tests/test.c b/tests/test.c index d8b39fd..5526653 100644 --- a/tests/test.c +++ b/tests/test.c @@ -8,7 +8,7 @@ typedef void (*foo_func_t)(void); #ifdef SUBHOOK_X86 #if defined SUBHOOK_WINDOWS #define FOO_CALL __cdecl - #elif defined SUBHOOK_UNIX + #elif defined SUBHOOK_UNIX || defined SUBHOOK_APPLE #define FOO_CALL __attribute__((cdecl)) #endif #endif diff --git a/tests/test.cpp b/tests/test.cpp index 7ba167a..30b7ca4 100644 --- a/tests/test.cpp +++ b/tests/test.cpp @@ -7,7 +7,7 @@ typedef void (*foo_func_t)(); #ifdef SUBHOOK_X86 #if defined SUBHOOK_WINDOWS #define FOO_CALL __cdecl - #elif defined SUBHOOK_UNIX + #elif defined SUBHOOK_UNIX || defined SUBHOOK_APPLE #define FOO_CALL __attribute__((cdecl)) #endif #endif -- cgit v1.1