Example #1
0
        private Field[] ReadFields(ulong count, BinaryReader reader, Dictionary <uint, List <Annotation> > annotations)
        {
            var   fields            = new Field[count];
            long  position          = 0;
            ulong currentFieldIndex = 0;

            for (ulong index = 0; index < count; index++)
            {
                currentFieldIndex += Leb128.ReadUleb(reader);
                var accessFlags = Leb128.ReadUleb(reader);

                position = reader.BaseStream.Position;

                var field = Dex.GetField((uint)currentFieldIndex);
                field.AccessFlags = (AccessFlag)accessFlags;

                List <Annotation> annotation = null;
                annotations.TryGetValue((uint)currentFieldIndex, out annotation);
                if (annotation != null)
                {
                    field.Annotations = annotation;
                }

                fields[index] = field;

                reader.BaseStream.Position = position;
            }

            return(fields);
        }
Example #2
0
        internal EncodedArray(BinaryReader reader)
        {
            Count         = Leb128.ReadUleb(reader);
            EncodedValues = new EncodedValue[Count];

            for (ulong i = 0; i < Count; i++)
            {
                EncodedValues[i] = EncodedValue.parse(reader);
            }
        }
Example #3
0
        public EncodedAnnotation(BinaryReader reader)
        {
            AnnotationType = Leb128.ReadUleb(reader);
            var size = Leb128.ReadUleb(reader);

            Elements = new AnnotationElement[size];

            for (ulong i = 0; i < size; i++)
            {
                Elements[i] = new AnnotationElement(reader);
            }
        }
Example #4
0
        private Method[] ReadMethods(ulong count, BinaryReader reader, Dictionary <uint, List <Annotation> > annotations, Dictionary <uint, List <Annotation> > parameterAnnotations)
        {
            var   methods            = new Method[count];
            long  position           = 0;
            ulong currentMethodIndex = 0;

            for (ulong currentMethod = 0; currentMethod < count; currentMethod++)
            {
                currentMethodIndex += Leb128.ReadUleb(reader);
                var accessFlags = Leb128.ReadUleb(reader);
                var codeOffset  = (uint)Leb128.ReadUleb(reader);

                position = reader.BaseStream.Position;

                var method = Dex.GetMethod((uint)currentMethodIndex, codeOffset);
                method.AccessFlags = accessFlags;

                List <Annotation> annotation = null;
                annotations.TryGetValue((uint)currentMethodIndex, out annotation);
                if (annotation != null)
                {
                    method.Annotations = annotation;
                }

                List <Annotation> parameterAnnotation = null;
                parameterAnnotations.TryGetValue((uint)currentMethodIndex, out parameterAnnotation);
                if (parameterAnnotation != null)
                {
                    method.ParameterAnnotations = parameterAnnotation;
                }

                methods[currentMethod] = method;

                reader.BaseStream.Position = position;
            }

            return(methods);
        }
