Pehea e pale ai i nā kaʻina hana a me nā hoʻonui kernel ma macOS

Aloha, Habr! I kēia lā makemake wau e kamaʻilio e pili ana i ke ʻano e hiki ai iā ʻoe ke pale i nā kaʻina mai ka hoʻouka ʻana e nā mea hoʻouka ma macOS. No ka laʻana, pono kēia no kahi antivirus a i ʻole ʻōnaehana backup, ʻoiai ma lalo o macOS aia nā ala he nui e "pepehi" i kahi kaʻina hana. E heluhelu e pili ana i kēia a me nā ʻano pale ma lalo o ka ʻoki.

Pehea e pale ai i nā kaʻina hana a me nā hoʻonui kernel ma macOS

ʻO ke ala maʻamau e "pepehi" i kahi kaʻina hana

ʻO kahi ala kaulana e "pepehi" i kahi kaʻina hana ʻo ka hoʻouna ʻana i kahi hōʻailona SIGKILL i ke kaʻina hana. Ma o ka bash hiki iā ʻoe ke kāhea i ka maʻamau "kill -SIGKILL PID" a i ʻole "pkill -9 NAME" e pepehi. Ua ʻike ʻia ke kauoha "pepehi" mai nā lā o UNIX a loaʻa ʻaʻole wale ma macOS, akā ma nā ʻōnaehana UNIX-like ʻē aʻe.

E like me nā ʻōnaehana UNIX-like, ʻae ʻo macOS iā ʻoe e hoʻopaʻa i nā hōʻailona i kahi kaʻina hana koe ʻelua - SIGKILL a me SIGSTOP. E kālele nui ana kēia ʻatikala i ka hōʻailona SIGKILL ma ke ʻano he hōʻailona e make ai ke kaʻina hana.

macOS kiko'ī

Ma ka macOS, kāhea ka ʻōnaehana pepehi i ka kernel XNU i ka hana psignal (SIGKILL,...). E ho'āʻo kākou e ʻike i nā hana mea hoʻohana ʻē aʻe i hiki ke kapa ʻia e ka hana psignal. E hoʻopau i nā kelepona i ka hana psignal i loko o nā mīkini o loko o ka kernel (ʻoiai he mea ʻole lākou, e waiho mākou iā lākou no kahi ʻatikala ʻē aʻe 🙂 - hōʻoia hōʻailona, ​​​​hewa hoʻomanaʻo, puka / hoʻopau i ka lawelawe ʻana, nā hewa palekana file, etc. .

E hoʻomaka kākou i ka loiloi me ka hana a me ke kelepona ʻōnaehana pili hoʻopau_me_kaumaha. Hiki ke ʻike ʻia ma ka hoʻohui ʻana i ke kelepona pepehi maʻamau, aia kahi ala ʻē aʻe i kikoʻī i ka ʻōnaehana hana macOS a ʻaʻole ʻike ʻia ma BSD. Ua like pū nā loina hana o nā kelepona ʻōnaehana ʻelua. He mau kelepona pololei lākou i ka kernel function psignal. E hoʻomaopopo hoʻi ma mua o ka pepehi ʻana i kahi kaʻina hana, hana ʻia kahi māka "cansignal" - inā hiki i ke kaʻina ke hoʻouna i kahi hōʻailona i kahi kaʻina hana ʻē aʻe; ʻaʻole ʻae ka ʻōnaehana i kekahi noi e pepehi i nā kaʻina hana, no ka laʻana.

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);
	}
...
}

hoʻokuʻu ʻia

Hoʻomaka ʻia ke ala maʻamau e hana ai i nā daemons i ka hoʻomaka ʻana o ka ʻōnaehana a mālama i ko lākou ola. E ʻoluʻolu e hoʻomaopopo ʻo nā kumu no ka mana kahiko o launchctl a hiki i ka macOS 10.10, hāʻawi ʻia nā code code no nā kumu hoʻohālike. Hoʻouna ʻo launchctl hou i nā hōʻailona hoʻolaha ma o XPC, ua hoʻoneʻe ʻia ka loiloi launchctl iā ia.

E nānā kākou i ka pau ʻana o nā noi. Ma mua o ka hoʻouna ʻana i ka hōʻailona SIGTERM, hoʻāʻo ʻia ka noi e hoʻōki me ka hoʻohana ʻana i ke kelepona ʻōnaehana "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));
		} 
...
<>

Ma lalo o ka hood, proc_terminate, ʻoiai kona inoa, hiki ke hoʻouna ʻaʻole wale i ka psignal me SIGTERM, akā ʻo SIGKILL pū kekahi.

