Ki jan yo pwoteje pwosesis ak ekstansyon nwayo sou macOS

Bonjou, Habr! Jodi a mwen ta renmen pale sou fason ou ka pwoteje pwosesis kont atak pa atakè nan macOS. Pou egzanp, sa a itil pou yon sistèm antivirus oswa backup, espesyalman depi anba macOS gen plizyè fason pou "touye" yon pwosesis. Li sou sa a ak metòd pwoteksyon anba koupe a.

Ki jan yo pwoteje pwosesis ak ekstansyon nwayo sou macOS

Fason klasik pou "touye" yon pwosesis

Yon fason byen koni pou "touye" yon pwosesis se voye yon siyal SIGKILL nan pwosesis la. Atravè bash ou ka rele estanda "kill -SIGKILL PID" oswa "pkill -9 NAME" pou touye. Yo konnen kòmandman "touye" la depi epòk UNIX epi li disponib pa sèlman sou macOS, men tou sou lòt sistèm ki tankou UNIX.

Menm jan ak sistèm UNIX, macOS pèmèt ou entèsepte nenpòt siyal nan yon pwosesis eksepte de - SIGKILL ak SIGSTOP. Atik sa a pral prensipalman konsantre sou siyal SIGKILL la kòm yon siyal ki lakòz yon pwosesis yo dwe touye.

spesifik macOS

Sou macOS, apèl sistèm touye nan nwayo XNU a rele fonksyon psignal(SIGKILL,...). Ann eseye wè ki lòt aksyon itilizatè nan espas itilizatè yo ka rele pa fonksyon an psignal. Ann elimine apèl nan fonksyon psignal nan mekanis entèn nwayo a (byenke yo ka pa trivial, men nou pral kite yo pou yon lòt atik 🙂 - verifikasyon siyati, erè memwa, manyen sòti/fini, vyolasyon pwoteksyon dosye, elatriye.

Ann kòmanse revizyon an ak fonksyon an ak apèl sistèm ki koresponn lan terminate_with_payload. Li ka wè ke anplis apèl la touye klasik, gen yon apwòch altènatif ki espesifik nan sistèm nan opere macOS epi yo pa jwenn nan BSD. Prensip fonksyònman tou de apèl sistèm yo sanble tou. Yo se apèl dirèk nan fonksyon nwayo psignal la. Epitou sonje ke anvan yo touye yon pwosesis, yo fè yon chèk "cansignal" - si pwosesis la ka voye yon siyal nan yon lòt pwosesis; sistèm nan pa pèmèt okenn aplikasyon pou touye pwosesis sistèm lan, pou egzanp.

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

lanse

Fason estanda pou kreye demon nan demaraj sistèm ak kontwole tout lavi yo lanse. Tanpri sonje ke sous yo se pou ansyen vèsyon launchctl jiska macOS 10.10, yo bay egzanp kòd pou rezon ilistrasyon. Modèn launchctl voye siyal launchd atravè XPC, lojik launchctl te deplase nan li.

Ann gade ki jan egzakteman aplikasyon yo sispann. Anvan yo voye siyal SIGTERM a, yo eseye sispann aplikasyon an lè l sèvi avèk apèl sistèm "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));
		} 
...
<>

Anba kapo a, proc_terminate, malgre non li, ka voye pa sèlman psignal ak SIGTERM, men tou SIGKILL.

Touye Endirèk - Limit Resous

Yon ka ki pi enteresan ka wè nan yon lòt apèl sistèm pwosesis_politik. Yon itilizasyon komen nan apèl sistèm sa a se limite resous aplikasyon, tankou pou yon indexer limite tan CPU ak kota memwa pou ke sistèm nan pa siyifikativman ralanti pa aktivite kachèt dosye. Si yon aplikasyon rive nan limit resous li, jan yo ka wè nan fonksyon proc_apply_resource_actions, yo voye yon siyal SIGKILL nan pwosesis la.

Malgre ke apèl sistèm sa a te kapab potansyèlman touye yon pwosesis, sistèm nan pa t ase tcheke dwa yo nan pwosesis la rele apèl sistèm lan. Aktyèlman tcheke te egziste, men li ase pou itilize drapo altènatif PROC_POLICY_ACTION_SET pou kontoune kondisyon sa a.

Pakonsekan, si ou "limite" kota itilizasyon CPU aplikasyon an (pa egzanp, pèmèt sèlman 1 ns kouri), Lè sa a, ou ka touye nenpòt pwosesis nan sistèm nan. Kidonk, malveyan an ka touye nenpòt pwosesis sou sistèm nan, ki gen ladan pwosesis la antivirus. Enteresan tou se efè ki rive lè yo touye yon pwosesis ak pid 1 (launchctl) - panik nwayo lè w ap eseye trete siyal SIGKILL la :)

