運行期修改可執行文件的路徑和Command Line

運行期修改可執行文件的路徑和Command Line

<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

 

 

NetRoc

http://www.DbgTech.net/

目前的很多主動防禦工具和反XX系統,在對特定進程進行保護的時候,出於兼容性的考慮,都會保留一些白名單。特別是一些系統進程,例如csrss.exesvchost.exe等等。而針對這些系統進程,判斷是否在白名單中的方式,爲了簡便起見經常採用取系統路徑、可執行文件名的方式。

內核中比較明顯的能夠取到可執行文件路徑的方法有下面幾個:

1、              通過PEB. ProcessParameters -> ImagePathName取得可執行文件路徑,通過PEB. ProcessParameters -> CommandLine取得執行的命令行,以及PEB. ProcessParameters裏面其他幾個成員取得其他一些相關的路徑信息。

2、              通過nt!_EPROCESSImageFileName取得。

3、              通過nt!_EPROCESS:: SeAuditProcessCreationInfo:: ImageFileName取得。

4、              通過和_EPROCESS相關的文件對象信息取得。

常見的方式一般只有12兩種。而上述的前三種方式都可以在運行時被修改掉,用來進行欺騙。特別是PEB裏面的信息由於在ring3直接就可以訪問,實現上來說非常簡單。

下面這段代碼通過NtQueryInformationProcess拿到PEB,然後修改路徑信息:

HMODULE hMod = GetModuleHandle( _T( "ntdll.dll"));

         pfnNtQueryInformationProcess p = (pfnNtQueryInformationProcess)::GetProcAddress( hMod, "NtQueryInformationProcess");

        

         PROCESS_BASIC_INFORMATION stInfo = {0};

         DWORD dwRetnLen = 0;

         DWORD dw = p( GetCurrentProcess(), ProcessBasicInformation, &stInfo, sizeof(stInfo), &dwRetnLen);

        

         PPEB pPeb = stInfo.PebBaseAddress;

 

         WCHAR wszFullPath[MAX_PATH] = {0};

         WCHAR wszTmp2[MAX_PATH] = {0};

         wcscpy( wszFullPath, wszPath);

         MultiByteToWideChar( CP_THREAD_ACP, 0, szName, -1, wszTmp2, MAX_PATH);

         wcscat( wszFullPath, wszTmp2);

        

         wcscpy( pPeb->ProcessParameters->ImagePathName.Buffer, wszFullPath);

         pPeb->ProcessParameters->ImagePathName.Length = wcslen( wszFullPath) * sizeof(WCHAR);

        

         int nParamStart = 0;

         WCHAR *wszTmp = new WCHAR[pPeb->ProcessParameters->CommandLine.MaximumLength];

         ZeroMemory( wszTmp, sizeof(WCHAR) * pPeb->ProcessParameters->CommandLine.MaximumLength);

        

         wcscpy( wszTmp, pPeb->ProcessParameters->CommandLine.Buffer);

        

         if ( pPeb->ProcessParameters->CommandLine.Buffer[0] == '"')

         {

                   for ( int i = 1; i < pPeb->ProcessParameters->CommandLine.Length / 2; i++)

                   {

                            if ( pPeb->ProcessParameters->CommandLine.Buffer[i] == '"')

                            {

                                     nParamStart = i;

                            }

                   }

         }

        

         if ( nParamStart != 0)

         {

                   if ( pPeb->ProcessParameters->CommandLine.Buffer[0] == '"')

                   {

                            pPeb->ProcessParameters->CommandLine.Buffer[0] = NULL;

                            wcscat( pPeb->ProcessParameters->CommandLine.Buffer, L"/"");

                   }

                   else

                   {

                            pPeb->ProcessParameters->CommandLine.Buffer[0] = NULL;

                   }

                   wcscat( pPeb->ProcessParameters->CommandLine.Buffer, wszFullPath);

                   wcscat( pPeb->ProcessParameters->CommandLine.Buffer, wszTmp + nParamStart);

         }

         delete[] wszTmp;

這個方式可以欺騙通過toolhelp函數枚舉出來的模塊路徑,以及直接讀取PEB獲取進程主模塊路徑的方式。

另外,通過修改EPROCESS中的主模塊名信息,可以欺騙一些在驅動層的程序。基本的代碼如下:

首先需要獲取EPROCESS裏面ImageFileName的偏移。這個函數必須在DriverEntry裏面調用。

ULONG GetNameOffsetInEProcss()

{

         PEPROCESS pProcess = NULL;

         ULONG i = 0;

 

         pProcess = PsGetCurrentProcess();

         for ( i = 0; i < 0x1000; i++)

         {

                   if ( strncmp( "System", (PUCHAR)pProcess + i, strlen("System")) == 0)

                   {

                            return i;

                   }

         }

         return 0;

}

然後可以在IoCtrl裏面修改當前進程的名字:

case IOCTL_CHANGE_EXENAME:

                            szName = (char*)Irp->AssociatedIrp.SystemBuffer;

                            if ( !szName)

                            {

                                     ntStatus = STATUS_UNSUCCESSFUL;

                                     break;

                            }

                            pEProcess = PsGetCurrentProcess();

                            strncpy( (PCHAR)pEProcess + g_NameOffsetInEProcess, szName, 16);

                            ntStatus = STATUS_SUCCESS;

                            break;

由於只是示例,所以只實現了良種方式。修改SeAuditProcessCreationInfo裏面的信息,考慮到兼容性問題,可能稍微複雜一點。不過也可以比較容易的實現。

這種方式的僞裝可以穿過多少主動防禦工具沒有試過,大家可以去看看,哈哈。

至於對付的方式,可以通過上面說的第四種取進程路徑的方法。不過就比較複雜了,呵呵。

流程就是,通過EPROCESSSectionObject獲得文件的FilePointer,通過ObQueryNameString取得這個對象的名字。然後就可以取得主映像模塊的路徑了。詳細的代碼可以參考wrkNtQueryInformationProcess的相關實現。

下面是實現代碼:

ImgPathChanger.rar

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章