MacOS تي عملن ۽ ڪنيل ايڪسٽينشن کي ڪيئن محفوظ ڪجي

هيلو، حبر! اڄ آئون ڳالهائڻ چاهيندس ته توهان ڪيئن محفوظ ڪري سگهو ٿا پروسيس کي حملن کان حملن کان macOS ۾. مثال طور، هي هڪ اينٽي وائرس يا بيڪ اپ سسٽم لاءِ ڪارآمد آهي، خاص طور تي جڏهن ته macOS جي تحت هڪ عمل کي ”مارڻ“ جا ڪيترائي طريقا آهن. هن جي باري ۾ پڙهو ۽ ڪٽ هيٺ حفاظت جي طريقن.

MacOS تي عملن ۽ ڪنيل ايڪسٽينشن کي ڪيئن محفوظ ڪجي

هڪ عمل کي "مارڻ" جو کلاسک طريقو

هڪ عمل کي ”مارڻ“ جو مشهور طريقو اهو آهي ته عمل ڏانهن هڪ SIGKILL سگنل موڪليو وڃي. بش ذريعي توهان مارڻ لاءِ معياري ”kill -SIGKILL PID“ يا ”pkill-9 NAME“ سڏي سگهو ٿا. "مارڻ" حڪم UNIX جي ڏينهن کان معلوم ٿئي ٿو ۽ موجود آهي نه رڳو macOS تي، پر ٻين UNIX-جهڙوڪ سسٽم تي پڻ.

UNIX-like سسٽم وانگر، macOS توهان کي اجازت ڏئي ٿو ڪنهن به سگنل کي ڪنهن پروسيس ۾ مداخلت ڪرڻ کان سواء ٻه - SIGKILL ۽ SIGSTOP. اهو آرٽيڪل بنيادي طور تي SIGKILL سگنل تي ڌيان ڏيندو سگنل جي طور تي جيڪو عمل کي مارڻ جو سبب بڻائيندو آهي.

macOS خاصيتون

macOS تي، XNU ڪرنل ۾ مارڻ وارو نظام ڪال psignal (SIGKILL، ...) فنڪشن کي سڏي ٿو. اچو ته اهو ڏسڻ جي ڪوشش ڪريون ته يوزر اسپيس ۾ ٻين صارفن جي عملن کي psignal فنڪشن ذريعي سڏي سگهجي ٿو. اچو ته ڪنيل جي اندروني ميڪانيزم ۾ psignal فنڪشن کي ڪالون ختم ڪريون (جيتوڻيڪ اهي غير معمولي هوندا، اسان انهن کي ڪنهن ٻئي مضمون لاءِ ڇڏي ڏينداسين 🙂 - دستخط جي تصديق، ياداشت ۾ غلطيون، ٻاهر نڪرڻ / ختم ڪرڻ، هٿ ڪرڻ، فائل تحفظ جي ڀڃڪڙي، وغيره. .

اچو ته جائزو شروع ڪريون فنڪشن ۽ لاڳاپيل سسٽم ڪال سان ٽرمينيٽ_with_payload. اهو ڏسي سگھجي ٿو ته کلاسک مار ڪال کان علاوه، هڪ متبادل طريقو آهي جيڪو مخصوص آهي MacOS آپريٽنگ سسٽم ۽ BSD ۾ نه مليو آهي. ٻنهي سسٽم ڪالن جا آپريٽنگ اصول پڻ ساڳيا آهن. اهي ڪننل فنڪشن 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);
	}
...
}

لانچ ڪيو

سسٽم جي شروعات تي ڊيمن ٺاهڻ ۽ انهن جي زندگي جي وقت کي ڪنٽرول ڪرڻ جو معياري طريقو شروع ڪيو ويو آهي. مهرباني ڪري نوٽ ڪريو ته ذريعا لانچڪٽل جي پراڻي ورزن لاءِ macOS 10.10 تائين آهن، ڪوڊ جا مثال مثالي مقصدن لاءِ مهيا ڪيا ويا آهن. جديد لانچڪٽ ايل ايڪس پي سي ذريعي لانچ سگنل موڪلي ٿو، لانچ سي ايل منطق ان ڏانهن منتقل ڪيو ويو آهي.

