-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathdbg.py
executable file
·170 lines (138 loc) · 4.12 KB
/
dbg.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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
#!/usr/bin/env python
import socket
from dbg_pb2 import *
import time
import struct
import sys
class XboxError(Exception):
def __init__(self, msg):
self.msg = msg
def __str__(self):
return self.msg
class Xbox(object):
def __init__(self):
self._sock = None
def connect(self, addr):
"""Connect to the Xbox"""
self._sock = socket.create_connection(addr, 5)
def disconnect(self):
"""Disconnect from the Xbox"""
self._sock.close()
self._sock = None
def _send_simple_request(self, req):
"""Send a simple request, expect success"""
self._sock.send(req.SerializeToString())
res = Response()
res.ParseFromString(self._sock.recv(4096))
if res.type != Response.OK:
raise XboxError(res.msg)
return res
def info(self):
"""Get system info"""
req = Request()
req.type = Request.SYSINFO
return self._send_simple_request(req).info
def reboot(self):
"""Reboot the system"""
msg = Request()
msg.type = Request.REBOOT
self._sock.send(msg.SerializeToString())
def malloc(self, size):
"""Allocate memory on the target"""
req = Request()
req.type = Request.MALLOC
req.size = size
return self._send_simple_request(req).address
def free(self, addr):
"""Free memory on the target"""
req = Request()
req.type = Request.FREE
req.address = addr
return self._send_simple_request(req)
def mem_read(self, addr, size):
"""read memory"""
req = Request()
req.type = Request.MEM_READ
req.size = size
req.address = addr
return self._send_simple_request(req).data
def mem_write(self, addr, data):
"""write memory"""
req = Request()
req.type = Request.MEM_WRITE
req.data = data
req.address = addr
return self._send_simple_request(req)
def debug_print(self, string):
"""Print a debug string to the screen"""
req = Request()
req.type = Request.DEBUG_PRINT
req.msg = string
return self._send_simple_request(req)
def show_debug_screen(self):
"""Show the debug screen"""
req = Request()
req.type = Request.SHOW_DEBUG_SCREEN
return self._send_simple_request(req)
def show_front_screen(self):
"""Show the front screen"""
req = Request()
req.type = Request.SHOW_FRONT_SCREEN
return self._send_simple_request(req)
def call(self, address, stack=None):
"""Call a function with given context"""
req = Request()
req.type = Request.CALL
req.address = address
if stack is not None:
req.data = stack
res = self._send_simple_request(req)
eax = struct.unpack_from("<I", res.data, 7*4)[0]
return eax
def main():
if (len(sys.argv) != 2):
print("Usage: " + sys.argv[0] + " <server>")
sys.exit(1)
xbox = Xbox()
addr = (sys.argv[1], 9269)
# Connect to the Xbox, display system info
xbox.connect(addr)
print(xbox.info())
# Print something to the screen
xbox.debug_print("Hello!")
# Allocate, write, read-back, free
addr = xbox.malloc(1024)
val = 0x5A
print("Allocated memory at 0x%x" % addr)
xbox.mem_write(addr, bytes([val]))
assert(xbox.mem_read(addr, 1)[0] == val)
xbox.free(addr)
# Inject a function which does `rdtsc; ret`.
# RDTSC means "Read Time Stamp Counter". The Time Stamp Counter is a value,
# which is incremented every CPU clock cycle.
code = bytes([0x0F, 0x31, 0xC3])
addr = xbox.malloc(len(code))
xbox.mem_write(addr, code)
# Repeatedly call the injected function until we have a stable timer
last_time = None
print("Testing call using RDTSC (please wait)")
while True:
# Ask the Xbox for the RDTSC value
eax = xbox.call(addr)
# The timer runs at 733MHz (Xbox CPU Clock speed); Convert to seconds
current_time = eax / 733333333.33
# This is necessary as the timer might wrap around between reads:
# First timestamp would appear to be later than the second timestamp.
# Also, at startup we only have one measurement, so we can't compare.
if last_time is not None and current_time > last_time:
break
# We wait 1 second (this is the time we expect to measure)
time.sleep(1.0)
last_time = current_time
# Print the measured time (should be ~1.0 seconds) and free function
print("RDTSC measured %.3f seconds" % (current_time - last_time))
xbox.free(addr)
#xbox.reboot()
xbox.disconnect()
if __name__ == '__main__':
main()