Ki jan yo pwoteje pwosesis ak ekstansyon nwayo sou macOS

Ki jan yo rezoud pwoblèm nan?

Fason ki pi senp pou anpeche yon pwosesis yo te touye se ranplase pwent fonksyon an nan tablo apèl sistèm lan. Malerezman, metòd sa a pa trivial pou plizyè rezon.

Premyèman, senbòl ki kontwole kote memwa sysent la pa sèlman prive nan senbòl nwayo XNU a, men li pa ka jwenn nan senbòl nwayo a. Ou pral oblije sèvi ak metòd rechèch euristik, tankou demonte dinamik fonksyon an epi chèche yon konsèy nan li.

Dezyèmman, estrikti nan antre nan tablo a depann de drapo yo ak ki nwayo a te konpile. Si yo deklare drapo CONFIG_REQUIRES_U32_MUNGING, gwosè estrikti a pral chanje - y ap ajoute yon lòt jaden. sy_arg_munge32. Li nesesè pou fè yon chèk adisyonèl pou detèmine ak ki drapo nwayo a te konpile, oswa altènativman, tcheke endikasyon fonksyon kont sa yo konnen.

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

Erezman, nan vèsyon modèn nan macOS, Apple bay yon nouvo API pou travay ak pwosesis. Endpoint Security API a pèmèt kliyan yo otorize anpil demann nan lòt pwosesis. Kidonk, ou ka bloke nenpòt siyal nan pwosesis, ki gen ladan siyal SIGKILL la, lè l sèvi avèk API ki mansyone anwo a.

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

Menm jan an tou, yon Règ MAC ka anrejistre nan nwayo a, ki bay yon metòd pwoteksyon siyal (politik proc_check_signal), men API a pa ofisyèlman sipòte.

Pwoteksyon ekstansyon Kernel

Anplis pwoteje pwosesis nan sistèm nan, pwoteje ekstansyon nwayo a li menm (kext) nesesè tou. macOS bay yon fondasyon pou devlopè yo fasil devlope chofè aparèy IOKit. Anplis bay zouti pou travay ak aparèy, IOKit bay metòd pou anpile chofè lè l sèvi avèk egzanp C++ klas yo. Yon aplikasyon nan espas itilizatè a pral kapab "jwenn" yon egzanp ki anrejistre nan klas la pou etabli yon relasyon nwayo-espas itilizatè.

Pou detekte kantite egzanp klas nan sistèm nan, gen sèvis piblik ioclasscount la.

my_kext_ioservice = 1
my_kext_iouserclient = 1

Nenpòt ekstansyon nwayo ki vle anrejistre ak pil chofè a dwe deklare yon klas ki eritye de IOService, pou egzanp my_kext_ioservice nan ka sa a. Konekte aplikasyon itilizatè yo lakòz kreyasyon yon nouvo egzanp nan klas la ki eritye de IOUserClient, nan egzanp my_kext_iouserclient.

Lè w ap eseye dechaje yon chofè nan sistèm nan (kextunload kòmand), yo rele fonksyon vityèl "bool terminate (IOOptionBits options)". Li se ase yo retounen fo sou apèl la fini lè w ap eseye dechaje enfim kextunload.

bool Kext::terminate(IOOptionBits options)
{

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

  return super::terminate(options);
}

IOUserClient ka mete drapo IsUnloadAllowed a lè w ap chaje. Lè gen yon limit download, lòd kextunload la pral retounen pwodiksyon sa a:

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.

Pwoteksyon menm jan an dwe fèt pou IOUserClient. Enstans klas yo ka dechaje lè l sèvi avèk fonksyon espas itilizatè IOKitLib "IOCatalogueTerminate(mach_port_t, uint32_t flag, io_name_t description);". Ou ka retounen fo lè w ap rele lòd "terminate" la jiskaske aplikasyon espas itilizatè a "mouri", sa vle di, fonksyon "clientDied" la pa rele.

Pwoteksyon dosye

