Skip to content
KitploitKITPLOIT
उपकरणब्लॉग
जमा करें
उपकरणब्लॉग
जमा करें

हैकिंग, पेनटेस्ट और साइबर सुरक्षा उपकरण आपके सुरक्षा शस्त्रागार के लिए!

Kitploit हैकिंग, साइबर सुरक्षा और पेंटेस्टिंग टूल्स की एक निर्देशिका है। कमजोरियों को खोजने, सिस्टम का विश्लेषण करने, परीक्षण को स्वचालित करने और अपनी सुरक्षा को मजबूत करने के लिए नवीनतम प्रोजेक्ट अपडेट खोजें।

··फ़ीड·संपर्क·गोपनीयता·© 2026 Kitploit

टूल निर्देशिका

श्रेणियाँ

सभी श्रेणियाँ देखें
Loading categories
ifuncd-up — GNU IFUNC, CVE-2024-3094 के पीछे असली कारण है | Kitploit
उपकरण/GitHubGitHub/robertdfrench/ifuncd-up
भेद्यता विश्लेषणगतिशील कोड विश्लेषण (DAST)शोषणरिवर्स इंजीनियरिंगबाइनरी विश्लेषणआपूर्ति श्रृंखला सुरक्षापेपर और शोधलर्निंग और शिक्षा
GitHubrobertdfrench/ifuncd-up

ifuncd-up

GNU IFUNC, CVE-2024-3094 के पीछे असली कारण है

रिपॉजिटरी देखें
6013 महीने पहलेKitploit द्वारा समीक्षित

सबसे लोकप्रिय

सभी देखें →

हमारे समुदाय द्वारा सबसे अधिक उपयोग किए जाने वाले उपकरण खोजें।

सभी उपकरण खोजें

हमारे उपकरणों का संग्रह ब्राउज़ करें

सभी उपकरण देखें →
साझा करें
वेबसाइट

हैकर न्यूज़ के जवाब में

मैं देख रहा हूँ कि [नारंगी वेबसाइट][hn] पर तुम जोकर मुझे परेशान कर रहे हो। मैं नीचे कुछ चुनिंदा जवाब दूँगा, लेकिन पहले मैं एक चुनौती पेश करता हूँ: मैं अपने निजी $500 उस पहले व्यक्ति को भेजूँगा जो बिना ifunc के इस हमले का प्रदर्शन कर सके। मैं वास्तव में उत्सुक हूँ, और इस ज्ञान के लिए पैसे देने को तैयार हूँ। इस रिपो को फोर्क करें और अपने काम करते PoC के साथ एक PR जमा करें, जीतने पर मैं आपका डाक पता निजी तौर पर माँगूँगा। अब जवाबों पर:

यह गलत पेड़ पर भौंक रहा है।

बच्चे, मैं उसी गलत पेड़ में रहता हूँ, मैं जिसे चाहूँ भौंक सकता हूँ।

यह शोषण के लिए आवश्यक नहीं था,

तुम शोषण के लिए आवश्यक नहीं हो!

अगर हम root के रूप में चलने वाले मनमाने कोड के खिलाफ सुरक्षा जोड़ना चाहते हैं तो selinux हमेशा मौजूद है।

एक बार लोड होने के बाद, इस हमले को किसी और syscall सीमा पार करने की आवश्यकता नहीं थी। तो हाँ, हम एक "बोनस" root सत्र को प्रतिबंधित कर सकते थे, लेकिन फिर भी मशीन पर अनामंत्रित मेहमान होते!

यह क्या है, बिल्बो का जन्मदिन?? पार्टी के काम के अलावा कोई प्रवेश नहीं!!

  1. main से पहले कोड चलाने का IFUNC शायद ही एकमात्र तरीका है।

लेकिन यह मेमोरी सुरक्षा स्थापित होने से पहले कोड चलाने का एक अनावश्यक तरीका है।

  1. उनके द्वारा प्रस्तुत विकल्प तर्कसंगत रूप से कम सुरक्षित है क्योंकि function pointer प्रक्रिया के जीवन भर लिखने योग्य बना रहेगा,

हम mprotect के साथ सुधार कर सकते हैं! Modifying LD_PRELOAD उपखंड से ऊपर अंतिम वाक्य देखें।

हाँ, यह ब्लॉग पथभ्रमित है।

माफ कीजिए, यह ब्लॉग बिना मार्गदर्शन के था। ये सारी शरारतें मैंने खुद कीं! किसी ने मुझे इतना मूर्ख बनने के लिए धोखा नहीं दिया।

IFUNC को [क्लाइंट] सॉफ़्टवेयर द्वारा ही लागू किया जाना चाहिए,

@CountWSS 💯 बिल्कुल हाँ

GitHub अनुरक्षक से लेकर ... तक स्पष्ट प्रक्रियागत विफलताओं की एक श्रृंखला

यह एकमात्र बिंदु है जिसका मैं गंभीरता से जवाब दूँगा:

