├── .gitignore ├── LICENSE ├── Makefile ├── README.md ├── SettingsWiFiPassword.plist ├── Tweak.S ├── Tweak.swift └── control /.gitignore: -------------------------------------------------------------------------------- 1 | .theos/ 2 | packages/ 3 | .DS_Store 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 Nightwind 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. -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | TARGET := iphone:clang:latest:14.0 2 | ARCHS = arm64 arm64e 3 | 4 | INSTALL_TARGET_PROCESSES = Preferences 5 | 6 | include $(THEOS)/makefiles/common.mk 7 | 8 | TWEAK_NAME = SettingsWiFiPassword 9 | 10 | SettingsWiFiPassword_FILES = Tweak.swift Tweak.S 11 | SettingsWiFiPassword_CFLAGS = -fobjc-arc 12 | 13 | include $(THEOS_MAKE_PATH)/tweak.mk 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SettingsWiFiPassword 2 | ### Compatible with iOS 11-15. 3 | Add a button to copy the WiFi password to the Settings app. 4 | 5 | ### How to install 6 | Head over to the [Releases](https://github.com/NightwindDev/SettingsWiFiPassword/releases) section and download the correct `.deb` for your device. 7 | 8 | ### How to compile manually 9 | Make sure you have [Theos](https://github.com/theos/theos) installed and configured. 10 | 11 | Clone the repo and run the command you need: 12 | ```bash 13 | # To build for rootful 14 | make clean package FINALPACKAGE=1 15 | # To build for rootless 16 | make clean package THEOS_PACKAGE_SCHEME=rootless FINALPACKAGE=1 17 | ``` 18 | 19 | #### License 20 | This project is licensed under [MIT](LICENSE). 21 | 22 | ###### Copyright (c) 2025 Nightwind -------------------------------------------------------------------------------- /SettingsWiFiPassword.plist: -------------------------------------------------------------------------------- 1 | { Filter = { Bundles = ( "com.apple.Preferences" ); }; } 2 | -------------------------------------------------------------------------------- /Tweak.S: -------------------------------------------------------------------------------- 1 | .mod_init_func 2 | .align 4 3 | .quad _swift_init -------------------------------------------------------------------------------- /Tweak.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2025 Nightwind 3 | // 4 | 5 | import UIKit 6 | import CydiaSubstrate 7 | 8 | @objc private protocol WFMutableNetworkProfile { 9 | @objc var ssid: String { get set } 10 | @objc var password: String { get set } 11 | } 12 | 13 | @objc private protocol WFSettingsController { 14 | @objc var profile: WFMutableNetworkProfile? { get set } 15 | } 16 | 17 | @objc private protocol WFNetworkSettingsViewController { 18 | @objc var navigationItem: UINavigationItem { get } 19 | @objc var dataCoordinator: WFSettingsController { get set } 20 | 21 | @objc(presentViewController:animated:completion:) 22 | func present(_ viewControllerToPresent: UIViewController, animated: Bool, completion: (() -> Void)?) 23 | } 24 | 25 | private struct Hooks { 26 | private static let targetClass: AnyClass = objc_getClass("WFNetworkSettingsViewController") as! AnyClass 27 | 28 | fileprivate static func hook() { 29 | var origIMP: IMP? 30 | 31 | let hook: @convention(block) (WFNetworkSettingsViewController, Selector) -> Void = { target, selector in 32 | let orig = unsafeBitCast(origIMP, to: (@convention(c) (WFNetworkSettingsViewController, Selector) -> Void).self) 33 | orig(target, selector) 34 | 35 | guard target.dataCoordinator.profile != nil else { return } 36 | 37 | guard let keyImage = UIImage(systemName: "lock.open") else { return } 38 | let topMenuButton = UIBarButtonItem(image: keyImage, style: .plain, target: target, action: sel_getUid("_swfp_handleShowPasswordClick:")) 39 | target.navigationItem.rightBarButtonItem = topMenuButton 40 | } 41 | 42 | MSHookMessageEx(targetClass, sel_getUid("viewDidLoad"), imp_implementationWithBlock(hook), &origIMP); 43 | } 44 | 45 | fileprivate static func addHandler() { 46 | let implementation: @convention(block) (WFNetworkSettingsViewController, Selector, UIBarButtonItem) -> Void = { target, selector, sender in 47 | guard let profile = target.dataCoordinator.profile else { return } 48 | 49 | let alert = UIAlertController(title: profile.ssid, message: profile.password, preferredStyle: .alert) 50 | 51 | let dismissAction = UIAlertAction(title: "Dismiss", style: .default) 52 | let copyAction = UIAlertAction(title: "Copy", style: .default, handler: { action in 53 | UIPasteboard.general.string = profile.password 54 | }) 55 | 56 | alert.addAction(dismissAction) 57 | alert.addAction(copyAction) 58 | 59 | alert.preferredAction = copyAction 60 | 61 | target.present(alert, animated: true, completion: nil) 62 | } 63 | 64 | class_addMethod(targetClass, sel_getUid("_swfp_handleShowPasswordClick:"), imp_implementationWithBlock(implementation), "v@:@") 65 | } 66 | } 67 | 68 | @_cdecl("swift_init") 69 | func tweakInit() { 70 | guard let bundle = Bundle(path: "/System/Library/PrivateFrameworks/WiFiKitUI.framework") else { return } 71 | if bundle.load() { 72 | Hooks.hook() 73 | Hooks.addHandler() 74 | } 75 | } -------------------------------------------------------------------------------- /control: -------------------------------------------------------------------------------- 1 | Package: com.nightwind.settingswifipassword 2 | Name: SettingsWiFiPassword 3 | Version: 0.0.1 4 | Architecture: iphoneos-arm 5 | Description: Add a button to copy the WiFi password to the Settings app. 6 | Maintainer: Nightwind 7 | Author: Nightwind 8 | Section: Tweaks 9 | Depends: mobilesubstrate (>= 0.9.5000), firmware (<< 16.0) 10 | --------------------------------------------------------------------------------