hackedteam/test-av2

View on GitHub
AVAgent/rcs_client.py

Summary

Maintainability
F
1 wk
Test Coverage
import urllib2
from urllib2 import HTTPError
import cookielib
import json
import traceback
from time import sleep
from StringIO import StringIO
import gzip

import os
import sys
import inspect

#pp = pprint.PrettyPrinter(indent=4)
if ".." not in sys.path:
    sys.path.insert(0, "..")

from AVCommon.logger import logging

class Rcs_client:
    myid = "0"

    def __init__(self, host, user="avtest", passwd="avtest"):
        self.host = host
        self.user = user
        self.passwd = passwd

        if 'logging' not in globals():
            from AVCommon.logger import logging
            globals()['logging']=logging
        #self.cookie = self.do_login

    def _get_response(self, link, cookies=None):
        """ Basic HTTP Request/Response with Cookie
        @param link
        @param cookie
        @returns response page
        """
        try:
            #print "calling link: %s" % link
            req = urllib2.Request(link)
            req.add_header('Accept-encoding', 'gzip')

            if cookies:
                opener = urllib2.build_opener(
                    urllib2.HTTPCookieProcessor(cookies))
            response = opener.open(req)

            if response.info().get('Content-Encoding') == 'gzip':
                buf = StringIO( response.read())
                f = gzip.GzipFile(fileobj=buf)
                data = f.read()
            else:
                data = response.read()

            sleep(1)
            return data
        except HTTPError as e:
            logging.error("ERROR: processing %s: %s, %s" % (link, e, e.read()))
            raise e

    def _post_response(self, link, cj, data=None):
        """ Basic POST Request / Response
        @param link
        @param data
        @param cookie
        @returns response page
        """
        try:
            opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cj),
                                          urllib2.HTTPHandler())
            req = urllib2.Request(link, data)
            resp = opener.open(req).read()
            sleep(1)
            return resp
        except HTTPError as e:
            logging.error("ERROR: processing %s: %s, %s" % (link, e, e.read()))
            raise e

    def _call_post(self, api_name, data={}, binary=False, argjson=True):
        link = 'https://%s/%s' % (self.host, api_name)
        logging.debug("_call: %s" % link)
        #logging.debug("binary %s, argjson %s" % (binary, argjson))
        arg = data
        if argjson:
            arg = json.dumps(data)

        resp = self._post_response(link, self.cookie, arg)
        if binary:
            return resp

        try:
            result = json.loads(resp)
            return result
        except Exception, e:
            logging.error("ERROR: %s" % e)
            logging.debug("DBG trace %s" % traceback.format_exc())
            logging.debug("call error: %s" % resp)
            raise e

    def _call_get(self, api_name):
        link = 'https://%s/%s' % (self.host, api_name)
        #logging.debug("_call_get: %s" % link)
        resp = self._get_response(link, self.cookie)
        result = json.loads(resp)
        return result

    def login(self):
        """ Do Login request to catch cookie
        @param link: url to login page
        @param data: post data
        @returns cookie
        """
        login = {'user': self.user,
                 'pass': self.passwd,
                 'version': 2013031101}

        link = "https://%s/auth/login" % self.host
        data = json.dumps(login)
        cj = cookielib.CookieJar()
        resp = self._post_response(link, cj, data)
        result = json.loads(resp)
        # logging.debug(result)
        self.myid = result['user']['_id']
        # logging.debug("my id = %s" % self.myid)

        self.cookie = cj
        return cj


    def logged_in(self):
        return self.cookie is not None

    def logout(self):
        """ Logout for session
        @param session cookie
        @return True/False
        """
        self._call_post('auth/logout')
        return True

    def server_status(self):
        status = self._call_get('status/counters')
        return status

    def disable_analysis(self):
        ret = self._call_post('agent/disable_analysis')
        return ret

    def operation(self, operation):
        """ gets the operation id of an operation """
        operations = self._call_get('operation')
        #logging.debug("DBG operation: %s" % operations)
        ret = [(op['_id'], op['group_ids'][0])
               for op in operations if op['name'] == operation]
        return ret[0] if ret else (None, None)

    def targets(self, operation_id, target=None):
        """ gets the targets id of an operation, matching the target name """
        targets = self._call_get('target')
        #logging.debug("targets: %s" % targets)
        #pp = pprint.PrettyPrinter(indent=4)
        # pp.pprint(targets)
        if target:
            ret = [op['_id']
                   for op in targets if op['name'] == target and op['path'][0] == operation_id]
        else:
            ret = [op['_id']
                   for op in targets if op['path'][0] == operation_id]
        return ret

    def all_factories(self):
        """ gets the factories """
        factories = self._call_get('factory')

        # pp.pprint(factories)
        ret = [(op['_id'], op['ident'], op['path'])
               for op in factories]
        return ret

    def factories(self, target_id, all_factories=None):
        """ gets the factories of an operation, matching the target id """
        if not all_factories:
            all_factories = self.all_factories()

        # pp.pprint(factories)
        ret = [(op[0], op[1])
               for op in all_factories if target_id in op[2]]
        return ret

    def instances(self, ident):
        """ gets the instances id of an operation, matching the ident """
        agents = self._call_get('agent')
        # instances: [{u'status': u'open', u'scout': False, u'good': True, u'name': u'avtagent_desktop_windows_elite_silent (1)', u'platform': u'windows', u'demo': False, u'_kind': u'agent', u'stat': {u'grid_size': 183088, u'last_sync': 1386874247, u'source': u'172.20.20.151', u'user': u'avtest', u'device': u'AVTAGENT', u'last_sync_status': 0, u'size': 34599}, u'upgradable': False, u'instance': u'7f198461c7ce800381480345cc5d8617b3015c89', u'ident': u'RCS_0000057058', u'version': 2013103102, u'path': [u'51224a314e091305b800005d', u'52a895cc4e0913f2e600b406'], u'_id': u'52aa04d14e0913a56300c604', u'type': u'desktop', u'desc': u'made by vmavtestat at Thu Dec 12 19:46:32 2013'}]
        # pp.pprint(agents)
        ret = [op['_id'] for op in agents if ident in op['ident'] and op['_kind'] == 'agent']
        return ret

    def instances_by_target_id(self, target_id):
        """ gets the instances id of an operation, matching the ident """
        logging.debug("lookin for instances with target: %s" % target_id)
        agents = self._call_get('agent')
        #logging.debug("agents: %s" % agents)
        #pp.pprint(agents)
        ret = [op for op in agents if target_id in op['path'] and op['_kind'] == 'agent']
        return ret

    def instances_by_name(self, name):
        """ gets the instances id of an operation, matching the ident """
        logging.debug("looking for instances with target: %s" % name)
        agents = self._call_get('agent')
        #logging.debug("agents: %s" % agents)
        #pp.pprint(agents)
        ret = [op for op in agents if name in op['name'] and op['_kind'] == 'agent']
        return ret

    def instances_by_deviceid(self, deviceid, target_id):
        """ gets the instances id of an operation, matching the ident """
        logging.debug("lookin for instances with deviceid: %s" % deviceid)
        agents = self._call_get('agent')

        ret = [op for op in agents
               if 'stat' in op and 'device' in op['stat'] and deviceid in op['stat']['device']
               and op['_kind'] == 'agent' and target_id in op['path']]
        return ret

    def agents(self, target_id):
        """ gets the agents (agents and factories) of an operation, matching the target id """
        agents = self._call_get('agent')
        # pp.pprint(agents)
        ret = [(op['_id'], op['ident'], op['name'])
               for op in agents if target_id in op['path']]
        return ret

    # user list : verifica presenza utente
    # add group to user
    def user_create(self, name, password, privs, group_id):
        """ Create a user """
        logging.debug("user_create: %s, %s, %s" % (name, password, group_id))
        try:
            data = {'name': name, 'pass': password, 'group_ids':
                [group_id], 'privs': privs, 'enabled': True}
            user = self._call_post('user/create', data)
            return user['_id']
            # return True
        except HTTPError as e:
            if e.code == 409:
                return True
            logging.error(e)
            return False

    def target_delete(self, target_id):
        """ Delete a given target """
        return self._call_post('target/destroy', {'_id': target_id})

    def target_create(self, operation_id, name, desc):
        """ Create a given target """
        data = {'name': name, 'desc': desc, 'operation': operation_id}
        target = self._call_post('target/create', data)
        return target['_id']

    def factory_create(self, operation_id, target_id, ftype, name, desc):
        """ Create a factory """
        data = {'name': name, 'desc': desc, 'operation':
            operation_id, 'target': target_id, 'type': ftype}
        factory = self._call_post('agent/create', data)
        return factory['_id'], factory['ident']

    def factory_add_config(self, factory_id, config):
        """ adds a config to a factory """
        data = {'_id': factory_id, 'config': config}
        return self._call_post('agent/add_config', data)

    def update_conf(self, conf_file, factory):
        """ Update sync configuration
        @param configuration file
        @param factory id
        @return True/False
        """
        try:
            base = 'https://%s' % self.host

            faclink = '%s/factory' % base
            resp = self._get_response(faclink, self.cookie)
            facts = json.loads(resp)
            for fact in facts:
                if fact["ident"] == factory:
                    fct = fact
                    break
            if not fct:
                return False
                # logging.debug(fct)
            addlink = '%s/agent/add_config' % base
            f = open(conf_file, 'r')
            cnf = f.read()
            data = {'_id': fct["_id"], 'config': cnf}
            # logging.debug(data)
            resp = self._post_response(addlink, self.cookie, json.dumps(data))

            return True
        except Exception as e:
            logging.debug("DBG trace %s" % traceback.format_exc())
            logging.error(e)
            return False

    def instance_upgrade(self, instance_id, force_soldier = False):
        params = {'_id': instance_id}
        if force_soldier:
            params["force"] = "soldier"
        logging.debug("upgrade: %s" % params)
        try:
            self._call_post('agent/upgrade', params)
            return True
        except:
            return False

    def instance_can_upgrade(self, instance_id):
        try:
            value = self._call_get('agent/can_upgrade/%s' % instance_id)
            return value
        except HTTPError, ex:
            logging.error("cannot get can_upgrade")
            return "Error%s" % ex.code
        except Exception, ex:
            logging.exception("cannot get can_upgrade")
            return "error"

    def instance_level(self, instance_id):
        params = {'_id': instance_id}
        try:
            info = self.instance_info(instance_id)
            logging.debug("info: %s" %(info))
            return info["level"]
        except:
            return False

    def instance_info(self, instance_id):
        agents = self._call_get('agent')
        # pp.pprint(agents)

        ret = [op for op in agents if op['_id'] == instance_id]
        return ret[0] if ret else None

    def instance_close(self, instance_id):
        params = {'_id': instance_id, 'status': 'closed'}
        self._call_post('agent/update', params)

    def instance_rename(self, instance_id, name):
        params = {'_id': instance_id, 'name': name}
        self._call_post('agent/update', params)

    def instance_delete(self, instance_id):
        """ Delete a given instance
        @param instance
        """
        data = {'_id': instance_id, 'permanent': True}
        return self._call_post('agent/destroy', data)
        # logging.debug(resp)

    def blacklist(self):
        return self._call_post('agent/blacklist')

    def evidences_by_instance(self, instance_id, filter_type=None, filter_value=None):
        logging.debug("evidences_by_instance: %s,%s,%s" %( instance_id, filter_type, filter_value))
        if filter_type and filter_value:
            f = {filter_type: filter_value, "agent": instance_id, 'date':'dr'}

        else:
            f = { "agent": instance_id, 'date':'dr'}

        filter = urllib2.quote(json.dumps(f))
        link = 'https://%s/evidence?filter=%s' % (self.host, filter)

        resp = self._get_response(link, self.cookie)
        result = json.loads(resp)
        logging.debug("results: " % result)
        return result

    def evidences(self, target_id, instance_id, filter_type=None, filter_value=None):
        """ Get evidences of given agent and target
        @param target
        @param agent
        @param type (if None all types should be returned)

        date: '24h' 'week' 'month' 'now'
        dr e da sono per il :date
        gli altri sono per il :from :to
        dr -> date received, da -> date acquired

        """
        logging.debug("evidences: %s,%s,%s,%s" %(target_id, instance_id, filter_type, filter_value))
        if filter_type and filter_value:
            f = {filter_type: filter_value, "target": target_id, "agent": instance_id, 'date':'dr'}

        else:
            f = {"target": target_id, "agent": instance_id, 'date':'dr'}

        filter = urllib2.quote(json.dumps(f))
        link = 'https://%s/evidence?filter=%s' % (self.host, filter)

        resp = self._get_response(link, self.cookie)
        result = json.loads(resp)
        logging.debug("results: " % result)
        return result

    def infos(self, target_id, instance_id, filter_type=None, filter_value=None):
        """ Get info of given agent and target
        @param target
        @param agent
        @param type (if None all types should be returned)

        date: '24h' 'week' 'month' 'now'
        dr e da sono per il :date
        gli altri sono per il :from :to
        dr -> date received, da -> date acquired

        """
        logging.debug("info: %s,%s,%s,%s" %(target_id, instance_id, filter_type, filter_value))
        if filter_type and filter_value:
            f = {filter_type: filter_value, "target": target_id, "agent": instance_id, 'date':'dr'}
        else:
            f = {"target": target_id, "agent": instance_id, 'date':'dr'}

        filter = urllib2.quote(json.dumps(f))
        link = 'https://%s/evidence/info?filter=%s' % (self.host, filter)

        resp = self._get_response(link, self.cookie)
        result = json.loads(resp)
        logging.debug("results: " % result)
        return result

    def build(self, factory, params, out_file):
        """ Build Silent Exe
        @param param_file
        @param factory
        @param out_file
        """

        params['factory'] = {"_id": "%s" % factory}
        # logging.debug("+ Build params: \n%s" % params)

        resp = self._call_post('build', params, binary=True)

        out = open(out_file, 'wb')
        out.write(resp)

        # logging.debug("+ %s bytes saved to %s" % (len(out),  out_file))

    def build_melt(self, factory, params, melt_file, out_file):
        """ Build Melted Exe
        @param param_file
        @param factory
        @param out_file
        """

        params['factory'] = {"_id": "%s" % factory}

        f = open(melt_file, "rb")
        payload = f.read()
        logging.debug("DBG payload size: %s file:  %s" % ( len(payload), melt_file))
        melt_id = self._call_post('upload', payload, binary=True, argjson=False)
        logging.debug("DBG uploaded:  %s" % melt_id)

        params['melt']['input'] = melt_id
        #:  Build: melting: {"admin"=>false, "bit64"=>true, "codec"=>true, "scout"=>true, "input"=>"4f60909baef1de0e4800000a-1361192221.897401094"}

        logging.debug("DBG Build melt params: \n%s" % params)
        #link  = 'https://%s/build' % self.host
        #resp = self.post_response(link, json.dumps(params))
        resp = self._call_post('build', params, binary=True)

        out = open(out_file, 'wb')
        out.write(resp)


if __name__ == "__main__":

    host = "rcs-minotauro"
    user = "avmonitor"
    passwd = "avmonitorp123"
    operation = 'AVMonitor'
    rcs=[]

    conn = Rcs_client(host, user, passwd)
    conn.login()

    try:
        #instance_id = "52efa51d4e0913760f000138"
        ret = conn.blacklist()
        print ret.encode('utf-8')
        logging.debug("ret: %s" % ret)
    finally:
        conn.logout()