@Lakr233 wrote:
不知道各位有没有注意到一个很有一的情况,那就是越狱软件在注销桌面的时候多了一个选项,名字叫做“Reload System Daemon”。LaunchDaemon作为系统的守护者,有着神圣不可轻犯的权威。你每次kill一个守护者,作为boss代号为launchd的守护着就会负责重启他。当launchd被kill,你的设备就失去了用户环境,内核会立即panic。那怎样在不丢失用户态环境的情况下“重启设备”,并且不产生崩溃日志呢?答案也很简单,我们要让除了launchd以外的所有进程被爸爸干掉。
首先,我们需要导入头文件。能力有限,不一一叙述头文件。(我太菜了
#include <cstdio> #include <cstdlib> #include <errno.h> #include <signal.h> #include <sysexits.h> #include <unistd.h> #include <launch.h> #include <sys/stat.h>
继续我们在main里面添加代码。我们要做的事情有三件。
- 获取进程列表
- 让进程自己死去
- 清理环境并且自己结束自己
获取进程列表
我们需要先创建一个请求,然后发送请求给launchd。在获取到数据以后,便可以释放我们创建的请求。这里没有auto_release_pool所以要额外的小心。咱们的守护者会死去,所以可能没有人来搭理善后。内核能做的非常有限。
launch_data_t req = launch_data_new_string(LAUNCH_KEY_GETJOBS); launch_data_t res = launch_msg(req); launch_data_free(req);
接下来我们需要验证数据的合法性,检查他是否存在,并确认眼神撒
if (res == NULL || launch_data_get_type(res) != LAUNCH_DATA_DICTIONARY) return EPERM; // Error Permit
让我们来看看我们获取到了什么 这里的数据很有意思。
<OS_xpc_dictionary: dictionary[0x103089ca0]: { /* GREAT STUFF*/ }>
我们拿到了一份清单。接下来我们写一个自己的方法,并通过迭代器来让每一个进程都作为参数执行我们需要的代码。
void execEach(launch_data_t v1, const char *name, void *baton) launch_data_dict_iterate(res, &execEach, NULL); // 接力开始!
让进程自己死去
首先我们从迭代器传入的launch_data_t中提取进程pid,然后给他发送信号。
if (launch_data_get_type(v1) != LAUNCH_DATA_DICTIONARY) // 再次检查 return; launch_data_t _Nullable v2(launch_data_dict_lookup(v1, LAUNCH_JOBKEY_PID)); if (v2 == NULL || launch_data_get_type(v2) != LAUNCH_DATA_INTEGER) // 检查pid data return; // 并不觉得我们需要这个但是做作更健康 long long qaqPID = launch_data_get_integer(v2); // 从data获取PID if (kill(qaqPID, 0) == -1) return; // 我们没有权限给他发送信号,差不多就是一些boos了。
那么问题来了,为什么我们不kill(qaqPID, 9)呢?因为这样进程就会产生一个没有被handle的sig,进而被其他守护者或kernel捕捉产生crash log。我们发送0的意义在于检查这个进程是不是真的需要被kill我们有没有能力让他kill以避免ldrestart在执行过程中崩溃。
接着我们获取进程在注册字典中的名字。
launch_data_t _Nullable v3 = launch_data_dict_lookup(v1, LAUNCH_JOBKEY_LABEL); if (v3 == NULL || launch_data_get_type(v3) != LAUNCH_DATA_STRING) return; // 通用检查
接下来到了让他自己死去的环节了。我们创建一个请求并发送。
launch_data_t dadHere = launch_data_alloc(LAUNCH_DATA_DICTIONARY); // 分配一个data // 在爸爸指令里面插入停止代码 lol 注意v3是进程标识符 他是launch_data_t auto hi(launch_data_dict_insert(dadHere, v3, LAUNCH_KEY_STOPJOB)); auto rettt(launch_msg(dadHere)); // 好了 结束了 他已经躺好了 轮到我们善后自己了 launch_data_t 似乎都需要手动释放 launch_data_free(dadHere); launch_data_free(rettt);
这种方式同样适用于检测到越狱以后无crash无追踪退出,但是具体的实现这里就不详细叙述了。
另外,现在还有更加优秀的sbreload来加速桌面环境的刷新。一般来说越狱开发者注销桌面有四个选择,按照推荐顺序分别是【sbreload】【ldrestart】【killall backboardd】【killall SpringBoard】。sbreload用户体验应该是最好的,ldrestart更加彻底。而干掉backboardd一定程度上解决的SpringBoard死得不够彻底的问题,也能够很神奇的解决一些循环等待SpringBoard加载而锁死的问题。虽然SpringBoard有超时自动kill的机制,但是这个时间经测试大概在5分钟左右。>> iOS 11.3.1
有错误还请各位指出咯。
Posts: 1
Participants: 1