Android渗透工具之Drozer源码分析


       最近时间比较充足,想找点事情来做做。再说Drozer这工具整天在手头用得着,只知其玄乎,又听大B哥说其架构是如何的NB。所以,就趁着这份热尽,体会了Drozer的神乎。确实挺神乎的,本人小菜一枚,求各位大神轻虐,在此放过了;如有想体会Drozer的神乎的朋友,在这抛砖引玉,不求感激,只求不坑了各位,哈哈、、、、

1.    Drozer简介

       Drozer是一个由MWR安全团队维护开源的软件,该软件可以说是针对Android平台的安全测试框架。安全人员可以通过Drozer自身提供的一些module完成一些基础的安全测试功能,同时也可以根据需求实现自己的module,甚至可以在利用Drozer提供的框架实现一些自动化审计功能。于目标设备上安装Agent,可以通过Agent接收PC端传来的指令或者代码并与Dalvik VM,其他app以及操作系统进行交互以达到某些安全审计功能。关于Drozer的源码可以从Githubhttps://github.com/mwrlabs)上获取:

drozer: 包含了控制台与服务端代码;

drozer-agent: 包含了运行于Android设备的Agent代码;

jdiesel:反射和通信协议的核心jar工程;

mwr-tls:安全通信jar工程;

mwr-android: 移动端界面jar工程;

2.    Drozer通信协议

       DrozerAgent之间的通信采用google protocol buffer协议,这种协议是一种轻便高效的结构化数据存储格式,可以用于结构化数据串行化,很适合做数据存储或 RPC 数据交换格式。它可用于通讯协议、数据存储等领域的语言无关、平台无关、可扩展的序列化结构数据格式。目前提供了 C++JavaPython 三种语言的 API。完整协议可以参见githubhttps://github.com/mwrlabs/mercury-common/blob/master/protobuf.proto)上的源码,该协议是两者协作的核心。

下面是对这个协议的简单介绍:

该协议中包含4种消息类型,其中包括SYSTEM_REQUESTSYSTEM_RESPONSEREFLECTION_REQUESTREFLECTION_RESPONSE

message Message {
         enum MessageType {
                   SYSTEM_REQUEST= 1;
                   SYSTEM_RESPONSE= 2;
                   REFLECTION_REQUEST= 3;
                   REFLECTION_RESPONSE= 4;
         }
   }

SystemRequest:包含设备信息,会话信息,连接控制

message SystemRequest {
                   enum RequestType {
                            PING= 1;
                            BIND_DEVICE= 2;
                            UNBIND_DEVICE= 3;
                            LIST_DEVICES= 4;
                            START_SESSION= 5;
                            STOP_SESSION= 6;
                            RESTART_SESSION= 7;
                            LIST_SESSIONS= 8;
                       }
                   required RequestType type = 1 [default = PING];
                   optional Device device = 5;
                   optional string session_id = 7;
                   optional string password = 8;
     }

SystemResponse:主要包括响应的类型(绑定服务,设备列表,会话列表等)状态信息

message SystemResponse {
                   enum ResponseType {
                            PONG= 1;
                            BOUND= 2;
                            UNBOUND= 3;
                            DEVICE_LIST= 4;
                            SESSION_ID= 5;
                            SESSION_LIST= 6;
                   }

                   enum ResponseStatus {
                            SUCCESS= 1;
                            ERROR= 2;
                   }
                   required ResponseType type = 1;
                   required ResponseStatus status = 2;
                   repeated Device devices = 6;
                   optional string session_id = 7;
                   optional string error_message = 8;
                   repeated Session sessions = 9;
         }

ReflectionRequest:java反射请求,主要有Resolve(所反射的classname)Construct(对象引用ObjectReferenceint32类型),方法对象method,和方法参数Argument)Invoke调用方法(同样包括对象引用ObjectReferenceint32类型),方法对象method,和方法参数Argument),以及对Propertygetset,还有Delete(对象引用ObjectReferenceint32类型))

message ReflectionRequest {
                   enum RequestType {
                            RESOLVE= 1;
                            CONSTRUCT= 2;
                            INVOKE= 3;
                            SET_PROPERTY= 4;
                            GET_PROPERTY= 5;
                            DELETE= 6;
                            DELETE_ALL= 7;
                   }

                   required string session_id = 1;
                   required RequestType type = 2;

                   message Resolve {
                            optional string classname = 1;
                   }

                   message Construct {
                            optional ObjectReference object = 1;
                            repeated Argument argument = 2;
                   }

                   message Invoke {
                            optional ObjectReference object = 1;
                            optional string method = 2;
                            repeated Argument argument = 3;
                   }

                   message SetProperty {
                            optional ObjectReference object = 1;
                            optional string property = 2;
                            optional Argument value = 3;
                   }

                   message GetProperty {
                            optional ObjectReference object = 1;
                            optional string property = 2;
                   }

                   message Delete {
                            optional ObjectReference object = 1;
                   }

                   optional Resolve resolve = 3;
                   optional Construct construct = 4;
                   optional Invoke invoke = 5;
                   optional SetProperty set_property = 6;
                   optional GetProperty get_property = 7;
                   optional Delete delete = 8;
         }

ReflectionResponse:主要是反射响应后的状态和参数,还有一些错误信息

message ReflectionResponse {
                   enum ResponseStatus {
                            SUCCESS= 1;
                            ERROR= 2;
                            FATAL= 3;
                   }

                   required string session_id = 1;
                   required ResponseStatus status = 2;
                   optional Argument result = 3;
                   optional string errormessage = 8;
         }

3.    Drozer源码解析

        由于Drozer存在很多命令,在源码中会存在很多分支路径,本文不打算全部分析,主要侧重点在于我们常用的命令(连接Agent,运行模块)代码的分析,一般处理指令如下:

drozer console connect

run module_name argv

下面的内容就这两类命令的执行流程进行源码分析。

3.1 Drozer consoleconnect命令执行过程

     首先以drozer console connect为切入点。这条命令是Drozer端与Agent建立console会话。

Drozer端:

找到运行这条命令的入口点,入口点在drozer\cli\console.py

from mwr.common import logger
from drozer.console import Console
logger.setLevel(logging.DEBUG)
logger.addStreamHandler()

#实例化Console,并执行run(),这里取第3个及之后的参数,这里取的是connect

Console().run(sys.argv[2::])

在这个模块中,运行Console().run(sys.argv[2::])Console这个类在drozer\console\console.py,这个类继承cli.Basemwr\common\cli.py)。这个run()就在cli.Base这个类中实现,定位到cli.Base.run()

def run(self, argv=None):
        if argv == None:
            argv = []
        
        self.prepare_argument_parser(argv)
        # parse argv into arguments using the generated ArgumentParser
        #解析命令行参数

        arguments = self.parse_arguments(self._parser, argv)
       #根据命令行参数调用对应的方法
        try:

            self.__invokeCommand(arguments)
        except UsageError as e:
            self.__showUsage(e.message)
        except Exception as e:
            self.handle_error(e)

继续跟踪__invokeCommand():

def __invokeCommand(self, arguments):
   
        try:
            command = arguments.command

            if "do_" + command in dir(self):
                #调用do_xxx方法

                getattr(self, "do_" + command)(arguments)
            else:
                raise UsageError("unknown command: " + command)
        except IndexError:
            raise UsageError("incorrect usage")

run()最后调用__invokeCommand(),通过getattr()调用do_xxx(),由于传入的参数connect,这里执行Console类里的do_connect()

def do_connect(self, arguments):
        if arguments.password:
            with warnings.catch_warnings():
                warnings.simplefilter("ignore")

                password = getpass.getpass()
        else:
            password = None
        #获取与Drozer绑定的设备

        device = self.__get_device(arguments)
        #获取与Agent连接的socket
        server = self.__getServerConnector(arguments)
        #获取与Agent开始会话的响应
        response = server.startSession(device, password)
        
        if response.type == Message.SYSTEM_RESPONSE and\
            response.system_response.status == Message.SystemResponse.SUCCESS:
            session_id = response.system_response.session_id

            try:
                if(arguments.debug):
                    session = DebugSession(server, session_id, arguments)
                else:
                     #与Agent建立会话

                    session = Session(server, session_id, arguments)

                if len(arguments.file) > 0:
                    session.do_load(" ".join(arguments.file))
                    session.do_exit("")
                elif arguments.onecmd != None:
                    session.onecmd(arguments.onecmd)
                    session.do_exit("")
                else:
                    #进入控制台,等待命令输入并执行

                    session.cmdloop()
            except KeyboardInterrupt:
                print
                print "Caught SIGINT, terminating your session."
            finally:
                session.do_exit("")
                
            self.__getServerConnector(arguments).close()
        else:
            self.handle_error(RuntimeError(response.system_response.error_message), fatal=True)

这里主要是实现DrozerAgent建立Session,进入控制台,等待命令的输入并执行。

下面根据drozer console connect这条命令的流程重点分析SystemRequest、ReflectionRequest两类消息的执行过程:

SystemRequest消息执行过程

device = self.__get_device(arguments),这个方法获取与Drozer建立连接的设备。这里以这个分支详细分析SystemRequest消息的执行过程。定位到__get_device():

