Void ReplaceMark(PWChar pLine, PWChar pSrc) { WChar ch; PWChar p, pBracket, pComma; pComma = NULL; pBracket = NULL; p = pLine; while (ch = *p++) { switch (ch) { case L'£¬': if (pComma == NULL) pComma = p - 1; break; case L'¡¸': if (pBracket == NULL) pBracket = p - 1; break; case L'¨D': // 0x2015 *(p - 1) = L'¡ª'; // 0x2014 break; case 0x30FB: *(p - 1) = L'¡¤'; break; } } if (pBracket && pComma && pComma < pBracket) *pComma = L','; p = pLine + StrLengthW(pLine) - 1; if ((ch = *p) != L'¡¹') { switch (ch) { case L'£¿': case L'?': case L'.': case L'¡£': case L'¡': case L'¡«': case L'¨D': // 0x2015 case L'¡ª': // 0x2014 return; } *++p = *(pSrc + StrLengthW(pSrc) - 1); *++p = 0; } }
PWChar CModelScript::PeekLine(PVoid pBuffer, PVoid pEndOfBuffer, PVoid pOutBuffer, PSizeT pcbOutBuffer) { if (pBuffer == NULL) return NULL; WChar ch; PWChar pStart, pEnd, pOutput; SSizeT BufferSize; if (pcbOutBuffer != NULL) { BufferSize = *pcbOutBuffer; *pcbOutBuffer = 0; } pStart = (PWChar)pBuffer; pEnd = pEndOfBuffer ? (PWChar)pEndOfBuffer : pStart + StrLengthW(pStart); if (pStart >= pEnd) return NULL; pOutput = (PWChar)pOutBuffer; if (*pStart == BOM_UTF16_LE) ++pStart; while (pStart < pEnd) { ch = *pStart++; if (ch == '\n') break; if (pOutput == NULL) continue; if (BufferSize > 0 && ch != '\r') { *pOutput++ = ch; BufferSize -= sizeof(ch); } } if (pOutput && BufferSize > 0) *pOutput = 0; BufferSize = (PByte)pOutput - (PByte)pOutBuffer; if (pcbOutBuffer) *pcbOutBuffer = BufferSize; if (BufferSize == 0) return pStart < pEnd ? pStart : NULL; return pStart; }
Bool PeekLine(LPVoid lpBuffer, LPVoid lpEndOfBuffer, LPVoid lpOutBuffer, PInt32 pcbOutBuffer) { if (lpBuffer == NULL) return False; WChar ch; PWChar pStart, pEnd, pOutput; Int32 BufferSize; if (pcbOutBuffer) { BufferSize = *pcbOutBuffer; *pcbOutBuffer = 0; } pStart = (PWChar)lpBuffer; pEnd = lpEndOfBuffer ? (PWChar)lpEndOfBuffer : pStart + StrLengthW(pStart); if (pStart >= pEnd) return False; pOutput = (PWChar)lpOutBuffer; while (pStart < pEnd) { ch = *pStart++; if (pOutput) { if (BufferSize > 0) { *pOutput++ = ch; BufferSize -= 2; } else break; } if (ch == '\n') break; } if (pOutput && BufferSize > 0) *pOutput = 0; if (pcbOutBuffer) *pcbOutBuffer = (PByte)pOutput - (PByte)lpOutBuffer; return True; }
PSTR WCharToMByte(PCWSTR Unicode, ULONG_PTR Length) { PSTR AnsiString; if (Length == -1) Length = StrLengthW(Unicode); ++Length; Length *= sizeof(WCHAR); AnsiString = (PSTR)AllocateMemoryP(Length); if (AnsiString == NULL) return NULL; RtlUnicodeToMultiByteN(AnsiString, Length, NULL, Unicode, Length); return AnsiString; }
LONG STDCALL DecCallback(PVOID, LPWIN32_FIND_DATAW pfd, ULONG_PTR) { ULONG Header; NTSTATUS Status; NtFileDisk file, filesrc; file.Open(pfd->cFileName); file.Read(&Header, 4); file.Close(); if (Header != TAG4('SDFA')) return 0; CHAR FileName[MAX_PATH]; PrintConsoleW(L"%s\n", pfd->cFileName); /* UnicodeToAnsi(FileName, countof(FileName), pfd->cFileName); pfopen fopen = (pfopen) 0x6585C3; pfseek fseek = (pfseek) 0x658587; pftell ftell = (pftell) 0x6585B9; pfread fread = (pfread) 0x6580FA; pfclose fclose = (pfclose)0x65994B; fopen = old_fopen; // fclose = (pfclose)0x659955; // zero_tc FILE *fp = fopen(FileName, "rb"); fseek(fp, 0, SEEK_END); Header = ftell(fp); fseek(fp, 0, SEEK_SET); PBYTE p = (PBYTE)AllocateMemory(Header); if (fread(p, Header, 1, fp) == 0) PrintConsoleW(L"failed\n"); fclose(fp); */ filesrc.Open(pfd->cFileName); Header = filesrc.GetSize32(); PBYTE p = (PBYTE)AllocateMemory(Header); filesrc.Read(p, Header); filesrc.Close(); ULONG len; static WCHAR suffix[] = L"_sc"; static WCHAR folder[] = L"data"; len = StrLengthW(pfd->cFileName) + 1; RtlMoveMemory( pfd->cFileName + CONST_STRLEN(folder) + CONST_STRLEN(suffix), pfd->cFileName + CONST_STRLEN(folder), len * 2 - CONST_STRLEN(folder) * sizeof(WCHAR) ); CopyMemory( pfd->cFileName + CONST_STRLEN(folder), suffix, sizeof(suffix) - sizeof(WCHAR) ); WCHAR c, *pname; pname = findnamew(pfd->cFileName); c = *pname; *pname = 0; CreateDirectoryRecursiveW(pfd->cFileName); *pname = c; Status = file.Create(pfd->cFileName); // PrintConsoleW(L"file.Create(): %08X\n", Status); if (NT_SUCCESS(Status)) { Status = file.Write(p, Header); // PrintConsoleW(L"file.Write(): Status = %08X, Size = %08X\n", Status, Header); } FreeMemory(p); // getch(); return 0; }
NTSTATUS GetRedirectFile(PUNICODE_STRING Redirected, PUNICODE_STRING Original) { ULONG_PTR Length; PWSTR Buffer; UNICODE_STRING FileName; typedef struct { UNICODE_STRING SubPath; ULONG_PTR SuffixLength; PCWSTR NewSubPath; } REDIRECT_ENTRY, *PDB_REDIRECT; PDB_REDIRECT Entry; static REDIRECT_ENTRY RedirectEntries[] = { { RTL_CONSTANT_STRING(L"\\All Users\\QQ\\History.db"), CONST_STRLEN(L"History.db") * sizeof(WCHAR), GlobalHistoryDb }, { RTL_CONSTANT_STRING(L"\\All Users\\QQ\\Registry.db"), CONST_STRLEN(L"Registry.db") * sizeof(WCHAR), GlobalRegistryDb }, //{ RTL_CONSTANT_STRING(L"QQProtect.exe"), CONST_STRLEN(L"QQProtect.exe") * sizeof(WCHAR), NULL }, }; RtlInitEmptyString(Redirected); LOOP_ONCE { if (Original == nullptr) continue; FOR_EACH_ARRAY(Entry, RedirectEntries) { if (Original->Length <= Entry->SubPath.Length) continue; FileName = *Original; FileName.Buffer = PtrSub(PtrAdd(FileName.Buffer, FileName.Length), Entry->SubPath.Length); FileName.Length = Entry->SubPath.Length; if (!RtlEqualUnicodeString(&FileName, &Entry->SubPath, TRUE)) continue; /* if (Entry->NewSubPath == NULL) { ExceptionBox(L"qqprotect"); ++Entry; } */ break; } if (Entry == &RedirectEntries[countof(RedirectEntries)]) break; Length = Original->Length + Entry->SubPath.Length + Entry->SuffixLength + sizeof(Entry->NewSubPath); Buffer = (PWSTR)AllocStack(Length); FileName.MaximumLength = Length; FileName.Buffer = Buffer; Length = StrLengthW(Entry->NewSubPath) * sizeof(WCHAR); RtlCopyUnicodeString(&FileName, Original); CopyMemory(PtrSub(PtrAdd(FileName.Buffer, FileName.Length), Entry->SuffixLength), Entry->NewSubPath, Length + sizeof(WCHAR)); FileName.Length = FileName.Length - Entry->SuffixLength + Length; RtlDuplicateUnicodeString(RTL_DUPSTR_ADD_NULL, &FileName, Redirected); return STATUS_SUCCESS; } return STATUS_NOT_FOUND; }
NTSTATUS ModifySelfSizeOfImage(LPWSTR ExeFullPath, LPWSTR CommandLine, ULONG SizeOfImage) { BOOL Result; ULONG Length; PVOID FakeCPInfoBuffer; WCHAR CmdFullPath[MAX_NTPATH]; PWCHAR CmdLineBuffer; NTSTATUS Status; PLDR_MODULE LdrModule; PIMAGE_DOS_HEADER DosHeader; PIMAGE_NT_HEADERS NtHeader; PIMAGE_SECTION_HEADER SectionHeader; FAKE_CREATE_PROCESS_INFO *fcpi; PROCESS_INFORMATION ProcessInformation; CONTEXT Context; NtFileDisk file; UNICODE_STRING ExeNtPath, *ProcessCommandLine; UNREFERENCED_PARAMETER(CommandLine); LdrModule = Nt_FindLdrModuleByName(NULL); DosHeader = (PIMAGE_DOS_HEADER)&__ImageBase; NtHeader = (PIMAGE_NT_HEADERS)((ULONG_PTR)DosHeader + DosHeader->e_lfanew); fcpi = (FAKE_CREATE_PROCESS_INFO *)AllocStack(0x2000); fcpi->PeHeaderSize = (ULONG_PTR)(IMAGE_FIRST_SECTION(NtHeader) + NtHeader->FileHeader.NumberOfSections) - (ULONG_PTR)DosHeader; Status = file.Open(LdrModule->FullDllName.Buffer); if (!NT_SUCCESS(Status)) return Status; Status = file.Read(fcpi->PeHeader, fcpi->PeHeaderSize); if (!NT_SUCCESS(Status)) return Status; CmdLineBuffer = (PWCHAR)((ULONG_PTR)fcpi->PeHeader + fcpi->PeHeaderSize); fcpi->CommandLine.Buffer = CmdLineBuffer; fcpi->CommandLine.Length = (USHORT)(StrLengthW(ExeFullPath) * sizeof(WCHAR)); ProcessCommandLine = &Nt_CurrentPeb()->ProcessParameters->CommandLine; CopyMemory(CmdLineBuffer, ProcessCommandLine->Buffer, ProcessCommandLine->Length); *(PULONG_PTR)&CmdLineBuffer += ProcessCommandLine->Length; CmdLineBuffer[0] = 0; fcpi->CommandLine.Length = ProcessCommandLine->Length; fcpi->CommandLine.MaximumLength = fcpi->CommandLine.Length + sizeof(WCHAR); ++CmdLineBuffer; CmdLineBuffer = (PWCHAR)ROUND_UP((ULONG_PTR)CmdLineBuffer, 16); RtlDosPathNameToNtPathName_U(LdrModule->FullDllName.Buffer, &ExeNtPath, NULL, NULL); fcpi->ExeNtPath.Buffer = CmdLineBuffer; CopyMemory(CmdLineBuffer, ExeNtPath.Buffer, ExeNtPath.Length); *(PULONG_PTR)&CmdLineBuffer += ExeNtPath.Length; CmdLineBuffer[0] = 0; fcpi->ExeNtPath.Length = ExeNtPath.Length; fcpi->ExeNtPath.MaximumLength = fcpi->ExeNtPath.Length + sizeof(WCHAR); *CmdLineBuffer++ = 0; RtlFreeUnicodeString(&ExeNtPath); DosHeader = (PIMAGE_DOS_HEADER)fcpi->PeHeader; NtHeader = (PIMAGE_NT_HEADERS)((ULONG_PTR)DosHeader + DosHeader->e_lfanew); SectionHeader = IMAGE_FIRST_SECTION(NtHeader); SectionHeader += NtHeader->FileHeader.NumberOfSections - 1; SizeOfImage -= LdrModule->SizeOfImage; SizeOfImage = ROUND_UP(SizeOfImage, MEMORY_PAGE_SIZE); SectionHeader->Misc.VirtualSize = ROUND_UP(SectionHeader->Misc.VirtualSize, MEMORY_PAGE_SIZE) + SizeOfImage; if (NtHeader->FileHeader.SizeOfOptionalHeader > FIELD_OFFSET(IMAGE_OPTIONAL_HEADER, SizeOfImage) + RTL_FIELD_SIZE(IMAGE_OPTIONAL_HEADER, SizeOfImage)) NtHeader->OptionalHeader.SizeOfImage += SizeOfImage; Length = Nt_GetSystemDirectory(CmdFullPath, countof(CmdFullPath)); StrCopyW(CmdFullPath + Length, L"cmd.exe"); ProcessInformation.hProcess = NtCurrentProcess(); ProcessInformation.hThread = NtCurrentThread(); #if 1 Result = Nt_CreateProcess(NULL, CmdFullPath, NULL, CREATE_SUSPENDED, NULL, &ProcessInformation); if (!Result) return STATUS_UNSUCCESSFUL; #endif FakeCPInfoBuffer = NULL; LOOP_ONCE { ULONG_PTR Offset; Status = NtDuplicateObject( NtCurrentProcess(), NtCurrentProcess(), ProcessInformation.hProcess, &fcpi->ProcessHandle, 0, 0, DUPLICATE_SAME_ACCESS ); if (!NT_SUCCESS(Status)) break; /* Status = NtDuplicateObject( NtCurrentProcess(), file, ProcessInformation.hProcess, &fcpi->FileHandle, 0, 0, DUPLICATE_SAME_ACCESS ); if (!NT_SUCCESS(Status)) break; */ Status = Nt_AllocateMemory(ProcessInformation.hProcess, &FakeCPInfoBuffer, MEMORY_PAGE_SIZE); if (!NT_SUCCESS(Status)) break; fcpi->CreateProcessInternalW = CreateProcessInternalW; fcpi->NtTerminateProcess = NtTerminateProcess; fcpi->LdrShutdownProcess = LdrShutdownProcess; fcpi->NtCreateFile = NtCreateFile; fcpi->NtWriteFile = NtWriteFile; fcpi->NtClose = NtClose; fcpi->NtWaitForSingleObject = NtWaitForSingleObject; fcpi->InitialDirectory.Buffer = NULL; Offset = (ULONG_PTR)FakeCPInfoBuffer - (ULONG_PTR)fcpi; *(PULONG_PTR)&fcpi->CommandLine.Buffer += Offset; *(PULONG_PTR)&fcpi->ExeNtPath.Buffer += Offset; Status = Nt_WriteMemory( ProcessInformation.hProcess, FakeCPInfoBuffer, fcpi, (ULONG_PTR)CmdLineBuffer - (ULONG_PTR)fcpi, &Length ); if (!NT_SUCCESS(Status)) break; Context.ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER; Status = NtGetContextThread(ProcessInformation.hThread, &Context); if (!NT_SUCCESS(Status)) break; Context.Eip = (ULONG_PTR)FakeCPInfoBuffer + Length; Context.Eip = ROUND_UP(Context.Eip, 16); Context.Ecx = (ULONG_PTR)FakeCPInfoBuffer; Status = Nt_WriteMemory( ProcessInformation.hProcess, (PVOID)Context.Eip, ModifySizeOfImage, (ULONG_PTR)ModifySizeOfImageEnd - (ULONG_PTR)ModifySizeOfImage, &Length ); if (!NT_SUCCESS(Status)) break; #if 1 Status = NtSetContextThread(ProcessInformation.hThread, &Context); if (!NT_SUCCESS(Status)) break; Status = NtResumeThread(ProcessInformation.hThread, NULL); #else INLINE_ASM jmp Context.Eip; #endif } if (!NT_SUCCESS(Status)) { if (FakeCPInfoBuffer != NULL) Nt_FreeMemory(ProcessInformation.hProcess, FakeCPInfoBuffer); NtTerminateProcess(ProcessInformation.hProcess, 0); } NtClose(ProcessInformation.hProcess); NtClose(ProcessInformation.hThread); return Status; }
static size_t StrLength(const wchar_t* lpData) { return StrLengthW(lpData); }
UPK_STATUS NitroPlus:: Pack( PCWSTR InputPath, PCWSTR OutputFile /* = NULL */, PLARGE_INTEGER PackedFiles /* = NULL */, ULONG Flags /* = 0 */ ) { UNREFERENCED_PARAMETER(OutputFile); UNREFERENCED_PARAMETER(Flags); ULONG PathLength, Length, Hash, Offset; ULONG Size, CompressedSize, FileBufferSize, CompresseBufferSize; WCHAR FilePath[MAX_NTPATH]; PVOID NpaEntryBase, FileBuffer, CompresseBuffer; PBYTE NpaEntryBuffer; PWSTR FileName; NTSTATUS Status; LARGE_INTEGER FileCount, PackedFileCount; NITRO_PLUS_ENTRY *BaseEntry, *Entry; NITRO_PLUS_NPA_HEADER Header; NITRO_PLUS_NPA_ETNRY *Info; NtFileDisk File; if (PackedFiles == NULL) PackedFiles = &PackedFileCount; PackedFiles->QuadPart = 0; if (!EnumDirectoryFiles( (PVOID *)&BaseEntry, L"*.*", sizeof(*BaseEntry), InputPath, &FileCount, (EnumDirectoryFilesCallBackRoutine)QueryFileList, 0, EDF_SUBDIR) ) { return STATUS_UNSUCCESSFUL; } FileBufferSize = 0; CompresseBufferSize = 0; FileBuffer = NULL; CompresseBuffer = NULL; *(PULONG)&Header.Signature = NPA_HEADER_MAGIC; Header.Version = NPA_GCLX_VERSION; Header.EntryCount = FileCount.LowPart; Header.FileCount = FileCount.LowPart; Header.DirectoryCount = 0; Header.IsCompressed = TRUE; Header.IsEncrypted = TRUE; RtlRandom(&Header.Hash[0]); RtlRandom(&Header.Hash[1]); PathLength = StrLengthW(InputPath); if (OutputFile != NULL) { Status = m_File.Create(OutputFile); } else { FileName = FilePath + PathLength; CopyMemory(FilePath, InputPath, PathLength * sizeof(*FilePath)); if (FileName[-1] == '\\') --FileName; *(PULONG64)FileName = TAG4W('.npa'); FileName[4] = 0; Status = m_File.Create(FilePath); } if (!NT_SUCCESS(Status)) goto RETURN_POINT; PathLength += InputPath[PathLength - 1] != '\\'; NpaEntryBase = AllocateMemory(sizeof(*BaseEntry) * FileCount.LowPart); if (NpaEntryBase == NULL) { Status = STATUS_INSUFFICIENT_RESOURCES; goto RETURN_POINT; } NpaEntryBuffer = (PBYTE)NpaEntryBase; Entry = BaseEntry; for (ULONG Index = 0, Count = FileCount.LowPart; Count; ++Index, --Count) { Length = StrLengthW(Entry->FileName) - PathLength; Length = WideCharToMultiByte( CP_SHIFTJIS, 0, Entry->FileName + PathLength, Length, (PSTR)NpaEntryBuffer + 4, INT_MAX, NULL, NULL ); // Nt_UnicodeToAnsi((PSTR)NpaEntryBuffer + 4, INT_MAX, Entry->FileName + PathLength, Length, &Length); *(PULONG)NpaEntryBuffer = Length; NpaEntryBuffer += 4; Entry->DecryptLength = Length; Entry->Seed = HashBuffer(NpaEntryBuffer, Length); EncryptName(NpaEntryBuffer, Length, Index, &Header); NpaEntryBuffer += Length; NpaEntryBuffer += sizeof(*Info); ++Entry; } Header.EntrySize = PtrOffset(NpaEntryBuffer, NpaEntryBase); Hash = Header.Hash[0] * Header.Hash[1]; NpaEntryBuffer = (PBYTE)NpaEntryBase; Entry = BaseEntry; Offset = 0; m_File.Seek(Header.EntrySize + sizeof(Header), FILE_BEGIN); for (ULONG Index = 0, Count = FileCount.LowPart; Count; ++Index, --Count) { Status = File.Open(Entry->FileName); if (!NT_SUCCESS(Status)) break; Size = File.GetSize32(); if (FileBufferSize < Size) { FileBufferSize = Size; FileBuffer = ReAllocateMemory(FileBuffer, FileBufferSize); if (FileBuffer == NULL) { Status = STATUS_INSUFFICIENT_RESOURCES; break; } } Status = File.Read(FileBuffer, Size); if (!NT_SUCCESS(Status)) break; CompressedSize = Size * 4; if (CompresseBufferSize < CompressedSize) { CompresseBufferSize = CompressedSize; CompresseBuffer = ReAllocateMemory(CompresseBuffer, CompresseBufferSize); if (CompresseBuffer == NULL) { Status = STATUS_INSUFFICIENT_RESOURCES; break; } } CompressedSize = CompresseBufferSize; Status = compress2(CompresseBuffer, &CompressedSize, FileBuffer, Size, Z_BEST_COMPRESSION); if (Status != Z_OK) { Status = STATUS_UNSUCCESSFUL; break; } EncryptData( CompresseBuffer, MY_MIN(CompressedSize, Entry->DecryptLength + 0x1000), (Hash + Entry->Seed) * Size ); NpaEntryBuffer += *(PULONG)NpaEntryBuffer + 4; Info = (NITRO_PLUS_NPA_ETNRY *)NpaEntryBuffer; NpaEntryBuffer += sizeof(*Info); Info->FileType = NP_FILE_TYPE_FILE; Info->CompressedSize = CompressedSize; Info->Offset = Offset; Info->OriginalSize = Size; Info->DirectoryIndex = 0; Status = m_File.Write(CompresseBuffer, CompressedSize); if (!NT_SUCCESS(Status)) break; Offset += CompressedSize; ++Entry; } if (!NT_SUCCESS(Status)) goto RETURN_POINT; m_File.Seek(0, FILE_BEGIN); Status = m_File.Write(&Header, sizeof(Header)); if (!NT_SUCCESS(Status)) goto RETURN_POINT; Status = m_File.Write(NpaEntryBase, Header.EntrySize); if (!NT_SUCCESS(Status)) goto RETURN_POINT; PackedFiles->QuadPart = FileCount.QuadPart; RETURN_POINT: FreeMemory(FileBuffer); EnumDirectoryFilesFree(BaseEntry); return Status; }
BOOL Initialize(PVOID BaseAddress) { PVOID hModule; SizeT Length, Length2; LPWSTR lpCmdLineW, pCmdLine; WChar end, szCmdLine[MAX_PATH + 40]; static WChar AddCmdLineHeadW[] = L" --user-data-dir=\""; static WChar AddCmdLineTailW[] = L"UserData\" --purge-memory-button"; LdrDisableThreadCalloutsForDll(BaseAddress); Length = Nt_GetSystemDirectory(szCmdLine, countof(szCmdLine)); CopyStruct(szCmdLine + Length, L"wtsapi32.dll", sizeof(L"wtsapi32.dll")); hModule = Ldr::LoadDll(szCmdLine); *(PVOID *)&StubWTSFreeMemory = GetRoutineAddress(hModule, "WTSFreeMemory"); *(PVOID *)&StubWTSQuerySessionInformationW = GetRoutineAddress(hModule, "WTSQuerySessionInformationW"); *(PVOID *)&StubWTSUnRegisterSessionNotification = GetRoutineAddress(hModule, "WTSUnRegisterSessionNotification"); *(PVOID *)&StubWTSRegisterSessionNotification = GetRoutineAddress(hModule, "WTSRegisterSessionNotification"); *(PVOID *)&StubWTSQueryUserToken = GetRoutineAddress(hModule, "WTSQueryUserToken"); lpCmdLineW = Ps::GetCommandLine(); Length = StrLengthW(lpCmdLineW); pCmdLine = szCmdLine; StrCopyW(pCmdLine, AddCmdLineHeadW); pCmdLine += countof(AddCmdLineHeadW) - 1; pCmdLine += Nt_GetExeDirectory(pCmdLine, countof(szCmdLine) - (pCmdLine - szCmdLine)); StrCopyW(pCmdLine, AddCmdLineTailW); pCmdLine += countof(AddCmdLineTailW); Length2 = pCmdLine - szCmdLine; g_pCmdLineW = (PWChar)AllocateMemory(Length * 2 + Length2 * 2 + 2); pCmdLine = lpCmdLineW; end = *pCmdLine++ == '\"' ? '\"' : ' '; while (*pCmdLine && *pCmdLine != end) ++pCmdLine; ++pCmdLine; /* if (*++pCmdLine) { while (*pCmdLine == ' ' || *pCmdLine == '\t') ++pCmdLine; } */ end = *pCmdLine; *pCmdLine = 0; StrCopyW(g_pCmdLineW, lpCmdLineW); *pCmdLine = end; lpCmdLineW = g_pCmdLineW + (pCmdLine - lpCmdLineW); StrCopyW(lpCmdLineW, szCmdLine); lpCmdLineW += Length2 - 1; StrCopyW(lpCmdLineW, pCmdLine); Length = StrLengthW(g_pCmdLineW); g_pCmdLineA = (PChar)AllocateMemory(Length * 2); // WideCharToMultiByte(CP_ACP, 0, g_pCmdLineW, -1, g_pCmdLineA, Length * 2, NULL, NULL); UnicodeToAnsi(g_pCmdLineA, Length * 2, g_pCmdLineW, -1); hModule = Nt_GetModuleHandle(L"chrome.dll"); MEMORY_FUNCTION_PATCH f[] = { INLINE_HOOK_JUMP_NULL(::GetCommandLineW, MyGetCommandLineW), INLINE_HOOK_JUMP_NULL(::GetCommandLineA, MyGetCommandLineA), INLINE_HOOK_JUMP(LoadAcceleratorsW, MyLoadAcceleratorsW, StubLoadAcceleratorsW), }; Nt_PatchMemory(0, 0, f, countof(f), 0); return TRUE; }