A key point here is that in Fiat-Shamir transformation, you need to make a distinction between what security means in real implementation and what it means in the theory of your design. It is true that in practice we use hash functions to implement Fiat-Shamir transformation, but as you mentioned it doesn't seem easy to simulate the proof in this case. In theory, however, we use an ideal object called "random oracle" and depending on which properties we assume for this random oracle, we can perform the simulation. More precisely, a random oracle can be either programmable or non-programmable. By programmability, it means that the simulator is allowed to choose the answers to the oracle queries. In the context of non-interactive zero-knowledge (NIZK) proofs, for example, this makes the simulator able to create a convincing but fake proof. On the other hand, the non-programmable random oracle (NPRO) model restricts the simulator such that it can no longer choose the answers for the queries. Instead, the simulator is only empowered by seeing all the query/answer pairs, made by the parties during the protocol. This restriction on the simulator (or more generally, the security reduction) makes the underlying proofs preferable, as they rely on fewer properties of the random oracle and so can be considered as a step toward getting rid of it. But, in some NIZK proofs such as Fiat-Shamir transformation of Schnorr's protocol, programming the random oracle seems crucial to provide ZK property.