Handle `!` with r_core_cmd_str_pipe Fix 'afl' output Add help for 'px' command Add pxQ and pxW to show one word per line Fix segmented io with maps and sections Some test cases got fixed Add test-r_anal.py
220 lines
5.1 KiB
Python
Executable file
220 lines
5.1 KiB
Python
Executable file
#!/usr/bin/python
|
|
#
|
|
# Python implementation of the radare remote protocol
|
|
#
|
|
|
|
##===================================================0
|
|
## server api
|
|
##===================================================0
|
|
|
|
from socket import *
|
|
from struct import *
|
|
import traceback
|
|
import sys
|
|
|
|
RAP_OPEN = 1
|
|
RAP_READ = 2
|
|
RAP_WRITE = 3
|
|
RAP_SEEK = 4
|
|
RAP_CLOSE = 5
|
|
RAP_SYSTEM = 6
|
|
RAP_CMD = 7
|
|
RAP_REPLY = 0x80
|
|
|
|
# TODO: Add udp
|
|
# TODO: allow to init funptrs with a tuple
|
|
class RapServer():
|
|
def __init__(self):
|
|
self.offset = 0
|
|
self.size = 0
|
|
self.handle_eof = None
|
|
self.handle_cmd_system = None
|
|
self.handle_cmd_seek = None
|
|
self.handle_cmd_read = None
|
|
self.handle_cmd_write = None
|
|
self.handle_cmd_open = None
|
|
self.handle_cmd_close = None
|
|
|
|
def _handle_packet(self, c, key):
|
|
ret = ""
|
|
if key == RAP_OPEN:
|
|
buffer = c.recv(2)
|
|
(flags, length) = unpack(">BB", buffer)
|
|
file = c.recv(length)
|
|
if self.handle_cmd_open != None:
|
|
fd = self.handle_cmd_open(file, flags)
|
|
else: fd = 3434
|
|
buf = pack(">Bi", key|RAP_REPLY, fd)
|
|
c.send(buf)
|
|
elif key == RAP_READ:
|
|
buffer = c.recv(4)
|
|
(length,) = unpack(">I", buffer)
|
|
if self.handle_cmd_read != None:
|
|
ret = str(self.handle_cmd_read(length))
|
|
try:
|
|
lon = len(ret)
|
|
except:
|
|
ret = ""
|
|
lon = 0
|
|
else:
|
|
ret = ""
|
|
lon = 0;
|
|
buf = pack(">Bi", key|RAP_REPLY, lon)
|
|
c.send(buf+ret)
|
|
elif key == RAP_WRITE:
|
|
buffer = c.recv(4)
|
|
(length,) = unpack(">I", buffer)
|
|
buffer = c.recv(length)
|
|
# TODO: get buffer and length
|
|
if self.handle_cmd_write != None:
|
|
length = self.handle_cmd_write (buffer)
|
|
buf = pack(">Bi", key|RAP_REPLY, length)
|
|
c.send(buf)
|
|
elif key == RAP_SEEK:
|
|
buffer = c.recv(9)
|
|
(type, off) = unpack(">BQ", buffer)
|
|
if self.handle_cmd_seek != None:
|
|
seek = self.handle_cmd_seek(off, type)
|
|
else:
|
|
if type == 0: # SET
|
|
seek = off;
|
|
elif type == 1: # CUR
|
|
seek = seek + off
|
|
elif type == 2: # END
|
|
seek = self.size;
|
|
self.offset = seek
|
|
buf = pack(">BQ", key|RAP_REPLY, seek)
|
|
c.send(buf)
|
|
elif key == RAP_CLOSE:
|
|
if self.handle_cmd_close != None:
|
|
length = self.handle_cmd_close (fd)
|
|
elif key == RAP_SYSTEM:
|
|
buf = c.recv(4)
|
|
(length,) = unpack(">i", buf)
|
|
ret = c.recv(length)
|
|
if self.handle_cmd_system != None:
|
|
reply = self.handle_cmd_system(ret)
|
|
else: reply = ""
|
|
buf = pack(">Bi", key|RAP_REPLY, len(str(reply)))
|
|
c.send(buf+reply)
|
|
else:
|
|
print "Unknown command"
|
|
c.close()
|
|
|
|
def _handle_client(self, c):
|
|
while True:
|
|
try:
|
|
buf = c.recv(1)
|
|
if buf == "" and self.handle_eof is not None:
|
|
self.handle_eof(c)
|
|
break
|
|
if len(buf) == 0:
|
|
print "Connection closed\n"
|
|
break
|
|
self._handle_packet(c, ord(buf))
|
|
except KeyboardInterrupt:
|
|
break
|
|
|
|
def listen_tcp(self, port):
|
|
s = socket();
|
|
s.bind(("0.0.0.0", port))
|
|
s.listen(999)
|
|
print "Listening at port %d"%port
|
|
while True:
|
|
(c, (addr,port)) = s.accept()
|
|
print "New client %s:%d"%(addr,port)
|
|
self._handle_client(c)
|
|
|
|
|
|
##===================================================0
|
|
## client api
|
|
##===================================================0
|
|
|
|
class RapClient():
|
|
def __init__(self, host, port):
|
|
self.connect_tcp(host, port)
|
|
|
|
def connect_tcp(self, host, port):
|
|
fd = socket();
|
|
fd.connect((host, port))
|
|
self.fd = fd
|
|
|
|
def disconnect(self):
|
|
self.fd.close()
|
|
self.fd = None
|
|
|
|
def open(self, file, flags):
|
|
b = pack(">BBB", RAP_OPEN, flags, len(file))
|
|
self.fd.send(b)
|
|
self.fd.send(file)
|
|
# response
|
|
buf = self.fd.recv(5)
|
|
(c,l) = unpack(">Bi", buf)
|
|
if c != (RAP_REPLY|RAP_OPEN):
|
|
print "rmt-open: Invalid response packet 0x%02x"%c
|
|
return l
|
|
|
|
def read(self, count):
|
|
b = pack(">Bi", RAP_READ, count) #len(buf))
|
|
self.fd.send(b)
|
|
# response
|
|
buf = self.fd.recv(5)
|
|
(c,l) = unpack(">Bi", buf)
|
|
buf = self.fd.recv(l)
|
|
return buf
|
|
|
|
# TODO: not tested
|
|
def write(self, buf):
|
|
#self.fd.send(buf)
|
|
b = pack(">Bi", RAP_WRITE, len(buf))
|
|
self.fd.send(b+buf)
|
|
# response
|
|
buf = self.fd.recv(5)
|
|
(c,l) = unpack(">Bi", buf)
|
|
if c != (RAP_REPLY|RAP_WRITE):
|
|
print "rmt-write: Invalid response packet 0x%02x"%c
|
|
|
|
def lseek(self, type, addr):
|
|
# WTF BBQ?
|
|
buf = pack(">BBQ", RAP_SEEK, type, addr)
|
|
self.fd.send(buf)
|
|
# read response
|
|
buf = self.fd.recv(5) # XXX READ 5!?!?!? shouldnt be 9 ?!?!? WTF
|
|
(c,l) = unpack(">Bi", buf)
|
|
#print "Lseek : %d"%l
|
|
return l
|
|
|
|
def close(self, fd):
|
|
buf = pack(">Bi", RAP_CLOSE, fd)
|
|
self.fd.send(buf)
|
|
# read response
|
|
buf = self.fd.recv(5)
|
|
(c,l) = unpack(">Bi", buf)
|
|
if c != RAP_REPLY | RAP_CLOSE:
|
|
print "rmt-close: Invalid response packet"
|
|
|
|
def cmd(self, cmd):
|
|
buf = pack(">Bi", RAP_CMD, len(str(cmd)))
|
|
self.fd.send(buf + cmd)
|
|
# read response
|
|
buf = self.fd.recv(5)
|
|
(c,l) = unpack(">Bi", buf)
|
|
if c != RAP_CMD | RAP_REPLY:
|
|
print "rmt-cmd: Invalid response packet"
|
|
return ""
|
|
buf = self.fd.recv(l)
|
|
return buf
|
|
|
|
def system(self, cmd):
|
|
buf = pack(">Bi", RAP_SYSTEM, len(str(cmd)))
|
|
self.fd.send(buf)
|
|
self.fd.send(cmd)
|
|
# read response
|
|
buf = self.fd.recv(5)
|
|
(c,l) = unpack(">Bi", buf)
|
|
if c != RAP_SYSTEM | RAP_REPLY:
|
|
print "rmt-system: Invalid response packet"
|
|
return ""
|
|
if l>0:
|
|
buf = self.fd.recv(l)
|
|
return buf
|