AlpacaHack Mirage writeup
chal.cには次のように書かれていた。
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#define N 19
uint8_t enc[N] = {
0x31, 0x54, 0x6c, 0x2f, 0x04, 0x52, 0x22, 0x41, 0x3f, 0x59,
0x27, 0x45, 0x67, 0x79, 0x1a, 0x4e, 0x78, 0x2d, 0x19
};
uint16_t step(uint16_t s) {
uint16_t bit = ((s >> 0) ^ (s >> 2) ^ (s >> 3) ^ (s >> 5)) & 1;
return (s >> 1) | (bit << 15);
}
int main(void) {
setvbuf(stdout, NULL, _IONBF, 0);
char buf[64];
printf("enter the flag: ");
if (!fgets(buf, sizeof(buf), stdin))
return 1;
buf[strcspn(buf, "\n")] = 0;
if (strlen(buf) != N) {
printf("wrong\n");
return 1;
}
uint16_t state = 0xACE1;
for (int i = 0; i < N; i++) {
state = step(state);
if (((uint8_t)buf[i] ^ (state & 0x7F)) != enc[i]) {
printf("wrong\n");
return 1;
}
}
printf("correct!\n");
return 0;
}
排他的論理和には次のような性質がある。
A ^ B = Cの時、元の値AはA = C ^ Bで求められる。
これを利用して次のようなコードを作成した。
#include <stdio.h>
#include <string.h>
#include <stdint.h>
uint16_t step(uint16_t s) {
uint16_t bit = ((s >> 0) ^ (s >> 2) ^ (s >> 3) ^ (s >> 5)) & 1;
return (s >> 1) | (bit << 15);
}
int main(void){
uint8_t enc[19] = {0x31, 0x54, 0x6c, 0x2f, 0x04, 0x52, 0x22, 0x41, 0x3f, 0x59,
0x27, 0x45, 0x67, 0x79, 0x1a, 0x4e, 0x78, 0x2d, 0x19};
uint16_t state = 0xACE1;
uint8_t flag[20] = {0};
for (int i = 0; i < 19; i++) {
state = step(state);
flag[i] = enc[i] ^ (state & 0x7F);
}
printf("flag: %s\n",flag);
return 0;
}
このコードを実行すれば、flagが求められる。
flag = Alpaca{mirrors_lie}