I am learning Pin and trying to conceal the presence of cmd.exe in the SYSTEM_PROCESS_INFORMATION linked list
This is what I have so far.
VOID HooksHandler::NtQuerySystemInformationIntercept(CONTEXT* ctxt, W::SYSTEM_INFORMATION_CLASS SystemInformationClass, PSYSTEM_PROCESS_INFO ProcessInformation, ADDRINT ret)
{
if (SystemInformationClass == SystemProcessInformation) {
// cast to our structure to retrieve the information returned
// from the NtSystemQueryInformation function
PSYSTEM_PROCESS_INFO spi = (PSYSTEM_PROCESS_INFO)ProcessInformation;
if (spi == NULL) {
return;
}
// iterate through all processes
while (spi->NextEntryOffset) {
if (spi->ImageName.Buffer != nullptr) {
char value[PATH_BUFSIZE];
GET_STR_TO_UPPER(spi->ImageName.Buffer, value, PATH_BUFSIZE);
std::stringstream sss;
sss << value;
EVASION("NtQuerySystemInformation ImageName.Buffer", sss.str().c_str());
if (wcscmp(spi->ImageName.Buffer, L"cmd.exe") == 0) {
MYINFO("NtQuerySystemInformation ImageName.Length before change", "%p", spi->ImageName.Length);
MYINFO("NtQuerySystemInformation ImageName.MaximumLength before change", "%p", spi->ImageName.MaximumLength);
if (spi->ImageName.MaximumLength >= sizeof(L"abc.exe") && spi->ImageName.Length >= sizeof(L"abc.exe")) {
PIN_SafeCopy(spi->ImageName.Buffer, L"abc.exe", sizeof(L"abc.exe"));
char value1[PATH_BUFSIZE];
GET_STR_TO_UPPER(spi->ImageName.Buffer, value1, PATH_BUFSIZE);
std::stringstream sss1;
sss1 << value1;
EVASION("NtQuerySystemInformation ImageName.Buffer in the if, after change", sss1.str().c_str());
break;
}
}
}
// calculate the address of the next entry.
spi = (PSYSTEM_PROCESS_INFO)((W::LPBYTE)spi + spi->NextEntryOffset);
}
}
}
typedef struct _SYSTEM_PROCESS_INFO
{
W::ULONG NextEntryOffset;
W::ULONG NumberOfThreads;
W::LARGE_INTEGER WorkingSetPrivateSize; // since VISTA
W::ULONG HardFaultCount; // since WIN7
W::ULONG NumberOfThreadsHighWatermark; // since WIN7
W::ULONGLONG CycleTime; // since WIN7
W::LARGE_INTEGER CreateTime;
W::LARGE_INTEGER UserTime;
W::LARGE_INTEGER KernelTime;
W::UNICODE_STRING ImageName;
W::KPRIORITY BasePriority;
W::HANDLE UniqueProcessId;
W::HANDLE InheritedFromUniqueProcessId;
W::ULONG HandleCount;
W::ULONG SessionId;
W::ULONG_PTR UniqueProcessKey; // since VISTA (requires SystemExtendedProcessInformation)
W::SIZE_T PeakVirtualSize;
W::SIZE_T VirtualSize;
W::ULONG PageFaultCount;
W::SIZE_T PeakWorkingSetSize;
W::SIZE_T WorkingSetSize;
W::SIZE_T QuotaPeakPagedPoolUsage;
W::SIZE_T QuotaPagedPoolUsage;
W::SIZE_T QuotaPeakNonPagedPoolUsage;
W::SIZE_T QuotaNonPagedPoolUsage;
W::SIZE_T PagefileUsage;
W::SIZE_T PeakPagefileUsage;
W::SIZE_T PrivatePageCount;
W::LARGE_INTEGER ReadOperationCount;
W::LARGE_INTEGER WriteOperationCount;
W::LARGE_INTEGER OtherOperationCount;
W::LARGE_INTEGER ReadTransferCount;
W::LARGE_INTEGER WriteTransferCount;
W::LARGE_INTEGER OtherTransferCount;
W::SYSTEM_THREAD_INFORMATION Threads[1];
} SYSTEM_PROCESS_INFO, * PSYSTEM_PROCESS_INFO;
I have tried various ways to change the ImageName.Buffer, including
PIN_SafeCopy(spi->ImageName.Buffer, L"abc.exe\0", sizeof(L"abc.exe\0"));
PIN_SafeCopy(spi->ImageName.Buffer, L"ab.exe", sizeof(L"ab.exe"));
PIN_SafeCopy(spi->ImageName.Buffer, L"a.exe", sizeof(L"a.exe"));
wcscpy(spi->ImageName.Buffer, L"abc.exe");
and
// Without the L prefix
PIN_SafeCopy(spi->ImageName.Buffer, "abc.exe", sizeof("abc.exe"));
and this works (does not cause an exception) around half of the time, it mangles the ImageName.Buffer which is a PWSTR and I can see in the log after the change that the ImageName.Buffer is ace.x
typedef struct _UNICODE_STRING {
USHORT Length;
USHORT MaximumLength;
PWSTR Buffer;
} UNICODE_STRING, *PUNICODE_STRING;
For all of this ways of changing ImageName.Buffer I can see in the log that after the PIN_SafeCopy the new Buffer reflects the change for example abc.exe but immediately after the break it throws and exception
EXCEPT_HANDLING_RESULT myExceptionHandler(THREADID tid, EXCEPTION_INFO* pExceptInfo, PHYSICAL_CONTEXT* pPhysCtxt, VOID* v) {
MYINFO("ExceptionHandler", "ExceptionHandler");
MYINFO("Pin Exception String ", "%s", PIN_ExceptionToString(pExceptInfo).c_str());
MYINFO("Pin Exception Code ", "%s", pExceptInfo->GetExceptCode());
return EHR_CONTINUE_SEARCH;
}
which logs "Pin Exception String" :Exception Code: RECEIVED_ACCESS_FAULT. Exception ADDRESS = 0x668c597. Access Type Read. Access Address 0x1d
I think it indicates that the Pin tool is trying to read from an invalid or inaccessible memory address and it could be I am not aligning the L"abc.exe" correctly.
One last thing, this is running on Win10 64 bit, and both the Pin tool (v3.25) and binary being instrumented are 32 bit, and I wonder if it could be a Wow64 issue with how it maps NTDLL.dll
Any pointers would be much appreciated, thank you