मुझे लगता है कि इसे उनकी ओर से की गई गलती के रूप में शुरू मानना xz-utils अनुरक्षक के प्रति अत्यंत अन्यायपूर्ण है और समुदाय के लिए काफी खतरनाक है। इसकी शुरुआत इस बात से हुई कि किसी ने भी इस परियोजना को बनाए रखने में मदद करने की परवाह नहीं की। हमलावर ने ifunc को एक तकनीकी कमजोरी और xz-utils के प्रति हमारी सामूहिक उपेक्षा को एक सामाजिक कमजोरी के रूप में इस्तेमाल किया। मुझे श्री कॉलिन के कार्यों को सामुदायिक सेवा के प्रति एक वीरतापूर्ण, वर्षों लंबे समर्पण के अलावा कुछ और मानना शर्मनाक लगता है।

और ब्रूस श्नियर मुझसे सहमत हैं तो... आपको बुरा लगे, आपकी दलील खत्म।

भाषा शायद आवश्यकता से अधिक कठोर रही हो

आपको यकीन नहीं होगा कि मेरे दोस्तों ने मुझे पहले इसे कितना नरम करने पर मजबूर किया।

लिनक्स वितरणों को अपने बारे में इतना ऊँचा नहीं सोचना चाहिए कि वे OpenBSD से अपनी गड़बड़ी के अनुरूप ढलने और उसे अपनाने की उम्मीद करें।

@debazel!!! Me gusta.

क्या पूरी बकवास है।

ठीक है, वह हिस्सा सटीक है।

IFUNC'd up

आपको xz-utils को [CVE-2024-3094][nvd] के लिए दोष देना क्यों बंद कर देना चाहिए। साथ ही मेरी ETSA Talk ज़रूर देखें!

मुझे लगता है IFUNC'd up

CVE-2024-3094, जिसे आमतौर पर "xz-utils बैकडोर" के रूप में जाना जाता है, वैश्विक साइबर सुरक्षा के लिए एक निकट-चूक था। यदि यह हमला समय रहते [Andres Freund][freund] द्वारा खोजा नहीं गया होता, तो हमारे ग्रह के अधिकांश SSH सर्वर इस हमले के पीछे की पार्टी को root एक्सेस देना शुरू कर देते।

दुर्भाग्य से, बहुत अधिक विश्लेषण इस बात पर केंद्रित रहा है कि [दुर्भावनापूर्ण कोड][JiaT75] xz-utils रिपो में कैसे पहुँचा। इसके बजाय, मैं यह तर्क देना चाहूँगा कि महत्वपूर्ण ओपन सोर्स सॉफ़्टवेयर में दो लंबे समय से चले आ रहे डिज़ाइन निर्णयों ने इस हमले को संभव बनाया: [OpenSSH को SystemD से जोड़ना][biebl], और [GNU IFUNC][sourceware] का अस्तित्व।

शुरू करने से पहले: इस चर्चा का अधिकांश भाग लिनक्स पर डायनेमिक लिंकिंग की पेचीदगियों से संबंधित है। यदि आपको पुनश्चर्या की आवश्यकता है, तो dynamic_linking.md देखें।

CVE-2024-3094 का त्वरित पुनर्कथन

xz-utils बैकडोर के उच्च-स्तरीय विवरणों को रेखांकित करने वाले बहुत सारे अच्छे लेख हैं, जैसे डैन गुडिन का [xz Utils बैकडोर के बारे में हम क्या जानते हैं जिसने लगभग दुनिया को संक्रमित कर दिया था][goodin1] और सैम जेम्स का [xz-utils बैकडोर (CVE-2024-3094) पर FAQ][thesamesam] gist। हमें यहाँ वह सब दोहराने की आवश्यकता नहीं है, इसलिए इस लेख के प्रयोजनों के लिए, यहाँ एक बहुत मोटा पुनर्कथन है:

  • कुछ Linux डिस्ट्रो OpenSSH को SystemD पर निर्भर करने के लिए संशोधित करते हैं
  • SystemD xz-utils पर निर्भर करता है, जो GNU IFUNC का उपयोग करता है
  • अतः, xz-utils OpenSSH के एड्रेस स्पेस में पहुँच जाता है
  • यह ifunc को SSH सर्वर में कोड संशोधित करने की अनुमति देता है```mermaid flowchart TD G["GNU IFUNC"] A["OpenSSH (OpenBSD)"] B["Portable OpenSSH
    (Linux / macOS / etc)"] C[OpenSSH + IFUNC] D[xz-utils] E["SystemD (Linux)"] A -->|Remove OpenBSD specifics| B B -->|Add SystemD specifics| C D --> E E --> C C --> F["Mayhem"] G --> D
root@kitploit:~
## लिनक्स डिस्ट्रोस OpenSSH को क्यों संशोधित करते हैं?

संक्षिप्त उत्तर यह है कि उन्हें करना पड़ता है। OpenSSH को OpenBSD समुदाय द्वारा, OpenBSD समुदाय के लिए विकसित किया गया है, और वे लिनक्स की ज़रा भी परवाह नहीं करते।  [Portable OpenSSH][mindrot] परियोजना पैचों का एक best-effort संग्रह है जो OpenBSD-विशिष्ट घटकों को सामान्य POSIX घटकों से बदलता है, और जहाँ प्रासंगिक हो वहाँ कुछ प्लेटफ़ॉर्म-विशिष्ट कोड भी शामिल करता है। SSH के लिए सॉफ़्टवेयर सप्लाई-चेन व्यवहार में कुछ इस प्रकार दिखती है:```mermaid
flowchart TD
  subgraph OpenBSD Folks
    A[OpenBSD]
    B[OpenSSH]
    H[improvements]
  end
  B-->A
  A-->H
  H-->B

  B-->C
  C[Portable OpenSSH]

  subgraph Debian Folks
    D[Debian SSH]
    G[improvements]
  end
  C-->D
  D-->G
  G-->C

  subgraph Fedora Folks
    J[Fedora SSH]
    K[improvements]
  end
  C-->J
  J-->K
  K-->C

