Samsung Firmware Boot.img Extractor

Automatically extracts boot.img from downloaded Samsung firmware files

Size

11.2 KB

Version

1.0.1

Created

Jan 27, 2026

Updated

7 days ago

1// ==UserScript==
2// @name		Samsung Firmware Boot.img Extractor
3// @description		Automatically extracts boot.img from downloaded Samsung firmware files
4// @version		1.0.1
5// @match		https://*.samfw.com/*
6// @icon		https://samfw.com/assets/img/favicon.ico
7// @require		https://cdnjs.cloudflare.com/ajax/libs/jszip/3.10.1/jszip.min.js
8// @grant		GM.xmlhttpRequest
9// ==/UserScript==
10(function() {
11    'use strict';
12    
13    console.log('Samsung Firmware Boot.img Extractor loaded');
14    
15    // UI Elements
16    let extractionPanel = null;
17    let statusText = null;
18    let progressBar = null;
19    
20    // Create UI for extraction status
21    function createExtractionUI() {
22        if (extractionPanel) return;
23        
24        extractionPanel = document.createElement('div');
25        extractionPanel.id = 'boot-extractor-panel';
26        extractionPanel.style.cssText = `
27            position: fixed;
28            top: 20px;
29            right: 20px;
30            width: 350px;
31            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
32            border-radius: 12px;
33            padding: 20px;
34            box-shadow: 0 10px 40px rgba(0,0,0,0.3);
35            z-index: 999999;
36            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
37            color: white;
38            display: none;
39        `;
40        
41        extractionPanel.innerHTML = `
42            <div style="display: flex; align-items: center; margin-bottom: 15px;">
43                <div style="font-size: 24px; margin-right: 10px;">🔧</div>
44                <div style="flex: 1;">
45                    <div style="font-weight: bold; font-size: 16px;">Boot.img Extractor</div>
46                    <div id="extractor-status" style="font-size: 13px; opacity: 0.9; margin-top: 3px;">Ready</div>
47                </div>
48            </div>
49            <div style="background: rgba(255,255,255,0.2); border-radius: 8px; height: 8px; overflow: hidden; margin-bottom: 10px;">
50                <div id="extractor-progress" style="background: white; height: 100%; width: 0%; transition: width 0.3s;"></div>
51            </div>
52            <button id="extractor-close" style="
53                position: absolute;
54                top: 10px;
55                right: 10px;
56                background: rgba(255,255,255,0.2);
57                border: none;
58                color: white;
59                width: 24px;
60                height: 24px;
61                border-radius: 50%;
62                cursor: pointer;
63                font-size: 16px;
64                line-height: 1;
65            ">×</button>
66        `;
67        
68        document.body.appendChild(extractionPanel);
69        
70        statusText = document.getElementById('extractor-status');
71        progressBar = document.getElementById('extractor-progress');
72        
73        document.getElementById('extractor-close').addEventListener('click', () => {
74            extractionPanel.style.display = 'none';
75        });
76        
77        console.log('Extraction UI created');
78    }
79    
80    // Show extraction panel
81    function showExtractionPanel() {
82        if (!extractionPanel) createExtractionUI();
83        extractionPanel.style.display = 'block';
84    }
85    
86    // Update status
87    function updateStatus(message, progress = null) {
88        console.log('Extractor status:', message, progress);
89        if (statusText) statusText.textContent = message;
90        if (progressBar && progress !== null) {
91            progressBar.style.width = progress + '%';
92        }
93    }
94    
95    // Extract boot.img from firmware file
96    async function extractBootImg(firmwareBlob, filename) {
97        try {
98            showExtractionPanel();
99            updateStatus('Loading firmware file...', 10);
100            
101            console.log('Starting extraction from file:', filename, 'Size:', firmwareBlob.size);
102            
103            // Load the ZIP file
104            const zip = await JSZip.loadAsync(firmwareBlob, {
105                createFolders: true
106            });
107            
108            updateStatus('Searching for boot.img...', 30);
109            console.log('ZIP loaded, files:', Object.keys(zip.files));
110            
111            // Look for boot.img in the archive
112            let bootImgFile = null;
113            let bootImgPath = null;
114            
115            // Search for boot.img (case insensitive)
116            for (let path in zip.files) {
117                const file = zip.files[path];
118                const fileName = path.toLowerCase();
119                
120                console.log('Checking file:', path);
121                
122                if (fileName.includes('boot.img') && !file.dir) {
123                    bootImgFile = file;
124                    bootImgPath = path;
125                    console.log('Found boot.img at:', path);
126                    break;
127                }
128            }
129            
130            // If not found directly, look inside nested archives (like .tar.md5)
131            if (!bootImgFile) {
132                updateStatus('Searching in nested archives...', 40);
133                console.log('boot.img not found in root, checking nested archives');
134                
135                for (let path in zip.files) {
136                    const file = zip.files[path];
137                    const fileName = path.toLowerCase();
138                    
139                    // Check for tar or tar.md5 files
140                    if ((fileName.endsWith('.tar') || fileName.endsWith('.tar.md5')) && !file.dir) {
141                        console.log('Found nested archive:', path);
142                        updateStatus('Extracting nested archive...', 50);
143                        
144                        try {
145                            const tarBlob = await file.async('blob');
146                            const tarZip = await JSZip.loadAsync(tarBlob);
147                            
148                            console.log('Nested archive files:', Object.keys(tarZip.files));
149                            
150                            for (let tarPath in tarZip.files) {
151                                const tarFile = tarZip.files[tarPath];
152                                if (tarPath.toLowerCase().includes('boot.img') && !tarFile.dir) {
153                                    bootImgFile = tarFile;
154                                    bootImgPath = tarPath;
155                                    console.log('Found boot.img in nested archive:', tarPath);
156                                    break;
157                                }
158                            }
159                            
160                            if (bootImgFile) break;
161                        } catch (e) {
162                            console.log('Could not extract nested archive:', path, e);
163                        }
164                    }
165                }
166            }
167            
168            if (!bootImgFile) {
169                updateStatus('❌ boot.img not found in firmware', 100);
170                console.error('boot.img not found in firmware archive');
171                setTimeout(() => {
172                    extractionPanel.style.display = 'none';
173                }, 5000);
174                return;
175            }
176            
177            updateStatus('Extracting boot.img...', 70);
178            console.log('Extracting boot.img from:', bootImgPath);
179            
180            // Extract boot.img
181            const bootImgBlob = await bootImgFile.async('blob');
182            
183            updateStatus('Preparing download...', 90);
184            console.log('boot.img extracted, size:', bootImgBlob.size);
185            
186            // Create download link
187            const url = URL.createObjectURL(bootImgBlob);
188            const a = document.createElement('a');
189            a.href = url;
190            a.download = 'boot.img';
191            document.body.appendChild(a);
192            a.click();
193            document.body.removeChild(a);
194            
195            // Clean up
196            setTimeout(() => URL.revokeObjectURL(url), 1000);
197            
198            updateStatus('✅ boot.img downloaded successfully!', 100);
199            console.log('boot.img download initiated');
200            
201            setTimeout(() => {
202                extractionPanel.style.display = 'none';
203            }, 5000);
204            
205        } catch (error) {
206            console.error('Error extracting boot.img:', error);
207            updateStatus('❌ Extraction failed: ' + error.message, 100);
208            setTimeout(() => {
209                extractionPanel.style.display = 'none';
210            }, 5000);
211        }
212    }
213    
214    // Add extraction button to download section
215    function addExtractionButton() {
216        const downloadSection = document.getElementById('download_section');
217        if (!downloadSection || document.getElementById('boot-extractor-button')) return;
218        
219        console.log('Adding extraction button to page');
220        
221        const buttonContainer = document.createElement('div');
222        buttonContainer.className = 'row my-2';
223        buttonContainer.innerHTML = `
224            <div class="col-lg-10 offset-lg-1 col-xl-6 offset-xl-3">
225                <button id="boot-extractor-button" class="btn btn-success btn-lg w-100" style="
226                    background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
227                    border: none;
228                    box-shadow: 0 4px 15px rgba(102, 126, 234, 0.4);
229                ">
230                    <i class="fas fa-magic"></i> Extract boot.img from Downloaded Firmware
231                </button>
232                <div class="small text-center mt-2" style="color: #666;">
233                    Click after downloading firmware to extract boot.img
234                </div>
235            </div>
236        `;
237        
238        const downloadArea = document.getElementById('download_area');
239        if (downloadArea) {
240            downloadArea.appendChild(buttonContainer);
241            
242            document.getElementById('boot-extractor-button').addEventListener('click', async () => {
243                console.log('Extract button clicked');
244                
245                // Create file input to select downloaded firmware
246                const fileInput = document.createElement('input');
247                fileInput.type = 'file';
248                fileInput.accept = '.zip,.tar,.tar.md5,.md5';
249                fileInput.style.display = 'none';
250                
251                fileInput.addEventListener('change', async (e) => {
252                    const file = e.target.files[0];
253                    if (file) {
254                        console.log('File selected:', file.name, file.size);
255                        await extractBootImg(file, file.name);
256                    }
257                    document.body.removeChild(fileInput);
258                });
259                
260                document.body.appendChild(fileInput);
261                fileInput.click();
262            });
263        }
264    }
265    
266    // Initialize
267    function init() {
268        console.log('Initializing Boot.img Extractor');
269        
270        // Wait for page to load
271        if (document.readyState === 'loading') {
272            document.addEventListener('DOMContentLoaded', init);
273            return;
274        }
275        
276        // Add extraction button
277        addExtractionButton();
278        
279        // Also try again after a delay in case page loads dynamically
280        setTimeout(addExtractionButton, 2000);
281        
282        console.log('Boot.img Extractor initialized');
283    }
284    
285    init();
286})();
Samsung Firmware Boot.img Extractor | Robomonkey