Moni, Habr! Lero ndikufuna kulankhula za momwe mungatetezere njira zanu ku ziwopsezo zoyipa. macOSMwachitsanzo, izi ndizothandiza pa ma antivayirasi kapena machitidwe osungira zinthu, makamaka chifukwa chakuti pansi pa macOS Pali njira zingapo "zophera" njira. Werengani pansipa kuti mudziwe zambiri ndi njira zodzitetezera.
Njira yachikale "kupha" njira
Njira yodziwika bwino yophera njira ndikutumiza chizindikiro cha SIGKILL kwa iyo. Mu bash, mutha kugwiritsa ntchito malamulo wamba a "kill -SIGKILL PID" kapena "pkill -9 NAME" kuti muphe. Lamulo la "kill" lakhalapo kuyambira masiku a UNIX ndipo likupezeka osati mu macOS, komanso pamakina ena ofanana ndi UNIX.
Monga momwe zilili ndi machitidwe ofanana ndi UNIX, macOS Imakulolani kuti mulepheretse chizindikiro chilichonse cha njira kupatula ziwiri—SIGKILL ndi SIGSTOP. Nkhaniyi ikuyang'ana kwambiri chizindikiro cha SIGKILL, chomwe chimayambitsa kupha kwa njira.
Zenizeni macOS
В macOS Kuyimba kwa dongosolo la kill mu XNU kernel kumatcha ntchito ya psignal(SIGKILL,…). Tiyeni tiyese kuwona zomwe zochita zina za ogwiritsa ntchito mu userspace zingatchule ntchito ya psignal. Tidzasefa mafoni ku ntchito ya psignal mu njira zamkati za kernel (ngakhale kuti zitha kukhala zopanda pake, tidzazisiya kuti zigwiritsidwe ntchito ina :)) - kutsimikizira siginecha, zolakwika pa kukumbukira, kutuluka/kuthetsa kusamalira, kuphwanya chitetezo cha mafayilo, ndi zina zotero.
Tiyeni tiyambe kuwunikiranso ndi ntchitoyo komanso kuyimba kofananira N'zoonekeratu kuti kuwonjezera pa kupha koyambirira, pali njira ina yomwe ndi yeniyeni pamakina ogwiritsira ntchito. macOS ndipo sichipezeka mu BSD. Mfundo zoyendetsera ntchito za mafoni onse awiriwa ndizofanana. Ndi mafoni olunjika ku ntchito ya kernel psignal. Dziwaninso kuti musanaphe njira, fufuzani "cansignal" - ngati njirayo ingatumize chizindikiro ku njira ina. Dongosolo sililola pulogalamu iliyonse kupha njira zamakina, mwachitsanzo.
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);
}
...
}
anayambitsa
Njira yodziwika bwino yopangira ma daemon pa nthawi yoyambira dongosolo ndikuwongolera nthawi yawo yonse ndi launchd. Dziwani kuti source code ndi ya mtundu wakale wa launchctl, isanayambe. macOS 10.10, zitsanzo za ma code zimaperekedwa kuti zigwiritsidwe ntchito pofotokoza. Launchctl yamakono imatumiza zizindikiro ku launchd kudzera mu XPC, ndipo launchctl logic yasunthidwira kumeneko.
Tiyeni tiwone momwe ndendende mapulogalamu amayimitsira. Musanatumize chizindikiro cha SIGTERM, ntchitoyo imayesedwa kuyimitsidwa pogwiritsa ntchito foni ya "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));
}
...
<>
Pansi pa hood, proc_terminate, ngakhale dzina lake, silingatumize psignal ndi SIGTERM, komanso SIGKILL.
Indirect Kill - Malire Othandizira
Nkhani yosangalatsa kwambiri imatha kuwoneka mu kuyimbira kwina kwadongosolo . Kugwiritsiridwa ntchito kofala kwa kuyimba kwadongosololi ndikuchepetsa zogwiritsira ntchito, monga cholozera kuti chichepetse nthawi ya CPU ndi ma memory quotas kuti dongosolo lisachedwe kwambiri ndi ntchito zosunga mafayilo. Ngati ntchito yafikira malire ake, monga momwe tingawonere kuchokera ku proc_apply_resource_actions ntchito, chizindikiro cha SIGKILL chimatumizidwa ku ndondomekoyi.
Ngakhale kuyitana kwa dongosololi kungathe kupha ndondomeko, dongosolo silinayang'ane mokwanira ufulu wa ndondomekoyi yomwe imayitana kuyitana kwadongosolo. Kufufuza , koma ndizokwanira kugwiritsa ntchito mbendera ya PROC_POLICY_ACTION_SET kuti mulambalale mkhalidwewu.
Chifukwa chake, ngati "muchepetsa" kuchuluka kwa kugwiritsa ntchito kwa CPU (mwachitsanzo, kulola 1 ns kuti igwire), ndiye kuti mutha kupha njira iliyonse mudongosolo. Chifukwa chake, pulogalamu yaumbanda imatha kupha njira iliyonse pamakina, kuphatikiza ma antivayirasi. Chosangalatsanso ndi zotsatira zomwe zimachitika mukapha njira ndi pid 1 (launchctl) - kernel panic poyesa kukonza chizindikiro cha SIGKILL :)