Pepehi ʻole - Ka palena waiwai

Hiki ke ʻike ʻia kahi hihia hoihoi hou aʻe ma kahi kelepona ʻōnaehana kaʻina_kulekele. ʻO ka hoʻohana maʻamau o kēia kelepona ʻo ka hoʻopaʻa ʻana i nā kumuwaiwai noi, e like me ka mea helu helu e kaupalena i ka manawa CPU a me nā puʻupuʻu hoʻomanaʻo i ʻole e lohi nui ʻia ka ʻōnaehana e nā hana hoʻopaʻa waihona. Inā hiki i kahi palapala noi i kona palena waiwai, e like me ka mea i ʻike ʻia mai ka hana proc_apply_resource_actions, hoʻouna ʻia kahi hōʻailona SIGKILL i ke kaʻina hana.

ʻOiai hiki i kēia kelepona pūnaewele ke pepehi i kahi kaʻina hana, ʻaʻole i nānā pono ka ʻōnaehana i nā kuleana o ke kaʻina e kāhea ana i ke kelepona ʻōnaehana. Ke nānā maoli nei ua noho, akā ua lawa ka hoʻohana ʻana i ka hae ʻē aʻe PROC_POLICY_ACTION_SET e kāpae i kēia kūlana.

No laila, inā ʻoe e "palena" i ka quota hoʻohana CPU o ka noi (no ka laʻana, e ʻae wale i ka 1 ns e holo), a laila hiki iā ʻoe ke pepehi i kekahi kaʻina hana i ka ʻōnaehana. No laila, hiki i ka malware ke pepehi i kekahi kaʻina hana ma ka ʻōnaehana, me ke kaʻina antivirus. He mea hoihoi nō hoʻi ka hopena i ka wā e pepehi ai i kahi kaʻina hana me pid 1 (launchctl) - kernel panic i ka wā e hoʻāʻo ai e hana i ka hōʻailona SIGKILL :)

Pehea e pale ai i nā kaʻina hana a me nā hoʻonui kernel ma macOS

Pehea e hoʻoponopono ai i ka pilikia?

ʻO ke ala maʻalahi loa e pale aku i kahi kaʻina mai ka pepehi ʻia ʻana, ʻo ia ke pani i ka pointer hana ma ka papa kelepona ʻōnaehana. ʻO ka mea pōʻino, he mea koʻikoʻi kēia ala no nā kumu he nui.

ʻO ka mea mua, ʻaʻole pilikino ka hōʻailona e hoʻomalu i ka wahi hoʻomanaʻo o sysent i ka hōʻailona kernel XNU, akā ʻaʻole hiki ke loaʻa i nā hōʻailona kernel. Pono ʻoe e hoʻohana i nā ʻano hulina heuristic, e like me ka wehe ʻana i ka hana a me ka ʻimi ʻana i kahi kuhikuhi i loko.

ʻO ka lua, ʻo ke ʻano o nā mea hoʻokomo i ka papaʻaina e pili ana i nā hae i hoʻohui ʻia ai ka kernel. Inā hōʻike ʻia ka hae CONFIG_REQUIRES_U32_MUNGING, e hoʻololi ʻia ka nui o ka hale - e hoʻohui ʻia kahi kahua hou. sy_arg_munge32. Pono e hoʻokō i kahi loiloi hou e hoʻoholo ai i ka hae i hui pū ʻia me ka kernel, a i ʻole, e nānā i nā kuhikuhi hana e kūʻē i nā mea i ʻike ʻia.

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
                                         */
};

ʻO ka mea pōmaikaʻi, i nā mana hou o macOS, hāʻawi ʻo Apple i API hou no ka hana ʻana me nā kaʻina hana. Hāʻawi ka Endpoint Security API i nā mea kūʻai aku e ʻae i nā noi he nui i nā kaʻina hana ʻē aʻe. No laila, hiki iā ʻoe ke pale i nā hōʻailona i nā kaʻina hana, me ka hōʻailona SIGKILL, me ka hoʻohana ʻana i ka API i ʻōlelo ʻia ma luna.

#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;
}

Pēlā nō, hiki ke hoʻopaʻa inoa ʻia kahi kulekele MAC i loko o ka kernel, e hāʻawi ana i kahi ala palekana hōʻailona (policy proc_check_signal), akā ʻaʻole kākoʻo ʻia ka API.

Palekana hoʻonui kernel

