αα½ααααΈ α αΆα! ααααααααααα»αα αααα·ααΆαα’αααΈαααααααα’αααα’αΆα ααΆαααΆαααααΎαααΆαααΈααΆαααΆααααα αΆααααα’αααααΆααααα αΆααα αααα»α macOS α α§ααΆα ααα ααΆααΆααααααααααααααΆααααααααααααα αΆααααααα α¬ααααααααααααα»ααα»α ααΆαα·αααα αΆααααΆααααΈαα ααααα macOS ααΆααα·ααΈααΆα αααΎαααΎααααΈ "αααααΆαα" ααααΎαααΆααα½αα α’αΆαα’αααΈαααα αΆααααα·ααα·ααΈααΆαααααααΆαααΆααα αααααααΆαααΆααα
αα·ααΈαα»ααΆαααΎααααΈ "αααααΆαα" ααααΎαααΆααα½αα
αααααααΆαααααααΈαα½αααΎααααΈ "αααααΆαα" ααααΎαααΆαααΊααΆααααααΌααααααΆ SIGKILL αα ααΆααααααΎαααΆαα ααΆαααα bash α’αααα’αΆα α α αααααααΆα "αααααΆαα -SIGKILL PID" α¬ "pkill -9 NAME" ααΎααααΈαααααΆααα ααΆααααααααΆ "αααααΆαα" ααααΌαααΆαααααααΆααααΆααααΈααααααΌααΈα α αΎαααΆααα·αααααΉααααα ααΎ macOS ααα»ααααααα ααα»ααααααααΆααα ααΎααααααααααααααααΉαααΌααΈααααααααααααααα
ααΌα αα αααα»αααααααααααΌα UNIX ααα macOS α’αα»ααααΆαα±ααα’αααααααΆααα αΆαααααααΆααΆαα½ααα ααΆααααααΎαααΆααα½α ααΎααααααααΈα - SIGKILL αα·α SIGSTOP α α’ααααααααααΉααααααααΆα ααααααΎαααααΆ SIGKILL ααΆαααααΆααααααααΆαα±ααααααΎαααΆααα½αααααΌαααΆααααααΆααα
αααααααα·ααα macOS
αα ααΎ macOS ααΆαα α αααααααααααααΆαααα αααα»αααΊααα XNU α α αα»αααΆα psignal(SIGKILL,...)α αααααααΆααΆαααΎαααΆααΎαααααααΆαααααα’αααααααΎαααααααααα αααα»α userspace α’αΆα ααααΌαααΆαα α ααααα»αααΆα psignal α α αΌααα»αααΆαα α αα ααΆαααα»αααΆα psignal αα αααα»αααααααΆαααΆααααα»αααααΊααα (αααααΈααΆααΆα’αΆα αα·ααααααΆααΏαααΌα ααΆα ααααα ααΎαααΉααα»αααΆαααααΆααα’ααααααα½ααααπ .
α
αΌαα
αΆααααααΎαααΆααα·αα·αααα‘αΎααα·αααΆαα½αααΉααα»αααΆα αα·αααΆαα α
αααααααααααααααΌαααααΆα
static int
terminate_with_payload_internal(struct proc *cur_proc, int target_pid, uint32_t reason_namespace,
uint64_t reason_code, user_addr_t payload, uint32_t payload_size,
user_addr_t reason_string, uint64_t reason_flags)
{
...
target_proc = proc_find(target_pid);
...
if (!cansignal(cur_proc, cur_cred, target_proc, SIGKILL)) {
proc_rele(target_proc);
return EPERM;
}
...
if (target_pid == cur_proc->p_pid) {
/*
* psignal_thread_with_reason() will pend a SIGKILL on the specified thread or
* return if the thread and/or task are already terminating. Either way, the
* current thread won't return to userspace.
*/
psignal_thread_with_reason(target_proc, current_thread(), SIGKILL, signal_reason);
} else {
psignal_with_reason(target_proc, SIGKILL, signal_reason);
}
...
}
ααΆαααΎαααααΎαααΆα
αα·ααΈαααααααΆαααΎααααΈαααααΎααααα·ααα αααα αΆααααααΎααααααααα αα·ααααααααααα’αΆαα»ααΆααααααα½αααααααΌαααΆαααΎαααααΎαααΆαα ααΌαα αααΆαααΆαααααααΊαααααΆααααααα αΆαααααα launchctl αα αΌαααα macOS 10.10 α§ααΆα αααααΌαααααΌαααΆααααααααΌααααααΆαααααααααααΆα§ααΆα αααα launchctl ααααΎααααααΌααααααΆααΎαααααΎαααΆαααΆαααα XPC, launchctl logic ααααΌαααΆαααααΆααααΈαα ααΆα
ααΌααααα‘ααααΎαααΆααΎαααααα·ααΈααααΌαααΆααααααααααααααααΆα αα»ααααααααΎαααααΆ SIGTERM αααααα·ααΈααααΌαααΆαααααΆααΆααααααααααααααΎααΆαα α ααΆααααααααα "proc_terminate" α
<launchctl src/core.c>
...
error = proc_terminate(j->p, &sig);
if (error) {
job_log(j, LOG_ERR | LOG_CONSOLE, "Could not terminate job: %d: %s", error, strerror(error));
job_log(j, LOG_NOTICE | LOG_CONSOLE, "Using fallback option to terminate job...");
error = kill2(j->p, SIGTERM);
if (error) {
job_log(j, LOG_ERR, "Could not signal job: %d: %s", error, strerror(error));
}
...
<>
αα ααααααααααΆααααα proc_terminate αααααΈααΆαααααααααααΆααααα α’αΆα ααααΎαα·αααααΉααα psignal ααΆαα½α SIGTERM ααα»αααααααααα»αααααααααΆαα SIGKILL αααααα
ααΆααααααΆααααααααααα - ααααααααααααΆα
ααααΈαα½αα±ααα
αΆααα’αΆαααααααααααααααα’αΆα
ααααΌαααΆαααααΎαααΎααα
αααα»αααΆαα α
ααΆαααααααααααααααααα
αααααΈααΆααΆαα α
ααΆααααααααααααα’αΆα
αααααΆααααααΎαααΆαααααα αααααααααααα·αααΆααα·αα·αααα±ααααΆααααααααααΆααααΌααα·αααα·ααααααΎαααΆαα α
ααΌαααααααα
αααααααααααααα αα·αα·αααααΆααααααα
ααΌα ααααα αΎα ααααα·αααΎα’ααα "ααααα" ααΌααΆααααΆαααααΎααααΆαα CPU αααααααααα·ααΈ (α§ααΆα ααα α’αα»ααααΆαα±ααααααΎαααΆαααααΉααα 1 ns) αααα’αααα’αΆα αααααΆααααααΎαααΆαααΆαα½ααα αααα»αααααααααααΆαα ααΌα αααα αααααα’αΆα αααααΆααααααΎαααΆαααΆαα½ααα ααΎαααααααα αα½αααΆααααααΎαααΆαααα αΆααααααααααααα αα½αα±ααα αΆααα’αΆαααααααααααααΊα₯αααα·αααααααΎαα‘αΎααα ααααααααΆααααααΎαααΆαααΆαα½α pid 1 (launchctl) - ααΊααααααααααααααααα αααααααΆααΆαααααΎαααΆααααααΆ SIGKILL :)
ααΎααααΌααααααααΆααααα αΆαααααααααΆ?
αααααααΆαααααααααα»ααααα»αααΆααααααααΆααααααΎαααΆααα½αααΈααΆααααααΆααααΊααΎααααΈαααα½αααααα·α αα»αααΆααα αααα»αααΆααΆαα α ααααααααα ααΆα’αα»αα αα·ααΈααΆααααααααααΊαα·αααααΆαααααααΆααα ααα»ααααΆα αααΎαα
ααΈαα½α αα·αα·ααααααααΆααααααααααααααΈααΆααα’αααα αα αΆααααα sysent ααΊαα·αααααΉαααα―αααα αααααα·αα·ααααααααΆααΊααα XNU ααα»ααααααα ααα»αααααα·αα’αΆα ααααΎααα αααα»ααα·αα·ααααααααΆααΊααααααααα α’αααααΉαααααΌαααααΎαα·ααΈααΆααααααααααααααΆαααααααααα»ααα ααΌα ααΆααΆαααααΆα ααα»αααΆααααααΆααααα αα·ααααααααααααα·α αα αααα»αααΆα
ααΈααΈα αα
ααΆααααααααααααΆαα»αα
αααα»αααΆααΆαα’αΆαααααααΎααααααααΊαααααααΌαααΆαα
αααααα ααααα·αααΎααα CONFIG_REQUIRES_U32_MUNGING ααααΌαααΆααααααΆα ααα ααααα
ααΆααααααααααΉαααααΌαααΆαααααΆααααααΌα - ααΆααααααααα½αααΉαααααΌαααΆααααααα
struct sysent { /* system call table */
sy_call_t *sy_call; /* implementing function */
#if CONFIG_REQUIRES_U32_MUNGING || (__arm__ && (__BIGGEST_ALIGNMENT__ > 4))
sy_munge_t *sy_arg_munge32; /* system call arguments munger for 32-bit process */
#endif
int32_t sy_return_type; /* system call return types */
int16_t sy_narg; /* number of args */
uint16_t sy_arg_bytes; /* Total size of arguments in bytes for
* 32-bit system calls
*/
};
ααΆααααΆαααα’αα αααα»αααααααααΎααα macOS Apple αααααααΌα API ααααΈαααααΆααααααΎααΆαααΆαα½αααααΎαααΆαα Endpoint Security API α’αα»ααααΆαα±ααα’αα·αα·ααα’αα»ααααΆαααααΎααΆα αααΎααα ααΆααααααΎαααΆαααααααααα ααΌα αααα α’αααα’αΆα αα·ααααααΆααΆαα½ααααααΆααααααΎαααΆα αα½αααΆαααααααΆ SIGKILL αααααααΎ API αααααΆααααααΆααααΆαααΎα
#include <bsm/libbsm.h>
#include <EndpointSecurity/EndpointSecurity.h>
#include <unistd.h>
int main(int argc, const char * argv[]) {
es_client_t* cli = nullptr;
{
auto res = es_new_client(&cli, ^(es_client_t * client, const es_message_t * message) {
switch (message->event_type) {
case ES_EVENT_TYPE_AUTH_SIGNAL:
{
auto& msg = message->event.signal;
auto target = msg.target;
auto& token = target->audit_token;
auto pid = audit_token_to_pid(token);
printf("signal '%d' sent to pid '%d'n", msg.sig, pid);
es_respond_auth_result(client, message, pid == getpid() ? ES_AUTH_RESULT_DENY : ES_AUTH_RESULT_ALLOW, false);
}
break;
default:
break;
}
});
}
{
es_event_type_t evs[] = { ES_EVENT_TYPE_AUTH_SIGNAL };
es_subscribe(cli, evs, sizeof(evs) / sizeof(*evs));
}
printf("%dn", getpid());
sleep(60); // could be replaced with other waiting primitive
es_unsubscribe_all(cli);
es_delete_client(cli);
return 0;
}
ααααααααααΆαααααα αααααΆααα MAC α’αΆα ααααΌαααΆαα α»αααααααα αααα»αααΊααα αααααααααα·ααΈααΆαααααααΆαααΆααααααΆ (αααααΆααα proc_check_signal) ααα»αααα API αα·αααααΌαααΆαααΆααααααΆααααΌαααΆαααα
ααΆαααΆαααΆααααααααααααααΊαααα
ααααααααΈααΎααΆαααΆαααΆαααααΎαααΆααα αααα»ααααααααα ααΆαααΆαααΆααααααααααααααΊααααααα½αααΆ (kext) ααα αΆαααΆα ααααααα macOS αααααβααΌαβααααααααβαα½αβαααααΆααβα’αααβα’αα·ααααααβααΎααααΈβααΆααααα½αβαααααΎαβαααααα·ααΈβαααααΆβα§ααααα IOKitα ααααααααΈααΎααΆααααααα§ααααααααααΆααααααΎααΆαααΆαα½αα§ααααα IOKit αααααααΌααα·ααΈααΆααααααααααΆααααΆαααααααααα·ααΈαααααΆαααααααΎα§ααΆα αααααααααΆαα C ++ α αααααα·ααΈαα½ααα αααα»α userspace ααΉαα’αΆα "ααααααα" instance αααααΆαα α»αααααααα class ααΎααααΈαααααΎαααααΆαααααα kernel-userspaceα
ααΎααααΈβααβααΎαβα ααα½α class instances αααα»αβαααααααα ααΆαβα§αααααβααααΎααααΆαα ioclasscount α
my_kext_ioservice = 1
my_kext_iouserclient = 1
αααααααααααααΊαααααΆαα½ααααα ααα α»ααααααααΆαα½αααααααααα·ααΈαααααΆααααΌααααααααΆαααααΆαααααααα½αααααααΈ IOService α§ααΆα ααα my_kext_ioservice αααα»αααααΈαααα ααΆαααααΆαααααααα·ααΈα’αααααααΎααααΆαααααααΆαα±ααααΆαααΆααααααΎα instance ααααΈαα class αααααα½αααααααΈ IOUserClient αααα»αα§ααΆα ααα my_kext_iouserclient α
αα αααααααΆααΆααααααααα·ααΈαααααΆα ααααΈαααααααα (ααΆααααααααΆ kextunload) αα»αααΆααα·αααα·α "bool terminate(IOOptionBits options)" ααααΌαααΆαα α α ααΆαααααααααΆααα αΎααααα»αααΆααααα‘αααα·ααα·ααα ααΎααΆαα α ααΌααααααααΎααααΈαααα αααα αααααααΆααΆα unload ααΎααααΈαα·α kextunload α
bool Kext::terminate(IOOptionBits options)
{
if (!IsUnloadAllowed)
{
// Unload is not allowed, returning false
return false;
}
return super::terminate(options);
}
ααα IsUnloadAllowed α’αΆα ααααΌαααΆααααααααα IOUserClient αα ααααααα»αα αα ααααααααΆαααααααααααΆααα αααααΆααααααααΆ kextunload ααΉααααα‘ααααααααααΌα ααΆααααααα
admin@admins-Mac drivermanager % sudo kextunload ./test.kext
Password:
(kernel) Can't remove kext my.kext.test; services failed to terminate - 0xe00002c7.
Failed to unload my.kext.test - (iokit/common) unsupported function.
ααΆαααΆαααΆαααααααααααΆααααΌαααααααΎα‘αΎααααααΆαα IOUserClient α ααααα»ααααααΆααα’αΆα ααααΌαααΆααα»αα αααααααααΎαα»αααΆα IOKitLib userspace βIOCatalogueTerminate(mach_port_t, uint32_t flag, io_name_t description);β α α’αααα’αΆα αααα‘αααα·ααα·ααα αααα α ααΆααααααααΆ "αααα αα" αα αΌαααααααααα·ααΈ userspace "ααααΆαα" αααααΊαα»αααΆα "clientDied" αα·αααααΌαααΆαα α ααα
ααΆαααΆαααΆαα―αααΆα
ααΎααααΈααΆαααΆαα―αααΆα ααΆαααααααααΆαααααα»αααΆαααααΎ Kauth API αααα’αα»ααααΆαα±ααα’αααααΆααααααα·αααΆαα αΌαααααΎα―αααΆαα Apple αααααα±ααα’αααα’αα·ααααααααΌαααΆαααΌαααααΉαα’αααΈααααΉαααα·ααΆααααααααααα αααα»ααα·ααΆαααΆα αααααΆαααα½αααΎα ααααα·ααααα·ααΆα KAUTH_VNODE_DELETE, KAUTH_VNODE_WRITE_DATA αα·α KAUTH_VNODE_DELETE_CHILD ααΆαααΆααααααΆααα αααααααΆαααΆααααα½ααααα»ααααα»αααΆαααΉααααααΉαααΆαα αΌαααααΎα―αααΆαααΊααΆαααααΌα - ααΎαααααΎ βvn_getpathβ API ααΎααααΈααα½αααΆαααααΌααα ααΆααα―αααΆα αα·ααααααααααα»αααααααααΌαα ααΌαα αααΆαααΆ ααΎααααΈαααααΎαααααα·αααααΆαααΆαααααΌααααααααααΌαααα―αααΆα αααααααααα·αα’αα»ααααΆαα±ααα αΌαααααΎα―αααΆαααΈαα½αααα ααα»ααααααΆαααα ααααααα―αααΆααααα½αααΆαααααααΌαααΆαααααΌααααααααα»αααααα ααΆα αΆαααΆα αααΎααααΈααααααααααααΌααα α αΎαααΆααααααα·α KAUTH_VNODE_DELETE αααααΆααααΆα
αα»ααα·ααααα·αααα·ααΈααΆααααααααα’αΆα
ααΉαααΆαααααΎαααΆαααΆα αααααΆαα
ααα½ααα»αααααααΎαα‘αΎαα ααΎααααΈααΆααΆααΆααΆααααααααααα·αααααΎααΉα O (αα»ααααα*αααααα) ααααα»αααααααΊααΆα
ααα½ααα»ααααα ααααααααΊααΆαααααααααααα α’αααα’αΆα
ααααΎ automaton finite deterministic (DFA) ααααααααΎαααααα»αααααα
α αΌαααΎααα·α αΆαααΆαα·ααΈααΆααααααααααΆαααααααΎα DFA αααααΆαααααα»ααα»ααααααααααΆααααααα±ααα ααΎαα αΆααααααΎαααααααααααα·α αα ααΎααααα»αααααααΈαα½ααα ααααα·αααΎααααααααααα·α ααΆααα’ααα ααα’α»ααα αα½α’ααααααΌα ααααΆ αααααΆαααααααααΎαααααααααααα·α ααΈαα½ααααααα½α’αααααα½α α αΎαα αα αΆαααΆαααααααααααααΆααααΌα ααααΆααΊααααΆααα½αα ααααα·αααΎααΆαααααααααααα·α ααΈααααααΆααα·αα·ααααααααΆαααααααααΆ ααΌααααα ααααααααααααα·α αα ααΆαααα»αααΆααα·αα·ααααααααΆααααα½αααα ααα’α»ααα α αΎαααααΎαααααααααΌααααα½ααααααααΆααααααΆαααααα»αααΈαα½ααα
αααα»αααααΈααααΌα (αα½α’ααααααΆααα’αααα αααααααααααααααα·α ααΊααΌα ααααΆ) ααΎαααα½αααΆααααα DFA αααααΆαααΆαααααΆααααααΌααααα½ααα ααΆααααααααααααΆααααΌα ααααΆα αααα»αααααΈααΈααΈα ααΎαααα½αααΆαααΆααΆαααααΆαααααΆααααααΌαααα α 256 (α ααα½ααα½α’αααα αα·αα ααα½αα’αα·ααααΆαααααα»α) αα ααααααΆαααααααααΆαααααααα½αααΆααααααΆαα α α‘αΎααα·αααΌααα»αααΆαα
ααΌααααα‘ααααΎαα§ααΆα ααααα½αα αααααΆαααααα»ααααα»ααααα (β/foo/bar/tmp/β, β/var/db/foo/β, β/foo/bar/aba/β, βfoo/bar/aac/β) α’αααα’αΆα ααα½αααΆαααΌα ααΆαααααα ααΈα’αα ααα’αα αα½αααααααααα αΆαααααΆαααααΆααααααΌααααααΆααα ααααααααααααααα ααΆαααααΆααααααΌαααααααααααΉααα·αααααΌαααΆααααα αααααααα
αα
αααααααααΆαααααα DKA α’αΆα
ααΆα 3 ααααΈα
- ααααΆαααΆαα α»ααααααααααΌαααΆαααΆαααα - ααααΌαααααΌαααΆαααΆαααΆα ααΎααααααααααα·ααααα·ααΆα KAUTH_VNODE_DELETE, KAUTH_VNODE_WRITE_DATA αα·α KAUTH_VNODE_DELETE_CHILD
- ααααΆαααΆαα α»αααααααα·αααααΌαααΆαααΆαααααα ααα»ααααααααΌα "ααΆααααα αα" (ααΆααααα ααααΆααααααααΌαααΆαααΆαααα) - ααααΌαααΊααΆαα ααΆα αΆαααΆα ααααα»αααΆαααααα KAUTH_VNODE_DELETE α α αααΆαααΆααααα·αααΎ vnode ααΊααΆαααα½α α’αααααααΌααααααα '/' αα α α»ααααα αα ααΎαα·αααΌα ααααααααΆα’αΆα αααααααΆαα α―αααΆα β/foor/bar/tβ ααααα·αααααΉαααααΌαα
- ααααΆαααΆαα α»αααααααα·αααΆααα αααααααΌααα·αααΆααααα ααα ααααΆααα»αααααααΆαα½αααααΌαααααΆααΆαα½αααααα ααΎααα·αααααΆαααΆαααΉααααααΉαααα
ααα ααααΈααααα·ααααΆα
ααααα αααααααααααΆααα»ααααα·ααΆαααααααα»αααααΌαααΆααααααΎαα‘αΎαααΊααΎααααΈαααααΎαααααα·ααα»ααααα·ααΆαααααα’αααααααΎααααΆαα αα·ααα·ααααααααααααΆααα αααααΆααα·αααα ααααα αααααααΌαααΆααααααα αααααΆαα’αα·ααααααααα·ααααααααα·ααΈ Acronis ααααα·αααΆαααΆααααααααααΆααααα αααααααααααααααα·ααααα·ααΆααααα½αα―α βαααααβα αααααΆααα·αααα ααΎααα·ααα½αααααααααα αααααα»αααΆααααααΉαααααααα»ααααα·ααΆαααΆααααα αααα’αΆα ααααΎα±αααααααΎαα‘αΎααα ααΎααααα OS ααΆαα·αααα αΆααααΆααααΈααΆααα·αααΆαααΆαααααααααααααα αααααΎααααααααΆαααααΆαααααα½αααααααΎαααΆααα·αααα ααΆαααΆααααααααααααΌαααΆαααΆαααΆααααα αααα»ααα»ααααα·ααΆαααα·ααα Apple α αΎαααααΌαααΆααα½ααα»ααα αααα»α macOS 10.14.5 (https://support.apple.com/en-gb/HT210119)α
ααΆααα’αααααα’αΆα
ααααΎααΆααα»αααααΆααα§αααααααααΎααααΆααααααα’αααααααΌαααΆαααα‘αΎαααΆααααΌαααΆααα
αααα»αααΊαααα αααααΊαα·αααΆαα
ααααααααα αααααααααααααΆαααααααα·ααΈααΆααααα
αα·αααααα·αα
ααααΆααααααα αααααΆαααΆαααΆααααα ααΌα
αααα’αααα’αΆα
ααΎαααΎα ααΌααααΈααααΆαααΆαααΆααααααα·ααΈααααα
αααΆααααΌα
ααΆααα
αΆααααααα αα·αααααααααααααα»ααα»αααααΆαααΆαααΆαααΆααααα ααα»ααααα₯α‘αΌααααααα·ααα Acronis ααααΈαααααΆαα macOS ααΉαααΆαααΆαααΆαααΆααααααααααααΆααααΉαααΆααααα»αα
ααααΈααααααααα
ααααα: www.habr.com