Exemplo n.º 1
0
        static public bool IsCorrectUnpacker(ExeImageLoader exe, byte[] rawImg)
        {
            int offset = ExePackHeaderOffset(exe);

            return(MemoryArea.CompareArrays(rawImg, offset, signature, signature.Length) ||
                   MemoryArea.CompareArrays(rawImg, offset, signature2, signature2.Length));
        }
Exemplo n.º 2
0
 /// <summary>
 /// Peeks at the beginning of the image to determine if it's an XML file.
 /// </summary>
 /// <remarks>
 /// We do not attempt to handle UTF-8 encoded Unicode BOM characters.
 /// </remarks>
 /// <param name="image"></param>
 /// <returns></returns>
 private static bool IsXmlFile(byte[] image)
 {
     if (MemoryArea.CompareArrays(image, 0, new byte[] { 0x3C, 0x3F, 0x78, 0x6D, 0x6C }, 5)) // <?xml
     {
         return(true);
     }
     return(false);
 }
Exemplo n.º 3
0
        static public bool IsCorrectUnpacker(ExeImageLoader exe, byte [] rawImg)
        {
            if (exe.e_ovno != 0)
            {
                return(false);
            }

            return(MemoryArea.CompareArrays(rawImg, (int)signatureOffset, signature, signature.Length));
        }
Exemplo n.º 4
0
		// EXE header test (is it LZEXE file?) 

		static public bool IsCorrectUnpacker(ExeImageLoader exe, byte [] rawImg)
		{
			if (exe.e_ovno != 0 || exe.e_lfaRelocations != 0x1C)
				return false;

			int lzHdrOffset = ((int) exe.e_cparHeader + (int) exe.e_cs) << 4;
			int entry = lzHdrOffset + exe.e_ip;
			return (MemoryArea.CompareArrays(rawImg, entry, s_sig91, s_sig91.Length) ||
					MemoryArea.CompareArrays(rawImg, entry, s_sig90, s_sig90.Length));
		}
Exemplo n.º 5
0
        public ExePackLoader(IServiceProvider services, string filename, byte[] imgRaw)
            : base(services, filename, imgRaw)
        {
            var cfgSvc = services.RequireService <IConfigurationService>();

            arch     = cfgSvc.GetArchitecture("x86-real-16");
            platform = cfgSvc.GetEnvironment("ms-dos")
                       .Load(Services, arch);

            var exe = new ExeImageLoader(services, filename, imgRaw);

            this.exeHdrSize = (uint)(exe.e_cparHeader * 0x10U);
            this.hdrOffset  = (uint)(exe.e_cparHeader + exe.e_cs) * 0x10U;
            EndianImageReader rdr = new LeImageReader(RawImage, hdrOffset);

            this.ip = rdr.ReadLeUInt16();
            this.cs = rdr.ReadLeUInt16();
            rdr.ReadLeUInt16();
            this.cbExepackHeader = rdr.ReadLeUInt16();
            this.sp             = rdr.ReadLeUInt16();
            this.ss             = rdr.ReadLeUInt16();
            this.cpUncompressed = rdr.ReadLeUInt16();

            int offset = ExePackHeaderOffset(exe);

            if (MemoryArea.CompareArrays(imgRaw, offset, signature, signature.Length))
            {
                relocationsOffset = 0x012D;
            }
            else if (MemoryArea.CompareArrays(imgRaw, offset, signature2, signature2.Length))
            {
                relocationsOffset = 0x0125;
            }
            else
            {
                throw new ApplicationException("Not a recognized EXEPACK image.");
            }
        }
Exemplo n.º 6
0
        /// <summary>
        /// Given a <paramref name="program" /> returns a list of locations
        /// where patches need to be applied.
        /// </summary>
        /// <remarks>
        /// Scans through all loaded segments, looking for a LCALL instruction
        /// to the Keil sparse switch subroutine.
        /// </remarks>
        /// <param name="program"></param>
        /// <returns></returns>
        private IEnumerable <CodePatch> MakeSparseSwitchPatches(Program program)
        {
            const byte LCall_Opcode = 0x12;

            foreach (var seg in program.SegmentMap.Segments.Values)
            {
                var rdr = seg.MemoryArea.CreateBeReader(0);
                while (rdr.TryReadByte(out byte b))
                {
                    if (b != LCall_Opcode)
                    {
                        continue;
                    }
                    var addrCall = rdr.Address - 1;
                    if (!rdr.TryReadBeUInt16(out ushort uAddrSwitchSubroutine))
                    {
                        break;
                    }
                    var addrSwitchSubroutine = Address.Ptr16(uAddrSwitchSubroutine);
                    if (!program.SegmentMap.TryFindSegment(addrSwitchSubroutine, out var segment))
                    {
                        continue;
                    }
                    var mem    = segment.MemoryArea;
                    var offset = (int)(addrSwitchSubroutine - mem.BaseAddress);
                    if (!MemoryArea.CompareArrays(mem.Bytes, offset, sparseSwitchSubroutine, sparseSwitchSubroutine.Length))
                    {
                        continue;
                    }

                    // We found the sparse switch subroutine. Now we parse the sparse switch
                    // data.

                    var cluster = MakeCluster(addrCall, rdr);
                    yield return(new CodePatch(cluster));
                }
            }
        }