اچو ته ڏسو ته ڪيئن مڪمل طور تي ايپليڪيشنن کي روڪيو ويو آهي. 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 پڻ.

اڻ سڌي طرح مارڻ - وسيلن جي حد

هڪ وڌيڪ دلچسپ ڪيس ٻئي سسٽم ڪال ۾ ڏسي سگھجي ٿو پروسيس_پاليسي. هن سسٽم ڪال جو هڪ عام استعمال ايپليڪيشن وسيلن کي محدود ڪرڻ آهي، جهڙوڪ هڪ انڊيڪسر لاءِ سي پي يو جي وقت ۽ ميموري ڪوٽا کي محدود ڪرڻ لاءِ ته جيئن فائل ڪيشنگ سرگرمين جي ڪري سسٽم کي خاص طور تي سست نه ڪيو وڃي. جيڪڏهن هڪ ايپليڪيشن پنهنجي وسيلن جي حد تائين پهچي چڪي آهي، جيئن proc_apply_resource_actions فنڪشن مان ڏسي سگهجي ٿو، هڪ SIGKILL سگنل پروسيس ڏانهن موڪليو ويو آهي.

جيتوڻيڪ هي سسٽم ڪال ممڪن طور تي هڪ عمل کي ختم ڪري سگهي ٿي، سسٽم مناسب طور تي سسٽم ڪال کي سڏڻ واري عمل جي حقن جي جانچ نه ڪئي. اصل ۾ چڪاس موجود هو, پر اھو ڪافي آھي متبادل پرچم استعمال ڪرڻ لاءِ PROC_POLICY_ACTION_SET ھن حالت کي نظرانداز ڪرڻ لاءِ.

ان ڪري، جيڪڏهن توهان ايپليڪيشن جي سي پي يو استعمال جي ڪوٽا کي "حد" ڪيو (مثال طور، صرف 1 اين ايس کي هلائڻ جي اجازت)، ته پوء توهان سسٽم ۾ ڪنهن به عمل کي ماري سگهو ٿا. اهڙيء طرح، مالويئر سسٽم تي ڪنهن به عمل کي ماري سگهي ٿو، بشمول اينٽي وائرس عمل. اهو پڻ دلچسپ اثر آهي جيڪو ٿئي ٿو جڏهن هڪ عمل کي مارڻ سان pid 1 (launchctl) - kernel panic جڏهن SIGKILL سگنل کي پروسيس ڪرڻ جي ڪوشش ڪندي :)

MacOS تي عملن ۽ ڪنيل ايڪسٽينشن کي ڪيئن محفوظ ڪجي

مسئلو ڪيئن حل ڪجي؟

ھڪڙي عمل کي مارڻ کان روڪڻ لاء سڀ کان وڌيڪ سڌو رستو سسٽم ڪال ٽيبل ۾ فنڪشن پوائنٽر کي تبديل ڪرڻ آھي. بدقسمتي سان، اهو طريقو ڪيترن ئي سببن لاء غير معمولي آهي.

پهرين، علامت جيڪا sysent جي ياداشت جي جڳهه کي سنڀاليندي آهي نه رڳو XNU ڪنييل علامت لاءِ پرائيويٽ آهي، پر ڪنيل علامتن ۾ نه ملي سگهي ٿي. توھان کي ھيورسٽڪ ڳولا جا طريقا استعمال ڪرڻا پوندا، جھڙوڪ فعل کي متحرڪ طور ڌار ڪرڻ ۽ ان ۾ ھڪ پوائنٽر ڳولڻ.

