You didn't mention how long the string is supposed to be or how many characters are possible at each position in the string; obviously these points would have an impact on the practicality of the process.
In any case, I think you're mistaken about preferring the use of hashes. Unless I misunderstood your post, the app you're talking about is just a matter of nested loops, one loop for each character position in the string. The inner-most loop prints the concatenation of all the loop iterators. The number of iterations on each loop is simply the number of possible characters to use at the corresponding position. It could be structured recursively to support handling strings of various lengths. But using hashes would be a waste of time, and a vast waste of memory.