Example #5
0
        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name='dex'>
        /// Pointer to the DEX file this class was loaded from
        /// </param>
        internal Class(Dex dex, BinaryReader reader)
        {
            Dex = dex;

            ClassIndex      = reader.ReadUInt32();
            AccessFlags     = (AccessFlag)reader.ReadUInt32();
            SuperClassIndex = reader.ReadUInt32();
            var interfacesOffset = reader.ReadUInt32();

            SourceFileIndex = reader.ReadUInt32();
            var annotationsOffset  = reader.ReadUInt32();
            var classDataOffset    = reader.ReadUInt32();
            var staticValuesOffset = reader.ReadUInt32();

            Interfaces = dex.ReadTypeList(interfacesOffset);

            var fieldAnnotations     = new Dictionary <uint, List <Annotation> >();
            var methodAnnotations    = new Dictionary <uint, List <Annotation> >();
            var parameterAnnotations = new Dictionary <uint, List <Annotation> >();

            if (annotationsOffset != 0)
            {
                reader.BaseStream.Position = annotationsOffset;

                // annotations_directory_item
                var classAnnotationsOffset   = reader.ReadUInt32();
                var annotatedFieldsCount     = reader.ReadUInt32();
                var annotatedMethodsCount    = reader.ReadUInt32();
                var annotatedParametersCount = reader.ReadUInt32();

                for (int i = 0; i < annotatedFieldsCount; i++)
                {
                    // field_annotation
                    var fieldIndex  = reader.ReadUInt32();
                    var annotations = Annotation.ReadAnnotations(reader);
                    fieldAnnotations.Add(fieldIndex, annotations);
                }

                for (int i = 0; i < annotatedMethodsCount; i++)
                {
                    // method_annotation
                    var methodIndex = reader.ReadUInt32();
                    var annotations = Annotation.ReadAnnotations(reader);
                    methodAnnotations.Add(methodIndex, annotations);
                }

                for (int i = 0; i < annotatedParametersCount; i++)
                {
                    // parameter_annotation
                    var methodIndex = reader.ReadUInt32();
                    var annotations = Annotation.ReadAnnotations(reader);
                    parameterAnnotations.Add(methodIndex, annotations);
                }

                if (classAnnotationsOffset > 0)
                {
                    reader.BaseStream.Position = classAnnotationsOffset;
                    Annotations = Annotation.ReadAnnotationSetItem(reader);
                }
            }

            if (classDataOffset != 0)
            {
                reader.BaseStream.Position = classDataOffset;

                var staticFieldsCount   = Leb128.ReadUleb(reader);
                var instanceFieldsCount = Leb128.ReadUleb(reader);
                var directMethodsCount  = Leb128.ReadUleb(reader);
                var virtualMethodsCount = Leb128.ReadUleb(reader);

                StaticFields   = ReadFields(staticFieldsCount, reader, fieldAnnotations);
                InstanceFields = ReadFields(instanceFieldsCount, reader, fieldAnnotations);
                DirectMethods  = ReadMethods(directMethodsCount, reader, methodAnnotations, parameterAnnotations);
                VirtualMethods = ReadMethods(virtualMethodsCount, reader, methodAnnotations, parameterAnnotations);
            }
            else
            {
                StaticFields   = new Field[0];
                InstanceFields = new Field[0];
                DirectMethods  = new Method[0];
                VirtualMethods = new Method[0];
            }

            if (staticValuesOffset != 0)
            {
                reader.BaseStream.Position = staticValuesOffset;

                var size   = Leb128.ReadUleb(reader);
                var values = new EncodedValue[size];

                for (int i = 0; i < (int)size; i++)
                {
                    values[i] = EncodedValue.parse(reader);
                }

                StaticFieldsValues = values;
            }
            else
            {
                StaticFieldsValues = new EncodedValue[0];
            }
        }
Example #6
0
        /// <summary>
        /// Read a string at the specified offset in the DEX file. The layout of a String is:
        ///     length: length of the decoded UTF16 string
        ///     data: string encoded in MUTF8 ending in a \0
        /// </summary>
        /// <returns>
        /// The string
        /// </returns>
        /// <param name='offset'>
        /// Offset of the string from the beginning of the file
        /// </param>
        /// <param name='reader'>
        /// stream reader to parse values from the Dex file
        /// </param>
        private string ReadString(uint offset, BinaryReader reader)
        {
            reader.BaseStream.Position = offset;

            // find out the length of the decoded string
            var stringLength = (int)Leb128.ReadUleb(reader);

            // strings are encoded in MUTF-8 format
            char[] chararr = new char[stringLength];
            int    c, char2, char3;
            int    chararr_count = 0;

            while (chararr_count < stringLength)
            {
                c = reader.ReadByte();

                switch (c >> 4)
                {
                /* 0xxxxxxx */
                case 0:
                case 1:
                case 2:
                case 3:
                case 4:
                case 5:
                case 6:
                case 7:
                    chararr[chararr_count++] = (char)c;
                    break;

                /* 110x xxxx || 10xx xxxx */
                case 12:
                case 13:
                    char2 = reader.ReadByte();
                    if ((char2 & 0xC0) != 0x80)
                    {
                        throw new InvalidDataException("MUTF-8 parsing error. 2nd byte must be 10xxxxxx. Dex offset:" + (DexStream.Position - 2));
                    }
                    chararr[chararr_count++] = (char)(((c & 0x1F) << 6) | (char2 & 0x3F));
                    break;

                /* 1110 xxxx || 10xx xxxx || 10xx xxxx */
                case 14:
                    char2 = reader.ReadByte();
                    char3 = reader.ReadByte();
                    if (((char2 & 0xC0) ^ (char3 & 0xC0)) != 0)
                    {
                        throw new InvalidDataException("MUTF-8 parsing error. Both bytes must be 10xxxxxx. Dex offset:" + (DexStream.Position - 3));
                    }
                    chararr[chararr_count++] = (char)(((c & 0x0F) << 12) |
                                                      ((char2 & 0x3F) << 6) |
                                                      ((char3 & 0x3F) << 0));
                    break;

                default:
                    throw new InvalidDataException("Invalid MUTF-8 encoding. Dex offset: " + (DexStream.Position - 1));
                }
            }

            // The number of chars produced may be less than utflen
            return(new string(chararr, 0, chararr_count));
        }