ٻيو، جدول ۾ داخلائن جي ڍانچي تي دارومدار رکي ٿو جھنڊو جن سان ڪنيل مرتب ڪيو ويو. جيڪڏهن CONFIG_REQUIRES_U32_MUNGING پرچم جو اعلان ڪيو ويو آهي، ساخت جي سائيز کي تبديل ڪيو ويندو - هڪ اضافي فيلڊ شامل ڪيو ويندو sy_arg_munge32. اهو ضروري آهي ته هڪ اضافي چيڪ ڪرڻ لاءِ اهو طئي ڪرڻ لاءِ ته ڪنيل کي ڪهڙي پرچم سان گڏ ڪيو ويو آهي، يا متبادل طور تي، سڃاتل ماڻهن جي خلاف فنڪشن پوائنٽرز کي چيڪ ڪريو.

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 جي جديد نسخن ۾، ايپل پروسيس سان ڪم ڪرڻ لاء هڪ نئون 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 سرڪاري طور تي سپورٽ نه آهي.

ڪني جي واڌ جي حفاظت

سسٽم ۾ عملن جي حفاظت ڪرڻ کان علاوه، ڪني جي واڌ جي حفاظت پاڻ کي (ڪيڪسٽ) پڻ ضروري آهي. macOS ڊولپرز لاءِ آساني سان IOKit ڊوائيس ڊرائيورز کي ترقي ڪرڻ لاءِ فريم ورڪ فراهم ڪري ٿو. ڊوائيسز سان ڪم ڪرڻ لاء اوزار مهيا ڪرڻ کان علاوه، IOKit C ++ ڪلاس جي مثالن کي استعمال ڪندي ڊرائيور اسٽيڪنگ لاء طريقا مهيا ڪري ٿو. يوزر اسپيس ۾ هڪ ايپليڪيشن ڪلاس جو هڪ رجسٽرڊ مثال ”ڳولڻ“ جي قابل هوندو ته ڪنيل-يوزر اسپيس تعلق قائم ڪرڻ لاءِ.

سسٽم ۾ ڪلاس مثالن جي تعداد کي ڳولڻ لاء، اتي موجود آهي ioclasscount افاديت.

my_kext_ioservice = 1
my_kext_iouserclient = 1

ڪو به ڪرنل ايڪسٽينشن جيڪو ڊرائيور اسٽيڪ سان رجسٽر ٿيڻ چاهي ٿو، ان کي لازمي طور تي هڪ ڪلاس جو اعلان ڪرڻ گهرجي جيڪو IOService کان ورثي ۾ ملي ٿو، مثال طور my_kext_ioservice هن صورت ۾. صارف ايپليڪيشنن کي ڳنڍڻ سبب ڪلاس جو هڪ نئون مثال پيدا ٿئي ٿو جيڪو IOUserClient کان ورثي ۾ آهي، مثال طور my_kext_iouserclient.

جڏهن سسٽم مان ڊرائيور کي لوڊ ڪرڻ جي ڪوشش ڪري رهيا آهيو (kextunload ڪمانڊ)، مجازي فنڪشن "بول ختم (IOOptionBits آپشنز)" سڏيو ويندو آهي. اهو ڪافي آهي ته ڪال تي غلط موٽڻ کي ختم ڪرڻ لاءِ جڏهن ڪيڪسٽون لوڊ کي بند ڪرڻ لاءِ ان لوڊ ڪرڻ جي ڪوشش ڪئي وڃي.

bool Kext::terminate(IOOptionBits options)
{

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

  return super::terminate(options);
}

IsUnloadAllowed پرچم IOUserClient طرفان سيٽ ڪري سگھجي ٿو جڏهن لوڊ ڪندي. جڏهن ڊائون لوڊ جي حد آهي، ڪيڪسٽونلوڊ حڪم هيٺ ڏنل ٻاھر موٽائي ڇڏيندو.

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 يوزر اسپيس فنڪشن "IOCatalogueTerminate(mach_port_t، uint32_t پرچم، io_name_t وضاحت)" استعمال ڪندي ان لوڊ ڪري سگھجن ٿا. توهان غلط موٽائي سگهو ٿا جڏهن ڪال ڪريو "ٽرمينيٽ" ڪمانڊ جيستائين يوزر اسپيس ايپليڪيشن "ڊيز" نه ٿئي، اهو آهي، "ڪلائنٽ ڊيڊ" فنڪشن نه سڏيو وڃي.

