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); }
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>();
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); }
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)); }
// 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; }
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(); }
public CmdAttribute(CmdID id) { this.id = id; }
public CmdInfo(CmdID id, Dictionary <string, object> args) { ID = id; Args = args; }