Example #1
0
        private void listBox_SelectedIndexChanged(object sender, System.EventArgs e)
        {
            // TODO: check if player is allowed to inject
            // TODO: get informations about hack
            HackStatus iHackStatus   = (HackStatus)listBox.SelectedIndex;
            bool       bEnableInject = false;
            DateTime   dtExpiresOn   = DateTime.Now;

            dtExpiresOn = dtExpiresOn.AddMinutes(listBox.SelectedIndex);
            // TODO:

            lblExpiresOnValue.Text      = dtExpiresOn.ToShortDateString() + ' ' + dtExpiresOn.ToShortTimeString();
            lblExpiresOnValue.ForeColor = dtExpiresOn > DateTime.Now ? System.Drawing.Color.Green : System.Drawing.Color.Red;

            switch (iHackStatus)
            {
            case HackStatus.Unknown:
                lblStatusValue.Text      = "Unknown";
                lblStatusValue.ForeColor = System.Drawing.Color.Orange;
                bEnableInject            = true;
                break;

            case HackStatus.Updating:
                lblStatusValue.Text      = "Updating";
                lblStatusValue.ForeColor = System.Drawing.Color.Red;
                bEnableInject            = false;
                break;

            case HackStatus.Undetected:
                lblStatusValue.Text      = "Undetected";
                lblStatusValue.ForeColor = System.Drawing.Color.Green;
                bEnableInject            = true;
                break;
            }

            btnInject.Enabled = bEnableInject;
        }
