Module pandare.extras.modeFilter

Simple helper and example to selectively execute callbacks based on a mode string

Expand source code
#!/usr/bin/env python3
'''
Simple helper and example to selectively execute callbacks based on a mode string
'''

from functools import wraps

class ModeFilter:
    '''
    Simple, inheritable class to provide a decorator to enable/disable callbacks
    depending on self.mode value.

    It is ill-advised to use on callbacks with high-performance impacts such as
    before_block_exec as this is a pure-Python plugin.

    Example:
        from pandare import Panda
        from pandare.extras import ModeFilter

        class MyClass(ModeFilter):
            def __init__(self, panda)
                self.panda = panda
                self.set_mode("mode1")

                @self.mode_filter("mode1")
                @self.panda.ppp("syscalls2", "on_sys_open_enter")
                def on_open(cpu, pc, fname_ptr, flags, mode):
                    # assert(self.mode == "mode1") # Note decorator ensures this
                    self.set_mode("mode2") # Change mode - so this callback won't run again
            ...
            def run(self):
                self.panda.run()

        p = panda(...)
        mc = MyClass(panda)
        mc.run()
    '''
    mode = "start"

    def mode_filter(self, mode_filter):
        '''
        Decorator to only run a function if self.mode matches the provided string
        '''
        def __mode_filter(func):
            @wraps(func)
            def wrapper(*args, **kwargs):
                if self.mode == mode_filter:
                    # Mode matches - run it!
                    func(*args, **kwargs)
            return wrapper
        return __mode_filter

    def set_mode(self, new):
        '''
        Helper to change mode
        '''
        if new != self.mode:
            print(f"Switching modes from {self.mode} to {new}")
        self.mode = new


class Tester(ModeFilter):
    '''
    Test class to drive a guest running a few commands
    while using mode filters for syscalls analyses
    '''
    def __init__(self, panda_obj):
        self.panda = panda_obj

        # PANDA decorators defined in init
        @self.panda.queue_async
        def driver():
            self.panda.revert_sync("root")
            self.set_mode("mode1")

            for cmd in ["head -n1 /etc/passwd", "whoami", "head -n1 /proc/cpuinfo"]:
                print(f"Starting: '{cmd}'")
                res = self.panda.run_serial_cmd(cmd)
                print(f"\tResult: {res}")

            assert self.mode == "end" # Should be set by on_open2
            self.panda.end_analysis()


        @self.panda.ppp("syscalls2", "on_sys_open_enter")
        @self.mode_filter("mode1")
        def on_open1(cpu, pc, fname_ptr, flags, mode):
            assert self.mode == "mode1"
            try:
                fname = self.panda.read_str(cpu, fname_ptr)
            except ValueError:
                return

            if fname == "/etc/passwd":
                print("Saw PASSWD - switch modes")
                self.set_mode("mode2")

        @self.panda.ppp("syscalls2", "on_sys_open_enter")
        @self.mode_filter("mode2")
        def on_open2(cpu, pc, fname_ptr, flags, mode):
            assert self.mode == "mode2"

            try:
                fname = self.panda.read_str(cpu, fname_ptr)
            except ValueError:
                return

            if fname == "/proc/cpuinfo":
                print("SAW CPUINFO - switch modes")
                self.set_mode("end")
        # End PANDA-decorated functions in init

    def run_guest(self):
        '''
        Run guest
        '''
        self.panda.run()

if __name__ == "__main__":
    from pandare import Panda
    # Note the test is architecture-specific, otherwise different syscalls are issued
    panda = Panda(generic="i386")
    test = Tester(panda)
    test.run_guest()

Classes

class ModeFilter

Simple, inheritable class to provide a decorator to enable/disable callbacks depending on self.mode value.

It is ill-advised to use on callbacks with high-performance impacts such as before_block_exec as this is a pure-Python plugin.

Example

from pandare import Panda from pandare.extras import ModeFilter

class MyClass(ModeFilter): def init(self, panda) self.panda = panda self.set_mode("mode1")

    @self.mode_filter("mode1")
    @self.panda.ppp("syscalls2", "on_sys_open_enter")
    def on_open(cpu, pc, fname_ptr, flags, mode):
        # assert(self.mode == "mode1") # Note decorator ensures this
        self.set_mode("mode2") # Change mode - so this callback won't run again