Pou pwoteje dosye, li ase pou itilize Kauth API, ki pèmèt ou limite aksè nan dosye yo. Apple bay devlopè yo notifikasyon sou divès evènman nan sijè ki abòde lan; pou nou, operasyon yo KAUTH_VNODE_DELETE, KAUTH_VNODE_WRITE_DATA ak KAUTH_VNODE_DELETE_CHILD enpòtan. Fason ki pi fasil pou mete restriksyon sou aksè nan dosye a se pa chemen - nou itilize API "vn_getpath" pou jwenn chemen an nan dosye a epi konpare prefiks chemen an. Remake byen ke pou optimize chanje non chemen dosye dosye a, sistèm nan pa otorize aksè nan chak fichye, men sèlman nan katab la li menm ki te chanje non. Li nesesè pou konpare chemen paran an epi mete restriksyon sou KAUTH_VNODE_DELETE pou li.

Ki jan yo pwoteje pwosesis ak ekstansyon nwayo sou macOS

Dezavantaj apwòch sa a ka ba pèfòmans kòm kantite prefiks ogmante. Pou asire ke konparezon an pa egal a O (prefiks * longè), kote prefiks se kantite prefiks, longè se longè fisèl la, ou ka itilize yon otomat fini detèminist (DFA) ki te konstwi pa prefiks.

Ann konsidere yon metòd pou konstwi yon DFA pou yon seri prefiks bay yo. Nou inisyalize kurseur yo nan kòmansman chak prefiks. Si tout kurseur lonje dwèt sou menm karaktè a, Lè sa a, ogmante chak kurseur pa yon karaktè epi sonje ke longè a nan menm liy lan pi gran pa youn. Si gen de kurseur ak senbòl diferan, divize kurseur yo an gwoup dapre senbòl yo montre epi repete algorithm la pou chak gwoup.

Nan premye ka a (tout karaktè ki anba kurseur yo se menm bagay la), nou jwenn yon eta DFA ki gen yon sèl tranzisyon sou menm liy lan. Nan dezyèm ka a, nou jwenn yon tablo tranzisyon gwosè 256 (kantite karaktè ak kantite maksimòm gwoup) nan eta ki vin apre yo jwenn lè yo rele fonksyon an recursively.

Ann gade yon egzanp. Pou yon seri prefiks ("/foo/bar/tmp/", "/var/db/foo/", "/foo/bar/aba/", "foo/bar/aac/") ou ka jwenn sa ki annapre yo. DFA. Figi a montre sèlman tranzisyon ki mennen nan lòt eta; lòt tranzisyon yo p ap final.

Ki jan yo pwoteje pwosesis ak ekstansyon nwayo sou macOS

Lè w ap pase nan eta DKA yo, ka gen 3 ka.

  1. Eta final la rive - chemen an pwoteje, nou limite operasyon yo KAUTH_VNODE_DELETE, KAUTH_VNODE_WRITE_DATA ak KAUTH_VNODE_DELETE_CHILD.
  2. Eta final la pa te rive jwenn, men chemen an "te fini" (terminator la nil te rive) - chemen an se yon paran, li nesesè limite KAUTH_VNODE_DELETE. Remake byen ke si vnode se yon katab, ou bezwen ajoute yon '/' nan fen a, otreman li ka limite li nan dosye a "/foor/bar/t", ki pa kòrèk.
  3. Eta final la pa te rive, chemen an pa te fini. Okenn nan prefiks yo matche ak sa a, nou pa prezante restriksyon.

Konklizyon

Objektif solisyon sekirite yo ap devlope se ogmante nivo sekirite itilizatè a ak done li yo. Sou yon bò, objektif sa a reyalize pa devlopman nan pwodwi lojisyèl Acronis, ki fèmen frajilite sa yo kote sistèm operasyon an tèt li "fèb". Nan lòt men an, nou pa ta dwe neglije ranfòse aspè sekirite sa yo ki ka amelyore sou bò OS, espesyalman depi fèmen frajilite sa yo ogmante pwòp estabilite nou kòm yon pwodwi. Yo te rapòte vilnerabilite a bay Ekip Sekirite Pwodwi Apple la epi li te fikse nan macOS 10.14.5 (https://support.apple.com/en-gb/HT210119).

Ki jan yo pwoteje pwosesis ak ekstansyon nwayo sou macOS

Tout bagay sa a ka fèt sèlman si sèvis piblik ou a te ofisyèlman enstale nan nwayo a. Sa vle di, pa gen okenn vid sa yo pou lojisyèl ekstèn ak vle. Sepandan, jan ou ka wè, menm pwoteje pwogram lejitim tankou antivirus ak sistèm backup mande pou travay. Men koulye a, nouvo pwodwi Acronis pou macOS pral gen plis pwoteksyon kont dechaje nan sistèm nan.

Sous: www.habr.com

Add nouvo kòmantè