Beispiel #1
0
        protected override object checkCctor(ref TypeDefinition type, MethodDefinition cctor)
        {
            var instrs = cctor.Body.Instructions;

            for (int i = 0; i < instrs.Count - 1; i++)
            {
                var ldci4 = instrs[i];
                if (!DotNetUtils.isLdcI4(ldci4))
                {
                    continue;
                }

                var call = instrs[i + 1];
                if (call.OpCode.Code != Code.Call)
                {
                    continue;
                }
                if (call.Operand != info.initMethod)
                {
                    continue;
                }

                int offset = DotNetUtils.getLdcI4Value(ldci4);
                reader.BaseStream.Position = offset;
                int rid = DeobUtils.readVariableLengthInt32(reader);
                if (rid != type.MetadataToken.RID)
                {
                    throw new ApplicationException("Invalid RID");
                }
                return(string.Empty);                   // It's non-null
            }
            return(null);
        }
Beispiel #2
0
        void decryptStrings(uint[] key)
        {
            var data = stringDataField.InitialValue;

            var encryptedData = new uint[data.Length / 4];

            Buffer.BlockCopy(data, 0, encryptedData, 0, data.Length);
            DeobUtils.xxteaDecrypt(encryptedData, key);
            var decryptedData = new byte[data.Length];

            Buffer.BlockCopy(encryptedData, 0, decryptedData, 0, data.Length);

            var inflated       = DeobUtils.inflate(decryptedData, 0, decryptedData.Length, true);
            var reader         = new BinaryReader(new MemoryStream(inflated));
            int deflatedLength = DeobUtils.readVariableLengthInt32(reader);
            int numStrings     = DeobUtils.readVariableLengthInt32(reader);

            decryptedStrings = new string[numStrings];
            var offsets = new int[numStrings];

            for (int i = 0; i < numStrings; i++)
            {
                offsets[i] = DeobUtils.readVariableLengthInt32(reader);
            }
            int startOffset = (int)reader.BaseStream.Position;

            for (int i = 0; i < numStrings; i++)
            {
                reader.BaseStream.Position = startOffset + offsets[i];
                decryptedStrings[i]        = reader.ReadString();
            }
        }
        public string decrypt(int token, int id)
        {
            if (!CanDecrypt)
            {
                throw new ApplicationException("Can't decrypt strings since decryptedData is null");
            }

            int index = id - (token & 0x00FFFFFF) - stringOffset;
            int len   = DeobUtils.readVariableLengthInt32(decryptedData, ref index);

            switch (StringDecrypterInfo.DecrypterVersion)
            {
            case StringDecrypterVersion.V1:
                // Some weird problem with 1.x decrypted strings. They all have a \x01 char at the end.
                var buf = Convert.FromBase64String(Encoding.ASCII.GetString(decryptedData, index, len));
                if (buf.Length % 2 != 0)
                {
                    Array.Resize(ref buf, buf.Length - 1);
                }
                return(Encoding.Unicode.GetString(buf));

            case StringDecrypterVersion.V2:
                return(Encoding.UTF8.GetString(Convert.FromBase64String(Encoding.ASCII.GetString(decryptedData, index, len))));

            default:
                return(Encoding.UTF8.GetString(Convert.FromBase64String(Encoding.UTF8.GetString(decryptedData, index, len))));
            }
        }