Exemplo n.º 7
0
        private void Validate(ExeImageLoader exe)
        {
            this.lzHdrOffset = (exe.e_cparHeader + exe.e_cs) << 4;

            // Locate the LzExe header and verify signature.

            byte[] abC = RawImage;
            int entry = lzHdrOffset + exe.e_ip;
            if (MemoryArea.CompareArrays(abC, entry, s_sig90, s_sig90.Length))
            {
                // Untested binary version
                isLz91 = false;
                throw new NotImplementedException("Untested");
            }
            else if (MemoryArea.CompareArrays(abC, entry, s_sig91, s_sig91.Length))
            {
                isLz91 = true;
            }
            else
            {
                throw new ApplicationException("Image is not an LzExe-compressed binary");
            }
        }
Exemplo n.º 8
0
        /// <summary>
        /// Tries to identify the main program of various MS-DOS compilers, and if
        /// successful, sets the DS register to the appropriate value.
        /// </summary>
        /// <returns></returns>
        public ImageSymbol FindMainAddress()
        {
            var     diagSvc = services.RequireService <IDiagnosticsService>();
            Address addrEntry;

            /* This function checks the startup code for various compilers' way of
             * loading DS. If found, it sets DS. This may not be needed in the future if
             * pushing and popping of registers is implemented.
             * Also sets prog.offMain and prog.segMain if possible */

            uint   startoff;
            uint   init;
            uint   i;
            ushort rel, para;
            char   chModel   = 'x';
            char   chVendor  = 'x';
            char   chVersion = 'x';

            char[] temp = new char[4];

            ImageSegment segment;

            prog.SegmentMap.TryFindSegment(start, out segment);
            var image    = segment.MemoryArea;
            var startOff = (uint)(start - image.BaseAddress);   // Offset into the Image of the initial CS:IP

            // Check the Turbo Pascal signatures first, since they involve only the
            // first 3 bytes, and false positives may be found with the others later
            if (locatePattern(image.Bytes,
                              startOff, startOff + 5, pattBorl4on, out i))
            {
                // The first 5 bytes are a far call. Follow that call and
                // determine the version from that */
                var addrNew = ReadSegPtr(image, startOff + 1);
                init = (uint)(addrNew - image.BaseAddress);
                if (locatePattern(image.Bytes, init, init + 26, pattBorl4Init, out i))
                {
                    setState("ds", image.ReadLeUInt16(i + 1));
                    Debug.Print("Borland Pascal v4 detected\n");
                    chVendor  = 't';                    /* Turbo */
                    chModel   = 'p';                    /* Pascal */
                    chVersion = '4';                    /* Version 4 */
                    addrEntry = start;                  /* Code starts immediately */
                                                        /* At the 5 byte jump */
                    goto gotVendor;                     /* Already have vendor */
                }
                else if (locatePattern(image.Bytes, init, init + 26, pattBorl5Init, out i))
                {
                    setState("ds", image.ReadLeUInt16(i + 1));
                    Debug.Print("Borland Pascal v5.0 detected");
                    chVendor  = 't';                    /* Turbo */
                    chModel   = 'p';                    /* Pascal */
                    chVersion = '5';                    /* Version 5 */
                    addrEntry = start;                  /* Code starts immediately */
                    goto gotVendor;                     /* Already have vendor */
                }
                else if (locatePattern(image.Bytes, init, init + 26, pattBorl7Init, out i))
                {
                    setState("ds", image.ReadLeUInt16(i + 1));
                    Debug.Print("Borland Pascal v7 detected");
                    chVendor  = 't';                    /* Turbo */
                    chModel   = 'p';                    /* Pascal */
                    chVersion = '7';                    /* Version 7 */
                    addrEntry = start;                  /* Code starts immediately */
                    goto gotVendor;                     /* Already have vendor */
                }
            }

            /* Search for the call to main pattern. This is compiler independant,
             *  but decides the model required. Note: must do the far data models
             *  (large and compact) before the others, since they are the same pattern
             *  as near data, just more pushes at the start. */
            if (image.Length > startOff + 0x180 + pattMainLarge.Length)
            {
                if (locatePattern(image.Bytes, startOff, startOff + 0x180, pattMainLarge, out i))
                {
                    addrEntry = ReadSegPtr(image, i + OFFMAINLARGE);
                    chModel   = 'l';                        /* Large model */
                }
                else if (locatePattern(image.Bytes, startOff, startOff + 0x180, pattMainCompact, out i))
                {
                    short srel = image.ReadLeInt16(i + OFFMAINCOMPACT);            /* This is the rel addr of main */
                    addrEntry = image.BaseAddress + i + OFFMAINCOMPACT + 2 + srel; /* Save absolute image offset */
                    chModel   = 'c';                                               /* Compact model */
                }
                else if (locatePattern(image.Bytes, startOff, startOff + 0x180, pattMainMedium,
                                       out i))
                {
                    addrEntry = ReadSegPtr(image, i + OFFMAINMEDIUM); /* This is abs off of main */
                    chModel   = 'm';                                  /* Medium model */
                }
                else if (locatePattern(image.Bytes, startOff, startOff + 0x180, pattMainSmall,
                                       out i))
                {
                    var srel = image.ReadLeInt16(i + OFFMAINSMALL);              /* This is rel addr of main */
                    addrEntry = image.BaseAddress + i + OFFMAINSMALL + 2 + srel; /* Save absolute image offset */
                    chModel   = 's';                                             /* Small model */
                }
                else if (MemoryArea.CompareArrays(image.Bytes, (int)startOff, pattTPasStart, pattTPasStart.Length))
                {
                    var srel = image.ReadLeInt16(startOff + 1); /* Get the jump offset */
                    addrEntry  = start + srel + 3;              /* Save absolute image offset */
                    addrEntry += 0x20;                          /* These first 32 bytes are setting up */
                    chVendor   = 't';                           /* Turbo.. */
                    chModel    = 'p';                           /* ...Pascal... (only 1 model) */
                    chVersion  = '3';                           /* 3.0 */
                    Debug.Print("Turbo Pascal 3.0 detected");
                    Debug.Print("Main at {0}", addrEntry);
                    goto gotVendor;                         /* Already have vendor */
                }
                else
                {
                    Debug.Print("Main could not be located!");
                    addrEntry = null;
                }
            }
            else
            {
                Debug.Print("Main could not be located!");
                addrEntry = null;
            }

            Debug.Print("Model: {0}", chModel);
            //prog.addressingMode = chModel;

            /* Now decide the compiler vendor and version number */
            if (MemoryArea.CompareArrays(image.Bytes, (int)startOff, pattMsC5Start, pattMsC5Start.Length))
            {
                /* Yes, this is Microsoft startup code. The DS is sitting right here
                 *  in the next 2 bytes */
                setState("ds", image.ReadLeUInt16((uint)(startOff + pattMsC5Start.Length)));
                chVendor  = 'm';                    /* Microsoft compiler */
                chVersion = '5';                    /* Version 5 */
                Debug.Print("MSC 5 detected");
            }

            /* The C8 startup pattern is different from C5's */
            else if (MemoryArea.CompareArrays(image.Bytes, (int)startOff, pattMsC8Start, pattMsC8Start.Length))
            {
                setState("ds", image.ReadLeUInt16((uint)(startOff + pattMsC8Start.Length)));
                chVendor  = 'm';                    /* Microsoft compiler */
                chVersion = '8';                    /* Version 8 */
                Debug.Print("MSC 8 detected");
            }

            /* The C8 .com startup pattern is different again! */
            else if (MemoryArea.CompareArrays(
                         image.Bytes,
                         (int)startOff,
                         pattMsC8ComStart,
                         pattMsC8ComStart.Length))
            {
                Debug.Print("MSC 8 .com detected");
                chVendor  = 'm';                    /* Microsoft compiler */
                chVersion = '8';                    /* Version 8 */
            }

            else if (locatePattern(image.Bytes, startOff, startOff + 0x30, pattBorl2Start,
                                   out i))
            {
                /* Borland startup. DS is at the second uint8_t (offset 1) */
                setState("ds", image.ReadLeUInt16(i + 1));
                Debug.Print("Borland v2 detected\n");
                chVendor  = 'b';                    /* Borland compiler */
                chVersion = '2';                    /* Version 2 */
            }

            else if (locatePattern(image.Bytes, startOff, startOff + 0x30, pattBorl3Start,
                                   out i))
            {
                /* Borland startup. DS is at the second uint8_t (offset 1) */
                setState("ds", image.ReadLeUInt16(i + 1));
                diagSvc.Inform("Borland C v3 runtime detected");
                chVendor  = 'b';                    /* Borland compiler */
                chVersion = '3';                    /* Version 3 */
            }

            else if (locatePattern(image.Bytes, startOff, startOff + 0x30, pattLogiStart,
                                   out i))
            {
                /* Logitech modula startup. DS is 0, despite appearances */
                Debug.Print("Logitech modula detected");
                chVendor  = 'l';                    /* Logitech compiler */
                chVersion = '1';                    /* Version 1 */
            }

            /* Other startup idioms would go here */
            else
            {
                Debug.Print("Warning - compiler not recognised");
                return(null);
            }

gotVendor:
            ;
            //sSigName = string.Format("dcc{0}{1}{2}.sig",
            //        chVendor, /* Add vendor */
            //        chVersion, /* Add version */
            //        chModel); /* Add model */
            //Debug.Print("Signature file: {0}", sSigName);
            return(new ImageSymbol(addrEntry)
            {
                Name = "main",
                ProcessorState = this.state,
                Type = SymbolType.Procedure,
            });
        }
