# [Python 2], 125 bytes

<!-- language-all: lang-python -->

    s="%64c"%10
    exec's*=63;s="".join(s[n][(s[n+3967:][:191]*3)[::64].strip()=="X":n!=2015]or"X"for n in range(4032));'*32
    print s

[Try it online!][TIO-kasiqhwh]

[Python 2]: https://docs.python.org/2/
[TIO-kasiqhwh]: https://tio.run/##FcjdCsIgGIDh812FCWPTYPiXMYf3EYgHMazs4FPUg7p6WycvPG/@tlcC0Xu1eNRqxyNnQ/iEfarUarkdGy/vFGGuDrz79yxXfTXeGb5yTyVxxmjll9pKzDOxFt@wgZMVjF98KoceqSBAEVC5wzPMiklByDZRKYZcIjRUe/8B "Python 2 – Try It Online"

This answer is by user "clock" based on hallvabo's solution, on the [Anarchy Golf version of this challenge][1] that I submitted. Note that output there is strict and is required to be exactly the picture of X's and spaces to STDOUT via a full program, with only an allowance for a trailing newline.

The most interesting part of this answer, in my opinion, is the concise construction `(s[n+3967:][:191]*3)[::64]` after `s*=63` to get the nine neighbors of the cell counting itself in a flat newline-joined string representing the grid. To check if there's exactly one `X` among them, `.strip()` is called to get rid of whitespace on either side, and the result is checked to equal just `"X"`.

It's interesting how simulating the steps on the string representation of the output directly (rather than an array of bits) not only saves on doing a conversion to characters later but also allows string-specific methods to be used in a golfy way.

Another neat trick, borrowed from hallvabo, is `"%64c"%10` used to initialize `s` to 63 spaces followed by a newline for a line of the initial empty grid. Using the `%c` format, which converts an ASCII value to a character, is shorter than `" "*63+"\n"` or `"%64s"%"\n"`.

  [1]: http://golf.shinh.org/p.rb?Square%20a%20snowflake