#pragma comment(lib, "Kernel32.lib")
#define USAGE \
"本ツールは実行中のプロセスにDLLを注入(ロード)します。\n" \
"使い方: dllinj EXEファイル名 DLLファイル名\n" \
"\tEXEファイル名: 注入先となるプロセスのEXEファイル名\n" \
"\tDLLファイル名: 注入するDLLファイル名\n" \
"※同じEXEファイル名のプロセスが複数ある場合には、\n" \
" 最初に見つけたものに注入します。\n"
#include <windows.h>
#include <tlhelp32.h>
#include <cstdio>
#include <memory>
#include <string>
using namespace std;
class Handle {
public:
Handle(HANDLE value);
virtual ~Handle();
virtual operator bool() const;
virtual void close();
HANDLE get();
protected:
HANDLE value;
};
class VirtualMemory {
public:
static VirtualMemory* allocate(const HANDLE& processHandle, const DWORD& size);
virtual ~VirtualMemory();
LPVOID getAddress();
protected:
VirtualMemory(const HANDLE& processHandle, LPVOID address);
LPVOID address;
HANDLE processHandle;
};
int main(int argc, char** argv) {
if (argc != 3) {
fprintf(stderr, USAGE);
return 1;
}
string exeName = string(argv[1]);
string dllName = string(argv[2]);
Handle processSnapHandle(CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0));
if (!processSnapHandle) {
fprintf(stderr, "エラー: 予期せぬエラーが発生しました。(%s:%d)\n", "CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS)", GetLastError());
return 1;
}
PROCESSENTRY32 pe32;
pe32.dwSize = sizeof(PROCESSENTRY32);
if (!Process32First(processSnapHandle.get(), &pe32)) {
fprintf(stderr, "エラー: 予期せぬエラーが発生しました。(%s:%d)\n", "Process32First", GetLastError());
return 1;
}
for (;;) {
if (string(pe32.szExeFile) == exeName) {
break;
}
if (!Process32Next(processSnapHandle.get(), &pe32)) {
fprintf(stderr, "エラー: プロセスが見つかりませんでした。(%s)\n", exeName.c_str());
return 1;
}
}
Handle processHandle(OpenProcess(PROCESS_ALL_ACCESS, FALSE, pe32.th32ProcessID));
if (!processHandle) {
fprintf(stderr, "エラー: 予期せぬエラーが発生しました。(%s:%d)\n", "OpenProcess", GetLastError());
return 1;
}
char dllFullPath[MAX_PATH];
DWORD dllFullPathLength = GetFullPathName(dllName.c_str(), MAX_PATH, dllFullPath, nullptr);
if (dllFullPathLength == 0) {
fprintf(stderr, "エラー: DLLファイルが見つかりませんでした。(%s)\n", dllName.c_str());
return 1;
}
shared_ptr<VirtualMemory> dllNameMemory(VirtualMemory::allocate(processHandle.get(), dllName.length() + 1));
if (!dllNameMemory.get()) {
return 1;
}
SIZE_T written;
if (!WriteProcessMemory(processHandle.get(), dllNameMemory->getAddress(), dllFullPath, dllFullPathLength + 1, &written)) {
fprintf(stderr, "エラー: 予期せぬエラーが発生しました。(%s:%d)\n", "WriteProcessMemory", GetLastError());
return 1;
}
LPTHREAD_START_ROUTINE procAddress = (LPTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle("Kernel32.dll"), "LoadLibraryA");
Handle threadHandle(CreateRemoteThread(processHandle.get(), nullptr, 0, procAddress, dllNameMemory->getAddress(), 0, nullptr));
if (!threadHandle) {
fprintf(stderr, "エラー: 予期せぬエラーが発生しました。(%s:%d)\n", "CreateRemoteThread", GetLastError());
return 1;
}
if (WaitForSingleObject(threadHandle.get(), INFINITE) != WAIT_OBJECT_0) {
fprintf(stderr, "エラー: 予期せぬエラーが発生しました。(%s:%d)\n", "WaitForSingleObject", GetLastError());
return 1;
}
HMODULE module;
if (!GetExitCodeThread(threadHandle.get(), (DWORD*)&module)) {
fprintf(stderr, "エラー: 予期せぬエラーが発生しました。(%s:%d)\n", "GetExitCodeThread", GetLastError());
return 1;
}
if (module == nullptr) {
fprintf(stderr, "エラー: 予期せぬエラーが発生しました。(%s)\n", "LoadLibraryA");
return 1;
}
printf("注入しました。(0x%08X)\n", module);
return 0;
}
Handle::Handle(HANDLE value) : value(value) {}
Handle::~Handle() {
close();
}
Handle::operator bool() const {
return value != nullptr && value != INVALID_HANDLE_VALUE;
}
void Handle::close() {
if (operator bool()) {
CloseHandle(value);
value = nullptr;
}
}
HANDLE Handle::get() {
return value;
}
VirtualMemory* VirtualMemory::allocate(const HANDLE& processHandle, const DWORD& size) {
LPVOID address = VirtualAllocEx(processHandle, nullptr, size, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if (address == nullptr) {
fprintf(stderr, "エラー: 予期せぬエラーが発生しました。(%s)\n", "VirtualAllocEx");
return nullptr;
}
return new VirtualMemory(processHandle, address);
}
VirtualMemory::~VirtualMemory() {
VirtualFreeEx(processHandle, address, 0, MEM_RELEASE);
}
LPVOID VirtualMemory::getAddress() {
return address;
}
VirtualMemory::VirtualMemory(const HANDLE& processHandle, LPVOID address) :
processHandle(processHandle), address(address) {}
I3ByYWdtYSBjb21tZW50KGxpYiwgIktlcm5lbDMyLmxpYiIpCgojZGVmaW5lIFVTQUdFIFwKICAgICLmnKzjg4Tjg7zjg6vjga/lrp/ooYzkuK3jga7jg5fjg63jgrvjgrnjgatETEzjgpLms6jlhaUo44Ot44O844OJKeOBl+OBvuOBmeOAglxuIiBcCgki5L2/44GE5pa5OiBkbGxpbmogRVhF44OV44Kh44Kk44Or5ZCNIERMTOODleOCoeOCpOODq+WQjVxuIiBcCgkiXHRFWEXjg5XjgqHjgqTjg6vlkI06IOazqOWFpeWFiOOBqOOBquOCi+ODl+ODreOCu+OCueOBrkVYReODleOCoeOCpOODq+WQjVxuIiBcCgkiXHRETEzjg5XjgqHjgqTjg6vlkI06IOazqOWFpeOBmeOCi0RMTOODleOCoeOCpOODq+WQjVxuIiBcCgki4oC75ZCM44GYRVhF44OV44Kh44Kk44Or5ZCN44Gu44OX44Ot44K744K544GM6KSH5pWw44GC44KL5aC05ZCI44Gr44Gv44CBXG4iIFwKCSIgIOacgOWIneOBq+imi+OBpOOBkeOBn+OCguOBruOBq+azqOWFpeOBl+OBvuOBmeOAglxuIgoKI2luY2x1ZGUgPHdpbmRvd3MuaD4KI2luY2x1ZGUgPHRsaGVscDMyLmg+CgojaW5jbHVkZSA8Y3N0ZGlvPgojaW5jbHVkZSA8bWVtb3J5PgojaW5jbHVkZSA8c3RyaW5nPgoKdXNpbmcgbmFtZXNwYWNlIHN0ZDsKCmNsYXNzIEhhbmRsZSB7CnB1YmxpYzoKCUhhbmRsZShIQU5ETEUgdmFsdWUpOwoJdmlydHVhbCB+SGFuZGxlKCk7Cgl2aXJ0dWFsIG9wZXJhdG9yIGJvb2woKSBjb25zdDsKCXZpcnR1YWwgdm9pZCBjbG9zZSgpOwoJSEFORExFIGdldCgpOwpwcm90ZWN0ZWQ6CglIQU5ETEUgdmFsdWU7Cn07CgpjbGFzcyBWaXJ0dWFsTWVtb3J5IHsKcHVibGljOgoJc3RhdGljIFZpcnR1YWxNZW1vcnkqIGFsbG9jYXRlKGNvbnN0IEhBTkRMRSYgcHJvY2Vzc0hhbmRsZSwgY29uc3QgRFdPUkQmIHNpemUpOwoJdmlydHVhbCB+VmlydHVhbE1lbW9yeSgpOwoJTFBWT0lEIGdldEFkZHJlc3MoKTsKcHJvdGVjdGVkOgoJVmlydHVhbE1lbW9yeShjb25zdCBIQU5ETEUmIHByb2Nlc3NIYW5kbGUsIExQVk9JRCBhZGRyZXNzKTsKCUxQVk9JRCBhZGRyZXNzOwoJSEFORExFIHByb2Nlc3NIYW5kbGU7Cn07CgppbnQgbWFpbihpbnQgYXJnYywgY2hhcioqIGFyZ3YpIHsKCWlmIChhcmdjICE9IDMpIHsKCQlmcHJpbnRmKHN0ZGVyciwgVVNBR0UpOwoJCXJldHVybiAxOwoJfQoJc3RyaW5nIGV4ZU5hbWUgPSBzdHJpbmcoYXJndlsxXSk7CglzdHJpbmcgZGxsTmFtZSA9IHN0cmluZyhhcmd2WzJdKTsKCUhhbmRsZSBwcm9jZXNzU25hcEhhbmRsZShDcmVhdGVUb29saGVscDMyU25hcHNob3QoVEgzMkNTX1NOQVBQUk9DRVNTLCAwKSk7CglpZiAoIXByb2Nlc3NTbmFwSGFuZGxlKSB7CgkJZnByaW50ZihzdGRlcnIsICLjgqjjg6njg7w6IOS6iOacn+OBm+OBrOOCqOODqeODvOOBjOeZuueUn+OBl+OBvuOBl+OBn+OAgiglczolZClcbiIsICJDcmVhdGVUb29saGVscDMyU25hcHNob3QoVEgzMkNTX1NOQVBQUk9DRVNTKSIsIEdldExhc3RFcnJvcigpKTsKCQlyZXR1cm4gMTsKCX0KCVBST0NFU1NFTlRSWTMyIHBlMzI7CglwZTMyLmR3U2l6ZSA9IHNpemVvZihQUk9DRVNTRU5UUlkzMik7CglpZiAoIVByb2Nlc3MzMkZpcnN0KHByb2Nlc3NTbmFwSGFuZGxlLmdldCgpLCAmcGUzMikpIHsKCQlmcHJpbnRmKHN0ZGVyciwgIuOCqOODqeODvDog5LqI5pyf44Gb44Gs44Ko44Op44O844GM55m655Sf44GX44G+44GX44Gf44CCKCVzOiVkKVxuIiwgIlByb2Nlc3MzMkZpcnN0IiwgR2V0TGFzdEVycm9yKCkpOwoJCXJldHVybiAxOwoJfQoJZm9yICg7OykgewoJCWlmIChzdHJpbmcocGUzMi5zekV4ZUZpbGUpID09IGV4ZU5hbWUpIHsKCQkJYnJlYWs7CgkJfQoJCWlmICghUHJvY2VzczMyTmV4dChwcm9jZXNzU25hcEhhbmRsZS5nZXQoKSwgJnBlMzIpKSB7CgkJCWZwcmludGYoc3RkZXJyLCAi44Ko44Op44O8OiDjg5fjg63jgrvjgrnjgYzopovjgaTjgYvjgorjgb7jgZvjgpPjgafjgZfjgZ/jgIIoJXMpXG4iLCBleGVOYW1lLmNfc3RyKCkpOwoJCQlyZXR1cm4gMTsKCQl9Cgl9CglIYW5kbGUgcHJvY2Vzc0hhbmRsZShPcGVuUHJvY2VzcyhQUk9DRVNTX0FMTF9BQ0NFU1MsIEZBTFNFLCBwZTMyLnRoMzJQcm9jZXNzSUQpKTsKCWlmICghcHJvY2Vzc0hhbmRsZSkgewoJCWZwcmludGYoc3RkZXJyLCAi44Ko44Op44O8OiDkuojmnJ/jgZvjgazjgqjjg6njg7zjgYznmbrnlJ/jgZfjgb7jgZfjgZ/jgIIoJXM6JWQpXG4iLCAiT3BlblByb2Nlc3MiLCBHZXRMYXN0RXJyb3IoKSk7CgkJcmV0dXJuIDE7Cgl9CgljaGFyIGRsbEZ1bGxQYXRoW01BWF9QQVRIXTsKCURXT1JEIGRsbEZ1bGxQYXRoTGVuZ3RoID0gR2V0RnVsbFBhdGhOYW1lKGRsbE5hbWUuY19zdHIoKSwgTUFYX1BBVEgsIGRsbEZ1bGxQYXRoLCBudWxscHRyKTsKCWlmIChkbGxGdWxsUGF0aExlbmd0aCA9PSAwKSB7CgkJZnByaW50ZihzdGRlcnIsICLjgqjjg6njg7w6IERMTOODleOCoeOCpOODq+OBjOimi+OBpOOBi+OCiuOBvuOBm+OCk+OBp+OBl+OBn+OAgiglcylcbiIsIGRsbE5hbWUuY19zdHIoKSk7CgkJcmV0dXJuIDE7Cgl9CglzaGFyZWRfcHRyPFZpcnR1YWxNZW1vcnk+IGRsbE5hbWVNZW1vcnkoVmlydHVhbE1lbW9yeTo6YWxsb2NhdGUocHJvY2Vzc0hhbmRsZS5nZXQoKSwgZGxsTmFtZS5sZW5ndGgoKSArIDEpKTsKCWlmICghZGxsTmFtZU1lbW9yeS5nZXQoKSkgewoJCXJldHVybiAxOwoJfQoJU0laRV9UIHdyaXR0ZW47CglpZiAoIVdyaXRlUHJvY2Vzc01lbW9yeShwcm9jZXNzSGFuZGxlLmdldCgpLCBkbGxOYW1lTWVtb3J5LT5nZXRBZGRyZXNzKCksIGRsbEZ1bGxQYXRoLCBkbGxGdWxsUGF0aExlbmd0aCArIDEsICZ3cml0dGVuKSkgewoJCWZwcmludGYoc3RkZXJyLCAi44Ko44Op44O8OiDkuojmnJ/jgZvjgazjgqjjg6njg7zjgYznmbrnlJ/jgZfjgb7jgZfjgZ/jgIIoJXM6JWQpXG4iLCAiV3JpdGVQcm9jZXNzTWVtb3J5IiwgR2V0TGFzdEVycm9yKCkpOwoJCXJldHVybiAxOwoJfQoJTFBUSFJFQURfU1RBUlRfUk9VVElORSBwcm9jQWRkcmVzcyA9IChMUFRIUkVBRF9TVEFSVF9ST1VUSU5FKUdldFByb2NBZGRyZXNzKEdldE1vZHVsZUhhbmRsZSgiS2VybmVsMzIuZGxsIiksICJMb2FkTGlicmFyeUEiKTsKCUhhbmRsZSB0aHJlYWRIYW5kbGUoQ3JlYXRlUmVtb3RlVGhyZWFkKHByb2Nlc3NIYW5kbGUuZ2V0KCksIG51bGxwdHIsIDAsIHByb2NBZGRyZXNzLCBkbGxOYW1lTWVtb3J5LT5nZXRBZGRyZXNzKCksIDAsIG51bGxwdHIpKTsKCWlmICghdGhyZWFkSGFuZGxlKSB7CgkJZnByaW50ZihzdGRlcnIsICLjgqjjg6njg7w6IOS6iOacn+OBm+OBrOOCqOODqeODvOOBjOeZuueUn+OBl+OBvuOBl+OBn+OAgiglczolZClcbiIsICJDcmVhdGVSZW1vdGVUaHJlYWQiLCBHZXRMYXN0RXJyb3IoKSk7CgkJcmV0dXJuIDE7Cgl9CglpZiAoV2FpdEZvclNpbmdsZU9iamVjdCh0aHJlYWRIYW5kbGUuZ2V0KCksIElORklOSVRFKSAhPSBXQUlUX09CSkVDVF8wKSB7CgkJZnByaW50ZihzdGRlcnIsICLjgqjjg6njg7w6IOS6iOacn+OBm+OBrOOCqOODqeODvOOBjOeZuueUn+OBl+OBvuOBl+OBn+OAgiglczolZClcbiIsICJXYWl0Rm9yU2luZ2xlT2JqZWN0IiwgR2V0TGFzdEVycm9yKCkpOwoJCXJldHVybiAxOwoJfQoJSE1PRFVMRSBtb2R1bGU7CglpZiAoIUdldEV4aXRDb2RlVGhyZWFkKHRocmVhZEhhbmRsZS5nZXQoKSwgKERXT1JEKikmbW9kdWxlKSkgewoJCWZwcmludGYoc3RkZXJyLCAi44Ko44Op44O8OiDkuojmnJ/jgZvjgazjgqjjg6njg7zjgYznmbrnlJ/jgZfjgb7jgZfjgZ/jgIIoJXM6JWQpXG4iLCAiR2V0RXhpdENvZGVUaHJlYWQiLCBHZXRMYXN0RXJyb3IoKSk7CgkJcmV0dXJuIDE7Cgl9CglpZiAobW9kdWxlID09IG51bGxwdHIpIHsKCQlmcHJpbnRmKHN0ZGVyciwgIuOCqOODqeODvDog5LqI5pyf44Gb44Gs44Ko44Op44O844GM55m655Sf44GX44G+44GX44Gf44CCKCVzKVxuIiwgIkxvYWRMaWJyYXJ5QSIpOwoJCXJldHVybiAxOwoJfQoJcHJpbnRmKCLms6jlhaXjgZfjgb7jgZfjgZ/jgIIoMHglMDhYKVxuIiwgbW9kdWxlKTsKCXJldHVybiAwOwp9CgpIYW5kbGU6OkhhbmRsZShIQU5ETEUgdmFsdWUpIDogdmFsdWUodmFsdWUpIHt9CgpIYW5kbGU6On5IYW5kbGUoKSB7CgljbG9zZSgpOwp9CgpIYW5kbGU6Om9wZXJhdG9yIGJvb2woKSBjb25zdCB7CglyZXR1cm4gdmFsdWUgIT0gbnVsbHB0ciAmJiB2YWx1ZSAhPSBJTlZBTElEX0hBTkRMRV9WQUxVRTsKfQoKdm9pZCBIYW5kbGU6OmNsb3NlKCkgewoJaWYgKG9wZXJhdG9yIGJvb2woKSkgewoJCUNsb3NlSGFuZGxlKHZhbHVlKTsKCQl2YWx1ZSA9IG51bGxwdHI7Cgl9Cn0KCkhBTkRMRSBIYW5kbGU6OmdldCgpIHsKCXJldHVybiB2YWx1ZTsKfQoKVmlydHVhbE1lbW9yeSogVmlydHVhbE1lbW9yeTo6YWxsb2NhdGUoY29uc3QgSEFORExFJiBwcm9jZXNzSGFuZGxlLCBjb25zdCBEV09SRCYgc2l6ZSkgewoJTFBWT0lEIGFkZHJlc3MgPSBWaXJ0dWFsQWxsb2NFeChwcm9jZXNzSGFuZGxlLCBudWxscHRyLCBzaXplLCBNRU1fQ09NTUlULCBQQUdFX0VYRUNVVEVfUkVBRFdSSVRFKTsKCWlmIChhZGRyZXNzID09IG51bGxwdHIpIHsKCQlmcHJpbnRmKHN0ZGVyciwgIuOCqOODqeODvDog5LqI5pyf44Gb44Gs44Ko44Op44O844GM55m655Sf44GX44G+44GX44Gf44CCKCVzKVxuIiwgIlZpcnR1YWxBbGxvY0V4Iik7CgkJcmV0dXJuIG51bGxwdHI7Cgl9CglyZXR1cm4gbmV3IFZpcnR1YWxNZW1vcnkocHJvY2Vzc0hhbmRsZSwgYWRkcmVzcyk7Cn0KClZpcnR1YWxNZW1vcnk6On5WaXJ0dWFsTWVtb3J5KCkgewoJVmlydHVhbEZyZWVFeChwcm9jZXNzSGFuZGxlLCBhZGRyZXNzLCAwLCBNRU1fUkVMRUFTRSk7Cn0KCkxQVk9JRCBWaXJ0dWFsTWVtb3J5OjpnZXRBZGRyZXNzKCkgewoJcmV0dXJuIGFkZHJlc3M7Cn0KClZpcnR1YWxNZW1vcnk6OlZpcnR1YWxNZW1vcnkoY29uc3QgSEFORExFJiBwcm9jZXNzSGFuZGxlLCBMUFZPSUQgYWRkcmVzcykgOiAKCXByb2Nlc3NIYW5kbGUocHJvY2Vzc0hhbmRsZSksIGFkZHJlc3MoYWRkcmVzcykge30K