├── Android.mk ├── UidCtrl ├── hardware │ └── nfc.h ├── Application.mk ├── logging.hpp ├── main.cpp ├── hook.hpp ├── Android.mk ├── logging.cpp └── hook.cpp ├── .gitmodules ├── Application.mk ├── README.md └── LICENSE /Android.mk: -------------------------------------------------------------------------------- 1 | MY_LOCAL_PATH := $(call my-dir) 2 | 3 | # Build dynamic library 4 | include $(MY_LOCAL_PATH)/UidCtrl/Android.mk 5 | 6 | # Build Injector Module 7 | include $(MY_LOCAL_PATH)/TinyInjector/Android.mk -------------------------------------------------------------------------------- /UidCtrl/hardware/nfc.h: -------------------------------------------------------------------------------- 1 | /* 2 | * DO NOT REMOVE THIS FILE !!! 3 | * DO NOT REMOVE THIS FILE !!! 4 | * DO NOT REMOVE THIS FILE !!! 5 | * 6 | * THIS FILE FIXED FILE INCLUDE ERROR IN FILE: 7 | * android_system_nfc/src/hal/include/nfc_hal_api.h 8 | */ -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "TinyInjector"] 2 | path = TinyInjector 3 | url = https://github.com/shunix/TinyInjector.git 4 | [submodule "UidCtrl/xHook"] 5 | path = UidCtrl/xHook 6 | url = https://github.com/iqiyi/xHook.git 7 | [submodule "UidCtrl/android_system_nfc"] 8 | path = UidCtrl/android_system_nfc 9 | url = https://github.com/LineageOS/android_system_nfc.git 10 | -------------------------------------------------------------------------------- /Application.mk: -------------------------------------------------------------------------------- 1 | APP_ABI := armeabi-v7a arm64-v8a 2 | APP_OPTIM := release 3 | APP_PLATFORM := android-21 4 | APP_STL := system 5 | APP_CPPFLAGS := -std=c++1y 6 | APP_THIN_ARCHIVE := true 7 | 8 | ifneq ($(APP_OPTIM), debug) 9 | $(info APP_OPTIM is $(APP_OPTIM) ...) 10 | APP_LDFLAGS += -Wl,--strip-all 11 | APP_CFLAGS += -fvisibility=hidden -fvisibility-inlines-hidden -g0 -O3 12 | APP_CFLAGS += -fomit-frame-pointer -ffunction-sections -fdata-sections 13 | endif 14 | -------------------------------------------------------------------------------- /UidCtrl/Application.mk: -------------------------------------------------------------------------------- 1 | APP_ABI := armeabi-v7a arm64-v8a 2 | APP_OPTIM := release 3 | APP_PLATFORM := android-21 4 | APP_STL := system 5 | APP_CPPFLAGS := -std=c++1y 6 | APP_THIN_ARCHIVE := true 7 | 8 | ifneq ($(APP_OPTIM), debug) 9 | $(info APP_OPTIM is $(APP_OPTIM) ...) 10 | APP_LDFLAGS += -Wl,--strip-all 11 | APP_CFLAGS += -fvisibility=hidden -fvisibility-inlines-hidden -g0 -O3 12 | APP_CFLAGS += -fomit-frame-pointer -ffunction-sections -fdata-sections 13 | endif 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 1. 简介 2 | 3 | 通过注入到 __com.android.nfc__ 进程,调用libnfc-nci.so的函数来设置UID(NFCID1)。 4 | 5 | 2. 用到的库 6 | 7 | [TinyInjector](https://github.com/shunix/TinyInjector),一个开源的Android注入工具。 8 | 9 | [xHook](https://github.com/iqiyi/xHook),iqiyi开源的一个Android PLT Hook库。 10 | 11 | [android_system_nfc](https://github.com/LineageOS/android_system_nfc),libnfc-nci.so的源代码,用到了里面的一些头文件。 12 | 13 | 3. 测试方法 14 | 15 | * 将项目克隆到本地,在项目根目录使用ndk-build进行编译。 16 | * 将编译好的injector与libuidctrl.so传输到手机/data/local/tmp/目录下,并授予injector可执行权限。 17 | * 以root身份执行/data/local/tmp/injector com.android.nfc /data/local/tmp/libuidctrl.so。 18 | -------------------------------------------------------------------------------- /UidCtrl/logging.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by joe on 19-4-7. 3 | // 4 | 5 | #ifndef UIDCTRL_LOG_HPP 6 | #define UIDCTRL_LOG_HPP 7 | 8 | 9 | class Log { 10 | public: 11 | enum LOG_LEVEL { 12 | LOG_LEVEL_INFO, 13 | LOG_LEVEL_DEBUG, 14 | LOG_LEVEL_ERROR, 15 | LOG_LEVEL_NONE 16 | }; 17 | 18 | private: 19 | LOG_LEVEL m_log_level; 20 | 21 | public: 22 | static Log &getInstance(LOG_LEVEL level = LOG_LEVEL_NONE); 23 | 24 | void printf(const LOG_LEVEL level, const char *tag, const char *fmt, ...); 25 | 26 | void print(const LOG_LEVEL level, const char *tag, const char *text); 27 | 28 | LOG_LEVEL getLogLevel() const; 29 | 30 | void setLogLevel(const LOG_LEVEL); 31 | 32 | private: 33 | Log(LOG_LEVEL); 34 | 35 | Log(const Log &) {} 36 | 37 | ~Log() {}; 38 | 39 | Log &operator=(const Log &) {} 40 | 41 | }; 42 | 43 | 44 | #endif //UIDCTRL_LOG_HPP 45 | -------------------------------------------------------------------------------- /UidCtrl/main.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by joe on 19-1-2. 3 | // 4 | 5 | #include "logging.hpp" 6 | #include "hook.hpp" 7 | 8 | const char LOG_TAG[] = "UIDCTRL:main ==> "; 9 | 10 | 11 | void __attribute__ ((constructor)) main_entry() { 12 | // init Log Singleton instance with verbose info level 13 | Log::getInstance(Log::LOG_LEVEL_INFO); 14 | 15 | /*********************************test logical*********************************/ 16 | Log &log = Log::getInstance(); 17 | log.print(Log::LOG_LEVEL_INFO, LOG_TAG, "entry in"); 18 | Hook &hook = Hook::getInstance(true); 19 | hook.hook(); 20 | if(hook.isHooked()){ 21 | uint8_t uid[4] = {0x4d, 0xf7, 0xf4, 0x40}; // four byte NFCID1 22 | hook.setNfcId(uid); 23 | } 24 | log.print(Log::LOG_LEVEL_INFO, LOG_TAG, "entry out"); 25 | /*********************************test logical*********************************/ 26 | 27 | return; 28 | } 29 | -------------------------------------------------------------------------------- /UidCtrl/hook.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by joe on 19-4-7. 3 | // 4 | 5 | #ifndef UIDCTRL_HOOK_HPP 6 | #define UIDCTRL_HOOK_HPP 7 | 8 | 9 | #include "logging.hpp" 10 | #include 11 | #include 12 | 13 | class Hook { 14 | private: 15 | bool m_hook; 16 | bool m_cpp; 17 | pthread_mutex_t m_hook_mutex; 18 | Log &log = Log::getInstance(); 19 | 20 | public: 21 | static Hook &getInstance(bool cpp = true); 22 | 23 | void hook(); 24 | 25 | // third-party library xHook does not support unhook currently 26 | // void dehook(); 27 | 28 | bool setNfcId(uint8_t *uid); 29 | 30 | bool isHooked(); 31 | 32 | bool isCpp() const; 33 | 34 | private: 35 | Hook(bool cpp) : m_hook(false), m_cpp(cpp) { 36 | pthread_mutex_init(&m_hook_mutex, nullptr); 37 | } 38 | 39 | ~Hook() { 40 | pthread_mutex_destroy(&m_hook_mutex); 41 | }; 42 | 43 | Hook(const Hook &) {} 44 | 45 | Hook &operator=(const Hook &) {} 46 | }; 47 | 48 | 49 | #endif //UIDCTRL_HOOK_HPP 50 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Pikachu 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. 22 | -------------------------------------------------------------------------------- /UidCtrl/Android.mk: -------------------------------------------------------------------------------- 1 | LOCAL_PATH := $(call my-dir) 2 | 3 | include $(CLEAR_VARS) 4 | 5 | LOCAL_MODULE := uidctrl 6 | LOCAL_SRC_FILES := main.cpp \ 7 | logging.cpp \ 8 | hook.cpp 9 | 10 | LOCAL_SRC_FILES += xHook/libxhook/jni/xhook.c \ 11 | xHook/libxhook/jni/xh_core.c \ 12 | xHook/libxhook/jni/xh_elf.c \ 13 | xHook/libxhook/jni/xh_jni.c \ 14 | xHook/libxhook/jni/xh_log.c \ 15 | xHook/libxhook/jni/xh_util.c \ 16 | xHook/libxhook/jni/xh_version.c 17 | 18 | LOCAL_C_INCLUDES += $(LOCAL_PATH) 19 | LOCAL_C_INCLUDES += $(LOCAL_PATH)/android_system_nfc/halimpl/bcm2079x/include 20 | LOCAL_C_INCLUDES += $(LOCAL_PATH)/android_system_nfc/halimpl/bcm2079x/gki/ulinux 21 | LOCAL_C_INCLUDES += $(LOCAL_PATH)/android_system_nfc/halimpl/bcm2079x/gki/common 22 | LOCAL_C_INCLUDES += $(LOCAL_PATH)/android_system_nfc/halimpl/bcm2079x/adaptation 23 | LOCAL_C_INCLUDES += $(LOCAL_PATH)/android_system_nfc/src/hal/include 24 | LOCAL_C_INCLUDES += $(LOCAL_PATH)/android_system_nfc/src/hal/int 25 | LOCAL_C_INCLUDES += $(LOCAL_PATH)/android_system_nfc/src/nfc/include 26 | LOCAL_C_INCLUDES += $(LOCAL_PATH)/android_system_nfc/src/nfa/include 27 | LOCAL_C_INCLUDES += $(LOCAL_PATH)/android_system_nfc/src/nfa/int 28 | LOCAL_C_INCLUDES += $(LOCAL_PATH)/android_system_nfc/src/udrv/include 29 | LOCAL_C_INCLUDES += $(LOCAL_PATH)/android_system_nfc/src/include 30 | LOCAL_C_INCLUDES += $(LOCAL_PATH)/xHook/libxhook/jni 31 | 32 | 33 | LOCAL_CFLAGS := -Wno-unused-parameter -fno-rtti -fno-exceptions \ 34 | -Wno-deprecated-register -fpermissive 35 | 36 | LOCAL_LDLIBS := -llog 37 | 38 | include $(BUILD_SHARED_LIBRARY) 39 | 40 | -------------------------------------------------------------------------------- /UidCtrl/logging.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by joe on 19-4-7. 3 | // 4 | 5 | #include "logging.hpp" 6 | #include 7 | #include 8 | 9 | Log &Log::getInstance(LOG_LEVEL level) { 10 | static Log log(level); 11 | return log; 12 | } 13 | 14 | void Log::print(const Log::LOG_LEVEL level, const char *tag, const char *text) { 15 | if (level < m_log_level || level == LOG_LEVEL_NONE) 16 | return; 17 | 18 | android_LogPriority prio; 19 | switch (level) { 20 | case LOG_LEVEL_INFO: 21 | prio = ANDROID_LOG_VERBOSE; 22 | break; 23 | case LOG_LEVEL_DEBUG: 24 | prio = ANDROID_LOG_DEBUG; 25 | break; 26 | case LOG_LEVEL_ERROR: 27 | prio = ANDROID_LOG_ERROR; 28 | break; 29 | default: 30 | prio = ANDROID_LOG_UNKNOWN; 31 | break; 32 | } 33 | 34 | __android_log_write(prio, tag, text); 35 | } 36 | 37 | void Log::printf(const LOG_LEVEL level, const char *tag, const char *fmt, ...) { 38 | if (level < m_log_level || level == LOG_LEVEL_NONE) 39 | return; 40 | 41 | android_LogPriority prio; 42 | switch (level) { 43 | case LOG_LEVEL_INFO: 44 | prio = ANDROID_LOG_VERBOSE; 45 | break; 46 | case LOG_LEVEL_DEBUG: 47 | prio = ANDROID_LOG_DEBUG; 48 | break; 49 | case LOG_LEVEL_ERROR: 50 | prio = ANDROID_LOG_ERROR; 51 | break; 52 | default: 53 | prio = ANDROID_LOG_UNKNOWN; 54 | break; 55 | } 56 | 57 | va_list args; 58 | va_start(args, fmt); 59 | __android_log_vprint(prio, tag, fmt, args); 60 | va_end(args); 61 | } 62 | 63 | Log::Log(Log::LOG_LEVEL level) { 64 | m_log_level = level; 65 | } 66 | 67 | Log::LOG_LEVEL Log::getLogLevel() const { 68 | return m_log_level; 69 | } 70 | 71 | void Log::setLogLevel(const Log::LOG_LEVEL level) { 72 | m_log_level = level; 73 | } 74 | 75 | -------------------------------------------------------------------------------- /UidCtrl/hook.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by joe on 19-4-7. 3 | // 4 | 5 | #include "hook.hpp" 6 | #include 7 | #include "xhook.h" 8 | 9 | #define HOOK_MACRO(FUN) xhook_register(".*libnfc-nci\\.so$", (#FUN), \ 10 | reinterpret_cast(my_##FUN), \ 11 | reinterpret_cast(&sys_##FUN)); 12 | 13 | //#define DEHOOK_MACRO(FUN) xhook_register(".*libnfc-nci\\.so$", (#FUN), \ 14 | // reinterpret_cast(sys_##FUN), nullptr); 15 | 16 | const char LOG_TAG[] = "UIDCTRL:hook ==> "; 17 | 18 | 19 | /**************** function pointer backup for C and CPP symbol ****************/ 20 | tNFC_STATUS (*sys_NFC_Deactivate)(tNFC_DEACT_TYPE deactivate_type); 21 | 22 | bool (*sys_nfa_dm_set_config)(tNFA_DM_MSG *p_data); 23 | 24 | // CPP 25 | tNFC_STATUS (*sys__Z14NFC_Deactivateh)(tNFC_DEACT_TYPE deactivate_type); 26 | 27 | bool (*sys__Z17nfa_dm_set_configP11tNFA_DM_MSG)(tNFA_DM_MSG *p_data); 28 | /******************************************************************************/ 29 | 30 | /********************** custom func for C and CPP symbol **********************/ 31 | static tNFC_STATUS my_NFC_Deactivate(tNFC_DEACT_TYPE deactivate_type) { 32 | Log &log = Log::getInstance(); 33 | log.print(Log::LOG_LEVEL_INFO, LOG_TAG, "my_NFC_Deactivate called"); 34 | tNFC_STATUS ret = sys_NFC_Deactivate(deactivate_type); 35 | if (ret != NFC_STATUS_OK) 36 | log.printf(Log::LOG_LEVEL_ERROR, LOG_TAG, "my_NFC_Deactivate return with %u", ret); 37 | return ret; 38 | } 39 | 40 | static bool my_nfa_dm_set_config(tNFA_DM_MSG *p_data) { 41 | Log &log = Log::getInstance(); 42 | log.print(Log::LOG_LEVEL_INFO, LOG_TAG, "my_nfa_dm_set_config called"); 43 | bool ret = sys_nfa_dm_set_config(p_data); 44 | if (!ret) 45 | log.printf(Log::LOG_LEVEL_ERROR, LOG_TAG, "my_nfa_dm_set_config return with %u", ret); 46 | return ret; 47 | } 48 | 49 | // CPP 50 | static tNFC_STATUS my__Z14NFC_Deactivateh(tNFC_DEACT_TYPE deactivate_type) { 51 | Log &log = Log::getInstance(); 52 | log.print(Log::LOG_LEVEL_INFO, LOG_TAG, "my__Z14NFC_Deactivateh called"); 53 | tNFC_STATUS ret = sys__Z14NFC_Deactivateh(deactivate_type); 54 | if (ret != NFC_STATUS_OK) 55 | log.printf(Log::LOG_LEVEL_ERROR, LOG_TAG, "my__Z14NFC_Deactivateh return with %u", ret); 56 | return ret; 57 | } 58 | 59 | static bool my__Z17nfa_dm_set_configP11tNFA_DM_MSG(tNFA_DM_MSG *p_data) { 60 | Log &log = Log::getInstance(); 61 | log.print(Log::LOG_LEVEL_INFO, LOG_TAG, \ 62 | "my__Z17nfa_dm_set_configP11tNFA_DM_MSG called"); 63 | bool ret = sys__Z17nfa_dm_set_configP11tNFA_DM_MSG(p_data); 64 | if (!ret) 65 | log.printf(Log::LOG_LEVEL_ERROR, LOG_TAG, 66 | "my__Z17nfa_dm_set_configP11tNFA_DM_MSG return with %u", ret); 67 | return ret; 68 | } 69 | 70 | /******************************************************************************/ 71 | 72 | Hook &Hook::getInstance(bool cpp) { 73 | static Hook hook(cpp); 74 | return hook; 75 | } 76 | 77 | void Hook::hook() { 78 | pthread_mutex_lock(&m_hook_mutex); 79 | 80 | if (!m_hook) { 81 | xhook_enable_debug(log.getLogLevel() == Log::LOG_LEVEL_NONE ? 0 : 1); 82 | if (m_cpp) { 83 | // CPP 84 | HOOK_MACRO(_Z14NFC_Deactivateh); 85 | HOOK_MACRO(_Z17nfa_dm_set_configP11tNFA_DM_MSG); 86 | } else { 87 | // C 88 | HOOK_MACRO(NFC_Deactivate); 89 | HOOK_MACRO(nfa_dm_set_config); 90 | 91 | } 92 | xhook_refresh(0); 93 | m_hook = true; 94 | } 95 | 96 | pthread_mutex_unlock(&m_hook_mutex); 97 | } 98 | 99 | //void Hook::dehook() { 100 | // pthread_mutex_lock(&m_hook_mutex); 101 | // 102 | // if (m_hook) { 103 | // if (m_cpp) { 104 | // // CPP 105 | // DEHOOK_MACRO(_Z14NFC_Deactivateh); 106 | // DEHOOK_MACRO(_Z17nfa_dm_set_configP11tNFA_DM_MSG); 107 | // } else { 108 | // // C 109 | // DEHOOK_MACRO(NFC_Deactivate); 110 | // DEHOOK_MACRO(nfa_dm_set_config); 111 | // } 112 | // xhook_refresh(0); 113 | // m_hook = false; 114 | // } 115 | // 116 | // pthread_mutex_unlock(&m_hook_mutex); 117 | //} 118 | 119 | bool Hook::isHooked() { 120 | pthread_mutex_lock(&m_hook_mutex); 121 | bool status = m_hook; 122 | pthread_mutex_unlock(&m_hook_mutex); 123 | 124 | return status; 125 | } 126 | 127 | bool Hook::isCpp() const { 128 | return m_cpp; 129 | } 130 | 131 | bool Hook::setNfcId(uint8_t *uid) { 132 | bool status = false; 133 | uint8_t buffer[32] = {0}; 134 | uint8_t *p = buffer; 135 | tNFA_DM_MSG data; 136 | 137 | UINT8_TO_STREAM(p, uid[0]); 138 | UINT8_TO_STREAM(p, uid[1]); 139 | UINT8_TO_STREAM(p, uid[2]); 140 | UINT8_TO_STREAM(p, uid[3]); 141 | data.setconfig = tNFA_DM_API_SET_CONFIG{{}, NFC_PMID_LA_NFCID1, (uint8_t) (p - buffer), buffer}; 142 | 143 | // sleep(1); 144 | pthread_mutex_lock(&m_hook_mutex); 145 | do { 146 | if (m_hook) { 147 | if (m_cpp) { 148 | if (my__Z14NFC_Deactivateh(NFC_DEACTIVATE_TYPE_IDLE) != NFC_STATUS_OK) 149 | break; 150 | if (!my__Z17nfa_dm_set_configP11tNFA_DM_MSG(&data)) 151 | break; 152 | if (my__Z14NFC_Deactivateh(NFC_DEACTIVATE_TYPE_DISCOVERY) != NFC_STATUS_OK) 153 | break; 154 | } else { 155 | if (my_NFC_Deactivate(NFC_DEACTIVATE_TYPE_IDLE) != NFC_STATUS_OK) 156 | break; 157 | if (!my_nfa_dm_set_config(&data)) 158 | break; 159 | if (my_NFC_Deactivate(NFC_DEACTIVATE_TYPE_DISCOVERY) != NFC_STATUS_OK) 160 | break; 161 | } 162 | status = true; 163 | } 164 | } while (false); 165 | pthread_mutex_unlock(&m_hook_mutex); 166 | 167 | return status; 168 | } 169 | --------------------------------------------------------------------------------