microsoft / binskim

A binary static analysis tool that provides security and correctness results for Windows Portable Executable and *nix ELF binary formats
Other
775 stars 158 forks source link

AccessViolationException while scanning three linux-arm ELF binaries simultaneously #743

Open dagood opened 1 year ago

dagood commented 1 year ago

I work on the Microsoft fork of Go, and saw strange behavior with recent versions of BinSkim with our linux-armv6l (arm32) cross-compiled build while running BinSkim on windows-x64. Here are the files I'm working with:

repro-linux_arm.zip

When I try to analyze all three files with binskim, I get raw exception failures with recent versions of BinSkim (extracted from the nuget packages), but successful analysis with 1.7.5:

2.0.0-rc1

#> C:\temp\binskim\microsoft.codeanalysis.binskim.2.0.0-rc1\tools\netcoreapp3.1\win-x64\BinSkim.exe analyze .\repro-linux_arm\dist .\repro-linux_arm\doc .\repro-linux_arm\fix
Analyzing...
Fatal error. System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
   at System.Runtime.InteropServices.Marshal.ReadInt32(IntPtr, Int32)
   at Microsoft.CodeAnalysis.BinaryParsers.Dwarf.DwarfMemoryReader.ReadUint()
   at Microsoft.CodeAnalysis.BinaryParsers.Dwarf.DwarfMemoryReader.ReadLength(Boolean ByRef)
   at Microsoft.CodeAnalysis.BinaryParsers.Dwarf.DwarfCommonInformationEntry.ParseEntry(Microsoft.CodeAnalysis.BinaryParsers.Dwarf.DwarfMemoryReader, Byte, Int32)
   at Microsoft.CodeAnalysis.BinaryParsers.Dwarf.DwarfCommonInformationEntry.ParseAll(Microsoft.CodeAnalysis.BinaryParsers.Dwarf.DwarfMemoryReader, Byte)
   at Microsoft.CodeAnalysis.BinaryParsers.Dwarf.DwarfSymbolProvider.ParseCommonInformationEntries(Byte[], Byte[], Microsoft.CodeAnalysis.BinaryParsers.Dwarf.DwarfExceptionHandlingFrameParsingInput)
   at Microsoft.CodeAnalysis.BinaryParsers.ElfBinary..ctor(System.Uri, System.String)
   at Microsoft.CodeAnalysis.IL.Sdk.BinaryTargetManager.GetBinaryFromFile(System.Uri, System.String, System.String, Boolean)
   at Microsoft.CodeAnalysis.IL.Sdk.BinaryAnalyzerContext.get_Binary()
   at Microsoft.CodeAnalysis.IL.Sdk.BinaryAnalyzerContext.get_TargetLoadException()
   at Microsoft.CodeAnalysis.Sarif.Driver.MultithreadedAnalyzeCommandBase`2[[System.__Canon, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.__Canon, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].DetermineApplicabilityAndAnalyze(System.__Canon, System.Collections.Generic.IEnumerable`1<Microsoft.CodeAnalysis.Sarif.Driver.Skimmer`1<System.__Canon>>, System.Collections.Generic.ISet`1<System.String>)
   at Microsoft.CodeAnalysis.Sarif.Driver.MultithreadedAnalyzeCommandBase`2+<ScanTargetsAsync>d__40[[System.__Canon, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.__Canon, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].MoveNext()
   at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[[Microsoft.CodeAnalysis.Sarif.Driver.MultithreadedAnalyzeCommandBase`2+<ScanTargetsAsync>d__40[[System.__Canon, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.__Canon, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], Sarif.Driver, Version=3.1.0.0, Culture=neutral, PublicKeyToken=21a5e83f6f5bb844]](<ScanTargetsAsync>d__40<System.__Canon,System.__Canon> ByRef)
   at System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1[[System.Boolean, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].Start[[Microsoft.CodeAnalysis.Sarif.Driver.MultithreadedAnalyzeCommandBase`2+<ScanTargetsAsync>d__40[[System.__Canon, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.__Canon, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], Sarif.Driver, Version=3.1.0.0, Culture=neutral, PublicKeyToken=21a5e83f6f5bb844]](<ScanTargetsAsync>d__40<System.__Canon,System.__Canon> ByRef)
   at Microsoft.CodeAnalysis.Sarif.Driver.MultithreadedAnalyzeCommandBase`2[[System.__Canon, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.__Canon, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].ScanTargetsAsync(System.Collections.Generic.IEnumerable`1<Microsoft.CodeAnalysis.Sarif.Driver.Skimmer`1<System.__Canon>>, System.Collections.Generic.ISet`1<System.String>)
   at Microsoft.CodeAnalysis.Sarif.Driver.MultithreadedAnalyzeCommandBase`2[[System.__Canon, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.__Canon, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].MultithreadedAnalyzeTargets(System.__Canon, System.__Canon, System.Collections.Generic.IEnumerable`1<Microsoft.CodeAnalysis.Sarif.Driver.Skimmer`1<System.__Canon>>, System.Collections.Generic.ISet`1<System.String>)
   at Microsoft.CodeAnalysis.Sarif.Driver.MultithreadedAnalyzeCommandBase`2[[System.__Canon, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.__Canon, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].AnalyzeTargets(System.__Canon, System.__Canon, System.Collections.Generic.IEnumerable`1<Microsoft.CodeAnalysis.Sarif.Driver.Skimmer`1<System.__Canon>>)
   at Microsoft.CodeAnalysis.Sarif.Driver.MultithreadedAnalyzeCommandBase`2[[System.__Canon, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.__Canon, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].Analyze(System.__Canon, Microsoft.CodeAnalysis.Sarif.Driver.AggregatingLogger)
   at Microsoft.CodeAnalysis.Sarif.Driver.MultithreadedAnalyzeCommandBase`2[[System.__Canon, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.__Canon, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].Run(System.__Canon)
   at Microsoft.CodeAnalysis.IL.MultithreadedAnalyzeCommand.Run(Microsoft.CodeAnalysis.IL.AnalyzeOptions)
   at Microsoft.CodeAnalysis.IL.BinSkim+<>c.<Main>b__0_1(Microsoft.CodeAnalysis.IL.AnalyzeOptions)
   at CommandLine.ParserResultExtensions.MapResult[[System.__Canon, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.__Canon, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.__Canon, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.__Canon, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.Int32, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]](CommandLine.ParserResult`1<System.Object>, System.Func`2<System.__Canon,Int32>, System.Func`2<System.__Canon,Int32>, System.Func`2<System.__Canon,Int32>, System.Func`2<System.__Canon,Int32>, System.Func`2<System.Collections.Generic.IEnumerable`1<CommandLine.Error>,Int32>)
   at Microsoft.CodeAnalysis.IL.BinSkim.Main(System.String[])

1.9.5

#> C:\temp\binskim\microsoft.codeanalysis.binskim.1.9.5\tools\netcoreapp3.1\win-x64\BinSkim.exe analyze .\repro-linux_arm\dist .\repro-linux_arm\doc .\repro-linux_arm\fix
Analyzing...
Fatal error. System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
C:\temp\binskim\repro-linux_arm\dist : error ERR997.ExceptionLoadingAnalysisTarget : Could not load analysis target 'dist'.
   at System.Runtime.InteropServices.Marshal.ReadInt32(IntPtr, Int32)
   at Microsoft.CodeAnalysis.BinaryParsers.Dwarf.DwarfMemoryReader.ReadUint()
   at Microsoft.CodeAnalysis.BinaryParsers.Dwarf.DwarfMemoryReader.ReadLength(Boolean ByRef)
   at Microsoft.CodeAnalysis.BinaryParsers.Dwarf.DwarfCommonInformationEntry.ParseEntry(Microsoft.CodeAnalysis.BinaryParsers.Dwarf.DwarfMemoryReader, Byte, Int32)
   at Microsoft.CodeAnalysis.BinaryParsers.Dwarf.DwarfCommonInformationEntry.ParseAll(Microsoft.CodeAnalysis.BinaryParsers.Dwarf.DwarfMemoryReader, Byte)
   at Microsoft.CodeAnalysis.BinaryParsers.Dwarf.DwarfSymbolProvider.ParseCommonInformationEntries(Byte[], Byte[], Microsoft.CodeAnalysis.BinaryParsers.Dwarf.DwarfExceptionHandlingFrameParsingInput)
   at Microsoft.CodeAnalysis.BinaryParsers.ElfBinary..ctor(System.Uri, System.String)
   at Microsoft.CodeAnalysis.IL.Sdk.BinaryTargetManager.GetBinaryFromFile(System.Uri, System.String, System.String, Boolean)
   at Microsoft.CodeAnalysis.IL.Sdk.BinaryAnalyzerContext.get_Binary()
   at Microsoft.CodeAnalysis.IL.Sdk.BinaryAnalyzerContext.get_TargetLoadException()
   at Microsoft.CodeAnalysis.Sarif.Driver.MultithreadedAnalyzeCommandBase`2[[System.__Canon, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.__Canon, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].DetermineApplicabilityAndAnalyze(System.__Canon, System.Collections.Generic.IEnumerable`1<Microsoft.CodeAnalysis.Sarif.Driver.Skimmer`1<System.__Canon>>, System.Collections.Generic.ISet`1<System.String>)
   at Microsoft.CodeAnalysis.Sarif.Driver.MultithreadedAnalyzeCommandBase`2+<AnalyzeTargetAsync>d__40[[System.__Canon, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.__Canon, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].MoveNext()
   at System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1+AsyncStateMachineBox`1[[System.Boolean, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[Microsoft.CodeAnalysis.Sarif.Driver.MultithreadedAnalyzeCommandBase`2+<AnalyzeTargetAsync>d__40[[System.__Canon, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.__Canon, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], Sarif.Driver, Version=2.4.15.0, Culture=neutral, PublicKeyToken=21a5e83f6f5bb844]].ExecutionContextCallback(System.Object)
   at System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object)
   at System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1+AsyncStateMachineBox`1[[System.Boolean, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[Microsoft.CodeAnalysis.Sarif.Driver.MultithreadedAnalyzeCommandBase`2+<AnalyzeTargetAsync>d__40[[System.__Canon, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.__Canon, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], Sarif.Driver, Version=2.4.15.0, Culture=neutral, PublicKeyToken=21a5e83f6f5bb844]].MoveNext(System.Threading.Thread)
   at System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1+AsyncStateMachineBox`1[[System.Boolean, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[Microsoft.CodeAnalysis.Sarif.Driver.MultithreadedAnalyzeCommandBase`2+<AnalyzeTargetAsync>d__40[[System.__Canon, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.__Canon, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], Sarif.Driver, Version=2.4.15.0, Culture=neutral, PublicKeyToken=21a5e83f6f5bb844]].MoveNext()
   at System.Threading.ThreadPoolGlobals+<>c.<.cctor>b__5_0(System.Object)
   at System.Threading.Channels.AsyncOperation`1[[System.Boolean, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].SetCompletionAndInvokeContinuation()
   at System.Threading.Channels.AsyncOperation`1[[System.Boolean, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].System.Threading.IThreadPoolWorkItem.Execute()
   at System.Threading.ThreadPoolWorkQueue.Dispatch()
   at System.Threading._ThreadPoolWaitCallback.PerformWaitCallback()

1.7.5 (success)

#> C:\temp\binskim\microsoft.codeanalysis.binskim.1.7.5\tools\netcoreapp3.1\win-x64\BinSkim.exe analyze .\repro-linux_arm\dist .\repro-linux_arm\doc .\repro-linux_arm\fix
Analyzing...
Analyzing 'dist'...
C:\temp\binskim\repro-linux_arm\dist: error BA3001: PIE disabled on executable 'dist'.  This means the code section will always be loaded to the same address, even if ASLR is enabled in the Linux kernel.  To address this, ensure you are compiling with '-fpie' when using clang/gcc.
C:\temp\binskim\repro-linux_arm\dist: error BA3003: The stack protector was not found in 'dist'.  This may be because the binary has no stack-based arrays, or because '--stack-protector-strong' was not used.
C:\temp\binskim\repro-linux_arm\dist: error BA3010: The GNU_RELRO segment is missing from this binary, so relocation sections in 'dist' will not be marked as read only after the binary is loaded.  An attacker can overwrite these to redirect control flow.  Ensure you are compiling with the compiler flags '-Wl,z,relro' to address this.
Analyzing 'doc'...
C:\temp\binskim\repro-linux_arm\doc: error BA3001: PIE disabled on executable 'doc'.  This means the code section will always be loaded to the same address, even if ASLR is enabled in the Linux kernel.  To address this, ensure you are compiling with '-fpie' when using clang/gcc.
C:\temp\binskim\repro-linux_arm\doc: error BA3003: The stack protector was not found in 'doc'.  This may be because the binary has no stack-based arrays, or because '--stack-protector-strong' was not used.
C:\temp\binskim\repro-linux_arm\doc: error BA3010: The GNU_RELRO segment is missing from this binary, so relocation sections in 'doc' will not be marked as read only after the binary is loaded.  An attacker can overwrite these to redirect control flow.  Ensure you are compiling with the compiler flags '-Wl,z,relro' to address this.
Analyzing 'fix'...
C:\temp\binskim\repro-linux_arm\fix: error BA3001: PIE disabled on executable 'fix'.  This means the code section will always be loaded to the same address, even if ASLR is enabled in the Linux kernel.  To address this, ensure you are compiling with '-fpie' when using clang/gcc.
C:\temp\binskim\repro-linux_arm\fix: error BA3003: The stack protector was not found in 'fix'.  This may be because the binary has no stack-based arrays, or because '--stack-protector-strong' was not used.
C:\temp\binskim\repro-linux_arm\fix: error BA3010: The GNU_RELRO segment is missing from this binary, so relocation sections in 'fix' will not be marked as read only after the binary is loaded.  An attacker can overwrite these to redirect control flow.  Ensure you are compiling with the compiler flags '-Wl,z,relro' to address this.
Analysis completed successfully.

One or more rules was disabled for an analysis target, as it was determined not to be applicable to it (this is a common condition). Pass --verbose on the command-line for more information.

A really bizarre part is that analyzing each file individually still has errors, but doesn't show the exception:

#> C:\temp\binskim\microsoft.codeanalysis.binskim.1.9.5\tools\netcoreapp3.1\win-x64\BinSkim.exe analyze .\repro-linux_arm\dist
Analyzing...
C:\temp\binskim\repro-linux_arm\dist : error ERR997.ExceptionLoadingAnalysisTarget : Could not load analysis target 'dist'.

Done. 1 files scanned.

Analysis did not complete due to one or more unrecoverable execution conditions.
Unexpected fatal runtime condition(s) observed: ExceptionLoadingTargetFile

#> C:\temp\binskim\microsoft.codeanalysis.binskim.1.9.5\tools\netcoreapp3.1\win-x64\BinSkim.exe analyze .\repro-linux_arm\doc
Analyzing...
C:\temp\binskim\repro-linux_arm\doc : error ERR997.ExceptionLoadingAnalysisTarget : Could not load analysis target 'doc'.

Done. 1 files scanned.

Analysis did not complete due to one or more unrecoverable execution conditions.
Unexpected fatal runtime condition(s) observed: ExceptionLoadingTargetFile

#> C:\temp\binskim\microsoft.codeanalysis.binskim.1.9.5\tools\netcoreapp3.1\win-x64\BinSkim.exe analyze .\repro-linux_arm\fix
Analyzing...
C:\temp\binskim\repro-linux_arm\fix : error ERR997.ExceptionLoadingAnalysisTarget : Could not load analysis target 'fix'.

Done. 1 files scanned.

Analysis did not complete due to one or more unrecoverable execution conditions.
Unexpected fatal runtime condition(s) observed: ExceptionLoadingTargetFile

Splitting * into args and changing the order can also influence whether the exception is shown:

#> C:\temp\binskim\microsoft.codeanalysis.binskim.2.0.0-rc1\tools\netcoreapp3.1\win-x64\BinSkim.exe analyze .\repro-linux_arm\dist .\repro-linux_arm\doc
Analyzing...
Fatal error. System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
   at System.Runtime.InteropServices.Marshal.ReadInt32(IntPtr, Int32)
   at Microsoft.CodeAnalysis.BinaryParsers.Dwarf.DwarfMemoryReader.ReadUint()
   at Microsoft.CodeAnalysis.BinaryParsers.Dwarf.DwarfMemoryReader.ReadLength(Boolean ByRef)
[...]
   at Microsoft.CodeAnalysis.IL.BinSkim.Main(System.String[])

#> C:\temp\binskim\microsoft.codeanalysis.binskim.2.0.0-rc1\tools\netcoreapp3.1\win-x64\BinSkim.exe analyze .\repro-linux_arm\doc .\repro-linux_arm\dist
Analyzing...
C:\temp\binskim\repro-linux_arm\doc : error ERR997.ExceptionLoadingAnalysisTarget : Could not load analysis target 'doc'.
C:\temp\binskim\repro-linux_arm\dist : error ERR997.ExceptionLoadingAnalysisTarget : Could not load analysis target 'dist'.

Done. 2 files scanned.
[...]

My first thought was threading could cause this kind of issue, so I tried adding --threads 1, but I don't see any change in the behavior.

Is this a bug in BinSkim, or is something wrong with the input?

michaelcfanning commented 1 year ago

@dagood, we think this issue may be fixed. we will include it in the 4.0.1 public release.