Example #2
0
        private async Task HandleSingleHackAsync(IEnumerable <ActorInfo> actors, HackStatus hack, JudgeStatus judge, Problem problem, Guid?testCaseId, CancellationToken token)
        {
            var sub       = new SubJudgeStatus();
            var isBadData = false;

            if (actors.Count(x => x.Name == "CompareActor") == 0)
            {
                var rangeValidateActor = actors.FirstOrDefault(x => x.Stage == "ValidateData");
                var rangeRunner        = rangeValidateActor == null ? null : await _mgmt.ReadBlobAsObjectAsync <Runner>(rangeValidateActor.Outputs.Single(x => x.Name == "runner.json").Id, token);

                var runActor  = actors.FirstOrDefault(x => x.Stage == "GenerateHackeeAnswer");
                var runRunner = runActor == null ? null : await _mgmt.ReadBlobAsObjectAsync <Runner>(runActor.Outputs.Single(x => x.Name == "runner.json").Id, token);

                if (rangeRunner != null && rangeRunner.ExitCode != 0)
                {
                    isBadData            = true;
                    sub.TimeUsedInMs     = 0;
                    sub.MemoryUsedInByte = 0;
                    sub.Result           = JudgeResult.Accepted;
                    sub.Hint             = string.Join(Environment.NewLine, rangeValidateActor.Exceptions) + Environment.NewLine + rangeRunner.Error;
                }
                else if (runRunner.IsTimeout)
                {
                    sub.TimeUsedInMs     = problem.TimeLimitationPerCaseInMs;
                    sub.MemoryUsedInByte = runRunner.PeakMemory;
                    sub.Result           = JudgeResult.TimeExceeded;
                    sub.Hint             = string.Join(Environment.NewLine, runActor.Exceptions) + Environment.NewLine + runRunner.Error;
                }
                else if (runRunner.ExitCode == 139 || runActor.Exceptions.Any(x => x.Contains("May cause by out of memory")) || runRunner.Error.Contains("std::bad_alloc") || runRunner.PeakMemory > problem.MemoryLimitationPerCaseInByte)
                {
                    sub.TimeUsedInMs     = runRunner.UserTime;
                    sub.MemoryUsedInByte = problem.MemoryLimitationPerCaseInByte;
                    sub.Result           = JudgeResult.MemoryExceeded;
                    sub.Hint             = string.Join(Environment.NewLine, runActor.Exceptions) + Environment.NewLine + runRunner.Error;
                }
                else if (runRunner.ExitCode != 0)
                {
                    sub.TimeUsedInMs     = runRunner.UserTime;
                    sub.MemoryUsedInByte = runRunner.PeakMemory;
                    sub.Result           = JudgeResult.RuntimeError;
                    sub.Hint             = string.Join(Environment.NewLine, runActor.Exceptions) + Environment.NewLine + runRunner.Error + Environment.NewLine + $"User process exited with code { runRunner.ExitCode }";
                }
            }
            else if (actors.Count(x => x.Name == "CompareActor") > 0)
            {
                var runners       = actors.Where(x => x.Name == "CompareActor").Select(x => x.Outputs.Single(y => y.Name == "runner.json"));
                var runnerResults = runners.Select(x => _mgmt.ReadBlobAsObjectAsync <Runner>(x.Id, token).Result);
                var exitCodes     = runnerResults.Select(x => x.ExitCode);
                if (exitCodes.Distinct().Count() > 1)
                {
                    isBadData = true;
                }
                else
                {
                    var runActor  = actors.First(x => x.Stage == "GenerateHackeeAnswer");
                    var runRunner = await _mgmt.ReadBlobAsObjectAsync <Runner>(runActor.Outputs.Single(x => x.Name == "runner.json").Id, token);

                    var compareActor = actors.Last(x => x.Name == "CompareActor");
                    var runner       = await _mgmt.ReadBlobAsObjectAsync <Runner>(compareActor.Outputs.Single(x => x.Name == "runner.json").Id, token);

                    if (runner.ExitCode < 0 || runner.ExitCode > 2)
                    {
                        sub.TimeUsedInMs     = 0;
                        sub.MemoryUsedInByte = 0;
                        sub.Result           = JudgeResult.SystemError;
                        sub.Hint             = string.Join(Environment.NewLine, runActor.Exceptions) + Environment.NewLine + runner.Error;
                    }
                    else
                    {
                        var validatorOutput = Encoding.UTF8.GetString((await _mgmt.GetBlobAsync(compareActor.Outputs.Single(x => x.Name == "stdout.txt").Id)).Body);
                        sub.TimeUsedInMs     = runRunner.UserTime;
                        sub.MemoryUsedInByte = runRunner.PeakMemory;
                        sub.Result           = (JudgeResult)runner.ExitCode;
                        sub.Hint             = validatorOutput + Environment.NewLine + string.Join(Environment.NewLine, runActor.Exceptions) + Environment.NewLine + runner.Error;
                    }
                }
            }
            else
            {
                isBadData = true;
            }

            if (hack == null && actors.Count(x => x.Stage == "GenerateHackeeAnswer") > 0 && testCaseId.HasValue)
            {
                var runActor = actors.First(x => x.Stage == "GenerateHackeeAnswer");
                var statusId = Guid.Parse(runActor.Tag);
                var testCase = await _db.TestCases.SingleAsync(x => x.Id == testCaseId.Value, token);

                var testCases = await _db.TestCases
                                .Where(x => x.ProblemId == problem.Id)
                                .Select(x => x.Id)
                                .ToListAsync(token);

                var status = await _db.JudgeStatuses
                             .Include(x => x.SubStatuses)
                             .SingleAsync(x => x.Id == statusId, token);

                sub.StatusId     = statusId;
                sub.TestCaseId   = testCaseId.Value;
                sub.InputBlobId  = testCase.InputBlobId;
                sub.OutputBlobId = testCase.OutputBlobId;
                sub.SubId        = testCases.IndexOf(testCaseId.Value);
                status.SubStatuses.Add(sub);
                status.MemoryUsedInByte = status.SubStatuses.Max(x => x.MemoryUsedInByte);
                status.TimeUsedInMs     = status.SubStatuses.Sum(x => x.TimeUsedInMs);
                status.Result           = status.SubStatuses.Max(x => x.Result);
                _db.SaveChanges();
            }

            if (hack != null)
            {
                _db.HackStatuses
                .Where(x => x.Id == hack.Id)
                .SetField(x => x.HackeeResult).WithValue(isBadData ? JudgeResult.Accepted : sub.Result)
                .SetField(x => x.TimeUsedInMs).WithValue(sub.TimeUsedInMs)
                .SetField(x => x.MemoryUsedInByte).WithValue(sub.MemoryUsedInByte)
                .SetField(x => x.Result).WithValue(isBadData ? (HackResult.BadData) : (sub.Result == JudgeResult.Accepted ? HackResult.Failed : HackResult.Succeeded))
                .SetField(x => x.Hint).WithValue(sub.Hint)
                .Update();
            }
        }
 public override void OnShowHackResult(HackStatus status)
 {
     status.HackDataBody = null;
 }
        public override void OnHackCompleted(HackStatus status)
        {
            if (status.Result == HackResult.Succeeded)
            {
                // 1. Set the status to be non-hackable
                DB.ContestProblemLastStatuses
                .Where(x => x.StatusId == status.JudgeStatusId && x.ContestId == ContestId)
                .SetField(x => x.IsHackable).WithValue(false)
                .SetField(x => x.IsHacked).WithValue(true)
                .Update();

                // 2. Add the hack data to problem
                var input           = status.HackDataBlobId.Value;
                var testCase        = DB.TestCases.FirstOrDefault(x => x.InputBlobId == input && x.ProblemId == status.Status.ProblemId);
                var testCaseExisted = testCase != null;
                if (!testCaseExisted)
                {
                    var inputLength  = ManagementService.GetBlobAsync(input).Result.Body.Length;
                    var stateMachine = ManagementService.GetStateMachineInstanceAsync(status.RelatedStateMachineIds.Last().StateMachineId).Result;
                    var output       = stateMachine.StartedActors.First(x => x.Tag == "Standard").Outputs.First(x => x.Name == "stdout.txt").Id;
                    var outputLength = ManagementService.GetBlobAsync(output).Result.Body.Length;

                    testCase = new TestCase
                    {
                        ContestId        = ContestId,
                        InputBlobId      = input,
                        InputSizeInByte  = inputLength,
                        OutputBlobId     = output,
                        OutputSizeInByte = outputLength,
                        ProblemId        = status.Status.ProblemId,
                        Type             = TestCaseType.Hack
                    };
                    DB.TestCases.Add(testCase);
                    DB.SaveChanges();
                }

                // 3. Add the result into sub judge status
                if (!testCaseExisted)
                {
                    var sub = new SubJudgeStatus
                    {
                        SubId            = DB.SubJudgeStatuses.Where(x => x.StatusId == status.JudgeStatusId).Count(),
                        Hint             = status.Hint,
                        MemoryUsedInByte = status.MemoryUsedInByte,
                        TimeUsedInMs     = status.TimeUsedInMs,
                        Result           = status.HackeeResult,
                        InputBlobId      = testCase.InputBlobId,
                        OutputBlobId     = testCase.OutputBlobId,
                        TestCaseId       = testCase.Id,
                        StatusId         = status.JudgeStatusId
                    };
                    DB.SubJudgeStatuses.Add(sub);
                    DB.SaveChanges();
                }

                // 4. Add point for the hacker
                DB.ContestProblemLastStatuses
                .Where(x => x.ContestId == ContestId && x.ProblemId == status.Status.ProblemId && x.UserId == status.UserId)
                .SetField(x => x.Point2).Plus(1)
                .Update();

                // 5. Hack all statuses
                if (!testCaseExisted && DB.Attendees.Any(x => x.ContestId == ContestId && x.UserId == status.UserId && !x.IsVirtual))
                {
                    var affectedStatuses = DB.ContestProblemLastStatuses
                                           .Include(x => x.Status)
                                           .Where(x => x.ProblemId == status.Status.ProblemId && x.ContestId == ContestId && x.Status.BinaryBlobId.HasValue && x.IsAccepted)
                                           .ToList();

                    var problem     = DB.Problems.Single(x => x.Id == status.Status.ProblemId);
                    var validatorId = problem.ValidatorBlobId.HasValue ? problem.ValidatorBlobId.Value : Guid.Parse(Configuration["JoyOI:StandardValidatorBlobId"]);

                    var blobs = new List <BlobInfo>(affectedStatuses.Count + 10);
                    blobs.Add(new BlobInfo
                    {
                        Id = ManagementService.PutBlobAsync("limit.json", Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(new
                        {
                            UserTime     = status.Status.Problem.TimeLimitationPerCaseInMs,
                            PhysicalTime = status.Status.Problem.TimeLimitationPerCaseInMs * 4,
                            Memory       = status.Status.Problem.MemoryLimitationPerCaseInByte
                        }))).Result,
                        Name = "limit.json",
                        Tag  = "Problem=" + status.Status.ProblemId
                    });
                    blobs.Add(new BlobInfo(validatorId, problem.ValidatorBlobId.HasValue ? "Validator" + Constants.GetBinaryExtension(problem.ValidatorLanguage) : "Validator.out"));
                    blobs.Add(new BlobInfo(status.HackDataBlobId.Value, "data.txt", testCase.Id.ToString()));
                    blobs.Add(new BlobInfo(testCase.OutputBlobId, "std.txt", testCase.Id.ToString()));
                    foreach (var x in affectedStatuses)
                    {
                        blobs.Add(new BlobInfo(x.Status.BinaryBlobId.Value, "Hackee" + Constants.GetBinaryExtension(x.Status.Language), x.StatusId.ToString()));
                    }

                    ManagementService.PutStateMachineInstanceAsync("HackAllStateMachine", Configuration["ManagementService:CallBack"], blobs, 2);
                }
            }
            else if (status.Result == HackResult.Failed)
            {
                DB.ContestProblemLastStatuses
                .Where(x => x.ContestId == ContestId && x.ProblemId == status.Status.ProblemId && x.UserId == status.UserId)
                .SetField(x => x.Point2).Subtract(1)
                .SetField(x => x.Point3).Plus(1)
                .Update();
            }
        }
Example #5
0
 public virtual void OnHackCompleted(HackStatus status)
 {
     throw new NotImplementedException();
 }
Example #6
0
 public virtual void OnShowHackResult(HackStatus status)
 {
 }
Example #7
0
        public async Task<IActionResult> Put(
            [FromServices] ContestExecutorFactory cef, 
            [FromServices] ManagementServiceClient mgmt,
            [FromServices] IHubContext<OnlineJudgeHub> hub,
            CancellationToken token)
        {
            var request = JsonConvert.DeserializeObject<HackRequest>(RequestBody);

            if (!User.IsSignedIn())
            {
                return Result(403, "Please login first.");
            }

            var judge = await DB.JudgeStatuses
                .Include(x => x.Problem)
                .SingleOrDefaultAsync(x => x.Id == request.JudgeStatusId, token);

            if (judge == null)
            {
                return Result(404, "The judge status is not found");
            }

            if (!judge.BinaryBlobId.HasValue)
            {
                return Result(400, "The lagency status could not be hacked.");
            }

            if (judge.UserId == User.Current.Id)
            {
                return Result(400, "You cannot hack yourself.");
            }
            
            if (IsGroupRequest() && !await IsGroupMemberAsync(token))
            {
                return Result(401, "You are not a member of this group.");
            }

            if (!string.IsNullOrEmpty(request.ContestId))
            {
                var ce = cef.Create(request.ContestId);

                if (!ce.IsStatusHackable(judge) || !ce.IsContestInProgress())
                {
                    return Result(400, "You cannot hack this status");
                }

                if (await DB.HackStatuses.AnyAsync(x => x.UserId == User.Current.Id && x.JudgeStatusId == request.JudgeStatusId && x.Result == HackResult.Succeeded && x.ContestId == request.ContestId, token))
                {
                    return Result(400, "You have already hacked this status.");
                }
            }

            // Upload hack data to management service
            if (request.IsBase64)
            {
                request.Data = request.Data.Substring(request.Data.IndexOf("base64,") + "base64,".Length);
            }
            var blobId = await mgmt.PutBlobAsync("data.txt", request.IsBase64 ? Convert.FromBase64String(request.Data) : Encoding.UTF8.GetBytes(request.Data), token);

            var hack = new HackStatus
            {
                ContestId = request.ContestId,
                JudgeStatusId = judge.Id,
                HackDataBlobId = blobId,
                Result = HackResult.Pending,
                Time = DateTime.UtcNow,
                UserId = User.Current.Id,
                HackeeResult = JudgeResult.Pending
            };
            DB.HackStatuses.Add(hack);
            await DB.SaveChangesAsync(token);

            var blobs = new List<BlobInfo>(10);

            // Put the limit.json into blob collection
            blobs.Add(new BlobInfo
            {
                Id = await mgmt.PutBlobAsync("limit.json", Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(new
                {
                    UserTime = judge.Problem.TimeLimitationPerCaseInMs,
                    PhysicalTime = judge.Problem.TimeLimitationPerCaseInMs * 4,
                    Memory = judge.Problem.MemoryLimitationPerCaseInByte
                }))),
                Name = "limit.json",
                Tag = "Problem=" + judge.ProblemId
            });

            // Put the data into blob collection
            blobs.Add(new BlobInfo(blobId, "data.txt"));

            // Put the hackee program into blob collection
            blobs.Add(new BlobInfo(judge.BinaryBlobId.Value, "Hackee" + Constants.GetBinaryExtension(judge.Language), judge.Id.ToString()));

            // Put range validator program into blob collection
            if (judge.Problem.RangeBlobId.HasValue && string.IsNullOrEmpty(judge.Problem.RangeError))
            {
                blobs.Add(new BlobInfo(judge.Problem.RangeBlobId.Value, "Range" + Constants.GetBinaryExtension(judge.Problem.RangeLanguage)));
            }

            // Put standard program into blob collection
            if (judge.Problem.StandardBlobId.HasValue && string.IsNullOrEmpty(judge.Problem.StandardError))
            {
                blobs.Add(new BlobInfo(judge.Problem.StandardBlobId.Value, "Standard" + Constants.GetBinaryExtension(judge.Problem.StandardLanguage)));
            }
            else
            {
                // Get 3 accepted programs instead of standard program
                var statuses = await DB.JudgeStatuses
                    .Where(x => x.Result == JudgeResult.Accepted && x.ProblemId == judge.ProblemId && x.BinaryBlobId.HasValue && x.Id != judge.Id)
                    .OrderBy(x => x.TimeUsedInMs)
                    .ThenBy(x => x.MemoryUsedInByte)
                    .Take(3)
                    .ToListAsync(token);

                if (statuses.Count == 0)
                {
                    return Result(400, "Missing standard program, this status could not be hacked");
                }

                var standards = statuses.Select(x => new BlobInfo(x.BinaryBlobId.Value, "Standard-" + x.Id.ToString().Substring(0,8) + Constants.GetBinaryExtension(x.Language), x.Id.ToString()));
                blobs.AddRange(standards);
            }

            // Put validator into blob collection
            if (judge.Problem.ValidatorBlobId.HasValue)
            {
                blobs.Add(new BlobInfo(judge.Problem.ValidatorBlobId.Value, "Validator" + Constants.GetBinaryExtension(judge.Problem.ValidatorLanguage)));
            }
            else
            {
                blobs.Add(new BlobInfo(Guid.Parse(Configuration["JoyOI:StandardValidatorBlobId"]), "Validator.out"));
            }

            // Start hack state machine
            var stateMachineId = await mgmt.PutStateMachineInstanceAsync("HackStateMachine", Configuration["ManagementService:CallBack"], blobs.ToArray(), 1, token);
            var stateMachine = new StateMachine { CreatedTime = DateTime.Now, Name = "HackStateMachine", Id = stateMachineId };
            DB.StateMachines.Add(stateMachine);
            hack.RelatedStateMachineIds = new List<HackStatusStateMachine>();
            hack.RelatedStateMachineIds.Add(new HackStatusStateMachine { StateMachineId = stateMachine.Id, StatusId = judge.Id });
            await DB.SaveChangesAsync(token);

            hub.Clients.All.InvokeAsync("ItemUpdated", "hack", hack.Id);

            return Result(hack.Id);
        }