
CFF फ़ॉन्ट में गोता लगाएँ और संयोगवश किसी jailbreak से cff पार्सिंग में bof के बारे में जानें। सिर्फ़ मज़े के लिए।
CFF फ़ॉन्ट में गोता लगाएँ और संयोगवश किसी jailbreak से cff पार्सिंग में bof के बारे में जानें। सिर्फ़ मनोरंजन के लिए
तो.... CFF आख़िर है क्या? मेरे ज्ञान से यह एक फ़ाइल फ़ॉर्मेट है, लेकिन चलिए देखने की कोशिश करते हैं कि wikipedia क्या कहता है: "CFF एक कंटेनर की तरह काम करता है जिसमें कई फ़ॉन्ट्स को एक साथ FontSet नामक इकाई में संग्रहीत किया जाता है।" (https://docs.fileformat.com/font/cff/) तो मूल रूप से हम फ़ॉन्ट्स को एक साथ स्टोर कर सकते हैं। बढ़िया, तो अब क्या? खैर, चूँकि यह एक फ़ाइल फ़ॉर्मेट है, इसलिए इसका कुछ spec होना चाहिए, और हाँ, इसका एक spec है और नहीं, यह अच्छा नहीं है क्योंकि यह 60 पेज का है और मैं इसके फ़ॉर्मेट को सीखने को तैयार नहीं हूँ। लेकिन हम star-master github repo के exploit (मुझे लगता है jailbreak 2.0 का सोर्स कोड) का उपयोग करके इसके फ़ॉर्मेट के बारे में जान सकते हैं।
तो... हम लेखक द्वारा प्रदान की गई cff.py स्क्रिप्ट का उपयोग करके शुरू करते हैं और hxd editor में out.cff (सामान्य सरल .cff फ़ाइल) भी खोलते हैं।
हम देख सकते हैं कि जब हम फ़ाइल को parse में देते हैं तो हमें निम्नलिखित मिलता है

तो हमने पहले ही कुछ प्रगति कर ली है क्योंकि हम cff के लिए एक परिभाषा तैयार कर सकते हैं, और हम इस निष्कर्ष पर पहुँच सकते हैं कि हमारे पास इसके header के बारे में कुछ metadata है जो tff संस्करणों को इंगित करता है, मेरा अनुमान है, headersize और absoffsize जो कुछ भी है।
तो अब तक |मेजर वर्जन(1 बाइट)|माइनर वर्जन(1 बाइट)|हेडर साइज़(1 बाइट) | हेडर absoffsize(1 बाइट) |
फिर हम आगे बढ़ते हैं और एक फ़ंक्शन देखते हैं जो बताता है कि इस .cff फ़ाइल में कौन-से फ़ॉन्ट्स उपयोग हो रहे हैं। जैसा कि देखा गया

तो हमें कैसे पता चलेगा कि इसका उद्देश्य यह पढ़ना है कि कौन-से फ़ॉन्ट्स उपयोग हो रहे हैं? खैर, टूल चलाने पर हमें cmd में निम्नलिखित परिणाम मिला

जिसमें हम देखते हैं कि ये फ़ाइल के metadata के बाद के अगले बाइट्स हैं

हम इस फ़ंक्शन के विश्लेषण पर बाद में लौटेंगे, लेकिन अभी के लिए हम अनुमान लगा सकते हैं कि फ़ाइल फ़ॉर्मेट है |मेजर वर्जन(1 बाइट)|माइनर वर्जन(1 बाइट)|हेडर साइज़(1 बाइट) | हेडर absoffsize(1 बाइट) | ABCDEF+पैक में फ़ॉन्ट्स|
आगे हम देखते हैं कि स्क्रिप्ट में हम उसे खोजते हैं जिसे string कहा जाता है:

ऐसा क्यों? क्योंकि मुझे लगता है कि वे पैक में उपयोग किए गए फ़ॉन्ट के बारे में जानकारी एकत्र करना चाहते हैं। docs के अनुसार, वे कहते हैं: "सभी strings, FontName और CIDFontName strings के अपवाद के साथ जो Name INDEX में दिखाई देते हैं, FontSet के भीतर विभिन्न फ़ॉन्ट्स द्वारा उपयोग किए जाते हैं, एक साथ एक INDEX संरचना में एकत्र किए जाते हैं और 2-बाइट unsigned number द्वारा संदर्भित किए जाते हैं जिसे string identifier या SID कहा जाता है। ये strings, जिन्हें standard strings के रूप में जाना जाता है, ISOAdobe और Expert character sets में उपयोग किए जाने वाले सभी नामों का वर्णन करते हैं।" वैसे, यहाँ ध्यान देने योग्य एक दिलचस्प बात यह है कि string तक पहुँचने के लिए हमने लगभग 41 बाइट्स छोड़ दिए।


आगे हमें .cff फ़ाइल में मौजूद फ़ॉन्ट्स के बारे में जानकारी मिलती है

हम ये कैसे करें? खैर, हम वह चीज़ इकट्ठा करते हैं जिसे top dict data कहा जाता है। वह क्या है? खैर, जितना मैं docs से समझ पाया, यह एक python dict है जिसमें कुछ जानकारी होती है, एक निश्चित तरीके से एन्कोडेड।

संयोगवश, यदि हम decoding algo का अनुसरण करते हैं:

हम strings डेटा टाइप को dereference करते हैं ताकि फ़ॉन्ट के बारे में जानकारी मिल सके, इसलिए हम यह निष्कर्ष निकालते हैं कि topdicts में केवल कुछ indexes होते हैं जिनका उपयोग बाद में strings डेटा टाइप में फ़ॉन्ट की जानकारी पाने के लिए होता है।
तो अब तक फ़ाइल की परिभाषा वैसी ही है,
|मेजर वर्जन(1 बाइट)|माइनर वर्जन(1 बाइट)|हेडर साइज़(1 बाइट) | हेडर absoffsize(1 बाइट) | ABCDEF+पैक में फ़ॉन्ट्स|41 ज्ञात बाइट्स|25 बाइट्स फ़ॉन्ट जानकारी|
बढ़िया, तो आगे क्या होता है? खैर, अगर हम parser स्क्रिप्ट का निरीक्षण करें तो हम देखते हैं कि उसे charstring_off, private_off मिलता है और वह charstring_off स्थिति पर जाकर कुछ और चीज़ें पढ़ता है।

लेकिन यह हमें बड़े परिप्रेक्ष्य को समझने में कैसे मदद करता है? तो मैं इसे अचानक समाप्त करूँगा। मूल रूप से मैंने 2 फ़ाइलों के बीच diff किया, एक सामान्य cff और दूसरी corrupted cff।

बाईं ओर corrupted .cff फ़ाइल है और दाईं ओर सामान्य .cff फ़ाइल है। यदि हम runtime परिणाम का निरीक्षण करें

पहली बार parse चलाने पर हम देखते हैं कि count, offsize, offbase जैसी सभी चीज़ें केवल कुछ offsets हैं, कुछ delimiters तक। कौन से delimiters? बिल्कुल फ़ॉन्ट का नाम। तो जैसा कि आप देख सकते हैं ('offbase', 8L), यानी फ़ाइल की शुरुआत से cff फ़ाइल में मौजूद फ़ॉन्ट की string की पहली मुठभेड़ तक।

जैसा कि "parse के दूसरे रन" में भी देखा जा सकता है

हम hexviewr में 0x6c offset पर \x0e\0xe\0xe\x0e देखते हैं, जो हमारे दुर्भावनापूर्ण डेटा की शुरुआत है।
तो निष्कर्ष के रूप में, .cff फ़ाइल का सामान्य फ़ॉर्मेट
|मेजर वर्जन(1 बाइट)|माइनर वर्जन(1 बाइट)|हेडर साइज़(1 बाइट) | हेडर absoffsize(1 बाइट) | ABCDEF+पैक में फ़ॉन्ट्स|41 ज्ञात बाइट्स|25 बाइट्स फ़ॉन्ट जानकारी|
और custom फ़ाइल फ़ॉर्मेट (उपयोगकर्ता सामग्री के साथ)
|मेजर वर्जन(1 बाइट)|माइनर वर्जन(1 बाइट)|हेडर साइज़(1 बाइट) | हेडर absoffsize(1 बाइट) | ABCDEF+पैक में फ़ॉन्ट्स|41 अज्ञात बाइट्स|25 बाइट्स फ़ॉन्ट जानकारी| 4 बाइट्स(count) | 4 बाइट्स(offsize) | 9 बाइट्स दस्तावेज़ीकरण शेष| उपयोगकर्ता सामग्री|