https://alpacahack.com/daily/challenges/lets-shut-down-linux
chal.cchal.c:50:69
/* Read a string from stdin, then parse it as decimal number. */
uint32_t my_read_uint32() {
char buf[64] = {};
ssize_t size = (ssize_t)my_syscall_3(SYS_read, STDIN_FILENO, (uint64_t)buf, sizeof(buf) - 1);
if (size <= 0) {
my_fatal("Failed to read...\n");
}
uint32_t result = 0;
for (int i = 0; buf[i] && buf[i] != '\n'; ++i) {
char c = buf[i];
if ('0' <= c && c <= '9') {
result *= 10;
result += (c - '0');
} else {
my_fatal("Characters should be digits...\n");
}
}
return result;
}
chal.c:80:87
my_write("arg1: ");
uint32_t arg1 = my_read_uint32();
my_write("arg2: ");
uint32_t arg2 = my_read_uint32();
my_write("arg3: ");
uint32_t arg3 = my_read_uint32();
my_write("Running a reboot system call!\n");
my_syscall_4(SYS_reboot, arg1, arg2, arg3, (uint64_t)"A constant string");
server.py:22:25
print(f"[server.py] {p.returncode = }")
if p.returncode == 0 and b"Power down" in output:
flag = os.getenv("FLAG", "Alpaca{REDACTED}")
print(f"[server.py] Linux has been shut down properly! FLAG: {flag}")
上のコードのように Linux に Power down と出力させればよいが、そのためにシステムコールを実行する必要がある。
ところで、my_syscall_4 とほぼ動作が等しい syscall() の引数は以下の通りである。
(my_syscall_4() はアセンブリを用いてそのまま syscall を呼び出す)
int syscall(SYS_reboot, int magic, int magic2, int op, void *arg);
https://man7.org/linux/man-pages/man2/reboot.2.html
である。これを読むと、引数の説明は以下であることがわかる
This system call fails (with the error EINVAL) unless magic equals LINUX_REBOOT_MAGIC1 (that is, 0xfee1dead) and magic2 equals LINUX_REBOOT_MAGIC2 (that is, 0x28121969).
... (中略) ... The op argument can have the following values: LINUX_REBOOT_CMD_POWER_OFF (RB_POWER_OFF, 0x4321fedc; since Linux 2.1.30). The message "Power down." is printed, the system is stopped, and all power is removed from the system, if possible. (後略) ...
すなわち、
magic = 0xfee1dead かつ magic2 = 0x28121969 であれば再起動が呼び出され、
op = 0x4321fedc であれば Power down と出力されシャットダウンが呼び出されることがわかる。
ところで my_read_uint32() を読むと、なにか頑張って 0 ~ 9 の10進数を uint32_t に変換していることがわかるので、入力は10進数でなければならない。
よって、適当に Windows の電卓の「プログラマー」タブを使うか (ただし、コピーするときは DEC にフォーカスを合わせ Ctrl + C する必要がある)、
単に以下の Python スクリプトの出力をそのまま入れればよい。
magic = 0xfee1dead
magic2 = 0x28121969
op = 0x4321fedc
print(int(magic))
print(int(magic2))
print(int(op))
以上の結果より、以下を順番に入力すればよい。