This repository has been archived by the owner on May 14, 2018. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 9
/
Copy pathtrustedthread.py
90 lines (77 loc) · 3.12 KB
/
trustedthread.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
#! /usr/bin/env python
import os, struct
## mimics the sharepoint structure in inject.h
SPACE_SIZE=512
OFFSET_OF_SPACE = 0
OFFSET_OF_SYSCALL_DROPBOX = OFFSET_OF_SPACE+SPACE_SIZE
OFFSET_OF_JUNK = OFFSET_OF_SYSCALL_DROPBOX + 28
OFFSET_OF_RETARRAY = OFFSET_OF_JUNK + 4
OFFSET_OF_SIGSET = OFFSET_OF_RETARRAY+256
END_STRUCTURE = OFFSET_OF_SIGSET+32*4
def range2tuple(s):
return map(lambda x: int(x, 16), s.split('-'))
class TrustedThread(object):
def __init__(self, pid, fd, mapping):
self.pid = pid
self.freespace_start = 0
self.mapping=mapping
self.fill_retbytes()
self.thread = os.fdopen(fd, 'w+')
sharespace = struct.unpack('I', self.thread.read(4))[0]
self.ro_area = (sharespace, sharespace+END_STRUCTURE)
def fill_retbytes(self):
self.mapping[OFFSET_OF_RETARRAY:OFFSET_OF_RETARRAY+256] = struct.pack('256B', *range(0, 256))
self.mapping[OFFSET_OF_SIGSET:OFFSET_OF_SIGSET+4] = struct.pack('I', 0x7fffffff)
self.mapping[OFFSET_OF_SIGSET+4:OFFSET_OF_SIGSET+8] = struct.pack('I', 0xfffffffe)
self.mapping[OFFSET_OF_SIGSET+8:OFFSET_OF_SIGSET+8+4*30] = '\xff'*(4*30)
def delegate(self, mm, willexit=False):
for name in ['eax', 'ebx', 'ecx', 'edx', 'esi', 'edi', 'ebp']:
value = getattr(mm, name)
if isinstance(value, str):
ptr = self.push_volatile(value)
setattr(mm, name, ptr)
self.push_registers(mm)
self.wakeup()
if not willexit:
ret = struct.unpack('I', self.thread.read(4))[0]
self.forget()
return ret
def mappings(self):
maps=[]
for line in open('/proc/' + self.pid + '/maps', 'r'):
fields = filter(lambda x: x, line.strip().split(' '))
(memrange, perms, offset, dev, inode) = fields[:5]
try:
name = fields[5]
except:
name = 'n/a'
maps.append([name, memrange, perms, inode])
return maps
def get_protected_sections(self):
sandboxedapp = os.readlink('/proc/' + self.pid + '/exe')
sections = [self.ro_area]
for mm in self.mappings():
if mm[0] in [sandboxedapp, '[vdso]', '/dev/shm/seccompnurse']:
sections.append(range2tuple(mm[1]))
return sections
def push_registers(self, mm):
raw = mm.pack()
ptr=OFFSET_OF_SYSCALL_DROPBOX
self.mapping[ptr:ptr+len(raw)] = raw
def wakeup(self):
self.thread.write('PING')
self.thread.flush()
def push_volatile(self, value):
start = self.freespace_start
end = start + len(value)
if end-start > self.mapping.size():
raise Exception('Not enought memory to store value argument')
self.mapping[start:end] = value
self.freespace_start = end
return start+self.ro_area[0]
def forget(self):
"""
syscall has been performed, we can now "free" the memory.
"""
self.freespace_start = 0
self.mapping[:OFFSET_OF_JUNK] = '\x00'*OFFSET_OF_JUNK