OpenBSD का OpenSSH संस्करण बाकी सबसे upstream है, और अधिकांश सुधार OpenBSD समुदाय के भीतर से आते हैं। ये परिवर्तन Portable OpenSSH प्रोजेक्ट तक downstream प्रवाहित होते हैं, जो प्रयास करता है कि नई सुविधाओं को ऐसे तरीकों से फिर से लागू किया जाए जो OpenBSD-विशिष्ट न हों। यही वह है जो SSH को Linux, macOS, FreeBSD, और यहाँ तक कि Windows पर भी काम करने की अनुमति देता है।

लेकिन यह यहीं नहीं रुकता। कुछ ऑपरेटिंग सिस्टम आगे भी Portable OpenSSH द्वारा प्रदान की गई सुविधाओं से परे अनुकूलन लागू करते हैं। उदाहरण के लिए, Apple ssh-add में [--apple-use-keychain][keith] फ्लैग जोड़ता है ताकि उसे macOS पासवर्ड मैनेजर के साथ एकीकृत होने में मदद मिल सके।

CVE-2024-3094 के मामले में, Fedora और Debian ने अपने OpenSSH forks के लिए अपने स्वयं के [SystemD patches][biebl] बनाए रखे, ताकि एक [sshd रीस्टार्ट के आसपास की race condition][schmidt] को ठीक किया जा सके। तो वास्तविक आपूर्ति श्रृंखला SSH की इस तरह दिखने लगी:```mermaid flowchart TD A[OpenSSH] B[Portable OpenSSH] C[Debian SSH] D[Fedora SSH] A-->B B-->C B-->D C<-->|SystemD Patches|D

root@kitploit:~
ये पैच Portable OpenSSH में कभी नहीं गए, क्योंकि Portable
OpenSSH टीम ["libsystemd पर निर्भरता लेने में interested नहीं थी"][djmdjm]। और ये upstream OpenSSH में भी कभी नहीं गए, क्योंकि
OpenBSD को SystemD का समर्थन करने की कोई आवश्यकता नहीं है।



### "Separation of Concerns" के बारे में चिंताएँ
यह काफी हानिरहित लगता है, लेकिन यह Open Source में, विशेष रूप से Linux में, एक बहुत बड़ी समस्या का उदाहरण है: ऑपरेटिंग सिस्टम के महत्वपूर्ण घटक
उन लोगों द्वारा विकसित किए जाते हैं जो एक-दूसरे को नहीं जानते, और
एक-दूसरे से बात नहीं करते।

* क्या जिन लोगों ने SystemD के लिए OpenSSH को पैच किया, वे जानते (या परवाह करते) थे कि
  libsystemd xz-utils पर निर्भर करता है?
* क्या SystemD वाले जानते (या परवाह करते) थे कि xz-utils ने
  ifunc का उपयोग शुरू कर दिया था?
* क्या OpenSSH वाले जानते (या परवाह करते) थे कि ifunc जैसी कोई चीज़ है? यह
  निश्चित रूप से OpenBSD पर कोई चीज़ नहीं है।

कुछ अर्थों में, संचार में यह टूट-फूट open source की एक विशेषता है:
मैं आपके काम को अपनी आवश्यकताओं के अनुसार ढाल सकता हूँ, बिना आपको इसके बारे में परेशान किए।
लेकिन यह अप्रत्यक्षता की एक ऐसी डिग्री भी पैदा कर सकता है जो महत्वपूर्ण डिज़ाइन
मान्यताओं (जैसे कि पारंपरिक dynamic linking प्रक्रिया) को बनाए रखने से रोकता है।

[Conway's Law][conway] का स्पष्ट अनुमानित परिणाम यह है कि यदि आप
अपना org chart ship कर रहे हैं, तो आप उन bugs को भी ship कर रहे हैं जो
आपके org chart की दरारों में रहते हैं। यहाँ किसी एक व्यक्ति या टीम ने वास्तव में
कोई गलती नहीं की, लेकिन पूर्वज्ञान के लाभ के साथ यह स्पष्ट है कि हमलावरों ने
महसूस किया कि Debian/Fedora SSH के बाएँ हाथ को नहीं पता था कि
xz-utils का दायाँ हाथ क्या कर रहा था।




## GNU IFUNC को *क्या* करना चाहिए?
यह आपको runtime पर यह निर्धारित करने की अनुमति देता है कि आप किसी फ़ंक्शन का
कौन सा संस्करण उपयोग करना चाहते हैं। यह आपको **arbitrary code**
चलाने का अवसर देकर ऐसा करता है ताकि linker symbols को कैसे resolve करता है, उसे प्रभावित किया जा सके।

![](https://assets.kitploit.com/production/public/readmes/31477/ea52603b42c9b38ff0f8f693b09c5d5c0d107a4175f3be4e1e48b39c9ca3eb55.png)



### CPU Features का पता लगाना
मान लीजिए आपके पास एक एप्लिकेशन है जिसे x86 CPUs की एक विस्तृत विविधता पर चलना चाहिए।
वर्तमान CPU की विशिष्ट विशेषताओं के आधार पर, आप उसी कार्य के लिए
विभिन्न एल्गोरिदम का उपयोग करना पसंद कर सकते हैं। IFUNC के पीछे मूल विचार
यह था कि प्रोग्राम को पहली बार फ़ंक्शन कॉल होने पर CPU सुविधाओं की जाँच करने दिया जाए, और उसके बाद
उस CPU के लिए सबसे उपयुक्त implementation का उपयोग किया जाए।

[`cpu_demo.c`](https://github.com/robertdfrench/ifuncd-up/blob/HEAD/code/cpu_demo.c) पर एक नज़र डालें:```c
void print_cpu_info() __attribute__((ifunc ("resolve_cpu_info")));
void print_avx2() { printf("AVX2 is present.\n"); }
void print_nope() { printf("AVX2 is missing.\n"); }

static void* resolve_cpu_info(void) {
    __builtin_cpu_init();

	if (__builtin_cpu_supports("avx2")) {
		return print_avx2;
	} else {
		return print_nope;
	}
}

int main() {
	print_cpu_info();
	return 0;
}

This program shows the most common use of IFUNC: it asks the CPU whether or not it supports certain features, and provides a different implementation of a function depending on what features are supported. In this case, our function print_cpu_info will end up printing either "AVX2 is present" or "AVX2 is missing" depending on how ancient your CPU is.

Probing the Process Environment

While IFUNC is intended for probing CPU capabilities, nothing stops you from running more complicated code in your resolvers. For example, tty_demo.c shows how you can load a different function implementation depending on whether STDOUT is a file or a terminal:```c // Print Green text to the Terminal void print_to_tty(const char *message) { const char *green_start = "\033[32m"; const char *color_reset = "\033[0m"; printf("%sTTY: %s%s\n", green_start, message, color_reset); }

// Print plain text to a file void print_to_file(const char *message) { printf("FILE: %s\n", message); }

void print_message(const char *message)
attribute((ifunc("resolve_print_function")));

void (*resolve_print_function(void))(const char *) { struct termios term;

root@kitploit:~
// Ask the kernel whether stdout is a file or a tty
int result = ioctl(STDOUT_FILENO, TCGETS, &term);
if (result == 0) {
    // stdout is a terminal
    return print_to_tty;
} else {
    // stdout is not a terminal
    return print_to_file;
}

}

int main() { print_message("Hello, World!"); return 0; }

root@kitploit:~
यह IFUNC का वास्तविक इच्छित उपयोग नहीं है, लेकिन यह दिखाता है कि क्या संभव है: आप ऐसे किसी भी प्रोग्राम में `main` से पहले मनमाना कोड चला सकते हैं जो आपके द्वारा घोषित IFUNC का उपयोग करता है।





## IFUNC शायद एक बुरा विचार है
![](https://assets.kitploit.com/production/public/readmes/31477/6d420d0d1b4f4c49a3ba8a4b2103d7f79d284c9d8fbda4449e6e6d0afa5b3cfa.png)

GNU IFUNC को लागू करना कठिन है, सही ढंग से उपयोग करना मुश्किल है, और (एक कथित प्रदर्शन उपकरण के रूप में) यह विकल्पों की तुलना में बहुत तेज़ नहीं है। जैसा कि हमने CVE-2024-3094 के साथ देखा है, यह सॉफ़्टवेयर आपूर्ति-श्रृंखला हमलों के लिए भी एक बहुत शक्तिशाली उपकरण है।

IFUNC का उपयोग GNU C Library के भीतर बड़े पैमाने पर किया जाता है, और यह शायद ठीक है। वे वही लोग हैं जिनके लिए इसे मूल रूप से विकसित किया गया था, और वे कंपाइलर और लिंकर टीमों से निकटता से जुड़े हुए हैं जो वास्तव में IFUNC को लागू करते हैं। वे ट्रेड-ऑफ़ को समझने की सर्वोत्तम स्थिति में हैं, और बहुत सारे libc फ़ंक्शन हैं जो CPU-विशिष्ट कार्यान्वयन से लाभान्वित होते हैं। मेरा मानना है कि हमें IFUNC को glibc के लिए एक आंतरिक इंटरफ़ेस मानना चाहिए, और अन्य अनुप्रयोगों में इसके उपयोग से बचना चाहिए।



### इसे सुरक्षित रूप से उपयोग करना बहुत भ्रमित करने वाला है
ifunc का उपयोग करना नितांत कठिन है। बहुत सारे [कोने के मामले][nagy] हैं, और [आधिकारिक दस्तावेज़ीकरण][gnu-cfa] [अपर्याप्त][sourceware] है। यह उपयोगकर्ताओं को गलत धारणा देता है कि ifunc को अपनाना सीधा है।

ifunc उपलब्ध होने के कई वर्षों बाद भी, विज्ञापित इंटरफ़ेस [काम नहीं करता था][agner]। GCC डेवलपर्स ने इसे [एक गलती][odonell] कहा है और IFUNC की नाजुकता की भरपाई के लिए चेतावनियाँ जोड़ने पर विचार किया है:

> glibc समाधान जो IFUNC को मजबूत बनाने के लिए आवश्यक हैं, मौजूद नहीं हैं,
> और इसलिए हमें उपयोगकर्ताओं को चेतावनी देने के लिए जो भी कर सकते हैं करना चाहिए कि यह टूट सकता है।

यह केवल IFUNC ही नहीं है। Apple Mach-O में एक समान सुविधा है जिसे `.symbol_resolver` कहा जाता है, जिसे उन्होंने ["जोड़ने पर पछतावा"][rjmccall] जताया है।



### यह RELRO को कमज़ोर करता है
जब Global Offset Table अभी भी लिखने योग्य हो, तब मनमाना कोड चलाने की अनुमति देकर, [RELRO](https://github.com/robertdfrench/ifuncd-up/blob/HEAD/dynamic_linking.md#relro) द्वारा प्रदत्त सुरक्षाएं [निष्प्रभावी][binarly-io] हो जाती हैं। 

यह ध्यान देने योग्य महत्वपूर्ण है, क्योंकि RELRO स्वयं को गतिशील रूप से लोड किए गए प्रतीकों की अखंडता की रक्षा करने के एक तरीके के रूप में प्रचारित करता है। उपयोगकर्ता के दृष्टिकोण से (आप, कंपाइलर और लिंकर के उपयोगकर्ता के रूप में), यह [कम से कम आश्चर्य का सिद्धांत][pola] का उल्लंघन करता है: कोई भी समझदार व्यक्ति यह उम्मीद नहीं करेगा कि *डायनामिक लाइब्रेरी लोड करना* एक सुरक्षा सुविधा से समझौता करे जो *डायनामिक लाइब्रेरीज़ की सुरक्षा करने* के लिए बनाई गई है।

![](https://assets.kitploit.com/production/public/readmes/31477/ad252f1cb2937e3f8b168ece1e3f15455dcb0d7647b8715dff7435f3babc0e1c.png)



### यह हमेशा आवश्यक नहीं है
इस स्थिति से निपटने के कई अन्य तरीके हैं। उनमें से प्रत्येक के अलग-अलग ट्रेड-ऑफ़ हैं, लेकिन वे सभी IFUNC की तुलना में कहीं अधिक सरल हैं। ये सभी IFUNC की तुलना में अधिक पोर्टेबल, समझने में आसान और शोषण करने में कठिन हैं।

> "Ifunc रनटाइम माइक्रोआर्क विशिष्ट कोड चयन करने का बिल्कुल बेवकूफी भरा तरीका है।"
>
> -- [Rich Felker](https://hachyderm.io/@dalias/112952237145378821),
> [musl](https://musl.libc.org) के अनुरक्षक।


#### ग्लोबल फंक्शन पॉइंटर्स
IFUNC आकर्षक है क्योंकि यह डेवलपर्स को फ़ंक्शन चयन को *घोषणात्मक रूप से* व्यक्त करने की अनुमति देता है न कि *अनिवार्य रूप से*। लेकिन इसे अनिवार्य रूप से करना वास्तव में उतना कठिन नहीं है। [`static_pointer.c`](https://github.com/robertdfrench/ifuncd-up/blob/HEAD/code/static_pointer.c) पर विचार करें, जो रनटाइम पर एक ग्लोबल फ़ंक्शन पॉइंटर को हल करता है:```c
static int (*triple)(int) = 0;
int triple_sse42(int n) { return 3 * n; }
int triple_plain(int n) { return n + n + n; }