...
def run(self):
    self.panda.run()

p = panda(…) mc = MyClass(panda) mc.run()

Expand source code
class ModeFilter:
    '''
    Simple, inheritable class to provide a decorator to enable/disable callbacks
    depending on self.mode value.

    It is ill-advised to use on callbacks with high-performance impacts such as
    before_block_exec as this is a pure-Python plugin.

    Example:
        from pandare import Panda
        from pandare.extras import ModeFilter

        class MyClass(ModeFilter):
            def __init__(self, panda)
                self.panda = panda
                self.set_mode("mode1")

                @self.mode_filter("mode1")
                @self.panda.ppp("syscalls2", "on_sys_open_enter")
                def on_open(cpu, pc, fname_ptr, flags, mode):
                    # assert(self.mode == "mode1") # Note decorator ensures this
                    self.set_mode("mode2") # Change mode - so this callback won't run again
            ...
            def run(self):
                self.panda.run()

        p = panda(...)
        mc = MyClass(panda)
        mc.run()
    '''
    mode = "start"

    def mode_filter(self, mode_filter):
        '''
        Decorator to only run a function if self.mode matches the provided string
        '''
        def __mode_filter(func):
            @wraps(func)
            def wrapper(*args, **kwargs):
                if self.mode == mode_filter:
                    # Mode matches - run it!
                    func(*args, **kwargs)
            return wrapper
        return __mode_filter

    def set_mode(self, new):
        '''
        Helper to change mode
        '''
        if new != self.mode:
            print(f"Switching modes from {self.mode} to {new}")
        self.mode = new

Subclasses

Class variables

var mode

Methods

def mode_filter(self, mode_filter)

Decorator to only run a function if self.mode matches the provided string

Expand source code
def mode_filter(self, mode_filter):
    '''
    Decorator to only run a function if self.mode matches the provided string
    '''
    def __mode_filter(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            if self.mode == mode_filter:
                # Mode matches - run it!
                func(*args, **kwargs)
        return wrapper
    return __mode_filter
def set_mode(self, new)

Helper to change mode

Expand source code
def set_mode(self, new):
    '''
    Helper to change mode
    '''
    if new != self.mode:
        print(f"Switching modes from {self.mode} to {new}")
    self.mode = new
class Tester (panda_obj)

Test class to drive a guest running a few commands while using mode filters for syscalls analyses

Expand source code
class Tester(ModeFilter):
    '''
    Test class to drive a guest running a few commands
    while using mode filters for syscalls analyses
    '''
    def __init__(self, panda_obj):
        self.panda = panda_obj

        # PANDA decorators defined in init
        @self.panda.queue_async
        def driver():
            self.panda.revert_sync("root")
            self.set_mode("mode1")

            for cmd in ["head -n1 /etc/passwd", "whoami", "head -n1 /proc/cpuinfo"]:
                print(f"Starting: '{cmd}'")
                res = self.panda.run_serial_cmd(cmd)
                print(f"\tResult: {res}")

            assert self.mode == "end" # Should be set by on_open2
            self.panda.end_analysis()


        @self.panda.ppp("syscalls2", "on_sys_open_enter")
        @self.mode_filter("mode1")
        def on_open1(cpu, pc, fname_ptr, flags, mode):
            assert self.mode == "mode1"
            try:
                fname = self.panda.read_str(cpu, fname_ptr)
            except ValueError:
                return

            if fname == "/etc/passwd":
                print("Saw PASSWD - switch modes")
                self.set_mode("mode2")

        @self.panda.ppp("syscalls2", "on_sys_open_enter")
        @self.mode_filter("mode2")
        def on_open2(cpu, pc, fname_ptr, flags, mode):
            assert self.mode == "mode2"

            try:
                fname = self.panda.read_str(cpu, fname_ptr)
            except ValueError:
                return

            if fname == "/proc/cpuinfo":
                print("SAW CPUINFO - switch modes")
                self.set_mode("end")
        # End PANDA-decorated functions in init

    def run_guest(self):
        '''
        Run guest
        '''
        self.panda.run()

Ancestors

Methods

def run_guest(self)

Run guest

Expand source code
def run_guest(self):
    '''
    Run guest
    '''
    self.panda.run()

Inherited members