"Programmer en binaire" ça ne veut pas dire grand chose.
Pour faire fonctionner les premiers ordinateurs, il fallait écrire les codes des instructions que l'on voulait exécuter ("code machine" que certains veulent appeler "code binaire"), et généralement à l'époque, on écrivait tout sur papier, on vérifiait trente fois que c'était ce qu'on voulait et seulement après on recopiait le code en une version lisible pour la machine (cartes perforées par ex).
Sauf que écrire les instructions c'était chiant. : Certains (tous ?) programmeurs n'écrivaient pas directement les instructions, mais écrivait quelque chose de plus compréhensible pour eux (un genre de code intermédiaire) en se concentrant sur les algorithmes, avant de traduire à la main le code intermédiaire en code machine. Depuis, ce genre de code intermédiaire à été codifié pour devenir de l'assembleur traduisible automatiquement en code machine. puis sont arrivés les langages de haut niveau ...
Aujourd'hui, les seuls qui doivent encore se préoccuper du code machine, c'est les méchants pirates qui veulent exploiter des programmes avec des failles de sécurité : ils ont des restrictions sur ce que peut contenir le code machine. La plupart du temps, le code machine d'un shell-code ne peut pas contenir un octet à 0. Parfois il y a d'autres restrictions, par exemple sur ce qui se passerait si on interprétait le shell code comme du texte : interdiction d'utiliser des lettres minuscules, lettres et chiffres uniquements ...
Mais bon aujourd'hui, la plupart des shellcodes sont déjà écrits, les cas ou il y a besoin d'en refaire sont rares. Et quand c'est le cas, les shellcodes sont quand même écrits en assembleur.