
Chrome pwning और v8 pwning के साथ शुरुआत करने के लिए एक उचित, सुव्यवस्थित दस्तावेज़ीकरण
Chrome pwning और v8 pwning के साथ शुरुआत करने के लिए एक उचित, सुव्यवस्थित दस्तावेज़
यह दस्तावेज़ कैसे व्यवस्थित है
ब्राउज़र आज की सबसे अधिक उपयोग होने वाली तकनीकों में से एक हैं। हर रेडी-मेड कंप्यूटर पर, अगर हम बस प्लग एंड प्ले करें, तो हमें एक ब्राउज़र इंस्टॉल दिखेगा। इसीलिए एक हमलावर के दृष्टिकोण और थ्रेट मॉडल के दृष्टिकोण से यह बहुत फायदेमंद है अगर हमलावर एक दुर्भावनापूर्ण पेज के माध्यम से ब्राउज़र से समझौता करने में सक्षम हो। उपरोक्त तर्कों को देखते हुए मैंने Google के Javascript Engine, विशेष रूप से v8 का अध्ययन करना चुना।
v8 प्रोजेक्ट की विशाल प्रकृति को देखते हुए, मैंने इंटरप्रेटर, अर्थात् d8 को शुरुआती बिंदु के रूप में चुना। हालाँकि d8 पर पहले से ही काफी शोध हो चुका है, हमें उम्मीद है कि कम से कम एक बग मिल जाएगा और अगर नहीं मिलता है, तो हम ब्राउज़र exploitation पर शोध आगे बढ़ाने में सक्षम होंगे, क्योंकि v8 ब्राउज़र exploitation में उपयोग की जाने वाली बुनियादी exploit development रणनीतियों के लिए प्रवेश क्षेत्र प्रदान करता है।
v8 को टारगेट चुनने का एक और कारण यह है कि यह कई ब्राउज़रों में उपयोग होता है।
अगर हम हुड के नीचे देखें, तो हम देख सकते हैं कि यह इंजन MicrosoftEdge में भी उपयोग होता है, इसलिए कई bug bounty पुरस्कार पाने का मौका है। अंतर्निहित ऑपरेटिंग सिस्टम के लिए, शोधकर्ता windows और linux का मिश्रण उपयोग करेगा, क्योंकि shell प्राप्त करने के मामले में कोई प्रतिबंध नहीं है, क्योंकि v8 बग wasm पेजों के माध्यम से कोड निष्पादन की अनुमति देते हैं और यह किसी विशेष प्लेटफ़ॉर्म से बंधा नहीं है।
दुर्भाग्य से, जबकि v8 में एक शोषित बग के परिणामस्वरूप कोड निष्पादन होगा, हम सैंडबॉक्स के कारण कोई कोड निष्पादित नहीं कर पाएंगे, और इस तरह हमें renderer के संदर्भ में कोड निष्पादन मिलेगा, जो हमें मशीन पर कोड निष्पादित करने की अनुमति नहीं देगा। उसके लिए हमें सैंडबॉक्स के लिए एक और exploit की आवश्यकता होगी, इस प्रकार सिस्टम को exploit करने के लिए हमें एक पूरी chain की आवश्यकता होगी।
और इस प्रकार हम ब्राउज़र हैकिंग के साथ शुरुआत करने के लिए निम्नलिखित लक्ष्यों को परिभाषित करते हैं:
परियोजना के पहले चरण में Chrome आर्किटेक्चर के बारे में और यह जानने की आवश्यकता है कि प्रत्येक घटक एक-दूसरे के साथ कैसे इंटरैक्ट करता है। इसे बेहतर ढंग से समझने के लिए हमें Chromium प्रोजेक्ट को कई उप-घटकों में विभाजित करने की आवश्यकता है, ताकि हम सब कुछ अलग कर सकें और ठीक से विश्लेषण कर सकें। अधिक सटीक रूप से, निम्नलिखित प्रत्येक घटक कितने उप-घटकों में टूटता है:
अब पहले कदम के लिए सबसे तार्किक कदम chromium आर्किटेक्चर को समझना है। तो ठीक है, हम ब्राउज़र को exploit करना चाहते हैं, लेकिन जब हम पहली बार ब्राउज़र शुरू करते हैं तो क्या होता है? chromium executable पर क्लिक करने के बाद, executable कुछ प्रक्रियाएँ शुरू करता है।
उनका क्रम और नाम इस प्रकार है:
पहली प्रक्रिया content process कहलाती है। यह प्रक्रिया क्या करती है?
अब जब हम संक्षेप में जान गए हैं कि यह क्या करता है, तो इस पर अधिक गहराई से जाने का समय है:
कम से कम Windows पर Chromium जिस तरह से काम करता है, वह यह है कि वह फ़ाइलों को एक dll में संकलित करता है, और उसके बाद उसे मेमोरी में लोड करता है। इसलिए Chromium ब्राउज़र का मुख्य लॉजिक chromium.dll में होता है।
यह कोड द्वारा भी पुष्टि की गई है
।
यह chrome_exe_main_win.cc से लिया गया है और यदि आप पूरा कोड पढ़ने के लिए उत्सुक हैं, तो यह chromium/src/chrome/app पर स्थित है। ठीक है, निष्पादन के साथ आगे बढ़ते हुए हम देख सकते हैं कि यह dll लोडेड क्लास को कॉल करने के लिए MakeMainDllLoader() को कॉल करता है, उसके बाद यह "loader" लॉन्च करता है, यानी यह chrome.dll लोड करता है और यदि आवश्यक हो तो आवश्यक command lines के साथ इसे पुनः आरंभ करता है। Loader का आगे विश्लेषण करने के लिए हमें इसका कोड समझने की आवश्यकता है, जो उसी निर्देशिका में mail_dll_loader_win.cc फ़ाइल में है। फ़ाइल के अंत तक स्क्रॉल करने पर हम MakeMainDllLoader का कॉल देख सकते हैं, जो आपके पास मौजूद संस्करण के आधार पर ChromeDllLoader या ChromiumDllLoader को कॉल करता है।

