From 6cd8912ebb1c85775198cd2f11efda898e258cf3 Mon Sep 17 00:00:00 2001 From: Mathieu Tarral Date: Mon, 19 Jun 2017 16:56:33 +0300 Subject: [PATCH 1/3] refactored ARG_SIZE in backends/arguments.py --- nitro/backends/arguments.py | 8 +++++++- nitro/backends/windows/arguments.py | 8 ++------ 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/nitro/backends/arguments.py b/nitro/backends/arguments.py index c1b8a76..622cf14 100644 --- a/nitro/backends/arguments.py +++ b/nitro/backends/arguments.py @@ -1,5 +1,5 @@ from enum import Enum - +from nitro.event import SyscallType class SyscallArgumentType(Enum): register = 0 @@ -7,6 +7,12 @@ class SyscallArgumentType(Enum): class ArgumentMap: + + ARG_SIZE = { + SyscallType.syscall: 'P', # x64 -> 8 bytes + SyscallType.sysenter: 'I' # x32 -> 4 bytes + } + __slots__ = ( "event", "name", diff --git a/nitro/backends/windows/arguments.py b/nitro/backends/windows/arguments.py index b1c9252..e13cc11 100644 --- a/nitro/backends/windows/arguments.py +++ b/nitro/backends/windows/arguments.py @@ -3,6 +3,7 @@ from nitro.event import SyscallType from nitro.backends.arguments import ArgumentMap, SyscallArgumentType + class WindowsArgumentMap(ArgumentMap): CONVENTION = { @@ -15,15 +16,10 @@ class WindowsArgumentMap(ArgumentMap): ], } - ARG_SIZE = { - SyscallType.syscall: 'P', # x64 -> 8 bytes - SyscallType.sysenter: 'I' # x32 -> 4 bytes - } - __slots__ = ( "arg_size_format", ) - + def __init__(self, event, name, process): super().__init__(event, name, process) self.arg_size_format = self.ARG_SIZE[self.event.type] From 762388914512e2971f4090518f36644afbb850e3 Mon Sep 17 00:00:00 2001 From: Mathieu Tarral Date: Tue, 20 Jun 2017 11:56:04 +0300 Subject: [PATCH 2/3] refactored arguments --- nitro/backends/arguments.py | 26 +++++++++++++++++++++++++- nitro/backends/windows/arguments.py | 28 +++++----------------------- 2 files changed, 30 insertions(+), 24 deletions(-) diff --git a/nitro/backends/arguments.py b/nitro/backends/arguments.py index 622cf14..bdc6731 100644 --- a/nitro/backends/arguments.py +++ b/nitro/backends/arguments.py @@ -1,3 +1,5 @@ +import struct + from enum import Enum from nitro.event import SyscallType @@ -17,7 +19,8 @@ class ArgumentMap: "event", "name", "process", - "modified" + "modified", + "arg_size_format" ) def __init__(self, event, name, process): @@ -25,3 +28,24 @@ def __init__(self, event, name, process): self.name = name self.process = process self.modified = {} + self.arg_size_format = self.ARG_SIZE[self.event.type] + + def get_argument_value(self, arg_type, opaque): + if arg_type == SyscallArgumentType.register: + value = self.event.get_register(opaque) + else: + # memory + size = struct.calcsize(self.arg_size_format) + addr = self.event.regs.rsp + (opaque * size) + value, *rest = struct.unpack(self.arg_size_format, self.process.read_memory(addr, size)) + return value + + def set_argument_value(self, arg_type, opaque, value): + if arg_type == SyscallArgumentType.register: + self.event.update_register(opaque, value) + else: + # memory + size = struct.calcsize(self.arg_size_format) + addr = self.event.regs.rsp + (opaque * size) + buffer = struct.pack(self.arg_size_format, value) + self.process.write_memory(addr, buffer) diff --git a/nitro/backends/windows/arguments.py b/nitro/backends/windows/arguments.py index e13cc11..5c0827d 100644 --- a/nitro/backends/windows/arguments.py +++ b/nitro/backends/windows/arguments.py @@ -16,30 +16,19 @@ class WindowsArgumentMap(ArgumentMap): ], } - __slots__ = ( - "arg_size_format", - ) - def __init__(self, event, name, process): super().__init__(event, name, process) - self.arg_size_format = self.ARG_SIZE[self.event.type] def __getitem__(self, index): try: arg_type, opaque = self.CONVENTION[self.event.type][index] except KeyError as error: - raise RuntimeError('Unknown covention') from error + raise RuntimeError('Unknown convention') from error except IndexError: arg_type, opaque = self.CONVENTION[self.event.type][-1] opaque += index - len(self.CONVENTION[self.event.type]) + 1 - if arg_type == SyscallArgumentType.register: - value = self.event.get_register(opaque) - else: - # memory - size = struct.calcsize(self.arg_size_format) - addr = self.event.regs.rsp + (opaque * size) - value, *rest = struct.unpack(self.arg_size_format, self.process.read_memory(addr, size)) - return value + + return self.get_argument_value(arg_type, opaque) def __setitem__(self, index, value): try: @@ -49,13 +38,6 @@ def __setitem__(self, index, value): except IndexError: arg_type, opaque = self.CONVENTION[self.event.type][-1] opaque += index - len(self.CONVENTION[self.event.type]) + 1 - if arg_type == SyscallArgumentType.register: - self.event.update_register(opaque, value) - else: - # memory - size = struct.calcsize(self.arg_size_format) - addr = self.event.regs.rsp + (opaque * size) - buffer = struct.pack(self.arg_size_format, value) - self.process.write_memory(addr, buffer) - self.modified[index] = value + self.set_argument_value(arg_type, opaque, value) + self.modified[index] = value From 33295168769e1346ffdfb56a7e58067947e86b40 Mon Sep 17 00:00:00 2001 From: Mathieu Tarral Date: Tue, 20 Jun 2017 11:56:17 +0300 Subject: [PATCH 3/3] implement Linux ArgumentMap --- nitro/backends/linux/arguments.py | 47 +++++++++++++++++++++++++++++-- 1 file changed, 44 insertions(+), 3 deletions(-) diff --git a/nitro/backends/linux/arguments.py b/nitro/backends/linux/arguments.py index a1834d2..f4b0101 100644 --- a/nitro/backends/linux/arguments.py +++ b/nitro/backends/linux/arguments.py @@ -1,8 +1,49 @@ -from nitro.backends.arguments import ArgumentMap +import struct + +from nitro.event import SyscallType +from nitro.backends.arguments import ArgumentMap, SyscallArgumentType class LinuxArgumentMap(ArgumentMap): + + CONVENTION = { + SyscallType.syscall: [ + (SyscallArgumentType.register, 'rdi'), + (SyscallArgumentType.register, 'rsi'), + (SyscallArgumentType.register, 'rdx'), + (SyscallArgumentType.register, 'r10'), + (SyscallArgumentType.register, 'r9'), + (SyscallArgumentType.register, 'r8'), + ], + SyscallType.sysenter: [ + (SyscallArgumentType.register, 'rbx'), + (SyscallArgumentType.register, 'rcx'), + (SyscallArgumentType.register, 'rdx'), + (SyscallArgumentType.register, 'rsi'), + (SyscallArgumentType.register, 'rdi'), + (SyscallArgumentType.register, 'rbp'), + ], + } + def __getitem__(self, index): - raise NotImplementedError() + try: + arg_type, opaque = self.CONVENTION[self.event.type][index] + except KeyError as error: + raise RuntimeError('Unknown convention') from error + except IndexError: + raise RuntimeError('Invalid argument index: Linux syscalls are ' + 'limited to 6 parameters') + + return self.get_argument_value(arg_type, opaque) + def __setitem__(self, index, value): - raise NotImplementedError() + try: + arg_type, opaque = self.CONVENTION[self.event.type][index] + except KeyError as error: + raise RuntimeError('Unknown convention') from error + except IndexError: + raise RuntimeError('Invalid argument index: Linux syscalls are ' + 'limited to 6 parameters') + + self.set_argument_value(arg_type, opaque, value) + self.modified[index] = value \ No newline at end of file