def __get_device(self, arguments):

        if arguments.device == None:
            #获取与Drozer建立连接的设备

            devices = self.__getServerConnector(arguments).listDevices().system_response.devices

            if len(devices) == 1:
                device = devices[0].id

                print "Selecting %s (%s %s %s)\n" % (devices[0].id, devices[0].manufacturer, devices[0].model, devices[0].software)

             ......
             ......
            return arguments.device

__getServerConnector()是为了得到与Agent建立连接的socket。实现代码如下:

def __getServerConnector(self, arguments):

        if self.__server == None:
            #实例化ServerConnector类

            self.__server = ServerConnector(arguments, self.__manage_trust)

        return self.__server

ServerConnector这个类在drozer\connector\server_connector.py,核心代码是调用父类SocketTransport__init__,从而获取与Agent31415端口建立的socket

class ServerConnector(SocketTransport):
    #连接的主机与端口

    DefaultHost = "127.0.0.1"
    DefaultPort = 31415

    
    def __init__(self, arguments, trust_callback=None):
        try:
             #调用SocketTransport.__init__,获取与Agent的31415端口建立的socket

            SocketTransport.__init__(self, arguments, trust_callback)
        ......
        ......

展开SocketTransport.__init__():

class SocketTransport(Transport):
    
    def __init__(self, arguments, trust_callback=None):
        Transport.__init__(self)
        #socket实例化

        self.__socket = socket.socket()
        
      ......
      ......

得到与agent建立连接的socket,接下来执行__getServerConnector(arguments).listDevices()定位到listDevices()

def listDevices(self):

        try:
            #向Agent发送LIST_DEVICES消息并接收响应

            return self.sendAndReceive(SystemRequestFactory.listDevices())
        except RuntimeError as e:
            if e.message == 'Received an empty response from the Agent. This normally means the remote service has crashed.':
                raise ConnectionError(e)
            else:
                raise

这个方法调用sendAndReceive(SystemRequestFactory.listDevices()),而sendAndReceive主要是发送一个messageagent,并获取返回结果,定位到sendAndReceive

def sendAndReceive(self, message):
         #为message加上一个id,然后将这个message封装为protocol buffer类型的Frame,最终发送给Agent

        message_id = self.send(message)

        while(True):
           #获取返回结果

            response = self.receive()

            if response == None:
                raise ConnectionError(RuntimeError('Received an empty response from the Agent.'))
            elif response.id == message_id:
                return response

展开send(message):

def send(self, message):
      
        try:
             #添加message id

            message_id = self.nextId()
            #封装为protocol buffer类对象
            frame = Frame.fromMessage(message.setId(message_id).build())
            #将消息发送给Agent
            self.__socket.sendall(str(frame))
    
            return message_id
      .....
      ......

我们再来看下此处message的细节。执行SystemRequestFactory.listDevices(),这个方法是为了获取与Drozer建立连接的Agent这样一个SystemRequest消息对象。定位到listDevices()

def listDevices(cls):
         #实例化SystemRequest类型的对象

        builder = SystemRequestFactory(Message.SystemRequest.LIST_DEVICES)

        return builder

到这里,SystemRequest消息在Drozer中执行完毕。接下来看Agent是如何接收这个SystemRequest.LIST-DEVICES这个请求,并如何处理的。

Agent端:

       Agent首先会通过一个Receiver启动ServerService,这个ServerService就是与Drozer建立连接的服务。定位到Receiver

public void onReceive(Context context, Intent intent) {
                   Intent start_service = new Intent();
                   start_service.putExtras(intent);         
                   if(intent.getCategories().contains("com.mwr.dz.START_EMBEDDED")){
                            start_service.addCategory("com.mwr.dz.START_EMBEDDED");

                            #Intent绑定ServerService

                            start_service.setComponent(new ComponentName("com.mwr.dz",
"com.mwr.dz.services.ServerService"));

                   }
                   else {
                            if(intent.getCategories().contains("com.mwr.dz.CREATE_ENDPOINT"))
                                     start_service.addCategory("com.mwr.dz.CREATE_ENDPOINT");
                            if(intent.getCategories().contains("com.mwr.dz.START_ENDPOINT"))
                                     start_service.addCategory("com.mwr.dz.START_ENDPOINT");                          
                            start_service.setComponent(new
ComponentName("com.mwr.dz", "com.mwr.dz.services.ClientService"));
                   }

                   #启动ServerService

                   context.startService(start_service);
         }

ServerService这个服务相对Drozer可以称为server端,主要负责监听Drozer的请求连接,并处理相关请求。

ServerService间接继承Service组件,onStartCommand()主要负责执行StartServer()这个方法。

public int onStartCommand(Intent intent, int flags, int startId){
                   int ret_val = super.onStartCommand(intent, flags, startId);
                   if(intent != null &&intent.getCategories() != null &&
intent.getCategories().contains("com.mwr.dz.START_EMBEDDED")) {
                            Agent.getInstance().setContext(this.getApplicationContext());


                            this.startServer();
                   }                 
                   return ret_val;
         }

定位到startServer()

public void startServer() {
                   if(this.server == null) {
                            (new ServerSettings()).load(this.server_parameters);                         
                            this.server_parameters.enabled= true;

                           #实例化Server对象,其中Server类间接继承Thread

                            this.server = new Server(this.server_parameters, Agent.getInstance().getDeviceInfo());

                            this.server.setLogger(this.server_parameters.getLogger());
                            this.server_parameters.getLogger().addOnLogMessageListener(this);

                            #启动Server这个实例化线程,执行run()

                            this.server.start();       
                    
                           Toast.makeText(this,String.format(Locale.ENGLISH, this.getString(R.string.embedded_server_started),this.server_parameters.getPort()), Toast.LENGTH_SHORT).show();
                   }
         }

代码中的this.serverServer类的对象,这个Server类继承Link类,而Link类间接继承Thread,所以说,Server类是一个线程类。当执行this.server.start()时,这个线程就启动了。定位到Server类的run()

