
x64 PE bin2bin obfuscator जो बाइनरी में section नहीं जोड़ता
निर्माण निर्देशों के लिए 4. निर्माण देखें।
यह अस्पष्टीक यंत्र bin2bin है, जिसका अर्थ है कि यह पहले से संकलित निष्पादन योग्य बाइनरी लेता है और अस्पष्टीकरण पास लागू करके इसे पुन: उत्पन्न करता है। इसका उपयोग मूल स्रोत कोड तक पहुँच के बिना किसी एप्लिकेशन को सुरक्षित करने के लिए किया जा सकता है। फिलहाल केवल x64 PE (पोर्टेबल निष्पादन योग्य) फ़ाइलें समर्थित हैं, लेकिन भविष्य में अन्य बाइनरी प्रारूपों (जैसे ELF) के लिए समर्थन जोड़ने की योजना है।
वर्तमान में, सभी ज्ञात bin2bin अस्पष्टीक यंत्र बाइनरी के अंत में एक अनुभाग सम्मिलित करते हैं ताकि अस्पष्ट कोड या डेटा को अंदर रखा जा सके। ऐसा इसलिए है ताकि पूर्व-मौजूद अनुभागों की सामग्री को बदलने की आवश्यकता न होने से बाइनरी का मूल लेआउट संरक्षित रहे। इसे प्रबंधित करना बहुत आसान है क्योंकि यह अधिकांश RVA (सापेक्ष पतों) को मान्य रखता है।
यह परियोजना bin2bin के लिए एक अनूठा दृष्टिकोण अपनाती है, जहाँ किसी भी अस्पष्ट कोड या डेटा को बाइनरी के मूल अनुभागों के भीतर डाला जाता है। इसके लिए एप्लिकेशन में प्रत्येक एकल RVA को ट्रैक करना आवश्यक है। इस दृष्टिकोण के लाभ हैं:
यह दस्तावेज़ निष्पादन योग्य बाइनरी के पुनर्लेखन और लागू किए गए अस्पष्टीकरण तकनीकों दोनों का वर्णन करेगा। निम्नलिखित अस्पष्टीकरण तकनीकों को लागू किया गया है:
इसके अलावा, इस परियोजना में अपवाद समर्थन (C++ अपवाद और SEH) भी है और यह अपवाद प्रबंधन वाले फ़ंक्शन को अस्पष्ट करने में सक्षम है।
बाइनरी में डिसअसेंबली और कोड की खोज में सहायता के लिए, प्रतीक फ़ाइलें (PDB और MAP दोनों) वैकल्पिक रूप से स्वीकार की जाती हैं। प्रतीक फ़ाइलें प्रदान करना आवश्यक नहीं है लेकिन जटिल बाइनरी में डिसअसेंबली में सहायता करता है। कुछ सुविधाएँ जैसे अपवाद समर्थन और नियंत्रण प्रवाह समतलन के लिए प्रतीक फ़ाइल प्रदान करना आवश्यक है।
एक बाइनरी पुनर्लेखक एक निष्पादन योग्य बाइनरी लेता है और उसके अंदर कोड या डेटा को बदलता है ताकि परिवर्तनों के साथ एक आउटपुट बाइनरी तैयार हो सके।
जैसे-जैसे अस्पष्ट कोड सीधे बाइनरी के मूल अनुभागों में डाला जाता है, प्रोग्राम में सापेक्ष पतों को ट्रैक किया जाना चाहिए ताकि उनके सभी संदर्भों को समायोजित किया जा सके। ऐसा इसलिए है ताकि कोड और डेटा डालने के बाद भी संदर्भ उसी स्थान पर इंगित करते रहें। अन्यथा डेटा या कोड गलत स्थान पर एक्सेस होगा, जिससे आउटपुट बाइनरी का व्यवहार बदल जाएगा और गंभीर अस्थिरता पैदा होगी।
जब भी किसी सापेक्ष पते का कोई संदर्भ मिलता है (जैसे rip सापेक्ष ऑपरेंड युक्त निर्देश या PE डेटा निर्देशिकाएँ), इसे पुनर्लेखन के अंत में अद्यतन करने के लिए एक ट्रैकिंग सूची में जोड़ा जाता है। जहाँ संदर्भ होता है उसका RVA ट्रैक किया जाता है (यह जानने के लिए कि संदर्भ को कहाँ अद्यतन करना है) साथ ही जिस RVA का संदर्भ दिया जा रहा है उसे भी ट्रैक किया जाता है (यह जानने के लिए कि संदर्भ को किस RVA से अद्यतन करना है)।
जब भी डिसअसेंबलर को एक rip सापेक्ष निर्देश मिलता है, तो वह इसे अस्पष्टीकरण के अंत में अद्यतन किए जाने वाले संदर्भों की सूची में जोड़ देगा। यह सुनिश्चित करता है कि वे सभी निर्देश अभी भी उसी स्थान पर इंगित कर रहे हैं जो मूल रूप से थे। जंप टेबल जैसे अन्य सापेक्ष निर्देश मामलों को भी अद्यतन किए जाने वाले संदर्भों के रूप में जोड़ा जाता है।
जब भी बाइनरी में कोई बाइट्स डाले या हटाए जाते हैं, तो ट्रैक किए गए सभी RVA को समायोजित करने की आवश्यकता होती है। उदाहरण के लिए, यहाँ बाइट सम्मिलन हैंडलर दिया गया है:```cpp
void binwrite::binary_t::insert(const rva_t rva, const std::span data, const bool inclusive)
{
buffer_.insert_range(buffer_.begin() + rva.value(), data);
update_rvas(rva, static_cast<rva_t::size_type>(data.size()), inclusive);
}
`update_rvas` वह स्थान है जहाँ बाइनरी में हुए परिवर्तन को दर्शाने के लिए प्रत्येक ट्रैक किए गए RVA को अपडेट किया जाता है। यहाँ इस प्रक्रिया का एक आरेख है:

चित्र 1. सापेक्ष पता ट्रैकिंग।
डाला गया डेटा (नीला) वर्तमान डेटा (ग्रे) को स्थानांतरित करता है। निर्देश का संदर्भित RVA (नारंगी) उसी मेमोरी को इंगित करने के लिए अपडेट होता है, जो डाले गए डेटा (नीला) को ध्यान में रखता है।
## 2.2. डिसएसेम्बली
सभी संभावित कोड प्रविष्टियाँ (एक्सपोर्ट, एंट्री पॉइंट, कोड सेक्शन की ओर इशारा करने वाले रिलोकेशन, आदि) को एक डिसएसेम्बली क्यू में जोड़ा जाता है। यदि कोई सिम्बोल फ़ाइल मौजूद है, तो सिम्बोल फ़ाइल द्वारा वर्णित सभी फ़ंक्शन भी डिसएसेम्बली क्यू में जोड़े जाते हैं। क्यू में प्रत्येक प्रविष्टि को एक व्यक्तिगत बेसिक ब्लॉक के रूप में माना जाता है।
एक बेसिक ब्लॉक बिना किसी ब्रांच के निर्देशों का एक समूह है; इसका मतलब है कि यह कंट्रोल फ्लो निर्देशों (जैसे जंप, ret, int) पर समाप्त होता है। बेसिक ब्लॉक कॉल पर समाप्त नहीं होते क्योंकि अधिकांश मामलों में उनके वापस लौटने की उम्मीद होती है। कुछ फ़ंक्शन वापस नहीं लौटते (जैसे _CxxThrowException) और अब से उन्हें 'noreturn' कॉल कहा जाएगा।
जब डिसएसेम्बली क्यू से किसी बेसिक ब्लॉक को प्रोसेस किया जा रहा होता है, तो प्रत्येक निर्देश को ऊपर से शुरू करके डिसएसेम्बल किया जाता है जब तक कि निम्नलिखित में से एक न हो जाए:
- कोई अन्य पहले से विश्लेषित बेसिक ब्लॉक पहुँच जाता है, जिससे ओवरलैप होता है। “बेसिक ब्लॉक विभाजन” देखें।
- समाप्ति निर्देश मिलता है (जंप, return, int)।
- निर्देश का डिसएसेम्बली विफल हो जाता है।
- कोड पैडिंग मिल जाती है।
नीचे डिसएसेम्बली और डिसएसेम्बली क्यू में प्रविष्टि का एक आरेख है (आरेख में कोड पैडिंग जाँच छोड़ दी गई है)। यह तब तक दोहराया जाता है जब तक डिसएसेम्बली क्यू खाली नहीं हो जाता।

चित्र 2. डिसएसेम्बली प्रसंस्करण।
### 2.2.1 बेसिक ब्लॉक विभाजन
यदि दो बेसिक ब्लॉक ओवरलैप होते हैं, तो उनमें से एक को विभाजित किया जाना चाहिए। इससे दो ब्लॉक एक ही निर्देशों का वर्णन करने से रुक जाते हैं। उदाहरण के लिए:```asm
wcslen proc
or rax, 0FFFFFFFFFFFFFFFFh
loc_140001078:
inc rax
cmp word ptr [rcx+rax*2], 0
jnz short loc_140001078
retn
wcslen endp
यह wcslen का एक कार्यान्वयन है, जो एक वाइड स्ट्रिंग की लंबाई प्राप्त करता है। जब पहली इंस्ट्रक्शन 'or rax, FFFFFFFFFFFFFFFF' को एक बेसिक ब्लॉक की शुरुआत के रूप में डिसअसेंबल किया जाता है, तो यह 'retn' तक डिसअसेंबल करता रहेगा।