हम देख सकते हैं कि ChromiumDllLoader एक class है जो से inherit करती है। हम definition से देख सकते हैं कि यह class केवल cmdline और process type को दिए गए arguments के आधार पर dll लोड करती है।
।
Launch method का विश्लेषण करके हम कुछ चीज़ें समझ सकते हैं जो chrome.dll शुरू होने से पहले होती हैं: हम इस टिप्पणी से समझ सकते हैं कि "// Launching is a matter of loading the right dll and calling the entry point. // Derived classes can add custom code in the OnBeforeLaunch callback." chrome लॉन्च करना कुछ dll लोड करने का मामला है जो वास्तव में काम करते हैं। दूसरे, यह command line में दिए गए arguments लेता है और आगे sandbox services को initialize करता है।
।
सबसे पहले यह जाँचता है कि क्या sandbox initialization को कॉल करने वाला browser है, फिर यह जाँचता है कि जिस प्रक्रिया ने sandbox के initialization को कॉल किया था, उसे cloud print service के रूप में बुलाया गया था या नहीं। यह यह भी जाँचता है कि क्या binary को पास किया गया था, जो मूल रूप से binary को बताता है कि sandbox में न चलें। यह जाँचता है कि क्या इनमें से कोई भी सेट था और यदि कोई सत्य है, तो यह sandbox को संबंधित विकल्पों के साथ कॉल करता है। फिर अंत में हम वहाँ पहुँचते हैं
जो हमारे लिए रुचि का विषय है, यह को कॉल करने के लिए wrapper को दर्शाता है।
एक प्रक्रिया जीवन चरण को ट्रैक करना जिसे इस रूप में परिभाषित किया गया है```
// The phases are generic and may have meaning to the tracker.
PROCESS_PHASE_UNKNOWN = 0,
PROCESS_LAUNCHED = 1,
PROCESS_LAUNCH_FAILED = 2,
PROCESS_EXITED_CLEANLY = 10,
PROCESS_EXITED_WITH_CODE = 11,
// Add here whatever is useful for analysis.
PROCESS_SHUTDOWN_STARTED = 100,
PROCESS_MAIN_LOOP_STARTED = 101,
जब कोई प्रोसेस exit होता है तो तुरंत log करें, मॉड्यूल (यानी क्रोमियम का एक घटक) के बारे में जानकारी सहेजें जब भी कोई मॉड्यूल लोड होता है, और मूल रूप से यही कार्यक्षमता दोहराई जाती है लेकिन विभिन्न threads और classes के लिए अलग होती है। यदि आप रुचि रखते हैं, तो आप इसे chromium/src/base/debug/activity_tracker.h पर पा सकते हैं।
इसके बाद यह जाँचता है कि क्या "Main()" पहले बुलाया गया था। यहाँ मुझे लगता है कि उनका मतलब है कि क्या ChromeMain() पहले बुलाया गया था। वे मूल रूप से जाँचते हैं कि क्या content process को कोई command दिया गया था, यानी क्या इसे किसी arguments के साथ बुलाया गया था। और यदि ऐसा था, तो वे सुनिश्चित करते हैं कि browser process को भी वही args मिलें। फिर वे platform-specific जाँच करते हैं और यदि windows पाया जाता है, तो वे CreateATLModuleIfNeeded करके अपना खुद का handler initialize करते हैं, फिर वही कहानी है—platform specifics की जाँच करना—और वे SetupCRT का उपयोग करके arguments पास करते हैं, और हम उस हिस्से पर पहुँचते हैं जहाँ हम ipc को initialize करते हैं ताकि हम उन अन्य processes से बात कर सकें जिन्हें हमने spawn किया है। यहाँ उसके लिए ज़िम्मेदार कोड है। हम इसके विवरण में नहीं जाएँगे, क्योंकि हम बाद में chrome के ipc mechanism के बारे में अधिक गहराई से चर्चा करने के लिए वापस आएँगे। अभी के लिए बस यह जान लें कि यह वह तंत्र है जो chrome की multi-architecture processes के बीच बातचीत को सुगम बनाता है। और यदि आप नहीं जानते कि IPC का क्या अर्थ है, तो यह inter process communication के लिए है।
.
फिर यह जो करता है वह यह है कि यह ui::RegisterPathProvider का उपयोग करके ui के लिए arguments "forward" करता है—बल्कि सेट करता है, tracker को कॉल करता है और content_main_runner->Initialize(std::move(params)) का उपयोग करके परिणाम प्राप्त करता है, एक parent console बनाता है, जो मुझे लगता है कि उनका मतलब है कि वे एक parent process बनाते हैं, कुछ और जाँच करते हैं और फिर हम महत्वपूर्ण भाग पर पहुँचते हैं जो है
.
यहाँ हम IsSubprocess नामक फ़ंक्शन का एक कॉल देखते हैं।
यह मूल रूप से पुराने boilerplate कोड से बचने के लिए करता है, यह एक फ़ंक्शन में command line पर प्राप्त process के type की जाँच करता है और यदि कोई option पास किया गया था, तो यह निम्न में से चुनता है और संबंधित process बनाता है।```
return type == switches::kGpuProcess ||
type == switches::kPpapiPluginProcess ||
type == switches::kRendererProcess ||
type == switches::kUtilityProcess || type == switches::kZygoteProcess;
वहाँ से हम content_main_runner->Run(); पर पहुँचते हैं, जो असल में सारा जादू करता है। चलिए इसे हुड के अंदर से जाँचते हैं। तो content_main_runner, ContentMainRunner क्लास का है (बिल्कुल स्पष्ट है), जो `content\app\content_main_runner_impl.cc` पर मिल सकता है।
इसके कोड फ्लो को सही से समझने के लिए हमें इसे नीचे से ऊपर तक ले जाना होगा। और ऐसा कहते हुए, हम फिर से नीचे स्क्रॉल करते हैं और पाते हैं कि असल में `ContentMainRunner::Create()` वास्तव में `ContentMainRunnerImpl::Create()` को कॉल करता है; जिससे हमें एहसास होता है कि हमें ContentMainRunner की नहीं, बल्कि ContentMainRunnerImpl की परिभाषा खोजनी होगी, जो उसी पहले बताए गए फ़ोल्डर में `content_main_runner_impl.h` में मिलती है।

हम देखते हैं कि यह ContentMainRunner से इनहेरिट करता है और हम इसके मुख्य मेथड्स देख सकते हैं। यहाँ वास्तव में बहुत कुछ नहीं है, क्योंकि इसका व्यवहार ज़्यादातर `content_main_runner_impl.cc` में ओवरराइट किया गया है।
`content_main_runner_impl.cc` के अंदर, run मेथड में यह सबसे पहले DCHECK का उपयोग करके कुछ जाँच करता है (यह फ़ंक्शन आखिर है क्या?(```The CHECK() macro will cause an immediate crash if its condition is not met. DCHECK() is like CHECK() but is only compiled in when DCHECK_IS_ON is true (debug builds and some bot configurations, but not end-user builds).``` गूगल डॉक्स से उद्धरण :) ) यह देखने के लिए कि क्या is_initialized, content_main_params_, is_shutdown_ सेट हैं।

उसके बाद यह आर्ग्युमेंट्स लेता है और उस प्रकार का निर्धारण करता है जिसका मैंने पहले उल्लेख किया है 
फिर अगर हमें वह नहीं मिलता, तो हम InitializeFieldTrialAndFeatureList() और delegate_->PostFieldTrialInitialization(); को कॉल करते हैं, और इसे mojo के ज़रिए एक संदेश के रूप में पोस्ट करते हैं।
 .
