예제 #1
0
        private static bool IsOpCodeCorrect(byte[] data, int off, Config cfg)
        {
            CmdID id = (CmdID)data[off];

            // check invalid opcodes
            if (!CmdEncoding.DEC_TABLE.ContainsKey(id))
            {
                return(false);
            }

            // check improbable opcodes
            if (cfg.ImprobableOpCodes.Contains(id))
            {
                return(false);
            }

            var patterns = cfg.Patterns.FindAll(p => p.ID == id);

            if (patterns.Count == 0)
            {
                return(true);
            }
            foreach (var pattern in patterns)
            {
                if (pattern.Check(data, off))
                {
                    return(true);
                }
            }

            return(false);
        }
예제 #2
0
        private void DecodeDlist(Memory mem, uint addr, int depth)
        {
            if (depth >= _maxDepth)
            {
                return;
            }

            for (int size = 0; ; size += 8)
            {
                CmdID id = (CmdID)mem.ReadBytes(addr + (uint)size, 1)[0];

                if (id == CmdID.G_DL || id == CmdID.G_ENDDL)
                {
                    var cmds = Command.CmdEncoding.DecodeCmds(mem.ReadBytes(addr, size + 8), 0);

                    // append previous command to the list and increment address
                    cmds.ForEach(cmd => { _cmds.Add(new CommandHolder(addr, depth, cmd)); addr += (uint)cmd.GetSize(); });

                    if (id == CmdID.G_DL)
                    {
                        var gdl = cmds[^ 1].Convert <GDl>();
예제 #3
0
        public static List <string> AnalyzeDlists(Z64Object obj, byte[] data, int segmentId)
        {
            List <string> errors = new List <string>();

            List <int> dlists = new List <int>();

            for (int i = 0; i < obj.Entries.Count; i++)
            {
                var entry = obj.Entries[i];
                if (entry.GetEntryType() == Z64Object.EntryType.DList)
                {
                    dlists.Add(obj.OffsetOf(entry));
                }
                else
                {
                    obj.Entries[i] = new Z64Object.UnknowHolder($"unk_{obj.OffsetOf(entry):X8}", entry.GetData());
                }
            }

            foreach (var dlist in dlists)
            {
                uint     lastTexAddr              = 0xFFFFFFFF;
                G_IM_FMT lastFmt                  = (G_IM_FMT)(-1);
                G_IM_SIZ lastSiz                  = (G_IM_SIZ)(-1);
                Z64Object.TextureHolder lastTlut  = null;
                Z64Object.TextureHolder lastCiTex = null;

                bool exit = false;
                for (int i = dlist; i < data.Length && !exit; i += 8)
                {
                    CmdID op = (CmdID)data[i];
                    switch (op)
                    {
                    case CmdID.G_QUAD:
                    case CmdID.G_TRI2:
                    case CmdID.G_TRI1:
                    case CmdID.G_TEXRECTFLIP:
                    case CmdID.G_TEXRECT:
                    {
                        if (lastCiTex != null && lastTlut != null)
                        {
                            lastCiTex.Tlut = lastTlut;
                            lastCiTex      = null;
                        }
                        break;
                    }

                    case CmdID.G_ENDDL:
                    {
                        exit = true;
                        break;
                    }

                    case CmdID.G_MTX:
                    {
                        var gmtx = CmdInfo.DecodeCommand <GMtx>(data, i);
                        var addr = new SegmentedAddress(gmtx.mtxaddr);
                        if (addr.Segmented && addr.SegmentId == segmentId)
                        {
                            obj.AddMtx(1, off: (int)addr.SegmentOff);
                        }
                        break;
                    }

                    case CmdID.G_VTX:
                    {
                        var gvtx = CmdInfo.DecodeCommand <GVtx>(data, i);

                        var addr = new SegmentedAddress(gvtx.vaddr);
                        if (addr.Segmented && addr.SegmentId == segmentId)
                        {
                            try
                            {
                                obj.AddVertices(gvtx.numv, off: (int)addr.SegmentOff);
                            }
                            catch (Exception ex)
                            {
                                errors.Add($"Error in Dlist 0x{new SegmentedAddress(segmentId, dlist).VAddr:X8} : {ex.Message}");
                            }
                        }
                        break;
                    }

                    case CmdID.G_SETTIMG:
                    {
                        var settimg = CmdInfo.DecodeCommand <GSetTImg>(data, i);
                        lastTexAddr = settimg.imgaddr;
                        break;
                    }

                    case CmdID.G_SETTILE:
                    {
                        var settile = CmdInfo.DecodeCommand <GSetTile>(data, i);
                        if (settile.tile != G_TX_TILE.G_TX_LOADTILE)
                        {
                            lastFmt = settile.fmt;
                            lastSiz = settile.siz;
                        }
                        break;
                    }

                    case CmdID.G_SETTILESIZE:
                    {
                        var settilesize = CmdInfo.DecodeCommand <GLoadTile>(data, i);
                        var addr        = new SegmentedAddress(lastTexAddr);

                        if ((int)lastFmt == -1 || (int)lastSiz == -1 || lastTexAddr == 0xFFFFFFFF)
                        {
                            /* can't really thow an exception here since in some object files, there are two gsDPSetTileSize next to each other (see object_en_warp_uzu) */
                            //throw new Z64ObjectAnalyzerException();
                            break;
                        }

                        if (addr.Segmented && addr.SegmentId == segmentId)
                        {
                            try
                            {
                                var tex = obj.AddTexture((int)(settilesize.lrs.Float() + 1), (int)(settilesize.lrt.Float() + 1), N64Texture.ConvertFormat(lastFmt, lastSiz), off: (int)addr.SegmentOff);
                                if (lastFmt == G_IM_FMT.G_IM_FMT_CI)
                                {
                                    lastCiTex = tex;
                                }
                            }
                            catch (Exception ex)
                            {
                                errors.Add($"Error in Dlist 0x{new SegmentedAddress(segmentId, dlist).VAddr:X8} : {ex.Message}");
                            }
                        }

                        lastFmt     = (G_IM_FMT)(-1);
                        lastSiz     = (G_IM_SIZ)(-1);
                        lastTexAddr = 0xFFFFFFFF;

                        break;
                    }

                    case CmdID.G_LOADTLUT:
                    {
                        var loadtlut = CmdInfo.DecodeCommand <GLoadTlut>(data, i);
                        var addr     = new SegmentedAddress(lastTexAddr);

                        if (lastTexAddr == 0xFFFFFFFF)
                        {
                            throw new Z64ObjectAnalyzerException();
                        }

                        int w = GetTlutWidth(loadtlut.count + 1);
                        if (addr.Segmented && addr.SegmentId == segmentId)
                        {
                            try
                            {
                                lastTlut = obj.AddTexture(w, (loadtlut.count + 1) / w, N64Texture.ConvertFormat(G_IM_FMT.G_IM_FMT_RGBA, G_IM_SIZ.G_IM_SIZ_16b), off: (int)addr.SegmentOff);
                            }
                            catch (Exception ex)
                            {
                                errors.Add($"Error in Dlist 0x{new SegmentedAddress(segmentId, dlist).VAddr:X8} : {ex.Message}");
                            }
                        }

                        break;
                    }
                    }
                }
            }

            // These are carried out here as they are dependent on a lot of heuristics.
            // Having lots of the object already mapped out reduces possible mis-identifications.
            FindSkeletons(obj, data, segmentId);
            FindAnimations(obj, data, segmentId);

            obj.GroupUnkEntries();
            obj.FixNames();
            obj.SetData(data);

            return(errors);
        }
예제 #4
0
        private static Tuple <List <int>, List <ReservedRegion> > FindRegions(byte[] data, int segmentId, Config cfg)
        {
            List <ReservedRegion> regions = new List <ReservedRegion>();
            List <int>            dlists  = new List <int>();

            var codeEnds = Utils.FindData(data, new byte[] { (byte)CmdID.G_ENDDL, 0, 0, 0, 0, 0, 0, 0, }, 8);

            codeEnds.Insert(0, 0);
            for (int i = 1; i < codeEnds.Count; i++)
            {
                int  end    = codeEnds[i];
                int  texels = -1;
                uint half1  = 0xFFFFFFFF;

                for (int off = end; off >= codeEnds[i - 1] + 8; off -= 8)
                {
                    CmdID op = (CmdID)data[off];

                    if (IsOverlap(off, regions) || !IsOpCodeCorrect(data, off, cfg))
                    {
                        break;
                    }

                    switch (op)
                    {
                    case CmdID.G_RDPHALF_1:
                    {
                        half1 = CmdInfo.DecodeCommand <GRdpHalf>(data, off).word;
                        break;
                    }

                    case CmdID.G_BRANCH_Z:
                    {
                        AddDlist(dlists, segmentId, half1, data.Length);
                        break;
                    }

                    case CmdID.G_DL:
                    {
                        var gdl = CmdInfo.DecodeCommand <GDl>(data, off);
                        AddDlist(dlists, segmentId, gdl.dl, data.Length);
                        break;
                    }

                    case CmdID.G_VTX:
                    {
                        var gmtx = CmdInfo.DecodeCommand <GVtx>(data, off);
                        AddRegion(regions, segmentId, gmtx.vaddr, gmtx.numv * 0x10, data.Length);
                        break;
                    }

                    case CmdID.G_SETTIMG:
                    {
                        var settimg = CmdInfo.DecodeCommand <GSetTImg>(data, off);
                        if (texels == -1)
                        {
                            break;
                        }
                        AddRegion(regions, segmentId, settimg.imgaddr, N64Texture.GetTexSize(texels, settimg.siz), data.Length);
                        texels = -1;
                        break;
                    }

                    case CmdID.G_LOADBLOCK:
                    {
                        var loadblock = CmdInfo.DecodeCommand <GLoadBlock>(data, off);
                        texels = loadblock.texels + 1;
                        break;
                    }

                    case CmdID.G_LOADTLUT:
                    {
                        var loadtlut = CmdInfo.DecodeCommand <GLoadTlut>(data, off);
                        texels = loadtlut.count + 1;
                        break;
                    }

                    default:
                        break;
                    }
                }
            }
            return(new Tuple <List <int>, List <ReservedRegion> >(dlists, regions));
        }
예제 #5
0
        // splits an SMTP command into command and argument(s)
        internal List<string> ParseCmdLine(CmdID id, string cmdLine)
        {
            List<string> parts = new List<string>();
            if (string.IsNullOrEmpty(cmdLine)) return parts;
            try
            {
                string cmdStr = CmdList[(int)id];
                string curCmd = CleanupString(cmdLine);

                int pos = -1;
                pos = cmdLine.IndexOf(cmdStr.Contains(':') ? ':' : ' ');
                if (-1 != pos)
                {
                    string cmd = CleanupString(cmdLine.Substring(0, pos));
                    string arg = CleanupString(cmdLine.Substring(pos + 1));
                    parts.Add(cmd.ToUpper());
                    parts.Add(arg);
                }
                else
                    parts.Add(CleanupString(cmdLine).ToUpper());
            }
            catch
            {
                parts = new List<string>();
            }

            return parts;
        }
예제 #6
0
        public void HandleSession()
        {
            string cmdLine = "?";
            Context context = new Context { Session = this };
            Processor.Context = context;
            CommandOk commandOk = new CommandOk();
            string response = commandOk.GetResponse();
            CmdID currCmd = CmdID.Invalid;
            bool connOk = true;

            if (false == _initOk)
            {
                CloseSession();
                return;
            }

            // sessions limit reached, reject session
            if (_sessCount > AppGlobals.MaxSessions)
            {
                if (connOk) SendLine(Resources.MSG_421_ServiceTemporarilyUnavailable);
                CloseSession();
                return;
            }

            // if the remote IP isn't a private one
            if (!IsPrivateIP(ClientIP))
            {
                // checks the incoming IP against whitelists, if listed skip blacklist checks
                bool isDnsListed = IsListed(ClientIP, AppGlobals.WhiteLists, "white");
                if (!isDnsListed)
                {
                    // check the IP against blacklists
                    isDnsListed = IsListed(ClientIP, AppGlobals.BlackLists, "black");
                    if ((isDnsListed) && (!AppGlobals.StoreData))
                    {
                        // if blacklisted and NOT storing messages
                        SendLine(string.Format(Resources.MSG_442_ConnectionTimedOut, ClientIP, DNSListName));
                        CloseSession();
                        return;
                    }
                }
            }

            // add a short delay before banner and check for early talker
            // see http://wiki.asrg.sp.am/wiki/Early_talker_detection
            SleepDown(AppGlobals.BannerDelay);
            _earlyTalker = IsEarlyTalker();
            if (_earlyTalker)
            {
                SendLine(Resources.MSG_554_MisbehavedSMTPSession);
                CloseSession();
                return;
            }

            // all ok, send out our banner
            CommandBanner commandBanner = new CommandBanner { Context = context };
            connOk = SendLine(commandBanner.GetResponse());
            while ((null != cmdLine) && connOk)
            {
                if (LastCmd == CmdID.Data)
                {
                    string mailMsg = RecvData();
                    if (_timedOut)
                    {
                        // got a receive timeout during the DATA phase
                        if (connOk) SendLine(Resources.MSG_442_ConnectionTimedOut);
                        CloseSession();
                        return;
                    }
                    CommandDot commandDot = new CommandDot { Context = context };
                    response = commandDot.GetResponse();
                    if (String.IsNullOrEmpty(mailMsg))
                        response = Resources.MSG_422_MailboxExceededQuota;
                    else
                    {
                        Processor.Process(mailMsg);
                        if (AppGlobals.DoTempFail)
                        {
                            // emit a tempfail AFTER storing the mail DATA
                            if (connOk) SendLine(Resources.MSG_421_ServiceTemporarilyUnavailable);
                            CloseSession();
                            return;
                        }
                    }
                    ResetSession();
                }
                else
                {
                    // read an SMTP command line and deal with the command
                    cmdLine = RecvLine();
                    if (null != cmdLine)
                    {
                        LogCmdAndResp(DIR_RX, cmdLine);
                        currCmd = GetCommandID(cmdLine);
                        context.CmdLine = cmdLine;

                        switch (currCmd)
                        {
                            case CmdID.Helo:            // HELO
                                CommandHelo commandHelo = new CommandHelo { Context = context };
                                response = commandHelo.GetResponse();
                                break;
                            case CmdID.Ehlo:            // EHLO
                                CommandHelo commandEhlo = new CommandHelo { Context = context };
                                response = commandEhlo.GetResponse();
                                break;
                            case CmdID.MailFrom:        // MAIL FROM:
                                CommandMailFrom commandMailFrom = new CommandMailFrom { Context = context };
                                response = commandMailFrom.GetResponse();
                                break;
                            case CmdID.RcptTo:          // RCPT TO:
                                CommandRcptTo commandRcptTo = new CommandRcptTo { Context = context };
                                response = commandRcptTo.GetResponse();
                                break;
                            case CmdID.Data:            // DATA
                                if ((AppGlobals.DoTempFail) && (!AppGlobals.StoreData))
                                {
                                    // emit a tempfail upon receiving the DATA command
                                    response = Resources.MSG_421_ServiceTemporarilyUnavailable;
                                    cmdLine = null;
                                    LastCmd = currCmd = CmdID.Quit;
                                }
                                else
                                {
                                    CommandData commandData = new CommandData { Context = context };
                                    response = commandData.GetResponse();
                                }
                                break;
                            case CmdID.Rset:            // RSET
                                CommandRset commandRset = new CommandRset { Context = context };
                                response = commandRset.GetResponse();
                                break;
                            case CmdID.Quit:            // QUIT
                                CommandQuit commandQuit = new CommandQuit { Context = context };
                                response = commandQuit.GetResponse();
                                cmdLine = null; // force closing
                                break;
                            case CmdID.Vrfy:            // VRFY
                                CommandVrfy commandVrfy = new CommandVrfy { Context = context };
                                response = commandVrfy.GetResponse();
                                break;
                            case CmdID.Expn:            // EXPN
                                CommandVrfy commandExpn = new CommandVrfy { Context = context };
                                response = commandExpn.GetResponse();
                                break;
                            case CmdID.Help:            // HELP
                                CommandHelp commandHelp = new CommandHelp { Context = context };
                                response = commandHelp.GetResponse();
                                break;
                            case CmdID.Noop:            // NOOP
                                CommandNoop commandNoop = new CommandNoop { Context = context };
                                response = commandNoop.GetResponse();
                                break;
                            default:                    // unkown/unsupported
                                CommandUnknown commandUnknown = new CommandUnknown { Context = context };
                                response = commandUnknown.GetResponse();
                                break;
                        }
                    }
                    else
                    {
                        // the read timed out (or we got an error), emit a message and drop the connection
                        response = Resources.MSG_442_ConnectionTimedOut;
                        currCmd = CmdID.Quit;
                    }
                }

                // send response
                if ((ErrCount > 0) && (CmdID.Quit != currCmd))
                {
                    // tarpit a bad client, time increases with error count
                    SleepDown(AppGlobals.ErrorDelay * ErrCount);
                }
                else
                {
                    // add a short delay
                    SleepDown(25);
                }

                // checks for early talkers
                _earlyTalker = IsEarlyTalker();

                // send out the response
                connOk = SendLine(response);

                // check/enforce hard limits (errors, vrfy ...)
                if ((CmdID.Quit != currCmd) && (connOk))
                {
                    string errMsg = null;
                    if (MsgCount > AppGlobals.MaxMessages)
                    {
                        // above max # of message in a single session
                        errMsg = Resources.MSG_451_SessionMessagesCountExceeded;
                    }
                    else if (ErrCount > AppGlobals.MaxSmtpErr)
                    {
                        // too many errors
                        errMsg = Resources.MSG_550_MaxErrors;
                    }
                    else if (VrfyCount > AppGlobals.MaxSmtpVrfy)
                    {
                        // tried to VRFY/EXPN too many addresses
                        errMsg = Resources.MSG_451_MaxRecipients;
                    }
                    else if (NoopCount > AppGlobals.MaxSmtpNoop)
                    {
                        // entered too many NOOP commands
                        errMsg = Resources.MSG_451_MaxNoop;
                    }
                    else if (RcptTo.Count > AppGlobals.MaxSmtpRcpt)
                    {
                        // too many recipients for a single message
                        errMsg = Resources.MSG_452_TooManyRecipients;
                    }
                    else if (_earlyTalker)
                    {
                        // early talker
                        errMsg = Resources.MSG_554_MisbehavedSMTPSession;
                    }
                    if (null != errMsg)
                    {
                        if (connOk) connOk = SendLine(errMsg);
                        cmdLine = null; // force closing
                    }
                }

                // check if connection Ok
                if (connOk) connOk = _client.Connected;
            } // while null...

            // close/reset this session
            CloseSession();
        }
예제 #7
0
 public CmdAttribute(CmdID id)
 {
     this.id = id;
 }
예제 #8
0
 public CmdInfo(CmdID id, Dictionary <string, object> args)
 {
     ID   = id;
     Args = args;
 }