Example #7
0
        internal Method(uint id, Dex dex, BinaryReader reader, uint codeOffset)
        {
            Id  = id;
            Dex = dex;

            ClassIndex     = reader.ReadUInt16();
            PrototypeIndex = reader.ReadUInt16();
            NameIndex      = reader.ReadUInt32();

            Annotations          = new Annotation[0];
            ParameterAnnotations = new List <Annotation>();

            // This method has no opcodes, must be abstract or native.
            // Or the method is being loaded directly from the methods list
            if (codeOffset != 0)
            {
                reader.BaseStream.Position = codeOffset;

                RegistersSize    = reader.ReadUInt16();
                ArgumentsSize    = reader.ReadUInt16();
                ReturnValuesSize = reader.ReadUInt16();
                var numberOfTryItems = reader.ReadUInt16();
                // Not parsing debug info
                /*var debugInfoOffset =*/ reader.ReadUInt32();
                CodeLength = reader.ReadUInt32();

                CodeOffset = reader.BaseStream.Position;

                // Skip the opcode block
                reader.BaseStream.Position += CodeLength * 2;

                // Skip the optional padding
                if ((numberOfTryItems != 0) && (CodeLength % 2 != 0))
                {
                    reader.BaseStream.Position += 2;
                }

                // Load the try blocks
                if (numberOfTryItems != 0)
                {
                    TryCatchBlocks = new TryCatchBlock[numberOfTryItems];
                    var handlerOffsets = new long[numberOfTryItems];

                    // read Try
                    for (int i = 0; i < numberOfTryItems; i++)
                    {
                        var tryCatch = new TryCatchBlock(CodeOffset);
                        tryCatch.StartAddress     = reader.ReadUInt32();
                        tryCatch.InstructionCount = reader.ReadUInt16();

                        TryCatchBlocks [i] = tryCatch;

                        handlerOffsets[i] = reader.ReadUInt16();
                    }

                    var encodedCatchHandlerListOffset = reader.BaseStream.Position;
                    // Size of the list, could be used to confirm the DEX is properly
                    // built. For this purpose will assume DEX files are always good
                    Leb128.ReadUleb(reader);

                    // read Catch blocks
                    for (int i = 0; i < numberOfTryItems; i++)
                    {
                        //encoded_catch_handler
                        if (handlerOffsets [i] > 0)
                        {
                            reader.BaseStream.Position = encodedCatchHandlerListOffset + handlerOffsets [i];

                            var handlersCount = Leb128.ReadLeb(reader);
                            var handlers      = new CatchHandler[handlersCount <= 0 ? Math.Abs(handlersCount) + 1 : handlersCount];

                            for (int j = 0; j < Math.Abs(handlersCount); j++)
                            {
                                var catchHandler = new CatchHandler(CodeOffset);
                                catchHandler.TypeIndex = Leb128.ReadUleb(reader);
                                catchHandler.Address   = Leb128.ReadUleb(reader);

                                handlers [j] = catchHandler;
                            }

                            // parse the catch all block
                            if (handlersCount <= 0)
                            {
                                var catchHandler = new CatchHandler(CodeOffset);
                                catchHandler.TypeIndex = 0;
                                catchHandler.Address   = Leb128.ReadUleb(reader);

                                handlers [handlers.Length - 1] = catchHandler;
                            }

                            TryCatchBlocks [i].Handlers = handlers;
                        }
                    }
                }
            }
        }
Example #8
0
 public AnnotationElement(BinaryReader reader)
 {
     NameIdx = (uint)Leb128.ReadUleb(reader);
     Value   = EncodedValue.parse(reader);
 }