├── .gitattributes ├── .gitignore ├── LICENSE ├── LetMeBlock.plist ├── Makefile ├── README.md ├── Tweak.xm └── layout ├── DEBIAN ├── control ├── extrainst_ └── postrm └── Library └── libSandy └── LetMeBlock.plist /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .theos 2 | .DS_Store 3 | packages/* 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 - 2024 PoomSmart 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /LetMeBlock.plist: -------------------------------------------------------------------------------- 1 | { Filter = { Executables = ( "mDNSResponder", "mDNSResponderHelper" ); }; } 2 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | PACKAGE_VERSION = 1.3.0 2 | ifeq ($(THEOS_PACKAGE_SCHEME),rootless) 3 | TARGET = iphone:clang:latest:14.0 4 | ARCHS = arm64 arm64e 5 | else 6 | TARGET = iphone:clang:14.5:9.0 7 | export PREFIX = $(THEOS)/toolchain/Xcode11.xctoolchain/usr/bin/ 8 | endif 9 | 10 | include $(THEOS)/makefiles/common.mk 11 | 12 | TWEAK_NAME = LetMeBlock 13 | $(TWEAK_NAME)_FILES = Tweak.xm 14 | $(TWEAK_NAME)_LIBRARIES = sandy 15 | $(TWEAK_NAME)_CFLAGS = -fobjc-arc 16 | 17 | include $(THEOS_MAKE_PATH)/tweak.mk 18 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # LetMeBlock 2 | 3 | Makes mDNSResponder care about `(/var/jb)/etc/hosts` on iOS 12+, and load **all** entries on iOS 9+ 4 | 5 | In order to load all entries on iOS 9+, the memory limits defined in `Version4 > Daemon > Override > com.apple.mDNSResponder.reloaded` of the jetsam properties plist **must be increased**. This can be done either by manually editing the plist (and rebooting) or using jetsamctl's API, see [here](https://github.com/conradev/jetsamctl). 6 | 7 | If in any cases the tweak does not seem to work, you either 8 | * Reinstall LetMeBlock from your package manager of choice 9 | * Run the command `killall -9 mDNSResponder; killall -9 mDNSResponderHelper` as root 10 | 11 | ## Compiling 12 | 13 | ``` 14 | make 15 | ``` 16 | 17 | If `xpc.h` isn't found, run: 18 | 19 | ``` 20 | sudo ln -s $(xcode-select -p)/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/xpc $(xcode-select -p)/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/usr/include/xpc 21 | sudo ln -s $(xcode-select -p)/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/launch.h $(xcode-select -p)/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/usr/include/launch.h 22 | ``` 23 | -------------------------------------------------------------------------------- /Tweak.xm: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | #import 4 | #import 5 | #import 6 | 7 | #include 8 | #include 9 | 10 | #define MEMORYSTATUS_CMD_SET_PRIORITY_PROPERTIES 2 11 | #define MEMORYSTATUS_CMD_SET_JETSAM_HIGH_WATER_MARK 5 12 | #define MEMORYSTATUS_CMD_SET_JETSAM_TASK_LIMIT 6 13 | #define MEMORYSTATUS_CMD_SET_PROCESS_IS_MANAGED 16 14 | #define JETSAM_PRIORITY_CRITICAL 19 15 | #define JETSAM_MEMORY_LIMIT 512 16 | #define DEFAULT_HOSTS_PATH "/etc/hosts" 17 | #define NEW_HOSTS_PATH ROOT_PATH("/etc/hosts.lmb") 18 | #define ROOTLESS_NEW_HOSTS_PATH "/var/jb/etc/hosts" 19 | 20 | typedef struct memorystatus_priority_properties { 21 | int32_t priority; 22 | uint64_t user_data; 23 | } memorystatus_priority_properties_t; 24 | 25 | static FILE *etcHosts; 26 | 27 | extern "C" int memorystatus_control(uint32_t command, pid_t pid, uint32_t flags, void *buffer, size_t buffersize); 28 | 29 | static void bypassJetsamMemoryLimit(pid_t pid) { 30 | HBLogDebug(@"LetMeBlock: bypassJetsamMemoryLimit for pid %d", pid); 31 | int rc; memorystatus_priority_properties_t props = {JETSAM_PRIORITY_CRITICAL, 0}; 32 | rc = memorystatus_control(MEMORYSTATUS_CMD_SET_PRIORITY_PROPERTIES, pid, 0, &props, sizeof(props)); 33 | if (rc) { 34 | HBLogDebug(@"LetMeBlock: memorystatus_control MEMORYSTATUS_CMD_SET_PRIORITY_PROPERTIES"); 35 | return; 36 | } 37 | rc = memorystatus_control(MEMORYSTATUS_CMD_SET_JETSAM_HIGH_WATER_MARK, pid, -1, NULL, 0); 38 | if (rc) { 39 | HBLogDebug(@"LetMeBlock: memorystatus_control MEMORYSTATUS_CMD_SET_JETSAM_HIGH_WATER_MARK"); 40 | return; 41 | } 42 | rc = memorystatus_control(MEMORYSTATUS_CMD_SET_PROCESS_IS_MANAGED, pid, 0, NULL, 0); 43 | if (rc) { 44 | HBLogDebug(@"LetMeBlock: memorystatus_control MEMORYSTATUS_CMD_SET_PROCESS_IS_MANAGED"); 45 | return; 46 | } 47 | rc = memorystatus_control(MEMORYSTATUS_CMD_SET_JETSAM_TASK_LIMIT, pid, JETSAM_MEMORY_LIMIT, NULL, 0); 48 | if (rc) { 49 | HBLogDebug(@"LetMeBlock: memorystatus_control MEMORYSTATUS_CMD_SET_JETSAM_TASK_LIMIT"); 50 | } 51 | } 52 | 53 | %group mDNSResponder_iOS12 54 | 55 | // Allow /etc/hosts to be read on iOS 12 and above 56 | bool (*os_variant_has_internal_diagnostics)(const char *) = NULL; 57 | %hookf(bool, os_variant_has_internal_diagnostics, const char *subsystem) { 58 | if (subsystem && strcmp(subsystem, "com.apple.mDNSResponder") == 0) 59 | return 1; 60 | return %orig(subsystem); 61 | } 62 | 63 | %end 64 | 65 | %group mDNSResponder 66 | 67 | unsigned int *mDNS_StatusCallback_allocated = NULL; 68 | 69 | // Reset the memory counter every time it is increased 70 | void (*mDNS_StatusCallback)(void *, int) = NULL; 71 | %hookf(void, mDNS_StatusCallback, void *arg1, int arg2) { 72 | if (mDNS_StatusCallback_allocated) 73 | *mDNS_StatusCallback_allocated = 0; 74 | %orig(arg1, arg2); 75 | } 76 | 77 | // Open UHB's hosts instead of DEFAULT_HOSTS_PATH 78 | // This new UHB will place all the blocked addresses to NEW_HOSTS_PATH so we won't mess up with the original file 79 | // If in any cases NEW_HOSTS_PATH got corrupted, we fallback to the original one (DEFAULT_HOSTS_PATH) 80 | %hookf(FILE *, fopen, const char *path, const char *mode) { 81 | if (path && strcmp(path, DEFAULT_HOSTS_PATH) == 0) { 82 | if (etcHosts) return etcHosts; 83 | FILE *r = %orig(ROOTLESS_NEW_HOSTS_PATH, mode); 84 | if (r) return r; 85 | r = %orig(NEW_HOSTS_PATH, mode); 86 | if (r) return r; 87 | } 88 | return %orig(path, mode); 89 | } 90 | 91 | %end 92 | 93 | %group mDNSResponderHelper 94 | 95 | void (*accept_client_block_invoke)(int, xpc_object_t); 96 | %hookf(void, accept_client_block_invoke, int arg0, xpc_object_t req_msg) { 97 | HBLogDebug(@"LetMeBlock: accept_client_block_invoke"); 98 | xpc_type_t type = xpc_get_type(req_msg); 99 | if (type != XPC_TYPE_DICTIONARY) { 100 | // mDNSResponder died, kill the helper now to respawn mDNSResponder with the helper intact 101 | exit(0); 102 | } 103 | %orig(arg0, req_msg); 104 | } 105 | 106 | void (*init_helper_service_block_invoke)(id, xpc_object_t); 107 | %hookf(void, init_helper_service_block_invoke, id arg0, xpc_object_t obj) { 108 | HBLogDebug(@"LetMeBlock: init_helper_service_block_invoke"); 109 | #define ORIG_API_UNAVAILABLE(...) API_UNAVAILABLE(__VA_ARGS__) 110 | #undef API_UNAVAILABLE 111 | #define API_UNAVAILABLE(...) 112 | pid_t pid = xpc_connection_get_pid(obj); 113 | #undef API_UNAVAILABLE 114 | #define API_UNAVAILABLE(...) ORIG_API_UNAVAILABLE(__VA_ARGS__) 115 | bypassJetsamMemoryLimit(pid); 116 | %orig; 117 | } 118 | 119 | %end 120 | 121 | %ctor { 122 | if (getuid()) { 123 | // mDNSResponder (_mDNSResponder) 124 | HBLogDebug(@"LetMeBlock: in mDNSResponder"); 125 | libSandy_applyProfile("LetMeBlock"); 126 | etcHosts = fopen(ROOTLESS_NEW_HOSTS_PATH, "r"); 127 | if (etcHosts == NULL) etcHosts = fopen(NEW_HOSTS_PATH, "r"); 128 | MSImageRef ref = MSGetImageByName("/usr/sbin/mDNSResponder"); 129 | mDNS_StatusCallback = (void (*)(void *, int))_PSFindSymbolCallable(ref, "_mDNS_StatusCallback"); 130 | mDNS_StatusCallback_allocated = (unsigned int *)_PSFindSymbolReadable(ref, "_mDNS_StatusCallback.allocated"); 131 | if (IS_IOS_OR_NEWER(iOS_12_0)) { 132 | MSImageRef libsys = MSGetImageByName("/usr/lib/system/libsystem_darwin.dylib"); 133 | os_variant_has_internal_diagnostics = (bool (*)(const char *))_PSFindSymbolCallable(libsys, "_os_variant_has_internal_diagnostics"); 134 | %init(mDNSResponder_iOS12); 135 | } 136 | %init(mDNSResponder); 137 | // Spawn mDNSResponderHelper if not already so that it will unlock mDNSResponder's memory limit as soon as possible 138 | void (*SendDict_ToServer)(xpc_object_t) = (void (*)(xpc_object_t))_PSFindSymbolCallable(ref, "_SendDict_ToServer"); 139 | if (SendDict_ToServer) { 140 | xpc_object_t dict = xpc_dictionary_create(NULL, NULL, 0); 141 | SendDict_ToServer(dict); 142 | } else { 143 | void (*Init_Connection)(void) = (void (*)(void))_PSFindSymbolCallable(ref, "_Init_Connection"); 144 | if (Init_Connection) 145 | Init_Connection(); 146 | } 147 | } else { 148 | // mDNSResponderHelper (root) 149 | HBLogDebug(@"LetMeBlock: in mDNSResponderHelper"); 150 | MSImageRef ref = MSGetImageByName("/usr/sbin/mDNSResponderHelper"); 151 | accept_client_block_invoke = (void (*)(int, xpc_object_t))_PSFindSymbolCallable(ref, "___accept_client_block_invoke"); 152 | init_helper_service_block_invoke = (void (*)(id, xpc_object_t))_PSFindSymbolCallable(ref, "___init_helper_service_block_invoke"); 153 | if (accept_client_block_invoke && init_helper_service_block_invoke) { 154 | %init(mDNSResponderHelper); 155 | } 156 | } 157 | } 158 | 159 | %dtor { 160 | if (etcHosts) fclose(etcHosts); 161 | } -------------------------------------------------------------------------------- /layout/DEBIAN/control: -------------------------------------------------------------------------------- 1 | Package: com.ps.letmeblock 2 | Name: LetMeBlock 3 | Depends: mobilesubstrate (>= 0.9.5000), firmware (>= 9.0), com.opa334.libsandy 4 | Version: 1.0.0 5 | Architecture: iphoneos-arm 6 | Description: Make mDNSResponder care more about /etc/hosts 7 | Maintainer: PoomSmart 8 | Author: PoomSmart 9 | Section: Tweaks 10 | Depiction: https://poomsmart.github.io/repo/depictions/letmeblock.html 11 | SileoDepiction: https://poomsmart.github.io/repo/sileodepictions/letmeblock.json 12 | -------------------------------------------------------------------------------- /layout/DEBIAN/extrainst_: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [[ $1 == upgrade ]];then 4 | killall -9 mDNSResponder || true 5 | killall -9 mDNSResponderHelper || true 6 | fi -------------------------------------------------------------------------------- /layout/DEBIAN/postrm: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [[ "$1" == "remove" || "$1" == "abort-install" ]];then 4 | killall -9 mDNSResponder || true 5 | killall -9 mDNSResponderHelper || true 6 | fi -------------------------------------------------------------------------------- /layout/Library/libSandy/LetMeBlock.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | AllowedProcesses 6 | 7 | com.apple.mDNSResponder 8 | 9 | Conditions 10 | 11 | 12 | ConditionType 13 | FileExistance 14 | FilePath 15 | /var/jb/etc/hosts 16 | Negated 17 | 18 | 19 | 20 | Extensions 21 | 22 | 23 | type 24 | file 25 | extension_class 26 | com.apple.app-sandbox.read 27 | path 28 | /var/jb/etc/hosts 29 | 30 | 31 | 32 | --------------------------------------------------------------------------------