public void run() {
                   this.running = true;                 
                   this.log(LogMessage.INFO,"Starting Server...");
                   while(this.running) {
                            try {
                                     if(this.connection== null) {               
                                               this.log(LogMessage.INFO,"Attempting to bind to port " +
((com.mwr.jdiesel.api.connectors.Server)this.parameters).getPort() +"...");

                                                #实例化ServerSocket对象

                                               this.server_socket= new
ServerSocketFactory().createSocket((com.mwr.jdiesel.api.connectors.Server)this.parameters);

                                              this.log(LogMessage.INFO,"Waiting for connections...");
                                               #接收Drozer的socket发送过来的请求

                                               Socket socket =this.server_socket.accept();
                                             
                                               if(socket!= null) {                                                                                                             
                                                        this.log(LogMessage.INFO,"Accepted connection...");                                             
                                                        this.log(LogMessage.INFO,"Starting drozer thread...");

                                                        #处理Drozer发过来的请求

                                                        this.createConnection(new SocketTransport(socket));
                                               }
                                     }

server_socket.accept()负责接收Drozer的请求。而createConnection(new SocketTransport(socket))负责处理这个请求。定位到createConnection()

protected void createConnection(Transport transport) {
                   if(transport.isLive()) {
                            #实例化Connection对象

                            this.connection = new Connection(this,this.device_info, transport);   
     
                            this.connection.start();
                   }
         }

创建一个Connection实例,而后启动它。这个Connection也是间接继承Thread,也是一个线程类。定位到这个类的run(),而这个run()是继承来自它的父类AbstractConnection,真正负责接收Drozer的请求与处理相对应的请求就在这里实现的。具体代码如下:

public void run() {
                   this.running = true;
                   this.started = true;
                   this.tryAndNotifyAll();                
                   this.last_message_at =System.currentTimeMillis();                
                   Message request = null;                 
                   if(!this.bindToServer(this.device_info))
                            this.stopConnection();                   
                   while(this.running) {

                             #获取Drozer发送过来的request

                            request = this.receive();  
                        
                            if(request != null){

                                     #处理request

                                     this.handleMessage(request);                          
                                     request =null;
                            }                        
                            this.checkForLiveness();                          
                            Thread.yield();
                   }

展开this.receive()这个函数,将请求转化为Frame对象,这里需要将request转化为Frame对象,是不是符合Drozermessage封装成Frame的过程?定位到receive()

protected Message receive() {
                   try {
                            #将request转化为Frame类型

                            Frame f = this.transport.receive();    
                     
                            return f != null ?f.getPayload() : null;
}   
          

再展开this.handleMessage(),代码如下:

private void handleMessage(Message message) {
                   try {
                            Message response = null;
                            switch(message.getType()){

                            case REFLECTION_REQUEST:
                                     response = this.handleReflectionRequest(message);
                                     break;

                            case REFLECTION_RESPONSE:
                                     response = this.handleReflectionResponse(message);
                                     break;

                            #匹配message类型,并做相应的处理

                            case SYSTEM_REQUEST:
                                     response = this.handleSystemRequest(message);

                                     break;

                            case SYSTEM_RESPONSE:
                                     response = this.handleSystemResponse(message);
                                     break;

                            default:
                                     throw new UnexpectedMessageException(message.getType());
                            }

                            #将处理后的结果返回给Drozer
                            if(response != null)

                                     this.send(response);
                   }

从这里可以看出,这里根据不同的消息类型进行处理。因为LIST_DEVICES属于SystemRequest,所以这个交给handleSystemRequest()处理。而handleSystemRequest()调用system_message_handler.handle()进行处理。而后将response返回给Drozer

展开system_message_handler.handle()system_message_handler属于SystemMessageHandler的实例。Handle()代码如下:

public Message handle(Message message) throws InvalidMessageException {
                   if(message.getType() != Message.MessageType.SYSTEM_REQUEST)
                            throw new InvalidMessageException(message);
                   if(!message.hasSystemRequest())
                            throw new InvalidMessageException(message);
                   switch(message.getSystemRequest().getType()){

                   #匹配具体的SystemRequest消息类型,并进行处理

                   case LIST_DEVICES:
                            return this.handleListDevices(message);

                   case LIST_SESSIONS:
                            return this.handleListSessions(message);                           
                   case PING:
                            return this.handlePing(message);                            
                   case START_SESSION:
                            return this.startSession(message);                           
                   case STOP_SESSION:
                            return this.stopSession(message);                          
                   default:
                            throw new InvalidMessageException(message);
                   }

到这里就看到LIST_DEVICES消息类型了。定位到handleListDevices()

protected Message handleListDevices(Message message) throws InvalidMessageException {
                   MessageFactory factory = new MessageFactory(SystemResponseFactory.deviceList(message).addDevice(
                                     this.device_info.getAndroidID(),
                                     this.device_info.getManufacturer(),
                                     this.device_info.getModel(),
                                     this.device_info.getSoftware()));                   
                   factory.inReplyTo(message);     
           
                   return factory.build();

         }

至此,整个获取与Drozer建立连接的设备就结束了。

接着往下走,下面重点分析

ReflectionRequest消息执行过程

现在我们重点分析建立会话过程,定位到Console.do_connect():

def do_connect(self, arguments):
        if arguments.password:
            with warnings.catch_warnings():
                warnings.simplefilter("ignore")

                password = getpass.getpass()
        else:
            password = None
        #获取与Drozer绑定的设备

        device = self.__get_device(arguments)
        #获取与Agent连接的socket
        server = self.__getServerConnector(arguments)        
        #获取与Agent开始会话的响应
        response = server.startSession(device, password)
        
        if response.type == Message.SYSTEM_RESPONSE and\
            response.system_response.status == Message.SystemResponse.SUCCESS:
            session_id = response.system_response.session_id

            try:
                if(arguments.debug):
                    session = DebugSession(server, session_id, arguments)
                else:                    
                     #与Agent建立会话

                    session = Session(server, session_id, arguments)

                if len(arguments.file) > 0:
                    session.do_load(" ".join(arguments.file))
                    session.do_exit("")
                elif arguments.onecmd != None:
                    session.onecmd(arguments.onecmd)
                    session.do_exit("")
                else:                   
                     #进入控制台,等待命令输入并执行

                    session.cmdloop()
            except KeyboardInterrupt:
                print
                print "Caught SIGINT, terminating your session."
            finally:
                session.do_exit("")
                
            self.__getServerConnector(arguments).close()
        else:
            self.handle_error(RuntimeError(response.system_response.error_message), fatal=True)

我们从这行入手session = Session(server, session_id, arguments),初始化session对象,建立与Agent联系的session

定位到Session类的__init__方法:

class Session(cmd.Cmd):

    def __init__(self, server, session_id, arguments):
        cmd.Cmd.__init__(self)
        self.__base = ""
        self.__has_context = None
        self.__module_pushed_completers = 0
        self.__permissions = None
        self.__server = server
        self.__session_id = session_id
        self.__onecmd = arguments.onecmd
        self.active = True
        self.aliases = { "l": "list", "ls": "list", "ll": "list" }
        self.intro = "drozer Console (v%s)" % meta.version
        self.history_file = os.path.sep.join([os.path.expanduser("~"), ".drozer_history"])
        #模块集

        self.modules = collection.ModuleCollection(loader.ModuleLoader())
        self.prompt = "dz> "
        #反射对象

        self.reflector = Reflector(self)
        if hasattr(arguments, 'no_color') and not arguments.no_color:
            self.stdout = ColouredStream(self.stdout)
            self.stderr = ColouredStream(self.stderr)
        else:
            self.stdout = DecolouredStream(self.stdout)
            self.stderr = DecolouredStream(self.stderr)

        #实例化Module对象m

        m = Module(self)

        if m.has_context():
            #如果Context不存在,获取com.mwr.dz.Agent的数据路径,得到的路径是/data/data/com.mwr.dz.Agent

            dataDir = str(m.getContext().getApplicationInfo().dataDir)
        else:
            dataDir = str(m.new("java.io.File", ".").getCanonicalPath().native())

        self.variables = {  'PATH': dataDir +'/bin:/sbin:/vendor/bin:/system/sbin:/system/bin:/system/xbin',
                            'WD': dataDir }
        
        self.__load_variables()
        
        if arguments.onecmd == None:
            self.__print_banner()

如果Context不存在,获取com.mwr.dz.Agent的数据路径,当然这里就要用到消息反射了。定位到ModulesgetContext()

def getContext(self):
         #利用反射得到com.mwr.dz.Agent的实例

        return self.klass('com.mwr.dz.Agent').getContext()

继续跟踪klass()

def klass(self, class_name):

        if not Module.cached_klass(class_name):
             #存储反射引用到cache中

            Module.cache_klass(class_name, self.reflector.resolve(class_name))
        
        return Module.get_cached_klass(class_name)

继续执行会跳转到Reflector.resolve方法:

def resolve(self, class_name):
          #将反射请求发送到Agent

        response = self.sendAndReceive(ReflectionRequestFactory.resolve(class_name))

        if response is None:
            raise ReflectionException("expected a response to RESOLVE")
        elif response.reflection_response.status == Message.ReflectionResponse.SUCCESS:
            return ReflectedType.fromArgument(response.reflection_response.result, reflector=self)
        else:
            raise ReflectionException(response.reflection_response.errormessage)

到这里,我们又看到SendAndReceive(),接下来的执行过程可参考Drozer端的SystemRequest消息的执行过程。

Agent端:

Agent接收与处理ReflecionRequest类消息可参考上节讲的SystemReqeust。这里重点讲下ReflectionRequest的处理过程。最终执行过程如下:

public Message handle(Message message) throws InvalidMessageException {
                   if(message.getType() != Message.MessageType.REFLECTION_REQUEST)
                            throw new InvalidMessageException(message);
                   if(!message.hasReflectionRequest())
                            throw new InvalidMessageException(message);
                   try {
                            switch(message.getReflectionRequest().getType()){
                            case CONSTRUCT:
                                     if(!message.getReflectionRequest().hasConstruct())
                                              throw new InvalidMessageException(message);                                   
                                     return this.handleConstruct(message);                                   
                            case DELETE:
                                     if(!message.getReflectionRequest().hasDelete())
                                               throw new InvalidMessageException(message);                                    
                                     return this.handleDelete(message);                                    
                            case DELETE_ALL:
                                     return this.handleDeleteAll(message);                                   
                            case GET_PROPERTY:
                                     if(!message.getReflectionRequest().hasGetProperty())
                                               throw new InvalidMessageException(message);                                    
                                     return this.handleGetProperty(message);                                   
                            case INVOKE:
                                     if(!message.getReflectionRequest().hasInvoke())
                                               throw new InvalidMessageException(message);                                 
                                     return this.handleInvoke(message);

                            #执行resolve类的ReflectionRequest消息

                            case RESOLVE:
                                     if(!message.getReflectionRequest().hasResolve())
                                               throw new InvalidMessageException(message)  
                                  
                                     return this.handleResolve(message);

                            case SET_PROPERTY:
                                     if(!message.getReflectionRequest().hasSetProperty())
                                               throw new InvalidMessageException(message);
                                     return this.handleSetProperty(message);
                            default:
                                  throw new InvalidMessageException(message);
                            }
                   }

定位到handResolve():

protected Message handleResolve(Message message) throws InvalidMessageException {
                  #利用反射得到类的class

                  Class<?>klass =
Reflector.resolve(message.getReflectionRequest().getResolve().getClassname());

                   if(klass != null) {
                            int ref = this.session.object_store.put(klass);
                            return this.createResponse(message,   ReflectionResponseFactory.object(ref));
                  }
                   else {
                            return this.handleError(message, "cannot resolve " +
message.getReflectionRequest().getResolve().getClassname());
                   }
         }

定位到Reflector.resolve

public static Class<?> resolve(String className) {
                   try {
                            #反射得到类名的class

                            return Class.forName(className);
                   }
                   catch(ClassNotFoundException e) {
                            return null;
                   }
         }

至此,ReflectonRequest整个请求与处理过程完成了。

3.2 runmodule_name argvs命令执行过程

为了方便,这里以run app.package. AttackSurface packageName为例说明。

现在我们重点分析在console中执行命令的过程,定位到Console.do_connect():


def do_connect(self, arguments):
        if arguments.password:
            with warnings.catch_warnings():
                warnings.simplefilter("ignore")

                password = getpass.getpass()
        else:
            password = None
        #获取与Drozer绑定的设备

        device = self.__get_device(arguments)
        #获取与Agent连接的socket
        server = self.__getServerConnector(arguments)        
        #获取与Agent开始会话的响应
        response = server.startSession(device, password)
        
        if response.type == Message.SYSTEM_RESPONSE and\
            response.system_response.status == Message.SystemResponse.SUCCESS:
            session_id = response.system_response.session_id

            try:
                if(arguments.debug):
                    session = DebugSession(server, session_id, arguments)
                else:                    
                     #与Agent建立会话

                    session = Session(server, session_id, arguments)

                if len(arguments.file) > 0:
                    session.do_load(" ".join(arguments.file))
                    session.do_exit("")
                elif arguments.onecmd != None:
                    session.onecmd(arguments.onecmd)
                    session.do_exit("")
                else:                   
                     #进入控制台,等待命令输入并执行

                    session.cmdloop()
            except KeyboardInterrupt:
                print
                print "Caught SIGINT, terminating your session."
            finally:
                session.do_exit("")
                
            self.__getServerConnector(arguments).close()
        else:
            self.handle_error(RuntimeError(response.system_response.error_message), fatal=True)

此处从session.cmdloop()入手,定位到cmdloop()方法:

def cmdloop(self, intro=None):
        self.preloop()
        if self.use_rawinput and self.completekey:
            self.push_completer(self.complete, self.history_file)
        try:
            stop = None
            while not stop:
                if self.cmdqueue:
                    line = self.cmdqueue.pop(0)
                else:
                    if self.use_rawinput:
                        try:
                           #得到用户输入的命令

                            line = raw_input(self.prompt)
                        except EOFError:
                            line = 'EOF'
                    else:
                        self.stdout.write(self.prompt)
                        self.stdout.flush()
                        line = self.stdin.readline()
                        if not len(line):
                            line = 'EOF'
                        else:
                            line = line.rstrip('\r\n')
                            
                try:
                    line = self.precmd(line)
                     #解析输入的命令

                    stop = self.onecmd(line)
                    stop = self.postcmd(stop, line)
               .....
               .....

这里首先获取用户的输入命令,然后执行onecmd()对获取到的命令进行解析。定位到onecmd()

def onecmd(self, line):
        cmd, arg, line = self.parseline(line)
        if not line:
            return self.emptyline()
        if cmd is None:
            return self.default(line)
        self.lastcmd = line
        if line == 'EOF' :
            self.lastcmd = ''
        if cmd == '':
            return self.default(line)
        else:
            try:
                #获取console当中的命令,调用do_xxx

                func = getattr(self, 'do_' + cmd)
            except AttributeError:
                return self.default(line)

            return func(arg)

这里,根据输入的命令跳转到对应do_xxx的方法进行解析。

此处分析 run命令的执行过程,定位到Session.do_run()方法:

def do_run(self, args):     
        argv = shlex.split(args, comments=True)

        if len(argv) == 1 and (argv[0] == "-h" or argv[0] == "--help"):
            self.do_help("run")
            return

        if len(argv) > 0:
            try:
                 #解析run语句后面的第一个参数,这个参数决定调用哪个module,此处这个module指的是app.package. AttackSurface

                module = self.__module(argv[0])
                module.push_completer = self.__push_module_completer
                module.pop_completer = self.__pop_module_completer
                
                self.__module_pushed_completers = 0
            except KeyError as e:
                self.stderr.write("unknown module: %s\n" % str(e))
                return None

            try:
                 #调用module.run(),这里argv[1:]指的packageName

                module.run(argv[1:])
            except KeyboardInterrupt:
                self.stderr.write("\nCaught SIGINT. Interrupt again to terminate you session.\n")
            except Exception as e:
                self.handleException(e)
            
            while self.__module_pushed_completers > 0:
                self.__pop_module_completer()
        else:
            self.do_help("run")

因为所以的modules都继承Module,而module.run()这个run()是在Module中实现的,定位到Module.run():

 def run(self, args):
   
         #实例化parse对象

        parser = self.__prepare_parser()

        parser.description = self.usage.formatted_description()
        parser.usage = self.usage.formatted_usage(parser)

        if "-h" in args or "--help" in args:
            return parser.print_help()
        else:
             #获取命令行参数

            arguments = parser.parse_args(args)
            
            if hasattr(self, 'execute'):
                 #执行app.package. AttackSurface中的execute()

                result = self.execute(arguments)
            else:
                self.stderr.write("drozer doesn't know how to do that.\n")
                self.stderr.write("The %s module does not define an execute() method.\n\n" % self.fqmn())
                
                result = None
                
            self.clearObjectStore()

            return result

定位到app.package. AttackSurface.execute():

def execute(self, arguments):
        if arguments.package != None:

            package = self.packageManager().getPackageInfo(arguments.package, common.PackageManager.GET_ACTIVITIES | common.PackageManager.GET_RECEIVERS | common.PackageManager.GET_PROVIDERS | common.PackageManager.GET_SERVICES)
            application = package.applicationInfo

            activities = self.match_filter(package.activities, 'exported', True)
            receivers = self.match_filter(package.receivers, 'exported', True)
            providers = self.match_filter(package.providers, 'exported', True)
            services = self.match_filter(package.services, 'exported', True)
            
            self.stdout.write("Attack Surface:\n")
            self.stdout.write("  %d activities exported\n" % len(activities))
            self.stdout.write("  %d broadcast receivers exported\n" % len(receivers))
            self.stdout.write("  %d content providers exported\n" % len(providers))
            self.stdout.write("  %d services exported\n" % len(services))


            if (application.flags & application.FLAG_DEBUGGABLE) != 0:
                self.stdout.write("    is debuggable\n")

            if package.sharedUserId != None:
                self.stdout.write("    Shared UID (%s)\n" % package.sharedUserId)
        else:
            self.stdout.write("No package specified\n")

至此,在console当中run命令的执行分析过程就结束了。

4.    Drozer小结

      Drozer可以看成是C/S结构的工具。PC端是用Python写的,Agent端是用java写的。利用Google Protocol Buffer协议作为消息载体。很重要的一点就是利用反射,很大一部分工作都是由Agent代理完成,最后由PC端处理解析。后面还有就是命令的具体实现部分,后面会陆续更新。

5.    参考链接

 http://www.freebuf.com/articles/terminal/111863.html

 http://bbs.pediy.com/showthread.php?t=190561


  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
比较好的sql注入工具源码 <?xml version="1.0" ?> - <root> - <signatures release="2008"> - <signature> <version>10.00.1300.13</version> <servicepack>February CTP</servicepack> </signature> - <signature> <version>10.00.1049.14</version> <servicepack>July CTP</servicepack> </signature> - <signature> <version>10.00.1019.17</version> <servicepack>June CTP</servicepack> </signature> </signatures> - <signatures release="2005"> - <signature> <version>9.00.3260</version> <servicepack>2+Q954950</servicepack> </signature> - <signature> <version>9.00.3259</version> <servicepack>2+Q954669</servicepack> </signature> - <signature> <version>9.00.3257</version> <servicepack>2+Q951217</servicepack> </signature> - <signature> <version>9.00.3244</version> <servicepack>2+Q952330</servicepack> </signature> - <signature> <version>9.00.3240</version> <servicepack>2+Q951204</servicepack> </signature> - <signature> <version>9.00.3239</version> <servicepack>2+Q949095</servicepack> </signature> - <signature> <version>9.00.3235</version> <servicepack>2+Q950189</servicepack> </signature> - <signature> <version>9.00.3232</version> <servicepack>2+Q949959</servicepack> </signature> - <signature> <version>9.00.3231</version> <servicepack>2+Q949687</servicepack> </signature> - <signature> <version>9.00.3230</version> <servicepack>2+Q949199</servicepack> </signature> - <signature> <version>9.00.3228</version> <servicepack>2+Q946608</servicepack> </signature> - <signature> <version>9.00.3224</version> <servicepack>2+Q947463</servicepack> </signature> - <signature> <version>9.00.3222</version> <servicepack>2+Q945640</servicepack> </signature> - <signature> <version>9.00.3221</version> <servicepack>2+Q942908</servicepack> </signature> - <signature> <version>9.00.3215</version> <servicepack>2+Q941450</servicepack> </signature> - <signature> <version>9.00.3209</version> <servicepack>2</servicepack> </signature> - <signature> <version>9.00.3208</version> <servicepack>2+Q944902</servicepack> </signature> - <signature> <version>9.00.3206</version> <servicepack>2+Q944677</servicepack> </signature> - <signature> <version>9.00.3205</version> <servicepack>2</servicepack> </signature> - <signature> <version>9.00.3203</version> <servicepack>2</servicepack> </signature> - <signature> <version>9.00.3200</version> <servicepack>2+Q941450</servicepack> </signature> - <signature> <version>9.00.3195</version> <servicepack>2</servicepack> </signature> - <signature> <version>9.00.3194</version> <servicepack>2+Q940933</servicepack> </signature> - <signature> <version>9.00.3186</version> <servicepack>2+Q939562</servicepack> </signature> - <signature> <version>9.00.3182</version> <servicepack>2+Q940128</servicepack> </signature> - <signature> <version>9.00.3180</version> <servicepack>2+Q939942</servicepack> </signature> - <signature> <version>9.00.3179</version> <servicepack>2+Q938243</servicepack> </signature> - <signature> <version>9.00.3178</version> <servicepack>2</servicepack> </signature> - <signature> <version>9.00.3177</version> <servicepack>2+Q939563</servicepack> </signature> - <signature> <version>9.00.3175</version> <servicepack>2+Q936305</servicepack> </signature> - <signature> <version>9.00.3171</version> <servicepack>2+Q937745</servicepack> </signature> - <signature> <version>9.00.3169</version> <servicepack>2+Q937041</servicepack> </signature> - <signature> <version>9.00.3166</version> <servicepack>2+Q936185</servicepack> </signature> - <signature> <version>9.00.3162</version> <servicepack>2+Q932610</servicepack> </signature> - <signature> <version>9.00.3161</version> <servicepack>2+Q935356</servicepack> </signature> - <signature> <version>9.00.3159</version> <servicepack>2+Q934459</servicepack> </signature> - <signature> <version>9.00.3156</version> <servicepack>2+Q934226</servicepack> </signature> - <signature> <version>9.00.3155</version> <servicepack>2+Q933549</servicepack> </signature> - <signature> <version>9.00.3154</version> <servicepack>2+Q934106</servicepack> </signature> - <signature> <version>9.00.3153</version> <servicepack>2+Q933564</servicepack> </signature> - <signature> <version>9.00.3152</version> <servicepack>2+Q933097</servicepack> </signature> - <signature> <version>9.00.3054</version> <servicepack>2+Q934458</servicepack> </signature> - <signature> <version>9.00.3050</version> <servicepack>2+Q933508</servicepack> </signature> - <signature> <version>9.00.3043</version> <servicepack>2+Q933508</servicepack> </signature> - <signature> <version>9.00.3042</version> <servicepack>'Fixed' 2</servicepack> </signature> - <signature> <version>9.00.3033</version> <servicepack>2 CTP</servicepack> </signature> - <signature> <version>9.00.3027</version> <servicepack>2 CTP</servicepack> </signature> - <signature> <version>9.00.3026</version> <servicepack>1+Q929376</servicepack> </signature> - <signature> <version>9.00.2245</version> <servicepack>1+Q933573</servicepack> </signature> - <signature> <version>9.00.2243</version> <servicepack>1+Q944968</servicepack> </signature> - <signature> <version>9.00.2242</version> <servicepack>1+Q943389</servicepack> </signature> - <signature> <version>9.00.2239</version> <servicepack>1+Q940961</servicepack> </signature> - <signature> <version>9.00.2237</version> <servicepack>1+Q940719</servicepack> </signature> - <signature> <version>9.00.2236</version> <servicepack>1+Q940287</servicepack> </signature> - <signature> <version>9.00.2234</version> <servicepack>1+Q937343</servicepack> </signature> - <signature> <version>9.00.2233</version> <servicepack>1+Q933499</servicepack> </signature> - <signature> <version>9.00.2232</version> <servicepack>1+Q937277</servicepack> </signature> - <signature> <version>9.00.2231</version> <servicepack>1+Q934812</servicepack> </signature> - <signature> <version>9.00.2230</version> <servicepack>1+Q936179</servicepack> </signature> - <signature> <version>9.00.2229</version> <servicepack>1+Q935446</servicepack> </signature> - <signature> <version>9.00.2227</version> <servicepack>1+Q934066</servicepack> </signature> - <signature> <version>9.00.2226</version> <servicepack>1+Q933762</servicepack> </signature> - <signature> <version>9.00.2224</version> <servicepack>1+Q932990</servicepack> </signature> - <signature> <version>9.00.2223</version> <servicepack>1+Q932393</servicepack> </signature> - <signature> <version>9.00.2221</version> <servicepack>1+Q931593</servicepack> </signature> - <signature> <version>9.00.2219</version> <servicepack>1+Q931329</servicepack> </signature> - <signature> <version>9.00.2218</version> <servicepack>1+Q931843</servicepack> </signature> - <signature> <version>9.00.2216</version> <servicepack>1+Q931821</servicepack> </signature> - <signature> <version>9.00.2215</version> <servicepack>1+Q931666</servicepack> </signature> - <signature> <version>9.00.2214</version> <servicepack>1+Q929240</servicepack> </signature> - <signature> <version>9.00.2211</version> <servicepack>1+Q930283</servicepack> </signature> - <signature> <version>9.00.2209</version> <servicepack>1+Q929278</servicepack> </signature> - <signature> <version>9.00.2208</version> <servicepack>1+Q929179</servicepack> </signature> - <signature> <version>9.00.2207</version> <servicepack>1+Q928394<</servicepack> </signature> - <signature> <version>9.00.2206</version> <servicepack>1+Q928539</servicepack> </signature> - <signature> <version>9.00.2202</version> <servicepack>1+Q927643</servicepack> </signature> - <signature> <version>9.00.2201</version> <servicepack>1+Q927289</servicepack> </signature> - <signature> <version>9.00.2198</version> <servicepack>1+Q926773</servicepack> </signature> - <signature> <version>9.00.2196</version> <servicepack>1+Q926285</servicepack> </signature> - <signature> <version>9.00.2195</version> <servicepack>1+Q926240</servicepack> </signature> - <signature> <version>9.00.2194</version> <servicepack>1+Q925744</servicepack> </signature> - <signature> <version>9.00.2192</version> <servicepack>1+Q924954</servicepack> </signature> - <signature> <version>9.00.2191</version> <servicepack>1+Q925135</servicepack> </signature> - <signature> <version>9.00.2190</version> <servicepack>1+Q925227</servicepack> </signature> - <signature> <version>9.00.2189</version> <servicepack>1+Q925153</servicepack> </signature> - <signature> <version>9.00.2187</version> <servicepack>1+Q923849</servicepack> </signature> - <signature> <version>9.00.2183</version> <servicepack>1+Q929404</servicepack> </signature> - <signature> <version>9.00.2181</version> <servicepack>1+Q923624</servicepack> </signature> - <signature> <version>9.00.2176</version> <servicepack>1+Q923296</servicepack> </signature> - <signature> <version>9.00.2175</version> <servicepack>1+Q922578</servicepack> </signature> - <signature> <version>9.00.2174</version> <servicepack>1+Q922063</servicepack> </signature> - <signature> <version>9.00.2167</version> <servicepack>1+Q920974</servicepack> </signature> - <signature> <version>9.00.2164</version> <servicepack>1+Q919636</servicepack> </signature> - <signature> <version>9.00.2156</version> <servicepack>1+Q919611</servicepack> </signature> - <signature> <version>9.00.2153</version> <servicepack>1+builds 1531</servicepack> </signature> - <signature> <version>9.00.2050</version> <servicepack>1+.NET Vulnerability fix</servicepack> </signature> - <signature> <version>9.00.2047</version> <servicepack>1 0</servicepack> </signature> - <signature> <version>9.00.2040</version> <servicepack>1 CTP</servicepack> </signature> - <signature> <version>9.00.2029</version> <servicepack>1 Beta</servicepack> </signature> - <signature> <version>9.00.1561</version> <servicepack>0+Q932556</servicepack> </signature> - <signature> <version>9.00.1558</version> <servicepack>0+Q926493</servicepack> </signature> - <signature> <version>9.00.1554</version> <servicepack>0+Q926292</servicepack> </signature> - <signature> <version>9.00.1551</version> <servicepack>0+Q922804</servicepack> </signature> - <signature> <version>9.00.1550</version> <servicepack>0+Q917887</servicepack> </signature> - <signature> <version>9.00.1547</version> <servicepack>0+Q918276</servicepack> </signature> - <signature> <version>9.00.1545</version> <servicepack>0+Q917905</servicepack> </signature> - <signature> <version>9.00.1541</version> <servicepack>0+Q917888</servicepack> </signature> - <signature> <version>9.00.1539</version> <servicepack>0+Q917738</servicepack> </signature> - <signature> <version>9.00.1538</version> <servicepack>0+Q917824</servicepack> </signature> - <signature> <version>9.00.1536</version> <servicepack>0+Q917016</servicepack> </signature> - <signature> <version>9.00.1534</version> <servicepack>0+Q916706</servicepack> </signature> - <signature> <version>9.00.1533</version> <servicepack>0+Q916086</servicepack> </signature> - <signature> <version>9.00.1532</version> <servicepack>0+Q916046</servicepack> </signature> - <signature> <version>9.00.1531</version> <servicepack>0+Q915918</servicepack> </signature> - <signature> <version>9.00.1528</version> <servicepack>0+Q915112</servicepack> </signature> - <signature> <version>9.00.1519</version> <servicepack>0+Q913494</servicepack> </signature> - <signature> <version>9.00.1518</version> <servicepack>0+Q912472</servicepack> </signature> - <signature> <version>9.00.1514</version> <servicepack>0+Q912471</servicepack> </signature> - <signature> <version>9.00.1503</version> <servicepack>0+Q911662</servicepack> </signature> - <signature> <version>9.00.1502</version> <servicepack>0+Q915793</servicepack> </signature> - <signature> <version>9.00.1500</version> <servicepack>0+Q910416</servicepack> </signature> - <signature> <version>9.00.1406</version> <servicepack>0+Q932557</servicepack> </signature> - <signature> <version>9.00.1399</version> <servicepack>0</servicepack> </signature> - <signature> <version>9.00.1314</version> <servicepack>September CTP Release</servicepack> </signature> - <signature> <version>9.00.1187</version> <servicepack>June CTP Release</servicepack> </signature> - <signature> <version>9.00.1116</version> <servicepack>April CTP Release</servicepack> </signature> - <signature> <version>9.00.1090</version> <servicepack>March CTP Release</servicepack> </signature> - <signature> <version>9.00.981</version> <servicepack>December CTP Release</servicepack> </signature> - <signature> <version>9.00.951</version> <servicepack>October CTP Release</servicepack> </signature> - <signature> <version>9.00.917</version> <servicepack>Internal build</servicepack> </signature> - <signature> <version>9.00.852</version> <servicepack>Beta 2</servicepack> </signature> - <signature> <version>9.00.849</version> <servicepack>Internal build</servicepack> </signature> - <signature> <version>9.00.844</version> <servicepack>Internal build</servicepack> </signature> - <signature> <version>9.00.836</version> <servicepack>Express Ed. Tech Preview</servicepack> </signature> - <signature> <version>9.00.823</version> <servicepack>Internal build</servicepack> </signature> - <signature> <version>9.00.790</version> <servicepack>Internal build</servicepack> </signature> - <signature> <version>9.00.767</version> <servicepack>Internal build</servicepack> </signature> - <signature> <version>9.00.747</version> <servicepack>Internal build</servicepack> </signature> - <signature> <version>9.00.645</version> <servicepack>MS Internal</servicepack> </signature> - <signature> <version>9.00.608</version> <servicepack>Beta 1</servicepack> </signature> </signatures> - <signatures release="7"> - <signature> <version>7.00.1152</version> <servicepack>4+Q941203</servicepack> </signature> - <signature> <version>7.00.1150</version> <servicepack>4+Q891116</servicepack> </signature> - <signature> <version>7.00.1144</version> <servicepack>4+Q830233</servicepack> </signature> - <signature> <version>7.00.1143</version> <servicepack>4+Q829015</servicepack> </signature> - <signature> <version>7.00.1097</version> <servicepack>4+Q822756</servicepack> </signature> - <signature> <version>7.00.1094</version> <servicepack>4+Q815495</servicepack> </signature> - <signature> <version>7.00.1079</version> <servicepack>329499</servicepack> </signature> - <signature> <version>7.00.1078</version> <servicepack>4+Q327068</servicepack> </signature> - <signature> <version>7.00.1077</version> <servicepack>4+Q316333</servicepack> </signature> - <signature> <version>7.00.1063</version> <servicepack>4</servicepack> </signature> - <signature> <version>7.00.1033</version> <servicepack>3+Q324469</servicepack> </signature> - <signature> <version>7.00.1026</version> <servicepack>3+Q319851</servicepack> </signature> - <signature> <version>7.00.1004</version> <servicepack>3+Q304851</servicepack> </signature> - <signature> <version>7.00.996</version> <servicepack>3+Q299717</servicepack> </signature> - <signature> <version>7.00.978</version> <servicepack>3+Q285870</servicepack> </signature> - <signature> <version>7.00.977</version> <servicepack>3+Q284351</servicepack> </signature> - <signature> <version>7.00.970</version> <servicepack>3+Q283837</servicepack> </signature> - <signature> <version>7.00.961</version> <servicepack>3</servicepack> </signature> - <signature> <version>7.00.921</version> <servicepack>2+Q283837</servicepack> </signature> - <signature> <version>7.00.919</version> <servicepack>2+Q282243</servicepack> </signature> - <signature> <version>7.00.918</version> <servicepack>2+Q280380</servicepack> </signature> - <signature> <version>7.00.917</version> <servicepack>2+Q279180</servicepack> </signature> - <signature> <version>7.00.910</version> <servicepack>2+Q275901</servicepack> </signature> - <signature> <version>7.00.905</version> <servicepack>2+Q274266</servicepack> </signature> - <signature> <version>7.00.889</version> <servicepack>2+Q243741</servicepack> </signature> - <signature> <version>7.00.879</version> <servicepack>2+Q281185</servicepack> </signature> - <signature> <version>7.00.857</version> <servicepack>2+Q260346</servicepack> </signature> - <signature> <version>7.00.842</version> <servicepack>2</servicepack> </signature> - <signature> <version>7.00.839</version> <servicepack>2 Unidentified</servicepack> </signature> - <signature> <version>7.00.835</version> <servicepack>2 Beta</servicepack> </signature> - <signature> <version>7.00.776</version> <servicepack>1+Q258087</servicepack> </signature> - <signature> <version>7.00.770</version> <servicepack>1+Q252905</servicepack> </signature> - <signature> <version>7.00.745</version> <servicepack>1+Q253738</servicepack> </signature> - <signature> <version>7.00.722</version> <servicepack>1+Q239458</servicepack> </signature> - <signature> <version>7.00.699</version> <servicepack>1</servicepack> </signature> - <signature> <version>7.00.689</version> <servicepack>1 Beta</servicepack> </signature> - <signature> <version>7.00.677</version> <servicepack>MSDE O2K Dev</servicepack> </signature> - <signature> <version>7.00.662</version> <servicepack>Gold+Q232707</servicepack> </signature> - <signature> <version>7.00.658</version> <servicepack>Gold+Q244763</servicepack> </signature> - <signature> <version>7.00.657</version> <servicepack>Gold+Q229875</servicepack> </signature> - <signature> <version>7.00.643</version> <servicepack>Gold+Q220156</servicepack> </signature> - <signature> <version>7.00.623</version> <servicepack>Gold</servicepack> </signature> - <signature> <version>7.00.583</version> <servicepack>RC1</servicepack> </signature> - <signature> <version>7.00.517</version> <servicepack>Beta 3</servicepack> </signature> </signatures> - <signatures release="2000"> - <signature> <version>8.00.2271</version> <servicepack>4+Q946584</servicepack> </signature> - <signature> <version>8.00.2265</version> <servicepack>4+Q944985</servicepack> </signature> - <signature> <version>8.00.2253</version> <servicepack>4+Q939317</servicepack> </signature> - <signature> <version>8.00.2249</version> <servicepack>4+Q936232</servicepack> </signature> - <signature> <version>8.00.2248</version> <servicepack>4+Q935950</servicepack> </signature> - <signature> <version>8.00.2246</version> <servicepack>4+Q935465</servicepack> </signature> - <signature> <version>8.00.2245</version> <servicepack>4+Q933573</servicepack> </signature> - <signature> <version>8.00.2244</version> <servicepack>4+Q934203</servicepack> </signature> - <signature> <version>8.00.2242</version> <servicepack>4+Q929131</servicepack> </signature> - <signature> <version>8.00.2238</version> <servicepack>4+Q931932</servicepack> </signature> - <signature> <version>8.00.2234</version> <servicepack>4+Q929440</servicepack> </signature> - <signature> <version>8.00.2232</version> <servicepack>4+Q928568</servicepack> </signature> - <signature> <version>8.00.2231</version> <servicepack>4+Q928079</servicepack> </signature> - <signature> <version>8.00.2229</version> <servicepack>4+Q927186</servicepack> </signature> - <signature> <version>8.00.2226</version> <servicepack>4+Q925684</servicepack> </signature> - <signature> <version>8.00.2223</version> <servicepack>4+Q925678</servicepack> </signature> - <signature> <version>8.00.2218</version> <servicepack>4+Q925297</servicepack> </signature> - <signature> <version>8.00.2217</version> <servicepack>4+Q924664</servicepack> </signature> - <signature> <version>8.00.2215</version> <servicepack>4+Q924662</servicepack> </signature> - <signature> <version>8.00.2209</version> <servicepack>4+Q923797</servicepack> </signature> - <signature> <version>8.00.2207</version> <servicepack>4+Q923344</servicepack> </signature> - <signature> <version>8.00.2201</version> <servicepack>4+Q920930</servicepack> </signature> - <signature> <version>8.00.2199</version> <servicepack>4+Q919221</servicepack> </signature> - <signature> <version>8.00.2197</version> <servicepack>4+Q919133</servicepack> </signature> - <signature> <version>8.00.2196</version> <servicepack>4+Q919165</servicepack> </signature> - <signature> <version>8.00.2194</version> <servicepack>4+Q917972</servicepack> </signature> - <signature> <version>8.00.2192</version> <servicepack>4+Q917606</servicepack> </signature> - <signature> <version>8.00.2191</version> <servicepack>4+Q916698</servicepack> </signature> - <signature> <version>8.00.2189</version> <servicepack>4+Q916652</servicepack> </signature> - <signature> <version>8.00.2187</version> <servicepack>4+916287</servicepack> </signature> - <signature> <version>8.00.2180</version> <servicepack>4+Q913684</servicepack> </signature> - <signature> <version>8.00.2175</version> <servicepack>4+Q911678</servicepack> </signature> - <signature> <version>8.00.2172</version> <servicepack>4+Q910707</servicepack> </signature> - <signature> <version>8.00.2171</version> <servicepack>4+Q909369</servicepack> </signature> - <signature> <version>8.00.2168</version> <servicepack>4+Q907813</servicepack> </signature> - <signature> <version>8.00.2167</version> <servicepack>4+Q921293</servicepack> </signature> - <signature> <version>8.00.2166</version> <servicepack>4+Q909734</servicepack> </signature> - <signature> <version>8.00.2162</version> <servicepack>4+Q904660</servicepack> </signature> - <signature> <version>8.00.2156</version> <servicepack>4+Q906790</servicepack> </signature> - <signature> <version>8.00.2151</version> <servicepack>4+Q903742</servicepack> </signature> - <signature> <version>8.00.2148</version> <servicepack>4+Q899430</servicepack> </signature> - <signature> <version>8.00.2147</version> <servicepack>4+Q899410</servicepack> </signature> - <signature> <version>8.00.2145</version> <servicepack>4+Q826906</servicepack> </signature> - <signature> <version>8.00.2040</version> <servicepack>4+Q899761</servicepack> </signature> - <signature> <version>8.00.2039</version> <servicepack>4</servicepack> </signature> - <signature> <version>8.00.2026</version> <servicepack>4 Beta</servicepack> </signature> - <signature> <version>8.00.1547</version> <servicepack>3+Q899410</servicepack> </signature> - <signature> <version>8.00.1037</version> <servicepack>3+Q930484</servicepack> </signature> - <signature> <version>8.00.1036</version> <servicepack>3+Q929410</servicepack> </signature> - <signature> <version>8.00.1035</version> <servicepack>3+Q917593</servicepack> </signature> - <signature> <version>8.00.1034</version> <servicepack>3+Q915328</servicepack> </signature> - <signature> <version>8.00.1029</version> <servicepack>3+Q902852</servicepack> </signature> - <signature> <version>8.00.1027</version> <servicepack>3+Q900416</servicepack> </signature> - <signature> <version>8.00.1025</version> <servicepack>3+Q899428</servicepack> </signature> - <signature> <version>8.00.1024</version> <servicepack>3+Q898709</servicepack> </signature> - <signature> <version>8.00.1021</version> <servicepack>3+Q887700</servicepack> </signature> - <signature> <version>8.00.1020</version> <servicepack>3+Q896985</servicepack> </signature> - <signature> <version>8.00.1019</version> <servicepack>3+Q897572</servicepack> </signature> - <signature> <version>8.00.1017</version> <servicepack>3+Q896425</servicepack> </signature> - <signature> <version>8.00.1014</version> <servicepack>3+Q895123</servicepack> </signature> - <signature> <version>8.00.1013</version> <servicepack>3+Q891866</servicepack> </signature> - <signature> <version>8.00.1009</version> <servicepack>3+Q894257</servicepack> </signature> - <signature> <version>8.00.1007</version> <servicepack>3+Q893312</servicepack> </signature> - <signature> <version>8.00.1000</version> <servicepack>3+Q891585</servicepack> </signature> - <signature> <version>8.00.997</version> <servicepack>3+Q891311</servicepack> </signature> - <signature> <version>8.00.996</version> <servicepack>3+Q891017</servicepack> </signature> - <signature> <version>8.00.994</version> <servicepack>3+Q890942</servicepack> </signature> - <signature> <version>8.00.993</version> <servicepack>3+Q890925</servicepack> </signature> - <signature> <version>8.00.991</version> <servicepack>3+Q889314</servicepack> </signature> - <signature> <version>8.00.990</version> <servicepack>3+Q890200</servicepack> </signature> - <signature> <version>8.00.988</version> <servicepack>3+Q889166</servicepack> </signature> - <signature> <version>8.00.985</version> <servicepack>3+Q889239</servicepack> </signature> - <signature> <version>8.00.980</version> <servicepack>3+Q887974</servicepack> </signature> - <signature> <version>8.00.977</version> <servicepack>3+Q888007</servicepack> </signature> - <signature> <version>8.00.973</version> <servicepack>3+Q884554</servicepack> </signature> - <signature> <version>8.00.972</version> <servicepack>3+Q885290</servicepack> </signature> - <signature> <version>8.00.970</version> <servicepack>3+Q872842</servicepack> </signature> - <signature> <version>8.00.967</version> <servicepack>3+Q878501</servicepack> </signature> - <signature> <version>8.00.962</version> <servicepack>3+Q883415</servicepack> </signature> - <signature> <version>8.00.961</version> <servicepack>3+Q873446</servicepack> </signature> - <signature> <version>8.00.959</version> <servicepack>3+Q878500</servicepack> </signature> - <signature> <version>8.00.957</version> <servicepack>3+Q870994</servicepack> </signature> - <signature> <version>8.00.955</version> <servicepack>3+Q867798</servicepack> </signature> - <signature> <version>8.00.954</version> <servicepack>3+Q843282</servicepack> </signature> - <signature> <version>8.00.952</version> <servicepack>3+Q867878</servicepack> </signature> - <signature> <version>8.00.944</version> <servicepack>3+Q839280</servicepack> </signature> - <signature> <version>8.00.937</version> <servicepack>3+Q841776</servicepack> </signature> - <signature> <version>8.00.936</version> <servicepack>3+Q841627</servicepack> </signature> - <signature> <version>8.00.935</version> <servicepack>3+Q841401</servicepack> </signature> - <signature> <version>8.00.934</version> <servicepack>3+Q841404</servicepack> </signature> - <signature> <version>8.00.933</version> <servicepack>3+Q840856</servicepack> </signature> - <signature> <version>8.00.929</version> <servicepack>3+Q839529</servicepack> </signature> - <signature> <version>8.00.928</version> <servicepack>3+Q839589</servicepack> </signature> - <signature> <version>8.00.927</version> <servicepack>3+Q839688</servicepack> </signature> - <signature> <version>8.00.926</version> <servicepack>3+Q839523</servicepack> </signature> - <signature> <version>8.00.923</version> <servicepack>3+Q838460</servicepack> </signature> - <signature> <version>8.00.922</version> <servicepack>3+Q837970</servicepack> </signature> - <signature> <version>8.00.919</version> <servicepack>3+Q837957</servicepack> </signature> - <signature> <version>8.00.916</version> <servicepack>3+Q317989</servicepack> </signature> - <signature> <version>8.00.915</version> <servicepack>3+Q837401</servicepack> </signature> - <signature> <version>8.00.913</version> <servicepack>3+Q836651</servicepack> </signature> - <signature> <version>8.00.911</version> <servicepack>3+Q837957</servicepack> </signature> - <signature> <version>8.00.910</version> <servicepack>3+Q834798</servicepack> </signature> - <signature> <version>8.00.908</version> <servicepack>3+Q834290</servicepack> </signature> - <signature> <version>8.00.904</version> <servicepack>3+Q834453</servicepack> </signature> - <signature> <version>8.00.892</version> <servicepack>3+Q833710</servicepack> </signature> - <signature> <version>8.00.891</version> <servicepack>3+Q836141</servicepack> </signature> - <signature> <version>8.00.879</version> <servicepack>3+Q832977</servicepack> </signature> - <signature> <version>8.00.878</version> <servicepack>3+Q831950</servicepack> </signature> - <signature> <version>8.00.876</version> <servicepack>3+Q830912</servicepack> </signature> - <signature> <version>8.00.873</version> <servicepack>3+Q830887</servicepack> </signature> - <signature> <version>8.00.871</version> <servicepack>3+Q830767</servicepack> </signature> - <signature> <version>8.00.870</version> <servicepack>3+Q830262</servicepack> </signature> - <signature> <version>8.00.869</version> <servicepack>3+Q830588</servicepack> </signature> - <signature> <version>8.00.867</version> <servicepack>3+Q830366</servicepack> </signature> - <signature> <version>8.00.866</version> <servicepack>3+Q830366</servicepack> </signature> - <signature> <version>8.00.865</version> <servicepack>3+Q830395</servicepack> </signature> - <signature> <version>8.00.863</version> <servicepack>3+Q829205</servicepack> </signature> - <signature> <version>8.00.859</version> <servicepack>3+Q821334</servicepack> </signature> - <signature> <version>8.00.858</version> <servicepack>3+Q828637</servicepack> </signature> - <signature> <version>8.00.857</version> <servicepack>3+Q828017</servicepack> </signature> - <signature> <version>8.00.856</version> <servicepack>3+Q828096</servicepack> </signature> - <signature> <version>8.00.854</version> <servicepack>3+Q828699</servicepack> </signature> - <signature> <version>8.00.852</version> <servicepack>3+Q830466</servicepack> </signature> - <signature> <version>8.00.851</version> <servicepack>3+Q826754</servicepack> </signature> - <signature> <version>8.00.850</version> <servicepack>3+Q826860</servicepack> </signature> - <signature> <version>8.00.848</version> <servicepack>3+Q826822</servicepack> </signature> - <signature> <version>8.00.847</version> <servicepack>3+Q826433</servicepack> </signature> - <signature> <version>8.00.845</version> <servicepack>3+Q826364</servicepack> </signature> - <signature> <version>8.00.844</version> <servicepack>3+Q826080</servicepack> </signature> - <signature> <version>8.00.842</version> <servicepack>3+Q825043</servicepack> </signature> - <signature> <version>8.00.841</version> <servicepack>3+Q825225</servicepack> </signature> - <signature> <version>8.00.840</version> <servicepack>3+Q319477</servicepack> </signature> - <signature> <version>8.00.839</version> <servicepack>3+Q823877</servicepack> </signature> - <signature> <version>8.00.837</version> <servicepack>3+Q821741</servicepack> </signature> - <signature> <version>8.00.819</version> <servicepack>3+Q826161</servicepack> </signature> - <signature> <version>8.00.818</version> <servicepack>3+Q821277</servicepack> </signature> - <signature> <version>8.00.816</version> <servicepack>3+Q818766</servicepack> </signature> - <signature> <version>8.00.814</version> <servicepack>3+Q819662</servicepack> </signature> - <signature> <version>8.00.811</version> <servicepack>3+Q819248</servicepack> </signature> - <signature> <version>8.00.807</version> <servicepack>3+Q818899</servicepack> </signature> - <signature> <version>8.00.804</version> <servicepack>3+Q818729</servicepack> </signature> - <signature> <version>8.00.801</version> <servicepack>3+Q818540</servicepack> </signature> - <signature> <version>8.00.800</version> <servicepack>3+Q818414</servicepack> </signature> - <signature> <version>8.00.798</version> <servicepack>3+Q817464</servicepack> </signature> - <signature> <version>8.00.794</version> <servicepack>3+Q817464</servicepack> </signature> - <signature> <version>8.00.791</version> <servicepack>3+Q815249</servicepack> </signature> - <signature> <version>8.00.790</version> <servicepack>3+Q817081</servicepack> </signature> - <signature> <version>8.00.789</version> <servicepack>3+Q816840</servicepack> </signature> - <signature> <version>8.00.788</version> <servicepack>3+Q816985</servicepack> </signature> - <signature> <version>8.00.781</version> <servicepack>3+Q815057</servicepack> </signature> - <signature> <version>8.00.780</version> <servicepack>3+Q816084</servicepack> </signature> - <signature> <version>8.00.779</version> <servicepack>3+Q814035</servicepack> </signature> - <signature> <version>8.00.776</version> <servicepack>3+Unidentified</servicepack> </signature> - <signature> <version>8.00.775</version> <servicepack>3+Q815115</servicepack> </signature> - <signature> <version>8.00.769</version> <servicepack>3+Q814889</servicepack> </signature> - <signature> <version>8.00.765</version> <servicepack><</servicepack> </signature> - <signature> <version>8.00.763</version> <servicepack>3+Q814113</servicepack> </signature> - <signature> <version>8.00.762</version> <servicepack>3+Q814032</servicepack> </signature> - <signature> <version>8.00.760</version> <servicepack>3</servicepack> </signature> - <signature> <version>8.00.743</version> <servicepack>2+Q818406</servicepack> </signature> - <signature> <version>8.00.741</version> <servicepack>2+Q818096</servicepack> </signature> - <signature> <version>8.00.736</version> <servicepack>2+Q816937</servicepack> </signature> - <signature> <version>8.00.735</version> <servicepack>2+Q814889</servicepack> </signature> - <signature> <version>8.00.733</version> <servicepack>2+Q813759</servicepack> </signature> - <signature> <version>8.00.730</version> <servicepack>2+Q813769</servicepack> </signature> - <signature> <version>8.00.728</version> <servicepack>2+Q814460</servicepack> </signature> - <signature> <version>8.00.725</version> <servicepack>2+Q812995</servicepack> </signature> - <signature> <version>8.00.723</version> <servicepack>2+Q812798</servicepack> </signature> - <signature> <version>8.00.721</version> <servicepack>2+Q812250</servicepack> </signature> - <signature> <version>8.00.718</version> <servicepack>2+Q811703</servicepack> </signature> - <signature> <version>8.00.715</version> <servicepack>2+Q810688</servicepack> </signature> - <signature> <version>8.00.714</version> <servicepack>2+Q811478</servicepack> </signature> - <signature> <version>8.00.713</version> <servicepack>2</servicepack> </signature> - <signature> <version>8.00.710</version> <servicepack>2</servicepack> </signature> - <signature> <version>8.00.705</version> <servicepack>2+Q810920</servicepack> </signature> - <signature> <version>8.00.703</version> <servicepack>2+Q810526</servicepack> </signature> - <signature> <version>8.00.702</version> <servicepack>2+Q328551</servicepack> </signature> - <signature> <version>8.00.701</version> <servicepack>2+Q810026</servicepack> </signature> - <signature> <version>8.00.700</version> <servicepack>2+Q810072</servicepack> </signature> - <signature> <version>8.00.696</version> <servicepack>2+Q810052</servicepack> </signature> - <signature> <version>8.00.695</version> <servicepack>2+Q331885</servicepack> </signature> - <signature> <version>8.00.693</version> <servicepack>2+Q330212</servicepack> </signature> - <signature> <version>8.00.689</version> <servicepack>2+Q329499</servicepack> </signature> - <signature> <version>8.00.688</version> <servicepack>2+Q329487</servicepack> </signature> - <signature> <version>8.00.686</version> <servicepack>2+Q316333</servicepack> </signature> - <signature> <version>8.00.682</version> <servicepack>3+Q319851</servicepack> </signature> - <signature> <version>8.00.679</version> <servicepack>2+Q316333</servicepack> </signature> - <signature> <version>8.00.678</version> <servicepack>2+Q328354</servicepack> </signature> - <signature> <version>8.00.667</version> <servicepack>2+8</servicepack> </signature> - <signature> <version>8.00.665</version> <servicepack>2+8</servicepack> </signature> - <signature> <version>8.00.661</version> <servicepack>2+Q326999</servicepack> </signature> - <signature> <version>8.00.655</version> <servicepack>2+7</servicepack> </signature> - <signature> <version>8.00.652</version> <servicepack>2+Q810010?</servicepack> </signature> - <signature> <version>8.00.650</version> <servicepack>2+Q322853</servicepack> </signature> - <signature> <version>8.00.644</version> <servicepack>2+Q324186</servicepack> </signature> - <signature> <version>8.00.608</version> <servicepack>2+Q319507</servicepack> </signature> - <signature> <version>8.00.604</version> <servicepack>2+3</servicepack> </signature> - <signature> <version>8.00.594</version> <servicepack>2+Q319477</servicepack> </signature> - <signature> <version>8.00.578</version> <servicepack>2+Q317979</servicepack> </signature> - <signature> <version>8.00.561</version> <servicepack>2+1</servicepack> </signature> - <signature> <version>8.00.558</version> <servicepack>2+Q314003</servicepack> </signature> - <signature> <version>8.00.552</version> <servicepack>2+Q313002</servicepack> </signature> - <signature> <version>8.00.534</version> <servicepack>2.01</servicepack> </signature> - <signature> <version>8.00.532</version> <servicepack>2</servicepack> </signature> - <signature> <version>8.00.475</version> <servicepack>1+1</servicepack> </signature> - <signature> <version>8.00.474</version> <servicepack>1+Q315395</servicepack> </signature> - <signature> <version>8.00.473</version> <servicepack>1+Q314003</servicepack> </signature> - <signature> <version>8.00.471</version> <servicepack>1+Q313302</servicepack> </signature> - <signature> <version>8.00.469</version> <servicepack>1+Q313005</servicepack> </signature> - <signature> <version>8.00.452</version> <servicepack>1+Q308547</servicepack> </signature> - <signature> <version>8.00.444</version> <servicepack>1+Q307540</servicepack> </signature> - <signature> <version>8.00.443</version> <servicepack>1+Q307538</servicepack> </signature> - <signature> <version>8.00.428</version> <servicepack>1+Q304850</servicepack> </signature> - <signature> <version>8.00.384</version> <servicepack>1</servicepack> </signature> - <signature> <version>8.00.287</version> <servicepack>0+Q297209</servicepack> </signature> - <signature> <version>8.00.251</version> <servicepack>0+Q300194</servicepack> </signature> - <signature> <version>8.00.250</version> <servicepack>0+Q291683</servicepack> </signature> - <signature> <version>8.00.249</version> <servicepack>0+Q288122</servicepack> </signature> - <signature> <version>8.00.239</version> <servicepack>0+Q285290</servicepack> </signature> - <signature> <version>8.00.233</version> <servicepack>0+Q282416</servicepack> </signature> - <signature> <version>8.00.231</version> <servicepack>0+Q282279</servicepack> </signature> - <signature> <version>8.00.226</version> <servicepack>0+Q278239</servicepack> </signature> - <signature> <version>8.00.225</version> <servicepack>0+Q281663</servicepack> </signature> - <signature> <version>8.00.223</version> <servicepack>0+Q280380</servicepack> </signature> - <signature> <version>8.00.222</version> <servicepack>0+Q281769</servicepack> </signature> - <signature> <version>8.00.218</version> <servicepack>0+Q279183</servicepack> </signature> - <signature> <version>8.00.217</version> <servicepack>0+Q279293</servicepack> </signature> - <signature> <version>8.00.211</version> <servicepack>0+Q276329</servicepack> </signature> - <signature> <version>8.00.210</version> <servicepack>0+Q275900</servicepack> </signature> - <signature> <version>8.00.205</version> <servicepack>0+Q274330</servicepack> </signature> - <signature> <version>8.00.204</version> <servicepack>0+Q274329</servicepack> </signature> - <signature> <version>8.00.194</version> <servicepack>0</servicepack> </signature> - <signature> <version>8.00.190</version> <servicepack>Gold, no</servicepack> </signature> - <signature> <version>8.00.100</version> <servicepack>Beta 2</servicepack> </signature> - <signature> <version>8.00.078</version> <servicepack>EAP5</servicepack> </signature> - <signature> <version>8.00.047</version> <servicepack>EAP4</servicepack> </signature> </signatures> </root>

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值