代码之家  ›  专栏  ›  技术社区  ›  izb

如何在AVM2字节码中找到方法?

  •  5
  • izb  · 技术社区  · 15 年前

    package
    {
         import flash.display.MovieClip;     
         import flash.events.Event;
    
         public class RedCircle extends MovieClip
         {
              public function RedCircle()
              {
                   this.addEventListener(Event.ENTER_FRAME, moveit);
              }
    
              function moveit(e:Event)
              {
                   this.x -=1;
              }
         }
    }
    

    它可以编译成:

    protected package protected RedCircle
    {
        class RedCircle extends flash.display.MovieClip
        {
            static () : Void
            {
                getlocal_0();
                pushscope();
                returnvoid();
            }
    
    
    
            RedCircle () : Void
            {
                getlocal_0();
                pushscope();
                getlocal_0();
                constructsuper(0);
                getlocal_0();
                getlex(flash.events.Event);
                getproperty(ENTER_FRAME);
                getlex(internal .moveit);       // ###1
                callpropvoid(addEventListener, 2);
                returnvoid();
            }
    
    
    
            function (anonymous) (flash.events.Event param1) : Void // ###2
            {
                getlocal_0();
                pushscope();
                getlocal_0();
                getlocal_0();
                getproperty(x);
                decrement();
                setproperty(x);
                returnvoid();
            }
        }
    }
    

    我的问题是“getlex”操作是如何工作的(我已经用#####1标记了它)。它被传递一个多名称,该多名称引用类的“moveit”方法。不幸的是,方法信息中的“name”字段似乎从来没有被编译器使用过。所有方法的名称都是空字符串(上面显示的是位于#####2的未命名函数)。

    flash播放器如何将多名称链接到未命名的方法?AVM2规范中似乎没有这方面的规定。

    我知道这是可能的,因为像sothink这样的商业反编译器能够确定方法名。我只是不确定他们是怎么做的,或者代码是怎么工作的。

    3 回复  |  直到 15 年前
        1
  •  5
  •   Joony s3rro    15 年前

    我不知道你的反编译程序为什么显示这个方法为(匿名的)。

    这里是abcData的一个转储:

    abcFile{
    minor_version (17): 16
    major_version (19): 46
    constant_pool{
        int_count (21): 0
            [0]: zero (not included in abcFile)
        uint_count (22): 0
            [0]: zero (not included in abcFile)
        double_count (23): 0
            [0]: NaN (not included in abcFile)
        string_count (24): 17
            string_info[0]{
                name: * (not included in abcFile)
            }
            string_info[1]{
                size (25): 12
                name (26): "flash.events"
            }
            string_info[2]{
                size (38): 5
                name (39): "Event"
            }
            string_info[3]{
                size (44): 0
                name (45): ""
            }
            string_info[4]{
                size (45): 9
                name (46): "RedCircle"
            }
            string_info[5]{
                size (55): 13
                name (56): "flash.display"
            }
            string_info[6]{
                size (69): 9
                name (70): "MovieClip"
            }
            string_info[7]{
                size (79): 6
                name (80): "moveit"
            }
            string_info[8]{
                size (86): 11
                name (87): "ENTER_FRAME"
            }
            string_info[9]{
                size (98): 16
                name (99): "addEventListener"
            }
            string_info[10]{
                size (115): 1
                name (116): "x"
            }
            string_info[11]{
                size (117): 6
                name (118): "Object"
            }
            string_info[12]{
                size (124): 15
                name (125): "EventDispatcher"
            }
            string_info[13]{
                size (140): 13
                name (141): "DisplayObject"
            }
            string_info[14]{
                size (154): 17
                name (155): "InteractiveObject"
            }
            string_info[15]{
                size (172): 22
                name (173): "DisplayObjectContainer"
            }
            string_info[16]{
                size (195): 6
                name (196): "Sprite"
            }
            namespace_count (202): 6
                namespace_info[0]{
                    kind: * (not included in abcFile)
                }
                namespace_info[1]{
                    kind (203): CONSTANT_PackageNamespace
                    name (204): 1
                }
                namespace_info[2]{
                    kind (205): CONSTANT_PackageNamespace
                    name (206): 3
                }
                namespace_info[3]{
                    kind (207): CONSTANT_PackageNamespace
                    name (208): 5
                }
                namespace_info[4]{
                    kind (209): CONSTANT_ProtectedNamespace
                    name (210): 4
                }
                namespace_info[5]{
                    kind (211): CONSTANT_PackageInternalNs
                    name (212): 3
                }
            ns_set_count (213): 0
                ns_set_info[0]{
                    ns: 0 (not included in abcFile)
                }
            multiname_count (214): 14
                multiname_info[0]{
                    kind: 0 (not included in abcFile)
                }
                multiname_info[1]{
                    kind (216): CONSTANT_QName
                    multiname_kind_QNAME{
                        ns (216): 1
                        name (217): 2 ("Event")
                    }
                }
                multiname_info[2]{
                    kind (219): CONSTANT_QName
                    multiname_kind_QNAME{
                        ns (219): 2
                        name (220): 4 ("RedCircle")
                    }
                }
                multiname_info[3]{
                    kind (222): CONSTANT_QName
                    multiname_kind_QNAME{
                        ns (222): 3
                        name (223): 6 ("MovieClip")
                    }
                }
                multiname_info[4]{
                    kind (225): CONSTANT_QName
                    multiname_kind_QNAME{
                        ns (225): 5
                        name (226): 7 ("moveit")
                    }
                }
                multiname_info[5]{
                    kind (228): CONSTANT_QName
                    multiname_kind_QNAME{
                        ns (228): 2
                        name (229): 8 ("ENTER_FRAME")
                    }
                }
                multiname_info[6]{
                    kind (231): CONSTANT_QName
                    multiname_kind_QNAME{
                        ns (231): 2
                        name (232): 9 ("addEventListener")
                    }
                }
                multiname_info[7]{
                    kind (234): CONSTANT_QName
                    multiname_kind_QNAME{
                        ns (234): 2
                        name (235): 10 ("x")
                    }
                }
                multiname_info[8]{
                    kind (237): CONSTANT_QName
                    multiname_kind_QNAME{
                        ns (237): 2
                        name (238): 11 ("Object")
                    }
                }
                multiname_info[9]{
                    kind (240): CONSTANT_QName
                    multiname_kind_QNAME{
                        ns (240): 1
                        name (241): 12 ("EventDispatcher")
                    }
                }
                multiname_info[10]{
                    kind (243): CONSTANT_QName
                    multiname_kind_QNAME{
                        ns (243): 3
                        name (244): 13 ("DisplayObject")
                    }
                }
                multiname_info[11]{
                    kind (246): CONSTANT_QName
                    multiname_kind_QNAME{
                        ns (246): 3
                        name (247): 14 ("InteractiveObject")
                    }
                }
                multiname_info[12]{
                    kind (249): CONSTANT_QName
                    multiname_kind_QNAME{
                        ns (249): 3
                        name (250): 15 ("DisplayObjectContainer")
                    }
                }
                multiname_info[13]{
                    kind (252): CONSTANT_QName
                    multiname_kind_QNAME{
                        ns (252): 3
                        name (253): 16 ("Sprite")
                    }
                }
        }
        method_count (254): 4
            method_info[0]{
                param_count (255): 0
                return_type (256): 0
                name (257): 0
                flags (258): 0
                    NEED_ARGUMENTS (0x01): false
                    NEED_ACTIVATION (0x02): false
                    NEED_REST (0x04): false
                    HAS_OPTIONAL (0x08): false
                    SET_DXNS (0x40): false
                    HAS_PARAM_NAMES (0x80): false
            }
            method_info[1]{
                param_count (259): 0
                return_type (260): 0
                name (261): 0
                flags (262): 0
                    NEED_ARGUMENTS (0x01): false
                    NEED_ACTIVATION (0x02): false
                    NEED_REST (0x04): false
                    HAS_OPTIONAL (0x08): false
                    SET_DXNS (0x40): false
                    HAS_PARAM_NAMES (0x80): false
            }
            method_info[2]{
                param_count (263): 1
                return_type (264): 0
                param_type[0] (265): 1
                name (266): 0
                flags (267): 0
                    NEED_ARGUMENTS (0x01): false
                    NEED_ACTIVATION (0x02): false
                    NEED_REST (0x04): false
                    HAS_OPTIONAL (0x08): false
                    SET_DXNS (0x40): false
                    HAS_PARAM_NAMES (0x80): false
            }
            method_info[3]{
                param_count (268): 0
                return_type (269): 0
                name (270): 0
                flags (271): 0
                    NEED_ARGUMENTS (0x01): false
                    NEED_ACTIVATION (0x02): false
                    NEED_REST (0x04): false
                    HAS_OPTIONAL (0x08): false
                    SET_DXNS (0x40): false
                    HAS_PARAM_NAMES (0x80): false
            }
        metadata_count (272): 0
        class_count (273): 1
            instance_info[0]{
                name (274): 2 (RedCircle)
                super_name (275): 3 (MovieClip)
                flags (276): 9
                    CONSTANT_ClassSealed (0x01): true
                    CONSTANT_ClassFinal (0x02): false
                    CONSTANT_ClassInterface (0x04): false
                    CONSTANT_ClassProtectedNs (0x08): true
                protectedNs (277): 4
                intrf_count (278): 0
                iinit (279): 1
                trait_count (280): 1
                    traits_info[0]{
                        name (281): 4 (moveit)
                        kind (282): Trait_Method
                        ATTR_Final (0x1): false
                        ATTR_Override (0x2): false
                        ATTR_Metadata (0x4): false
                        trait_method{
                            disp_id (283): 0
                            method (284): 2
                        }
                    }
            }
            class_info[0]{
                cinit (285): 0
                trait_count (286): 0
            }
        script_count (287): 1
            init (288): 3
                trait_count (289): 1
                    traits_info[0]{
                        name (290): 2 (RedCircle)
                        kind (291): Trait_Class
                        ATTR_Metadata (0x4): false
                        trait_class{
                            slot_id (292): 1
                            classi (293): 0
                        }
                    }
        method_body_count (294): 4
            method_body_info[0]{
                method (295): 0
                max_stack (296): 1
                local_count (297): 1
                init_scope_depth (298): 9
                max_scope_depth (299): 10
                code_length (300): 3
                    208 0xD0 (301) getlocal_0
                    48 0x30 (302) pushscope
                    71 0x47 (303) returnvoid
    
                exception_count (304): 0
                trait_count (305): 0
            }
            method_body_info[1]{
                method (306): 1
                max_stack (307): 3
                local_count (308): 1
                init_scope_depth (309): 10
                max_scope_depth (310): 11
                code_length (311): 17
                    208 0xD0 (312) getlocal_0
                    48 0x30 (313) pushscope
                    208 0xD0 (314) getlocal_0
                    73 0x49 (315) constructsuper
                        arg_count: 0
                    208 0xD0 (317) getlocal_0
                    96 0x60 (318) getlex
                        index: 1 (Event)
                    102 0x66 (320) getproperty
                        index: 5 (ENTER_FRAME)
                    208 0xD0 (322) getlocal_0
                    102 0x66 (323) getproperty
                        index: 4 (moveit)
                    79 0x4F (325) callpropvoid
                        index: 6 (addEventListener)
                        arg_count: 2
                    71 0x47 (328) returnvoid
    
                exception_count (329): 0
                trait_count (330): 0
            }
            method_body_info[2]{
                method (331): 2
                max_stack (332): 3
                local_count (333): 2
                init_scope_depth (334): 10
                max_scope_depth (335): 11
                code_length (336): 10
                    208 0xD0 (337) getlocal_0
                    48 0x30 (338) pushscope
                    208 0xD0 (339) getlocal_0
                    208 0xD0 (340) getlocal_0
                    102 0x66 (341) getproperty
                        index: 7
                    147 0x93 (343) decrement
                    97 0x61 (344) setproperty
                        index: 7
                    71 0x47 (346) returnvoid
    
                exception_count (347): 0
                trait_count (348): 0
            }
            method_body_info[3]{
                method (349): 3
                max_stack (350): 2
                local_count (351): 1
                init_scope_depth (352): 1
                max_scope_depth (353): 9
                code_length (354): 39
                    208 0xD0 (355) getlocal_0
                    48 0x30 (356) pushscope
                    101 0x65 (357) getscopeobject
                        index: 0
                    96 0x60 (359) getlex
                        index: 8
                    48 0x30 (361) pushscope
                    96 0x60 (362) getlex
                        index: 9
                    48 0x30 (364) pushscope
                    96 0x60 (365) getlex
                        index: 10
                    48 0x30 (367) pushscope
                    96 0x60 (368) getlex
                        index: 11
                    48 0x30 (370) pushscope
                    96 0x60 (371) getlex
                        index: 12
                    48 0x30 (373) pushscope
                    96 0x60 (374) getlex
                        index: 13
                    48 0x30 (376) pushscope
                    96 0x60 (377) getlex
                        index: 3
                    48 0x30 (379) pushscope
                    96 0x60 (380) getlex
                        index: 3
                    88 0x58 (382) newclass
                        index: 0
                    29 0x1D (384) popscope
                    29 0x1D (385) popscope
                    29 0x1D (386) popscope
                    29 0x1D (387) popscope
                    29 0x1D (388) popscope
                    29 0x1D (389) popscope
                    29 0x1D (390) popscope
                    104 0x68 (391) initproperty
                        index: 2
                    71 0x47 (393) returnvoid
    
                exception_count (394): 0
                trait_count (395): 0
            }
     }
    

    你感兴趣的是实例信息[0]。这是类的运行时实例的定义,在这里是红圈。实例具有各种类型的特性。RedCircle有一个trait(moveit)类型trait_Method,这意味着该trait引用了一个方法(2)。

    因此,如果您跳到方法_body_info[1](RedCircle的构造函数),您可以在字节323处看到getProperty是用索引4调用的。

    102 0x66 (323) getproperty
                       index: 4 (moveit)
    

    multiname_info[4]{
        kind (225): CONSTANT_QName
        multiname_kind_QNAME{
            ns (225): 5
            name (226): 7 ("moveit")
        }
    }
    

    当调用该方法时,它会在实例的traits中查找名称索引。

    traits_info[0]{
        name (281): 4 (moveit)
        kind (282): Trait_Method
        ATTR_Final (0x1): false
        ATTR_Override (0x2): false
        ATTR_Metadata (0x4): false
        trait_method{
            disp_id (283): 0
            method (284): 2
        }
    }
    

    然后调用相关方法。

    method_info[2]{
        param_count (263): 1
        return_type (264): 0
        param_type[0] (265): 1
        name (266): 0
        flags (267): 0
            NEED_ARGUMENTS (0x01): false
            NEED_ACTIVATION (0x02): false
            NEED_REST (0x04): false
            HAS_OPTIONAL (0x08): false
            SET_DXNS (0x40): false
            HAS_PARAM_NAMES (0x80): false
    }
    
    method_body_info[2]{
        method (331): 2
        max_stack (332): 3
        local_count (333): 2
        init_scope_depth (334): 10
        max_scope_depth (335): 11
        code_length (336): 10
            208 0xD0 (337) getlocal_0
            48 0x30 (338) pushscope
            208 0xD0 (339) getlocal_0
            208 0xD0 (340) getlocal_0
            102 0x66 (341) getproperty
                               index: 7 (x)
            147 0x93 (343) decrement
            97 0x61 (344) setproperty
                               index: 7 (x)
            71 0x47 (346) returnvoid
        exception_count (347): 0
        trait_count (348): 0
    }
    

    有点简单的答案,但我希望它能澄清一些问题。

        2
  •  0
  •   www0z0k    15 年前

    package com.codeazur.as3abc.factories
        public function create(code:int):AbstractOperation
            switch (code) {//in real life this switch block is really huge
                 case Opcodes.GetLex:    return new MultinameOperation(code);
            }
    

    以及:

    package com.codeazur.as3abc.data.bytecode
    public class Opcodes
    
    public static const GetLex:uint = 0x60;
    _opNames[ GetLex ] = "GetLex";
    

    所以据我所知,它只是AVM2中的一个关键字。关于你的问题:我想在这里:

    getlex(flash.events.Event);
    getproperty(输入帧);
    getlex(内部移动);


    我们可以看到一种添加事件侦听器的方式(或者我只是疯了),还有一件事要提:你的前一个 moveit 函数是唯一接受 Event
    and here's a link to some avm2 bytecode from adobe

        3
  •  0
  •   izb    15 年前

    结果发现,方法名是存储在类traits中的多个名称;我在string表中而不是在多个名称表中查找traits名称这一事实使问题更加复杂。哎呀。

    不过,方法名字段在ABC文件中似乎是多余的。