Beispiel #4
0
        void decryptStrings()
        {
            uint usHeapRva  = peHeader.getRva1(0x0E00, mcKey.readUInt32(0x0078));
            uint usHeapSize = peHeader.readUInt32(0x0E04) ^ mcKey.readUInt32(0x0082);

            if (usHeapRva == 0 || usHeapSize == 0)
            {
                return;
            }
            var usHeap = peImage.Cor20Header.metadata.getStream("#US");

            if (usHeap == null ||
                peImage.rvaToOffset(usHeapRva) != usHeap.fileOffset ||
                usHeapSize != usHeap.Length)
            {
                Log.w("Invalid #US heap RVA and size found");
            }

            Log.v("Decrypting strings @ RVA {0:X8}, {1} bytes", usHeapRva, usHeapSize);
            Log.indent();

            int mcKeyOffset  = 0;
            int usHeapOffset = (int)peImage.rvaToOffset(usHeapRva);
            int usHeapEnd    = usHeapOffset + (int)usHeapSize;

            usHeapOffset++;
            while (usHeapOffset < usHeapEnd)
            {
                if (fileData[usHeapOffset] == 0 || fileData[usHeapOffset] == 1)
                {
                    usHeapOffset++;
                    continue;
                }

                int usHeapOffsetOrig   = usHeapOffset;
                int stringDataLength   = DeobUtils.readVariableLengthInt32(fileData, ref usHeapOffset);
                int usHeapOffsetString = usHeapOffset;
                int encryptedLength    = stringDataLength - (usHeapOffset - usHeapOffsetOrig == 1 ? 1 : 2);
                for (int i = 0; i < encryptedLength; i++)
                {
                    byte k = mcKey.readByte(mcKeyOffset++ % 0x2000);
                    fileData[usHeapOffset] = rolb((byte)(fileData[usHeapOffset] ^ k), 3);
                    usHeapOffset++;
                }

                try {
                    Log.v("Decrypted string: {0}", Utils.toCsharpString(Encoding.Unicode.GetString(fileData, usHeapOffsetString, stringDataLength - 1)));
                }
                catch {
                    Log.v("Could not decrypt string at offset {0:X8}", usHeapOffsetOrig);
                }

                usHeapOffset++;
            }

            Log.deIndent();
        }
Beispiel #5
0
        byte[] findMethodsData(PeImage peImage, byte[] fileData)
        {
            var section = peImage.Sections[0];

            var reader = new BinaryReader(new MemoryStream(fileData));

            const int RVA_EXECUTIVE_OFFSET = 1 * 4;
            const int ENC_CODE_OFFSET      = 6 * 4;
            int       lastOffset           = (int)(section.pointerToRawData + section.sizeOfRawData);

            for (int offset = getStartOffset(peImage); offset < lastOffset;)
            {
                offset = findSig(fileData, offset, lastOffset, initializeMethodEnd);
                if (offset < 0)
                {
                    return(null);
                }
                offset += initializeMethodEnd.Length;

                short retImm16 = BitConverter.ToInt16(fileData, offset);
                if (retImm16 != 0x0C && retImm16 != 0x10)
                {
                    continue;
                }
                offset += 2;
                if (offset + ENC_CODE_OFFSET + 4 > lastOffset)
                {
                    return(null);
                }

                // rva is 0 when the assembly has been embedded
                int rva = BitConverter.ToInt32(fileData, offset + RVA_EXECUTIVE_OFFSET);
                if (rva != 0 && mainType.Rvas.IndexOf(rva) < 0)
                {
                    continue;
                }

                int relOffs = BitConverter.ToInt32(fileData, offset + ENC_CODE_OFFSET);
                if (relOffs <= 0 || relOffs >= section.sizeOfRawData)
                {
                    continue;
                }
                reader.BaseStream.Position = section.pointerToRawData + relOffs;

                int size      = DeobUtils.readVariableLengthInt32(reader);
                int endOffset = relOffs + size;
                if (endOffset < relOffs || endOffset > section.sizeOfRawData)
                {
                    continue;
                }

                return(reader.ReadBytes(size));
            }

            return(null);
        }
Beispiel #6
0
        protected override void getCallInfo(object context, FieldDefinition field, out MethodReference calledMethod, out OpCode callOpcode)
        {
            byte flags = reader.ReadByte();

            int methodToken      = 0x06000000 + ((flags & 0x3F) << 24) + DeobUtils.readVariableLengthInt32(reader);
            int genericTypeToken = (flags & 0x40) == 0 ? -1 : 0x1B000000 + DeobUtils.readVariableLengthInt32(reader);

            callOpcode = (flags & 0x80) != 0 ? OpCodes.Callvirt : OpCodes.Call;

            calledMethod = module.LookupToken(methodToken) as MethodReference;
            if (calledMethod == null)
            {
                throw new ApplicationException("Could not find method");
            }
            if (genericTypeToken != -1 && calledMethod.DeclaringType.MetadataToken.ToInt32() != genericTypeToken)
            {
                throw new ApplicationException("Invalid declaring type token");
            }
        }