अगला, यह UI के लिए कुछ चीज़ें सेट करता है 
फिर से उस आधार पर जो उसे कमांड लाइन पर पास किया गया था, और यह RegisterMainThreadFactories को कॉल करता है, जो RegisterUtilityMainThreadFactory के लिए एक रैपर है, जो केवल g_utility_main_thread_factory सेट करता है, जो नाम से मुझे लगता है कि यह मुख्य थ्रेड बनाता है, जो बाकी थ्रेड्स के लिए वॉचर की तरह है, और अंत में ब्राउज़र प्रोसेस लॉन्च करता है। 
अगर आपको मुझ पर भरोसा नहीं है, तो यहाँ chromium को binja में डिसअसेंबल किया गया है और हम उसका कुछ इन-मेमोरी विश्लेषण भी देखेंगे।
हमारी किस्मत अच्छी है, हमारे पास chome.exe.pdb है जो हमें डीबग सिंबल देता है और बाइनरी को रिवर्स करते समय हमें कोई परेशानी नहीं होगी।
चूँकि हम विंडोज़ पर chrome पर काम करते हैं, प्रोग्राम का मुख्य एंट्री पॉइंट wWinMain है:
ग्राफ़ ऐसा दिखता है
.
फ़ंक्शन स्वयं काफी बड़ा है, इसलिए मैं केवल इसके आवश्यक हिस्से दिखाऊँगा। बहुत सारे इनिशियलाइज़ेशन के बाद हम उस बिंदु पर पहुँचते हैं जहाँ यह `MakeMainDllLoader()` को कॉल करता है।
, जिसके बारे में हम पहले ही समझा चुके हैं कि यह क्या करता है। तो हम chrome को डायनामिक रूप से कैसे डीबग करें और वह सब साबित करें जो मैंने पहले बताया है? पहले हम इसे windbg में लोड करते हैं, फिर lm करते हैं और एक्ज़ीक्यूटेबल का नाम देखते हैं। उसके बाद हम chrome!MakeMainDllLoader नामक फ़ंक्शन की तलाश करते हैं, एक bp सेट करते हैं और एक्ज़ीक्यूशन को चलने देते हैं। . हम इसके अंदर जाते हैं  इसे तब तक चलने देते हैं जब तक यह ret को हिट न कर दे और हम इससे बाहर आ जाएँ, तब हम chrome!wWinMain+0x764 में पहुँचते हैं . फिर हम इसे chrome!MainDllLoader::Launch तक चलने देते हैं और उसमें स्टेप करते हैं। वहाँ से हम chrome!MainDllLoader::Load पर bp लगाते हैं ताकि हम देख सकें कि chrome.dll मेमोरी में कैसे लोड होता है। और जैसा कि हम देख सकते हैं, सबसे पहले लोड होने वाली चीज़ों में से एक chrome.dll थी।  यहाँ से विश्लेषण का प्रवाह वही है, और पूरा इन-मेमोरी विश्लेषण पाठक के लिए एक अभ्यास के रूप में छोड़ दिया जाएगा। एक विशेष उद्देश्य के लिए, मैं विश्लेषण उस बिंदु तक करूँगा जहाँ लगभग कंटेंट प्रोसेस पूरा हो जाता है, और ब्राउज़र प्रोसेस शुरू होने से ठीक पहले, मैं वहाँ रुक जाऊँगा। इसका उद्देश्य केवल यह दिखाना है कि IPC एक-दूसरे के बीच संवाद कैसे शुरू करता है। अब DLL लोड होने के बाद, हमें 'call rax' इंस्ट्रक्शन की तलाश करनी होगी। मैंने जो किया वह यह था कि DLL लोड करने के बाद वर्तमान eip से 0x40 इंस्ट्रक्शन सूचीबद्ध किए।. उस एड्रेस पर वास्तव में वही है जिसे हम खोज रहे हैं, जो chrome!ChromeMain है।
वहाँ से हम  पर ब्रेक लगाना चाहते हैं, जो मूल रूप से content!content::ContentMain में कूदने से पहले एक बड़ी जाँच है। वहाँ से हम कुछ इंस्ट्रक्शन आगे बढ़ना चाहते हैं और content!content::ContentMain को हिट करना चाहते हैं। हम अंदर स्टेप करना चाहते हैं और content!content::RunContentProcess पर ब्रेक लगाना चाहते हैं। हम अंदर स्टेप करना चाहते हैं, और content!content::ContentMainRunnerImpl::Run+0x430 पर bp सेट करना चाहते हैं, और जैसे ही हम आगे बढ़ते हैं  हम mojo IPC शुरू होते देखते हैं और हम निष्कर्ष निकालते हैं कि अगली प्रोसेस यानी ब्राउज़र प्रोसेस वास्तविक ब्राउज़र कार्यान्वयन और अन्य सभी प्रोसेसों को संभालने के लिए ज़िम्मेदार है।
===============================================================================================
2.
पिछली बार हम कंटेंट प्रोसेस को समझने के बाद रुके थे। आज हम ब्राउज़र प्रोसेस के बारे में देखेंगे।
यह वह प्रोसेस है जो कंटेंट प्रोसेस के बाद शुरू होती है और यह chrome द्वारा शुरू की गई प्रोसेसों में दूसरी है।
आइए इसे संक्षेप में वर्णित करें:
* हम इसे मुख्य प्रोसेस मान सकते हैं, क्योंकि कंटेंट प्रोसेस अधिकतर एक इनिशियलाइज़ेशन रूटीन और कुछ डिपेंडेंसी जाँच है, और यह कंटेंट प्रोसेस द्वारा शुरू की जाती है।
* यह ब्राउज़र के पूरे जीवनकाल तक सक्रिय रहती है।
* यह सभी प्रोसेसों का केंद्रीय समन्वयक है, और ब्राउज़र के लिए उपलब्ध उच्चतम विशेषाधिकार स्तर पर कार्य करती है।
* चूँकि यह उच्चतम विशेषाधिकार स्तरों पर चलती है, यदि अन्य प्रोसेसों को कोई उच्च-स्तरीय ऑपरेशन करने की आवश्यकता होती है, तो उस अनुरोध को ब्राउज़र प्रोसेस द्वारा संभाला जाता है।
* यह एड्रेस बार, बुकमार्क और बैक/फॉरवर्ड/रीलोड बटन जैसी सुविधाओं को नियंत्रित करती है। चूँकि यह सबसे विशेषाधिकार प्राप्त प्रोसेस है, यह अन्य प्रोसेसों द्वारा दिए गए डेटा पर भरोसा नहीं करती।
* यह आवश्यक होने पर अन्य प्रोसेसों के लिए UI, नेटवर्किंग या फ़ाइलसिस्टम स्टोरेज जैसे विशेषाधिकार प्राप्त ऑपरेशन भी संभालती है।
अब जब हम संक्षेप में जान गए हैं कि यह क्या करती है, तो इस पर और गहराई से विचार करने का समय है:
हमारी यात्रा `src\content\app` में content_main_runner_impl.cc नामक फ़ाइल में int ContentMainRunnerImpl::RunBrowser(MainFunctionParams main_params,bool start_minimal_browser) फ़ंक्शन से शुरू होती है। पहला ऑपरेशन जो यह निष्पादित करता है, वह है TRACE_EVENT_INSTANT0। .
वह क्या है? उससे पहले, ट्रेस फ़ंक्शन होता क्या है? खैर, अगर हम https://lwn.net/Articles/379903/ पर जाएँ, तो हम देख सकते हैं कि वे इसे  के रूप में परिभाषित करते हैं। थोड़ा सा अमूर्तन करने पर हम इस निष्कर्ष पर पहुँच सकते हैं कि ट्रेस फ़ंक्शन वह फ़ंक्शन है जो स्टैकफ्रेम में एक विशिष्ट बिंदु पर डेटा रिकॉर्ड करता है। यह केवल निष्पादन फ़ंक्शन के स्टैक को रिकॉर्ड करने से अधिक करता है; यह अंतिम निष्पादित फ़ंक्शन के लोकल वेरिएबल्स को भी रिकॉर्ड कर सकता है। अब जब हम जानते हैं कि ट्रेस फ़ंक्शन क्या है, तो देखते हैं कि हमारा वाला क्या करता है।
अगर हम https://chromium.googlesource.com/chromium/src/base/trace_event/common/+/refs/heads/main/trace_event_common.h पर जाते हैं, तो हम देखते हैं कि वे इसे एक ऐसे फ़ंक्शन के रूप में परिभाषित करते हैं जिसका एकमात्र उद्देश्य "एप्लिकेशन प्रदर्शन और संसाधन उपयोग को ट्रैक करना" है। थोड़ा और गहराई में जाकर यह समझने के लिए कि यह क्या करता है, हम देखते हैं कि यह एक मैक्रो है और इसे  के रूप में परिभाषित किया गया है। मैक्रो के ऊपर हम एक छोटी परिभाषा देख सकते हैं जो कहती है कि यह "name" नामक एक एकल इवेंट को तुरंत रिकॉर्ड करता है, जिसमें 0, 1 या 2 आर्ग्युमेंट होते हैं। और यदि संबंधित इवेंट की श्रेणी सक्षम नहीं है, तो यह कुछ नहीं करता है। हम देख सकते हैं कि पैरामीटर के रूप में हमारे पास मुख्य श्रेणी के रूप में "startup" है और सबसिस्टम के रूप में "ContentMainRunnerImpl::RunBrowser(begin)" है, और तीसरा पैरामीटर TRACE_EVENT_SCOPE_THREAD है, जो "#define TRACE_EVENT_SCOPE_THREAD (static_cast<unsigned char>(2 << 2))" है, जो मान के आधार पर मुझे लगता है कि संबंधित इंस्टेंट इवेंट के लिए एक आईडी है। तो संक्षेप में, यह केवल इस तथ्य को ट्रेस (लॉग) करता है कि हमने RunBrowser फ़ंक्शन में अपना निष्पादन शुरू किया है। फिर हम यह जाँच करते हैं कि क्या ब्राउज़र मुख्य लूप पहले ही शुरू हो चुका है, और यदि यह पहले ही शुरू हो चुका है तो हम फ़ंक्शन से बाहर निकल जाते हैं  . फिर हम एक फ़्लैग सेट करते हैं और उसके बाद हम कोड के एक दिलचस्प हिस्से पर पहुँचते हैं। हम जाँचते हैं कि क्या हमारे पास mojo_ipc तंत्र के लिए समर्थन है, और यदि हाँ, तो हम ShouldCreateFeatureList का उपयोग करते हैं, जो विभिन्न प्रोसेसों के साथ एक फ़ीचर सूची बनाता है, उन्हें इनिशियलाइज़ करने का प्रयास करता है, और अंत में mojo सुविधाओं को इनिशियलाइज़ करने का प्रयास करता है। फिर हम एक थ्रेडपूल बनाते हैं। थ्रेडपूल आखिर है क्या???! विकिपीडिया से उद्धृत करते हुए: "एक सॉफ्टवेयर डिज़ाइन पैटर्न जो कंप्यूटर प्रोग्राम में निष्पादन की समवर्तीता प्राप्त करने के लिए होता है"। अधिक सही ढंग से समझाया जाए: "एक थ्रेड पूल कई थ्रेड्स को बनाए रखता है जो पर्यवेक्षक प्रोग्राम द्वारा समवर्ती निष्पादन के लिए कार्य आवंटित किए जाने की प्रतीक्षा करते हैं" (यह भी विकिपीडिया से उद्धरण है)। अधिक स्पष्ट रूप से समझाने के लिए, एक फैक्ट्री में काम करने वाली लोगों की दो पंक्तियों की कल्पना करें। चलिए उन्हें लाइन a और लाइन b कहते हैं। वे सभी एक बॉस द्वारा पर्यवेक्षित हैं। चलिए उसे लाइन c कहते हैं। अब लाइन b को काम करने के लिए लाइन a का अपना काम पूरा करने और लाइन c द्वारा सूचित किए जाने की प्रतीक्षा करनी होती है। और लाइन a के लिए भी यही बात है। और यही एक थ्रेडपूल है। यहाँ एक छोटा सा C उदाहरण भी है । यह बेशर्मी से https://stackoverflow.com/questions/15752659/thread-pooling-in-c11 से लिया गया है।इसके बाद हमारे पास PreBrowserMain(); का कॉल है, जो कुछ प्लेटफ़ॉर्म-विशिष्ट इनिशियलाइज़ेशन करता है, और उसके बाद हम उस बिंदु पर पहुँचते हैं जहाँ हम `BrowserTaskExecutor::Create()` को कॉल करते हैं।
 चलिए इस पर गहराई से नज़र डालते हैं कि यह क्या करता है, क्योंकि नाम काफी दिलचस्प है, और एक शिक्षित अनुमान के आधार पर हम महसूस कर सकते हैं कि यह दिलचस्प हो सकता है। हमारा चक्कर content/browser/scheduler/browser_task_executor.h के अंदर से शुरू होता है, जहाँ हम पाते हैं कि BrowserTaskExecutor एक क्लास है जो "ब्राउज़र प्रोसेस के लिए base::TaskTraits को वास्तविक टास्क कतारों में मैप करने" के लिए है। फ़ाइल में थोड़ा नीचे जाने पर हम सबसे पहले  देखते हैं, यह BaseBrowserTaskExecutor से इनहेरिट करता है। तो अब BrowserTaskExecutor को समझने के लिए हमें BaseBrowserTaskExecutor को समझना होगा। हम देख सकते हैं कि यह TaskExecutor से इनहेरिट करता है। सौभाग्य से, हम देखते हैं कि यह TaskExecutor की विधियों को overwriteable गुण के साथ ओवरराइट करता है, जिसका अर्थ है कि बाद में उन्हें अन्य विधियों द्वारा ओवरराइट कर दिया जाएगा। लेकिन केवल जिज्ञासु लोगों के लिए, हम इसे base/task/task_executor.h पर पा सकते हैं, और यदि हम इसका निरीक्षण करें तो हम पा सकते हैं कि TaskExecutor एक क्लास है जो "एक विशिष्ट TaskTraits एक्सटेंशन आईडी के साथ टास्क निष्पादित कर सकता है"  .
