Should I cast my shstrab into a Elf64_Sym so that I can use the st_name?
No.
Here is the loop you want:
Elf64_Sym *sym = (Elf64_Sym*) (data + symtab->sh_offset);
str = (char*) (data + strtab->sh_offset);
for (size_t i = 0; i < symtab->sh_size / sizeof(Elf64_Sym); i++) {
printf("%s\n", str + sym[i].st_name);
}