فائل جي حفاظت

فائلن کي بچائڻ لاءِ، اهو ڪافي آهي ڪائوٿ API استعمال ڪرڻ، جيڪو توهان کي فائلن تائين رسائي کي محدود ڪرڻ جي اجازت ڏئي ٿو. ايپل ڊولپرز کي مختلف واقعن بابت اطلاعن سان مهيا ڪري ٿو دائري ۾؛ اسان لاءِ، آپريشن KAUTH_VNODE_DELETE، KAUTH_VNODE_WRITE_DATA ۽ KAUTH_VNODE_DELETE_CHILD اهم آهن. فائلن تائين رسائي کي محدود ڪرڻ جو آسان طريقو رستو آهي - اسان استعمال ڪريون ٿا “vn_getpath” API فائل ڏانهن رستو حاصل ڪرڻ ۽ رستي جي اڳڪٿي جو مقابلو ڪرڻ لاءِ. نوٽ ڪريو ته فائل فولڊر جي رستن جي نالي کي بهتر ڪرڻ لاء، سسٽم هر فائل تائين رسائي جي اجازت نه ڏيندو آهي، پر صرف ان فولڊر ڏانهن جيڪو نالو تبديل ڪيو ويو آهي. اهو ضروري آهي ته پيرن واٽ جو مقابلو ڪيو وڃي ۽ ان لاءِ KAUTH_VNODE_DELETE کي محدود ڪيو وڃي.

MacOS تي عملن ۽ ڪنيل ايڪسٽينشن کي ڪيئن محفوظ ڪجي

ھن طريقي جو نقصان گھٽ ڪارڪردگي ٿي سگھي ٿو جيئن اڳين جو تعداد وڌي ٿو. انهي ڳالهه کي يقيني بڻائڻ لاءِ ته مقابلو O(prefix*length) جي برابر نه آهي، جتي اڳياڙي آهي اڳياڙين جو تعداد، ڊگھائي اسٽرنگ جي ڊگھائي آهي، توهان استعمال ڪري سگهو ٿا هڪ deterministic finite automaton (DFA) اڳياڙين سان ٺهيل.

اچو ته هڪ DFA ٺاھڻ جي ھڪڙي طريقي تي غور ڪريون پريفڪس جي ڏنل سيٽ لاءِ. اسان هر اڳياڙيءَ جي شروعات ۾ ڪرسر کي شروع ڪريون ٿا. جيڪڏهن سڀئي ڪرسر هڪ ئي ڪردار ڏانهن اشارو ڪن ٿا، ته پوءِ هر ڪرسر کي هڪ اکر کان وڌايو ۽ ياد رکو ته ساڳئي لڪير جي ڊيگهه هڪ کان وڌيڪ آهي. جيڪڏهن ٻه ڪرسر آهن مختلف علامتن سان، ڪرسرن کي گروپن ۾ ورهايو انهن علامتن جي مطابق جنهن ڏانهن اهي اشارو ڪن ٿا ۽ هر گروپ لاءِ الگورتھم ورجائي.

پهرين صورت ۾ (سڀ اکر هيٺان ڪرسر ساڳيا آهن)، اسان هڪ DFA رياست حاصل ڪندا آهيون جنهن ۾ هڪ ئي لڪير سان صرف هڪ منتقلي آهي. ٻئي صورت ۾، اسان کي 256 سائيز (ڪردارن جو تعداد ۽ گروپن جو وڌ ۾ وڌ تعداد) جي منتقلي جي جدول ايندڙ رياستن کي حاصل ڪريون ٿا جيڪو فنڪشن کي بار بار ڪال ڪندي حاصل ڪيو ويو آهي.