Kodi mungathetse bwanji vutoli?
Njira yowongoka kwambiri yopewera kuphedwa ndikusintha cholozera chantchito patebulo loyimba foni. Tsoka ilo, njira iyi si yachidule pazifukwa zambiri.
Choyamba, chizindikiro chomwe chimayang'anira malo okumbukira a sysent sichingokhala chachinsinsi ku chizindikiro cha XNU kernel, koma sichipezeka muzizindikiro za kernel. Muyenera kugwiritsa ntchito njira zofufuzira za heuristic, monga kusokoneza ntchitoyo ndikufufuza cholozera mmenemo.
Kachiwiri, kapangidwe kazolemba patebulo zimatengera mbendera zomwe kernel idapangidwa. Ngati mbendera ya CONFIG_REQUIRES_U32_MUNGING italengezedwa, kukula kwake kudzasinthidwa - gawo lina lidzawonjezedwa. . Ndikofunikira kuchita cheke chowonjezera kuti mudziwe kuti ndi mbendera iti yomwe idapangidwa ndi, kapenanso, fufuzani zolozera zogwirira ntchito motsutsana ndi omwe amadziwika.
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
*/
};
Mwamwayi, m'mabaibulo amakono macOS Apple imapereka API yatsopano yogwirira ntchito ndi njira. Endpoint Security API imalola makasitomala kuvomereza zopempha zambiri ku njira zina. Mwachitsanzo, zizindikiro zilizonse ku njira, kuphatikizapo chizindikiro cha SIGKILL, zitha kutsekedwa pogwiritsa ntchito API yomwe yatchulidwa pamwambapa.
#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;
}
Mofananamo, MAC Policy ikhoza kulembedwa mu kernel, yomwe imapereka njira yotetezera chizindikiro (policy proc_check_signal), koma API sichimathandizidwa mwalamulo.
Chitetezo chowonjezera cha Kernel
Kuwonjezera pa kuteteza njira zomwe zili mu dongosolo, ndikofunikiranso kuteteza kernel extension (kext) yokha. macOS IOKit imapereka dongosolo kwa opanga mapulogalamu kuti apange mosavuta madalaivala a chipangizo cha IOKit. Kupatula pakupereka zida zogwirira ntchito ndi zipangizo, IOKit imathandizira njira zosungira madalaivala pogwiritsa ntchito zochitika za kalasi ya C++. Pulogalamu ya malo ogwiritsira ntchito imatha "kupeza" zochitika za kalasi yolembetsedwa kuti ikhazikitse kulumikizana kwa kernel-userspace.
Kuti muwone kuchuluka kwa zochitika zamakalasi mudongosolo, pali ntchito ya ioclasscount.
my_kext_ioservice = 1
my_kext_iouserclient = 1
Kuwonjeza kulikonse kwa kernel komwe kukufuna kulembetsa ndi stack yoyendetsa kuyenera kulengeza kalasi yomwe imalandira cholowa kuchokera ku IOService, mwachitsanzo my_kext_ioservice pamenepa.Kulumikiza mapulogalamu a ogwiritsa ntchito kumapangitsa kupanga kwatsopano kwa kalasi yomwe imatenga cholowa kuchokera ku IOUserClient, mu chitsanzo my_kext_iouserclient.
Mukayesa kutsitsa dalaivala kuchokera padongosolo (kextunload command), ntchito yeniyeni "bool terminate (IOOptionBits options)" imatchedwa. Ndikokwanira kubweza zabodza pa kuyitana kuti muthe poyesa kutsitsa kuti mulepheretse kextunload.
bool Kext::terminate(IOOptionBits options)
{
if (!IsUnloadAllowed)
{
// Unload is not allowed, returning false
return false;
}
return super::terminate(options);
}
Mbendera ya IsUnloadAllowed ikhoza kukhazikitsidwa ndi IOUserClient potsegula. Pakakhala malire otsitsa, lamulo la kextunload libweza zotsatirazi:
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.
Chitetezo chofananira chiyenera kuchitidwa kwa IOUserClient. Zochitika zamakalasi zitha kutsitsidwa pogwiritsa ntchito ntchito ya IOKitLib "IOCatalogueTerminate(mach_port_t, uint32_t flag, io_name_t description);". Mutha kubweza zabodza mukamayitana lamulo la "terminate" mpaka ntchito ya "userspace" imwalira, ndiko kuti, ntchito ya "clientDied" siyimatchedwa.
Chitetezo cha Fayilo
Kuti muteteze mafayilo, ndikwanira kugwiritsa ntchito Kauth API, yomwe imakupatsani mwayi wolepheretsa mafayilo. Apple imapatsa opanga zidziwitso zokhudzana ndi zochitika zosiyanasiyana; kwa ife, machitidwe a KAUTH_VNODE_DELETE, KAUTH_VNODE_WRITE_DATA ndi KAUTH_VNODE_DELETE_CHILD ndi ofunikira. Njira yosavuta yoletsa kupeza mafayilo ndi njira - timagwiritsa ntchito "vn_getpath" API kuti tipeze njira yopita ku fayilo ndikufanizira njira yoyambira. Zindikirani kuti kukhathamiritsa kusinthidwanso kwamafoda a fayilo, makinawo samalola mwayi wofikira fayilo iliyonse, koma kufoda yomwe idasinthidwanso. Ndikofunikira kufananiza njira ya makolo ndikuletsa KAUTH_VNODE_DELETE pa izo.