Ma waho aʻe o ka pale ʻana i nā kaʻina hana i loko o ka ʻōnaehana, pono pū ka pale ʻana i ka hoʻonui kernel ponoʻī (kext). Hāʻawi ka macOS i kahi hoʻolālā no nā mea hoʻomohala e hoʻomohala maʻalahi i nā mea hoʻokele IOKit. Ma waho aʻe o ka hāʻawi ʻana i nā mea hana no ka hana ʻana me nā polokalamu, hāʻawi ʻo IOKit i nā ala no ka hoʻokele hoʻokele me ka hoʻohana ʻana i nā manawa o nā papa C++. Hiki i kahi noi ma ka mea hoʻohana ke "loaʻa" i kahi mea i hoʻopaʻa inoa ʻia o ka papa e hoʻokumu i kahi pilina kernel-userspace.

No ka ʻike ʻana i ka helu o nā manawa papa i ka ʻōnaehana, aia ka pono ioclasscount.

my_kext_ioservice = 1
my_kext_iouserclient = 1

ʻO kēlā me kēia hoʻonui kernel e makemake ana e hoʻopaʻa inoa me ka mea hoʻokele kaʻa, pono e haʻi i kahi papa i hoʻoilina mai IOService, no ka laʻana my_kext_ioservice ma kēia hihia.

Ke ho'āʻo nei e wehe i kahi mea hoʻokele mai ka ʻōnaehana (kextunload command), ua kapa ʻia ka hana virtual "bool terminate (IOOptionBits options)". Ua lawa ka hoʻihoʻi hewa ʻana i ke kelepona e hoʻopau i ka wā e hoʻāʻo ai e wehe i ka kextunload.

bool Kext::terminate(IOOptionBits options)
{

  if (!IsUnloadAllowed)
  {
    // Unload is not allowed, returning false
    return false;
  }

  return super::terminate(options);
}

Hiki ke hoʻonoho ʻia ka hae IsUnloadAllowed e ka IOUserClient ke hoʻouka. Ke loaʻa kahi palena hoʻoiho, e hoʻihoʻi ke kauoha kextunload i kēia huahana:

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.

Pono e hana ʻia ka pale like no IOUserClient. Hiki ke hoʻokuʻu ʻia nā manawa o nā papa me ka hoʻohana ʻana i ka hana hoʻohana IOKitLib "IOCatalogueTerminate (mach_port_t, uint32_t hae, io_name_t wehewehe);". Hiki iā ʻoe ke hoʻihoʻi hewa i ke kāhea ʻana i ke kauoha "hoʻopau" a hiki i ka "make" o ka mea hoʻohana, ʻo ia hoʻi, ʻaʻole i kapa ʻia ka hana "clientDied".

Mālama waihona

No ka pale ʻana i nā faila, ua lawa ka hoʻohana ʻana i ka Kauth API, kahi e hiki ai iā ʻoe ke kaupalena i ke komo ʻana i nā faila. Hāʻawi ʻo Apple i nā mea hoʻomohala me nā hoʻolaha e pili ana i nā hanana like ʻole i ka laulā; no mākou, he mea nui nā hana KAUTH_VNODE_DELETE, KAUTH_VNODE_WRITE_DATA a me KAUTH_VNODE_DELETE_CHILD. ʻO ke ala maʻalahi loa e kaupalena i ke komo ʻana i nā faila ma ke ala - hoʻohana mākou i ka API "vn_getpath" e kiʻi i ke ala i ka faila a hoʻohālikelike i ka prefix ala. E hoʻomaopopo i ka hoʻololi ʻana i ka inoa o nā ala waihona waihona, ʻaʻole ʻae ka ʻōnaehana i ke komo ʻana i kēlā me kēia faila, akā i ka waihona ponoʻī i kapa hou ʻia. Pono e hoohalike i ke ala makua a kaohi ia KAUTH_VNODE_DELETE no ia mea.

Pehea e pale ai i nā kaʻina hana a me nā hoʻonui kernel ma macOS

ʻO ka hemahema o kēia ʻano hana haʻahaʻa paha i ka piʻi ʻana o nā prefixes. No ka hōʻoia ʻana ʻaʻole like ka hoʻohālikelike ʻana me O(prefix*length), kahi prefix ka helu o nā prefixes, ʻo ka lōʻihi ka lōʻihi o ke kaula, hiki iā ʻoe ke hoʻohana i ka deterministic finite automaton (DFA) i kūkulu ʻia e nā prefixes.