Beispiel #7
0
            public virtual bool decrypt(BinaryReader fileDataReader, DumpedMethod dm)
            {
                if (fileDataReader.ReadByte() != 0x2A)
                {
                    return(false);                      // Not a RET
                }
                int methodsDataOffset = DeobUtils.readVariableLengthInt32(fileDataReader);

                methodsDataReader.BaseStream.Position = methodsDataOffset;

                dm.mhCodeSize = (uint)DeobUtils.readVariableLengthInt32(methodsDataReader);
                dm.code       = methodsDataReader.ReadBytes((int)dm.mhCodeSize);
                if ((dm.mhFlags & 8) != 0)
                {
                    dm.extraSections = readExtraSections(methodsDataReader);
                }

                if (!decryptCode(dm))
                {
                    return(false);
                }

                return(true);
            }
Beispiel #8
0
        public string decrypt(int index)
        {
            int len = DeobUtils.readVariableLengthInt32(decryptedData, ref index);

            return(Encoding.Unicode.GetString(decryptedData, index, len));
        }
Beispiel #9
0
 public int readVariableLengthInt32()
 {
     return(DeobUtils.readVariableLengthInt32(reader));
 }
Beispiel #10
0
        void decryptStrings()
        {
            var peHeader = decrypterInfo.peHeader;
            var mcKey    = decrypterInfo.mcKey;
            var peImage  = decrypterInfo.peImage;
            var fileData = decrypterInfo.fileData;

            uint usHeapRva  = peHeader.getRva(0x0E00, mcKey.readUInt32(0x0078));
            uint usHeapSize = peHeader.readUInt32(0x0E04) ^ mcKey.readUInt32(0x0082);

            if (usHeapRva == 0 || usHeapSize == 0)
            {
                return;
            }
            var usHeap = peImage.DotNetFile.MetaData.USStream;

            if (usHeap.StartOffset == 0 ||              // Start offset is 0 if it's not present in the file
                peImage.rvaToOffset(usHeapRva) != (uint)usHeap.StartOffset ||
                usHeapSize != (uint)(usHeap.EndOffset - usHeap.StartOffset))
            {
                Logger.w("Invalid #US heap RVA and size found");
            }

            Logger.v("Decrypting strings @ RVA {0:X8}, {1} bytes", usHeapRva, usHeapSize);
            Logger.Instance.indent();

            int mcKeyOffset  = 0;
            int usHeapOffset = (int)peImage.rvaToOffset(usHeapRva);
            int usHeapEnd    = usHeapOffset + (int)usHeapSize;

            usHeapOffset++;
            while (usHeapOffset < usHeapEnd)
            {
                if (fileData[usHeapOffset] == 0 || fileData[usHeapOffset] == 1)
                {
                    usHeapOffset++;
                    continue;
                }

                int usHeapOffsetOrig   = usHeapOffset;
                int stringDataLength   = DeobUtils.readVariableLengthInt32(fileData, ref usHeapOffset);
                int usHeapOffsetString = usHeapOffset;
                int encryptedLength    = stringDataLength - (usHeapOffset - usHeapOffsetOrig == 1 ? 1 : 2);
                for (int i = 0; i < encryptedLength; i++)
                {
                    byte k = mcKey.readByte(mcKeyOffset++ % 0x2000);
                    fileData[usHeapOffset] = rolb((byte)(fileData[usHeapOffset] ^ k), 3);
                    usHeapOffset++;
                }

                try {
                    Logger.v("Decrypted string: {0}", Utils.toCsharpString(Encoding.Unicode.GetString(fileData, usHeapOffsetString, stringDataLength - 1)));
                }
                catch {
                    Logger.v("Could not decrypt string at offset {0:X8}", usHeapOffsetOrig);
                }

                usHeapOffset++;
            }

            Logger.Instance.deIndent();
        }