mactype/expfunc.cpp
2023-08-22 17:48:13 +08:00

1048 lines
28 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#ifndef _GDIPP_EXE
#include "settings.h"
#include "override.h"
#include <tlhelp32.h>
#include <shlwapi.h> //DLLVERSIONINFO
#include "undocAPI.h"
#include <windows.h>
#include <dwrite_1.h>
#include <dwrite_2.h>
#include <dwrite_3.h>
#include <locale>
#include "wow64ext.h"
#include <VersionHelpers.h>
#include "crc32.h"
// win2k以降
//#pragma comment(linker, "/subsystem:windows,5.0")
#ifndef _WIN64
#ifdef DEBUG
#pragma comment(lib, "wow64ext_dbg.lib")
#else
#pragma comment(lib, "wow64ext.lib")
#endif
#endif
EXTERN_C LRESULT CALLBACK GetMsgProc(int code, WPARAM wParam, LPARAM lParam)
{
//何もしない
return CallNextHookEx(NULL, code, wParam, lParam);
}
EXTERN_C HRESULT WINAPI GdippDllGetVersion(DLLVERSIONINFO* pdvi)
{
if (!pdvi || pdvi->cbSize < sizeof(DLLVERSIONINFO)) {
return E_INVALIDARG;
}
const UINT cbSize = pdvi->cbSize;
ZeroMemory(pdvi, cbSize);
pdvi->cbSize = cbSize;
HRSRC hRsrc = FindResource(GetDLLInstance(), MAKEINTRESOURCE(VS_VERSION_INFO), RT_VERSION);
if (!hRsrc) {
return E_FAIL;
}
HGLOBAL hGlobal = LoadResource(GetDLLInstance(), hRsrc);
if (!hGlobal) {
return E_FAIL;
}
const WORD* lpwPtr = (const WORD*)LockResource(hGlobal);
if (lpwPtr[1] != sizeof(VS_FIXEDFILEINFO)) {
return E_FAIL;
}
const VS_FIXEDFILEINFO* pvffi = (const VS_FIXEDFILEINFO*)(lpwPtr + 20);
if (pvffi->dwSignature != VS_FFI_SIGNATURE ||
pvffi->dwStrucVersion != VS_FFI_STRUCVERSION) {
return E_FAIL;
}
//8.0.2006.1027
// -> Major: 8, Minor: 2006, Build: 1027
pdvi->dwMajorVersion = HIWORD(pvffi->dwFileVersionMS);
pdvi->dwMinorVersion = LOWORD(pvffi->dwFileVersionMS) * 10 + HIWORD(pvffi->dwFileVersionLS);
pdvi->dwBuildNumber = LOWORD(pvffi->dwFileVersionLS);
pdvi->dwPlatformID = DLLVER_PLATFORM_NT;
if (pdvi->cbSize < sizeof(DLLVERSIONINFO2)) {
return S_OK;
}
DLLVERSIONINFO2* pdvi2 = (DLLVERSIONINFO2*)pdvi;
pdvi2->ullVersion = MAKEDLLVERULL(pdvi->dwMajorVersion, pdvi->dwMinorVersion, pdvi->dwBuildNumber, 2);
return S_OK;
}
#endif //!_GDIPP_EXE
extern LONG interlock;
extern LONG g_bHookEnabled;
#include "gdiPlusFlat2.h"
#ifdef USE_DETOURS
//detours
#include "detours.h"
//
#define HOOK_MANUALLY(rettype, name, argtype, arglist) ;
#define HOOK_DEFINE(rettype, name, argtype, arglist) \
DetourDetach(&(PVOID&)ORIG_##name, IMPL_##name);
LONG hook_term()
{
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
#include "hooklist.h"
LONG error = DetourTransactionCommit();
if (error != NOERROR) {
TRACE(_T("hook_term error: %#x\n"), error);
}
return error;
}
#undef HOOK_DEFINE
#undef HOOK_MANUALLY
#else
#include "easyhook.h"
#define HOOK_MANUALLY(rettype, name, argtype, arglist) ;
#define HOOK_DEFINE(rettype, name, argtype, arglist) \
ORIG_##name = name;
#pragma optimize("s", on)
static LONG hook_term()
{
#include "hooklist.h"
LhUninstallAllHooks();
return LhWaitForPendingRemovals();
}
#pragma optimize("", on)
#undef HOOK_DEFINE
#undef HOOK_MANUALLY
#endif
HMODULE GetSelfModuleHandle()
{
MEMORY_BASIC_INFORMATION mbi;
return ((::VirtualQuery(GetSelfModuleHandle, &mbi, sizeof(mbi)) != 0)
? (HMODULE) mbi.AllocationBase : NULL);
}
EXTERN_C void WINAPI CreateControlCenter(IControlCenter** ret)
{
*ret = (IControlCenter*)new CControlCenter;
}
EXTERN_C void WINAPI ReloadConfig()
{
CControlCenter::ReloadConfig();
}
extern HINSTANCE g_dllInstance;
EXTERN_C void SafeUnload()
{
static BOOL bInited = false;
if (bInited)
return; //防重入
bInited = true;
while (CThreadCounter::Count())
Sleep(0);
CCriticalSectionLock * lock = new CCriticalSectionLock;
BOOL last;
if (last=InterlockedExchange(&g_bHookEnabled, FALSE)) {
if (hook_term()!=NOERROR)
{
InterlockedExchange(&g_bHookEnabled, last);
bInited = false;
delete lock;
ExitThread(ERROR_ACCESS_DENIED);
}
}
delete lock;
while (CThreadCounter::Count())
Sleep(10);
Sleep(0);
do
{
Sleep(10);
} while (CThreadCounter::Count()); //double check for xp
bInited = false;
FreeLibraryAndExitThread(g_dllInstance, 0);
}
void ChangeFileName(LPWSTR lpSrc, int nSize, LPCWSTR lpNewFileName) {
for (int i = nSize; i > 0; --i){
if (lpSrc[i] == L'\\') {
lpSrc[i + 1] = L'\0';
break;
}
}
wcscat(lpSrc, lpNewFileName);
}
std::string WstringToString(const std::wstring str)
{// wstringתstring
unsigned len = str.size() * 4;
setlocale(LC_CTYPE, "");
char *p = new char[len];
wcstombs(p, str.c_str(), len);
std::string str1(p);
delete[] p;
return str1;
}
// make a unique name with fullname + crc32_of_fullname + familyname +stylename
std::wstring MakeUniqueFontName(const std::wstring strFullName, const std::wstring strFamilyName, const std::wstring strStyleName)
{
return strFullName + to_wstring(crc32::getCrc32(0, strFullName.c_str(), strFullName.length() * sizeof(WCHAR))) + strFamilyName + strStyleName;
}
#ifndef Assert
#include <crtdbg.h>
#define Assert _ASSERTE
#endif //!Assert
#include "array.h"
#include <strsafe.h>
#include <shlwapi.h>
#include "dll.h"
//kernel32専用GetProcAddressモドキ
FARPROC K32GetProcAddress(LPCSTR lpProcName)
{
#ifndef _WIN64
//序数渡しには対応しない
Assert(!IS_INTRESOURCE(lpProcName));
//kernel32のベースアドレス取得
LPBYTE pBase = (LPBYTE)GetModuleHandleA("kernel32.dll");
//この辺は100%成功するはずなのでエラーチェックしない
PIMAGE_DOS_HEADER pdosh = (PIMAGE_DOS_HEADER)pBase;
Assert(pdosh->e_magic == IMAGE_DOS_SIGNATURE);
PIMAGE_NT_HEADERS pnth = (PIMAGE_NT_HEADERS)(pBase + pdosh->e_lfanew);
Assert(pnth->Signature == IMAGE_NT_SIGNATURE);
const DWORD offs = pnth->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
const DWORD size = pnth->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size;
if (offs == 0 || size == 0) {
return NULL;
}
PIMAGE_EXPORT_DIRECTORY pdir = (PIMAGE_EXPORT_DIRECTORY)(pBase + offs);
DWORD* pFunc = (DWORD*)(pBase + pdir->AddressOfFunctions);
WORD* pOrd = (WORD*)(pBase + pdir->AddressOfNameOrdinals);
DWORD* pName = (DWORD*)(pBase + pdir->AddressOfNames);
for(DWORD i=0; i<pdir->NumberOfFunctions; i++) {
for(DWORD j=0; j<pdir->NumberOfNames; j++) {
if(pOrd[j] != i)
continue;
if(strcmp((LPCSTR)pBase + pName[j], lpProcName) != 0)
continue;
return (FARPROC)(pBase + pFunc[i]);
}
}
return NULL;
#else
Assert(!IS_INTRESOURCE(lpProcName));
//kernel32のベースアドレス取得
WCHAR sysdir[MAX_PATH];
GetWindowsDirectory(sysdir, MAX_PATH);
if (GetModuleHandle(_T("kernelbase.dll"))) //查看自己是否加载了Kernelbase.dll文件存在则说明是win7系统
wcscat(sysdir, L"\\SysWow64\\kernelbase.dll");
else
wcscat(sysdir, L"\\SysWow64\\kernel32.dll"); //不存在就是vista
HANDLE hFile = CreateFile(sysdir, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, NULL, NULL);
if (hFile == INVALID_HANDLE_VALUE)
return NULL;
DWORD dwSize = GetFileSize(hFile, NULL);
BYTE* pMem = new BYTE[dwSize]; //分配内存
ReadFile(hFile, pMem, dwSize, &dwSize, NULL);//读取文件
CloseHandle(hFile);
CMemLoadDll MemDll;
MemDll.MemLoadLibrary(pMem, dwSize, false, false);
delete[] pMem;
return FARPROC((DWORD_PTR)MemDll.MemGetProcAddress(lpProcName)-MemDll.GetImageBase()); //返回偏移值
#endif
}
typedef struct _UNICODE_STRING64 {
USHORT Length;
USHORT MaximumLength;
DWORD64 Buffer;
} UNICODE_STRING64, *PUNICODE_STRING64;
#include <pshpack1.h>
class opcode_data {
private:
BYTE code[0x100];
//注: dllpathをWORD境界にしないと場合によっては正常に動作しない
WCHAR dllpath[MAX_PATH];
UNICODE_STRING64 uniDllPath;
DWORD64 hDumyDllHandle;
public:
opcode_data()
{
//int 03hで埋める
FillMemory(this, sizeof(*this), 0xcc);
}
bool initWow64(LPDWORD remoteaddr, LONG orgEIP) //Wow64初始化
{
//WORD境界チェック
C_ASSERT((offsetof(opcode_data, dllpath) & 1) == 0);
register BYTE* p = code;
#define emit_(t,x) *(t* UNALIGNED)p = (t)(x); p += sizeof(t)
#define emit_db(b) emit_(BYTE, b)
#define emit_dw(w) emit_(WORD, w)
#define emit_dd(d) emit_(DWORD, d)
//なぜかGetProcAddressでLoadLibraryWのアドレスが正しく取れないことがあるので
//kernel32のヘッダから自前で取得する
FARPROC pfn = K32GetProcAddress("LoadLibraryExW");
if(!pfn)
return false;
emit_db(0x60); //pushad
/*
mov eax,fs:[0x30]
mov eax,[eax+0x0c]
mov esi,[eax+0x1c]
lodsd
move ax,[eax+$08]//这个时候eax中保存的就是k32的基址了
在win7获得的是KernelBase.dll的地址
*/
emit_db(0x64);
emit_db(0xA1);
emit_db(0x30);
emit_db(00);
emit_db(00);
emit_db(00);
emit_db(0x8B);
emit_db(0x40);
emit_db(0x0C);
emit_db(0x8B);
emit_db(0x70);
emit_db(0x1C);
emit_db(0xAD);
emit_db(0x8B);
emit_db(0x40);
emit_db(0x08); //use assemble to fetch kernel base
emit_dw(0x006A); //push 0
emit_dw(0x006A); //push 0
emit_db(0x68); //push dllpath
emit_dd((LONG)remoteaddr + offsetof(opcode_data, dllpath));
emit_db(0x05); //add eax, LoadLibraryExW offset
emit_dd(pfn);
emit_dw(0xD0FF); //call eax
emit_db(0x61); //popad
emit_db(0xE9); //jmp original_EIP
emit_dd(orgEIP - (LONG)remoteaddr - (p - code) - sizeof(LONG));
// gdi++.dllのパス
int nSize = GetModuleFileNameW(GetDLLInstance(), dllpath, MAX_PATH);
if (nSize) {
ChangeFileName(dllpath, nSize, L"MTBootStrap.dll");
}
return !!nSize;
}
bool init32(LPDWORD remoteaddr, LONG orgEIP) //32位程序初始化
{
//WORD境界チェック
C_ASSERT((offsetof(opcode_data, dllpath) & 1) == 0);
register BYTE* p = code;
#define emit_(t,x) *(t* UNALIGNED)p = (t)(x); p += sizeof(t)
#define emit_db(b) emit_(BYTE, b)
#define emit_dw(w) emit_(WORD, w)
#define emit_dd(d) emit_(DWORD, d)
//なぜかGetProcAddressでLoadLibraryWのアドレスが正しく取れないことがあるので
//kernel32のヘッダから自前で取得する
FARPROC pfn = K32GetProcAddress("LoadLibraryW");
if(!pfn)
return false;
emit_db(0x60); //pushad
#if _DEBUG
emit_dw(0xC033); //xor eax, eax
emit_db(0x50); //push eax
emit_db(0x50); //push eax
emit_db(0x68); //push dllpath
emit_dd((LONG)remoteaddr + offsetof(opcode_data, dllpath));
emit_db(0x50); //push eax
emit_db(0xB8); //mov eax, MessageBoxW
emit_dd((LONG)MessageBoxW);
emit_dw(0xD0FF); //call eax
#endif
emit_db(0x68); //push dllpath
emit_dd((LONG)remoteaddr + offsetof(opcode_data, dllpath));
emit_db(0xB8); //mov eax, LoadLibraryW
emit_dd(pfn);
emit_dw(0xD0FF); //call eax
emit_db(0x61); //popad
emit_db(0xE9); //jmp original_EIP
emit_dd(orgEIP - (LONG)remoteaddr - (p - code) - sizeof(LONG));
// gdi++.dllのパス
int nSize = GetModuleFileNameW(GetDLLInstance(), dllpath, MAX_PATH);
if (nSize) {
ChangeFileName(dllpath, nSize, L"MTBootStrap.dll");
}
return !!nSize;
}
bool init64From32(DWORD64 remoteaddr, DWORD64 orgEIP)
{
C_ASSERT((offsetof(opcode_data, dllpath) & 1) == 0);
register BYTE* p = code;
#define emit_(t,x) *(t* UNALIGNED)p = (t)(x); p += sizeof(t)
#define emit_db(b) emit_(BYTE, b)
#define emit_dw(w) emit_(WORD, w)
#define emit_dd(d) emit_(DWORD, d)
#define emit_ddp(dp) emit_(DWORD64, dp)
//なぜかGetProcAddressでLoadLibraryWのアドレスが正しく取れないことがあるので
//kernel32のヘッダから自前で取得する
WCHAR x64Addr[30] = { 0 };
if (!GetEnvironmentVariable(L"MACTYPE_X64ADDR", x64Addr, 29)) return false;
DWORD64 pfn = wcstoull(x64Addr, NULL, 10);
//DWORD64 pfn = getenv("MACTYPE_X64ADDR"); //GetProcAddress64(GetModuleHandle64(L"kernelbase.dll"), "LoadLibraryW");
if (!pfn)
return false;
emit_db(0x50); //push rax
emit_db(0x51); //push rcx
emit_db(0x52); //push rdx
emit_db(0x53); //push rbx
emit_dd(0x28ec8348); //sub rsp,28h
emit_db(0x48); //mov rcx, dllpath
emit_db(0xB9);
emit_ddp((DWORD64)remoteaddr + offsetof(opcode_data, dllpath));
emit_db(0x48); //mov rsi, LoadLibraryW
emit_db(0xBE);
emit_ddp(pfn);
//emit_db(0x48);
emit_db(0xFF); //call rdi
emit_db(0xD6);
emit_dd(0x28c48348); //add rsp,28h
emit_db(0x5B);
emit_db(0x5A);
emit_db(0x59);
emit_db(0x58); //popad
emit_db(0x48); //mov rdi, orgRip
emit_db(0xBE);
emit_ddp(orgEIP);
emit_db(0xFF); //jmp rdi
emit_db(0xE6);
// gdi++.dllのパス
int nSize = GetModuleFileNameW(GetDLLInstance(), dllpath, MAX_PATH);
if (nSize) {
ChangeFileName(dllpath, nSize, L"MTBootStrap64.dll");
}
return !!nSize;
}
bool init64From32(DWORD64 remoteaddr, DWORD64 orgEIP, DWORD dwLoaderOffset)
{
C_ASSERT((offsetof(opcode_data, dllpath) & 1) == 0);
int nSize = GetModuleFileNameW(GetDLLInstance(), dllpath, MAX_PATH);
if (nSize) {
ChangeFileName(dllpath, nSize, L"MTBootStrap64.dll");
}
if (!nSize)
return false;
uniDllPath.Length = wcslen(dllpath)*sizeof(WCHAR);
uniDllPath.MaximumLength = uniDllPath.Length+2;
uniDllPath.Buffer = remoteaddr + (DWORD64)offsetof(opcode_data, dllpath); //prepare PUNICODE_STRING for remote process
register BYTE* p = code;
#define emit_(t,x) *(t* UNALIGNED)p = (t)(x); p += sizeof(t)
#define emit_db(b) emit_(BYTE, b)
#define emit_dw(w) emit_(WORD, w)
#define emit_dd(d) emit_(DWORD, d)
#define emit_ddp(dp) emit_(DWORD64, dp)
//get ntdll.dll imagebase
//credit to http://www.52pojie.cn/thread-162625-1-1.html
/*asm:
mov rsi, [gs:60h] ; peb from teb
mov rsi, [rsi+18h] ;_peb_ldr_data from peb
mov rsi, [rsi+30h] ;InInitializationOrderModuleList.Flink, ntdll.dll
;mov rsi, [rsi] ;kernelbase.dll
;mov rsi, [rsi] ;kernel32.dll (not used for win7+)
mov rsi, [rsi+10h]
*/
// emit_db(0xEB);
// emit_db(0xFE); // make a dead loop
emit_db(0x65);
emit_db(0x48);
emit_db(0x8B);
emit_db(0x34);
emit_db(0x25);
emit_db(0x60);
emit_db(0x00);
emit_db(0x00);
emit_db(0x00);
emit_db(0x48);
emit_db(0x8B);
emit_db(0x76);
emit_db(0x18);
emit_db(0x48);
emit_db(0x8B);
emit_db(0x76);
emit_db(0x30);
// emit_db(0x48);
// emit_db(0x8B);
// emit_db(0x36);
emit_db(0x48);
emit_db(0x8B);
emit_db(0x76);
emit_db(0x10);
//rsi = ntdll.dll baseaddress
emit_db(0x50); //push rax
emit_db(0x51); //push rcx
emit_db(0x52); //push rdx
emit_db(0x53); //push rbx
emit_dd(0x28ec8348); //sub rsp,28h
emit_db(0x48);
emit_db(0x31);
emit_db(0xc9); //xor rcx, rcx
emit_db(0x48);
emit_db(0x31);
emit_db(0xd2); //xor rdx, rdx
emit_db(0x49);
emit_db(0xB8);
emit_ddp((DWORD64)remoteaddr + offsetof(opcode_data, uniDllPath));//mov r8, uniDllPath
emit_db(0x49);
emit_db(0xB9);
emit_ddp((DWORD64)remoteaddr + offsetof(opcode_data, hDumyDllHandle));//mov r9, hDumyDllHandle
//emit_db(0x48); //mov rsi, LdrLoadDll
//emit_db(0xBE);
emit_db(0x48);
emit_db(0x81);
emit_db(0xC6); //add rsi, offset LdrLoadDll
emit_dd(dwLoaderOffset);
//emit_db(0x48);
emit_db(0xFF); //call rsi
emit_db(0xD6);
emit_dd(0x28c48348); //add rsp,28h
emit_db(0x5B);
emit_db(0x5A);
emit_db(0x59);
emit_db(0x58); //popad
emit_db(0x48); //mov rdi, orgRip
emit_db(0xBE);
emit_ddp(orgEIP);
emit_db(0xFF); //jmp rdi
emit_db(0xE6);
// gdi++.dllのパス
return !!nSize;
}
bool init(DWORD_PTR* remoteaddr, DWORD_PTR orgEIP)
{
//WORD境界チェック
C_ASSERT((offsetof(opcode_data, dllpath) & 1) == 0);
register BYTE* p = code;
#undef emit_ddp
#define emit_(t,x) *(t* UNALIGNED)p = (t)(x); p += sizeof(t)
#define emit_db(b) emit_(BYTE, b)
#define emit_dw(w) emit_(WORD, w)
#define emit_dd(d) emit_(DWORD, d)
#define emit_ddp(dp) emit_(DWORD_PTR, dp)
//なぜかGetProcAddressでLoadLibraryWのアドレスが正しく取れないことがあるので
//kernel32のヘッダから自前で取得する
FARPROC pfn = GetProcAddress(GetModuleHandle(L"kernel32.dll"), "LoadLibraryW");
//if(!pfn)
// return false;
//emit_db(0xEB);
//emit_db(0xFE); // make a dead loop
emit_db(0x50); //push rax
emit_db(0x51); //push rcx
emit_db(0x52); //push rdx
emit_db(0x53); //push rbx
/*
#ifdef DEBUG
emit_dd(0x28ec8348);
emit_db(0x48);
emit_db(0x31);
emit_db(0xD0); //xor rax,rax
emit_db(0x48);
emit_db(0x31);
emit_db(0xC9); //xor rcx,rcx
emit_db(0x48);
emit_db(0x31);
emit_db(0xD2); //xor rdx,rdx
emit_db(0x45);
emit_db(0x31);
emit_db(0xC0); //xor r8d,r8d
emit_db(0x45);
emit_db(0x31);
emit_db(0xC9); //xor r9d,r9d
emit_db(0x48); //mov rsi, MessageBoxW
emit_db(0xBE);
emit_ddp((DWORD_PTR)MessageBoxW);
emit_db(0xFF);
emit_db(0xD6);
emit_dd(0x28c48348);
#endif*/
/*
//Debug function2, Sleep for 10sec.
emit_dd(0x28ec8348);
emit_db(0x48); //mov rsi, MessageBoxW
emit_db(0xBE);
emit_ddp((DWORD_PTR)Sleep);
emit_db(0x48); emit_db(0xc7); emit_db(0xc1); emit_db(0x10); emit_db(0x27); emit_db(0x00); emit_db(0x00);
emit_db(0xFF);
emit_db(0xD6);
emit_dd(0x28c48348);
*/
emit_dd(0x28ec8348); //sub rsp,28h
emit_db(0x48); //mov rcx, dllpath
emit_db(0xB9);
emit_ddp((DWORD_PTR)remoteaddr + offsetof(opcode_data, dllpath));
emit_db(0x48); //mov rsi, LoadLibraryW
emit_db(0xBE);
emit_ddp(pfn);
//emit_db(0x48);
emit_db(0xFF); //call rdi
emit_db(0xD6);
emit_dd(0x28c48348); //add rsp,28h
emit_db(0x5B);
emit_db(0x5A);
emit_db(0x59);
emit_db(0x58); //popad
emit_db(0x48); //mov rdi, orgRip
emit_db(0xBE);
emit_ddp(orgEIP);
emit_db(0xFF); //jmp rdi
emit_db(0xE6);
// gdi++.dllのパス
int nSize = GetModuleFileNameW(GetDLLInstance(), dllpath, MAX_PATH);
if (nSize) {
ChangeFileName(dllpath, nSize, L"MTBootStrap64.dll");
}
return !!nSize;
}
};
#include <poppack.h>
// 安全的取得真实系统信息
VOID SafeGetNativeSystemInfo(__out LPSYSTEM_INFO lpSystemInfo)
{
if (NULL == lpSystemInfo) return;
typedef VOID(WINAPI *LPFN_GetNativeSystemInfo)(LPSYSTEM_INFO lpSystemInfo);
LPFN_GetNativeSystemInfo fnGetNativeSystemInfo = (LPFN_GetNativeSystemInfo)GetProcAddress(GetModuleHandle(_T("kernel32")), "GetNativeSystemInfo");;
if (NULL != fnGetNativeSystemInfo)
{
fnGetNativeSystemInfo(lpSystemInfo);
}
else
{
GetSystemInfo(lpSystemInfo);
}
}
// 获取操作系统位数
int GetSystemBits()
{
SYSTEM_INFO si;
SafeGetNativeSystemInfo(&si);
if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64 ||
si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_IA64)
{
return 64;
}
return 32;
}
static bool bIsOS64 = GetSystemBits() == 64; // check if running in a x64 system.
#ifdef _M_IX86
// 止めているプロセスにLoadLibraryするコードを注入
EXTERN_C BOOL WINAPI GdippInjectDLL(const PROCESS_INFORMATION* ppi)
{
BOOL bIsX64Proc = false;
if (bIsOS64 && IsWow64Process(ppi->hProcess, &bIsX64Proc) && !bIsX64Proc)
{
//x86 process launches a x64 process
_CONTEXT64 ctx = { 0 };
ctx.ContextFlags = CONTEXT_CONTROL;
if (!GetThreadContext64(ppi->hThread, &ctx))
return false;
static bool bTryLoadDll64 = false;
static DWORD dwLoaderOffset = 0;
if (!bTryLoadDll64) {
bTryLoadDll64 = true;
GetEnvironmentVariable(L"MACTYPE_X64ADDR", NULL, 0);
if (GetLastError() == ERROR_ENVVAR_NOT_FOUND) {
DWORD64 hNtdll = 0;
hNtdll = GetModuleHandle64(L"ntdll.dll");
if (hNtdll) {
DWORD64 pfnLdrAddr = GetProcAddress64(hNtdll, "LdrLoadDll");
if (pfnLdrAddr) {
dwLoaderOffset = (DWORD)(pfnLdrAddr - hNtdll);
}
}
}
}
opcode_data local;
DWORD64 remote = VirtualAllocEx64(ppi->hProcess, NULL, sizeof(opcode_data), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if (!remote)
return false;
bool basmIniter = dwLoaderOffset ? local.init64From32(remote, ctx.Rip, dwLoaderOffset) : local.init64From32(remote, ctx.Rip);
if (!basmIniter || !WriteProcessMemory64(ppi->hProcess, remote, &local, sizeof(opcode_data), NULL)) {
VirtualFreeEx64(ppi->hProcess, remote, 0, MEM_RELEASE);
return false;
}
//FlushInstructionCache64(ppi->hProcess, remote, sizeof(opcode_data));
//FARPROC a=(FARPROC)remote;
//a();
ctx.Rip = (DWORD64)remote;
return !!SetThreadContext64(ppi->hThread, &ctx);
}
else {
CONTEXT ctx = { 0 };
ctx.ContextFlags = CONTEXT_CONTROL;
if (!GetThreadContext(ppi->hThread, &ctx))
return false;
opcode_data local;
opcode_data* remote = (opcode_data*)VirtualAllocEx(ppi->hProcess, NULL, sizeof(opcode_data), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if (!remote)
return false;
if (!local.init32((LPDWORD)remote, ctx.Eip)
|| !WriteProcessMemory(ppi->hProcess, remote, &local, sizeof(opcode_data), NULL)) {
VirtualFreeEx(ppi->hProcess, remote, 0, MEM_RELEASE);
return false;
}
FlushInstructionCache(ppi->hProcess, remote, sizeof(opcode_data));
ctx.Eip = (DWORD)remote;
return !!SetThreadContext(ppi->hThread, &ctx);
}
}
#else
EXTERN_C BOOL WINAPI GdippInjectDLL(const PROCESS_INFORMATION* ppi)
{
BOOL bWow64 = false;
IsWow64Process(ppi->hProcess, &bWow64);
if (bWow64)
{
WOW64_CONTEXT ctx = { 0 };
ctx.ContextFlags = CONTEXT_CONTROL;
//CREATE_SUSPENDEDなので基本的に成功するはず
if(!Wow64GetThreadContext(ppi->hThread, &ctx))
return false;
opcode_data local;
LPVOID remote = VirtualAllocEx(ppi->hProcess, NULL, sizeof(opcode_data), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if(!remote)
return false;
if(!local.initWow64((LPDWORD)remote, ctx.Eip)
|| !WriteProcessMemory(ppi->hProcess, remote, &local, sizeof(opcode_data), NULL)) {
VirtualFreeEx(ppi->hProcess, remote, 0, MEM_RELEASE);
return false;
}
FlushInstructionCache(ppi->hProcess, remote, sizeof(opcode_data));
//FARPROC a=(FARPROC)remote;
//a();
ctx.Eip = (DWORD)remote;
return !!Wow64SetThreadContext(ppi->hThread, &ctx);
}
else
{
CONTEXT ctx = { 0 };
ctx.ContextFlags = CONTEXT_CONTROL;
//CREATE_SUSPENDEDなので基本的に成功するはず
if(!GetThreadContext(ppi->hThread, &ctx))
return false;
opcode_data local;
LPVOID remote = VirtualAllocEx(ppi->hProcess, NULL, sizeof(opcode_data), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if(!remote)
return false;
if(!local.init((DWORD_PTR*)remote, ctx.Rip)
|| !WriteProcessMemory(ppi->hProcess, remote, &local, sizeof(opcode_data), NULL)) {
VirtualFreeEx(ppi->hProcess, remote, 0, MEM_RELEASE);
return false;
}
FlushInstructionCache(ppi->hProcess, remote, sizeof(opcode_data));
//FARPROC a=(FARPROC)remote;
//a();
ctx.Rip = (DWORD_PTR)remote;
return !!SetThreadContext(ppi->hThread, &ctx);
}
}
#endif
template <typename _TCHAR>
int strlendb(const _TCHAR* psz)
{
const _TCHAR* p = psz;
while (*p) {
for (; *p; p++);
p++;
}
return p - psz + 1;
}
template <typename _TCHAR>
_TCHAR* strdupdb(const _TCHAR* psz, int pad)
{
int len = strlendb(psz);
_TCHAR* p = (_TCHAR*)calloc(sizeof(_TCHAR), len + pad);
if(p) {
memcpy(p, psz, sizeof(_TCHAR) * len);
}
return p;
}
bool MultiSzToArray(LPWSTR p, CArray<LPWSTR>& arr)
{
for (; *p; ) {
LPWSTR cp = _wcsdup(p);
if(!cp || !arr.Add(cp)) {
free(cp);
return false;
}
for (; *p; p++);
p++;
}
return true;
}
LPWSTR ArrayToMultiSz(CArray<LPWSTR>& arr)
{
size_t cch = 1;
for (int i=0; i<arr.GetSize(); i++) {
cch += wcslen(arr[i]) + 1;
}
LPWSTR pmsz = (LPWSTR)calloc(sizeof(WCHAR), cch);
if (!pmsz)
return NULL;
LPWSTR p = pmsz;
for (int i=0; i<arr.GetSize(); i++) {
StringCchCopyExW(p, cch, arr[i], &p, &cch, STRSAFE_NO_TRUNCATION);
p++;
}
*p = 0;
return pmsz;
}
bool AddPathEnv(CArray<LPWSTR>& arr, LPWSTR dir, int dirlen)
{
for (int i=0; i<arr.GetSize(); i++) {
LPWSTR env = arr[i];
if (_wcsnicmp(env, L"PATH=", 5)) {
continue;
}
LPWSTR p = env + 5;
LPWSTR pp = p;
for (; ;) {
for (; *p && *p != L';'; p++);
int len = p - pp;
if (len == dirlen && !_wcsnicmp(pp, dir, dirlen)) {
return false;
}
if (!*p)
break;
pp = p + 1;
p++;
}
size_t cch = wcslen(env) + MAX_PATH + 4;
env = (LPWSTR)realloc(env, sizeof(WCHAR) * cch);
if(env) {
StringCchCatW(env, cch, L";");
StringCchCatW(env, cch, dir);
arr[i] = env;
return true;
}
return false;
}
size_t cch = dirlen + sizeof("PATH=") + 1;
LPWSTR p = (LPWSTR)calloc(sizeof(WCHAR), cch);
if(p) {
StringCchCopyW(p, cch, L"PATH=");
StringCchCatW(p, cch, dir);
if (arr.Add(p)) {
return true;
}
free(p);
}
return false;
}
bool AddX64Env(CArray<LPWSTR>& arr)
{
FARPROC k32 = GetProcAddress(GetModuleHandle(L"kernel32.dll"), "LoadLibraryW");
WCHAR szAddr[20] = { 0 };
_ui64tow((DWORD64)k32, szAddr, 10);
//wsprintf(szAddr, L"%Ld", (DWORD_PTR)k32);
size_t cch = wcslen(szAddr) + sizeof("MACTYPE_X64ADDR=") + 1;
LPWSTR p = (LPWSTR)calloc(sizeof(WCHAR), cch);
if (p) {
StringCchCopyW(p, cch, L"MACTYPE_X64ADDR=");
StringCchCatW(p, cch, szAddr);
if (arr.Add(p)) {
return true;
}
free(p);
}
return false;
}
EXTERN_C LPWSTR WINAPI GdippEnvironment(DWORD& dwCreationFlags, LPVOID lpEnvironment)
{
#ifndef _WIN64
return NULL;
#endif
TCHAR dir[MAX_PATH];
int dirlen = GetModuleFileName(GetDLLInstance(), dir, MAX_PATH);
LPTSTR lpfilename=dir+dirlen;
while (lpfilename>dir && *lpfilename!=_T('\\') && *lpfilename!=_T('/')) --lpfilename;
*lpfilename = 0;
dirlen = wcslen(dir);
LPWSTR pEnvW = NULL;
if (lpEnvironment) {
if (dwCreationFlags & CREATE_UNICODE_ENVIRONMENT) {
pEnvW = strdupdb((LPCWSTR)lpEnvironment, MAX_PATH + 1);
} else {
int alen = strlendb((LPCSTR)lpEnvironment);
int wlen = MultiByteToWideChar(CP_ACP, 0, (LPCSTR)lpEnvironment, alen, NULL, 0) + 1;
pEnvW = (LPWSTR)calloc(sizeof(WCHAR), wlen + MAX_PATH + 1);
if (pEnvW) {
MultiByteToWideChar(CP_ACP, 0, (LPCSTR)lpEnvironment, alen, pEnvW, wlen);
}
}
} else {
LPWSTR block = (LPWSTR)GetEnvironmentStringsW();
if (block) {
pEnvW = strdupdb(block, MAX_PATH + 1);
FreeEnvironmentStrings(block);
}
}
if (!pEnvW) {
return NULL;
}
CArray<LPWSTR> envs;
bool ret = MultiSzToArray(pEnvW, envs);
free(pEnvW);
pEnvW = NULL;
/*if (ret) {
ret = AddPathEnv(envs, dir, dirlen);
}*/
#ifdef _WIN64
{
GetEnvironmentVariableW(L"MACTYPE_X64ADDR", NULL, 0);
if (GetLastError() == ERROR_ENVVAR_NOT_FOUND) {
ret = AddX64Env(envs);
}
}
#endif
if (ret) {
pEnvW = ArrayToMultiSz(envs);
}
for (int i=0; i<envs.GetSize(); free(envs[i++]));
if (!pEnvW) {
return NULL;
}
#ifdef _DEBUG
{
LPWSTR tmp = strdupdb(pEnvW, 0);
LPWSTR tmpe = tmp + strlendb(tmp);
PathRemoveFileSpec(dir);
for (LPWSTR z=tmp; z<tmpe; z++)if(!*z)*z=L'\n';
StringCchCatW(dir,MAX_PATH,L"\\");
StringCchCatW(dir,MAX_PATH,L"gdienv.txt");
HANDLE hf = CreateFileW(dir,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,0,NULL);
if(hf) {
DWORD cb;
WORD w = 0xfeff;
WriteFile(hf,&w, sizeof(WORD), &cb, 0);
WriteFile(hf,tmp, sizeof(WCHAR) * (tmpe - tmp), &cb, 0);
SetEndOfFile(hf);
CloseHandle(hf);
free(tmp);
}
}
#endif
dwCreationFlags |= CREATE_UNICODE_ENVIRONMENT;
return pEnvW;
}
void DebugOut(const WCHAR* szFormat, ...) {
#ifdef TRACE
va_list args;
va_start(args, szFormat);
WCHAR buffer[1024] = { 0 };
vswprintf(buffer, szFormat, args);
std::wstring fullmsg = L"[MTCore] " + std::wstring(buffer);
OutputDebugString(fullmsg.c_str());
#endif
}