diff --git a/cpp/shareddllproxy/LR.cpp b/cpp/shareddllproxy/LR.cpp deleted file mode 100644 index 081ec19a..00000000 --- a/cpp/shareddllproxy/LR.cpp +++ /dev/null @@ -1,61 +0,0 @@ - -#include - -struct LRProfile -{ - UINT CodePage; - UINT LCID; - long Bias; - int HookIME; - int HookLCID; -}; -int WrtieConfigFileMap(LRProfile *profile) -{ - SetEnvironmentVariableW(L"LRCodePage", (LPCWSTR)&profile->CodePage); - SetEnvironmentVariableW(L"LRLCID", (LPCWSTR)&profile->LCID); - SetEnvironmentVariableW(L"LRBIAS", (LPCWSTR)&profile->Bias); - SetEnvironmentVariableW(L"LRHookIME", (LPCWSTR)&profile->HookIME); - SetEnvironmentVariableW(L"LRHookLCID", (LPCWSTR)&profile->HookLCID); - return 0; -} -// https://github.com/InWILL/Locale_Remulator/blob/master/LRProc/LRProc.cpp -int LRwmain(int argc, wchar_t *wargv[]) -{ - char current[2048]; - GetModuleFileNameA(NULL, current, 2048); - std::string _s = current; - _s = _s.substr(0, _s.find_last_of("\\")); - auto dllpath = _s + "\\Locale_Remulator\\"; - auto targetexe = wargv[6]; - std::wstring cmd = L""; - for (int i = 6; i < argc; i++) - { - cmd += L"\""; - cmd += wargv[i]; - cmd += L"\" "; - } - DWORD type; - GetBinaryTypeW(targetexe, &type); - if (type == 6) - dllpath += "LRHookx64.dll"; - else - dllpath += "LRHookx32.dll"; - LRProfile beta; - beta.CodePage = std::stoi(wargv[1]); // 932; - beta.LCID = std::stoi(wargv[2]); // 0x0411; - beta.Bias = std::stoi(wargv[3]); // 540; // Bias will become negative in HookGetTimeZoneInformation - beta.HookIME = std::stoi(wargv[4]); // false; - beta.HookLCID = std::stoi(wargv[5]); // true; - - WrtieConfigFileMap(&beta); - STARTUPINFOW si; - PROCESS_INFORMATION pi; - ZeroMemory(&si, sizeof(STARTUPINFO)); - ZeroMemory(&pi, sizeof(PROCESS_INFORMATION)); - si.cb = sizeof(STARTUPINFO); - DetourCreateProcessWithDllExW(NULL, cmd.data(), NULL, - NULL, FALSE, CREATE_DEFAULT_ERROR_MODE, NULL, NULL, - &si, &pi, dllpath.c_str(), NULL); - - return 0; -} \ No newline at end of file diff --git a/cpp/shareddllproxy/le.cpp b/cpp/shareddllproxy/le.cpp deleted file mode 100644 index 9815f590..00000000 --- a/cpp/shareddllproxy/le.cpp +++ /dev/null @@ -1,151 +0,0 @@ - -#define SHIFT_JIS 932 -namespace -{ - int GetCharsetFromANSICodepage(int ansicp) - { - auto charset = ANSI_CHARSET; - - switch (ansicp) - { - case 932: // Japanese - charset = SHIFTJIS_CHARSET; - break; - case 936: // Simplified Chinese - charset = GB2312_CHARSET; - break; - case 949: // Korean - charset = HANGEUL_CHARSET; - break; - case 950: // Traditional Chinese - charset = CHINESEBIG5_CHARSET; - break; - case 1250: // Eastern Europe - charset = EASTEUROPE_CHARSET; - break; - case 1251: // Russian - charset = RUSSIAN_CHARSET; - break; - case 1252: // Western European Languages - charset = ANSI_CHARSET; - break; - case 1253: // Greek - charset = GREEK_CHARSET; - break; - case 1254: // Turkish - charset = TURKISH_CHARSET; - break; - case 1255: // Hebrew - charset = HEBREW_CHARSET; - break; - case 1256: // Arabic - charset = ARABIC_CHARSET; - break; - case 1257: // Baltic - charset = BALTIC_CHARSET; - break; - } - - return charset; - } - - // https://github.com/xupefei/Locale-Emulator-Core/blob/ae7160dc5deb97947396abcd784f9b98b6ee38b3/LocaleEmulator/LocaleEmulator.h#L131 - - typedef struct - { - USHORT Length; - USHORT MaximumLength; - union - { - PWSTR Buffer; - ULONG64 Dummy; - }; - - } UNICODE_STRING3264, *PUNICODE_STRING3264; - - typedef UNICODE_STRING3264 UNICODE_STRING64; - typedef PUNICODE_STRING3264 PUNICODE_STRING64; - typedef struct - { - ULONG64 Root; - UNICODE_STRING64 SubKey; - UNICODE_STRING64 ValueName; - ULONG DataType; - PVOID64 Data; - ULONG64 DataSize; - - } REGISTRY_ENTRY64; - - typedef struct - { - REGISTRY_ENTRY64 Original; - REGISTRY_ENTRY64 Redirected; - - } REGISTRY_REDIRECTION_ENTRY64, *PREGISTRY_REDIRECTION_ENTRY64; - typedef struct - { - ULONG AnsiCodePage; - ULONG OemCodePage; - ULONG LocaleID; - ULONG DefaultCharset; - ULONG HookUILanguageApi; - WCHAR DefaultFaceName[LF_FACESIZE]; - TIME_ZONE_INFORMATION Timezone; - ULONG64 NumberOfRegistryRedirectionEntries; - REGISTRY_REDIRECTION_ENTRY64 RegistryReplacement[1]; - - } LOCALE_ENUMLATOR_ENVIRONMENT_BLOCK, *PLOCALE_ENUMLATOR_ENVIRONMENT_BLOCK, LEB, *PLEB; - -} -int lewmain(int argc, wchar_t *argv[]) -{ - /* - argv[0] le - argv[1] ANSICodePage - argv[2] OEMCodePage - argv[3] LCID - argv[4] dirname - argv[5] RedirectRegistry - argv[6] HookUILanguageAPI - argvx exe - ... args - */ -#define exeargi 7 - std::wstring cmd = L""; - for (int i = exeargi; i < argc; i++) - { - cmd += L"\""; - cmd += argv[i]; - cmd += L"\" "; - } - std::wstring process = argv[exeargi]; - auto ANSICodePage = std::stoi(argv[1]);//932 SHIFT_JIS - auto OEMCodePage = std::stoi(argv[2]);//932 SHIFT_JIS - auto LCID = std::stoi(argv[3]);//0x11 LANG_JAPANESE - auto dirname = argv[4]; - auto RedirectRegistry = std::stoi(argv[5]); - auto HookUILanguageAPI = std::stoi(argv[6]); - - PROCESS_INFORMATION info = {}; - if (HMODULE localeEmulator = LoadLibraryW(L".\\LoaderDll")) - { - - LEB _leb; - ZeroMemory(&_leb, sizeof(LEB)); - _leb.AnsiCodePage = ANSICodePage; - _leb.OemCodePage = OEMCodePage; - _leb.LocaleID = LCID; - _leb.DefaultCharset = GetCharsetFromANSICodepage(ANSICodePage); - _leb.HookUILanguageApi = HookUILanguageAPI; - GetTimeZoneInformation(&_leb.Timezone); - auto ret = ((LONG(__stdcall *)(LEB *, LPCWSTR appName, LPWSTR commandLine, LPCWSTR currentDir, void *, void *, PROCESS_INFORMATION *, void *, void *, void *, void *)) - GetProcAddress(localeEmulator, "LeCreateProcess"))(&_leb, process.c_str(), cmd.data(), dirname, NULL, NULL, &info, NULL, NULL, NULL, NULL); - if (ret == 0) - { - WaitForSingleObject(info.hProcess, INFINITE); - CloseHandle(info.hProcess); - CloseHandle(info.hThread); - } - } - return 1; -} diff --git a/cpp/shareddllproxy/ntleas.cpp b/cpp/shareddllproxy/ntleas.cpp deleted file mode 100644 index f1609c73..00000000 --- a/cpp/shareddllproxy/ntleas.cpp +++ /dev/null @@ -1,685 +0,0 @@ - -#define NTLEA_PARAMETERS_LENGTH (LF_FACESIZE + 20) - -#define szRcpIntMtx "RcpInternalMutex" -#define szTranslation "\\VarFileInfo\\Translation" -#define szRcpEvent "RcpEvent000" -#define szRcpFileMap "RcpFileMap000" -#define szRshFileMap "RshFileMap000" -#define szCaption "NT Locale Emulator Advance" - -#if defined(_AMD64_) -#define RegIP Rip -#define IMAGE_FILE_MACHINE_VALID IMAGE_FILE_MACHINE_AMD64 -#define IMAGE_FILE_MACHINE_INVALID IMAGE_FILE_MACHINE_I386 -#define IMAGE_FILE_MACHINE_ESTRING L"x86" -#define WM_CLASSMASK 0xFFFFFFFF00000000 -#elif defined(_X86_) -#define RegIP Eip -#define IMAGE_FILE_MACHINE_VALID IMAGE_FILE_MACHINE_I386 -#define IMAGE_FILE_MACHINE_INVALID IMAGE_FILE_MACHINE_AMD64 -#define IMAGE_FILE_MACHINE_ESTRING L"x64" -#define WM_CLASSMASK 0xFFFF0000 -#endif - -typedef enum -{ - ERR_UKNOWN = -10000, - ERR_PE_FORMAT_INVALID = -10001, - ERR_MULTIPLE_INSTANCE = -10002, - ERR_EXECUTABLE_MISSING = -10003, - ERR_EXECUTABLE_INVALID = -10004, - ERR_PROCESS_CREATE_FAILED = -10005, - ERR_NTLEA_DLL_MISSING = -10006, - ERR_FAILED_ALLOCATE_MEM = -10007, - ERR_HOOKPROCESS_MISSING = -10008, - ERR_FAILED_QUERY_PROCESS = -10009, - ERR_FAILED_READFILEINFO = -10010, - ERR_UNKNOWN_FORMAT_INVALID = -10011, - // ----- - ERR_REDIRECTED_PLATFORM = 10001, -} NtleaErrorNo; - -typedef struct -{ - // -------------- inputparam - DWORD dwCompOption; - DWORD dwCodePage; - DWORD dwLCID; - DWORD dwTimeZone; - DWORD dwSpApp; - BYTE FontFaceName[LF_FACESIZE]; - // -------------- internal - HANDLE RcpEvent, RcpFileMap; // HANDLE - LPVOID FileMappingAddress, ImageBase, EntryPoint; // LPVOID - HMODULE hInstance; - // ... -} NtleaProcess; - -#if defined(_AMD64_) -static WCHAR rcpHookDll[] = L"ntleak.dll"; // default use ... -#elif defined(_X86_) -static WCHAR rcpHookDll[] = L"ntleai.dll"; // default use ... -#endif -extern LPCWSTR szRcpHookDLL = rcpHookDll; - -NtleaErrorNo PrintErrorString(NtleaErrorNo errnum); - -#include -#include - -void ParseFileMapParams(NtleaProcess *process) -{ - HANDLE hRshFileMap = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, NTLEA_PARAMETERS_LENGTH, szRshFileMap); - if (GetLastError()) - { // mapping not found - LPVOID hView = MapViewOfFile(hRshFileMap, FILE_MAP_ALL_ACCESS, 0, 0, NTLEA_PARAMETERS_LENGTH); - process->dwCompOption = *((LPDWORD)hView + 0); - process->dwCodePage = *((LPDWORD)hView + 1); - process->dwLCID = *((LPDWORD)hView + 2); - process->dwTimeZone = *((LPDWORD)hView + 3); - process->dwSpApp = *((LPDWORD)hView + 4); - lstrcpyA((char *)process->FontFaceName, (char const *)hView + 20); - } - else - { // 20 BYTES - process->dwCompOption = 0; - process->dwCodePage = 932; - process->dwLCID = 0x411; - process->dwTimeZone = (DWORD)-540; - process->dwSpApp = 100; // ntlea use this value /100 for font-ratio ! - *(LPDWORD)process->FontFaceName = 0; // copy empty - } - CloseHandle(hRshFileMap); -} - -int CreateFileMapInf(NtleaProcess *process, HANDLE hexecute, LPBYTE FileBuffer) -{ - DWORD dwread; - if (ReadFile(hexecute, FileBuffer, 1024, &dwread, NULL) && (*(WORD *)FileBuffer == 0x5A4D)) - { - CloseHandle(hexecute); - // now parse the entrypoint : - IMAGE_DOS_HEADER *pdoshead = (IMAGE_DOS_HEADER *)(FileBuffer); - IMAGE_NT_HEADERS *pntheads = (IMAGE_NT_HEADERS *)(FileBuffer + pdoshead->e_lfanew); - // check x86 or x64 or ... ??? - if (pntheads->FileHeader.Machine == IMAGE_FILE_MACHINE_VALID || - pntheads->FileHeader.Machine == IMAGE_FILE_MACHINE_INVALID) - { - // calc the entry point ?? - process->ImageBase = (LPVOID)(DWORD_PTR)(pntheads->OptionalHeader.ImageBase); - process->EntryPoint = (LPVOID)(DWORD_PTR)(pntheads->OptionalHeader.AddressOfEntryPoint); - // build event & filemapping : - process->RcpEvent = CreateEventA(NULL, FALSE, FALSE, szRcpEvent); - process->RcpFileMap = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, sizeof(LPVOID), szRcpFileMap); - process->FileMappingAddress = MapViewOfFile(process->RcpFileMap, FILE_MAP_ALL_ACCESS, 0, 0, sizeof(LPVOID)); - // return continue flag or not : - return (pntheads->FileHeader.Machine == IMAGE_FILE_MACHINE_VALID) ? (0) : (ERR_PE_FORMAT_INVALID); - } - else - { - return (ERR_UNKNOWN_FORMAT_INVALID); - } - } - else - { - return (ERR_FAILED_READFILEINFO); - } -} - -int DeleteFileMapping(NtleaProcess *process) -{ - if (process->FileMappingAddress) - UnmapViewOfFile(process->FileMappingAddress); - if (process->RcpFileMap) - CloseHandle(process->RcpFileMap); - if (process->RcpEvent) - CloseHandle(process->RcpEvent); - return (0); -} - -// -------------------------------- - -int CreateProcessStartW(NtleaProcess *process, wchar_t const *applicationPath) -{ - DWORD bintype; - HANDLE hexecute; - BYTE FileBuffer[1024]; - if (GetBinaryTypeW(applicationPath, &bintype)) - { - hexecute = CreateFileW(applicationPath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); - if (hexecute == INVALID_HANDLE_VALUE) - { - return ERR_EXECUTABLE_MISSING; // exit !! - } - else - { - return CreateFileMapInf(process, hexecute, FileBuffer); - } - } - else - { - return ERR_EXECUTABLE_INVALID; // exit !! - } -} - -int CreateProcessBeginW(NtleaProcess *process, wchar_t const *applicationPath) -{ - // ParseFileMapParams(process); - return CreateProcessStartW(process, applicationPath); -} -// first see MSDN : http://msdn.microsoft.com/en-us/library/windows/desktop/ms684280(v=vs.85).aspx -// read process address, see also : http://www.cnblogs.com/jeJee/archive/2013/03/08/2950345.html -// for more info, see : http://stackoverflow.com/questions/8447801/getting-a-module-handle-from-other-process -// and : http://stackoverflow.com/questions/8336214/how-can-i-get-a-process-entry-point-address -typedef struct -{ - DWORD_PTR ExitStatus; - DWORD_PTR PebBaseAddress; - DWORD_PTR AffinityMask; - DWORD_PTR BasePriority; - ULONG_PTR UniqueProcessId; - ULONG_PTR InheritedFromUniqueProcessId; -} PROCESS_BASIC_INFORMATION; - -typedef enum -{ - ProcessBasicInformation = 0, - ProcessDebugPort = 7, - ProcessWow64Information = 26, - ProcessImageFileName = 27, - ProcessBreakOnTermination = 28, -} PROCESSINFOCLASS; - -int ResetBaseAddress(NtleaProcess *process, PROCESS_INFORMATION const *proinfo) -{ - PROCESS_BASIC_INFORMATION pbi; - SIZE_T bytesRead; - DWORD_PTR baseAddr; - // ------------------------------- - typedef NTSTATUS(WINAPI * PROCNTQSIP)(HANDLE, PROCESSINFOCLASS, PVOID, ULONG, PULONG); - PROCNTQSIP NtQueryInformationProcess = (PROCNTQSIP)GetProcAddress(GetModuleHandleA("ntdll"), "NtQueryInformationProcess"); - if (!NtQueryInformationProcess) - { - return ERR_FAILED_QUERY_PROCESS; - } - // Retrieve information : - NTSTATUS ret = NtQueryInformationProcess(proinfo->hProcess, ProcessBasicInformation, (PVOID)&pbi, sizeof(PROCESS_BASIC_INFORMATION), NULL); - fprintf(stderr, "QueryProcess info pointer : %p, ret : %d\n", NtQueryInformationProcess, ret); - if (ret >= 0) - { - ReadProcessMemory(proinfo->hProcess, (PVOID)(pbi.PebBaseAddress + 2 * sizeof(PVOID)), &baseAddr, sizeof(baseAddr), &bytesRead); - process->EntryPoint = (LPBYTE)process->EntryPoint + baseAddr; - fprintf(stderr, "ProcessID : %u, EntryPoint_1 : %p\n", proinfo->dwProcessId, process->EntryPoint); - } - else - { - process->EntryPoint = (LPBYTE)process->EntryPoint + (DWORD_PTR)process->ImageBase; - fprintf(stderr, "ProcessID : %u, EntryPoint_0 : %p\n", proinfo->dwProcessId, process->EntryPoint); - } - return (0); -} - -int ResetWorkingDirectory(HANDLE hprocess) -{ - WCHAR exepath[MAX_PATH * 2]; - DWORD len = ARRAYSIZE(exepath); // i think it should be enough ?? -#if 1 - BOOL(WINAPI * pfnQueryFullProcessImageName) - (HANDLE, DWORD, LPWSTR, PDWORD); - pfnQueryFullProcessImageName = (BOOL(WINAPI *)(HANDLE, DWORD, LPWSTR, PDWORD)) - GetProcAddress(LoadLibraryW(L"kernel32.dll"), "QueryFullProcessImageNameW"); - // ----------------------------- XP won't support this, but just skip that's ok - if (pfnQueryFullProcessImageName && pfnQueryFullProcessImageName(hprocess, 0, exepath, &len)) -#else - DWORD(WINAPI * pfnGetModuleFileNameEx) - (HANDLE hProcess, HMODULE hModule, LPWSTR lpFilename, DWORD nSize); - HMODULE hModuleLib = LoadLibraryW(L"psapi.dll"); - pfnGetModuleFileNameEx = (DWORD(WINAPI *)(HANDLE, HMODULE, LPWSTR, DWORD))GetProcAddress(hModuleLib, "GetModuleFileNameExW"); - len = pfnGetModuleFileNameEx(hProcess, NULL, exepath, len); - FreeLibrary(hModuleLib); - // ----------------------------- - if (len > 0) -#endif - { - LPCWSTR p = len + exepath; - while (p > exepath && *p != L'\\') - --p; - if (*p == L'\\') - { - exepath[p - exepath] = L'\0'; // make as tail - SetCurrentDirectoryW(exepath); - fprintf(stderr, "set current working directory to %S\n", exepath); - } - } - return (0); -} - -int InjectProcessDLL(NtleaProcess const *process, PROCESS_INFORMATION const *proinfo) -{ - // ParameterExists : CurrentDir with PathLength + szRcpHookDLL, then : FontFaceName with strlen, 4 * DWORD - WCHAR CurrentDir[MAX_PATH + (NTLEA_PARAMETERS_LENGTH / 2)]; - // Search Directories : - - GetModuleFileNameW(NULL, CurrentDir, 2048); - std::wstring _s = CurrentDir; - _s = _s.substr(0, _s.find_last_of(L"\\")); - auto dllpath = _s + L"\\NTLEAS\\"; - dllpath += szRcpHookDLL; - lstrcpyW(CurrentDir, dllpath.c_str()); - - UINT PathLength = dllpath.size(); - - if (PathLength == 0) - { - return ERR_NTLEA_DLL_MISSING; - } // can't find dll ! - // ----------------------- - LPBYTE p = (LPBYTE)(CurrentDir + lstrlenW(CurrentDir) + 1); - lstrcpyA((LPSTR)p, (LPSTR)process->FontFaceName); - p += lstrlenA((LPSTR)process->FontFaceName) + 1; - *((LPDWORD)p) = process->dwCompOption; - p += sizeof(DWORD); - *((LPDWORD)p) = process->dwCodePage; - p += sizeof(DWORD); - *((LPDWORD)p) = process->dwLCID; - p += sizeof(DWORD); - *((LPDWORD)p) = process->dwTimeZone; - p += sizeof(DWORD); - // allocate memory for remote-process DLL parameters : - DWORD length = (DWORD)(p - (LPBYTE)CurrentDir); - LPVOID BaseAddress = VirtualAllocEx(proinfo->hProcess, NULL, length, MEM_COMMIT, PAGE_EXECUTE_READWRITE); - if (!BaseAddress) - { - return ERR_FAILED_ALLOCATE_MEM; // failed exit - } - *(LPVOID *)process->FileMappingAddress = BaseAddress; // required for other thread usage ?? - WriteProcessMemory(proinfo->hProcess, BaseAddress, CurrentDir, length, NULL); - // why [ecx(LoadLibraryW) + 2] for LoadLibraryW in NTLEA ??? - HANDLE hRemoteThread; - DWORD dwRemoteThreadId; - hRemoteThread = CreateRemoteThread(proinfo->hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)LoadLibraryW, BaseAddress, 0, &dwRemoteThreadId); - fprintf(stderr, "remote thread handle : 0x%p, threadid : %u\n", hRemoteThread, dwRemoteThreadId); - CloseHandle(hRemoteThread); - // ----------------------- - return (0); -} - -static void checkNtleaSignal(void) -{ - HANDLE ntleasig = OpenEventW(EVENT_ALL_ACCESS, FALSE, L"ntleasig"); - if (ntleasig) - { - WaitForSingleObject(ntleasig, INFINITE); - CloseHandle(ntleasig); - } -} - -int CreateProcessEnd(NtleaProcess *process, PROCESS_INFORMATION const *proinfo, BOOL bSuspendFlag) -{ - static BYTE const BreakPoint[] = { - 0xEB, - 0xFE, - }; - BYTE instrcache[sizeof(BreakPoint)]; - int ret; - - // just wait for the initial breakpoint : - ret = ResetBaseAddress(process, proinfo); - if (ret < 0) - { - fprintf(stderr, "failed rebase address ret = %d!\n", ret); - return ret; - } - - // try to add an breakpoint at the entrypoint ! - ReadProcessMemory(proinfo->hProcess, process->EntryPoint, instrcache, sizeof(instrcache), NULL); - WriteProcessMemory(proinfo->hProcess, process->EntryPoint, BreakPoint, sizeof(BreakPoint), NULL); - FlushInstructionCache(proinfo->hProcess, process->EntryPoint, sizeof(instrcache)); - - // wait thread arrived their ?? - ResumeThread(proinfo->hThread); - Sleep(32); // sleep shorter time - SuspendThread(proinfo->hThread); - while (proinfo->hThread == proinfo->hThread /*true*/) - { // Wow64GetThreadContext - CONTEXT threadctx = { - 0, - }; - // see : http://stackoverflow.com/questions/11396034/cant-get-thread-context-from-a-windows-64-bit-process - // ContextFlags on x64 offset no longer at the very beginning ! - threadctx.ContextFlags = CONTEXT_CONTROL; - if (!GetThreadContext(proinfo->hThread, &threadctx)) - { - fprintf(stderr, "Failed GetThreadContext : %u\n", GetLastError()); - return ERR_HOOKPROCESS_MISSING; - } - ResumeThread(proinfo->hThread); - Sleep(32); // sleep shorter time - SuspendThread(proinfo->hThread); - // AVC said that, x64 version of GetThreadContext may not require the correct value if different sys-bandwidth. - if (threadctx.RegIP == (DWORD_PTR)process->EntryPoint) - break; // X86 only - } - - if (!process->hInstance) - { - checkNtleaSignal(); - } - - // inject DLL : - ret = InjectProcessDLL(process, proinfo); - if (ret < 0) - { - fprintf(stderr, "failed inject DLL ret = %d!\n", ret); - return ret; - } - - // wait remote process hooking prepared : - if (WAIT_OBJECT_0 == WaitForSingleObject(process->RcpEvent, 30 * 1000)) - { - fprintf(stderr, "success wait signal!\n"); - } - else - { - fprintf(stderr, "failed wait signal timeout!\n"); - } - - if (!process->hInstance) - { - checkNtleaSignal(); - } - - // free all resource : - DeleteFileMapping(process); - // put back the instruction : - WriteProcessMemory(proinfo->hProcess, process->EntryPoint, instrcache, sizeof(instrcache), NULL); - FlushInstructionCache(proinfo->hProcess, process->EntryPoint, sizeof(instrcache)); - - if (!bSuspendFlag) - ResumeThread(proinfo->hThread); - - return (0); -} - -int CreateProcessEndExt(NtleaProcess *process, PROCESS_INFORMATION const *proinfo, BOOL bSuspendFlag) -{ - static BYTE const BreakPoint[] = { - 0xCC, - 0xCC, - 0xCC, - 0xCC, - }; - BYTE instrcache[sizeof(BreakPoint)]; - DEBUG_EVENT dbgevent; - int ret, fin = 0; - void *dbgstrbuf = HeapAlloc(GetProcessHeap(), 0, 1024); - - // just wait for the initial breakpoint : - ret = ResetBaseAddress(process, proinfo); - if (ret < 0) - { - fprintf(stderr, "failed rebase address ret = %d!\n", ret); - return ret; - } - - // DebugActiveProcess(proinfo->dwProcessId); - // just wait for the initial breakpoint : - while (!fin) - { - ret = WaitForDebugEvent(&dbgevent, 25); - if (ret) - { - switch (dbgevent.dwDebugEventCode) - { - case CREATE_PROCESS_DEBUG_EVENT: - { // prepare ! ParameterExists : - fprintf(stderr, "proc start address %p vs calc address %p\n", - (LPVOID)(DWORD_PTR)dbgevent.u.CreateProcessInfo.lpStartAddress, process->EntryPoint); - // try to add an breakpoint at the entrypoint ! - ReadProcessMemory(proinfo->hProcess, process->EntryPoint, instrcache, sizeof(instrcache), NULL); - WriteProcessMemory(proinfo->hProcess, process->EntryPoint, BreakPoint, sizeof(BreakPoint), NULL); - // inject DLL : - InjectProcessDLL(process, proinfo); - // now continue ?? - ContinueDebugEvent(dbgevent.dwProcessId, dbgevent.dwThreadId, DBG_CONTINUE); - } - break; - /* case CREATE_THREAD_DEBUG_EVENT: - { - CREATE_THREAD_DEBUG_INFO* dbginfo = &dbgevent.u.CreateThread; - fprintf(stderr, "threadstartup baseaddr : 0x%p, handle : 0x%p, ID : %u\n", dbginfo->lpStartAddress, dbginfo->hThread, dbgevent.dwThreadId); - ContinueDebugEvent(dbgevent.dwProcessId, dbgevent.dwThreadId, DBG_CONTINUE); - } break; - case EXIT_THREAD_DEBUG_EVENT: - { - EXIT_THREAD_DEBUG_INFO* dbginfo = &dbgevent.u.ExitThread; - fprintf(stderr, "threadexit code : %u, ID : %u\n", dbginfo->dwExitCode, dbgevent.dwThreadId); - ContinueDebugEvent(dbgevent.dwProcessId, dbgevent.dwThreadId, DBG_CONTINUE); - } break; */ - case LOAD_DLL_DEBUG_EVENT: - { - LOAD_DLL_DEBUG_INFO *dbginfo = &dbgevent.u.LoadDll; - /* if (dbginfo->lpImageName) { - void* lpImageNameStr = NULL; - ReadProcessMemory(proinfo->hProcess, dbginfo->lpImageName, &lpImageNameStr, sizeof(lpImageNameStr), NULL); - fprintf(stderr, (dbginfo->fUnicode ? "loadDLLevent %S basedlladdr : 0x%p, ID : %u\n" - : "loadDLLevent %s basedlladdr : 0x%p, ID : %u\n"), lpImageNameStr, dbginfo->lpBaseOfDll, dbgevent.dwThreadId); - }*/ - // we have the responsibility to cleanup the handle of DLL file : - if (dbginfo->hFile) - CloseHandle(dbginfo->hFile); - ContinueDebugEvent(dbgevent.dwProcessId, dbgevent.dwThreadId, DBG_CONTINUE); - } - break; - case EXCEPTION_DEBUG_EVENT: - { - EXCEPTION_DEBUG_INFO *dbginfo = &dbgevent.u.Exception; - // EXCEPTION_ACCESS_VIOLATION - fprintf(stderr, "Exception code : 0x%08X, ID : %u, Address : 0x%p\n", - dbginfo->ExceptionRecord.ExceptionCode, dbgevent.dwThreadId, - dbginfo->ExceptionRecord.ExceptionAddress); - // EXCEPTION_BREAKPOINT 0x80000003 - if (EXCEPTION_BREAKPOINT == dbginfo->ExceptionRecord.ExceptionCode) - { - // we check breakpoint interrupt, then - if (dbgevent.u.Exception.ExceptionRecord.ExceptionAddress == (LPVOID)(DWORD_PTR)process->EntryPoint) - { - SuspendThread(proinfo->hThread); - // put back the instruction : - WriteProcessMemory(proinfo->hProcess, process->EntryPoint, instrcache, sizeof(instrcache), NULL); - FlushInstructionCache(proinfo->hProcess, process->EntryPoint, sizeof(instrcache)); - // put back the eip : - CONTEXT threadctx = { - CONTEXT_CONTROL, - }; - if (GetThreadContext(proinfo->hThread, &threadctx)) - { // Wow64GetThreadContext - fprintf(stderr, "EIP at 0x%p to 0x%p\n", (void *)threadctx.RegIP, process->EntryPoint); - threadctx.RegIP = (DWORD)(DWORD_PTR)process->EntryPoint; // X86 only ?? - SetThreadContext(proinfo->hThread, &threadctx); - } - } - ContinueDebugEvent(dbgevent.dwProcessId, dbgevent.dwThreadId, DBG_CONTINUE); - } - else - { - switch (dbginfo->ExceptionRecord.ExceptionCode) - { - case EXCEPTION_ACCESS_VIOLATION: - fprintf(stderr, "error : EXCEPTION_ACCESS_VIOLATION(chance=%u)\n", dbginfo->dwFirstChance); - break; - case EXCEPTION_STACK_OVERFLOW: - fprintf(stderr, "error EXCEPTION_STACK_OVERFLOW(chance=%u)\n", dbginfo->dwFirstChance); - break; - case EXCEPTION_ARRAY_BOUNDS_EXCEEDED: - case EXCEPTION_DATATYPE_MISALIGNMENT: - case EXCEPTION_FLT_DENORMAL_OPERAND: - case EXCEPTION_FLT_DIVIDE_BY_ZERO: - case EXCEPTION_FLT_INEXACT_RESULT: - case EXCEPTION_FLT_INVALID_OPERATION: - case EXCEPTION_FLT_OVERFLOW: - case EXCEPTION_FLT_STACK_CHECK: - case EXCEPTION_FLT_UNDERFLOW: - fprintf(stderr, "error : EXCEPTION_FLT_XXX(code=%08X)\n", dbginfo->ExceptionRecord.ExceptionCode); - break; - case EXCEPTION_ILLEGAL_INSTRUCTION: - case EXCEPTION_IN_PAGE_ERROR: - case EXCEPTION_INT_DIVIDE_BY_ZERO: - case EXCEPTION_INT_OVERFLOW: - case EXCEPTION_INVALID_DISPOSITION: - case EXCEPTION_NONCONTINUABLE_EXCEPTION: - case EXCEPTION_PRIV_INSTRUCTION: - case EXCEPTION_SINGLE_STEP: - fprintf(stderr, "error : exception other(code=%08X)\n", dbginfo->ExceptionRecord.ExceptionCode); - break; - default: - fprintf(stderr, "error : unknown(code=%08X)\n", dbginfo->ExceptionRecord.ExceptionCode); - break; - } - ContinueDebugEvent(dbgevent.dwProcessId, dbgevent.dwThreadId, DBG_EXCEPTION_NOT_HANDLED); - fin = 1; - } - } - break; - case EXIT_PROCESS_DEBUG_EVENT: - { - // fprintf(stderr, "Debugging Process Exit with %u(0x%08X)!\n", dbgevent.u.ExitProcess.dwExitCode, dbgevent.u.ExitProcess.dwExitCode); - fin = 1; // breakout !! - ContinueDebugEvent(dbgevent.dwProcessId, dbgevent.dwThreadId, DBG_CONTINUE); - } - break; - case OUTPUT_DEBUG_STRING_EVENT: - { - OUTPUT_DEBUG_STRING_INFO *dbginfo = (OUTPUT_DEBUG_STRING_INFO *)&dbgevent.u.DebugString; - unsigned char *msg = (unsigned char *)dbgstrbuf; - // read debug string from debugee process : - ReadProcessMemory(proinfo->hProcess, dbginfo->lpDebugStringData, msg, std::min(1024, (int)dbginfo->nDebugStringLength), NULL); - fprintf(stderr, dbginfo->fUnicode ? "%S\n" : "%s\n", msg); - ContinueDebugEvent(dbgevent.dwProcessId, dbgevent.dwThreadId, DBG_CONTINUE); - } - break; - default: - ContinueDebugEvent(dbgevent.dwProcessId, dbgevent.dwThreadId, DBG_CONTINUE); - break; - } - } - if (WAIT_OBJECT_0 == WaitForSingleObject(process->RcpEvent, 0)) - { - DeleteFileMapping(process); - // fin = 1; - if (!bSuspendFlag) - ResumeThread(proinfo->hThread); - } - else - { - SetLastError(ERROR_SUCCESS); - } - } - HeapFree(GetProcessHeap(), 0, dbgstrbuf); - - // DebugActiveProcessStop(proinfo->dwProcessId); - - return (0); -} - -int ntleaswmain(int argc, wchar_t *wargv[]) -{ - // 0. accept only 1 instance ... - CreateMutexA(NULL, FALSE, szRcpIntMtx); - if (GetLastError()) - { - return PrintErrorString(ERR_MULTIPLE_INSTANCE); - } - - NtleaProcess ntproc = {0}; - { - auto process = &ntproc; - process->dwCompOption = std::stoi(wargv[1]); // 0; - process->dwCodePage = std::stoi(wargv[2]); // 932; - process->dwLCID = std::stoi(wargv[3]); // 0x411; - process->dwTimeZone = std::stoi(wargv[4]); //(DWORD)-540; - process->dwSpApp = 100; // ntlea use this value /100 for font-ratio ! - *(LPDWORD)process->FontFaceName = 0; // copy empty - } - LPCWSTR pApplicationName = NULL; - // 1. parse params and prepare helper data : - int dbg = 0, dir = 0, qit = 0, ret = 0; - - ret = CreateProcessBeginW(&ntproc, (pApplicationName = wargv[5])); - lstrcpyA((LPSTR)ntproc.FontFaceName, "MS PGothic"); - - // 5. if failed create process, exit ... - if (ret < 0) - { - ExitProcess(qit ? ret : PrintErrorString((NtleaErrorNo)ret)); - } - // 6. now create process : - PROCESS_INFORMATION proinfo = { - NULL, - NULL, - }; - STARTUPINFOW stinfo = { - sizeof(STARTUPINFOW), - }; - DWORD dwflags = dbg ? (DEBUG_ONLY_THIS_PROCESS) : (CREATE_SUSPENDED); - if (!CreateProcessW(pApplicationName, NULL, NULL, NULL, 0, dwflags, NULL, NULL, &stinfo, &proinfo)) - { - ExitProcess((UINT)-1); // exit !! - } - if (dir) - ResetWorkingDirectory(proinfo.hProcess); // - // 7. hook process : - ret = (dbg ? CreateProcessEndExt : CreateProcessEnd)(&ntproc, &proinfo, FALSE); - // 8. exit and free : - CloseHandle(proinfo.hThread); - if (ret < 0) - { - TerminateProcess(proinfo.hProcess, (UINT)ret); // exit !! - ExitProcess(qit ? ret : PrintErrorString((NtleaErrorNo)ret)); - } - else - { - CloseHandle(proinfo.hProcess); - } - // -------------- - ExitProcess(0); // explicit exit process ... -} - -NtleaErrorNo PrintErrorString(NtleaErrorNo errnum) -{ - char const *errdesc = "!"; - switch (errnum) - { - case ERR_PE_FORMAT_INVALID: - errdesc = "Err: NTLEAS detect that the PE Machine could not support."; - break; - case ERR_MULTIPLE_INSTANCE: - errdesc = "Err: NTLEAS could not startup two instances at one time."; - break; - case ERR_EXECUTABLE_MISSING: - errdesc = "Err: NTLEAS could not find or open specified PE file."; - break; - case ERR_EXECUTABLE_INVALID: - errdesc = "Err: NTLEAS detect that the given is an invalid PE file."; - break; - case ERR_PROCESS_CREATE_FAILED: - errdesc = "Err: NTLEAS could not create specified process of Exe."; - break; - case ERR_NTLEA_DLL_MISSING: - errdesc = "Err: NTLEAS could not find inject ntleai.dll."; - break; - case ERR_FAILED_ALLOCATE_MEM: - errdesc = "Err: NTLEAS was failed to virtual allocate memory."; - break; - case ERR_HOOKPROCESS_MISSING: - errdesc = "Err: NTLEAS may be lost connection with hook process."; - break; - case ERR_FAILED_QUERY_PROCESS: - errdesc = "Err: NTLEAS failed query process information."; - break; - } - MessageBoxA(GetForegroundWindow(), errdesc, szCaption, MB_OK); - - return errnum; -}