E noʻonoʻo kākou i ke ʻano o ke kūkulu ʻana i kahi DFA no kahi hoʻonohonoho prefix i hāʻawi ʻia. Hoʻomaka mākou i nā cursors ma ka hoʻomaka o kēlā me kēia prefix. Inā kuhikuhi nā ʻōkuhi a pau i ke ʻano hoʻokahi, a laila e hoʻonui i kēlā me kēia pehu i hoʻokahi ʻano a e hoʻomanaʻo i ka lōʻihi o ka laina hoʻokahi i ʻoi aku ka nui o ka laina hoʻokahi. Inā ʻelua mau ʻōkuhi me nā hōʻailona like ʻole, e hoʻokaʻawale i nā cursors i mau pūʻulu e like me ka hōʻailona a lākou e kuhikuhi ai a hana hou i ka algorithm no kēlā me kēia hui.

I ka hihia mua (ʻo nā huaʻōlelo āpau ma lalo o nā cursors ua like ia), loaʻa iā mākou kahi mokuʻāina DFA i hoʻokahi wale nō hoʻololi ma ka laina like. Ma ka hihia ʻelua, loaʻa iā mākou kahi papa o nā hoʻololi o ka nui 256 (helu o nā huaʻōlelo a me ka helu kiʻekiʻe o nā pūʻulu) i nā mokuʻāina i loaʻa ma ke kāhea ʻana i ka hana.

E nānā kākou i kekahi laʻana. No kahi hoʻonohonoho prefixes (“/foo/bar/tmp/”, “/var/db/foo/”, “/foo/bar/aba/”, “foo/bar/aac/”) hiki iā ʻoe ke loaʻa i kēia mau mea. DFA. Hōʻike ke kiʻi i nā hoʻololi e alakaʻi ana i nā mokuʻāina ʻē aʻe; ʻaʻole e pau nā hoʻololi ʻē aʻe.

Pehea e pale ai i nā kaʻina hana a me nā hoʻonui kernel ma macOS

Ke hele nei ma nā mokuʻāina DKA, aia paha he 3 mau hihia.

  1. Ua hōʻea ka mokuʻāina hope - pale ʻia ke ala, kaupalena mākou i nā hana KAUTH_VNODE_DELETE, KAUTH_VNODE_WRITE_DATA a me KAUTH_VNODE_DELETE_CHILD
  2. ʻAʻole i hiki ke kūlana hope, akā "ua pau" ke ala (ua hiki i ka null terminator) - he makua ke ala, pono e kaupalena iā KAUTH_VNODE_DELETE. E hoʻomaopopo inā he waihona ʻo vnode, pono ʻoe e hoʻohui i kahi '/' ma ka hopena, i ʻole e kaupalena ʻia ia i ka faila "/foor/bar/t", ʻaʻole pololei.
  3. ʻAʻole i hiki ke kūlana hope, ʻaʻole i pau ke ala. ʻAʻohe o nā prefix e like me kēia, ʻaʻole mākou e hoʻokomo i nā mea kapu.

hopena

ʻO ka pahuhopu o nā hoʻonā palekana e hoʻomohala ʻia e hoʻonui i ka pae o ka palekana o ka mea hoʻohana a me kāna ʻikepili. Ma kekahiʻaoʻao, ua hoʻokōʻia kēia pahuhopu e ka hoʻomohalaʻana i ka huahana polokalamu Acronis, kahi e pani ai i kēlā mau nāwaliwali kahi i "nāwaliwali" ai ka'ōnaehana hana. Ma ka ʻaoʻao ʻē aʻe, ʻaʻole pono mākou e haʻalele i ka hoʻoikaika ʻana i kēlā mau mea palekana e hiki ke hoʻomaikaʻi ʻia ma ka ʻaoʻao OS, ʻoi aku ka nui o ka pani ʻana i kēlā mau nāwaliwali e hoʻonui i ko mākou kūpaʻa ponoʻī ma ke ʻano he huahana. Ua hōʻike ʻia ka nāwaliwali i ka Apple Product Security Team a ua hoʻopaʻa ʻia ma macOS 10.14.5 (https://support.apple.com/en-gb/HT210119).

Pehea e pale ai i nā kaʻina hana a me nā hoʻonui kernel ma macOS

Hiki ke hana i kēia mau mea inā ua hoʻokomo ʻia kāu pono i loko o ka kernel. ʻO ia hoʻi, ʻaʻohe puka puka no waho a me nā polokalamu makemake ʻole. Eia naʻe, e like me kāu e ʻike ai, ʻo ka pale ʻana i nā polokalamu kūpono e like me ka antivirus a me nā ʻōnaehana backup pono e hana. Akā i kēia manawa e loaʻa i nā huahana Acronis hou no ka macOS ka pale hou mai ka wehe ʻana mai ka ʻōnaehana.

Source: www.habr.com

Pākuʻi i ka manaʻo hoʻopuka