टास्क क्या है और TaskTraits क्या हैं? हम पहले ही बता चुके हैं कि टास्क क्या है, लेकिन याद दिलाने के लिए, यह chrome की प्रोसेसों में से एक प्रोसेस का भाग है, और अब TaskTraits क्या हैं? वे base/task/task_traits.h पर स्थित हैं, और उन्हें इस प्रकार परिभाषित किया गया है: "किसी टास्क के बारे में जानकारी समाहित करना जो थ्रेड पूल को बेहतर शेड्यूलिंग निर्णय लेने में मदद करती है।" वापस अपने BrowserTaskExecutor पर आते हैं। जिस विधि को हम कॉल करते हैं वह Create() है, और इसका विश्लेषण इस प्रकार है 
पहले यह जाँच करता है कि क्या वर्तमान टास्क को SingleThreadTaskRunner से चलाने की आवश्यकता है, अर्थात यदि हमें इस टास्क को एक स्वतंत्र थ्रेड का उपयोग करके चलाने की आवश्यकता है। हम ऐसा tls के लिए एक पॉइंटर प्राप्त करके करते हैं। फिर हम एक ui और एक थ्रेड शेड्यूलर को इनिशियलाइज़ करते हैं। मूल रूप से यहाँ हम ui से संबंधित भविष्य की घटनाओं के लिए एक शेड्यूलर init करते हैं।
और उस सुविधा के लिए बस इतना ही। content_main_runner_impl.cc के विश्लेषण के साथ आगे बढ़ते हुए हम यहाँ पहुँचते हैं।
variations ids provider क्लास फ़ाइल की खोज करने पर हमें वह `components/variations/variations_ids_provider.h` पर मिलती है, वहाँ हमें कुछ काफी दिलचस्प दिखता है। इसमें एक `.mojom.h` फ़ाइल शामिल है। हम इसकी परिभाषा `Debug/gen/components/variations/` में variations.mojom.h पर पा सकते हैं, जिसका अर्थ है कि इसका IPC तंत्र से कुछ लेना-देना है। अब क्लास की वास्तविक परिभाषा को देखते हुए हमें एक टिप्पणी दिखती है जो इसे "कस्टम HTTP अनुरोध हेडर में प्रेषित क्लाइंट प्रयोगों और मेट्रिक्स स्थिति को बनाए रखने के लिए एक सहायक क्लास" के रूप में वर्णित करती है। इसके व्यवहार और स्रोत परिभाषा को देखते हुए, हम निष्कर्ष निकालते हैं कि यह केवल एक फ़ंक्शन के लिए मार्कर के रूप में उपयोग किया जाता है, जो GetClientDataHeaders() को आपूर्ति किए गए "साइन-इन पैरामीटर" को चिह्नित करता है, जिसका अर्थ है कि स्टैक निष्पादन में कहीं न कहीं GetClientDataHeaders का कॉल है और बाद में इसे एक पैरामीटर के साथ कॉल किया जाएगा। फिर हम delegate_->PostEarlyInitialization(!!main_params.ui_task); करते हैं, जो केवल mojo के IPC पर यह पोस्ट करता है कि उसे UI टास्क शुरू करने हैं। हम कुछ और इनिशियलाइज़ेशन करते हैं  और फिर हम RunBrowserProcessMain को कॉल करने के लिए पहुँचते हैं।  यदि आपने मेरी तरह आशा की थी कि यह वह जगह है जहाँ हम GUI शुरू होते देखेंगे, तो आप गलत हैं। मास्टर ऊगवे का एक उद्धरण । फिर हम कुछ और जाँच करते हैं और हम BrowserMain को हिट करते हैं। इसके ऊपर जाने पर यह कुछ ट्रेसिंग करता है और फिर हम पर पहुँचते हैं, जहाँ हम वास्तव में GUI शुरू करते हैं। अब यदि आपको मुझ पर भरोसा नहीं है, तो आपको तब तक थोड़ा और धैर्य रखना होगा जब तक हम डायनामिक विश्लेषण तक नहीं पहुँचते। फिर हम Run मेथड पर पहुँचते हैं, जो वास्तविक चीज़ है जिसमें हमारी रुचि है; उसके बाद हम ब्राउज़र प्रोसेस को समझने के अगले बिंदु पर पहुँचेंगे। लेकिन अभी के लिए, चलिए एक और छोटा चक्कर लगाते हैं और जाँचते हैं कि Initialize मेथड कैसे बनाया गया है। तुरंत ही हम देखते हैं कि यह init मेथड के निष्पादन को ट्रेस करता है, और उससे पहले यह एक हिस्टोग्राम बनाता है। फिर हम initialization_started_ फ़्लैग की जाँच करते हैं कि क्या हम इनिशियलाइज़ेशन चरण तक पहुँचे हैं, और यदि नहीं पहुँचे, तो हम skia को init करते हैं, जो chrome द्वारा उपयोग की जाने वाली ग्राफिक्स लाइब्रेरी है; एक "टाइमर" शुरू करते हैं जो बाद में हिस्टोग्राम में उपयोग के लिए इस मेथड को चलाने में बीते सेकंड की गिनती करता है; जाँचते हैं कि क्या हमने बाइनरी को डीबगर को प्रोसेस से अटैच होने की प्रतीक्षा करने के लिए एक पैरामीटर दिया है; और अंत में notification_service_ शुरू करते हैं, जो एक शिक्षित अनुमान के अनुसार थ्रेडपूल के मुख्य वॉचर को सूचित करेगा कि उसे सेवा कब शुरू करनी है। । फिर हम chrome के लिए आवश्यक फ़ॉन्ट्स इनिशियलाइज़ करते हैं और mainbrowserloop बनाते हैं, जो सभी प्रोसेसों का समन्वयक है, और हम तीन मेथड्स के ऊपर से कूद जाते हैं जिनमें हमें कोई दिलचस्पी नहीं है:
main_loop_->CreateStartupTasks();
int result_code = main_loop_->GetResultCode();
यहाँ से हमें CreateStartupTasks में जाने में दिलचस्पी है। वहाँ से हम content\browser\browser_main_loop.cc को देखते हैं, हमें startup_task_runner_->RunAllTasksNow(); में दिलचस्पी है, जो createstartuptask मेथड के अंदर है। starup_task_runner_ एक StartupTaskRunner है जो उसी निर्देशिका में startup_task_runner.cc फ़ाइल के अंदर स्थित है। अब यदि हम RunAllTasksNow मेथड का निरीक्षण करते हैं, तो हम देखते हैं कि यह केवल सभी कार्यों पर पुनरावृति करता है और उन्हें चलाता है
==========================================================================================
अब समय है कुछ डायनेमिक विश्लेषण का।```अब रेंडरर को पकड़ने के लिए हमें windbg में बाइनरी को शुरू करना होगा। यह केवल File->Open Executable करके और --renderer-startup-dialog --no-sandbox --wait-for-debugger-children=renderer --renderer-process-limit=1 को तर्क के रूप में पास करके प्राप्त किया जा सकता है।. फिर हम content!content::StartupTaskRunner::RunAllTasksNow+0x88 पर एक bp सेट करते हैं ताकि हम ipc संदेशों को और बाद में रेंडरर को पकड़ सकें। केवल एक संदर्भ बिंदु के रूप में, इसे एक बार चलाने के बाद आपका dbg इस तरह दिखना चाहिए  । आपको chrome is running in full browser mode संदेश देखना चाहिए। वहाँ से आप एक से पाँच तक गिनती चलाते हैं, ताकि आप इसे चार बार और चलाएँ। और फिर आपको कुछ ऐसा दिखना चाहिए । मैं procmon उपयोग करने की सलाह देता हूँ ताकि आप रेंडरर प्रक्रिया की निगरानी कर सकें जब वह शुरू हो। उसके बाद आप इसे किसी अन्य डिबगर में हुक करते हैं, और यदि आपने ऊपर दिए गए तर्कों का उपयोग किया है तो आपको रेंडरर pid बताने वाला एक मैसेज बॉक्स पॉप अप दिखना चाहिए। वहाँ से आप base!base::RunLoop::Run पर bp लगाना चाहेंगे। दुर्भाग्य से आप content!content::RendererMain पर ब्रेक नहीं कर सकते, किसी कारण से। शायद इसलिए क्योंकि हम प्रक्रिया को renderemain फ़ंक्शन से बाहर निकलने के ठीक बाद हुक करते हैं और यह एक थ्रेड द्वारा चलाई जाती है। फिर भी, चार रन के बाद ipc इस तरह दिखता है।। यह इंगित करता है कि gui शुरू हो गया है। और रेंडरर प्रक्रिया शुरू होने के बाद ipc इस तरह दिखता है।। फिर हम एक bp सेट करते हैं
content!content::StartupTaskRunner::RunAllTasksNow+0x88 और content!content::RunOtherNamedProcessTypeMain पर। इसे चलने दें
============================================================================================================
3.अब ब्राउज़र प्रक्रिया विश्लेषण के दूसरे भाग के लिए, हम उस बिंदु पर पहुँच गए हैं जहाँ हम रेंडरर को समझ और डिबग कर पाएँगे, लेकिन हम अभी वहाँ नहीं जाएँगे। मैंने जानबूझकर RunBrowserProcessMain के बाद विश्लेषण करने के लिए एक और फ़ंक्शन छोड़ा है, सैद्धांतिक रूप से यह RunBrowser के बाद आता है, लेकिन जैसा कि आपको याद होगा, RunBrowser, RunBrowserProcessMain के लिए एक रैपर है। अब जो मैंने बाहर छोड़ा है वह यह है कि src/content/app फ़ोल्डर में content_main_runner_impl.cc नामक फ़ाइल में एक और फ़ंक्शन है जिसे हम रेंडरर को स्पॉन करने के बाद कॉल करते हैं और इसे RunOtherNamedProcessTypeMain कहा जाता है। यह प्रक्रिया अन्य सभी प्रक्रियाओं को चलाने के लिए जिम्मेदार है।। अब समझते हैं कि कोड में क्या होता है। हम देखते हैं कि इसका प्रोटोटाइप है , जो इंगित करता है कि यह cmdline को पास किए गए तर्कों को लेगा, किस प्रक्रिया प्रकार की अपेक्षा करनी है और एक chrome delegate। फिर हम फ़ंक्शन की शुरुआत में पहुँचते हैं जहाँ हमारे पास प्लेटफ़ॉर्म विशिष्टताओं की जाँच करने के लिए एक मैक्रो परिभाषा है और यह जाँचने के लिए कि किस प्रक्रिया के लिए एक इवेंट हैंडलर इंस्टैंशिएट करना है। यानी यह जाँचने के लिए कि यह कंसोल प्रक्रिया के लिए या ब्राउज़र प्रक्रिया के लिए कुछ फ़ंक्शन चलाता है या नहीं। । फिर हम पास की गई प्रक्रियाओं पर पुनरावृति करते हैं और उनकी तुलना ज्ञात प्रक्रियाओं की सूची से करते हैं और संबंधित प्रक्रिया को चलाते हैं।  यदि हमें संबंधित प्रक्रिया नहीं मिलती है, तो यह किसी के द्वारा कार्यान्वित एक कस्टम प्रक्रिया है
कस्टम प्रक्रिया को कार्यान्वित करने के लिए यहाँ एक लिंक है और हम इस उदाहरण का उपयोग गतिशील विश्लेषण के दूसरे भाग के लिए करेंगे। https://bitbucket.org/chromiumembedded/cef/wiki/Tutorial ।
=====================================================================
गतिशील विश्लेषण भाग
पहले भाग की शुरुआत इस प्रकार होती है: पहले एडमिन अधिकार वाले cmd.exe से निम्न कमांड चलाएँ: windbg.exe chrome.exe -G -o --renderer-startup-dialog --no-sandbox --wait-for-debugger-children=renderer --renderer-process-limit=1 --allow-pre-commit-input --allow-sandbox-debugging । उसके बाद .childdbg 1 सेट करें ताकि हम नई स्पॉन की गई चाइल्ड प्रक्रियाओं को डिबग कर सकें। संक्षेप में उपरोक्त कमांड जो करता है वह यह है "सुनिश्चित करें कि आप सभी चाइल्ड प्रक्रियाओं से जुड़े हैं"। @spoofyroot और @_coreDump को बहुत-बहुत धन्यवाद जिन्होंने मल्टीप्रोसेस डिबगिंग के साथ मुझे सही दिशा में इंगित किया। .childdbg 1 सेट करने के बाद यह इस तरह दिखना चाहिए  अब चूँकि मैं किसी अन्य तरीके से यह कैप्चर नहीं कर सका कि आगे क्या होता है, मैंने एक वीडियो बनाया जिसमें मैं समझाऊँगा कि आगे क्या होता है। https://streamable.com/9t4iof । मूल रूप से जब हम content!content::StartupTaskRunner::RunAllTasksNow+0x88 को आखिरी बार चलाते हैं, तो हम नई प्रक्रियाएँ स्पॉन करते हैं जो कुछ ipc सामान संभालती हैं, और हमें content!content::RunContentProcess पर bp सेट करते रहना होगा जब तक कि वह इसे हिट न कर ले। इसे मैं शिक्षित परीक्षण और त्रुटि कहता हूँ :))।
=====================================================================
4.रेंडरर विश्लेषण
!अस्वीकरण
जब हम रेंडरर कोड का विश्लेषण करेंगे, तो हम blink कोड में भी थोड़ा गोता लगाएँगे ताकि हम समझ सकें कि रेंडरर में वास्तव में क्या होता है
इस कोर्स का यह भाग लिखते समय मुझे एहसास हुआ कि मैं संक्षेप में यह बताना भूल गया कि यह क्या करता है और हम इसे देखते भी क्यों हैं। जैसा कि हम जानते हैं, यह क्रोमियम द्वारा शुरू की गई तीसरी प्रक्रिया है और इसे रेंडरर कहा जाता है। लेकिन इसे "रेंडरर" क्यों कहा जाता है? इसे ऐसा इसलिए कहा जाता है क्योंकि इसका काम उन सभी चीज़ों को रेंडर(चित्रित) करना है जो हम एक वेबसाइट पर देखते हैं। मूल रूप से यही कारण है कि जब आप किसी वेबसाइट पर जाते हैं तो आपकी तालिका एक तालिका की तरह दिखती है, या आपका css किसी टेक्स्ट के टुकड़े को अनुकूलित करना संभव बनाता है। या आपका js ब्लैक मैजिक* करने में सक्षम क्यों है। एक और महत्वपूर्ण कारण जिसके लिए हम इसका विश्लेषण करते हैं, वह यह है कि अधिकांश बग यहीं से आते हैं। चाहे हम html, css, या js या किसी अन्य घटक के बारे में बात करें, आप उन सभी को chrome bugs.chromium.org पर blink के अंतर्गत देखेंगे।
* अधिक रेंडरर प्रक्रियाएँ होती हैं। ब्राउज़र द्वारा वर्तमान में खोले गए प्रत्येक टैब के लिए एक पूरी तरह से अलग प्रक्रिया होती है।
* यह प्रक्रिया वास्तविक वेबसाइट टैब के अंदर की किसी भी चीज़ को नियंत्रित करती है
* 2018 से शुरू करके, iframe को एक अपग्रेड मिला जहाँ उन सभी के टैब हो सकते हैं। और इस प्रकार iframe के प्रत्येक टैब के पास एक व्यक्तिगत रेंडरर प्रक्रिया होती है। इसे Site-Isolation कहा जाता है
* इसकी ज़िम्मेदारी है एक वेबसाइट को पार्स करना, आपकी स्क्रीन पर वह चित्रित करना जो वेबसाइट के अंदर है जैसे तालिकाएँ, चित्र, जावास्क्रिप्ट निष्पादित करना
* यह सैंडबॉक्स किया गया है
* इसके मूल में यह Blink नामक एक रेंडरिंग इंजन का उपयोग करता है।
* url-स्कीम बनाता और संभालता है जैसे : chrome://, devtools://, chrome-error://
* Blink इंजन को आरंभ करता है जो वास्तव में रेंडरर प्रक्रिया के लिए सभी पार्सिंग और भारी काम करेगा।
पिछली बार हमने ब्राउज़र प्रक्रिया विश्लेषण पूरा किया था और अब वह समय आ गया है जिसका हम सभी इंतज़ार कर रहे थे, रेंडरर विश्लेषण भाग करने का। ठीक है, जब मैं क्रोमियम के साथ खेल रहा था तो मैं इसे क्रैश कराने में सफल रहा और मुझे निम्न स्टैक ट्रेस मिला।  इसके आधार पर हम जानते हैं कि हमारी यात्रा content::RendererMain से शुरू होती है जो `\content\renderer\renderer_main.cc` में स्थित है। आपने सही अनुमान लगाया, प्रारंभिक बिंदु RendererMain है। आइए विश्लेषण करके शुरू करें कि इसे कैसे परिभाषित किया गया है और इसके अंदर थोड़ा सा  । हम देख सकते हैं कि यह MainFunctionParams प्रकार का एक पैरामीटर स्वीकार करता है जिसका अर्थ है कि यह फ़ंक्शन बाइनरी को पास किए गए तर्कों को स्वीकार करेगा। इसके बाद हम एक ट्रेस पॉइंट जोड़ते हैं ताकि हम जान सकें कि हम RendererMain को कॉल करने पर पहुँच गए हैं, और फिर parameters के मान को डीरेफ़रेंस करके command_line में सहेजते हैं। फिर हमारे पास कुछ मैक्रोज़ हैं जो प्लेटफ़ॉर्म-विशिष्ट आर्किटेक्चर की जाँच करते हैं जिन्हें हम अनदेखा कर सकते हैं , हम kTimeZoneForTesting को पास किए गए मान की जाँच करते हैं जो परीक्षण के लिए उपयोग किया जाने वाला एक समय क्षेत्र है, फिर हम icu नामक एक नई क्लास और डेटा प्रकार से मिलते हैं।

अब इसके लिए किसी परिभाषा स्रोत की खोज करते हुए हम https://unicode-org.github.io/icu-docs पर पहुँचते हैं। यदि हम फ़ाइल की शुरुआत देखें जहाँ include निर्देश है, तो हम देख सकते हैं कि यह एक तृतीय-पक्ष लाइब्रेरी है। तो अब तक हम जानते हैं कि यह एक तृतीय-पक्ष लाइब्रेरी है जो यूनिकोड के लिए अंतर्राष्ट्रीय घटकों से संबंधित है, यानी हम इसका उपयोग यूनिकोड समर्थन के लिए करते हैं। ठीक है, लेकिन वह फ़ंक्शन क्या करता है? https://unicode-org.github.io/icu-docs पर जाने पर हम देखते हैं , यानी हमारे द्वारा पैरामीटर के रूप में सेट किए गए मान के आधार पर डिफ़ॉल्ट समय क्षेत्र सेट करता है। फिर हम skia लाइब्रेरी को आरंभ करते हैं और --renderer-startup-dialog को संभालते हैं
। फिर हम RendererMainPlatformDelegate नामक एक नई क्लास से मिलते हैं।
यह क्या करता है? खैर, पहले हमें यह निर्दिष्ट करना होगा कि यह एक अमूर्त क्लास है जो प्लेटफ़ॉर्म-विशिष्ट है। हमारे मामले के लिए यह /content/renderer में renderer_main_platform_delegate_win.cc नामक फ़ाइल के अंदर स्थित होगा। यह इस तरह दिखता है
। तो हम यह निष्कर्ष निकाल सकते हैं कि यह सब एक सहायक फ़ंक्शन है जो सैंडबॉक्स को सक्षम करता है, यदि हम --no-sandbox पास करते हैं तो आवश्यक क्रियाएँ करता है और बस इतना ही। फिर हम अपने थ्रेड का नाम CrRendererMain सेट करते हैं। फिर हम RenderThread नामक एक और नई क्लास से मिलते हैं। 
चूँकि हम मूल रूप से नहीं जानते कि यह क्या करता है, आइए इसे थोड़ा खोजें। RendererThread कैसा दिखता है इसे समझने की हमारी खोज content/public/renderer/render_thread.h से शुरू होती है। render_thread.h फ़ाइल के अंदर देखने पर हम देखते हैं कि यह इस प्रकार परिभाषित है । उस पूरी फ़ाइल में से हमें IsMainThread में रुचि है जो rendere_thread.cc फ़ाइल में परिभाषित है और यह इस तरह दिखता है  (इस तंत्र के बारे में एक लंबा विवरण जोड़ें)। अब रेंडरर कोड के विश्लेषण के साथ आगे बढ़ते हुए हम सबसे प्रतीक्षित क्षण देख सकते हैं और वह यह है कि हम अंततः कुछ blink कोड देख पाते हैं। यह अपनी तरह का पहला है और यह लाइब्रेरी को आरंभ करता है।। पर्दे के पीछे फ़ंक्शन इस तरह दिखता है । अब स्वाभाविक प्रश्न उठता है कि वे क्लासेज़ क्या हैं? WTF और Platform क्या हैं? हमारी किस्मत अच्छी है, blink के दस्तावेज़ वास्तव में हमें बताते हैं कि वे क्या हैं।
https://docs.google.com/document/d/1aitSOucL0VHZa9Z2vbRJSyAIsAz24kX8LFByQ5xQnUg/edit । "Directory structure and dependencies" को देखते हुए हम अनुमान लगा सकते हैं कि platform एक क्लास है जो ज्यामिति और ग्राफिक्स में मदद करती है। अब WTF और Partitions क्लासेज़ पर। blink दस्तावेज़ WTF के बारे में भी कहते हैं: यह Web Template Framework से आता है और यह बहुत हद तक एक stl लाइब्रेरी "रैपर" है, जैसे "यह Blink के लिए एक आधार लाइब्रेरी है जो विभिन्न प्रकार की बुनियादी कार्यक्षमताएँ प्रदान करती है, जैसे कंटेनर, स्ट्रिंग लाइब्रेरी, रेफरेंस काउंटिंग तंत्र, फ़ंक्टर, थ्रेडिंग प्रिमिटिव आदि।"(blink दस्तावेज़ों से उद्धरण(https://chromium.googlesource.com/chromium/src/+/refs/heads/main/third_party/blink/renderer/platform/wtf/README.md))।blink के बारे में और विवरण जोड़ें
ठीक है, अब renderer_main.cc के विश्लेषण के साथ आगे बढ़ते हुए हम फिर से कुछ देखते हैं जिसके बारे में हम नहीं जानते कि यह क्या करता है और यह है  कल विवरण जोड़ें।फिर हम कॉल करते हैं ।फिर हम जाँचते हैं कि क्या हमने संकलन करते समय प्लगिन सक्षम किया है और यदि हमने किया है तो हम उन्हें लोड करते हैं।
 फिर हम कुछ और जाँच करते हैं जिन्हें मैंने समझाना छोड़ने का निर्णय लिया क्योंकि यह काफी लंबा स्पष्टीकरण हो रहा है और वे इस चरण में आवश्यक नहीं हैं। लेकिन TL;DR संस्करण में, यह देखना है कि RenderProcess आरंभीकरण से पहले सैंडबॉक्स को सक्षम करना है या नहीं। और फिर हम अंततः पर पहुँचते हैं ।(शेष फ़ंक्शनों के बारे में बाकी विवरण जोड़ें)। यद्यपि यह रेंडरर विश्लेषण का अंत नहीं है, हम इसे वास्तविक रेंडरर विश्लेषण का प्रारंभिक बिंदु मान सकते हैं क्योंकि जैसा कि हम बाद में देखेंगे, यहाँ अधिकांश दिलचस्प चीज़ें होती हैं, इसलिए हम इसे रेंडरर का कोड मान सकते हैं। हमें RenderThreadImpl में रुचि है, जो इस तरह दिखता है । उस सभी कोड से हमें Init() फ़ंक्शन में रुचि है, जो इस तरह दिखता है:
, लेकिन यह बहुत लंबा है। :) दुर्भाग्य से हम इसे एक ही चित्र में कैप्चर नहीं कर सकते, और इसलिए हमने इसकी शुरुआत कैप्चर की है। इसके अलावा, InitializeWebKit() के बाद जो कुछ भी होता है, वह वास्तव में हमारी रुचि का नहीं है क्योंकि इसका अधिकांश भाग केवल gpu प्रक्रिया के साथ ipc संचार है, जो अभी हमारे रडार पर नहीं है। किस्मत हम पर मुस्कुराती है क्योंकि उस फ़ंक्शन में हमने उन फ़ंक्शनों में से एक को भी पकड़ा जिनमें हमारी रुचि है, ठीक वैसे ही InitializeWebKit() ,जो फिर से इस तरह दिखता है ।हम renderer_main.cc को समझाने की अपनी खोज से थोड़ा भटक जाते हैं ताकि InitializeWebKit के अंदर क्या होता है इसे बेहतर ढंग से समझ सकें। मुझे पता है कि यह समझने के लिए बहुत कुछ है, लेकिन मेरे साथ धैर्य रखें क्योंकि हम इस अव्यवस्था का कुछ अर्थ निकालने की कोशिश करते हैं। तो हम देखते हैं कि InitializeWebKit() इस प्रक्रिया को पास किए गए जो भी तर्क लेकर शुरू होता है, फिर हम जाँचते हैं कि क्या हमने संकलन करते समय -dENABLE_VTUNE_JIT_INTERFACE सक्षम किया है, और यदि हमने किया है तो हम cmdline को पास किए गए विकल्प की जाँच करते हैं जो enable-vtune-support है। WTF क्या है? हमने गूगल पर खोजा और हमें https://www.intel.com/content/www/us/en/develop/documentation/vtune-help/top.html पर एक लिंक मिलता है और उस पृष्ठ पर यह कहता है: "यह सीरियल और मल्टीथ्रेडेड अनुप्रयोगों के लिए एक प्रदर्शन विश्लेषण उपकरण है"। तो tl;dr कुछ ऐसा जो आपके क्रोम के प्रदर्शन में सुधार करता है।फिर हम blink को आरंभ करते हैं । अब blink आरंभीकरण की प्रक्रिया को समझने के लिए आइए संक्षेप में समझाएँ क्योंकि हम अगले अध्याय में विस्तार में जाएँगे जो blink पर गहराई से देखेगा। हम एक और क्लास से मिलते हैं जो हमारे लिए एक अजनबी है और वह है RendererBlinkPlatformImpl, जो इस तरह दिखता है
 और content/renderer/renderer_blink_platform_impl.cc पर पाया जा सकता है। नाम के आधार पर हम यह निष्कर्ष निकाल सकते हैं कि यह एक अमूर्त क्लास है जो प्लेटफ़ॉर्म के आधार पर कार्यान्वित की जाती है और हम यह भी देख सकते हैं कि यह से विरासत प्राप्त करती है  RendererBlinkPlatformImpl वास्तव में क्या करता है इसे देखते हुए हम देखते हैं कि यह प्लेटफ़ॉर्म-आधारित जाँच करता है और फिर जाँच के परिणामों के आधार पर एक फ़्लैग चिह्नित करता है, फिर tls के लिए एक पॉइंटर प्राप्त करके जाँचता है कि क्या वर्तमान थ्रेड एक RendererThread है
ब्ला ब्ला ब्ला, देखो कि क्लासेज़ के बारे में और सामग्री जोड़नी है या नहीं। फिर हम किसी ऐसी चीज़ पर पहुँचते हैं जिसका हम सभी इंतज़ार कर रहे थे और वह है v8 कोड का पहला टुकड़ा। जो है । यह क्या करता है? सबसे पहले हम दस्तावेज़ों से जानते हैं कि एक v8::isolate V8 इंजन का एक उदाहरण है। यानी(V8 रनटाइम की एक स्वतंत्र प्रति, जिसमें हीप मैनेजर, गार्बेज कलेक्टर आदि शामिल हैं) स्क्रिप्ट चलाने के लिए पर्याप्त नहीं है। हम देखते हैं कि blink::MainThreadIsolate() इस प्रकार परिभाषित है
 जो blink/renderer/platform/bindings/v8_per_isolate_data.cc फ़ाइल में है, जो बदले में V8PerIsolateData::MainThreadIsolate() इस तरह दिखता है
 , V8PerIsolateData जो बदले में आपने अनुमान लगाया, एक क्लास भी है जो bindings/core/v8/V8PerIsolateData.h में पाई जाती है और लगभग इस तरह दिखती है ब्ला ब्ला ब्ला विवरण जोड़ें। फिर हम जाँचते हैं कि क्या हमने kDisableThreadedCompositing(कल जोड़ें कि फ़्लैग वास्तव में कैसा दिखता है)को कमांड लाइन पर पास किया है। यदि हमने नहीं किया तो हम एक compositor थ्रेड शुरू करते हैं। वह क्या है? https://frontendmasters.com/courses/web-performance/the-compositor-thread/ से उद्धृत करते हुए, यह एक थ्रेड है जिसका "एकमात्र काम बिटमैप बनाना, बिटमैप लेना, उन्हें GPU को भेजना, उन्हें स्क्रीन पर रखना है"। फिर हम रजिस्टर करते हैं जिसे scheme कहा जाता है। मूल रूप से क्या आपको याद है जब सोर्स देखते समय आपके पास url के सामने कुछ होता है जैसे: "view-source:website" । हाँ, वह वास्तव में रेंडरर द्वारा संभाला जाता है। और ऐसी और भी schemes हैं। रजिस्टर करने से उनका क्या मतलब है? मुझे अभी तक निश्चित नहीं है, लेकिन मुझे लगता है कि उनका मतलब है जैसे 'अरे, यह कुछ ऐसा है जिसे मैं चाहता हूँ कि आप संभालें जब उपयोगकर्ता आकर यह चीज़ करता है।' वैसे भी यह इस तरह दिखता है। और विवरण जोड़ें। ठीक है, अब जब मैं जोड़ता हूँ, तो कोड के अंतिम टुकड़े का भी विवरण दें 
। ब्ला ब्ला और अंत में हम renderer_main के अंतिम भाग पर पहुँच गए विवरण के साथ अपडेट करें

=====================================================================
गतिशील विश्लेषण भागअब इसे डायनामिक रूप से डीबग करने में सक्षम होने के लिए, यदि आप उतने ही नौसिखिए (noob) हैं जितना मैं हूँ, तो आप cmd.exe से windbg को निम्नानुसार चलाना चाहेंगे: windbg.exe chrome.exe -G -o --renderer-startup-dialog --no-sandbox --wait-for-debugger-children=renderer --renderer-process-limit=1 --allow-pre-commit-input --allow-sandbox-debugging --time-zone-for-testing="US/Pacific", और स्पॉन हुए चाइल्ड प्रोसेस को डीबग करने में सक्षम होने के लिए .childdbg 1 सेट करें। वहाँ से आप content!content::RendererMain पर bp लगाना चाहेंगे और इसे लगभग 5 या 6 बार चलने दें। (इसे बदलकर वीडियो में 4 का संदर्भ दें क्योंकि यह अधिक स्पष्ट है) उसके बाद हम  पर पहुँचते हैं।





MainDllLoader

--no-sandbox
chrome_mainअब देखते हैं यह क्या करता है। हम chromium.dll को binja में खोलते हैं।
https://blogs.igalia.com/jaragunde/files/2019/03/chrome-init-sequence.png से इस तस्वीर के आधार पर हमें एक मोटा अंदाज़ा है कि हमें binja में क्या खोजना चाहिए।
binja में ग्राफ़ इस प्रकार दिखता है
।
इसे बेहतर ढंग से ट्रैक करने के लिए ChromeMain नामक function को खोजें। यह chrome का main (यानी core) लॉजिक है। इसके अंदर हम chrome.dll के startup पर चलने के पहले बताए गए चरणों को देख सकते हैं:
यहाँ हम देख सकते हैं कि पहले यह कुछ functions को कॉल करता है जैसे sub_180001420, sub_180017020, sub_180017020, जो chrome कैसे install/compile किया गया था, इसके बारे में कुछ विवरण जाँचने के लिए कुछ checking करते हैं। स्रोत कोड का उपयोग करके हम उनके attributes को ट्रैक कर सकते हैं। पहला function, sub_180001420, UmaHistogramEnumeration से मेल खाता है, अगला हमारे पास sub_180017020 है जो InitializeFromPrimaryModule है और तीसरा और अंतिम sub_180017020 chrome_main_delegate है।
हम chrome_main_delegate को दोहराते रहते हैं लेकिन हमने कभी परिभाषित नहीं किया कि इसका उद्देश्य क्या है। ChromeMainDelegate एक class है जो ContentMainDelegate से inherit करती है और मुख्य रूप से startup से संबंधित functions और process call processing प्रदान करती है। ! यदि आप चाहें तो Content module के डिफ़ॉल्ट व्यवहार को बदलने के लिए एक custom ContentMainDelegate interface को implement कर सकते हैं, और Chromium में startup प्रक्रिया के व्यवहार को customize करने के लिए एक custom ChromeMainDelegate class का उपयोग कर सकते हैं।

इसके अंदर कुछ function calls हैं जो कुछ data regions पर xor करते हैं और chrome startup से संबंधित कुछ options प्राप्त करने के लिए इसे कुछ registry के साथ जोड़ते हैं।
।
यह भी ध्यान दें कि function sub_180001510 दो callbacks के साथ एक scoped pointer reference बना रहा है। यह वास्तव में महत्वपूर्ण नहीं है, लेकिन यह सीखना दिलचस्प है कि BindStateBase क्या है। हम इसे chrome के basecode में बहुत मिलेंगे।
अब आप सोच रहे होंगे कि आखिरी तीन पंक्तियाँ, विशेष रूप से
क्या करती हैं। तो पहली पंक्ति मूल रूप से Closures के लिए एक std::unique_ptr<> बनाती है। WTF! एक closure क्या है!? अच्छा, अगर हम mozila dev से उद्धृत करें, "closure is the combination of a function bundled together (enclosed) with references to its surrounding state (the lexical environment). In other words, a closure gives you access to an outer function’s scope from an inner function. In JavaScript, closures are created every time a function is created, at function creation time." अगर हम इसे मानवीय भाषा में कहें, तो यह एक function है जो दूसरे function के अंदर होता है और बाहरी function के भीतर एक variable को access करता है। उदा.
।
तो संक्षेप में यह सुनिश्चित करता है कि closure निष्पादित होगा। और बाकी दो पंक्तियाँ chrome crashes.InstallDetails::Get().VersionMismatch() के समय dumps के लिए कुछ विशेष व्यवहार सेट करती हैं। patchuie aici
आगे बढ़ते हुए, यह runtime पर अपने version की जाँच करता है और यदि यह मेल नहीं खाता है, तो यह crash हो जाता है और हम command line parsing पर पहुँचते हैं 
sub_184171800 के अंदर जाने पर हम देख सकते हैं कि यह इतना बड़ा नहीं है
सबसे पहले यह वर्तमान process को दिए गए arguments लेता है, फिर एक function को कॉल करता है जो एक StringPiece लेता है, जो मूल रूप से std::string के लिए एक class wrapper है, लेकिन थोड़ा अच्छा है, और वह function मूल रूप से जाँचता है कि क्या binary को headless कहा गया था, यह तुलना करता है कि जो binary चलाई गई थी उसका नाम chrome है या नहीं, जाँचता है कि USE_HEADLESS_CHROME सेट है या नहीं, और फिर अगले चरण में आगे बढ़ता है जो content main है।
दिए गए arguments के आधार पर, content main का काम संबंधित shell को शुरू करना है।
अब यदि हम shell को कोई arguments नहीं देते हैं, तो execution flow इस पर चला जाता है
।
यह समझने के लिए कि यह क्या करता है, हमें इसके स्रोत का सत्यापन करना होगा। हम इसे /src/content/app/content_main.cc पर पा सकते हैं
हमें सबसे नीचे तक स्क्रॉल करना होगा और वहाँ हमें ContentMain function की परिभाषा मिलेगी। वहाँ हम देखते हैं कि यह दो functions को कॉल करता है। एक जो ContentMainRunner को initialize करता है, जो वह class है जो browser ipc sqli net आदि बनाने के संदर्भ में सभी "process creation" को संभालता है। और दूसरा जो मूल रूप से subprocesses के प्रकार की जाँच करता है और उसे ContentMainRunner class को feed करता है।
अब codeflow को समझने के लिए एक कदम पीछे चलते हैं। पहले RunContentProcess की जाँच करते हैं क्योंकि ContentMainRunner काफी जटिल है। पहला कदम यह करता है कि एक GlobalActivityTracker बनाता है। ओह!!! आपने इसका अंदाज़ा लगा लिया, google आपको ट्रैक करता है :))) नहीं, बस मज़ाक कर रहा हूँ, कृपया मुझ पर मुकदमा मत करो Google। लेकिन गंभीरता से, यह प्रत्येक thread को ट्रैक करता है, एक thread tracker है, और यह बेहतर debugging के लिए कुछ अच्छी चीज़ें करता है जैसे:
जिसका सार यह है कि प्रत्येक thread के लिए एक अद्वितीय integer identifier के रूप में उपयोग किया जाएगा ताकि यह बेहतर ढंग से समझा जा सके कि process को किस कारण से break हुआ।
उदा.:```
kTypeIdActivityTracker = 0x5D7381AF + 4, // SHA1(ActivityTracker) v4
kTypeIdUserDataRecord = 0x615EDDD7 + 3, // SHA1(UserDataRecord) v3
kTypeIdGlobalLogMessage = 0x4CF434F9 + 1, // SHA1(GlobalLogMessage) v1
kTypeIdProcessDataRecord = kTypeIdUserDataRecord + 0x100,