void print_fifteen() {
	int fifteen = triple(5);
	printf("%d\n", fifteen);
}

int main() {
	__builtin_cpu_init();
	if (__builtin_cpu_supports("sse4.2")) {
		triple = triple_sse42;
	} else {
		triple = triple_plain;
	}
	
	print_fifteen();
	return 0;
}

क्या यह सच में इतना बुरा है कि हमें लिंकर में विशेष तरकीबों की ज़रूरत है, सिर्फ इससे बचने के लिए?

इस दृष्टिकोण का एक नुकसान यह है कि फ़ंक्शन पॉइंटर triple रनटाइम पर लिखने योग्य है, जबकि IFUNC+RELRO यह सुनिश्चित करेगा कि ifunc पते GOT में एक बार हल हो जाने के बाद अपरिवर्तनीय हों। हालाँकि, थोड़े अतिरिक्त प्रयास से, हम ऐसे पॉइंटर्स को रीड-ओनली चिह्नित करने के लिए [mprotect(2)][mprotect] का उपयोग कर सकते हैं।

LD_PRELOAD को संशोधित करना

यदि आप जानते हैं कि आपके कोड को किन CPU सुविधाओं की आवश्यकता है, और आपके पास प्रत्येक मामले के लिए अपनी डायनामिक लाइब्रेरी की एक अलग प्रति है, तो आप $LD_PRELOAD के साथ सही लाइब्रेरी निर्दिष्ट करके भी यही काम पूरा कर सकते हैं जैसे:```bash #!/bin/bash if (cat /proc/cpuinfo | grep flags | grep avx2 > /dev/null); then LD_PRELOAD=./myfunc_avx2.so ./my_app else LD_PRELOAD=./myfunc_normal.so ./my_app fi

root@kitploit:~
(अगर आप `LD_PRELOAD` से परिचित नहीं हैं, तो catonmat का ["एक सरल
`LD_PRELOAD` ट्यूटोरियल"][catonmat] देखें।)



#### प्रति फीचर संयोजन अलग बाइनरीज़
आपको वास्तव में कितने अद्वितीय CPU फीचर संयोजनों का समर्थन करने की आवश्यकता है?
कितने मौजूद भी हैं?

पहली नज़र में, यह एक संयोजनात्मक विस्फोट जैसा लगता है। amd64 ISA में
दर्जनों अलग-अलग वेक्टर अंकगणित, वर्चुअलाइज़ेशन और सुरक्षा एक्सटेंशन हैं।
लेकिन ये सुविधाएँ वास्तविक दुनिया में स्वतंत्र रूप से नहीं पाई जातीं।
उदाहरण के लिए, ऐसा कोई CPU नहीं है जिसमें AVX-512 हो लेकिन SSE4.2 या AES-NI न हो।

यह जानना कि आपके एप्लिकेशन को किन CPU सुविधाओं की आवश्यकता है, और
उनमें से कौन सी वास्तविक चिप्स पर एक साथ पाई जाती हैं, यह निर्धारित करने में मदद
कर सकता है कि आपको कितने अलग-अलग बाइनरी भेजने होंगे। यह उतने नहीं हो सकते
जितने आप अपेक्षा करते हैं। अधिकांश पैकेज मैनेजर आपको इंस्टॉल के समय स्क्रिप्ट
चलाने की अनुमति देते हैं; आप एक ही rpm या deb फ़ाइल में कई बाइनरी भेज सकते हैं और
होस्ट CPU के लिए सर्वश्रेष्ठ चुनने हेतु इंस्टॉल-समय तर्क का उपयोग कर सकते हैं।



### यह विकल्पों से अधिक तेज़ नहीं है

> लंबे समय से मेरे लिए स्पष्ट रहा है कि, भले ही ifunc का कोई प्रदर्शन लाभ हो,
> यह केवल तभी हो सकता है जब पूरा फ़ंक्शन कॉल इतना छोटा हो कि कॉल ओवरहेड
> कुल समय का एक महत्वपूर्ण हिस्सा हो सके।
>
> -- [Rich Felker](https://hachyderm.io/@dalias/113074264762553873),
> [musl](https://musl.libc.org) के अनुरक्षक।

चूँकि ifunc के लिए सामान्य औचित्य प्रदर्शन-संबंधी है, मैं यह देखना चाहता था कि
*ifunc स्वयं* कितना ओवरहेड पैदा करता है। आखिरकार, कोई भी फ़ंक्शन जो अनुकूलन के
लायक है, संभवतः बार-बार कॉल किया जाता है, इसलिए फ़ंक्शन आह्वान का ओवरहेड
स्वीकार करने योग्य है।

इसे समझने के लिए, मैंने एक प्रयोग डिज़ाइन किया जो एक *गतिशील रूप से हल किया
गया* फ़ंक्शन को एक कसी हुई लूप में बार-बार कॉल करेगा। [`speed_demo/ifunc`](https://github.com/robertdfrench/ifuncd-up/blob/HEAD/code/speed_demo/ifunc/main.c) और
[`speed_demo/pointer`](https://github.com/robertdfrench/ifuncd-up/blob/HEAD/code/speed_demo/pointer/main.c) पर एक नज़र डालें।
ये प्रोग्राम दोनों एक ही काम करते हैं (एक स्टैटिक काउंटर को बढ़ाना), लेकिन
वृद्धि करने वाले फ़ंक्शन अलग-अलग तरीकों से हल किए जाते हैं: पहला GNU IFUNC का
लाभ उठाता है, और दूसरा सामान्य पुराने फ़ंक्शन पॉइंटर्स पर निर्भर करता है।

यहाँ समग्र तर्क है:

1. यह निर्धारित करने के लिए कि किस वृद्धिकर्ता का उपयोग करना है, एक resolver फ़ंक्शन को कॉल करें।
1. इस उत्तर को कहीं रिकॉर्ड करें (GOT में, या एक फ़ंक्शन पॉइंटर के रूप में)।
1. इसकी लागत का अनुमान लगाने के लिए इस वृद्धिकर्ता फ़ंक्शन को कुछ अरब बार कॉल करें।

नियंत्रण के रूप में, [`speed_demo/fixed`](https://github.com/robertdfrench/ifuncd-up/blob/HEAD/code/speed_demo/fixed/main.c) भी है,
जो वही वृद्धिकर्ता कार्य करता है लेकिन बिना किसी गतिशील रूप से हल किए गए फ़ंक्शन के।
इसका उपयोग यह अनुमान लगाने में सहायता के लिए किया जा सकता है कि रनटाइम का
कितना हिस्सा फ़ंक्शन आह्वान के लिए समर्पित है बनाम कितना हिस्सा केवल जोड़ कर रहा है।

Makefile लक्ष्य `rigorous_speed_demo` इनमें से प्रत्येक प्रोग्राम के कई रन करता है
और उनके प्रदर्शन के बारे में कुछ सरल आँकड़े तैयार करता है। ये संख्याएँ निश्चित रूप से
आपके हार्डवेयर के आधार पर बदलेंगी, लेकिन `fixed` परीक्षण को तुलना के लिए आधार
रेखा के रूप में काम करना चाहिए।

| *परिणाम* | न्यूनतम | अधिकतम | औसत   |
|-----------|------|------|-------|
| fixed     | 2.93 | 4.20 | 3.477 |
| ifunc     | 9.50 | 10.56| 9.986 |
| pointer   | 6.23 | 7.44 | 6.791 |

यहाँ हम देखते हैं कि सामान्य पुराने फ़ंक्शन पॉइंटर का उपयोग करने की तुलना में
ifunc का ओवरहेड महत्वहीन नहीं है। औसतन, मेरे हार्डवेयर पर, किसी ifunc फ़ंक्शन को
2 अरब बार कॉल करने में फ़ंक्शन पॉइंटर को 2 अरब बार आह्वान करने की तुलना में लगभग
दोगुना समय लगता है।

क्या वास्तविक जीवन में इससे कोई फर्क पड़ता है? बिल्कुल नहीं। जो फ़ंक्शन अनुकूलन के
लायक हैं, वे उन "एक से बढ़ाने" वाले फ़ंक्शनों की तुलना में कहीं अधिक महंगे हैं जिनका
हम यहाँ विश्लेषण कर रहे हैं। यह केवल इसलिए दिलचस्प है क्योंकि GNU IFUNC
प्रदर्शन के लिए वरदान होने का दावा करता है, फिर भी फ़ंक्शन पॉइंटर्स की तुलना में अधिक
लागत वहन करता प्रतीत होता है।


#### अन्य तकनीकों का प्रदर्शन
ऐसी अन्य तकनीकें भी हैं जो ifunc से धीमी हैं। `super_rigorous_speed_demo` पर एक
नज़र डालें, जो दो अन्य प्रयोगों को शामिल करता है: [`speed_demo/upfront`](https://github.com/robertdfrench/ifuncd-up/blob/HEAD/code/speed_demo/upfront/main.c)
और [`speed_demo/always`](https://github.com/robertdfrench/ifuncd-up/blob/HEAD/code/speed_demo/always/main.c)।

`speed_demo/upfront` `speed_demo/pointer` के समान व्यवहार करता है, सिवाय इसके कि
यह फ़ंक्शन पॉइंटर पर नज़र रखने के बजाय CPU फीचर जाँचों के परिणामों को ग्लोबल
वेरिएबल्स में संग्रहीत करता है। इसके लिए अभी भी पहले एक "resolver" फ़ंक्शन चलाने
की आवश्यकता होती है, ताकि इन ग्लोबल वेरिएबल्स के मान के आधार पर यह निर्धारित किया जा
सके कि कौन सा कार्यान्वयन उपयोग किया जाए। यह तकनीक ifunc से धीमी साबित होती है,
लेकिन यह फ़ंक्शन पॉइंटर्स संग्रहीत करने से भी अधिक सुरक्षित है: जहाँ फ़ंक्शन
पॉइंटर्स को मनमाने मानों पर सेट किया जा सकता है, वहीं बूलियन फ़्लैग्स को नहीं।
इसलिए एक हमलावर जो इन वेरिएबल्स को संशोधित करने में सक्षम है, प्रोग्राम को *धीमा*
बना सकता है, लेकिन प्रोग्राम को *अलग* व्यवहार नहीं करा सकता।

`speed_demo/always` को सबसे धीमी तकनीक के रूप में डिज़ाइन किया गया है -- यह जब भी
किसी कार्यान्वयन की आवश्यकता होती है, सभी आवश्यक CPU सुविधाओं की जाँच करता है और
तुरंत एक चुन लेता है। दिलचस्प बात यह है, यह तकनीक किसी भी अन्य की तुलना में
महत्वपूर्ण रूप से धीमी नहीं है। यह केवल उस मामले में ifunc से मामूली रूप से धीमी है
जहाँ हमें केवल एक ही CPU सुविधा की जाँच करनी होती है।

| परीक्षण | न्यूनतम | अधिकतम  | औसत     |
|---------|------|-------|---------|
| fixed   | 5.02 | 5.70  | 5.37    |
| pointer | 6.40 | 7.02  | 6.66    |
| ifunc   | 8.56 | 11.11 | 9.64    |
| upfront | 9.24 | 9.41  | 9.33333 |
| always  | 10.07| 10.56 | 10.2333 |




## निष्कर्ष
GNU IFUNC gcc/ld.so की एक विशिष्ट (niche) विशेषता है, जिसके बारे में
CVE-2024-3094 में उपयोग किए जाने से पहले बहुत कम लोग जानते थे। इसमें
गैर-स्पष्ट नुकसान और अपर्याप्त दस्तावेज़ीकरण हैं। लिंकर को `main` से पहले, प्रोसेस
इमेज के महत्वपूर्ण हिस्सों के प्रारंभ और सुरक्षित होने से पहले मनमाना कोड चलाने देकर,
यह प्रोग्रामिंग की सबसे बुनियादी मान्यताओं में से एक को कमजोर करता है: कि केवल
लाइब्रेरी लोड करने की क्रिया स्वाभाविक रूप से आपके प्रोग्राम को *बदल* नहीं देगी।

IFUNC के प्रदर्शन लाभ वास्तविक हैं, लेकिन विकल्पों से सार्थक रूप से बेहतर नहीं हैं।
एक ही बाइनरी तैनात करने की सरलता जो कई CPUs के लिए अनुकूलित हो, बहुत आकर्षक है,
लेकिन इसे सरल तकनीकों (जैसे फ़ंक्शन पॉइंटर्स) से पूरा किया जा सकता है।

मेरा मानना है कि IFUNC को gcc में डिफ़ॉल्ट रूप से अक्षम किया जाना चाहिए। इसे सक्षम
करने के लिए एक डरावना दिखने वाला फ़्लैग आवश्यक होना चाहिए, जैसे
`--enable-cve-2024-3094`। libc के बाहर इसका उपयोग करने वाले किसी भी व्यक्ति से यह
अपेक्षा की जानी चाहिए कि वह एक कठोर, अच्छी तरह से शोधित तर्क प्रदान करे कि कोई
वैकल्पिक समाधान उपयुक्त नहीं है।

![हाँ, सभी साझा लाइब्रेरीज़](https://assets.kitploit.com/production/public/readmes/31477/039631e9f0441a38341d4f2299c0666f63a731c02cb2239257afd7613455461c.png)

<!-- REFERENCES -->
[aes-ni]: https://en.wikipedia.org/wiki/AES_instruction_set
[agner]: https://www.agner.org/optimize/blog/read.php?i=167
[biebl]: https://salsa.debian.org/ssh-team/openssh/-/commit/818791ef8edf087481bd49eb32335c8d7e1953d6
[binarly-io]: https://github.com/binarly-io/binary-risk-intelligence/tree/master/xz-backdoor
[catonmat]: https://catonmat.net/simple-ld-preload-tutorial
[conway]: https://en.wikipedia.org/wiki/Conway%27s_law
[djmdjm]: https://github.com/openssh/openssh-portable/pull/251#issuecomment-2027935208
[fr0gger]: https://infosec.exchange/@fr0gger/112189232773640259
[freund]: https://www.openwall.com/lists/oss-security/2024/03/29/4
[gnu-cfa]: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-ifunc-function-attribute
[goodin1]: https://arstechnica.com/security/2024/04/what-we-know-about-the-xz-utils-backdoor-that-almost-infected-the-world/
[hn]: https://news.ycombinator.com/item?id=48056749
[jasoncc]: https://jasoncc.github.io/gnu_gcc_glibc/gnu-ifunc.html#relocations-and-pic
[JiaT75]: https://github.com/tukaani-project/xz/commit/cf44e4b7f5dfdbf8c78aef377c10f71e274f63c0
[keith]: https://keith.github.io/xcode-man-pages/ssh-add.1.html#apple-use-keychain
[mindrot]: https://anongit.mindrot.org/openssh.git
[mprotect]: https://www.man7.org/linux/man-pages/man2/mprotect.2.html
[musl]: https://musl.libc.org
[nagy]: https://sourceware.org/legacy-ml/libc-alpha/2015-11/msg00108.html
[nvd]: https://nvd.nist.gov/vuln/detail/CVE-2024-3094
[odonell]: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70082#c0
[OpenSSH9.8p1]: https://www.openssh.com/releasenotes.html#9.8p1
[openssh-unix-dev]: https://marc.info/?l=openssh-unix-dev&m=171288895109872&w=2
[pola]: https://en.wikipedia.org/wiki/Principle_of_least_astonishment
[rjmccall]: https://reviews.llvm.org/D139163#3993795
[schmidt]: https://bugzilla.redhat.com/show_bug.cgi?id=1381997#c4
[sourceware]: https://sourceware.org/glibc/wiki/GNU_IFUNC
[thesamesam]: https://gist.github.com/thesamesam/223949d5a074ebc3dce9ee78baad9e27#design
टूल डाउनलोड करें