Exemplo n.º 9
0
        /// <summary>
        /// Check this function to see if it is a library function. Return true if
        /// it is, and copy its name to pProc.Name
        /// </summary>
        public bool LibCheck(IServiceProvider services, Program program, Procedure proc, Address addr)
        {
            var diagSvc = services.RequireService<IDiagnosticsService>();
            long fileOffset;
            int h;
            // i, j, arg;
            uint Idx;

            if (false) //  && program.bSigs == false)
            {
                /* No signatures... can't rely on hash parameters to be initialised
                so always return false */
                return false;
            }

            ImageSegment segment;
            if (!program.SegmentMap.TryFindSegment(addr, out segment))
                return false;
            

            fileOffset = addr - segment.MemoryArea.BaseAddress;              /* Offset into the image */
            //if (fileOffset == program.offMain)
            //{
            //    /* Easy - this function is called main! */
            //    pProc.Name = "main";
            //    return false;
            //}

            byte[] pat = new byte[PATLEN];
            if (!segment.MemoryArea.TryReadBytes(fileOffset, PATLEN, pat))
                return false;

            fixWildCards(pat);                                   /* Fix wild cards in the copy */
            h = g_pattern_hasher.hash(pat);                      /* Hash the found proc */
                                                                 /* We always have to compare keys, because the hash function will always return a valid index */
            if (MemoryArea.CompareArrays(ht[h].htPat, 0, pat, PATLEN))
            {
#if NOT_YET
                /* We have a match. Save the name, if not already set */
                if (string.IsNullOrEmpty(pProc.Name))     /* Don't overwrite existing name */
                {
                    /* Give proc the new name */
                    pProc.Name = ht[h].htSym;
                }
                /* But is it a real library function? */
                i = NIL;
                if ((numFunc == 0) || (i = searchPList(ht[h].htSym)) != NIL)
                {
                    pProc.flg |= PROC_ISLIB;        /* It's a lib function */
                    pProc.callingConv(CConv::C);
                    if (i != NIL)
                    {
                        /* Allocate space for the arg struct, and copy the hlType to
                            the appropriate field */
                        arg = pFunc[i].firstArg;
                        pProc.args.numArgs = pFunc[i].numArg;
                        pProc.args.resize(pFunc[i].numArg);
                        for (j = 0; j < pFunc[i].numArg; j++)
                        {
                            pProc.args[j].type = pArg[arg++];
                        }
                        if (pFunc[i].typ != hlType.TYPE_UNKNOWN)
                        {
                            pProc.retVal.type = pFunc[i].typ;
                            pProc.flg |= PROC_IS_FUNC;
                            switch (pProc.retVal.type)
                            {
                            case hlType.TYPE_LONG_SIGN:
                            case hlType.TYPE_LONG_UNSIGN:
                                pProc.liveOut.setReg(rDX).addReg(rAX);
                                break;
                            case hlType.TYPE_WORD_SIGN:
                            case hlType.TYPE_WORD_UNSIGN:
                                pProc.liveOut.setReg(rAX);
                                break;
                            case hlType.TYPE_BYTE_SIGN:
                            case hlType.TYPE_BYTE_UNSIGN:
                                pProc.liveOut.setReg(rAL);
                                break;
                            case hlType.TYPE_STR:
                            case hlType.TYPE_PTR:
                                fprintf(stderr, "Warning assuming Large memory model\n");
                                pProc.liveOut.setReg(rAX).addReg(rDS);
                                break;
                            default:
                                diagSvc.Warn(string.Format("Unknown retval type {0} for {1} in LibCheck.",
                                           pProc.retVal.type,
                                           pProc.Name);
                                break;
                                /*** other types are not considered yet ***/
                            }
                        }
                        pProc.getFunctionType()->m_vararg = pFunc[i].bVararg;
                    }
                }
                else if (i == NIL)
                {
                    /* Have a symbol for it, but does not appear in a header file.
                        Treat it as if it is not a library function */
                    pProc.flg |= PROC_RUNTIME;      /* => is a runtime routine */
                }
#endif
            }
            if (locatePattern(segment.MemoryArea.Bytes, (uint) fileOffset,
                              (uint) (fileOffset + pattMsChkstk.Length),
                              pattMsChkstk, out Idx))
            {
                /* Found _chkstk */
                //pProc.Name = "chkstk";
                //pProc.flg |= PROC_ISLIB;        /* We'll say its a lib function */
                //pProc.args.numArgs = 0;     /* With no args */
            }

            return true;  // ((pProc.flg & PROC_ISLIB) != 0);
        }
Exemplo n.º 10
0
        bool DFS(int parentE, int v)
        {
            int e, w;

            // Depth first search of the graph, starting at vertex v, looking for
            // cycles. parent and v are origin 1. Note parent is an EDGE,
            // not a vertex

            visited[v] = true;

            // For each e incident with v ..
            for (e = graphFirst[v]; e != 0; e = graphNext[NumEntry + e])
            {
                byte[] key1;

                if (deleted[Math.Abs(e)])
                {
                    /* A deleted key. Just ignore it */
                    continue;
                }
                key1 = m_collector.getKey(Math.Abs(e) - 1);
                w    = graphNode[NumEntry + e];
                if (visited[w])
                {
                    /* Did we just come through this edge? If so, ignore it. */
                    if (Math.Abs(e) != Math.Abs(parentE))
                    {
                        /* There is a cycle in the graph. There is some subtle code here
                         *  to work around the distinct possibility that there may be
                         *  duplicate keys. Duplicate keys will always cause unit
                         *  cycles, since f1 and f2 (used to select v and w) will be the
                         *  same for both. The edges (representing an index into the
                         *  array of keys) are distinct, but the key values are not.
                         *  The logic is as follows: for the candidate edge e, check to
                         *  see if it terminates in the parent vertex. If so, we test
                         *  the keys associated with e and the parent, and if they are
                         *  the same, we can safely ignore e for the purposes of cycle
                         *  detection, since edge e adds nothing to the cycle. Cycles
                         *  involving v, w, and e0 will still be found. The parent
                         *  edge was not similarly eliminated because at the time when
                         *  it was a candidate, v was not yet visited.
                         *  We still have to remove the key from further consideration,
                         *  since each edge is visited twice, but with a different
                         *  parent edge each time.
                         */
                        /* We save some stack space by calculating the parent vertex
                         *  for these relatively few cases where it is needed */
                        int parentV = graphNode[NumEntry - parentE];

                        if (w == parentV)
                        {
                            byte[] key2;

                            key2 = m_collector.getKey(Math.Abs(parentE) - 1);
                            if (MemoryArea.CompareArrays(key1, 0, key2, EntryLen))
                            {
                                Debug.Print("Duplicate keys with edges {0} and {1} (",
                                            e, parentE);
                                m_collector.dispKey(Math.Abs(e) - 1);
                                Debug.Print(" & ");
                                m_collector.dispKey(Math.Abs(parentE) - 1);
                                Debug.Print(")\n");
                                deleted[Math.Abs(e)] = true;      /* Wipe the key */
                            }
                            else
                            {
                                /* A genuine (unit) cycle. */
                                Debug.Print("There is a unit cycle involving vertex %d and edge %d\n", v, e);
                                return(true);
                            }
                        }
                        else
                        {
                            // We have reached a previously visited vertex not the
                            // parent. Therefore, we have uncovered a genuine cycle
                            Debug.Print("There is a cycle involving vertex {0} and edge {1}", v, e);
                            return(true);
                        }
                    }
                }
                else                                // Not yet seen. Traverse it
                {
                    if (DFS(e, w))
                    {
                        // Cycle found deeper down. Exit
                        return(true);
                    }
                }
            }
            return(false);
        }