Kuipa kwa njira iyi kungakhale kocheperako pamene chiwerengero cha ma prefixes chikuwonjezeka. Kuwonetsetsa kuti kufananitsa sikuli kofanana ndi O(prefix* length), pomwe choyambirira ndi chiwerengero cha prefixes, kutalika ndi kutalika kwa chingwe, mutha kugwiritsa ntchito deterministic finite automaton (DFA) yomangidwa ndi prefixes.
Tiyeni tikambirane njira yopangira DFA pagulu lina la prefixes. Timayambira zolozera kumayambiriro kwa chiyambi chilichonse. Ngati zolozera zonse ziloza ku chikhalidwe chomwecho, ndiye onjezerani cholozera chilichonse ndi khalidwe limodzi ndipo kumbukirani kuti kutalika kwa mzere womwewo ndi waukulu ndi umodzi. Ngati pali zolozera ziwiri zomwe zili ndi zizindikiro zosiyana, gawani zolozerazo m'magulu malinga ndi chizindikiro chomwe akuloza ndikubwereza ndondomeko ya gulu lirilonse.
Pachiyambi choyamba (zolemba zonse pansi pa zolozera ndizofanana), timapeza dziko la DFA lomwe liri ndi kusintha kumodzi kokha pamzere womwewo. M'chigawo chachiwiri, timapeza tebulo la kusintha kwa kukula 256 (chiwerengero cha zilembo ndi chiwerengero chachikulu cha magulu) kupita ku mayiko otsatirawa omwe akupezeka poyitana ntchitoyo mobwerezabwereza.
Tiyeni tione chitsanzo. Pamagulu oyambira (“/foo/bar/tmp/”, “/var/db/foo/”, “/foo/bar/aba/”, “foo/bar/aac/”) mukhoza kupeza zotsatirazi DFA. Chithunzichi chikuwonetsa kusintha komwe kumapita kumayiko ena; zosintha zina sizikhala zomaliza.

Mukadutsa m'maboma a DKA, pakhoza kukhala milandu itatu.
- Gawo lomaliza lafika - njirayo ndi yotetezedwa, timachepetsa ntchito KAUTH_VNODE_DELETE, KAUTH_VNODE_WRITE_DATA ndi KAUTH_VNODE_DELETE_CHILD
- Dziko lomaliza silinafike, koma njira "inatha" (chomaliza chinafikira) - njirayo ndi kholo, m'pofunika kuchepetsa KAUTH_VNODE_DELETE. Dziwani kuti ngati vnode ndi chikwatu, muyenera kuwonjezera '/' kumapeto, apo ayi akhoza kuchepetsa ku fayilo "/foor/bar/t", zomwe sizolondola.
- Dziko lomaliza silinafike, njirayo sinathe. Palibe prefixes yofanana ndi iyi, sitikudziwitsani zoletsa.
Pomaliza
Cholinga chopanga njira zotetezera ndikuwonjezera chitetezo cha ogwiritsa ntchito ndi deta yawo. Cholinga ichi chimakwaniritsidwa kudzera mukupanga mapulogalamu a Acronis, omwe amayang'anira zovuta zomwe zili mu operating system yokha. Kumbali ina, sitiyenera kunyalanyaza kulimbitsa mbali zachitetezo zomwe zingawongoleredwe kumbali ya OS, makamaka popeza kutseka zovuta zotere kumawonjezera kulimba mtima kwathu ngati chinthu. Kufooka kumeneku kunanenedwa ku Apple Product Security Team ndipo kunakonzedwa mu macOS 10.14.5 (https://support.apple.com/en-gb/HT210119).

Zonsezi zitha kuchitika pokhapokha ngati chida chanu chidayikidwa mwalamulo mu kernel. Izi zikutanthauza kuti palibe mipata yotere ya mapulogalamu akunja ndi osafunikira. Komabe, monga mukuonera, ngakhale kuteteza mapulogalamu ovomerezeka monga ma antivirus ndi ma backup system kumafuna khama. Koma tsopano, zinthu zatsopano za Acronis za macOS adzakhala ndi chitetezo chowonjezera kuti asatulutse zinthu kuchokera mu dongosololi.
Source: www.habr.com
