A resposta curta é que você não pode usar SQL dinâmico em um TRIGGER.
Estou confuso com a consulta do valor auto_increment e a atribuição de um valor à coluna ID. Não entendo por que você precisa definir o valor da coluna ID. Essa não é a coluna definida como AUTO_INCREMENT? O banco de dados irá lidar com a atribuição.
Também não está claro se é garantido que sua consulta retorne valores exclusivos, especialmente quando inserções simultâneas são executadas. (Eu não testei, então pode funcionar.)
Mas o código é peculiar.
Parece que o que você está tentando realizar é obter o valor de uma coluna da linha inserida mais recentemente. Eu acho que existem algumas restrições em consultar a mesma tabela em que o gatilho está definido. (Eu sei com certeza que existe no Oracle; MySQL pode ser mais liberal.)
Se eu precisasse fazer algo assim, eu tentaria algo assim:
SELECT @prev_hash := t.hash AS prev_hash
FROM core_Test t
ORDER BY t.ID DESC LIMIT 1;
SET NEW.hash = @prev_hash;
Mas, novamente, não tenho certeza se isso funcionará (eu precisaria testar). Se funciona em um caso simples, isso não é prova de que funciona o tempo todo, no caso de inserções simultâneas, no caso de uma inserção estendida, et al.
Eu escrevi a consulta da maneira que fiz para que ela possa usar um índice na coluna ID, para fazer uma operação de varredura reversa. Se ele não usar o índice, eu tentaria reescrever essa consulta (provavelmente como um JOIN, para obter o melhor desempenho possível.
SELECT @prev_hash := t.hash AS prev_hash
FROM ( SELECT r.ID FROM core_Test r ORDER BY r.ID DESC LIMIT 1 ) s
JOIN core_Test t
ON t.ID = s.ID
Trecho do Manual de Referência do MySQL 5.1
E.1 Restrições em Programas Armazenados