• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

Gallopsled / pwntools / 8912ca5a8c3a9725c3ba6d30561607150a6faebe-PR-2205

pending completion
8912ca5a8c3a9725c3ba6d30561607150a6faebe-PR-2205

Pull #2205

github-actions

web-flow
Merge 81f463e2c into 8b4cacf8b
Pull Request #2205: Fix stable Python 2 installation from a built wheel

3878 of 6371 branches covered (60.87%)

12199 of 16604 relevant lines covered (73.47%)

0.73 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

23.16
/pwnlib/adb/bootloader.py
1
from __future__ import unicode_literals
1✔
2
from __future__ import division
1✔
3

4
import ctypes
1✔
5
import io
1✔
6
import os
1✔
7
import six
1✔
8
import sys
1✔
9

10
from pwnlib.log import getLogger
1✔
11

12
log = getLogger(__name__)
1✔
13

14
class img_info(ctypes.Structure):
1✔
15
    _fields_ = [
1✔
16
        ('name', ctypes.c_char * 64),
17
        ('size', ctypes.c_uint32)
18
    ]
19

20
class bootloader_images_header(ctypes.Structure):
1✔
21
    _fields_ = [
1✔
22
        ('magic', ctypes.c_char * 8),
23
        ('num_images', ctypes.c_uint32),
24
        ('start_offset', ctypes.c_uint32),
25
        ('bootldr_size', ctypes.c_uint32),
26
    ]
27

28
BOOTLDR_MAGIC = b'BOOTLDR!'
1✔
29

30
class BootloaderImage(object):
1✔
31
    def __init__(self, data):
1✔
32
        """Android Bootloader image
33

34
        Arguments:
35
            data(str): Binary data from the image file.
36
        """
37
        self.data = data
×
38
        self.header = bootloader_images_header.from_buffer_copy(data)
×
39

40
        if self.magic != BOOTLDR_MAGIC:
×
41
            log.error("Incorrect magic (%r, expected %r)" % (self.magic, BOOTLDR_MAGIC))
×
42

43
        if(self.bootldr_size > len(data)):
×
44
            log.warn_once("Bootloader is supposed to be %#x bytes, only have %#x",
×
45
                          self.bootldr_size,
46
                          len(data))
47

48
        if(self.num_images >= 0x100):
×
49
            old = self.num_images
×
50
            self.num_images = 1
×
51
            log.warn_once("Bootloader num_images (%#x) appears corrupted, truncating to 1",
×
52
                          old)
53

54
        imgarray = ctypes.ARRAY(img_info, self.num_images)
×
55
        self.img_info = imgarray.from_buffer_copy(data, ctypes.sizeof(self.header))
×
56

57
    def extract(self, index_or_name):
1✔
58
        """extract(index_or_name) -> bytes
59

60
        Extract the contents of an image.
61

62
        Arguments:
63
            index_or_name(str,int): Either an image index or name.
64

65
        Returns:
66
            Contents of the image.
67
        """
68
        if isinstance(index_or_name, six.integer_types):
×
69
            index = index_or_name
×
70
        else:
71
            for i in range(len(self.img_info)):
×
72
                if self.img_info[i].name == index_or_name:
×
73
                    index = i
×
74
                    break
×
75
            else:
76
                raise ValueError("Invalid img name: %r" % index_or_name)
×
77

78
        if index >= len(self.img_info):
×
79
            raise ValueError("index out of range (%s, max %s)" % (index, len(self.img_info)))
×
80

81
        offset = self.start_offset
×
82

83
        for i in range(index):
×
84
            offset += self.img_info[i].size
×
85

86
        return self.data[offset:offset + self.img_info[index].size]
×
87

88
    def extract_all(self, path):
1✔
89
        """extract_all(path)
90

91
        Extracts all images to the provided path.  The filenames are taken
92
        from the image name, with '.img' appended.
93
        """
94
        if not os.path.isdir(path):
×
95
            raise ValueError("%r does not exist or is not a directory" % path)
×
96

97
        for img in self.img_info:
×
98
            imgpath = os.path.join(path, img.name + '.img')
×
99
            with open(imgpath, 'wb+') as f:
×
100
                data = self.extract(img.name)
×
101
                f.write(data)
×
102

103
    def __str__(self):
1✔
104
        rv = []
×
105
        rv.append("Bootloader")
×
106
        rv.append("  Magic:  %r" % self.magic)
×
107
        rv.append("  Offset: %#x" % self.start_offset)
×
108
        rv.append("  Size:   %#x" % self.bootldr_size)
×
109
        rv.append("  Images: %s" % self.num_images)
×
110
        for img in self.img_info:
×
111
            rv.append("    Name: %s" % img.name)
×
112
            rv.append("    Size: %#x" % img.size)
×
113
            rv.append("    Data: %r..." % self.extract(img.name)[:32])
×
114
        return '\n'.join(rv)
×
115

116
    def __getattr__(self, name):
1✔
117
        if name.startswith('_'):
×
118
            raise AttributeError(name)
×
119

120
        return getattr(self.header, name)
×
121

122

123
if __name__ == '__main__':
1!
124
    # Easy sanity checking
125
    b = BootloaderImage(open(sys.argv[1], 'rb').read())
×
126
    print(b)
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc