この問題では、入力を検証し、空白を削除して md5 をフラグとして使用します。入力は非常に特殊で、scanf を使用して整数の一連の入力を読み取ります。配列に格納した後、2 つの関数で検証する必要があります。
(以下、ghidra の発言をお願いします)
int check1(int *nums)
{
int j;
int s;
int i;
int res;
res = 0;
i = 0;
while( true ) {
if (0x400 < i) {
return res;
}
if (nums[i] == 0) break;
s = 0;
for (j = 0; j <= res; j = j + 1) {
s = s + nums[i + j];
}
if (1 << ((byte)res & 0x1f) != s) {
return -1;
}
i = ((res + 2) * (res + 1)) / 2;
res = res + 1;
}
return res;
}
//param_20にはcheck1の戻り値(杨辉三角形の階数)が渡されます(main関数で20と等しいかどうかを検証しています)
int check2(int *nums,int param_20)
{
int j;
int s;
int i;
int i0;
i0 = 0;
i = 1;
while( true ) {
if (para_20 <= i) {
return 1;
}
s = 0;
j = i + -1;
if (nums[i] == 0) break;
for (; j < para_20 + -1; j = j + 1) {
s = s + nums[i0 + ((j + 1) * j) / 2];
}
if (nums[i + ((j + 1) * j) / 2] != s) {
return 0;
}
i0 = i0 + 1;
i = i + 1;
}
return 0;
}
writeup を見た後:
check1 では、res は階数であり、i = (res + 2) * (res + 1) / 2 は各階の開始インデックスです。check1 は、res の階の合計が i の res 乗であるかどうかを検証しています。(res & 0x1f で res の下位 5 ビットを取得するという効果的な操作に困惑しましたが、おそらくオーバーフローを防ぐためのものですか?違うようです。アセンブリでは SHL EBX,CL という命令で、EBX には 1 が格納されています。非常に奇妙です)
check2 は、「斜線上の数字の合計が左側(左上から右下への斜線)または右側(右上から左下への斜線)の数字と等しいかどうかを検証します。角の数字も含まれます。」という意味です。理解してください。
したがって、最終的に提出するフラグは RCTF {20 層去皮杨辉三角形の md5} です。