اچو ته هڪ مثال ڏسو. اڳڪٿين جي ھڪڙي سيٽ لاءِ (“/foo/bar/tmp/”، “/var/db/foo/”، “/foo/bar/aba/”، “foo/bar/aac/”) توھان ھيٺ ڏنل حاصل ڪري سگھو ٿا ڊي ايف اي. انگ اکر صرف ٻين رياستن ڏانهن منتقلي ڏيکاري ٿو؛ ٻيون منتقلي حتمي نه هوندي.

MacOS تي عملن ۽ ڪنيل ايڪسٽينشن کي ڪيئن محفوظ ڪجي

جڏهن DKA رياستن جي ذريعي وڃڻ، اتي ٿي سگهي ٿو 3 ڪيس.

  1. آخري حالت تي پهچي ويو آهي - رستو محفوظ آهي، اسان آپريشن کي محدود ڪريون ٿا KAUTH_VNODE_DELETE، KAUTH_VNODE_WRITE_DATA ۽ KAUTH_VNODE_DELETE_CHILD
  2. آخري حالت تي پهچي نه ويو، پر رستو "ختم" (نال ٽرمينيٽر پهچي ويو) - رستو هڪ والدين آهي، اهو ضروري آهي ته KAUTH_VNODE_DELETE کي محدود ڪيو وڃي. نوٽ ڪريو ته جيڪڏهن vnode هڪ فولڊر آهي، توهان کي آخر ۾ هڪ '/' شامل ڪرڻ جي ضرورت آهي، ٻي صورت ۾ اهو ان کي فائل تائين محدود ڪري سگهي ٿو "/foor/bar/t"، جيڪو غلط آهي.
  3. آخري حالت تي پهچي نه سگهيو، رستو ختم نه ٿيو. ڪو به اڳڪٿي هن سان نه ٿو ملي، اسان پابنديون متعارف نه ٿا ڪريون.

ٿڪل

ترقي يافته سيڪيورٽي حل جو مقصد صارف ۽ سندس ڊيٽا جي سيڪيورٽي جي سطح کي وڌائڻ آهي. هڪ طرف، هي مقصد حاصل ڪيو ويو آهي ترقي ڪندي Acronis سافٽ ويئر پراڊڪٽ، جيڪو انهن خطرن کي بند ڪري ٿو جتي آپريٽنگ سسٽم پاڻ کي "ڪمزور" آهي. ٻئي طرف، اسان کي انهن حفاظتي پهلوئن کي مضبوط ڪرڻ ۾ غفلت نه ڪرڻ گهرجي جيڪي او ايس پاسي ۾ بهتر ٿي سگهن ٿيون، خاص طور تي جيئن ته اهڙين خامين کي بند ڪرڻ اسان جي پنهنجي استحڪام کي پيداوار جي طور تي وڌائي ٿو. ايپل پراڊڪٽ سيڪيورٽي ٽيم کي نقصان جي اطلاع ڏني وئي ۽ macOS 10.14.5 (https://support.apple.com/en-gb/HT210119) ۾ مقرر ڪئي وئي آهي.

MacOS تي عملن ۽ ڪنيل ايڪسٽينشن کي ڪيئن محفوظ ڪجي

اهو سڀ صرف تڏهن ٿي سگهي ٿو جڏهن توهان جي افاديت کي سرڪاري طور تي ڪنييل ۾ نصب ڪيو ويو آهي. اهو آهي، ٻاهرئين ۽ ناپسنديده سافٽ ويئر لاء ڪو به اهڙيون خاميون نه آهن. بهرحال، جيئن توهان ڏسي سگهو ٿا، جيتوڻيڪ جائز پروگرامن کي تحفظ ڏيڻ جهڙوڪ اينٽي وائرس ۽ بيڪ اپ سسٽم ڪم جي ضرورت آهي. پر هاڻي MacOS لاءِ نئين Acronis پروڊڪٽس کي سسٽم مان لوڊ ڪرڻ جي خلاف اضافي تحفظ حاصل هوندو.

جو ذريعو: www.habr.com

تبصرو شامل ڪريو